Merge "Add Metrics for unknown Carrier Id"
diff --git a/proto/telephony.proto b/proto/telephony.proto
index 1f1a2bb..700c961 100644
--- a/proto/telephony.proto
+++ b/proto/telephony.proto
@@ -547,6 +547,9 @@
 
     // System time overwritten by NITZ (Network time)
     NITZ_TIME = 12;
+
+    // Carrier Identification Matching Event
+    CARRIER_ID_MATCHING = 13;
   }
 
   // Setup a packet data connection
@@ -772,6 +775,25 @@
      optional string reason = 2;
   }
 
+  message CarrierIdMatching {
+
+    // Carrier id table version number
+    optional int32 cid_table_version = 1;
+
+    // Carrier id matching result object
+    optional CarrierIdMatchingResult result = 2;
+  }
+
+  message CarrierIdMatchingResult {
+
+    // A unique carrier id
+    optional int32 carrier_id = 1;
+
+    // Group id level 1. Logged only if gid1 is configured from subscription
+    // but its matching rule is unknown
+    optional string gid1 = 2;
+  }
+
   // Time when event happened on device, in milliseconds since epoch
   optional int64 timestamp_millis = 1;
 
@@ -816,6 +838,9 @@
 
   // NITZ time in milliseconds
   optional int64 nitz_timestamp_millis = 15;
+
+  // Carrier id matching event
+  optional CarrierIdMatching carrier_id_matching = 16;
 }
 
 enum TimeInterval {
@@ -1060,7 +1085,7 @@
     // Time since previous event
     optional TimeInterval delay = 2;
 
-    // Settings at the begining of the session or when changed
+    // Settings at the beginning of the session or when changed
     optional TelephonySettings settings = 3;
 
     // State at the beginning of the session or when changed
@@ -1196,7 +1221,7 @@
     // Time since previous event
     optional TimeInterval delay = 2;
 
-    // Settings at the begining of the session or when changed
+    // Settings at the beginning of the session or when changed
     optional TelephonySettings settings = 3;
 
     // State at the beginning of the session or when changed
diff --git a/src/java/com/android/internal/telephony/CarrierIdentifier.java b/src/java/com/android/internal/telephony/CarrierIdentifier.java
index 5a700ae..4f808a4 100644
--- a/src/java/com/android/internal/telephony/CarrierIdentifier.java
+++ b/src/java/com/android/internal/telephony/CarrierIdentifier.java
@@ -34,6 +34,7 @@
 import android.util.LocalLog;
 import android.util.Log;
 
+import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.uicc.IccRecords;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.util.IndentingPrintWriter;
@@ -542,6 +543,7 @@
                 maxRule = rule;
             }
         }
+
         if (maxScore == CarrierMatchingRule.SCORE_INVALID) {
             logd("[matchCarrier - no match] cid: " + TelephonyManager.UNKNOWN_CARRIER_ID
                     + " name: " + null);
@@ -550,6 +552,20 @@
             logd("[matchCarrier] cid: " + maxRule.mCid + " name: " + maxRule.mName);
             updateCarrierIdAndName(maxRule.mCid, maxRule.mName);
         }
+
+        /*
+         * Write Carrier Identification Matching event, logging with the
+         * matching score and carrierId to differentiate below cases of metrics:
+         * 1) unknown mccmnc - the Carrier Id provider contains no rule that matches the
+         * read mccmnc.
+         * 2) the Carrier Id provider contains some rule(s) that match the read mccmnc,
+         * but the read gid1 is not matched within the highest-scored rule.
+         * 3) successfully found a matched carrier id in the provider.
+         */
+        String gid1ToLog = ((maxScore & CarrierMatchingRule.SCORE_GID1) == 0
+                && !TextUtils.isEmpty(subscriptionRule.mGid1)) ? subscriptionRule.mGid1 : null;
+        TelephonyMetrics.getInstance().writeCarrierIdMatchingEvent(
+                mPhone.getPhoneId(), mCarrierId, gid1ToLog);
     }
 
     public int getCarrierId() {
diff --git a/src/java/com/android/internal/telephony/metrics/TelephonyEventBuilder.java b/src/java/com/android/internal/telephony/metrics/TelephonyEventBuilder.java
index 6530802..d28c035 100644
--- a/src/java/com/android/internal/telephony/metrics/TelephonyEventBuilder.java
+++ b/src/java/com/android/internal/telephony/metrics/TelephonyEventBuilder.java
@@ -20,6 +20,7 @@
 import static com.android.internal.telephony.nano.TelephonyProto.ImsConnectionState;
 import static com.android.internal.telephony.nano.TelephonyProto.RilDataCall;
 import static com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
+import static com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.CarrierIdMatching;
 import static com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.ModemRestart;
 import static com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilDeactivateDataCall;
 import static com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilSetupDataCall;
@@ -116,4 +117,13 @@
         mEvent.modemRestart = modemRestart;
         return this;
     }
+
+    /**
+     * Set and build Carrier Id Matching event
+     */
+    public TelephonyEventBuilder setCarrierIdMatching(CarrierIdMatching carrierIdMatching) {
+        mEvent.type = TelephonyEvent.Type.CARRIER_ID_MATCHING;
+        mEvent.carrierIdMatching = carrierIdMatching;
+        return this;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
index d972547..d935b33 100644
--- a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
+++ b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
@@ -40,6 +40,7 @@
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyHistogram;
+import android.telephony.TelephonyManager;
 import android.telephony.data.DataCallResponse;
 import android.text.TextUtils;
 import android.util.Base64;
@@ -65,6 +66,8 @@
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.RilCall;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.RilCall.Type;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.CarrierIdMatching;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.CarrierIdMatchingResult;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.ModemRestart;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilDeactivateDataCall;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilSetupDataCall;
@@ -1714,6 +1717,31 @@
         addTelephonyEvent(event);
     }
 
+    /**
+     * Write carrier identification matching event
+     *
+     * @param phoneId Phone id
+     * @param cid Unique Carrier Id
+     * @param gid1 Group id level 1
+     */
+    public void writeCarrierIdMatchingEvent(int phoneId, int cid, String gid1) {
+        final CarrierIdMatching carrierIdMatching = new CarrierIdMatching();
+        final CarrierIdMatchingResult carrierIdMatchingResult = new CarrierIdMatchingResult();
+
+        if (cid != TelephonyManager.UNKNOWN_CARRIER_ID) {
+            carrierIdMatchingResult.carrierId = cid;
+            if (gid1 != null) {
+                carrierIdMatchingResult.gid1 = gid1;
+            }
+        }
+
+        carrierIdMatching.result = carrierIdMatchingResult;
+
+        TelephonyEvent event = new TelephonyEventBuilder(phoneId).setCarrierIdMatching(
+                carrierIdMatching).build();
+        addTelephonyEvent(event);
+    }
+
     //TODO: Expand the proto in the future
     public void writeOnImsCallProgressing(int phoneId, ImsCallSession session) {}
     public void writeOnImsCallStarted(int phoneId, ImsCallSession session) {}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
index 08758fd..e659333 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
@@ -38,6 +38,7 @@
 import android.net.LinkAddress;
 import android.net.NetworkUtils;
 import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
 import android.telephony.data.DataCallResponse;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Base64;
@@ -181,6 +182,42 @@
         assertEquals("Test", log.events[0].modemRestart.reason);
     }
 
+    // Test write Carrier Identification matching event
+    @Test
+    @SmallTest
+    public void testWriteCarrierIdMatchingEventWithInvalidMatchingScore() throws Exception {
+
+        mMetrics.writeCarrierIdMatchingEvent(mPhone.getPhoneId(),
+                TelephonyManager.UNKNOWN_CARRIER_ID, "gid1Test");
+        TelephonyLog log = buildProto();
+
+        assertEquals(1, log.events.length);
+        assertEquals(0, log.callSessions.length);
+        assertEquals(0, log.smsSessions.length);
+
+        assertEquals(mPhone.getPhoneId(), log.events[0].phoneId);
+        assertEquals(TelephonyEvent.Type.CARRIER_ID_MATCHING, log.events[0].type);
+        assertTrue(log.events[0].carrierIdMatching.result.gid1.isEmpty());
+    }
+
+    // Test write Carrier Identification matching event
+    @Test
+    @SmallTest
+    public void testWriteCarrierIdMatchingEvent() throws Exception {
+
+        mMetrics.writeCarrierIdMatchingEvent(mPhone.getPhoneId(), 1, "gid1Test");
+        TelephonyLog log = buildProto();
+
+        assertEquals(1, log.events.length);
+        assertEquals(0, log.callSessions.length);
+        assertEquals(0, log.smsSessions.length);
+
+        assertEquals(mPhone.getPhoneId(), log.events[0].phoneId);
+        assertEquals(TelephonyEvent.Type.CARRIER_ID_MATCHING, log.events[0].type);
+        assertEquals(1, log.events[0].carrierIdMatching.result.carrierId);
+        assertEquals("gid1Test", log.events[0].carrierIdMatching.result.gid1);
+    }
+
     // Test write on IMS call start
     @Test
     @SmallTest