diff options
4 files changed, 82 insertions, 5 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index d9b40b1..da34094 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -866,6 +866,7 @@ public final class Pm { private void runInstall() { int installFlags = PackageManager.INSTALL_ALL_USERS; + int userId = UserHandle.USER_ALL; String installerPackageName = null; String opt; @@ -909,6 +910,13 @@ public final class Pm { } } else if (opt.equals("--abi")) { abi = checkAbiArgument(nextOptionData()); + } else if (opt.equals("--user")) { + userId = Integer.parseInt(nextOptionData()); + if (userId == UserHandle.USER_ALL) { + installFlags |= PackageManager.INSTALL_ALL_USERS; + } else { + installFlags &= ~PackageManager.INSTALL_ALL_USERS; + } } else { System.err.println("Error: Unknown option: " + opt); return; @@ -953,8 +961,8 @@ public final class Pm { VerificationParams verificationParams = new VerificationParams(verificationURI, originatingURI, referrerURI, VerificationParams.NO_UID, null); - mPm.installPackage(apkFilePath, obs.getBinder(), installFlags, installerPackageName, - verificationParams, abi); + mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags, installerPackageName, + verificationParams, abi, userId); synchronized (obs) { while (!obs.finished) { diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 44478d4..bd1487c 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -198,6 +198,14 @@ interface IPackageManager { in VerificationParams verificationParams, in String packageAbiOverride); + void installPackageAsUser(in String originPath, + in IPackageInstallObserver2 observer, + int flags, + in String installerPackageName, + in VerificationParams verificationParams, + in String packageAbiOverride, + int userId); + void finishPackageInstall(int token); void setInstallerPackageName(in String targetPackage, in String installerPackageName); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 2cb9077..fbaeb37 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -7698,8 +7698,21 @@ public class PackageManagerService extends IPackageManager.Stub { public void installPackage(String originPath, IPackageInstallObserver2 observer, int installFlags, String installerPackageName, VerificationParams verificationParams, String packageAbiOverride) { + installPackageAsUser(originPath, observer, installFlags, installerPackageName, verificationParams, + packageAbiOverride, UserHandle.getCallingUserId()); + } + + @Override + public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer, + int installFlags, String installerPackageName, VerificationParams verificationParams, + String packageAbiOverride, int userId) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null); + if (UserHandle.getCallingUserId() != userId) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + "installPackage " + userId); + } final File originFile = new File(originPath); final int uid = Binder.getCallingUid(); @@ -7717,7 +7730,7 @@ public class PackageManagerService extends IPackageManager.Stub { if ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0) { user = UserHandle.ALL; } else { - user = new UserHandle(UserHandle.getUserId(uid)); + user = new UserHandle(userId); } final int filteredInstallFlags; @@ -12965,7 +12978,7 @@ public class PackageManagerService extends IPackageManager.Stub { } /** Called by UserManagerService */ - void cleanUpUserLILPw(int userHandle) { + void cleanUpUserLILPw(UserManagerService userManager, int userHandle) { mDirtyUsers.remove(userHandle); mSettings.removeUserLPw(userHandle); mPendingBroadcasts.remove(userHandle); @@ -12976,6 +12989,50 @@ public class PackageManagerService extends IPackageManager.Stub { mInstaller.removeUserDataDirs(userHandle); } mUserNeedsBadging.delete(userHandle); + removeUnusedPackagesLILPw(userManager, userHandle); + } + + /** + * We're removing userHandle and would like to remove any downloaded packages + * that are no longer in use by any other user. + * @param userHandle the user being removed + */ + private void removeUnusedPackagesLILPw(UserManagerService userManager, final int userHandle) { + final boolean DEBUG_CLEAN_APKS = false; + int [] users = userManager.getUserIdsLPr(); + Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator(); + while (psit.hasNext()) { + PackageSetting ps = psit.next(); + final String packageName = ps.pkg.packageName; + // Skip over if system app + if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) { + continue; + } + if (DEBUG_CLEAN_APKS) { + Slog.i(TAG, "Checking package " + packageName); + } + boolean keep = false; + for (int i = 0; i < users.length; i++) { + if (users[i] != userHandle && ps.getInstalled(users[i])) { + keep = true; + if (DEBUG_CLEAN_APKS) { + Slog.i(TAG, " Keeping package " + packageName + " for user " + + users[i]); + } + break; + } + } + if (!keep) { + if (DEBUG_CLEAN_APKS) { + Slog.i(TAG, " Removing package " + packageName); + } + mHandler.post(new Runnable() { + public void run() { + deletePackageX(packageName, userHandle, 0); + } //end run + }); + } + } } /** Called by UserManagerService */ diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 8ded7ca..2929939 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -293,6 +293,10 @@ public class UserManagerService extends IUserManager.Stub { private List<UserInfo> getProfilesLocked(int userId, boolean enabledOnly) { UserInfo user = getUserInfoLocked(userId); ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size()); + if (user == null) { + // Probably a dying user + return users; + } for (int i = 0; i < mUsers.size(); i++) { UserInfo profile = mUsers.valueAt(i); if (!isProfileOf(user, profile)) { @@ -1280,7 +1284,7 @@ public class UserManagerService extends IUserManager.Stub { private void removeUserStateLocked(final int userHandle) { // Cleanup package manager settings - mPm.cleanUpUserLILPw(userHandle); + mPm.cleanUpUserLILPw(this, userHandle); // Remove this user from the list mUsers.remove(userHandle); |