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

Commit efbc3472 authored by Miriam Polzer's avatar Miriam Polzer
Browse files

Unsuspend apps for affected user correctly

When unsuspending apps for a single user, the call was made unsuspend
apps for user 0 even when the original intent was to unsuspend apps for
user 10. Keep the target user a bit longer, and pass suspending and
target user correctly to the unsuspend call.

This caused couple of test failures on HSUM because the respective test
left all personal apps suspended, causing weird failures in subsequent
tests.

Bug: 384826303
Test: btest android.devicepolicy.cts.DeviceManagementCoexistenceTest
Test: atest SuspendPackageHelperTest
Test: atest CtsSuspendAppsTestCases
Test: atest ActivityStartInterceptorTest
Test: atest PackageManagerSettingsTests
Test: atest PackageUserStateTest
Flag: EXEMPT BUG_FIX
Change-Id: I7eb757363dee14f4cfc7c6798697cfc4ccb5a87e
parent 7d96d0a4
Loading
Loading
Loading
Loading
+11 −10
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
import static android.content.pm.PackageManager.DELETE_SUCCEEDED;
import static android.content.pm.PackageManager.MATCH_KNOWN_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.UserHandle.USER_ALL;

import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
@@ -122,7 +123,7 @@ final class DeletePackageHelper {
        final boolean res;

        final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
                ? UserHandle.USER_ALL : userId;
                ? USER_ALL : userId;

        final PackageSetting uninstalledPs;
        final PackageSetting disabledSystemPs;
@@ -183,7 +184,7 @@ final class DeletePackageHelper {
                if (libraryInfo != null) {
                    boolean flagSdkLibIndependence = Flags.sdkLibIndependence();
                    for (int currUserId : allUsers) {
                        if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) {
                        if (removeUser != USER_ALL && removeUser != currUserId) {
                            continue;
                        }
                        var libClientPackagesPair = computer.getPackagesUsingSharedLibrary(
@@ -227,7 +228,7 @@ final class DeletePackageHelper {
                    && ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
                // We're downgrading a system app, which will apply to all users, so
                // freeze them all during the downgrade
                freezeUser = UserHandle.USER_ALL;
                freezeUser = USER_ALL;
                priorUserStates = new SparseArray<>();
                for (int i = 0; i < allUsers.length; i++) {
                    PackageUserState userState = uninstalledPs.readUserState(allUsers[i]);
@@ -421,7 +422,7 @@ final class DeletePackageHelper {
        if (PackageManagerServiceUtils.isSystemApp(ps)) {
            final boolean deleteSystem = (flags & PackageManager.DELETE_SYSTEM_APP) != 0;
            final boolean deleteAllUsers =
                    user == null || user.getIdentifier() == UserHandle.USER_ALL;
                    user == null || user.getIdentifier() == USER_ALL;
            if ((!deleteSystem || deleteAllUsers) && disabledPs == null) {
                Slog.w(TAG, "Attempt to delete unknown system package "
                        + ps.getPkg().getPackageName());
@@ -464,9 +465,9 @@ final class DeletePackageHelper {
                    Manifest.permission.SUSPEND_APPS, packageName, userId) == PERMISSION_GRANTED);
        }

        final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
        final int userId = user == null ? USER_ALL : user.getIdentifier();
        // Remember which users are affected, before the installed states are modified
        outInfo.mRemovedUsers = userId == UserHandle.USER_ALL
        outInfo.mRemovedUsers = userId == USER_ALL
                ? ps.queryUsersInstalledOrHasData(allUserHandles)
                : new int[]{userId};
        outInfo.populateBroadcastUsers(ps);
@@ -479,7 +480,7 @@ final class DeletePackageHelper {
        outInfo.mRemovedPackageVersionCode = ps.getVersionCode();

        if ((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)
                && userId != UserHandle.USER_ALL) {
                && userId != USER_ALL) {
            // The caller is asking that the package only be deleted for a single
            // user.  To do this, we just mark its uninstalled state and delete
            // its data. If this is a system app, we only allow this to happen if
@@ -552,7 +553,7 @@ final class DeletePackageHelper {
        for (final int affectedUserId : outInfo.mRemovedUsers) {
            if (hadSuspendAppsPermission.get(affectedUserId)) {
                mPm.unsuspendForSuspendingPackage(snapshot, packageName,
                        affectedUserId /*suspendingUserId*/, true /*inAllUsers*/);
                        affectedUserId /*suspendingUserId*/, USER_ALL);
                mPm.removeAllDistractingPackageRestrictions(snapshot, affectedUserId);
            }
        }
@@ -590,7 +591,7 @@ final class DeletePackageHelper {

    @GuardedBy("mPm.mLock")
    private void markPackageUninstalledForUserLPw(PackageSetting ps, UserHandle user, int flags) {
        final int[] userIds = (user == null || user.getIdentifier() == UserHandle.USER_ALL)
        final int[] userIds = (user == null || user.getIdentifier() == USER_ALL)
                ? mUserManagerInternal.getUserIds()
                : new int[] {user.getIdentifier()};
        for (int nextUserId : userIds) {
@@ -687,7 +688,7 @@ final class DeletePackageHelper {
            flags |= PackageManager.DELETE_KEEP_DATA;
        }
        try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
            deleteInstalledPackageLIF(deletedPs, UserHandle.USER_ALL, true, flags, allUserHandles,
            deleteInstalledPackageLIF(deletedPs, USER_ALL, true, flags, allUserHandles,
                    outInfo, writeSettings);
        }
    }
+1 −1
Original line number Diff line number Diff line
@@ -689,7 +689,7 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal {
        final int suspendingUserId =
                crossUserSuspensionEnabledRo() ? UserHandle.USER_SYSTEM : affectedUser;
        mService.unsuspendForSuspendingPackage(
                snapshot(), PLATFORM_PACKAGE_NAME, suspendingUserId, /* inAllUsers= */ false);
                snapshot(), PLATFORM_PACKAGE_NAME, suspendingUserId, affectedUser);
    }

    @Override
+25 −23
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET;
import static android.crashrecovery.flags.Flags.refactorCrashrecovery;
import static android.os.Process.INVALID_UID;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.UserHandle.USER_ALL;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
@@ -1587,13 +1588,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService
    }

    void scheduleWritePackageRestrictions(UserHandle user) {
        final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
        final int userId = user == null ? USER_ALL : user.getIdentifier();
        scheduleWritePackageRestrictions(userId);
    }

    void scheduleWritePackageRestrictions(@CanBeALL @UserIdInt int userId) {
        invalidatePackageInfoCache();
        if (userId == UserHandle.USER_ALL) {
        if (userId == USER_ALL) {
            synchronized (mDirtyUsers) {
                for (int aUserId : mUserManager.getUserIds()) {
                    mDirtyUsers.add(aUserId);
@@ -1806,7 +1807,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
    private void installAllowlistedSystemPackages() {
        if (mUserManager.installWhitelistedSystemPackages(isFirstBoot(), isDeviceUpgrading(),
                mExistingPackages)) {
            scheduleWritePackageRestrictions(UserHandle.USER_ALL);
            scheduleWritePackageRestrictions(USER_ALL);
            scheduleWriteSettings();
        }
    }
@@ -2393,7 +2394,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                    final PackageSetting ps = packageSettings.valueAt(i);
                    if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.getVolumeUuid())) {
                        // No apps are running this early, so no need to freeze
                        mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL,
                        mAppDataHelper.clearAppDataLIF(ps.getPkg(), USER_ALL,
                                FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                                        | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
                                        | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
@@ -3076,7 +3077,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService

    @NonNull
    int[] resolveUserIds(@CanBeALL @UserIdInt int userId) {
        return (userId == UserHandle.USER_ALL) ? mUserManager.getUserIds() : new int[] { userId };
        return (userId == USER_ALL) ? mUserManager.getUserIds() : new int[]{userId};
    }

    private void setUpInstantAppInstallerActivityLP(ActivityInfo installerActivity) {
@@ -3109,7 +3110,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
    }

    void killApplication(String pkgName, @AppIdInt int appId, String reason, int exitInfoReason) {
        killApplication(pkgName, appId, UserHandle.USER_ALL, reason, exitInfoReason);
        killApplication(pkgName, appId, USER_ALL, reason, exitInfoReason);
    }

    void killApplication(String pkgName, @AppIdInt int appId,
@@ -3229,23 +3230,24 @@ public class PackageManagerService implements PackageSender, TestUtilityService
    }

    /**
     * @param inAllUsers Whether to unsuspend packages suspended by the given package in other
     *                   users. This flag is only used when cross-user suspension is enabled.
     * @param suspendingUserId The user that has suspended apps using the suspending package.
     * @param targetUserId The user whose apps should be unsuspended. Pass {@code USER_ALL} to
     *                     unsuspend for all users.
     */
    void unsuspendForSuspendingPackage(@NonNull Computer computer, String suspendingPackage,
            @UserIdInt int suspendingUserId, boolean inAllUsers) {
            @UserIdInt int suspendingUserId, @CanBeALL @UserIdInt int targetUserId) {
        // TODO: This can be replaced by a special parameter to iterate all packages, rather than
        //  this weird pre-collect of all packages.
        final String[] allPackages = computer.getPackageStates().keySet().toArray(new String[0]);
        final Predicate<UserPackage> suspenderPredicate =
                UserPackage.of(suspendingUserId, suspendingPackage)::equals;
        if (!crossUserSuspensionEnabledRo() || !inAllUsers) {
        if (!crossUserSuspensionEnabledRo() || targetUserId != USER_ALL) {
            mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(computer,
                    allPackages, suspenderPredicate, suspendingUserId);
                    allPackages, suspenderPredicate, targetUserId);
        } else {
            for (int targetUserId: mUserManager.getUserIds()) {
            for (int user : mUserManager.getUserIds()) {
                mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(
                        computer, allPackages, suspenderPredicate, targetUserId);
                        computer, allPackages, suspenderPredicate, user);
            }
        }
    }
@@ -3382,7 +3384,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                && !snapshot.isCallerSameApp(packageName, callingUid)) {
            return false;
        }
        return isPackageDeviceAdmin(packageName, UserHandle.USER_ALL);
        return isPackageDeviceAdmin(packageName, USER_ALL);
    }

    // TODO(b/261957226): centralise this logic in DPM
@@ -3406,7 +3408,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                // Does it contain a device admin for any user?
                int[] allUsers = mUserManager.getUserIds();
                int[] targetUsers;
                if (userId == UserHandle.USER_ALL) {
                if (userId == USER_ALL) {
                    targetUsers = allUsers;
                } else {
                    targetUsers = new int[]{userId};
@@ -4153,7 +4155,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                // This app should not generally be allowed to get disabled by the UI, but
                // if it ever does, we don't want to end up with some of the user's apps
                // permanently suspended.
                unsuspendForSuspendingPackage(computer, packageName, userId, true /* inAllUsers */);
                unsuspendForSuspendingPackage(computer, packageName, userId, USER_ALL);
                removeAllDistractingPackageRestrictions(computer, userId);
            }
            success = true;
@@ -4244,9 +4246,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService
        };
        mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
                        .getUriFor(Global.ENABLE_EPHEMERAL_FEATURE),
                false, co, UserHandle.USER_ALL);
                false, co, USER_ALL);
        mContext.getContentResolver().registerContentObserver(android.provider.Settings.Secure
                .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_ALL);
                .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, USER_ALL);
        co.onChange(true);

        mAppsFilter.onSystemReady(LocalServices.getService(PackageManagerInternal.class));
@@ -4774,7 +4776,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
            final Computer snapshot = snapshotComputer();
            final AndroidPackage pkg = snapshot.getPackage(packageName);
            try (PackageFreezer ignored =
                            freezePackage(packageName, UserHandle.USER_ALL,
                            freezePackage(packageName, USER_ALL,
                                    "clearApplicationProfileData",
                                    ApplicationExitInfo.REASON_OTHER, null /* request */)) {
                try (PackageManagerTracedLock installLock = mInstallLock.acquireLock()) {
@@ -4820,7 +4822,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                public void run() {
                    mHandler.removeCallbacks(this);
                    final boolean succeeded;
                    try (PackageFreezer freezer = freezePackage(packageName, UserHandle.USER_ALL,
                    try (PackageFreezer freezer = freezePackage(packageName, USER_ALL,
                            "clearApplicationUserData",
                            ApplicationExitInfo.REASON_USER_REQUESTED, null /* request */,
                            /* waitAppKilled= */ true)) {
@@ -4847,7 +4849,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                                == PERMISSION_GRANTED) {
                            final Computer snapshot = snapshotComputer();
                            unsuspendForSuspendingPackage(
                                    snapshot, packageName, userId, true /* inAllUsers */);
                                    snapshot, packageName, userId, USER_ALL);
                            removeAllDistractingPackageRestrictions(snapshot, userId);
                            synchronized (mLock) {
                                flushPackageRestrictionsAsUserInternalLocked(userId);
@@ -6372,13 +6374,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService
            if (mComponentResolver.updateMimeGroup(snapshotComputer(), packageName, mimeGroup)) {
                Binder.withCleanCallingIdentity(() -> {
                    mPreferredActivityHelper.clearPackagePreferredActivities(packageName,
                            UserHandle.USER_ALL);
                            USER_ALL);
                    // Send the ACTION_PACKAGE_CHANGED when the mimeGroup has changes
                    final Computer snapShot = snapshotComputer();
                    final ArrayList<String> components = new ArrayList<>(
                            Collections.singletonList(packageName));
                    final int appId = packageState.getAppId();
                    final int[] userIds = resolveUserIds(UserHandle.USER_ALL);
                    final int[] userIds = resolveUserIds(USER_ALL);
                    final String reason = "The mimeGroup is changed";
                    for (int i = 0; i < userIds.length; i++) {
                        final PackageUserStateInternal pkgUserState =