Merge "Added logging for contacts provider metrics."
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java
index 2f0c9b2..b9bd233 100644
--- a/java/com/android/dialer/app/calllog/CallLogAdapter.java
+++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java
@@ -82,8 +82,10 @@
 import com.android.dialer.enrichedcall.EnrichedCallComponent;
 import com.android.dialer.enrichedcall.EnrichedCallManager;
 import com.android.dialer.logging.ContactSource;
+import com.android.dialer.logging.ContactSource.Type;
 import com.android.dialer.logging.DialerImpression;
 import com.android.dialer.logging.Logger;
+import com.android.dialer.logging.LoggingBindings.ContactsProviderMatchInfo;
 import com.android.dialer.logging.UiAction;
 import com.android.dialer.main.MainActivityPeer;
 import com.android.dialer.performancereport.PerformanceReport;
@@ -94,6 +96,9 @@
 import com.android.dialer.spam.SpamComponent;
 import com.android.dialer.telecom.TelecomUtil;
 import com.android.dialer.util.PermissionsUtil;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.Set;
@@ -152,6 +157,13 @@
   public boolean deselectAllMode = false;
   private final SparseArray<String> selectedItems = new SparseArray<>();
 
+  /**
+   * Maps a raw input number to match info. We only log one MatchInfo per raw input number to reduce
+   * the amount of data logged.
+   */
+  private final Map<String, ContactsProviderMatchInfo> contactsProviderMatchInfos =
+      new ArrayMap<>();
+
   private final ActionMode.Callback actionModeCallback =
       new ActionMode.Callback() {
 
@@ -678,6 +690,7 @@
   }
 
   public void onResume() {
+    contactsProviderMatchInfos.clear();
     if (PermissionsUtil.hasPermission(activity, android.Manifest.permission.READ_CONTACTS)) {
       contactInfoCache.start();
     }
@@ -688,6 +701,11 @@
   }
 
   public void onPause() {
+    // The call log can be resumed/paused without loading any contacts. Don't log these events.
+    if (!contactsProviderMatchInfos.isEmpty()) {
+      Logger.get(activity).logContactsProviderMetrics(contactsProviderMatchInfos.values());
+    }
+
     getDuo().unregisterListener(this);
     pauseCache();
     for (Uri uri : hiddenItemUris) {
@@ -1063,6 +1081,7 @@
               position
                   < ConfigProviderBindings.get(activity)
                       .getLong("number_of_call_to_do_remote_lookup", 5L));
+      logCp2Metrics(details, info);
     }
     CharSequence formattedNumber =
         info.formattedNumber == null
@@ -1467,6 +1486,44 @@
     notifyDataSetChanged();
   }
 
+  private void logCp2Metrics(PhoneCallDetails details, ContactInfo contactInfo) {
+    if (details == null) {
+      return;
+    }
+    CharSequence inputNumber = details.number;
+    if (inputNumber == null) {
+      return;
+    }
+
+    ContactsProviderMatchInfo.Builder matchInfo =
+        ContactsProviderMatchInfo.builder()
+            .setInputNumberLength(PhoneNumberUtils.normalizeNumber(inputNumber.toString()).length())
+            .setInputNumberHasPostdialDigits(
+                !PhoneNumberUtils.extractPostDialPortion(inputNumber.toString()).isEmpty()
+                    || (details.postDialDigits != null && !details.postDialDigits.isEmpty()));
+
+    PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+    try {
+      PhoneNumber phoneNumber = phoneNumberUtil.parse(inputNumber, details.countryIso);
+      matchInfo.setInputNumberValid(phoneNumberUtil.isValidNumber(phoneNumber));
+    } catch (NumberParseException e) {
+      // Do nothing
+      matchInfo.setInputNumberValid(false);
+    }
+
+    if (contactInfo != null
+        && contactInfo.number != null
+        && contactInfo.sourceType == Type.SOURCE_TYPE_DIRECTORY) {
+      matchInfo
+          .setMatchedContact(true)
+          .setMatchedNumberLength(PhoneNumberUtils.normalizeNumber(contactInfo.number).length())
+          .setMatchedNumberHasPostdialDigits(
+              !PhoneNumberUtils.extractPostDialPortion(contactInfo.number).isEmpty());
+    }
+
+    contactsProviderMatchInfos.put(inputNumber.toString(), matchInfo.build());
+  }
+
   /** Interface used to initiate a refresh of the content. */
   public interface CallFetcher {
 
diff --git a/java/com/android/dialer/logging/LoggingBindings.java b/java/com/android/dialer/logging/LoggingBindings.java
index 7c580cb..9288324 100644
--- a/java/com/android/dialer/logging/LoggingBindings.java
+++ b/java/com/android/dialer/logging/LoggingBindings.java
@@ -16,6 +16,8 @@
 
 import android.app.Activity;
 import android.widget.QuickContactBadge;
+import com.google.auto.value.AutoValue;
+import java.util.Collection;
 
 /** Allows the container application to gather analytics. */
 public interface LoggingBindings {
@@ -96,4 +98,48 @@
 
   /** Logs annotated call log metrics. */
   void logAnnotatedCallLogMetrics(int numberRowsThatDidPop, int numberRowsThatDidNotPop);
+
+  /** Logs contacts provider metrics. */
+  void logContactsProviderMetrics(Collection<ContactsProviderMatchInfo> matchInfos);
+
+  /** Input type for {@link #logContactsProviderMetrics(Collection)}. */
+  @AutoValue
+  abstract class ContactsProviderMatchInfo {
+    public abstract boolean matchedContact();
+
+    public abstract boolean inputNumberValid();
+
+    public abstract int inputNumberLength();
+
+    public abstract int matchedNumberLength();
+
+    public abstract boolean inputNumberHasPostdialDigits();
+
+    public abstract boolean matchedNumberHasPostdialDigits();
+
+    public static Builder builder() {
+      return new AutoValue_LoggingBindings_ContactsProviderMatchInfo.Builder()
+          .setMatchedContact(false)
+          .setMatchedNumberLength(0)
+          .setMatchedNumberHasPostdialDigits(false);
+    }
+
+    /** Builder. */
+    @AutoValue.Builder
+    public abstract static class Builder {
+      public abstract Builder setMatchedContact(boolean value);
+
+      public abstract Builder setInputNumberValid(boolean value);
+
+      public abstract Builder setInputNumberLength(int value);
+
+      public abstract Builder setMatchedNumberLength(int value);
+
+      public abstract Builder setInputNumberHasPostdialDigits(boolean value);
+
+      public abstract Builder setMatchedNumberHasPostdialDigits(boolean value);
+
+      public abstract ContactsProviderMatchInfo build();
+    }
+  }
 }
diff --git a/java/com/android/dialer/logging/LoggingBindingsStub.java b/java/com/android/dialer/logging/LoggingBindingsStub.java
index 65ebd1a..9231782 100644
--- a/java/com/android/dialer/logging/LoggingBindingsStub.java
+++ b/java/com/android/dialer/logging/LoggingBindingsStub.java
@@ -16,6 +16,7 @@
 
 import android.app.Activity;
 import android.widget.QuickContactBadge;
+import java.util.Collection;
 
 /** Default implementation for logging bindings. */
 public class LoggingBindingsStub implements LoggingBindings {
@@ -70,4 +71,7 @@
 
   @Override
   public void logAnnotatedCallLogMetrics(int numberRowsThatDidPop, int numberRowsThatDidNotPop) {}
+
+  @Override
+  public void logContactsProviderMetrics(Collection<ContactsProviderMatchInfo> matchInfos) {}
 }