Loading proto/src/telephony.proto +34 −2 Original line number Diff line number Diff line Loading @@ -1573,11 +1573,43 @@ message TelephonyEvent { // Group id level 1. Logged only if gid1 is configured from subscription // but its matching rule is unknown optional string gid1 = 2; optional string unknown_gid1 = 2; // MCC and MNC that map to this carrier. Logged only if mccmnc is configured // from subscription but its matching rule is unknown optional string mccmnc = 3; optional string unknown_mccmnc = 3; // MCC and MNC from the subscription that map to this carrier. optional string mccmnc = 4; // Group id level 1 from the subscription that map to this carrier. optional string gid1 = 5; // Group id level 2 from the subscription that map to this carrier. optional string gid2 = 6; // spn from the subscription that map to this carrier. optional string spn = 7; // pnn from the subscription that map to this carrier. optional string pnn = 8; // iccid prefix from the subscription that map to this carrier. // only log first 7 outof 20 bit of full iccid optional string iccid_prefix = 9; // imsi prefix from the subscription that map to this carrier. // only log additional 2 bits other than MCC MNC. optional string imsi_prefix = 10; // Carrier Privilege Access Rule in hex string from the subscription. // Sample values: 61ed377e85d386a8dfee6b864bd85b0bfaa5af88 repeated string privilege_access_rule = 11; // The Access Point Name, corresponding to "apn" field returned by // "content://telephony/carriers/preferapn" on device. // Sample values: fast.t-mobile.com, internet. Note only log if this apn is not user edited. optional string preferApn = 12; } // Time when event happened on device, in milliseconds since epoch Loading src/java/com/android/internal/telephony/CarrierResolver.java +110 −62 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.text.TextUtils; import android.util.LocalLog; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.uicc.IccRecords; import com.android.internal.telephony.uicc.UiccController; Loading Loading @@ -362,6 +363,23 @@ public class CarrierResolver extends Handler { return null; } private boolean isPreferApnUserEdited(@NonNull String preferApn) { try (Cursor cursor = mContext.getContentResolver().query( Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "preferapn/subId/" + mPhone.getSubId()), /* projection */ new String[]{Telephony.Carriers.EDITED_STATUS}, /* selection */ Telephony.Carriers.APN + "=?", /* selectionArgs */ new String[]{preferApn}, /* sortOrder */ null) ) { if (cursor != null && cursor.moveToFirst()) { return cursor.getInt(cursor.getColumnIndexOrThrow( Telephony.Carriers.EDITED_STATUS)) == Telephony.Carriers.USER_EDITED; } } catch (Exception ex) { loge("[isPreferApnUserEdited]- exception: " + ex); } return false; } public void setTestOverrideApn(String apn) { logd("[setTestOverrideApn]: " + apn); mTestOverrideApn = apn; Loading Loading @@ -472,7 +490,7 @@ public class CarrierResolver extends Handler { /** * carrier matching attributes with corresponding cid */ private static class CarrierMatchingRule { public static class CarrierMatchingRule { /** * These scores provide the hierarchical relationship between the attributes, intended to * resolve conflicts in a deterministic way. The scores are constructed such that a match Loading @@ -495,16 +513,16 @@ public class CarrierResolver extends Handler { private static final int SCORE_INVALID = -1; // carrier matching attributes private final String mMccMnc; private final String mImsiPrefixPattern; private final String mIccidPrefix; private final String mGid1; private final String mGid2; private final String mPlmn; private final String mSpn; private final String mApn; public final String mccMnc; public final String imsiPrefixPattern; public final String iccidPrefix; public final String gid1; public final String gid2; public final String plmn; public final String spn; public final String apn; // there can be multiple certs configured in the UICC private final List<String> mPrivilegeAccessRule; public final List<String> privilegeAccessRule; // user-facing carrier name private String mName; Loading @@ -515,33 +533,34 @@ public class CarrierResolver extends Handler { private int mScore = 0; private CarrierMatchingRule(String mccmnc, String imsiPrefixPattern, String iccidPrefix, @VisibleForTesting public CarrierMatchingRule(String mccmnc, String imsiPrefixPattern, String iccidPrefix, String gid1, String gid2, String plmn, String spn, String apn, List<String> privilegeAccessRule, int cid, String name, int parentCid) { mMccMnc = mccmnc; mImsiPrefixPattern = imsiPrefixPattern; mIccidPrefix = iccidPrefix; mGid1 = gid1; mGid2 = gid2; mPlmn = plmn; mSpn = spn; mApn = apn; mPrivilegeAccessRule = privilegeAccessRule; mccMnc = mccmnc; this.imsiPrefixPattern = imsiPrefixPattern; this.iccidPrefix = iccidPrefix; this.gid1 = gid1; this.gid2 = gid2; this.plmn = plmn; this.spn = spn; this.apn = apn; this.privilegeAccessRule = privilegeAccessRule; mCid = cid; mName = name; mParentCid = parentCid; } private CarrierMatchingRule(CarrierMatchingRule rule) { mMccMnc = rule.mMccMnc; mImsiPrefixPattern = rule.mImsiPrefixPattern; mIccidPrefix = rule.mIccidPrefix; mGid1 = rule.mGid1; mGid2 = rule.mGid2; mPlmn = rule.mPlmn; mSpn = rule.mSpn; mApn = rule.mApn; mPrivilegeAccessRule = rule.mPrivilegeAccessRule; mccMnc = rule.mccMnc; imsiPrefixPattern = rule.imsiPrefixPattern; iccidPrefix = rule.iccidPrefix; gid1 = rule.gid1; gid2 = rule.gid2; plmn = rule.plmn; spn = rule.spn; apn = rule.apn; privilegeAccessRule = rule.privilegeAccessRule; mCid = rule.mCid; mName = rule.mName; mParentCid = rule.mParentCid; Loading @@ -554,67 +573,67 @@ public class CarrierResolver extends Handler { // matches at the same tier, the match with highest score will be used. public void match(CarrierMatchingRule subscriptionRule) { mScore = 0; if (mMccMnc != null) { if (!CarrierResolver.equals(subscriptionRule.mMccMnc, mMccMnc, false)) { if (mccMnc != null) { if (!CarrierResolver.equals(subscriptionRule.mccMnc, mccMnc, false)) { mScore = SCORE_INVALID; return; } mScore += SCORE_MCCMNC; } if (mImsiPrefixPattern != null) { if (!imsiPrefixMatch(subscriptionRule.mImsiPrefixPattern, mImsiPrefixPattern)) { if (imsiPrefixPattern != null) { if (!imsiPrefixMatch(subscriptionRule.imsiPrefixPattern, imsiPrefixPattern)) { mScore = SCORE_INVALID; return; } mScore += SCORE_IMSI_PREFIX; } if (mIccidPrefix != null) { if (!iccidPrefixMatch(subscriptionRule.mIccidPrefix, mIccidPrefix)) { if (iccidPrefix != null) { if (!iccidPrefixMatch(subscriptionRule.iccidPrefix, iccidPrefix)) { mScore = SCORE_INVALID; return; } mScore += SCORE_ICCID_PREFIX; } if (mGid1 != null) { if (!gidMatch(subscriptionRule.mGid1, mGid1)) { if (gid1 != null) { if (!gidMatch(subscriptionRule.gid1, gid1)) { mScore = SCORE_INVALID; return; } mScore += SCORE_GID1; } if (mGid2 != null) { if (!gidMatch(subscriptionRule.mGid2, mGid2)) { if (gid2 != null) { if (!gidMatch(subscriptionRule.gid2, gid2)) { mScore = SCORE_INVALID; return; } mScore += SCORE_GID2; } if (mPlmn != null) { if (!CarrierResolver.equals(subscriptionRule.mPlmn, mPlmn, true)) { if (plmn != null) { if (!CarrierResolver.equals(subscriptionRule.plmn, plmn, true)) { mScore = SCORE_INVALID; return; } mScore += SCORE_PLMN; } if (mSpn != null) { if (!CarrierResolver.equals(subscriptionRule.mSpn, mSpn, true)) { if (spn != null) { if (!CarrierResolver.equals(subscriptionRule.spn, spn, true)) { mScore = SCORE_INVALID; return; } mScore += SCORE_SPN; } if (mPrivilegeAccessRule != null && !mPrivilegeAccessRule.isEmpty()) { if (!carrierPrivilegeRulesMatch(subscriptionRule.mPrivilegeAccessRule, mPrivilegeAccessRule)) { if (privilegeAccessRule != null && !privilegeAccessRule.isEmpty()) { if (!carrierPrivilegeRulesMatch(subscriptionRule.privilegeAccessRule, privilegeAccessRule)) { mScore = SCORE_INVALID; return; } mScore += SCORE_PRIVILEGE_ACCESS_RULE; } if (mApn != null) { if (!CarrierResolver.equals(subscriptionRule.mApn, mApn, true)) { if (apn != null) { if (!CarrierResolver.equals(subscriptionRule.apn, apn, true)) { mScore = SCORE_INVALID; return; } Loading Loading @@ -669,15 +688,15 @@ public class CarrierResolver extends Handler { public String toString() { return "[CarrierMatchingRule] -" + " mccmnc: " + mMccMnc + " gid1: " + mGid1 + " gid2: " + mGid2 + " plmn: " + mPlmn + " imsi_prefix: " + mImsiPrefixPattern + " iccid_prefix" + mIccidPrefix + " spn: " + mSpn + " privilege_access_rule: " + mPrivilegeAccessRule + " apn: " + mApn + " mccmnc: " + mccMnc + " gid1: " + gid1 + " gid2: " + gid2 + " plmn: " + plmn + " imsi_prefix: " + imsiPrefixPattern + " iccid_prefix" + iccidPrefix + " spn: " + spn + " privilege_access_rule: " + privilegeAccessRule + " apn: " + apn + " name: " + mName + " cid: " + mCid + " score: " + mScore; Loading @@ -698,7 +717,8 @@ public class CarrierResolver extends Handler { if (!TextUtils.isEmpty(mTestOverrideCarrierPriviledgeRule)) { accessRules = new ArrayList<>(Arrays.asList(mTestOverrideCarrierPriviledgeRule)); } else { accessRules = mTelephonyMgr.getCertsFromCarrierPrivilegeAccessRules(); accessRules = mTelephonyMgr.createForSubscriptionId(mPhone.getSubId()) .getCertsFromCarrierPrivilegeAccessRules(); } if (VDBG) { Loading Loading @@ -793,13 +813,41 @@ public class CarrierResolver extends Handler { * 4) use carrier list version to compare the unknown carrier ratio between each version. */ String unknownGid1ToLog = ((maxScore & CarrierMatchingRule.SCORE_GID1) == 0 && !TextUtils.isEmpty(subscriptionRule.mGid1)) ? subscriptionRule.mGid1 : null; && !TextUtils.isEmpty(subscriptionRule.gid1)) ? subscriptionRule.gid1 : null; String unknownMccmncToLog = ((maxScore == CarrierMatchingRule.SCORE_INVALID || (maxScore & CarrierMatchingRule.SCORE_GID1) == 0) && !TextUtils.isEmpty(subscriptionRule.mMccMnc)) ? subscriptionRule.mMccMnc : null; && !TextUtils.isEmpty(subscriptionRule.mccMnc)) ? subscriptionRule.mccMnc : null; // pass subscription rule to metrics. scrub all possible PII before uploading. // only log apn if not user edited. String apn = (subscriptionRule.apn != null && !isPreferApnUserEdited(subscriptionRule.apn)) ? subscriptionRule.apn : null; // only log first 7 bits of iccid String iccidPrefix = (subscriptionRule.iccidPrefix != null) && (subscriptionRule.iccidPrefix.length() >= 7) ? subscriptionRule.iccidPrefix.substring(0, 7) : subscriptionRule.iccidPrefix; // only log first 8 bits of imsi String imsiPrefix = (subscriptionRule.imsiPrefixPattern != null) && (subscriptionRule.imsiPrefixPattern.length() >= 8) ? subscriptionRule.imsiPrefixPattern.substring(0, 8) : subscriptionRule.imsiPrefixPattern; CarrierMatchingRule simInfo = new CarrierMatchingRule( subscriptionRule.mccMnc, imsiPrefix, iccidPrefix, subscriptionRule.gid1, subscriptionRule.gid2, subscriptionRule.plmn, subscriptionRule.spn, apn, subscriptionRule.privilegeAccessRule, -1, null, -1); TelephonyMetrics.getInstance().writeCarrierIdMatchingEvent( mPhone.getPhoneId(), getCarrierListVersion(), mCarrierId, unknownMccmncToLog, unknownGid1ToLog); unknownMccmncToLog, unknownGid1ToLog, simInfo); } public int getCarrierListVersion() { Loading Loading @@ -874,7 +922,7 @@ public class CarrierResolver extends Handler { int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; int maxScore = CarrierMatchingRule.SCORE_INVALID; List<CarrierMatchingRule> rules = getCarrierMatchingRulesFromMccMnc( context, targetRule.mMccMnc); context, targetRule.mccMnc); for (CarrierMatchingRule rule : rules) { rule.match(targetRule); if (rule.mScore > maxScore) { Loading src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java +26 −8 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import android.text.TextUtils; import android.util.Base64; import android.util.SparseArray; import com.android.internal.telephony.CarrierResolver; import com.android.internal.telephony.DriverCall; import com.android.internal.telephony.GsmCdmaConnection; import com.android.internal.telephony.PhoneConstants; Loading Loading @@ -2397,27 +2398,44 @@ public class TelephonyMetrics { * @param phoneId Phone id * @param version Carrier table version * @param cid Unique Carrier Id * @param mccmnc MCC and MNC that map to this carrier * @param gid1 Group id level 1 * @param unknownMcmnc MCC and MNC that map to this carrier * @param unknownGid1 Group id level 1 * @param simInfo Subscription info */ public void writeCarrierIdMatchingEvent(int phoneId, int version, int cid, String mccmnc, String gid1) { String unknownMcmnc, String unknownGid1, CarrierResolver.CarrierMatchingRule simInfo) { final CarrierIdMatching carrierIdMatching = new CarrierIdMatching(); final CarrierIdMatchingResult carrierIdMatchingResult = new CarrierIdMatchingResult(); // fill in information for unknown mccmnc and gid1 for unidentified carriers. if (cid != TelephonyManager.UNKNOWN_CARRIER_ID) { // Successful matching event if result only has carrierId carrierIdMatchingResult.carrierId = cid; // Unknown Gid1 event if result only has carrierId, gid1 and mccmnc if (gid1 != null) { carrierIdMatchingResult.mccmnc = mccmnc; carrierIdMatchingResult.gid1 = gid1; if (unknownGid1 != null) { carrierIdMatchingResult.unknownMccmnc = unknownMcmnc; carrierIdMatchingResult.unknownGid1 = unknownGid1; } } else { // Unknown mccmnc event if result only has mccmnc if (mccmnc != null) { carrierIdMatchingResult.mccmnc = mccmnc; } if (unknownMcmnc != null) { carrierIdMatchingResult.unknownMccmnc = unknownMcmnc; } } // fill in complete matching information from the SIM. carrierIdMatchingResult.mccmnc = simInfo.mccMnc; carrierIdMatchingResult.spn = simInfo.spn; carrierIdMatchingResult.pnn = simInfo.plmn; carrierIdMatchingResult.gid1 = simInfo.gid1; carrierIdMatchingResult.gid2 = simInfo.gid2; carrierIdMatchingResult.imsiPrefix = simInfo.imsiPrefixPattern; carrierIdMatchingResult.iccidPrefix = simInfo.iccidPrefix; carrierIdMatchingResult.preferApn = simInfo.apn; if (simInfo.privilegeAccessRule != null) { carrierIdMatchingResult.privilegeAccessRule = simInfo.privilegeAccessRule.stream().toArray(String[]::new); } carrierIdMatching.cidTableVersion = version; Loading tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java +46 −4 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.test.suitebuilder.annotation.SmallTest; import android.util.Base64; import com.android.internal.telephony.Call; import com.android.internal.telephony.CarrierResolver; import com.android.internal.telephony.GsmCdmaConnection; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.SmsResponse; Loading @@ -73,6 +74,7 @@ import org.junit.Test; import org.mockito.Mock; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; public class TelephonyMetricsTest extends TelephonyTest { Loading Loading @@ -188,9 +190,23 @@ public class TelephonyMetricsTest extends TelephonyTest { @Test @SmallTest public void testWriteCarrierIdMatchingEventWithInvalidMatchingScore() throws Exception { CarrierResolver.CarrierMatchingRule simInfo = new CarrierResolver.CarrierMatchingRule( "mccmncTest", "imsiPrefixTest", "iccidPrefixTest", "gid1Test", "gid2Test", "plmnTest", "spnTest", "apnTest", new ArrayList<>(), -1, null, -1); mMetrics.writeCarrierIdMatchingEvent(mPhone.getPhoneId(), 1, TelephonyManager.UNKNOWN_CARRIER_ID, "mccmncTest", "gid1Test"); TelephonyManager.UNKNOWN_CARRIER_ID, "unknownMccmncTest", "unknownGid1Test", simInfo); TelephonyLog log = buildProto(); assertEquals(1, log.events.length); Loading @@ -200,16 +216,35 @@ public class TelephonyMetricsTest extends TelephonyTest { assertEquals(mPhone.getPhoneId(), log.events[0].phoneId); assertEquals(1, log.events[0].carrierIdMatching.cidTableVersion); assertEquals(TelephonyEvent.Type.CARRIER_ID_MATCHING, log.events[0].type); assertEquals("unknownMccmncTest", log.events[0].carrierIdMatching.result.unknownMccmnc); assertTrue(log.events[0].carrierIdMatching.result.unknownGid1.isEmpty()); assertEquals("iccidPrefixTest", log.events[0].carrierIdMatching.result.iccidPrefix); assertEquals("imsiPrefixTest", log.events[0].carrierIdMatching.result.imsiPrefix); assertEquals("spnTest", log.events[0].carrierIdMatching.result.spn); assertEquals("plmnTest", log.events[0].carrierIdMatching.result.pnn); assertEquals("apnTest", log.events[0].carrierIdMatching.result.preferApn); assertEquals("mccmncTest", log.events[0].carrierIdMatching.result.mccmnc); assertTrue(log.events[0].carrierIdMatching.result.gid1.isEmpty()); assertEquals("gid1Test", log.events[0].carrierIdMatching.result.gid1); } // Test write Carrier Identification matching event @Test @SmallTest public void testWriteCarrierIdMatchingEvent() throws Exception { mMetrics.writeCarrierIdMatchingEvent(mPhone.getPhoneId(), 1, 1, "mccmncTest", "gid1Test"); CarrierResolver.CarrierMatchingRule simInfo = new CarrierResolver.CarrierMatchingRule( "mccmncTest", "imsiPrefixTest", "iccidPrefixTest", "gid1Test", "gid2Test", "plmnTest", "spnTest", "apnTest", new ArrayList<>(), -1, null, -1); mMetrics.writeCarrierIdMatchingEvent(mPhone.getPhoneId(), 1, 1, "unknownMccmncTest", "unknownGid1Test", simInfo); TelephonyLog log = buildProto(); assertEquals(1, log.events.length); Loading @@ -220,6 +255,13 @@ public class TelephonyMetricsTest extends TelephonyTest { assertEquals(TelephonyEvent.Type.CARRIER_ID_MATCHING, log.events[0].type); assertEquals(1, log.events[0].carrierIdMatching.cidTableVersion); assertEquals(1, log.events[0].carrierIdMatching.result.carrierId); assertEquals("unknownMccmncTest", log.events[0].carrierIdMatching.result.unknownMccmnc); assertEquals("unknownGid1Test", log.events[0].carrierIdMatching.result.unknownGid1); assertEquals("iccidPrefixTest", log.events[0].carrierIdMatching.result.iccidPrefix); assertEquals("imsiPrefixTest", log.events[0].carrierIdMatching.result.imsiPrefix); assertEquals("spnTest", log.events[0].carrierIdMatching.result.spn); assertEquals("plmnTest", log.events[0].carrierIdMatching.result.pnn); assertEquals("apnTest", log.events[0].carrierIdMatching.result.preferApn); assertEquals("mccmncTest", log.events[0].carrierIdMatching.result.mccmnc); assertEquals("gid1Test", log.events[0].carrierIdMatching.result.gid1); } Loading Loading
proto/src/telephony.proto +34 −2 Original line number Diff line number Diff line Loading @@ -1573,11 +1573,43 @@ message TelephonyEvent { // Group id level 1. Logged only if gid1 is configured from subscription // but its matching rule is unknown optional string gid1 = 2; optional string unknown_gid1 = 2; // MCC and MNC that map to this carrier. Logged only if mccmnc is configured // from subscription but its matching rule is unknown optional string mccmnc = 3; optional string unknown_mccmnc = 3; // MCC and MNC from the subscription that map to this carrier. optional string mccmnc = 4; // Group id level 1 from the subscription that map to this carrier. optional string gid1 = 5; // Group id level 2 from the subscription that map to this carrier. optional string gid2 = 6; // spn from the subscription that map to this carrier. optional string spn = 7; // pnn from the subscription that map to this carrier. optional string pnn = 8; // iccid prefix from the subscription that map to this carrier. // only log first 7 outof 20 bit of full iccid optional string iccid_prefix = 9; // imsi prefix from the subscription that map to this carrier. // only log additional 2 bits other than MCC MNC. optional string imsi_prefix = 10; // Carrier Privilege Access Rule in hex string from the subscription. // Sample values: 61ed377e85d386a8dfee6b864bd85b0bfaa5af88 repeated string privilege_access_rule = 11; // The Access Point Name, corresponding to "apn" field returned by // "content://telephony/carriers/preferapn" on device. // Sample values: fast.t-mobile.com, internet. Note only log if this apn is not user edited. optional string preferApn = 12; } // Time when event happened on device, in milliseconds since epoch Loading
src/java/com/android/internal/telephony/CarrierResolver.java +110 −62 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.text.TextUtils; import android.util.LocalLog; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.uicc.IccRecords; import com.android.internal.telephony.uicc.UiccController; Loading Loading @@ -362,6 +363,23 @@ public class CarrierResolver extends Handler { return null; } private boolean isPreferApnUserEdited(@NonNull String preferApn) { try (Cursor cursor = mContext.getContentResolver().query( Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "preferapn/subId/" + mPhone.getSubId()), /* projection */ new String[]{Telephony.Carriers.EDITED_STATUS}, /* selection */ Telephony.Carriers.APN + "=?", /* selectionArgs */ new String[]{preferApn}, /* sortOrder */ null) ) { if (cursor != null && cursor.moveToFirst()) { return cursor.getInt(cursor.getColumnIndexOrThrow( Telephony.Carriers.EDITED_STATUS)) == Telephony.Carriers.USER_EDITED; } } catch (Exception ex) { loge("[isPreferApnUserEdited]- exception: " + ex); } return false; } public void setTestOverrideApn(String apn) { logd("[setTestOverrideApn]: " + apn); mTestOverrideApn = apn; Loading Loading @@ -472,7 +490,7 @@ public class CarrierResolver extends Handler { /** * carrier matching attributes with corresponding cid */ private static class CarrierMatchingRule { public static class CarrierMatchingRule { /** * These scores provide the hierarchical relationship between the attributes, intended to * resolve conflicts in a deterministic way. The scores are constructed such that a match Loading @@ -495,16 +513,16 @@ public class CarrierResolver extends Handler { private static final int SCORE_INVALID = -1; // carrier matching attributes private final String mMccMnc; private final String mImsiPrefixPattern; private final String mIccidPrefix; private final String mGid1; private final String mGid2; private final String mPlmn; private final String mSpn; private final String mApn; public final String mccMnc; public final String imsiPrefixPattern; public final String iccidPrefix; public final String gid1; public final String gid2; public final String plmn; public final String spn; public final String apn; // there can be multiple certs configured in the UICC private final List<String> mPrivilegeAccessRule; public final List<String> privilegeAccessRule; // user-facing carrier name private String mName; Loading @@ -515,33 +533,34 @@ public class CarrierResolver extends Handler { private int mScore = 0; private CarrierMatchingRule(String mccmnc, String imsiPrefixPattern, String iccidPrefix, @VisibleForTesting public CarrierMatchingRule(String mccmnc, String imsiPrefixPattern, String iccidPrefix, String gid1, String gid2, String plmn, String spn, String apn, List<String> privilegeAccessRule, int cid, String name, int parentCid) { mMccMnc = mccmnc; mImsiPrefixPattern = imsiPrefixPattern; mIccidPrefix = iccidPrefix; mGid1 = gid1; mGid2 = gid2; mPlmn = plmn; mSpn = spn; mApn = apn; mPrivilegeAccessRule = privilegeAccessRule; mccMnc = mccmnc; this.imsiPrefixPattern = imsiPrefixPattern; this.iccidPrefix = iccidPrefix; this.gid1 = gid1; this.gid2 = gid2; this.plmn = plmn; this.spn = spn; this.apn = apn; this.privilegeAccessRule = privilegeAccessRule; mCid = cid; mName = name; mParentCid = parentCid; } private CarrierMatchingRule(CarrierMatchingRule rule) { mMccMnc = rule.mMccMnc; mImsiPrefixPattern = rule.mImsiPrefixPattern; mIccidPrefix = rule.mIccidPrefix; mGid1 = rule.mGid1; mGid2 = rule.mGid2; mPlmn = rule.mPlmn; mSpn = rule.mSpn; mApn = rule.mApn; mPrivilegeAccessRule = rule.mPrivilegeAccessRule; mccMnc = rule.mccMnc; imsiPrefixPattern = rule.imsiPrefixPattern; iccidPrefix = rule.iccidPrefix; gid1 = rule.gid1; gid2 = rule.gid2; plmn = rule.plmn; spn = rule.spn; apn = rule.apn; privilegeAccessRule = rule.privilegeAccessRule; mCid = rule.mCid; mName = rule.mName; mParentCid = rule.mParentCid; Loading @@ -554,67 +573,67 @@ public class CarrierResolver extends Handler { // matches at the same tier, the match with highest score will be used. public void match(CarrierMatchingRule subscriptionRule) { mScore = 0; if (mMccMnc != null) { if (!CarrierResolver.equals(subscriptionRule.mMccMnc, mMccMnc, false)) { if (mccMnc != null) { if (!CarrierResolver.equals(subscriptionRule.mccMnc, mccMnc, false)) { mScore = SCORE_INVALID; return; } mScore += SCORE_MCCMNC; } if (mImsiPrefixPattern != null) { if (!imsiPrefixMatch(subscriptionRule.mImsiPrefixPattern, mImsiPrefixPattern)) { if (imsiPrefixPattern != null) { if (!imsiPrefixMatch(subscriptionRule.imsiPrefixPattern, imsiPrefixPattern)) { mScore = SCORE_INVALID; return; } mScore += SCORE_IMSI_PREFIX; } if (mIccidPrefix != null) { if (!iccidPrefixMatch(subscriptionRule.mIccidPrefix, mIccidPrefix)) { if (iccidPrefix != null) { if (!iccidPrefixMatch(subscriptionRule.iccidPrefix, iccidPrefix)) { mScore = SCORE_INVALID; return; } mScore += SCORE_ICCID_PREFIX; } if (mGid1 != null) { if (!gidMatch(subscriptionRule.mGid1, mGid1)) { if (gid1 != null) { if (!gidMatch(subscriptionRule.gid1, gid1)) { mScore = SCORE_INVALID; return; } mScore += SCORE_GID1; } if (mGid2 != null) { if (!gidMatch(subscriptionRule.mGid2, mGid2)) { if (gid2 != null) { if (!gidMatch(subscriptionRule.gid2, gid2)) { mScore = SCORE_INVALID; return; } mScore += SCORE_GID2; } if (mPlmn != null) { if (!CarrierResolver.equals(subscriptionRule.mPlmn, mPlmn, true)) { if (plmn != null) { if (!CarrierResolver.equals(subscriptionRule.plmn, plmn, true)) { mScore = SCORE_INVALID; return; } mScore += SCORE_PLMN; } if (mSpn != null) { if (!CarrierResolver.equals(subscriptionRule.mSpn, mSpn, true)) { if (spn != null) { if (!CarrierResolver.equals(subscriptionRule.spn, spn, true)) { mScore = SCORE_INVALID; return; } mScore += SCORE_SPN; } if (mPrivilegeAccessRule != null && !mPrivilegeAccessRule.isEmpty()) { if (!carrierPrivilegeRulesMatch(subscriptionRule.mPrivilegeAccessRule, mPrivilegeAccessRule)) { if (privilegeAccessRule != null && !privilegeAccessRule.isEmpty()) { if (!carrierPrivilegeRulesMatch(subscriptionRule.privilegeAccessRule, privilegeAccessRule)) { mScore = SCORE_INVALID; return; } mScore += SCORE_PRIVILEGE_ACCESS_RULE; } if (mApn != null) { if (!CarrierResolver.equals(subscriptionRule.mApn, mApn, true)) { if (apn != null) { if (!CarrierResolver.equals(subscriptionRule.apn, apn, true)) { mScore = SCORE_INVALID; return; } Loading Loading @@ -669,15 +688,15 @@ public class CarrierResolver extends Handler { public String toString() { return "[CarrierMatchingRule] -" + " mccmnc: " + mMccMnc + " gid1: " + mGid1 + " gid2: " + mGid2 + " plmn: " + mPlmn + " imsi_prefix: " + mImsiPrefixPattern + " iccid_prefix" + mIccidPrefix + " spn: " + mSpn + " privilege_access_rule: " + mPrivilegeAccessRule + " apn: " + mApn + " mccmnc: " + mccMnc + " gid1: " + gid1 + " gid2: " + gid2 + " plmn: " + plmn + " imsi_prefix: " + imsiPrefixPattern + " iccid_prefix" + iccidPrefix + " spn: " + spn + " privilege_access_rule: " + privilegeAccessRule + " apn: " + apn + " name: " + mName + " cid: " + mCid + " score: " + mScore; Loading @@ -698,7 +717,8 @@ public class CarrierResolver extends Handler { if (!TextUtils.isEmpty(mTestOverrideCarrierPriviledgeRule)) { accessRules = new ArrayList<>(Arrays.asList(mTestOverrideCarrierPriviledgeRule)); } else { accessRules = mTelephonyMgr.getCertsFromCarrierPrivilegeAccessRules(); accessRules = mTelephonyMgr.createForSubscriptionId(mPhone.getSubId()) .getCertsFromCarrierPrivilegeAccessRules(); } if (VDBG) { Loading Loading @@ -793,13 +813,41 @@ public class CarrierResolver extends Handler { * 4) use carrier list version to compare the unknown carrier ratio between each version. */ String unknownGid1ToLog = ((maxScore & CarrierMatchingRule.SCORE_GID1) == 0 && !TextUtils.isEmpty(subscriptionRule.mGid1)) ? subscriptionRule.mGid1 : null; && !TextUtils.isEmpty(subscriptionRule.gid1)) ? subscriptionRule.gid1 : null; String unknownMccmncToLog = ((maxScore == CarrierMatchingRule.SCORE_INVALID || (maxScore & CarrierMatchingRule.SCORE_GID1) == 0) && !TextUtils.isEmpty(subscriptionRule.mMccMnc)) ? subscriptionRule.mMccMnc : null; && !TextUtils.isEmpty(subscriptionRule.mccMnc)) ? subscriptionRule.mccMnc : null; // pass subscription rule to metrics. scrub all possible PII before uploading. // only log apn if not user edited. String apn = (subscriptionRule.apn != null && !isPreferApnUserEdited(subscriptionRule.apn)) ? subscriptionRule.apn : null; // only log first 7 bits of iccid String iccidPrefix = (subscriptionRule.iccidPrefix != null) && (subscriptionRule.iccidPrefix.length() >= 7) ? subscriptionRule.iccidPrefix.substring(0, 7) : subscriptionRule.iccidPrefix; // only log first 8 bits of imsi String imsiPrefix = (subscriptionRule.imsiPrefixPattern != null) && (subscriptionRule.imsiPrefixPattern.length() >= 8) ? subscriptionRule.imsiPrefixPattern.substring(0, 8) : subscriptionRule.imsiPrefixPattern; CarrierMatchingRule simInfo = new CarrierMatchingRule( subscriptionRule.mccMnc, imsiPrefix, iccidPrefix, subscriptionRule.gid1, subscriptionRule.gid2, subscriptionRule.plmn, subscriptionRule.spn, apn, subscriptionRule.privilegeAccessRule, -1, null, -1); TelephonyMetrics.getInstance().writeCarrierIdMatchingEvent( mPhone.getPhoneId(), getCarrierListVersion(), mCarrierId, unknownMccmncToLog, unknownGid1ToLog); unknownMccmncToLog, unknownGid1ToLog, simInfo); } public int getCarrierListVersion() { Loading Loading @@ -874,7 +922,7 @@ public class CarrierResolver extends Handler { int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; int maxScore = CarrierMatchingRule.SCORE_INVALID; List<CarrierMatchingRule> rules = getCarrierMatchingRulesFromMccMnc( context, targetRule.mMccMnc); context, targetRule.mccMnc); for (CarrierMatchingRule rule : rules) { rule.match(targetRule); if (rule.mScore > maxScore) { Loading
src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java +26 −8 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import android.text.TextUtils; import android.util.Base64; import android.util.SparseArray; import com.android.internal.telephony.CarrierResolver; import com.android.internal.telephony.DriverCall; import com.android.internal.telephony.GsmCdmaConnection; import com.android.internal.telephony.PhoneConstants; Loading Loading @@ -2397,27 +2398,44 @@ public class TelephonyMetrics { * @param phoneId Phone id * @param version Carrier table version * @param cid Unique Carrier Id * @param mccmnc MCC and MNC that map to this carrier * @param gid1 Group id level 1 * @param unknownMcmnc MCC and MNC that map to this carrier * @param unknownGid1 Group id level 1 * @param simInfo Subscription info */ public void writeCarrierIdMatchingEvent(int phoneId, int version, int cid, String mccmnc, String gid1) { String unknownMcmnc, String unknownGid1, CarrierResolver.CarrierMatchingRule simInfo) { final CarrierIdMatching carrierIdMatching = new CarrierIdMatching(); final CarrierIdMatchingResult carrierIdMatchingResult = new CarrierIdMatchingResult(); // fill in information for unknown mccmnc and gid1 for unidentified carriers. if (cid != TelephonyManager.UNKNOWN_CARRIER_ID) { // Successful matching event if result only has carrierId carrierIdMatchingResult.carrierId = cid; // Unknown Gid1 event if result only has carrierId, gid1 and mccmnc if (gid1 != null) { carrierIdMatchingResult.mccmnc = mccmnc; carrierIdMatchingResult.gid1 = gid1; if (unknownGid1 != null) { carrierIdMatchingResult.unknownMccmnc = unknownMcmnc; carrierIdMatchingResult.unknownGid1 = unknownGid1; } } else { // Unknown mccmnc event if result only has mccmnc if (mccmnc != null) { carrierIdMatchingResult.mccmnc = mccmnc; } if (unknownMcmnc != null) { carrierIdMatchingResult.unknownMccmnc = unknownMcmnc; } } // fill in complete matching information from the SIM. carrierIdMatchingResult.mccmnc = simInfo.mccMnc; carrierIdMatchingResult.spn = simInfo.spn; carrierIdMatchingResult.pnn = simInfo.plmn; carrierIdMatchingResult.gid1 = simInfo.gid1; carrierIdMatchingResult.gid2 = simInfo.gid2; carrierIdMatchingResult.imsiPrefix = simInfo.imsiPrefixPattern; carrierIdMatchingResult.iccidPrefix = simInfo.iccidPrefix; carrierIdMatchingResult.preferApn = simInfo.apn; if (simInfo.privilegeAccessRule != null) { carrierIdMatchingResult.privilegeAccessRule = simInfo.privilegeAccessRule.stream().toArray(String[]::new); } carrierIdMatching.cidTableVersion = version; Loading
tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java +46 −4 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.test.suitebuilder.annotation.SmallTest; import android.util.Base64; import com.android.internal.telephony.Call; import com.android.internal.telephony.CarrierResolver; import com.android.internal.telephony.GsmCdmaConnection; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.SmsResponse; Loading @@ -73,6 +74,7 @@ import org.junit.Test; import org.mockito.Mock; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; public class TelephonyMetricsTest extends TelephonyTest { Loading Loading @@ -188,9 +190,23 @@ public class TelephonyMetricsTest extends TelephonyTest { @Test @SmallTest public void testWriteCarrierIdMatchingEventWithInvalidMatchingScore() throws Exception { CarrierResolver.CarrierMatchingRule simInfo = new CarrierResolver.CarrierMatchingRule( "mccmncTest", "imsiPrefixTest", "iccidPrefixTest", "gid1Test", "gid2Test", "plmnTest", "spnTest", "apnTest", new ArrayList<>(), -1, null, -1); mMetrics.writeCarrierIdMatchingEvent(mPhone.getPhoneId(), 1, TelephonyManager.UNKNOWN_CARRIER_ID, "mccmncTest", "gid1Test"); TelephonyManager.UNKNOWN_CARRIER_ID, "unknownMccmncTest", "unknownGid1Test", simInfo); TelephonyLog log = buildProto(); assertEquals(1, log.events.length); Loading @@ -200,16 +216,35 @@ public class TelephonyMetricsTest extends TelephonyTest { assertEquals(mPhone.getPhoneId(), log.events[0].phoneId); assertEquals(1, log.events[0].carrierIdMatching.cidTableVersion); assertEquals(TelephonyEvent.Type.CARRIER_ID_MATCHING, log.events[0].type); assertEquals("unknownMccmncTest", log.events[0].carrierIdMatching.result.unknownMccmnc); assertTrue(log.events[0].carrierIdMatching.result.unknownGid1.isEmpty()); assertEquals("iccidPrefixTest", log.events[0].carrierIdMatching.result.iccidPrefix); assertEquals("imsiPrefixTest", log.events[0].carrierIdMatching.result.imsiPrefix); assertEquals("spnTest", log.events[0].carrierIdMatching.result.spn); assertEquals("plmnTest", log.events[0].carrierIdMatching.result.pnn); assertEquals("apnTest", log.events[0].carrierIdMatching.result.preferApn); assertEquals("mccmncTest", log.events[0].carrierIdMatching.result.mccmnc); assertTrue(log.events[0].carrierIdMatching.result.gid1.isEmpty()); assertEquals("gid1Test", log.events[0].carrierIdMatching.result.gid1); } // Test write Carrier Identification matching event @Test @SmallTest public void testWriteCarrierIdMatchingEvent() throws Exception { mMetrics.writeCarrierIdMatchingEvent(mPhone.getPhoneId(), 1, 1, "mccmncTest", "gid1Test"); CarrierResolver.CarrierMatchingRule simInfo = new CarrierResolver.CarrierMatchingRule( "mccmncTest", "imsiPrefixTest", "iccidPrefixTest", "gid1Test", "gid2Test", "plmnTest", "spnTest", "apnTest", new ArrayList<>(), -1, null, -1); mMetrics.writeCarrierIdMatchingEvent(mPhone.getPhoneId(), 1, 1, "unknownMccmncTest", "unknownGid1Test", simInfo); TelephonyLog log = buildProto(); assertEquals(1, log.events.length); Loading @@ -220,6 +255,13 @@ public class TelephonyMetricsTest extends TelephonyTest { assertEquals(TelephonyEvent.Type.CARRIER_ID_MATCHING, log.events[0].type); assertEquals(1, log.events[0].carrierIdMatching.cidTableVersion); assertEquals(1, log.events[0].carrierIdMatching.result.carrierId); assertEquals("unknownMccmncTest", log.events[0].carrierIdMatching.result.unknownMccmnc); assertEquals("unknownGid1Test", log.events[0].carrierIdMatching.result.unknownGid1); assertEquals("iccidPrefixTest", log.events[0].carrierIdMatching.result.iccidPrefix); assertEquals("imsiPrefixTest", log.events[0].carrierIdMatching.result.imsiPrefix); assertEquals("spnTest", log.events[0].carrierIdMatching.result.spn); assertEquals("plmnTest", log.events[0].carrierIdMatching.result.pnn); assertEquals("apnTest", log.events[0].carrierIdMatching.result.preferApn); assertEquals("mccmncTest", log.events[0].carrierIdMatching.result.mccmnc); assertEquals("gid1Test", log.events[0].carrierIdMatching.result.gid1); } Loading