summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Song Chun Fan <schfan@google.com> 2024-01-04 21:35:37 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-01-04 21:35:37 +0000
commit77e00b7e8f033a2ba372b5b5b9facf038380662f (patch)
treef88719476a747bbf021a665ab6622f12d14a0fee
parent7c60604a02949d00605f7fe6494df14342883e16 (diff)
parent291365de73d8c5fa054d2fb9fce8e4035a733708 (diff)
Merge "[pm] fix corner cases of DELETE_KEEP_USER with multi-user" into main
-rw-r--r--services/core/java/com/android/server/pm/DeletePackageHelper.java12
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java12
-rw-r--r--services/core/java/com/android/server/pm/RemovePackageHelper.java37
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) {