Merge "Fixed deadlock while mapping and unmapping process in AMS"
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0e354d5..562e80d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -666,16 +666,50 @@
     final class PidMap {
         private final SparseArray<ProcessRecord> mPidMap = new SparseArray<>();
 
+        /**
+         * Puts the process record in the map.
+         * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
+         * method.
+         */
         void put(int key, ProcessRecord value) {
-            mPidMap.put(key, value);
+            synchronized (this) {
+                mPidMap.put(key, value);
+            }
             mAtmInternal.onProcessMapped(key, value.getWindowProcessController());
         }
 
+        /**
+         * Removes the process record from the map.
+         * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
+         * method.
+         */
         void remove(int pid) {
-            mPidMap.remove(pid);
+            synchronized (this) {
+                mPidMap.remove(pid);
+            }
             mAtmInternal.onProcessUnMapped(pid);
         }
 
+        /**
+         * Removes the process record from the map if it has a thread.
+         * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
+         * method.
+         */
+        boolean removeIfNoThread(int pid) {
+            boolean removed = false;
+            synchronized (this) {
+                final ProcessRecord app = get(pid);
+                if (app != null && app.thread == null) {
+                    mPidMap.remove(pid);
+                    removed = true;
+                }
+            }
+            if (removed) {
+                mAtmInternal.onProcessUnMapped(pid);
+            }
+            return removed;
+        }
+
         ProcessRecord get(int pid) {
             return mPidMap.get(pid);
         }
@@ -1889,9 +1923,7 @@
                 app.getWindowProcessController().setPid(MY_PID);
                 app.maxAdj = ProcessList.SYSTEM_ADJ;
                 app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
-                synchronized (mPidsSelfLocked) {
-                    mPidsSelfLocked.put(app.pid, app);
-                }
+                mPidsSelfLocked.put(app.pid, app);
                 mProcessList.updateLruProcessLocked(app, false, null);
                 updateOomAdjLocked();
             }
@@ -4254,14 +4286,7 @@
 
     private final void processStartTimedOutLocked(ProcessRecord app) {
         final int pid = app.pid;
-        boolean gone = false;
-        synchronized (mPidsSelfLocked) {
-            ProcessRecord knownApp = mPidsSelfLocked.get(pid);
-            if (knownApp != null && knownApp.thread == null) {
-                mPidsSelfLocked.remove(pid);
-                gone = true;
-            }
-        }
+        boolean gone = mPidsSelfLocked.removeIfNoThread(pid);
 
         if (gone) {
             Slog.w(TAG, "Process " + app + " failed to attach");
@@ -13113,11 +13138,8 @@
             return true;
         } else if (app.pid > 0 && app.pid != MY_PID) {
             // Goodbye!
-            boolean removed;
-            synchronized (mPidsSelfLocked) {
-                mPidsSelfLocked.remove(app.pid);
-                mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
-            }
+            mPidsSelfLocked.remove(app.pid);
+            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
             if (app.isolated) {
                 mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 7991783..62f1009 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1246,10 +1246,8 @@
         long startTime = SystemClock.elapsedRealtime();
         if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) {
             checkSlow(startTime, "startProcess: removing from pids map");
-            synchronized (mService.mPidsSelfLocked) {
-                mService.mPidsSelfLocked.remove(app.pid);
-                mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
-            }
+            mService.mPidsSelfLocked.remove(app.pid);
+            mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             checkSlow(startTime, "startProcess: done removing from pids map");
             app.setPid(0);
         }
@@ -1767,8 +1765,8 @@
             mService.cleanUpApplicationRecordLocked(oldApp, false, false, -1,
                     true /*replacingPid*/);
         }
+        mService.mPidsSelfLocked.put(pid, app);
         synchronized (mService.mPidsSelfLocked) {
-            mService.mPidsSelfLocked.put(pid, app);
             if (!procAttached) {
                 Message msg = mService.mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                 msg.obj = app;
@@ -1928,10 +1926,8 @@
                 .pendingStart)) {
             int pid = app.pid;
             if (pid > 0) {
-                synchronized (mService.mPidsSelfLocked) {
-                    mService.mPidsSelfLocked.remove(pid);
-                    mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
-                }
+                mService.mPidsSelfLocked.remove(pid);
+                mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
                 mService.mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
                 if (app.isolated) {
                     mService.mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);