Yet more movement from ActivityStack to Supervisor

- Remove redundant synchronize in ActivityStack.activityIdleInternal().
- Move startSpecificActivityLocked from ActivityStack to Supervisor.
- Move handleAppDiedLocked from Supervisor to ActivityStack.

Change-Id: Id746ab3bdff861b61182282bea1deb8fcf284084
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index d18cc4c..4e3e457 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -368,7 +368,9 @@
                     // so we need to be conservative and assume it isn't.
                     ActivityRecord r = (ActivityRecord)msg.obj;
                     Slog.w(TAG, "Activity idle timeout for " + r);
-                    activityIdleInternal(r != null ? r.appToken : null, true, null);
+                    synchronized (this) {
+                        activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
+                    }
                 } break;
                 case LAUNCH_TICK_MSG: {
                     ActivityRecord r = (ActivityRecord)msg.obj;
@@ -390,7 +392,9 @@
                 } break;
                 case IDLE_NOW_MSG: {
                     ActivityRecord r = (ActivityRecord)msg.obj;
-                    activityIdleInternal(r != null ? r.appToken : null, false, null);
+                    synchronized (mService) {
+                        activityIdleInternalLocked(r != null ? r.appToken : null, false, null);
+                    }
                 } break;
                 case LAUNCH_TIMEOUT_MSG: {
                     if (mService.mDidDexOpt) {
@@ -663,12 +667,7 @@
         if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle);
     }
 
-    private final void startSpecificActivityLocked(ActivityRecord r,
-            boolean andResume, boolean checkConfig) {
-        // Is this activity's application already running?
-        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
-                r.info.applicationInfo.uid);
-
+    void setLaunchTime(ActivityRecord r) {
         if (r.launchTime == 0) {
             r.launchTime = SystemClock.uptimeMillis();
             if (mInitialStartTime == 0) {
@@ -677,23 +676,6 @@
         } else if (mInitialStartTime == 0) {
             mInitialStartTime = SystemClock.uptimeMillis();
         }
-
-        if (app != null && app.thread != null) {
-            try {
-                app.addPackage(r.info.packageName);
-                mStackSupervisor.realStartActivityLocked(r, app, andResume, checkConfig);
-                return;
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Exception when starting activity "
-                        + r.intent.getComponent().flattenToShortString(), e);
-            }
-
-            // If a dead object exception was thrown -- fall through to
-            // restart the application.
-        }
-
-        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
-                "activity", r.intent.getComponent(), false, false);
     }
 
     void stopIfSleepingLocked() {
@@ -733,6 +715,7 @@
         checkReadyForSleepLocked();
     }
 
+    // Checked.
     void checkReadyForSleepLocked() {
         if (!mService.isSleepingOrShuttingDown()) {
             // Do not care.
@@ -1066,6 +1049,7 @@
         prev.cpuTimeAtResume = 0; // reset it
     }
 
+    // Checked.
     /**
      * Once we know that we have asked an application to put an activity in
      * the resumed state (either by launching it or explicitly telling it),
@@ -1092,6 +1076,7 @@
         }
 
         if (mStackSupervisor.isMainStack(this)) {
+            // Should this be done for all stacks, not just mMainStack?
             mService.reportResumedActivityLocked(next);
         }
 
@@ -1115,6 +1100,7 @@
         }
     }
 
+    // Checked.
     /**
      * Make sure that all activities that need to be visible (that is, they
      * currently can be seen by the user) actually are.
@@ -1171,7 +1157,7 @@
                                 mService.mWindowManager.setAppVisibility(r.appToken, true);
                             }
                             if (r != starting) {
-                                startSpecificActivityLocked(r, false, false);
+                                mStackSupervisor.startSpecificActivityLocked(r, false, false);
                             }
                         }
 
@@ -1244,6 +1230,7 @@
         }
     }
 
+    // Checked.
     /**
      * Version of ensureActivitiesVisible that can easily be called anywhere.
      */
@@ -1603,7 +1590,7 @@
                                 null, true);
                     }
                 }
-                startSpecificActivityLocked(next, true, false);
+                mStackSupervisor.startSpecificActivityLocked(next, true, false);
                 return true;
             }
 
@@ -1638,7 +1625,7 @@
                 }
                 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
             }
-            startSpecificActivityLocked(next, true, true);
+            mStackSupervisor.startSpecificActivityLocked(next, true, true);
         }
 
         return true;
@@ -2893,7 +2880,8 @@
         mHandler.sendMessage(msg);
     }
 
-    final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
+    // Checked.
+    final ActivityRecord activityIdleInternalLocked(IBinder token, boolean fromTimeout,
             Configuration config) {
         if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
 
@@ -2911,81 +2899,79 @@
         boolean enableScreen = false;
         boolean activityRemoved = false;
 
-        synchronized (mService) {
-            ActivityRecord r = ActivityRecord.forToken(token);
-            if (r != null) {
-                mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
-                r.finishLaunchTickingLocked();
+        ActivityRecord r = ActivityRecord.forToken(token);
+        if (r != null) {
+            mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
+            r.finishLaunchTickingLocked();
+        }
+
+        // Get the activity record.
+        if (isInStackLocked(token) != null) {
+            res = r;
+
+            if (fromTimeout) {
+                reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
             }
 
-            // Get the activity record.
-            if (isInStackLocked(token) != null) {
-                res = r;
-
-                if (fromTimeout) {
-                    reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
-                }
-
-                // This is a hack to semi-deal with a race condition
-                // in the client where it can be constructed with a
-                // newer configuration from when we asked it to launch.
-                // We'll update with whatever configuration it now says
-                // it used to launch.
-                if (config != null) {
-                    r.configuration = config;
-                }
-
-                // No longer need to keep the device awake.
-                if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
-                    mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
-                    mLaunchingActivity.release();
-                }
-
-                // We are now idle.  If someone is waiting for a thumbnail from
-                // us, we can now deliver.
-                r.idle = true;
-                mService.scheduleAppGcsLocked();
-                if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
-                    sendThumbnail = r.app.thread;
-                    r.thumbnailNeeded = false;
-                }
-
-                // If this activity is fullscreen, set up to hide those under it.
-
-                if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
-                ensureActivitiesVisibleLocked(null, 0);
-
-                //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
-                if (mStackSupervisor.isMainStack(this)) {
-                    if (!mService.mBooted) {
-                        mService.mBooted = true;
-                        enableScreen = true;
-                    }
-                }
-            } else if (fromTimeout) {
-                reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
+            // This is a hack to semi-deal with a race condition
+            // in the client where it can be constructed with a
+            // newer configuration from when we asked it to launch.
+            // We'll update with whatever configuration it now says
+            // it used to launch.
+            if (config != null) {
+                r.configuration = config;
             }
 
-            // Atomically retrieve all of the other things to do.
-            stops = processStoppingActivitiesLocked(true);
-            NS = stops != null ? stops.size() : 0;
-            if ((NF=mFinishingActivities.size()) > 0) {
-                finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
-                mFinishingActivities.clear();
-            }
-            if ((NT=mCancelledThumbnails.size()) > 0) {
-                thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
-                mCancelledThumbnails.clear();
+            // No longer need to keep the device awake.
+            if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
+                mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
+                mLaunchingActivity.release();
             }
 
+            // We are now idle.  If someone is waiting for a thumbnail from
+            // us, we can now deliver.
+            r.idle = true;
+            mService.scheduleAppGcsLocked();
+            if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
+                sendThumbnail = r.app.thread;
+                r.thumbnailNeeded = false;
+            }
+
+            // If this activity is fullscreen, set up to hide those under it.
+
+            if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
+            ensureActivitiesVisibleLocked(null, 0);
+
+            //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
             if (mStackSupervisor.isMainStack(this)) {
-                booting = mService.mBooting;
-                mService.mBooting = false;
+                if (!mService.mBooted) {
+                    mService.mBooted = true;
+                    enableScreen = true;
+                }
             }
-            if (mStartingUsers.size() > 0) {
-                startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
-                mStartingUsers.clear();
-            }
+        } else if (fromTimeout) {
+            reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
+        }
+
+        // Atomically retrieve all of the other things to do.
+        stops = processStoppingActivitiesLocked(true);
+        NS = stops != null ? stops.size() : 0;
+        if ((NF=mFinishingActivities.size()) > 0) {
+            finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
+            mFinishingActivities.clear();
+        }
+        if ((NT=mCancelledThumbnails.size()) > 0) {
+            thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
+            mCancelledThumbnails.clear();
+        }
+
+        if (mStackSupervisor.isMainStack(this)) {
+            booting = mService.mBooting;
+            mService.mBooting = false;
+        }
+        if (mStartingUsers.size() > 0) {
+            startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
+            mStartingUsers.clear();
         }
 
         int i;
@@ -3003,7 +2989,7 @@
         // Stop any activities that are scheduled to do so but have been
         // waiting for the next one to start.
         for (i=0; i<NS; i++) {
-            ActivityRecord r = stops.get(i);
+            r = stops.get(i);
             synchronized (mService) {
                 if (r.finishing) {
                     finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
@@ -3016,7 +3002,7 @@
         // Finish any activities that are scheduled to do so but have been
         // waiting for the next one to start.
         for (i=0; i<NF; i++) {
-            ActivityRecord r = finishes.get(i);
+            r = finishes.get(i);
             synchronized (mService) {
                 activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
             }
@@ -3024,7 +3010,7 @@
 
         // Report back to any thumbnail receivers.
         for (i=0; i<NT; i++) {
-            ActivityRecord r = thumbnails.get(i);
+            r = thumbnails.get(i);
             mService.sendPendingThumbnail(r, null, null, null, true);
         }
 
@@ -4364,6 +4350,33 @@
         }
     }
 
+    void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
+        if (mPausingActivity != null && mPausingActivity.app == app) {
+            if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG,
+                    "App died while pausing: " + mPausingActivity);
+            mPausingActivity = null;
+        }
+        if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
+            mLastPausedActivity = null;
+        }
+
+        // Remove this application's activities from active lists.
+        boolean hasVisibleActivities = removeHistoryRecordsForAppLocked(app);
+
+        if (!restarting) {
+            if (!resumeTopActivityLocked(null)) {
+                // If there was nothing to resume, and we are not already
+                // restarting this process, but there is a visible activity that
+                // is hosted by the process...  then make sure all visible
+                // activities are running, taking care of restarting this
+                // process.
+                if (hasVisibleActivities) {
+                    ensureActivitiesVisibleLocked(null, 0);
+                }
+            }
+        }
+    }
+
     void handleAppCrashLocked(ProcessRecord app) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;