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

Commit 34666400 authored by Rambo Wang's avatar Rambo Wang
Browse files

Refresh carrier service state when carrier app is en/disabled

CarrierPrivilegesTracker will monitor package en/disabling
and update the carrier service accordingly. This will remove
the burden from downstream components who can reliably
get the carrier service change through CarrierPrivilegesCallback.

When carrier package is disabled by user or when in rare case
when we receive package changed but package does not exist
(e.g. a race occurred with package removed), treat it as the
same as package has been removed by cleaning up the cache.

Bug: 200277555
Test: atest CarrierPrivilegesTrackerTest
Test: atest android.appsecurity.cts.PkgInstallSignatureVerificationTest
Merged-In: Ia57a2d8aca5fff8a0041008e54e3b30a51801472
Change-Id: Ia57a2d8aca5fff8a0041008e54e3b30a51801472
(cherry picked from commit 31ddd73d)
parent caecb9fb
Loading
Loading
Loading
Loading
+37 −20
Original line number Diff line number Diff line
@@ -139,16 +139,17 @@ public class CarrierPrivilegesTracker extends Handler {
    private static final int ACTION_SIM_STATE_UPDATED = 4;

    /**
     * Action for tracking when a package is installed or replaced on the device.
     * obj: String package name that was installed or replaced on the device.
     * Action for tracking when a package is installed, replaced or changed (exclude the case
     * disabled by user) on the device.
     * obj: String package name that was installed, replaced or changed on the device.
     */
    private static final int ACTION_PACKAGE_ADDED_OR_REPLACED = 5;
    private static final int ACTION_PACKAGE_ADDED_REPLACED_OR_CHANGED = 5;

    /**
     * Action for tracking when a package is uninstalled on the device.
     * obj: String package name that was installed on the device.
     * Action for tracking when a package is uninstalled or disabled by user on the device.
     * obj: String package name that was installed or disabled by user on the device.
     */
    private static final int ACTION_PACKAGE_REMOVED = 6;
    private static final int ACTION_PACKAGE_REMOVED_OR_DISABLED_BY_USER = 6;

    /**
     * Action used to initialize the state of the Tracker.
@@ -306,11 +307,8 @@ public class CarrierPrivilegesTracker extends Handler {
                        }
                        case Intent.ACTION_PACKAGE_ADDED: // fall through
                        case Intent.ACTION_PACKAGE_REPLACED: // fall through
                        case Intent.ACTION_PACKAGE_REMOVED: {
                            int what =
                                    (action.equals(Intent.ACTION_PACKAGE_REMOVED))
                                            ? ACTION_PACKAGE_REMOVED
                                            : ACTION_PACKAGE_ADDED_OR_REPLACED;
                        case Intent.ACTION_PACKAGE_REMOVED: // fall through
                        case Intent.ACTION_PACKAGE_CHANGED: {
                            Uri uri = intent.getData();
                            String pkgName = (uri != null) ? uri.getSchemeSpecificPart() : null;
                            if (TextUtils.isEmpty(pkgName)) {
@@ -318,6 +316,24 @@ public class CarrierPrivilegesTracker extends Handler {
                                return;
                            }

                            boolean removed = action.equals(Intent.ACTION_PACKAGE_REMOVED);
                            boolean disabledByUser = false;
                            boolean notExist = false;
                            try {
                                disabledByUser = action.equals(Intent.ACTION_PACKAGE_CHANGED)
                                        && mPackageManager.getApplicationEnabledSetting(pkgName)
                                        == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
                            } catch (IllegalArgumentException iae) {
                                // Very rare case when package changed race with package removed
                                Rlog.w(TAG, "Package does not exist: " + pkgName);
                                notExist = true;
                            }
                            // When a package is explicitly disabled by the user or does not exist,
                            // treat them as if it was removed: clear it from the cache
                            int what = (removed || disabledByUser || notExist)
                                    ? ACTION_PACKAGE_REMOVED_OR_DISABLED_BY_USER
                                    : ACTION_PACKAGE_ADDED_REPLACED_OR_CHANGED;

                            sendMessage(obtainMessage(what, pkgName));
                            break;
                        }
@@ -349,6 +365,7 @@ public class CarrierPrivilegesTracker extends Handler {
        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        packageFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);

        // For package-related broadcasts, specify the data scheme for "package" to receive the
        // package name along with the broadcast
@@ -379,14 +396,14 @@ public class CarrierPrivilegesTracker extends Handler {
                handleSimStateChanged(msg.arg1, msg.arg2);
                break;
            }
            case ACTION_PACKAGE_ADDED_OR_REPLACED: {
            case ACTION_PACKAGE_ADDED_REPLACED_OR_CHANGED: {
                String pkgName = (String) msg.obj;
                handlePackageAddedOrReplaced(pkgName);
                handlePackageAddedReplacedOrChanged(pkgName);
                break;
            }
            case ACTION_PACKAGE_REMOVED: {
            case ACTION_PACKAGE_REMOVED_OR_DISABLED_BY_USER: {
                String pkgName = (String) msg.obj;
                handlePackageRemoved(pkgName);
                handlePackageRemovedOrDisabledByUser(pkgName);
                break;
            }
            case ACTION_INITIALIZE_TRACKER: {
@@ -530,7 +547,7 @@ public class CarrierPrivilegesTracker extends Handler {
        return uiccProfile.getCarrierPrivilegeAccessRules();
    }

    private void handlePackageAddedOrReplaced(@Nullable String pkgName) {
    private void handlePackageAddedReplacedOrChanged(@Nullable String pkgName) {
        if (pkgName == null) return;

        PackageInfo pkg;
@@ -546,7 +563,7 @@ public class CarrierPrivilegesTracker extends Handler {
        // installed for a user it wasn't installed in before, which means there will be an
        // additional UID.
        getUidsForPackage(pkg.packageName, /* invalidateCache= */ true);
        mLocalLog.log("Package added/replaced:"
        mLocalLog.log("Package added/replaced/changed:"
                + " pkg=" + Rlog.pii(TAG, pkgName)
                + " cert hashes=" + mInstalledPackageCerts.get(pkgName));

@@ -567,15 +584,15 @@ public class CarrierPrivilegesTracker extends Handler {
        mInstalledPackageCerts.put(pkg.packageName, certs);
    }

    private void handlePackageRemoved(@Nullable String pkgName) {
    private void handlePackageRemovedOrDisabledByUser(@Nullable String pkgName) {
        if (pkgName == null) return;

        if (mInstalledPackageCerts.remove(pkgName) == null || mCachedUids.remove(pkgName) == null) {
            Rlog.e(TAG, "Unknown package was uninstalled: " + pkgName);
            Rlog.e(TAG, "Unknown package was uninstalled or disabled by user: " + pkgName);
            return;
        }

        mLocalLog.log("Package removed: pkg=" + Rlog.pii(TAG, pkgName));
        mLocalLog.log("Package removed or disabled by user: pkg=" + Rlog.pii(TAG, pkgName));

        maybeUpdatePrivilegedPackagesAndNotifyRegistrants();
    }
+57 −0
Original line number Diff line number Diff line
@@ -313,6 +313,22 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        }
    }

    private void verifyCarrierServicesChangedUpdates(List<Pair<String, Integer>> expectedUpdates) {
        if (expectedUpdates.isEmpty()) {
            verify(mTelephonyRegistryManager, never())
                    .notifyCarrierPrivilegesChanged(anyInt(), any(), any());
        } else {
            InOrder inOrder = inOrder(mTelephonyRegistryManager);
            for (Pair<String, Integer> expectedUpdate : expectedUpdates) {
                // By looking at TelephonyRegistryManager, we can see the full flow as
                // it evolves.
                inOrder.verify(mTelephonyRegistryManager)
                        .notifyCarrierServiceChanged(
                                eq(PHONE_ID), eq(expectedUpdate.first), eq(expectedUpdate.second));
            }
        }
    }

    @Test
    public void testRegisterListener() throws Exception {
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
@@ -867,6 +883,47 @@ public class CarrierPrivilegesTrackerTest extends TelephonyTest {
        verifyCarrierPrivilegesChangedUpdates(List.of());
    }

    @Test
    public void testPackageDisabledAndThenEnabled() throws Exception {
        // Start with certs and packages installed
        setupCarrierConfigRules(carrierConfigRuleString(getHash(CERT_1)));
        setupInstalledPackages(
                new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
                new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
        when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
        when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
        ResolveInfo resolveInfoPkg1 = new ResolveInfoBuilder().setService(PACKAGE_1).build();
        doReturn(List.of(resolveInfoPkg1))
                .when(mPackageManager)
                .queryIntentServices(any(), anyInt());
        mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();

        // Package_1 is disabled
        when(mPackageManager.getApplicationEnabledSetting(eq(PACKAGE_1))).thenReturn(
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
        doReturn(List.of()).when(
                mPackageManager).queryIntentServices(any(), anyInt());
        sendPackageChangedIntent(Intent.ACTION_PACKAGE_CHANGED, PACKAGE_1);
        mTestableLooper.processAllMessages();

        verifyCurrentState(Set.of(), new int[0]);
        verifyCarrierPrivilegesChangedUpdates(List.of(new Pair<>(Set.of(), Set.of())));
        verifyCarrierServicesChangedUpdates(List.of(new Pair<>(null, -1)));

        // Package_1 is re-enabled
        when(mPackageManager.getApplicationEnabledSetting(eq(PACKAGE_1))).thenReturn(
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
        doReturn(List.of(resolveInfoPkg1)).when(
                mPackageManager).queryIntentServices(any(), anyInt());
        sendPackageChangedIntent(Intent.ACTION_PACKAGE_CHANGED, PACKAGE_1);
        mTestableLooper.processAllMessages();

        verifyCurrentState(Set.of(PACKAGE_1), new int[] {UID_1});
        verifyCarrierPrivilegesChangedUpdates(
                List.of(new Pair<>(Set.of(PACKAGE_1), Set.of(UID_1))));
        verifyCarrierServicesChangedUpdates(List.of(new Pair<>(PACKAGE_1, UID_1)));
    }

    @Test
    public void testSetCarrierTestOverrideWithEmptyRule() throws Exception {
        // Start with PACKAGE_1 & PACKAGE_2 installed and have privileges from CarrierConfig