Freeze apps during upgrade, check if uninstalled.

When an app is actively being upgraded, mark it as being "frozen"
to prevent it from being launched in a weird state.  Also verify that
app is actually installed before letting Zygote fork it, working
around race conditions during user setup.

When the ProcessRecord of an ActivityRecord is inconsistent,
warn about it, but correct it and keep moving if the UIDs match.

Bug: 27200022, 26205678
Change-Id: I6628cf1cece5613f07647e0acc2d49265e69dc69
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8b67d0e..9070849 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18362,9 +18362,14 @@
             for (int j = 0; j < activitiesSize; j++) {
                 final ActivityRecord r = app.activities.get(j);
                 if (r.app != app) {
-                    Slog.w(TAG, "Wtf, activity " + r + " in proc activity list not using proc "
-                            + app + "?!? Using " + r.app + " instead.");
-                    continue;
+                    Log.wtf(TAG, "Found activity " + r + " in proc activity list using " + r.app
+                            + " instead of expected " + app);
+                    if (r.app == null || (r.app.uid == app.uid)) {
+                        // Only fix things up when they look sane
+                        r.app = app;
+                    } else {
+                        continue;
+                    }
                 }
                 if (r.visible) {
                     // App has a visible activity; only upgrade adjustment.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 64f8c98..1a80a46 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2899,6 +2899,11 @@
                 throw new SecurityException("Package " + packageName + " was not found!");
             }
 
+            if (!ps.getInstalled(userId)) {
+                throw new SecurityException(
+                        "Package " + packageName + " was not installed for user " + userId + "!");
+            }
+
             if (mSafeMode && !ps.isSystem()) {
                 throw new SecurityException("Package " + packageName + " not a system app!");
             }
@@ -13130,6 +13135,7 @@
         final PackageParser.Package oldPackage;
         final String pkgName = pkg.packageName;
         final int[] allUsers;
+        final boolean weFroze;
 
         // First find the old package info and check signatures
         synchronized(mPackages) {
@@ -13162,8 +13168,32 @@
 
             // In case of rollback, remember per-user/profile install state
             allUsers = sUserManager.getUserIds();
+
+            // Mark the app as frozen to prevent launching during the upgrade
+            // process, and then kill all running instances
+            if (!ps.frozen) {
+                ps.frozen = true;
+                weFroze = true;
+            } else {
+                weFroze = false;
+            }
         }
 
+        try {
+            replacePackageDirtyLI(pkg, oldPackage, parseFlags, scanFlags, user, allUsers,
+                    installerPackageName, res);
+        } finally {
+            // Regardless of success or failure of upgrade steps above, always
+            // unfreeze the package if we froze it
+            if (weFroze) {
+                unfreezePackage(pkgName);
+            }
+        }
+    }
+
+    private void replacePackageDirtyLI(PackageParser.Package pkg, PackageParser.Package oldPackage,
+            int parseFlags, int scanFlags, UserHandle user, int[] allUsers,
+            String installerPackageName, PackageInstalledInfo res) {
         // Update what is removed
         res.removedInfo = new PackageRemovedInfo();
         res.removedInfo.uid = oldPackage.applicationInfo.uid;