Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9a64865 authored by Chen Xu's avatar Chen Xu Committed by android-build-merger
Browse files

Merge "improve carrier id metrics" into qt-dev

am: 3394d9fa

Change-Id: Idd31a986303b556c9c83ce78970c763b99fe37bc
parents 81ed826f 3394d9fa
Loading
Loading
Loading
Loading
+34 −2
Original line number Diff line number Diff line
@@ -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
+110 −62
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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
@@ -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;
@@ -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;
@@ -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;
                }
@@ -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;
@@ -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) {
@@ -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() {
@@ -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) {
+26 −8
Original line number Diff line number Diff line
@@ -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;
@@ -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;
+46 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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 {
@@ -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);
@@ -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);
@@ -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);
    }