Filter out contacts with null primary display names in search.

Bug: 68848807
Test: unit
PiperOrigin-RevId: 175190786
Change-Id: I15b525951cb87afb8b48f3bdb2174605c94c99cf
diff --git a/java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java b/java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java
index df67b76..166902b 100644
--- a/java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java
+++ b/java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java
@@ -132,8 +132,8 @@
   }
 
   private static List<Cp2Contact> coalesceContacts(List<Cp2Contact> contactsWithSameContactId) {
-    String companyName = null;
-    String nickName = null;
+    StringBuilder companyName = new StringBuilder();
+    StringBuilder nickName = new StringBuilder();
     List<Cp2Contact> phoneContacts = new ArrayList<>();
     for (Cp2Contact contact : contactsWithSameContactId) {
       if (contact.mimeType().equals(Phone.CONTENT_ITEM_TYPE)) {
@@ -141,11 +141,11 @@
       } else if (contact.mimeType().equals(Organization.CONTENT_ITEM_TYPE)) {
         // Since a contact can have more than one company name but they aren't visible to the user
         // in our search UI, we can lazily concatenate them together to make them all searchable.
-        companyName += " " + contact.companyName();
+        companyName.append(" ").append(contact.companyName());
       } else if (contact.mimeType().equals(Nickname.CONTENT_ITEM_TYPE)) {
         // Since a contact can have more than one nickname but they aren't visible to the user
         // in our search UI, we can lazily concatenate them together to make them all searchable.
-        nickName += " " + contact.nickName();
+        nickName.append(" ").append(contact.nickName());
       }
     }
 
@@ -154,7 +154,11 @@
     List<Cp2Contact> coalescedContacts = new ArrayList<>();
     for (Cp2Contact phoneContact : phoneContacts) {
       coalescedContacts.add(
-          phoneContact.toBuilder().setCompanyName(companyName).setNickName(nickName).build());
+          phoneContact
+              .toBuilder()
+              .setCompanyName(companyName.length() == 0 ? null : companyName.toString())
+              .setNickName(nickName.length() == 0 ? null : nickName.toString())
+              .build());
     }
     return coalescedContacts;
   }
diff --git a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
index 3551801..2b7af11 100644
--- a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
+++ b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
@@ -43,9 +43,20 @@
     this.query = query;
   }
 
+  /**
+   * Note: ContactsProvider can make no guarantee that any given field is non-null, and display name
+   * has been observed to be null in the wild, though it is unclear when that might happen (possibly
+   * a third-party is inserting such data). See a bug.
+   *
+   * <p>We skip showing contacts without a display name because there is no UI treatment for showing
+   * such results. (Note that even contacts with only a number still have a display name set to the
+   * number.)
+   */
   private static String whereStatement() {
     return (Phone.NUMBER + " IS NOT NULL")
         + " AND "
+        + (Data.DISPLAY_NAME_PRIMARY + " IS NOT NULL")
+        + " AND "
         + Data.MIMETYPE
         + " IN (\'"
         + Phone.CONTENT_ITEM_TYPE