Allow access to the NORMALIZED_NUMBER, so that sync adapters can sync it

Bug:6126736

Change-Id: Ia1c83c4c600e44f3a354aec7e206267341143ef4
diff --git a/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java b/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java
index f6d6d5d..2ee61e4 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java
@@ -41,25 +41,18 @@
     @Override
     public long insert(SQLiteDatabase db, TransactionContext txContext, long rawContactId,
             ContentValues values) {
-        long dataId;
+        fillNormalizedNumber(values);
+
+        final long dataId = super.insert(db, txContext, rawContactId, values);
         if (values.containsKey(Phone.NUMBER)) {
-            String number = values.getAsString(Phone.NUMBER);
-
-            String numberE164 =
-                    PhoneNumberUtils.formatNumberToE164(number, mDbHelper.getCurrentCountryIso());
-            if (numberE164 != null) {
-                values.put(Phone.NORMALIZED_NUMBER, numberE164);
-            }
-            dataId = super.insert(db, txContext, rawContactId, values);
-
-            updatePhoneLookup(db, rawContactId, dataId, number, numberE164);
+            final String number = values.getAsString(Phone.NUMBER);
+            final String normalizedNumber = values.getAsString(Phone.NORMALIZED_NUMBER);
+            updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber);
             mContactAggregator.updateHasPhoneNumber(db, rawContactId);
             fixRawContactDisplayName(db, txContext, rawContactId);
-            if (numberE164 != null) {
+            if (normalizedNumber != null) {
                 triggerAggregation(txContext, rawContactId);
             }
-        } else {
-            dataId = super.insert(db, txContext, rawContactId, values);
         }
         return dataId;
     }
@@ -67,18 +60,7 @@
     @Override
     public boolean update(SQLiteDatabase db, TransactionContext txContext, ContentValues values,
             Cursor c, boolean callerIsSyncAdapter) {
-        String number = null;
-        String numberE164 = null;
-        if (values.containsKey(Phone.NUMBER)) {
-            number = values.getAsString(Phone.NUMBER);
-            if (number != null) {
-                numberE164 = PhoneNumberUtils.formatNumberToE164(number,
-                        mDbHelper.getCurrentCountryIso());
-            }
-            if (numberE164 != null) {
-                values.put(Phone.NORMALIZED_NUMBER, numberE164);
-            }
-        }
+        fillNormalizedNumber(values);
 
         if (!super.update(db, txContext, values, c, callerIsSyncAdapter)) {
             return false;
@@ -87,7 +69,9 @@
         if (values.containsKey(Phone.NUMBER)) {
             long dataId = c.getLong(DataUpdateQuery._ID);
             long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID);
-            updatePhoneLookup(db, rawContactId, dataId, number, numberE164);
+            updatePhoneLookup(db, rawContactId, dataId,
+                    values.getAsString(Phone.NUMBER),
+                    values.getAsString(Phone.NORMALIZED_NUMBER));
             mContactAggregator.updateHasPhoneNumber(db, rawContactId);
             fixRawContactDisplayName(db, txContext, rawContactId);
             triggerAggregation(txContext, rawContactId);
@@ -95,6 +79,25 @@
         return true;
     }
 
+    private void fillNormalizedNumber(ContentValues values) {
+        // No NUMBER? Also ignore NORMALIZED_NUMBER
+        if (!values.containsKey(Phone.NUMBER)) {
+            values.remove(Phone.NORMALIZED_NUMBER);
+            return;
+        }
+
+        // NUMBER is given. Try to extract NORMALIZED_NUMBER from it, unless it is also given
+        final String number = values.getAsString(Phone.NUMBER);
+        final String numberE164 = values.getAsString(Phone.NORMALIZED_NUMBER);
+        if (number != null && numberE164 == null) {
+            final String newNumberE164 = PhoneNumberUtils.formatNumberToE164(number,
+                    mDbHelper.getCurrentCountryIso());
+            if (newNumberE164 != null) {
+                values.put(Phone.NORMALIZED_NUMBER, newNumberE164);
+            }
+        }
+    }
+
     @Override
     public int delete(SQLiteDatabase db, TransactionContext txContext, Cursor c) {
         long dataId = c.getLong(DataDeleteQuery._ID);
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index bef077c..fb9f357 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -923,6 +923,63 @@
         assertStoredValues(dedupeUri, values1);
     }
 
+    public void testPhonesNormalizedNumber() {
+        final long rawContactId = createRawContact();
+
+        // Write both a number and a normalized number. Those should be written as-is
+        final ContentValues values = new ContentValues();
+        values.put(Data.RAW_CONTACT_ID, rawContactId);
+        values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+        values.put(Phone.NUMBER, "1234");
+        values.put(Phone.NORMALIZED_NUMBER, "5678");
+        values.put(Phone.TYPE, Phone.TYPE_HOME);
+
+        final Uri dataUri = mResolver.insert(Data.CONTENT_URI, values);
+
+        // Ensure both can be looked up
+        assertEquals(1,
+                getCount(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "1234"), null, null));
+        assertEquals(1,
+                getCount(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "5678"), null, null));
+
+        // Replace both in an UPDATE
+        values.clear();
+        values.put(Phone.NUMBER, "4321");
+        values.put(Phone.NORMALIZED_NUMBER, "8765");
+        mResolver.update(dataUri, values, null, null);
+        assertEquals(0,
+                getCount(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "1234"), null, null));
+        assertEquals(1,
+                getCount(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "4321"), null, null));
+        assertEquals(0,
+                getCount(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "5678"), null, null));
+        assertEquals(1,
+                getCount(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "8765"), null, null));
+
+        // Replace only NUMBER ==> NORMALIZED_NUMBER will be inferred (we test that by making
+        // sure the old manual value can not be found anymore)
+        values.clear();
+        values.put(Phone.NUMBER, "1-800-466-5432");
+        mResolver.update(dataUri, values, null, null);
+        assertEquals(
+                1,
+                getCount(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "1-800-466-5432"), null,
+                        null));
+        assertEquals(0,
+                getCount(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "8765"), null, null));
+
+        // Replace only NORMALIZED_NUMBER ==> call is ignored, things will be unchanged
+        values.clear();
+        values.put(Phone.NORMALIZED_NUMBER, "8765");
+        mResolver.update(dataUri, values, null, null);
+        assertEquals(
+                1,
+                getCount(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "1-800-466-5432"), null,
+                        null));
+        assertEquals(0,
+                getCount(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, "8765"), null, null));
+    }
+
     public void testPhonesFilterQuery() {
         testPhonesFilterQueryInter(Phone.CONTENT_FILTER_URI);
     }