OSDN Git Service

DO NOT MERGE: Clean up when recycling a pid with a pending launch
authorAmith Yamasani <yamasani@google.com>
Fri, 5 Aug 2016 22:25:03 +0000 (15:25 -0700)
committerSudheer Shanka <sudheersai@google.com>
Sat, 13 Aug 2016 01:32:42 +0000 (18:32 -0700)
Fix for accidental launch of a broadcast receiver in an
incorrect app instance.

Bug: 30202481
Change-Id: I8ec8f19c633f3aec8da084dab5fd5b312443336f

services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/BroadcastQueue.java

index f8c2f1e..08b3627 100755 (executable)
@@ -3068,6 +3068,15 @@ public final class ActivityManagerService extends ActivityManagerNative
             app.killedByAm = false;
             checkTime(startTime, "startProcess: starting to update pids map");
             synchronized (mPidsSelfLocked) {
+                ProcessRecord oldApp;
+                // If there is already an app occupying that pid that hasn't been cleaned up
+                if ((oldApp = mPidsSelfLocked.get(startResult.pid)) != null && !app.isolated) {
+                    // Clean up anything relating to this pid first
+                    Slog.w(TAG, "Reusing pid " + startResult.pid
+                            + " while app is still mapped to it");
+                    cleanUpApplicationRecordLocked(oldApp, false, false, -1,
+                            true /*replacingPid*/);
+                }
                 this.mPidsSelfLocked.put(startResult.pid, app);
                 if (isActivityProcess) {
                     Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
@@ -4558,7 +4567,8 @@ public final class ActivityManagerService extends ActivityManagerNative
     private final void handleAppDiedLocked(ProcessRecord app,
             boolean restarting, boolean allowRestart) {
         int pid = app.pid;
-        boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
+        boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
+                false /*replacingPid*/);
         if (!kept && !restarting) {
             removeLruProcessLocked(app);
             if (pid > 0) {
@@ -14875,7 +14885,8 @@ public final class ActivityManagerService extends ActivityManagerNative
      * app that was passed in must remain on the process lists.
      */
     private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
-            boolean restarting, boolean allowRestart, int index) {
+            boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
+        Slog.d(TAG, "cleanUpApplicationRecord -- " + app.pid);
         if (index >= 0) {
             removeLruProcessLocked(app);
             ProcessList.remove(app.pid);
@@ -15005,8 +15016,10 @@ public final class ActivityManagerService extends ActivityManagerNative
         if (!app.persistent || app.isolated) {
             if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG,
                     "Removing non-persistent process during cleanup: " + app);
-            mProcessNames.remove(app.processName, app.uid);
-            mIsolatedProcesses.remove(app.uid);
+            if (!replacingPid) {
+                mProcessNames.remove(app.processName, app.uid);
+                mIsolatedProcesses.remove(app.uid);
+            }
             if (mHeavyWeightProcess == app) {
                 mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
                         mHeavyWeightProcess.userId, 0));
@@ -18589,7 +18602,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                             // Ignore exceptions.
                         }
                     }
-                    cleanUpApplicationRecordLocked(app, false, true, -1);
+                    cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/);
                     mRemovedProcesses.remove(i);
 
                     if (app.persistent) {
index 9b7d0b2..c7a4a0d 100644 (file)
@@ -264,6 +264,11 @@ public final class BroadcastQueue {
         boolean didSomething = false;
         final BroadcastRecord br = mPendingBroadcast;
         if (br != null && br.curApp.pid == app.pid) {
+            if (br.curApp != app) {
+                Slog.e(TAG, "App mismatch when sending pending broadcast to "
+                        + app.processName + ", intended target is " + br.curApp.processName);
+                return false;
+            }
             try {
                 mPendingBroadcast = null;
                 processCurBroadcastLocked(br, app);