OSDN Git Service

Delayed install completion
authorWinson <chiuwinson@google.com>
Fri, 5 Apr 2019 00:41:28 +0000 (17:41 -0700)
committerWinson Chiu <chiuwinson@google.com>
Fri, 19 Apr 2019 22:52:41 +0000 (22:52 +0000)
This change is an attempt at delaying the install complete callback
to the installer on a DONT_KILL install until the package indicates
that it as completed updating its classpath with the new APKs.

Bug: 80269951
Bug: 109751013

Test: manual test of dynamic delivery/instant apps

Merged-In: I689ec523522da37987cff9b1a67eaae9e5633ffb
Change-Id: I689ec523522da37987cff9b1a67eaae9e5633ffb
(cherry picked from commit abfc054c9065f96ae34023119623bdd310cb6e48)

core/java/android/app/ActivityThread.java
core/java/android/content/pm/IPackageManager.aidl
services/core/java/com/android/server/am/ProcessList.java
services/core/java/com/android/server/pm/PackageManagerService.java

index 474f25b..a83f91e 100644 (file)
@@ -5718,14 +5718,18 @@ public final class ActivityThread extends ClientTransactionHandler {
                 if (packages == null) {
                     break;
                 }
+
+                List<String> packagesHandled = new ArrayList<>();
+
                 synchronized (mResourcesManager) {
                     for (int i = packages.length - 1; i >= 0; i--) {
-                        WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
+                        String packageName = packages[i];
+                        WeakReference<LoadedApk> ref = mPackages.get(packageName);
                         LoadedApk pkgInfo = ref != null ? ref.get() : null;
                         if (pkgInfo != null) {
                             hasPkgInfo = true;
                         } else {
-                            ref = mResourcePackages.get(packages[i]);
+                            ref = mResourcePackages.get(packageName);
                             pkgInfo = ref != null ? ref.get() : null;
                             if (pkgInfo != null) {
                                 hasPkgInfo = true;
@@ -5736,8 +5740,8 @@ public final class ActivityThread extends ClientTransactionHandler {
                         // Adjust it's internal references to the application info and
                         // resources.
                         if (pkgInfo != null) {
+                            packagesHandled.add(packageName);
                             try {
-                                final String packageName = packages[i];
                                 final ApplicationInfo aInfo =
                                         sPackageManager.getApplicationInfo(
                                                 packageName,
@@ -5769,6 +5773,13 @@ public final class ActivityThread extends ClientTransactionHandler {
                         }
                     }
                 }
+
+                try {
+                    getPackageManager().notifyPackagesReplacedReceived(
+                            packagesHandled.toArray(new String[0]));
+                } catch (RemoteException ignored) {
+                }
+
                 break;
             }
         }
index cf704d5..6ab4657 100644 (file)
@@ -770,4 +770,6 @@ interface IPackageManager {
     int getRuntimePermissionsVersion(int userId);
 
     void setRuntimePermissionsVersion(int version, int userId);
+
+    void notifyPackagesReplacedReceived(in String[] packages);
 }
index 1bcc4c8..a93f218 100644 (file)
@@ -3172,15 +3172,28 @@ public final class ProcessList {
 
     @GuardedBy("mService")
     void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) {
+        boolean foundProcess = false;
         for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
             ProcessRecord r = mLruProcesses.get(i);
             if (r.thread != null && (userId == UserHandle.USER_ALL || r.userId == userId)) {
                 try {
+                    for (int index = packages.length - 1; index >= 0 && !foundProcess; index--) {
+                        if (packages[index].equals(r.info.packageName)) {
+                            foundProcess = true;
+                        }
+                    }
                     r.thread.dispatchPackageBroadcast(cmd, packages);
                 } catch (RemoteException ex) {
                 }
             }
         }
+
+        if (!foundProcess) {
+            try {
+                AppGlobals.getPackageManager().notifyPackagesReplacedReceived(packages);
+            } catch (RemoteException ignored) {
+            }
+        }
     }
 
     /** Returns the uid's process state or PROCESS_STATE_NONEXISTENT if not running */
index f032400..3c336ea 100644 (file)
@@ -952,6 +952,9 @@ public class PackageManagerService extends IPackageManager.Stub
     ActivityInfo mInstantAppInstallerActivity;
     final ResolveInfo mInstantAppInstallerInfo = new ResolveInfo();
 
+    private final Map<String, Pair<PackageInstalledInfo, IPackageInstallObserver2>>
+            mNoKillInstallObservers = Collections.synchronizedMap(new HashMap<>());
+
     final SparseArray<IntentFilterVerificationState> mIntentFilterVerificationStates
             = new SparseArray<>();
 
@@ -1320,8 +1323,10 @@ public class PackageManagerService extends IPackageManager.Stub
     static final int ENABLE_ROLLBACK_STATUS = 21;
     static final int ENABLE_ROLLBACK_TIMEOUT = 22;
     static final int DEFERRED_NO_KILL_POST_DELETE = 23;
+    static final int DEFERRED_NO_KILL_INSTALL_OBSERVER = 24;
 
-    static final int DEFERRED_NO_KILL_POST_DELETE_DELAY_MS = 5 * 1000;
+    static final int DEFERRED_NO_KILL_POST_DELETE_DELAY_MS = 3 * 1000;
+    static final int DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS = 500;
 
     static final int WRITE_SETTINGS_DELAY = 10*1000;  // 10 seconds
 
@@ -1531,7 +1536,15 @@ public class PackageManagerService extends IPackageManager.Stub
                 case DEFERRED_NO_KILL_POST_DELETE: {
                     synchronized (mInstallLock) {
                         InstallArgs args = (InstallArgs) msg.obj;
-                        args.doPostDeleteLI(true);
+                        if (args != null) {
+                            args.doPostDeleteLI(true);
+                        }
+                    }
+                } break;
+                case DEFERRED_NO_KILL_INSTALL_OBSERVER: {
+                    String packageName = (String) msg.obj;
+                    if (packageName != null) {
+                        notifyInstallObserver(packageName);
                     }
                 } break;
                 case WRITE_SETTINGS: {
@@ -1800,7 +1813,10 @@ public class PackageManagerService extends IPackageManager.Stub
             String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
             boolean launchedForRestore, String installerPackage,
             IPackageInstallObserver2 installObserver) {
-        if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
+        final boolean succeeded = res.returnCode == PackageManager.INSTALL_SUCCEEDED;
+        final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null;
+
+        if (succeeded) {
             // Send the removed broadcasts
             if (res.removedInfo != null) {
                 res.removedInfo.sendPackageRemovedBroadcasts(killApp);
@@ -1828,8 +1844,6 @@ public class PackageManagerService extends IPackageManager.Stub
                         mPermissionCallback);
             }
 
-            final boolean update = res.removedInfo != null
-                    && res.removedInfo.removedPackage != null;
             final String installerPackageName =
                     res.installerPackageName != null
                             ? res.installerPackageName
@@ -2072,12 +2086,43 @@ public class PackageManagerService extends IPackageManager.Stub
             }
         }
 
-        // If someone is watching installs - notify them
+        final boolean deferInstallObserver = succeeded && update && !killApp;
+        if (deferInstallObserver) {
+            scheduleDeferredNoKillInstallObserver(res, installObserver);
+        } else {
+            notifyInstallObserver(res, installObserver);
+        }
+    }
+
+    @Override
+    public void notifyPackagesReplacedReceived(String[] packages) {
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getUserId(callingUid);
+
+        for (String packageName : packages) {
+            PackageSetting setting = mSettings.mPackages.get(packageName);
+            if (setting != null && filterAppAccessLPr(setting, callingUid, callingUserId)) {
+                notifyInstallObserver(packageName);
+            }
+        }
+    }
+
+    private void notifyInstallObserver(String packageName) {
+        Pair<PackageInstalledInfo, IPackageInstallObserver2> pair =
+                mNoKillInstallObservers.remove(packageName);
+
+        if (pair != null) {
+            notifyInstallObserver(pair.first, pair.second);
+        }
+    }
+
+    private void notifyInstallObserver(PackageInstalledInfo info,
+            IPackageInstallObserver2 installObserver) {
         if (installObserver != null) {
             try {
-                Bundle extras = extrasForInstallResult(res);
-                installObserver.onPackageInstalled(res.name, res.returnCode,
-                        res.returnMsg, extras);
+                Bundle extras = extrasForInstallResult(info);
+                installObserver.onPackageInstalled(info.name, info.returnCode,
+                        info.returnMsg, extras);
             } catch (RemoteException e) {
                 Slog.i(TAG, "Observer no longer exists.");
             }
@@ -2089,6 +2134,14 @@ public class PackageManagerService extends IPackageManager.Stub
         mHandler.sendMessageDelayed(message, DEFERRED_NO_KILL_POST_DELETE_DELAY_MS);
     }
 
+    private void scheduleDeferredNoKillInstallObserver(PackageInstalledInfo info,
+            IPackageInstallObserver2 observer) {
+        String packageName = info.pkg.packageName;
+        mNoKillInstallObservers.put(packageName, Pair.create(info, observer));
+        Message message = mHandler.obtainMessage(DEFERRED_NO_KILL_INSTALL_OBSERVER, packageName);
+        mHandler.sendMessageDelayed(message, DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS);
+    }
+
     /**
      * Gets the type of the external storage a package is installed on.
      * @param packageVolume The storage volume of the package.