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

Commit 1230bdf6 authored by Benedict Wong's avatar Benedict Wong Committed by Android (Google) Code Review
Browse files

Merge changes from topic "carrier-service-override-udc-dev" into udc-dev

* changes:
  Add ability to override carrier service package
  Only use SIM certificates for determining Carrier Provisioning package
parents 381dccc7 9879101d
Loading
Loading
Loading
Loading
+79 −16
Original line number Diff line number Diff line
@@ -101,6 +101,11 @@ public class CarrierPrivilegesTracker extends Handler {
    private static final String SHA_1 = "SHA-1";
    private static final String SHA_256 = "SHA-256";

    private static final int PACKAGE_NOT_PRIVILEGED = 0;
    private static final int PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG = 1;
    private static final int PACKAGE_PRIVILEGED_FROM_SIM = 2;
    private static final int PACKAGE_PRIVILEGED_FROM_CARRIER_SERVICE_TEST_OVERRIDE = 3;

    // TODO(b/232273884): Turn feature on when find solution to handle the inter-carriers switching
    /**
     * Time delay to clear UICC rules after UICC is gone.
@@ -162,6 +167,14 @@ public class CarrierPrivilegesTracker extends Handler {
     */
    private static final int ACTION_UICC_ACCESS_RULES_LOADED = 10;

    /**
     * Action to set the test override rule through {@link
     * TelephonyManager#setCarrierServicePackageOverride}.
     *
     * <p>obj: String of the carrierServicePackage from method setCarrierServicePackageOverride.
     */
    private static final int ACTION_SET_TEST_OVERRIDE_CARRIER_SERVICE_PACKAGE = 11;

    private final Context mContext;
    private final Phone mPhone;
    private final PackageManager mPackageManager;
@@ -180,6 +193,7 @@ public class CarrierPrivilegesTracker extends Handler {
    // - Empty list indicates test override to simulate no rules (CC and UICC rules are ignored)
    // - Non-empty list indicates test override with specific rules (CC and UICC rules are ignored)
    @Nullable private List<UiccAccessRule> mTestOverrideRules = null;
    @Nullable private String mTestOverrideCarrierServicePackage = null;
    // Map of PackageName -> Certificate hashes for that Package
    @NonNull private final Map<String, Set<String>> mInstalledPackageCerts = new ArrayMap<>();
    // Map of PackageName -> UIDs for that Package
@@ -393,6 +407,11 @@ public class CarrierPrivilegesTracker extends Handler {
                handleUiccAccessRulesLoaded();
                break;
            }
            case ACTION_SET_TEST_OVERRIDE_CARRIER_SERVICE_PACKAGE: {
                String carrierServicePackage = (String) msg.obj;
                handleSetTestOverrideCarrierServicePackage(carrierServicePackage);
                break;
            }
            default: {
                Rlog.e(TAG, "Received unknown msg type: " + msg.what);
                break;
@@ -686,23 +705,36 @@ public class CarrierPrivilegesTracker extends Handler {

    @NonNull
    private PrivilegedPackageInfo getCurrentPrivilegedPackagesForAllUsers() {
        Set<String> carrierServiceEligiblePackages = new ArraySet<>();
        Set<String> privilegedPackageNames = new ArraySet<>();
        Set<Integer> privilegedUids = new ArraySet<>();
        for (Map.Entry<String, Set<String>> e : mInstalledPackageCerts.entrySet()) {
            if (isPackagePrivileged(e.getKey(), e.getValue())) {
            final int priv = getPackagePrivilegedStatus(e.getKey(), e.getValue());
            switch (priv) {
                case PACKAGE_PRIVILEGED_FROM_SIM:
                case PACKAGE_PRIVILEGED_FROM_CARRIER_SERVICE_TEST_OVERRIDE: // fallthrough
                    carrierServiceEligiblePackages.add(e.getKey());
                    // fallthrough
                case PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG:
                    privilegedPackageNames.add(e.getKey());
                privilegedUids.addAll(getUidsForPackage(e.getKey(), /* invalidateCache= */ false));
                    privilegedUids.addAll(
                            getUidsForPackage(e.getKey(), /* invalidateCache= */ false));
            }
        }
        return new PrivilegedPackageInfo(privilegedPackageNames, privilegedUids,
                getCarrierService(privilegedPackageNames));

        return new PrivilegedPackageInfo(
                privilegedPackageNames,
                privilegedUids,
                getCarrierService(carrierServiceEligiblePackages));
    }

    /**
     * Returns true iff there is an overlap between the provided certificate hashes and the
     * certificate hashes stored in mTestOverrideRules, mCarrierConfigRules and mUiccRules.
     * Returns the privilege status of the provided package.
     *
     * <p>Returned privilege status depends on whether a package matches the certificates from
     * carrier config, from test overrides or from certificates stored on the SIM.
     */
    private boolean isPackagePrivileged(@NonNull String pkgName, @NonNull Set<String> certs) {
    private int getPackagePrivilegedStatus(@NonNull String pkgName, @NonNull 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
@@ -711,23 +743,25 @@ public class CarrierPrivilegesTracker extends Handler {
            if (mTestOverrideRules != null) {
                for (UiccAccessRule rule : mTestOverrideRules) {
                    if (rule.matches(cert, pkgName)) {
                        return true;
                        return PACKAGE_PRIVILEGED_FROM_SIM;
                    }
                }
            } else {
                for (UiccAccessRule rule : mCarrierConfigRules) {
                for (UiccAccessRule rule : mUiccRules) {
                    if (rule.matches(cert, pkgName)) {
                        return true;
                        return PACKAGE_PRIVILEGED_FROM_SIM;
                    }
                }
                for (UiccAccessRule rule : mUiccRules) {
                for (UiccAccessRule rule : mCarrierConfigRules) {
                    if (rule.matches(cert, pkgName)) {
                        return true;
                        return pkgName.equals(mTestOverrideCarrierServicePackage)
                                ? PACKAGE_PRIVILEGED_FROM_CARRIER_SERVICE_TEST_OVERRIDE
                                : PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG;
                    }
                }
            }
        }
        return false;
        return PACKAGE_NOT_PRIVILEGED;
    }

    @NonNull
@@ -807,6 +841,30 @@ public class CarrierPrivilegesTracker extends Handler {
        sendMessage(obtainMessage(ACTION_SET_TEST_OVERRIDE_RULE, carrierPrivilegeRules));
    }

    /**
     * Override the carrier provisioning package, if it exists.
     *
     * <p>This API is to be used ONLY for testing, and requires the provided package to be carrier
     * privileged. While this override is set, ONLY the specified package will be considered
     * eligible to be bound as the carrier provisioning package, and any existing bindings will be
     * terminated.
     *
     * @param carrierServicePackage the package to be used as the overridden carrier service
     *     package, or {@code null} to reset override
     * @see TelephonyManager#setCarrierServicePackageOverride
     */
    public void setTestOverrideCarrierServicePackage(@Nullable String carrierServicePackage) {
        sendMessage(obtainMessage(
                ACTION_SET_TEST_OVERRIDE_CARRIER_SERVICE_PACKAGE, carrierServicePackage));
    }

    private void handleSetTestOverrideCarrierServicePackage(
            @Nullable String carrierServicePackage) {
        mTestOverrideCarrierServicePackage = carrierServicePackage;
        refreshInstalledPackageCache();
        maybeUpdatePrivilegedPackagesAndNotifyRegistrants();
    }

    private void handleSetTestOverrideRules(@Nullable String carrierPrivilegeRules) {
        if (carrierPrivilegeRules == null) {
            mTestOverrideRules = null;
@@ -969,13 +1027,18 @@ public class CarrierPrivilegesTracker extends Handler {
    }

    @NonNull
    private Pair<String, Integer> getCarrierService(@NonNull Set<String> privilegedPackageNames) {
    private Pair<String, Integer> getCarrierService(@NonNull Set<String> simPrivilegedPackages) {
        List<ResolveInfo> carrierServiceResolveInfos = mPackageManager.queryIntentServices(
                new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), /* flags= */ 0);
        String carrierServicePackageName = null;
        for (ResolveInfo resolveInfo : carrierServiceResolveInfos) {
            String packageName = getPackageName(resolveInfo);
            if (privilegedPackageNames.contains(packageName)) {
            if (mTestOverrideCarrierServicePackage != null
                    && !mTestOverrideCarrierServicePackage.equals(packageName)) {
                continue;
            }

            if (simPrivilegedPackages.contains(packageName)) {
                carrierServicePackageName = packageName;
                break;
            }
+104 −13
Original line number Diff line number Diff line
@@ -780,7 +780,7 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    @Test
    public void testPackageDisabledAndThenEnabled() throws Exception {
        // Start with certs and packages installed
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1)));
        setupSimLoadedRules(ruleWithHashOnly(getHash(CERT_1)));
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
@@ -919,9 +919,12 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
    }

    @Test
    public void testGetCarrierService_haveCarrierServiceWithCarrierPrivileges() throws Exception {
        // Only packages with CERT_1 have carrier privileges
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1)));
    public void testGetCarrierService_haveCarrierServiceWithSimCarrierPrivileges()
            throws Exception {
        // Package 1 has SIM loaded rules, making it eligible for carrier service bindings
        setupSimLoadedRules(ruleWithHashOnly(getHash(CERT_1)));
        // Package 2 has only carrier-config based rules, which is insufficient for carrier services
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_2)));
        // Setup all odd packages privileged, even packages not
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
@@ -948,7 +951,6 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        assertEquals(PACKAGE_1, carrierServicePackageName);
        assertEquals(UID_1, carrierServiceUid);


        reset(mPackageManager);
        // Get CS again
        carrierServicePackageName = mCarrierPrivilegesTracker.getCarrierServicePackageName();
@@ -959,27 +961,32 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        verify(mPackageManager, never()).queryIntentServices(any(), anyInt());
        assertEquals(PACKAGE_1, carrierServicePackageName);
        assertEquals(UID_1, carrierServiceUid);

    }

    @Test
    public void testGetCarrierService_haveCarrierServiceWithNoCarrierPrivileges() throws Exception {
        // Only packages with CERT_1 have carrier privileges
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1)));
    public void testGetCarrierService_haveCarrierServiceWithoutSimCarrierPrivileges()
            throws Exception {
        // Package 1 has no carrier privileges, package 2 has carrier-config based privileges, but
        // no matching certificate on the SIM.
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_2)));
        // Setup all odd packages privileged, even packages not
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2),
                new PackageCertInfo(PACKAGE_3, CERT_1, USER_1, UID_1));
        // One declared CarrierService which has no carrier privileges
        ResolveInfo noPrivilegeService = new ResolveInfoBuilder().setService(PACKAGE_2).build();
        // Two declared CarrierService, only PACKAGE_1 has carrier privileges
        ResolveInfo service1 = new ResolveInfoBuilder().setService(PACKAGE_1).build();
        ResolveInfo service2 = new ResolveInfoBuilder().setService(PACKAGE_2).build();
        // Use doReturn instead of when/thenReturn which has NPE with unknown reason
        doReturn(List.of(noPrivilegeService)).when(
                mPackageManager).queryIntentServices(any(), anyInt());
        doReturn(List.of(service1, service2))
                .when(mPackageManager)
                .queryIntentServices(any(), anyInt());
        when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
        when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
        when(mPackageManager.getPackageUid(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);

        // Verify that neither carrier service (no privileges, or carrier-config based privileges)
        // are accepted.
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
        String carrierServicePackageName = mCarrierPrivilegesTracker.getCarrierServicePackageName();
        int carrierServiceUid = mCarrierPrivilegesTracker.getCarrierServicePackageUid();
@@ -1017,6 +1024,90 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        verify(mPackageManager).queryIntentServices(any(), anyInt());
    }

    @Test
    public void testSetCarrierServiceOverride_noCarrierPrivileges() throws Exception {
        // Setup one package, without a matching cert to grant carrier privileges
        setupInstalledPackages(new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1));
        ResolveInfo carrierService = new ResolveInfoBuilder().setService(PACKAGE_1).build();

        doReturn(List.of(carrierService))
                .when(mPackageManager)
                .queryIntentServices(any(), anyInt());
        when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);

        // Set override, and verify the carrier service package was not set due to a lack of a
        // matching cert.
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
        mCarrierPrivilegesTracker.setTestOverrideCarrierServicePackage(PACKAGE_1);
        mTestableLooper.processAllMessages();

        assertNull(mCarrierPrivilegesTracker.getCarrierServicePackageName());
        assertEquals(Process.INVALID_UID, mCarrierPrivilegesTracker.getCarrierServicePackageUid());
    }

    @Test
    public void testSetCarrierServiceOverride_withCarrierConfigCarrierPrivileges()
            throws Exception {
        // Setup two packages with matching carrier config certificates
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1)));
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_1, USER_1, UID_2));
        ResolveInfo service1 = new ResolveInfoBuilder().setService(PACKAGE_1).build();
        ResolveInfo service2 = new ResolveInfoBuilder().setService(PACKAGE_2).build();

        doReturn(List.of(service1, service2))
                .when(mPackageManager)
                .queryIntentServices(any(), anyInt());
        when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
        when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);

        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();

        // Set override, and verify the carrier service package was truly set.
        mCarrierPrivilegesTracker.setTestOverrideCarrierServicePackage(PACKAGE_1);
        mTestableLooper.processAllMessages();

        assertEquals(PACKAGE_1, mCarrierPrivilegesTracker.getCarrierServicePackageName());
        assertEquals(UID_1, mCarrierPrivilegesTracker.getCarrierServicePackageUid());

        // Set other package as override, and verify the carrier service package was truly set.
        mCarrierPrivilegesTracker.setTestOverrideCarrierServicePackage(PACKAGE_2);
        mTestableLooper.processAllMessages();

        assertEquals(PACKAGE_2, mCarrierPrivilegesTracker.getCarrierServicePackageName());
        assertEquals(UID_2, mCarrierPrivilegesTracker.getCarrierServicePackageUid());

        // Clear override, and verify that everything went back to null.
        mCarrierPrivilegesTracker.setTestOverrideCarrierServicePackage(null);
        mTestableLooper.processAllMessages();

        assertNull(mCarrierPrivilegesTracker.getCarrierServicePackageName());
        assertEquals(Process.INVALID_UID, mCarrierPrivilegesTracker.getCarrierServicePackageUid());
    }

    @Test
    public void testSetCarrierServiceOverride_invalidPackage() throws Exception {
        // Setup one package, without a matching cert to grant carrier privileges
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1)));
        setupInstalledPackages(new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1));
        ResolveInfo carrierService = new ResolveInfoBuilder().setService(PACKAGE_1).build();

        doReturn(List.of(carrierService))
                .when(mPackageManager)
                .queryIntentServices(any(), anyInt());
        when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);

        // Set override, and expect that an invalid package name would not be selected as the
        // carrier config service.
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
        mCarrierPrivilegesTracker.setTestOverrideCarrierServicePackage("invalid.package");
        mTestableLooper.processAllMessages();

        assertNull(mCarrierPrivilegesTracker.getCarrierServicePackageName());
        assertEquals(Process.INVALID_UID, mCarrierPrivilegesTracker.getCarrierServicePackageUid());
    }

    private void sendCarrierConfigChanged(int subId, int phoneId) {
        mCarrierConfigChangeListener.onCarrierConfigChanged(phoneId, subId,
                TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);