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

Commit a7719379 authored by Hunter Knepshield's avatar Hunter Knepshield Committed by Gerrit Code Review
Browse files

Merge "Migrate CarrierPrivilegesTracker to UiccAccessRule."

parents 9cc70d6f 2fde259f
Loading
Loading
Loading
Loading
+67 −61
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@ import android.util.IntArray;
import android.util.LocalLog;

import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.UiccCard;
import com.android.internal.telephony.uicc.UiccProfile;
import com.android.telephony.Rlog;

import java.io.FileDescriptor;
@@ -135,11 +137,11 @@ public class CarrierPrivilegesTracker extends Handler {
    private final RegistrantList mRegistrantList;
    private final LocalLog mLocalLog;

    // Stores rules for Carrier Config-loaded certs
    private final List<UiccAccessRule> mCarrierConfigCerts;
    // Stores rules for Carrier Config-loaded rules
    private final List<UiccAccessRule> mCarrierConfigRules;

    // TODO(b/151981841): Use Set<UiccAccessRule> to also check for package names loaded from SIM
    private final Set<String> mUiccCerts;
    // Stores rules for SIM-loaded rules.
    private final List<UiccAccessRule> mUiccRules;

    // Map of PackageName -> Certificate hashes for that Package
    private final Map<String, Set<String>> mInstalledPackageCerts;
@@ -235,8 +237,8 @@ public class CarrierPrivilegesTracker extends Handler {
        mContext.registerReceiver(mIntentReceiver, packageFilter);

        mRegistrantList = new RegistrantList();
        mCarrierConfigCerts = new ArrayList<>();
        mUiccCerts = new ArraySet<>();
        mCarrierConfigRules = new ArrayList<>();
        mUiccRules = new ArrayList<>();
        mInstalledPackageCerts = new ArrayMap<>();
        mCachedUids = new ArrayMap<>();
        mPrivilegedUids = new int[0];
@@ -298,67 +300,72 @@ public class CarrierPrivilegesTracker extends Handler {
    private void handleCarrierConfigUpdated(int subId, int slotIndex) {
        if (slotIndex != mPhone.getPhoneId()) return;

        List<UiccAccessRule> updatedCarrierConfigCerts = Collections.EMPTY_LIST;
        List<UiccAccessRule> updatedCarrierConfigRules = Collections.EMPTY_LIST;

        // Carrier Config broadcasts with INVALID_SUBSCRIPTION_ID when the SIM is removed. This is
        // an expected event. When this happens, clear the certificates from the previous configs.
        // The certs will be cleared in maybeUpdateCertsAndNotifyRegistrants() below.
        // The rules will be cleared in maybeUpdateRulesAndNotifyRegistrants() below.
        if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            updatedCarrierConfigCerts = getCarrierConfigCerts(subId);
            updatedCarrierConfigRules = getCarrierConfigRules(subId);
        }

        mLocalLog.log("CarrierConfigUpdated:"
                + " subId=" + subId
                + " slotIndex=" + slotIndex
                + " updated CarrierConfig certs=" + updatedCarrierConfigCerts);
        maybeUpdateCertsAndNotifyRegistrants(mCarrierConfigCerts, updatedCarrierConfigCerts);
                + " updated CarrierConfig rules=" + updatedCarrierConfigRules);
        maybeUpdateRulesAndNotifyRegistrants(mCarrierConfigRules, updatedCarrierConfigRules);
    }

    private List<UiccAccessRule> getCarrierConfigCerts(int subId) {
    private List<UiccAccessRule> getCarrierConfigRules(int subId) {
        PersistableBundle carrierConfigs = mCarrierConfigManager.getConfigForSubId(subId);
        if (!mCarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfigs)) {
            return Collections.EMPTY_LIST;
        }

        String[] carrierConfigCerts =
        String[] carrierConfigRules =
                carrierConfigs.getStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY);
        if (carrierConfigCerts == null) {
        if (carrierConfigRules == null) {
            return Collections.EMPTY_LIST;
        }
        return Arrays.asList(UiccAccessRule.decodeRulesFromCarrierConfig(carrierConfigCerts));
        return Arrays.asList(UiccAccessRule.decodeRulesFromCarrierConfig(carrierConfigRules));
    }

    private void handleSimStateChanged(int slotId, int simState) {
        if (slotId != mPhone.getPhoneId()) return;

        Set<String> updatedUiccCerts = Collections.EMPTY_SET;
        List<UiccAccessRule> updatedUiccRules = Collections.EMPTY_LIST;

        // Only include the UICC certs if the SIM is fully loaded
        // Only include the UICC rules if the SIM is fully loaded
        if (simState == SIM_STATE_LOADED) {
            updatedUiccCerts = getSimCerts();
            updatedUiccRules = getSimRules();
        }

        mLocalLog.log("SIM State Changed:"
                + " slotId=" + slotId
                + " simState=" + simState
                + " updated SIM-loaded certs=" + updatedUiccCerts);
        maybeUpdateCertsAndNotifyRegistrants(mUiccCerts, updatedUiccCerts);
                + " updated SIM-loaded rules=" + updatedUiccRules);
        maybeUpdateRulesAndNotifyRegistrants(mUiccRules, updatedUiccRules);
    }

    private Set<String> getSimCerts() {
        Set<String> updatedUiccCerts = Collections.EMPTY_SET;
        TelephonyManager telMan = mTelephonyManager.createForSubscriptionId(mPhone.getSubId());

        if (telMan.hasIccCard(mPhone.getPhoneId())) {
            updatedUiccCerts = new ArraySet<>();
            List<String> uiccCerts = telMan.getCertsFromCarrierPrivilegeAccessRules();
            if (uiccCerts != null) {
                for (String cert : uiccCerts) {
                    updatedUiccCerts.add(cert.toUpperCase());
    private List<UiccAccessRule> getSimRules() {
        if (!mTelephonyManager.hasIccCard(mPhone.getPhoneId())) {
            return Collections.EMPTY_LIST;
        }
        UiccCard uiccCard = mPhone.getUiccCard();
        if (uiccCard == null) {
            Rlog.w(
                    TAG,
                    "Null UiccCard, but hasIccCard was true for phoneId " + mPhone.getPhoneId());
            return Collections.EMPTY_LIST;
        }
        UiccProfile uiccProfile = uiccCard.getUiccProfile();
        if (uiccProfile == null) {
            Rlog.w(
                    TAG,
                    "Null UiccProfile, but hasIccCard was true for phoneId " + mPhone.getPhoneId());
            return Collections.EMPTY_LIST;
        }
        return updatedUiccCerts;
        return uiccProfile.getCarrierPrivilegeAccessRules();
    }

    private void handlePackageAddedOrReplaced(String pkgName) {
@@ -406,11 +413,11 @@ public class CarrierPrivilegesTracker extends Handler {
    }

    private void handleInitializeTracker() {
        // Cache CarrierConfig Certs
        mCarrierConfigCerts.addAll(getCarrierConfigCerts(mPhone.getSubId()));
        // Cache CarrierConfig rules
        mCarrierConfigRules.addAll(getCarrierConfigRules(mPhone.getSubId()));

        // Cache SIM certs
        mUiccCerts.addAll(getSimCerts());
        // Cache SIM rules
        mUiccRules.addAll(getSimRules());

        // Cache all installed packages and their certs
        int flags =
@@ -428,8 +435,8 @@ public class CarrierPrivilegesTracker extends Handler {
        maybeUpdatePrivilegedUidsAndNotifyRegistrants();

        String msg = "Initializing state:"
                + " CarrierConfig certs=" + mCarrierConfigCerts
                + " SIM-loaded certs=" + mUiccCerts;
                + " CarrierConfig rules=" + mCarrierConfigRules
                + " SIM-loaded rules=" + mUiccRules;
        if (VDBG) {
            msg += " installed pkgs=" + getObfuscatedPackages();
        }
@@ -444,22 +451,12 @@ public class CarrierPrivilegesTracker extends Handler {
        return obfuscatedPkgs.toString();
    }

    private void maybeUpdateCertsAndNotifyRegistrants(
            Set<String> currentCerts, Set<String> updatedCerts) {
        if (currentCerts.equals(updatedCerts)) return;

        currentCerts.clear();
        currentCerts.addAll(updatedCerts);

        maybeUpdatePrivilegedUidsAndNotifyRegistrants();
    }

    private void maybeUpdateCertsAndNotifyRegistrants(
            List<UiccAccessRule> currentCerts, List<UiccAccessRule> updatedCerts) {
        if (currentCerts.equals(updatedCerts)) return;
    private void maybeUpdateRulesAndNotifyRegistrants(
            List<UiccAccessRule> currentRules, List<UiccAccessRule> updatedRules) {
        if (currentRules.equals(updatedRules)) return;

        currentCerts.clear();
        currentCerts.addAll(updatedCerts);
        currentRules.clear();
        currentRules.addAll(updatedRules);

        maybeUpdatePrivilegedUidsAndNotifyRegistrants();
    }
@@ -494,16 +491,25 @@ public class CarrierPrivilegesTracker extends Handler {

    /**
     * Returns true iff there is an overlap between the provided certificate hashes and the
     * certificate hashes stored in mCarrierConfigCerts and mUiccCerts.
     * certificate hashes stored in mCarrierConfigRules and mUiccRules.
     */
    private boolean isPackagePrivileged(String pkgName, Set<String> certs) {
        // Double-nested for loops, but each collection should contain at most 2 elements in nearly
        // every case.
        // TODO(b/184382310) find a way to speed this up
        for (String cert : certs) {
            if (mCarrierConfigCerts.stream().anyMatch(rule -> rule.matches(cert, pkgName))) {
            for (UiccAccessRule rule : mCarrierConfigRules) {
                if (rule.matches(cert, pkgName)) {
                    return true;
                }
            }

        return !Collections.disjoint(mUiccCerts, certs);
            for (UiccAccessRule rule : mUiccRules) {
                if (rule.matches(cert, pkgName)) {
                    return true;
                }
            }
        }
        return false;
    }

    private Set<Integer> getUidsForPackage(String pkgName) {
@@ -536,8 +542,8 @@ public class CarrierPrivilegesTracker extends Handler {
        pw.println("CarrierPrivilegesTracker - Log End ----");
        pw.println("CarrierPrivilegesTracker - Privileged UIDs: "
                + Arrays.toString(mPrivilegedUids));
        pw.println("CarrierPrivilegesTracker - SIM-loaded Certs: " + mUiccCerts);
        pw.println("CarrierPrivilegesTracker - CarrierPrivileged Certs: " + mCarrierConfigCerts);
        pw.println("CarrierPrivilegesTracker - SIM-loaded rules: " + mUiccRules);
        pw.println("CarrierPrivilegesTracker - Carrier config rules: " + mCarrierConfigRules);
        if (VDBG) {
            pw.println("CarrierPrivilegesTracker - Obfuscated Pkgs + Certs: "
                    + getObfuscatedPackages());
+4 −4
Original line number Diff line number Diff line
@@ -149,7 +149,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";

    // Key used to read/write data_roaming_is_user_setting pref
    public static final String DATA_ROAMING_IS_USER_SETTING_KEY = "data_roaming_is_user_setting_key";
    public static final String DATA_ROAMING_IS_USER_SETTING_KEY =
            "data_roaming_is_user_setting_key";

    // Default value when there has been no last emergency SMS time recorded yet.
    private static final int EMERGENCY_SMS_NO_TIME_RECORDED = -1;
@@ -451,7 +452,7 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    protected boolean mIsCarrierNrSupported = false;

    private boolean mUnitTestMode;
    private final CarrierPrivilegesTracker mCarrierPrivilegesTracker;
    private CarrierPrivilegesTracker mCarrierPrivilegesTracker = null;

    protected VoiceCallSessionStats mVoiceCallSessionStats;
    protected SmsStats mSmsStats;
@@ -577,8 +578,6 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        mIsVoiceCapable = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
                .isVoiceCapable();

        mCarrierPrivilegesTracker = new CarrierPrivilegesTracker(mLooper, this, mContext);

        /**
         *  Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
         *  to be generated locally. Ideally all ring tones should be loops
@@ -614,6 +613,7 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        mSimActivationTracker = mTelephonyComponentFactory
                .inject(SimActivationTracker.class.getName())
                .makeSimActivationTracker(this);
        mCarrierPrivilegesTracker = new CarrierPrivilegesTracker(mLooper, this, mContext);
        if (getPhoneType() != PhoneConstants.PHONE_TYPE_SIP) {
            mCi.registerForSrvccStateChanged(this, EVENT_SRVCC_STATE_CHANGED, null);
        }
+9 −0
Original line number Diff line number Diff line
@@ -1733,6 +1733,15 @@ public class UiccProfile extends IccCard {
        return certs.isEmpty() ? null : certs;
    }

    /** @return a list of {@link UiccAccessRule}s, or an empty list if none have been loaded yet. */
    public List<UiccAccessRule> getCarrierPrivilegeAccessRules() {
        UiccCarrierPrivilegeRules carrierPrivilegeRules = getCarrierPrivilegeRules();
        if (carrierPrivilegeRules == null) {
            return Collections.EMPTY_LIST;
        }
        return new ArrayList<>(carrierPrivilegeRules.getAccessRules());
    }

    /**
     * Exposes {@link UiccCarrierPrivilegeRules#getCarrierPackageNamesForIntent}.
     */
+105 −33
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.os.Message;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccAccessRule;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
@@ -114,8 +115,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        mHandler = new CarrierPrivilegesTrackerTestHandler();

        // set mock behavior so CarrierPrivilegeTracker initializes with no privileged UIDs
        setupCarrierConfigCerts();
        setupSimLoadedCerts();
        setupCarrierConfigRules();
        setupSimLoadedRules();
        setupInstalledPackages();
    }

@@ -124,16 +125,33 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        super.tearDown();
    }

    private void setupCarrierConfigCerts(String... certHashes) {
        mCarrierConfigs.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, certHashes);
    /** @param rules can either be "hash" or "hash:package[,package...]" */
    private void setupCarrierConfigRules(String... rules) {
        mCarrierConfigs.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, rules);
        mCarrierConfigs.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
        when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfigs);
    }

    private void setupSimLoadedCerts(String... certHashes) {
    private static String carrierConfigRuleString(String certificateHash, String... packageNames) {
        if (packageNames == null || packageNames.length == 0) {
            return certificateHash;
        }
        return certificateHash + ':' + String.join(",", packageNames);
    }

    private void setupSimLoadedRules(UiccAccessRule... certHashes) {
        when(mTelephonyManager.hasIccCard(PHONE_ID)).thenReturn(true);
        when(mTelephonyManager.getCertsFromCarrierPrivilegeAccessRules())
                .thenReturn(Arrays.asList(certHashes));
        when(mUiccProfile.getCarrierPrivilegeAccessRules()).thenReturn(Arrays.asList(certHashes));
    }

    private static UiccAccessRule ruleWithHashOnly(String certificateHash) {
        return ruleWithHashAndPackage(certificateHash, null /* packageName */);
    }

    private static UiccAccessRule ruleWithHashAndPackage(
            String certificateHash, String packageName) {
        return new UiccAccessRule(
                IccUtils.hexStringToBytes(certificateHash), packageName, /* accessType= */ 0L);
    }

    private void setupInstalledPackages(PackageCertInfo... pkgCertInfos) throws Exception {
@@ -165,7 +183,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
     * <p>The initial configuration of the CarrierPrivilegesTracker will be based on the current
     * state of certificate hashes and installed packages.
     *
     * See #setupCarrierConfigCerts, #setupSimLoadedCerts, #setupInstalledPackages.
     * <p>See {@link #setupCarrierConfigRules}, {@link #setupSimLoadedRules}, {@link
     * #setupInstalledPackages}.
     */
    private CarrierPrivilegesTracker createCarrierPrivilegesTracker() throws Exception {
        CarrierPrivilegesTracker cpt =
@@ -180,7 +199,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    }

    private void setupCarrierPrivilegesTrackerWithCarrierConfigUids() throws Exception {
        setupCarrierConfigCerts(getHash(CERT_1), getHash(CERT_2));
        setupCarrierConfigRules(
                carrierConfigRuleString(getHash(CERT_1)), carrierConfigRuleString(getHash(CERT_2)));
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
@@ -188,7 +208,7 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    }

    private void setupCarrierPrivilegesTrackerWithSimLoadedUids() throws Exception {
        setupSimLoadedCerts(getHash(CERT_1), getHash(CERT_2));
        setupSimLoadedRules(ruleWithHashOnly(getHash(CERT_1)), ruleWithHashOnly(getHash(CERT_2)));
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
@@ -202,17 +222,15 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case REGISTRANT_WHAT: {
                case REGISTRANT_WHAT:
                    AsyncResult asyncResult = (AsyncResult) msg.obj;
                    privilegedUids = (int[]) asyncResult.result;
                    numUidUpdates++;
                    break;
                }
                default: {
                default:
                    fail("Unexpected msg received. what=" + msg.what);
            }
        }
        }

        void reset() {
            privilegedUids = null;
@@ -271,10 +289,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
        mCarrierConfigs.putStringArray(
                KEY_CARRIER_CERTIFICATE_STRING_ARRAY,
                new String[] {getHash(CERT_1), getHash(CERT_2)});
        when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfigs);
        setupCarrierConfigRules(
                carrierConfigRuleString(getHash(CERT_1)), carrierConfigRuleString(getHash(CERT_2)));

        sendCarrierConfigChangedIntent(SUB_ID, PHONE_ID);
        mTestableLooper.processAllMessages();
@@ -318,6 +334,34 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        verifyPrivilegedUids(new int[0] /* expectedUids */, 1 /* expectedUidUpdates */);
    }

    @Test
    public void testCarrierConfigUpdatedExplicitPackageNames() throws Exception {
        // Start with privileges specified just by wildcard certificate hashes, verify specifying
        // package names clears privileges on UIDs that don't match the updated rules.
        setupCarrierPrivilegesTrackerWithCarrierConfigUids();

        // Package 1 keeps its privileges by matching the first rule; the second rule no longer
        // matches package 2.
        setupCarrierConfigRules(
                carrierConfigRuleString(getHash(CERT_1), PACKAGE_1),
                carrierConfigRuleString(getHash(CERT_2), PACKAGE_1));

        sendCarrierConfigChangedIntent(SUB_ID, PHONE_ID);
        mTestableLooper.processAllMessages();

        verifyPrivilegedUids(new int[] {UID_1} /* expectedUids */, 1 /* expectedUidUpdates */);

        // Give package 2 privileges again.
        setupCarrierConfigRules(
                carrierConfigRuleString(getHash(CERT_1), PACKAGE_1),
                carrierConfigRuleString(getHash(CERT_2), PACKAGE_1, PACKAGE_2));

        sendCarrierConfigChangedIntent(SUB_ID, PHONE_ID);
        mTestableLooper.processAllMessages();

        verifyPrivilegedUids(PRIVILEGED_UIDS /* expectedUids */, 2 /* expectedUidUpdates */);
    }

    @Test
    public void testSimCardStateChanged() throws Exception {
        // Start with packages installed and no certs
@@ -326,9 +370,7 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();

        when(mTelephonyManager.getCertsFromCarrierPrivilegeAccessRules())
                .thenReturn(Arrays.asList(getHash(CERT_1), getHash(CERT_2)));
        when(mTelephonyManager.hasIccCard(PHONE_ID)).thenReturn(true);
        setupSimLoadedRules(ruleWithHashOnly(getHash(CERT_1)), ruleWithHashOnly(getHash(CERT_2)));

        sendSimCardStateChangedIntent(PHONE_ID, SIM_STATE_LOADED);
        mTestableLooper.processAllMessages();
@@ -344,9 +386,7 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();

        when(mTelephonyManager.getCertsFromCarrierPrivilegeAccessRules())
                .thenReturn(Arrays.asList(getHash(CERT_1), getHash(CERT_2)));
        when(mTelephonyManager.hasIccCard(PHONE_ID)).thenReturn(true);
        setupSimLoadedRules(ruleWithHashOnly(getHash(CERT_1)), ruleWithHashOnly(getHash(CERT_2)));

        sendSimApplicationStateChangedIntent(PHONE_ID, SIM_STATE_LOADED);
        mTestableLooper.processAllMessages();
@@ -391,10 +431,39 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        verifyPrivilegedUids(new int[0] /* expectedUids */, 1 /* expectedUidUpdates */);
    }

    @Test
    public void testSimStateChangedExplicitPackageNames() throws Exception {
        // Start with privileges specified just by wildcard certificate hashes, verify specifying
        // package names clears privileges on UIDs that don't match the updated rules.
        setupCarrierPrivilegesTrackerWithSimLoadedUids();

        // Package 1 keeps its privileges by matching the first rule; the second rule no longer
        // matches package 2.
        setupSimLoadedRules(
                ruleWithHashAndPackage(getHash(CERT_1), PACKAGE_1),
                ruleWithHashAndPackage(getHash(CERT_2), PACKAGE_1));

        sendSimCardStateChangedIntent(PHONE_ID, SIM_STATE_LOADED);
        mTestableLooper.processAllMessages();

        verifyPrivilegedUids(new int[] {UID_1} /* expectedUids */, 1 /* expectedUidUpdates */);

        // Give package 2 privileges again.
        setupSimLoadedRules(
                ruleWithHashAndPackage(getHash(CERT_1), PACKAGE_1),
                ruleWithHashAndPackage(getHash(CERT_2), PACKAGE_1),
                ruleWithHashAndPackage(getHash(CERT_2), PACKAGE_2));

        sendSimCardStateChangedIntent(PHONE_ID, SIM_STATE_LOADED);
        mTestableLooper.processAllMessages();

        verifyPrivilegedUids(PRIVILEGED_UIDS /* expectedUids */, 2 /* expectedUidUpdates */);
    }

    @Test
    public void testPackageAdded() throws Exception {
        // Start with certs and no packages installed
        setupCarrierConfigCerts(getHash(CERT_1));
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1)));
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();

        setupInstalledPackages(new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1));
@@ -408,7 +477,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    @Test
    public void testPackageAddedMultipleUsers() throws Exception {
        // Start with certs and no packages installed
        setupCarrierConfigCerts(getHash(CERT_1), getHash(CERT_2));
        setupCarrierConfigRules(
                carrierConfigRuleString(getHash(CERT_1)), carrierConfigRuleString(getHash(CERT_2)));
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();

        setupInstalledPackages(
@@ -424,7 +494,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    @Test
    public void testPackageReplaced() throws Exception {
        // Start with certs and an unmatched package
        setupCarrierConfigCerts(getHash(CERT_1), getHash(CERT_2));
        setupCarrierConfigRules(
                carrierConfigRuleString(getHash(CERT_1)), carrierConfigRuleString(getHash(CERT_2)));
        setupInstalledPackages(new PackageCertInfo(PACKAGE_1, CERT_3, USER_1, UID_1));
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();

@@ -441,7 +512,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    @Test
    public void testPackageAddedOrReplacedNoSignatures() throws Exception {
        // Start with certs and packages installed
        setupCarrierConfigCerts(getHash(CERT_1), getHash(CERT_2));
        setupCarrierConfigRules(
                carrierConfigRuleString(getHash(CERT_1)), carrierConfigRuleString(getHash(CERT_2)));
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
@@ -462,7 +534,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    @Test
    public void testPackageAddedOrReplacedSignatureChanged() throws Exception {
        // Start with certs and packages installed
        setupCarrierConfigCerts(getHash(CERT_1), getHash(CERT_2));
        setupCarrierConfigRules(
                carrierConfigRuleString(getHash(CERT_1)), carrierConfigRuleString(getHash(CERT_2)));
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
@@ -482,7 +555,8 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    @Test
    public void testPackageRemoved() throws Exception {
        // Start with certs and packages installed
        setupCarrierConfigCerts(getHash(CERT_1), getHash(CERT_2));
        setupCarrierConfigRules(
                carrierConfigRuleString(getHash(CERT_1)), carrierConfigRuleString(getHash(CERT_2)));
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
@@ -531,9 +605,7 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        mContext.sendBroadcast(new Intent(action, new Uri.Builder().path(pkgName).build()));
    }

    /**
     * Returns the SHA-1 hash (as a hex String) for the given hex String.
     */
    /** Returns the SHA-1 hash (as a hex String) for the given hex String. */
    private static String getHash(String hexString) throws Exception {
        MessageDigest sha1 = MessageDigest.getInstance(SHA_1);
        byte[] result = sha1.digest(IccUtils.hexStringToBytes(hexString));