[Issue 2147424] Making sure that a contact can be filtered/looked up by any word in the name

Which is not to say that it can be aggregated on any word in the name - that limit is still 4.

Change-Id: I61821af3d8103e3ec58b42df10f96171667c5eca
diff --git a/src/com/android/providers/contacts/NameLookupBuilder.java b/src/com/android/providers/contacts/NameLookupBuilder.java
index d1588b5..a408531 100644
--- a/src/com/android/providers/contacts/NameLookupBuilder.java
+++ b/src/com/android/providers/contacts/NameLookupBuilder.java
@@ -30,8 +30,7 @@
 
     private final NameSplitter mSplitter;
     private String[][] mNicknameClusters = new String[MAX_NAME_TOKENS][];
-    private StringBuilder mStringBuilder1 = new StringBuilder();
-    private StringBuilder mStringBuilder2 = new StringBuilder();
+    private StringBuilder mStringBuilder = new StringBuilder();
     private String[] mNames = new String[NameSplitter.MAX_TOKENS];
 
     public NameLookupBuilder(NameSplitter splitter) {
@@ -80,6 +79,15 @@
                 }
             });
 
+            // Insert a collation key for each extra word - useful for contact filtering
+            // and suggestions
+            String firstToken = mNames[0];
+            for (int i = MAX_NAME_TOKENS; i < tokenCount; i++) {
+                mNames[0] = mNames[i];
+                insertCollationKey(rawContactId, dataId, MAX_NAME_TOKENS);
+            }
+            mNames[0] = firstToken;
+
             tokenCount = MAX_NAME_TOKENS;
         }
 
@@ -135,30 +143,37 @@
      */
     private void insertNameVariant(long rawContactId, long dataId, int tokenCount,
             int lookupType, boolean buildCollationKey) {
-        mStringBuilder1.setLength(0);
+        mStringBuilder.setLength(0);
 
         for (int i = 0; i < tokenCount; i++) {
             if (i != 0) {
-                mStringBuilder1.append('.');
+                mStringBuilder.append('.');
             }
-            mStringBuilder1.append(mNames[i]);
+            mStringBuilder.append(mNames[i]);
         }
 
-        insertNameLookup(rawContactId, dataId, lookupType, mStringBuilder1.toString());
+        insertNameLookup(rawContactId, dataId, lookupType, mStringBuilder.toString());
 
         if (buildCollationKey) {
-            mStringBuilder2.setLength(0);
-
-            for (int i = 0; i < tokenCount; i++) {
-                mStringBuilder2.append(mNames[i]);
-            }
-
-            insertNameLookup(rawContactId, dataId, NameLookupType.NAME_COLLATION_KEY,
-                    mStringBuilder2.toString());
+            insertCollationKey(rawContactId, dataId, tokenCount);
         }
     }
 
     /**
+     * Inserts a collation key for the current contents of {@link #mNames}.
+     */
+    private void insertCollationKey(long rawContactId, long dataId, int tokenCount) {
+        mStringBuilder.setLength(0);
+
+        for (int i = 0; i < tokenCount; i++) {
+            mStringBuilder.append(mNames[i]);
+        }
+
+        insertNameLookup(rawContactId, dataId, NameLookupType.NAME_COLLATION_KEY,
+                mStringBuilder.toString());
+    }
+
+    /**
      * For all tokens that correspond to nickname clusters, substitutes each cluster key
      * and inserts all permutations with that key.
      */
diff --git a/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java b/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
index b492ab2..84dc6f3 100644
--- a/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
+++ b/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
@@ -182,9 +182,21 @@
     public void testMultiwordName() {
         mBuilder.insertNameLookup(0, 0, "Jo Jeffrey John Jessy Longname");
         String actual = mBuilder.inserted();
-        assertTrue(actual.startsWith(
-                "(0:Jo.Jeffrey.John.Jessy.Longname)" +  // Exact
-                "(2:JoJeffreyJohnJessyLongname)" +      // Full collation key
-                "(1:Longname.Jeffrey.Jessy.John)"));    // Variant: four longest parts
+
+        // Exact name
+        assertTrue(actual.contains("(0:Jo.Jeffrey.John.Jessy.Longname)"));
+
+        // Full collation key
+        assertTrue(actual.contains("(2:JoJeffreyJohnJessyLongname)"));
+
+        // Variant: four longest parts
+        assertTrue(actual.contains("(1:Longname.Jeffrey.Jessy.John)"));
+
+        // All individual words
+        assertTrue(actual.contains("(2:Jo"));
+        assertTrue(actual.contains("(2:Jeffrey"));
+        assertTrue(actual.contains("(2:John"));
+        assertTrue(actual.contains("(2:Jessy"));
+        assertTrue(actual.contains("(2:Longname"));
     }
 }