Merge "Relax phone number collapser"
diff --git a/src/com/android/contacts/ContactsUtils.java b/src/com/android/contacts/ContactsUtils.java
index ea567fb..9a014f4 100644
--- a/src/com/android/contacts/ContactsUtils.java
+++ b/src/com/android/contacts/ContactsUtils.java
@@ -22,7 +22,6 @@
 import com.android.contacts.model.AccountWithDataSet;
 import com.android.contacts.test.NeededForTesting;
 import com.android.contacts.util.Constants;
-import com.android.i18n.phonenumbers.PhoneNumberUtil;
 
 import android.content.Context;
 import android.content.Intent;
@@ -129,36 +128,41 @@
         // mimetypes could have more sophisticated matching is the future, e.g. addresses)
         if (!TextUtils.equals(Phone.CONTENT_ITEM_TYPE, mimetype1)) return false;
 
-        // Now do the full phone number thing. split into parts, seperated by waiting symbol
-        // and compare them individually
-        final String[] dataParts1 = data1.toString().split(WAIT_SYMBOL_AS_STRING);
-        final String[] dataParts2 = data2.toString().split(WAIT_SYMBOL_AS_STRING);
-        if (dataParts1.length != dataParts2.length) return false;
-        final PhoneNumberUtil util = PhoneNumberUtil.getInstance();
-        for (int i = 0; i < dataParts1.length; i++) {
-            final String dataPart1 = dataParts1[i];
-            final String dataPart2 = dataParts2[i];
+        return shouldCollapsePhoneNumbers(data1.toString(), data2.toString());
+    }
 
-            // substrings equal? shortcut, don't parse
-            if (TextUtils.equals(dataPart1, dataPart2)) continue;
+    private static final boolean shouldCollapsePhoneNumbers(
+            String number1WithLetters, String number2WithLetters) {
+        final String number1 = PhoneNumberUtils.convertKeypadLettersToDigits(number1WithLetters);
+        final String number2 = PhoneNumberUtils.convertKeypadLettersToDigits(number2WithLetters);
 
-            // do a full parse of the numbers
-            switch (util.isNumberMatch(dataPart1, dataPart2)) {
-                case NOT_A_NUMBER:
-                    // don't understand the numbers? let's play it safe
-                    return false;
-                case NO_MATCH:
-                    return false;
-                case EXACT_MATCH:
-                case SHORT_NSN_MATCH:
-                case NSN_MATCH:
-                    break;
-                default:
-                    throw new IllegalStateException("Unknown result value from phone number " +
-                            "library");
+        int index1 = 0;
+        int index2 = 0;
+        for (;;) {
+            // Skip formatting characters.
+            while (index1 < number1.length() &&
+                    !PhoneNumberUtils.isNonSeparator(number1.charAt(index1))) {
+                index1++;
             }
+            while (index2 < number2.length() &&
+                    !PhoneNumberUtils.isNonSeparator(number2.charAt(index2))) {
+                index2++;
+            }
+            // If both have finished, match.  If only one has finished, not match.
+            final boolean number1End = (index1 == number1.length());
+            final boolean number2End = (index2 == number2.length());
+            if (number1End) {
+                return number2End;
+            }
+            if (number2End) return false;
+
+            // If the non-formatting characters are different, not match.
+            if (number1.charAt(index1) != number2.charAt(index2)) return false;
+
+            // Go to the next characters.
+            index1++;
+            index2++;
         }
-        return true;
     }
 
     /**
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index ca6fa63..faeb0c5 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -601,7 +601,7 @@
                 } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
                     // Build phone entries
                     String phoneNumberE164 =
-                            entryValues.getAsString(PhoneLookup.NORMALIZED_NUMBER);
+                            entryValues.getAsString(Phone.NORMALIZED_NUMBER);
                     entry.data = PhoneNumberUtils.formatNumber(
                             entry.data, phoneNumberE164, mDefaultCountryIso);
                     final Intent phoneIntent = mHasPhone ?
diff --git a/tests/src/com/android/contacts/ContactDetailTest.java b/tests/src/com/android/contacts/ContactDetailTest.java
index e8d1550..b2c19f4 100644
--- a/tests/src/com/android/contacts/ContactDetailTest.java
+++ b/tests/src/com/android/contacts/ContactDetailTest.java
@@ -21,7 +21,9 @@
 import com.android.contacts.tests.mocks.MockContentProvider;
 
 import android.test.ActivityUnitTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 
+@SmallTest
 public class ContactDetailTest extends ActivityUnitTestCase<ContactDetailActivity> {
     private ContactsMockContext mContext;
     private MockContentProvider mContactsProvider;
diff --git a/tests/src/com/android/contacts/ContactsUtilsTests.java b/tests/src/com/android/contacts/ContactsUtilsTests.java
index 82d0cb0..d2d5bbb 100644
--- a/tests/src/com/android/contacts/ContactsUtilsTests.java
+++ b/tests/src/com/android/contacts/ContactsUtilsTests.java
@@ -126,7 +126,7 @@
         assertCollapses("72", true,
                 Phone.CONTENT_ITEM_TYPE, "+49 (8092) 1234",
                 Phone.CONTENT_ITEM_TYPE, "+49 (8092)1234");
-        assertCollapses("73", true,
+        assertCollapses("73", false,
                 Phone.CONTENT_ITEM_TYPE, "0049 (8092) 1234",
                 Phone.CONTENT_ITEM_TYPE, "+49/80921234");
         assertCollapses("74", false,
@@ -147,14 +147,37 @@
                 Phone.CONTENT_ITEM_TYPE, "1234567;+49 (8092) 1234",
                 Phone.CONTENT_ITEM_TYPE, "1234567;+49/80921234");
 
-        // this makes sure that if if two segments are identical, we don't even try to parse
-        // (and therefore allow invalid phone numbers)
-        assertCollapses("84", true,
-                Phone.CONTENT_ITEM_TYPE, "+49/80921234;a89",
-                Phone.CONTENT_ITEM_TYPE, "+49 (8092) 1234;a89");
-        assertCollapses("85", false,
-                Phone.CONTENT_ITEM_TYPE, "+49/80921234;a89",
-                Phone.CONTENT_ITEM_TYPE, "+49/80921234;b89");
+        assertCollapses("86", true,
+                Phone.CONTENT_ITEM_TYPE, "",
+                Phone.CONTENT_ITEM_TYPE, "");
+
+        assertCollapses("87", false,
+                Phone.CONTENT_ITEM_TYPE, "1",
+                Phone.CONTENT_ITEM_TYPE, "");
+
+        assertCollapses("88", false,
+                Phone.CONTENT_ITEM_TYPE, "",
+                Phone.CONTENT_ITEM_TYPE, "1");
+
+        assertCollapses("89", true,
+                Phone.CONTENT_ITEM_TYPE, "---",
+                Phone.CONTENT_ITEM_TYPE, "---");
+
+        assertCollapses("90", true,
+                Phone.CONTENT_ITEM_TYPE, "1-/().",
+                Phone.CONTENT_ITEM_TYPE, "--$%1");
+
+        assertCollapses("91", true,
+                Phone.CONTENT_ITEM_TYPE, "abcdefghijklmnopqrstuvwxyz",
+                Phone.CONTENT_ITEM_TYPE, "22233344455566677778889999");
+
+        assertCollapses("92", false,
+                Phone.CONTENT_ITEM_TYPE, "1;2",
+                Phone.CONTENT_ITEM_TYPE, "12");
+
+        assertCollapses("93", false,
+                Phone.CONTENT_ITEM_TYPE, "1,2",
+                Phone.CONTENT_ITEM_TYPE, "12");
     }
 
     private void assertCollapses(String message, boolean expected, CharSequence mimetype1,
@@ -164,12 +187,17 @@
         assertEquals(message, expected,
                 ContactsUtils.shouldCollapse(mimetype2, data2, mimetype1, data1));
 
+        // If data1 and data2 are the same instance, make sure the same test passes with different
+        // instances.
         if (data1 == data2 && data1 != null) {
-            // make sure we also do a test where object equality is not given
-            final CharSequence data2_newref = data2 + "";
+            // Create a different instance
+            final CharSequence data2_newref = new StringBuilder(data2).append("").toString();
 
-            // this just makes sure the test is working
-            assertFalse(data1 == data2_newref);
+            if (data1 == data2_newref) {
+                // In some cases no matter what we do the runtime reuses the same instance, so
+                // we can't do the "different instance" test.
+                return;
+            }
 
             // we have two different instances, now make sure we get the same result as before
             assertEquals(message, expected,