Tweak display name search experiment queries

* Display name, phonetic name, and email queries should do
  a prefix match.
* We should always try to match phone numbers and
  also start matching right away (we were waiting until the
  query looked like a phone number and also not doing both
  email and phone queries at the same time).

Bug 26697731
Bug 27324941

Change-Id: Ifdd9a3995921ba1f562fda122cbd7d6a2f4a7737
diff --git a/src/com/android/contacts/common/list/ContactListAdapter.java b/src/com/android/contacts/common/list/ContactListAdapter.java
index b5ef47d..abb0ccc 100644
--- a/src/com/android/contacts/common/list/ContactListAdapter.java
+++ b/src/com/android/contacts/common/list/ContactListAdapter.java
@@ -146,7 +146,7 @@
                 // SearchSnippets.SNIPPET not supported for Contacts.CONTENT_URI
         };
 
-        public static final String[] FILTER_PROJECTION_PRIMARY_EMAIL = new String[] {
+        public static final String[] FILTER_PROJECTION_PRIMARY_EXTRA = new String[] {
                 Contacts._ID,                           // 0
                 Contacts.DISPLAY_NAME_PRIMARY,          // 1
                 Contacts.CONTACT_PRESENCE,              // 2
@@ -161,30 +161,13 @@
                 Contacts.STARRED,                       // 10
                 // SearchSnippets.SNIPPET not supported for Data.CONTENT_URI
                 Email.ADDRESS,                          // 11
+                Phone.NUMBER,                           // 12
+                Phone.NORMALIZED_NUMBER,                // 13
         };
 
         public static final int EMAIL_ADDRESS = 11;
-
-        public static final String[] FILTER_PROJECTION_PRIMARY_PHONE = new String[] {
-                Contacts._ID,                           // 0
-                Contacts.DISPLAY_NAME_PRIMARY,          // 1
-                Contacts.CONTACT_PRESENCE,              // 2
-                Contacts.CONTACT_STATUS,                // 3
-                Contacts.PHOTO_ID,                      // 4
-                Contacts.PHOTO_THUMBNAIL_URI,           // 5
-                Contacts.LOOKUP_KEY,                    // 6
-                // Contacts.IS_USER_PROFILE not supported for Data.CONTENT_URI
-                Contacts.IN_VISIBLE_GROUP,              // 7
-                Contacts.PHONETIC_NAME,                 // 8
-                Contacts.TIMES_CONTACTED,               // 9
-                Contacts.STARRED,                       // 10
-                // SearchSnippets.SNIPPET not supported for Data.CONTENT_URI
-                Phone.NUMBER,                           // 11
-                Phone.NORMALIZED_NUMBER,                // 12
-        };
-
-        public static final int NUMBER = 11;
-        public static final int NORMAILIZED_NUMBER = 12;
+        public static final int NUMBER = 12;
+        public static final int NORMAILIZED_NUMBER = 13;
     }
 
     private CharSequence mUnknownNameText;
diff --git a/src/com/android/contacts/common/list/DefaultContactListAdapter.java b/src/com/android/contacts/common/list/DefaultContactListAdapter.java
index cf260c4..2ac5004 100644
--- a/src/com/android/contacts/common/list/DefaultContactListAdapter.java
+++ b/src/com/android/contacts/common/list/DefaultContactListAdapter.java
@@ -38,7 +38,6 @@
 import com.android.contacts.common.compat.ContactsCompat;
 import com.android.contacts.common.compat.PhoneNumberUtilsCompat;
 import com.android.contacts.common.preference.ContactsPreferences;
-import com.android.contacts.common.util.ContactDisplayUtils;
 import com.android.contacts.commonbind.experiments.Flags;
 
 import java.util.ArrayList;
@@ -76,7 +75,7 @@
                 loader.setSelection("0");
             } else if (flags.getBoolean(Experiments.FLAG_SEARCH_DISPLAY_NAME_QUERY, false)
                 && directoryId == Directory.DEFAULT) {
-                // Configure the loader to match display and phonetic names
+                // Configure the loader to prefix match display names and phonetic names
                 final String displayNameColumn =
                         getContactNameDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY
                                 ? Contacts.DISPLAY_NAME_PRIMARY : Contacts.DISPLAY_NAME_ALTERNATIVE;
@@ -89,28 +88,20 @@
                 loader.setSelectionArgs(getDisplayNameSelectionArgs(query));
 
                 // Configure an extra query to show email and phone number matches and merge
-                // them in after the display name loader query result.
+                // them in after the display name loader query results. Emails are prefix matched
+                // but phone numbers are matched anywhere in the normalized phone number string.
                 final ProfileAndContactsLoader profileAndContactsLoader =
                         (ProfileAndContactsLoader) loader;
-                final Builder extraBuilder = Data.CONTENT_URI.buildUpon();
-                if (ContactDisplayUtils.isPossiblePhoneNumber(query)) {
-                    final String normalizedQuery = PhoneNumberUtilsCompat.normalizeNumber(query);
-                    profileAndContactsLoader.setLoadExtraContactsLast(
-                            extraBuilder.build(),
-                            ExperimentQuery.FILTER_PROJECTION_PRIMARY_PHONE,
-                            Data.MIMETYPE + "=? AND " + Phone.NORMALIZED_NUMBER + " LIKE ? AND " +
-                                    Contacts.IN_VISIBLE_GROUP + "=?",
-                            new String[]{Phone.CONTENT_ITEM_TYPE, "%" + normalizedQuery + "%",
-                                    "1"});
-                } else {
-                    final Builder emailBuilder = Data.CONTENT_URI.buildUpon();
-                    profileAndContactsLoader.setLoadExtraContactsLast(
-                            emailBuilder.build(),
-                            ExperimentQuery.FILTER_PROJECTION_PRIMARY_EMAIL,
-                            Data.MIMETYPE + "=? AND " + Email.ADDRESS + " LIKE ? AND " +
-                                    Contacts.IN_VISIBLE_GROUP + "=?",
-                            new String[]{Email.CONTENT_ITEM_TYPE, "%" + query + "%", "1"});
-                }
+                final String normalizedNumberQuery = PhoneNumberUtilsCompat.normalizeNumber(query);
+                profileAndContactsLoader.setLoadExtraContactsLast(
+                        Data.CONTENT_URI,
+                        ExperimentQuery.FILTER_PROJECTION_PRIMARY_EXTRA,
+                        Contacts.IN_VISIBLE_GROUP + "=? AND " +
+                        "((" + Data.MIMETYPE + "=? AND " + Phone.NORMALIZED_NUMBER + " LIKE ?) OR " +
+                        "(" + Data.MIMETYPE + "=? AND " + Email.ADDRESS + " LIKE ?))",
+                        new String[]{"1",
+                                Phone.CONTENT_ITEM_TYPE, "%" + normalizedNumberQuery + "%",
+                                Email.CONTENT_ITEM_TYPE, query + "%"});
                 if (flags.getBoolean(Experiments.FLAG_SEARCH_STREQUENTS_FIRST, false)) {
                     sortOrder = String.format("%s DESC, %s DESC",
                             Contacts.TIMES_CONTACTED, Contacts.STARRED);
@@ -182,14 +173,14 @@
 
     /**
      * Splits the given query by whitespace and returns the resulting tokens, each one
-     * wrapped with "%" on either side.
+     * with a "%" added to the end.
      */
     @VisibleForTesting
     static String[] getDisplayNameSelectionArgs(String query) {
         final String[] tokens = getDisplayNameSelectionTokens(query);
         if (tokens == null) return null;
         for (int i = 0; i < tokens.length; i++) {
-            tokens[i] = "%" + tokens[i] + "%";
+            tokens[i] = tokens[i] + "%";
         }
         return tokens;
     }
diff --git a/tests/src/com/android/contacts/common/list/DefaultContactListAdapterTest.java b/tests/src/com/android/contacts/common/list/DefaultContactListAdapterTest.java
index 2112daa..b8a9a0e 100644
--- a/tests/src/com/android/contacts/common/list/DefaultContactListAdapterTest.java
+++ b/tests/src/com/android/contacts/common/list/DefaultContactListAdapterTest.java
@@ -58,10 +58,10 @@
         assertNull(getDisplayNameSelectionArgs("\t"));
         assertNull(getDisplayNameSelectionArgs("\t "));
 
-        String[] expected = new String[]{"%foo%"};
+        String[] expected = new String[]{"foo%"};
         assertArrayEquals(expected, getDisplayNameSelectionArgs("foo"));
 
-        expected = new String[]{"%foo%","%bar%"};
+        expected = new String[]{"foo%","bar%"};
         assertArrayEquals(expected, getDisplayNameSelectionArgs("foo bar"));
         assertArrayEquals(expected, getDisplayNameSelectionArgs(" foo bar "));
         assertArrayEquals(expected, getDisplayNameSelectionArgs("foo\t bar"));