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

Commit 9879101d authored by Benedict Wong's avatar Benedict Wong
Browse files

Add ability to override carrier service package

This change introduces a Carrier Service Package override, requiring
MODIFY_PHONE_STATE, ensuring that CTS can export a CarrierService, and
set itself as the carrier service.

The requirement for the application to also be carrier-privileged still
stands, but omits the SIM-certificate-match requirement, instead
allowing carrierConfig based certificates + carrier service package
override as a sufficient gate (which critically need to both be doable
with the CTS Shell permission identity)

Bug: 266904760
Test: Manually tested with a demo CTS build, will be used for Core
      Networking CTS tests
Change-Id: Idcaaff8c9c3ed67b93bc23237de841219a5be7d7
Merged-In: Idcaaff8c9c3ed67b93bc23237de841219a5be7d7
(cherry picked from commit 7d9c790f)
parent a8e12b27
Loading
Loading
Loading
Loading
+48 −1
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ public class CarrierPrivilegesTracker extends Handler {
    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
    /**
@@ -166,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;
@@ -184,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
@@ -397,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;
@@ -697,6 +712,7 @@ public class CarrierPrivilegesTracker extends Handler {
            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:
@@ -738,7 +754,9 @@ public class CarrierPrivilegesTracker extends Handler {
                }
                for (UiccAccessRule rule : mCarrierConfigRules) {
                    if (rule.matches(cert, pkgName)) {
                        return PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG;
                        return pkgName.equals(mTestOverrideCarrierServicePackage)
                                ? PACKAGE_PRIVILEGED_FROM_CARRIER_SERVICE_TEST_OVERRIDE
                                : PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG;
                    }
                }
            }
@@ -823,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;
@@ -991,6 +1033,11 @@ public class CarrierPrivilegesTracker extends Handler {
        String carrierServicePackageName = null;
        for (ResolveInfo resolveInfo : carrierServiceResolveInfos) {
            String packageName = getPackageName(resolveInfo);
            if (mTestOverrideCarrierServicePackage != null
                    && !mTestOverrideCarrierServicePackage.equals(packageName)) {
                continue;
            }

            if (simPrivilegedPackages.contains(packageName)) {
                carrierServicePackageName = packageName;
                break;
+84 −0
Original line number Diff line number Diff line
@@ -1024,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);