diff options
| author | 2024-01-04 21:35:37 +0000 | |
|---|---|---|
| committer | 2024-01-04 21:35:37 +0000 | |
| commit | 77e00b7e8f033a2ba372b5b5b9facf038380662f (patch) | |
| tree | f88719476a747bbf021a665ab6622f12d14a0fee | |
| parent | 7c60604a02949d00605f7fe6494df14342883e16 (diff) | |
| parent | 291365de73d8c5fa054d2fb9fce8e4035a733708 (diff) | |
Merge "[pm] fix corner cases of DELETE_KEEP_USER with multi-user" into main
3 files changed, 48 insertions, 13 deletions
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java index c920ca89b75e..588c6291f2f1 100644 --- a/services/core/java/com/android/server/pm/DeletePackageHelper.java +++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java @@ -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); } } diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 02ce15922272..45fc49a2e855 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -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; } diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java index 285445361a29..02e28ddf24c7 100644 --- a/services/core/java/com/android/server/pm/RemovePackageHelper.java +++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java @@ -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) { |