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

Commit 77e00b7e authored by Song Chun Fan's avatar Song Chun Fan Committed by Android (Google) Code Review
Browse files

Merge "[pm] fix corner cases of DELETE_KEEP_USER with multi-user" into main

parents 7c60604a 291365de
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -487,7 +487,7 @@ final class DeletePackageHelper {
                    // Do not uninstall the APK if an app should be cached
                    boolean keepUninstalledPackage =
                            mPm.shouldKeepUninstalledPackageLPr(packageName);
                    if (ps.isInstalledOrHasDataOnAnyOtherUser(
                    if (ps.isInstalledOnAnyOtherUser(
                            mUserManagerInternal.getUserIds(), userId) || keepUninstalledPackage) {
                        // Other users still have this package installed, so all
                        // we need to do is clear this user's data and save that
@@ -533,7 +533,7 @@ final class DeletePackageHelper {
                // artifacts are not stored in the same directory as the APKs
                deleteArtDexoptArtifacts(packageName);
            }
            deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles,
            deleteInstalledPackageLIF(ps, userId, deleteCodeAndResources, flags, allUserHandles,
                    outInfo, writeSettings);
        }

@@ -554,7 +554,7 @@ final class DeletePackageHelper {
    }

    @GuardedBy("mPm.mInstallLock")
    private void deleteInstalledPackageLIF(PackageSetting ps,
    private void deleteInstalledPackageLIF(PackageSetting ps, int userId,
            boolean deleteCodeAndResources, int flags, @NonNull int[] allUserHandles,
            @NonNull PackageRemovedInfo outInfo, boolean writeSettings) {
        synchronized (mPm.mLock) {
@@ -567,7 +567,7 @@ final class DeletePackageHelper {

        // Delete package data from internal structures and also remove data if flag is set
        mRemovePackageHelper.removePackageDataLIF(
                ps, allUserHandles, outInfo, flags, writeSettings);
                ps, userId, allUserHandles, outInfo, flags, writeSettings);

        // Delete application code and resources only for parent packages
        if (deleteCodeAndResources) {
@@ -677,8 +677,8 @@ final class DeletePackageHelper {
            flags |= PackageManager.DELETE_KEEP_DATA;
        }
        synchronized (mPm.mInstallLock) {
            deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles, outInfo,
                    writeSettings);
            deleteInstalledPackageLIF(deletedPs, UserHandle.USER_ALL, true, flags, allUserHandles,
                    outInfo, writeSettings);
        }
    }

+11 −1
Original line number Diff line number Diff line
@@ -825,7 +825,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
        return changed;
    }

    boolean isInstalledOrHasDataOnAnyOtherUser(int[] allUsers, int currentUser) {
    boolean isInstalledOnAnyOtherUser(int[] allUsers, int currentUser) {
        for (int user: allUsers) {
            if (user == currentUser) {
                continue;
@@ -834,6 +834,16 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
            if (userState.isInstalled()) {
                return true;
            }
        }
        return false;
    }

    boolean hasDataOnAnyOtherUser(int[] allUsers, int currentUser) {
        for (int user: allUsers) {
            if (user == currentUser) {
                continue;
            }
            final PackageUserStateInternal userState = readUserState(user);
            if (userState.dataExists()) {
                return true;
            }
+31 −6
Original line number Diff line number Diff line
@@ -355,16 +355,22 @@ final class RemovePackageHelper {
    // Called to clean up disabled system packages
    public void removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles) {
        synchronized (mPm.mInstallLock) {
            removePackageDataLIF(deletedPs, allUserHandles, new PackageRemovedInfo(),
                    /* flags= */ 0, /* writeSettings= */ false);
            removePackageDataLIF(deletedPs, UserHandle.USER_ALL, allUserHandles,
                    new PackageRemovedInfo(), /* flags= */ 0, /* writeSettings= */ false);
        }
    }

    /*
    /**
     * This method deletes the package from internal data structures such as mPackages / mSettings.
     *
     * @param targetUserId indicates the target user of the deletion. It equals to
     *                     {@link UserHandle.USER_ALL} if the deletion was initiated for all users,
     *                     otherwise it equals to the specific user id that the deletion was meant
     *                     for.
     */
    @GuardedBy("mPm.mInstallLock")
    public void removePackageDataLIF(final PackageSetting deletedPs, @NonNull int[] allUserHandles,
    public void removePackageDataLIF(final PackageSetting deletedPs, int targetUserId,
            @NonNull int[] allUserHandles,
            @NonNull PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
        String packageName = deletedPs.getPackageName();
        if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + deletedPs);
@@ -372,7 +378,7 @@ final class RemovePackageHelper {
        final AndroidPackage deletedPkg = deletedPs.getPkg();

        // Delete all the data and states related to this package.
        clearPackageStateForUserLIF(deletedPs, UserHandle.USER_ALL, flags);
        clearPackageStateForUserLIF(deletedPs, targetUserId, flags);

        // Delete from mPackages
        removePackageLI(packageName, (flags & PackageManager.DELETE_CHATTY) != 0);
@@ -384,7 +390,7 @@ final class RemovePackageHelper {
            deletedPs.setPkg(null);
        }

        if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
        if (shouldDeletePackageSetting(deletedPs, targetUserId, allUserHandles, flags)) {
            // Delete from mSettings
            final SparseBooleanArray changedUsers = new SparseBooleanArray();
            synchronized (mPm.mLock) {
@@ -457,6 +463,25 @@ final class RemovePackageHelper {
        }
    }

    private static boolean shouldDeletePackageSetting(PackageSetting deletedPs, int userId,
                                                      int[] allUserHandles, int flags) {
        if ((flags & PackageManager.DELETE_KEEP_DATA) != 0) {
            return false;
        }
        if (userId == UserHandle.USER_ALL) {
            // Deleting for ALL. Let's wipe the PackageSetting.
            return true;
        }
        if (deletedPs.hasDataOnAnyOtherUser(allUserHandles, userId)) {
            // We arrived here because we are uninstalling the package for a specified user, and the
            // package isn't installed on any other user. Before we proceed to completely delete the
            // PackageSetting from mSettings, let's first check if data exists on any other user.
            // If so, do not wipe the PackageSetting.
            return false;
        }
        return true;
    }

    void cleanUpResources(@Nullable String packageName, @Nullable File codeFile,
                          @Nullable String[] instructionSets) {
        synchronized (mPm.mInstallLock) {