When uninstalling, only kill the requested user.

When an app is being uninstalled for a specific user, only kill the
app under that user; leave the app running under other users.

Bug: 28875343
Change-Id: Ie60753cfd22df10a2b17d8c3732b6f19d2fe1fb9
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 3c7eef5..cf5240b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1813,12 +1813,13 @@
             return true;
         }
 
-        case KILL_APPLICATION_WITH_APPID_TRANSACTION: {
+        case KILL_APPLICATION_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String pkg = data.readString();
-            int appid = data.readInt();
+            int appId = data.readInt();
+            int userId = data.readInt();
             String reason = data.readString();
-            killApplicationWithAppId(pkg, appid, reason);
+            killApplication(pkg, appId, userId, reason);
             reply.writeNoException();
             return true;
         }
@@ -5291,15 +5292,16 @@
         reply.recycle();
     }
 
-    public void killApplicationWithAppId(String pkg, int appid, String reason)
+    public void killApplication(String pkg, int appId, int userId, String reason)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(pkg);
-        data.writeInt(appid);
+        data.writeInt(appId);
+        data.writeInt(userId);
         data.writeString(reason);
-        mRemote.transact(KILL_APPLICATION_WITH_APPID_TRANSACTION, data, reply, 0);
+        mRemote.transact(KILL_APPLICATION_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index ac21346..5037e3e 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -398,7 +398,7 @@
 
     public void addPackageDependency(String packageName) throws RemoteException;
 
-    public void killApplicationWithAppId(String pkg, int appid, String reason)
+    public void killApplication(String pkg, int appId, int userId, String reason)
             throws RemoteException;
 
     public void closeSystemDialogs(String reason) throws RemoteException;
@@ -852,7 +852,7 @@
     int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
     int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
     int ADD_PACKAGE_DEPENDENCY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
-    int KILL_APPLICATION_WITH_APPID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
+    int KILL_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
     int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
     int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
     int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98;
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 55464e4..cdd977b 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -827,8 +827,9 @@
                 if (provider != null) {
                     final IActivityManager am = ActivityManagerNative.getDefault();
                     try {
-                        am.killApplicationWithAppId(provider.applicationInfo.packageName,
-                                UserHandle.getAppId(provider.applicationInfo.uid), "vold reset");
+                        am.killApplication(provider.applicationInfo.packageName,
+                                UserHandle.getAppId(provider.applicationInfo.uid),
+                                UserHandle.USER_ALL, "vold reset");
                         // We only need to run this once. It will kill all users' media processes.
                         break;
                     } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 09a5185..9cba6c7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1849,13 +1849,13 @@
             } break;
             case KILL_APPLICATION_MSG: {
                 synchronized (ActivityManagerService.this) {
-                    int appid = msg.arg1;
-                    boolean restart = (msg.arg2 == 1);
+                    final int appId = msg.arg1;
+                    final int userId = msg.arg2;
                     Bundle bundle = (Bundle)msg.obj;
                     String pkg = bundle.getString("pkg");
                     String reason = bundle.getString("reason");
-                    forceStopPackageLocked(pkg, appid, restart, false, true, false,
-                            false, UserHandle.USER_ALL, reason);
+                    forceStopPackageLocked(pkg, appId, false, false, true, false,
+                            false, userId, reason);
                 }
             } break;
             case FINALIZE_PENDING_INTENT_MSG: {
@@ -5717,12 +5717,12 @@
      * The pkg name and app id have to be specified.
      */
     @Override
-    public void killApplicationWithAppId(String pkg, int appid, String reason) {
+    public void killApplication(String pkg, int appId, int userId, String reason) {
         if (pkg == null) {
             return;
         }
         // Make sure the uid is valid.
-        if (appid < 0) {
+        if (appId < 0) {
             Slog.w(TAG, "Invalid appid specified for pkg : " + pkg);
             return;
         }
@@ -5731,8 +5731,8 @@
         if (UserHandle.getAppId(callerUid) == Process.SYSTEM_UID) {
             // Post an aysnc message to kill the application
             Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
-            msg.arg1 = appid;
-            msg.arg2 = 0;
+            msg.arg1 = appId;
+            msg.arg2 = userId;
             Bundle bundle = new Bundle();
             bundle.putString("pkg", pkg);
             bundle.putString("reason", reason);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 96513b9..00199730 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9534,6 +9534,10 @@
     }
 
     private void killApplication(String pkgName, int appId, String reason) {
+        killApplication(pkgName, appId, UserHandle.USER_ALL, reason);
+    }
+
+    private void killApplication(String pkgName, int appId, int userId, String reason) {
         // Request the ActivityManager to kill the process(only for existing packages)
         // so that we do not end up in a confused state while the user is still using the older
         // version of the application while the new one gets installed.
@@ -9542,7 +9546,7 @@
             IActivityManager am = ActivityManagerNative.getDefault();
             if (am != null) {
                 try {
-                    am.killApplicationWithAppId(pkgName, appId, reason);
+                    am.killApplication(pkgName, appId, userId, reason);
                 } catch (RemoteException e) {
                 }
             }
@@ -15555,10 +15559,10 @@
         final PackageRemovedInfo info = new PackageRemovedInfo();
         final boolean res;
 
-        final UserHandle removeForUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
-                ? UserHandle.ALL : new UserHandle(userId);
+        final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
+                ? UserHandle.USER_ALL : userId;
 
-        if (isPackageDeviceAdmin(packageName, removeForUser.getIdentifier())) {
+        if (isPackageDeviceAdmin(packageName, removeUser)) {
             Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
             return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
         }
@@ -15578,11 +15582,21 @@
             info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true);
         }
 
+        final int freezeUser;
+        if (isUpdatedSystemApp(uninstalledPs)
+                && ((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;
+        } else {
+            freezeUser = removeUser;
+        }
+
         synchronized (mInstallLock) {
             if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
-            try (PackageFreezer freezer = freezePackageForDelete(packageName, deleteFlags,
-                    "deletePackageX")) {
-                res = deletePackageLIF(packageName, removeForUser, true, allUsers,
+            try (PackageFreezer freezer = freezePackageForDelete(packageName, freezeUser,
+                    deleteFlags, "deletePackageX")) {
+                res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
                         deleteFlags | REMOVE_CHATTY, info, true, null);
             }
             synchronized (mPackages) {
@@ -19837,24 +19851,38 @@
     }
 
     public PackageFreezer freezePackage(String packageName, String killReason) {
-        return new PackageFreezer(packageName, killReason);
+        return freezePackage(packageName, UserHandle.USER_ALL, killReason);
+    }
+
+    public PackageFreezer freezePackage(String packageName, int userId, String killReason) {
+        return new PackageFreezer(packageName, userId, killReason);
     }
 
     public PackageFreezer freezePackageForInstall(String packageName, int installFlags,
             String killReason) {
+        return freezePackageForInstall(packageName, UserHandle.USER_ALL, installFlags, killReason);
+    }
+
+    public PackageFreezer freezePackageForInstall(String packageName, int userId, int installFlags,
+            String killReason) {
         if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
             return new PackageFreezer();
         } else {
-            return freezePackage(packageName, killReason);
+            return freezePackage(packageName, userId, killReason);
         }
     }
 
     public PackageFreezer freezePackageForDelete(String packageName, int deleteFlags,
             String killReason) {
+        return freezePackageForDelete(packageName, UserHandle.USER_ALL, deleteFlags, killReason);
+    }
+
+    public PackageFreezer freezePackageForDelete(String packageName, int userId, int deleteFlags,
+            String killReason) {
         if ((deleteFlags & PackageManager.DELETE_DONT_KILL_APP) != 0) {
             return new PackageFreezer();
         } else {
-            return freezePackage(packageName, killReason);
+            return freezePackage(packageName, userId, killReason);
         }
     }
 
@@ -19885,14 +19913,14 @@
             mCloseGuard.open("close");
         }
 
-        public PackageFreezer(String packageName, String killReason) {
+        public PackageFreezer(String packageName, int userId, String killReason) {
             synchronized (mPackages) {
                 mPackageName = packageName;
                 mWeFroze = mFrozenPackages.add(mPackageName);
 
                 final PackageSetting ps = mSettings.mPackages.get(mPackageName);
                 if (ps != null) {
-                    killApplication(ps.name, ps.appId, killReason);
+                    killApplication(ps.name, ps.appId, userId, killReason);
                 }
 
                 final PackageParser.Package p = mPackages.get(packageName);
@@ -19901,7 +19929,7 @@
                     mChildren = new PackageFreezer[N];
                     for (int i = 0; i < N; i++) {
                         mChildren[i] = new PackageFreezer(p.childPackages.get(i).packageName,
-                                killReason);
+                                userId, killReason);
                     }
                 } else {
                     mChildren = null;
@@ -20040,7 +20068,7 @@
             seinfo = pkg.applicationInfo.seinfo;
             label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo));
             targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
-            freezer = new PackageFreezer(packageName, "movePackageInternal");
+            freezer = freezePackage(packageName, "movePackageInternal");
             installedUserIds = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
         }