Fix issue #6381224: Initial emulator boot fails and shows a blank black screen.

Make sure that all cases where we remove an activity from the history
stack, we call resumeTopActivityLocked() to cause the home activity
to be launched if the stack is now empty.

Also fixed a problem where some timeouts would not be removed when destroying
an activity, and a race condition in boot that would cause the
PhoneWindowManager to initially start out with the home key not working.

Bug: 6381224
Change-Id: If046bb01aed624b0d9ee3bbaaba68ed6b98fd1d0
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index e2d6d98..be39711 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1129,6 +1129,11 @@
             resumeTopActivityLocked(prev);
         } else {
             checkReadyForSleepLocked();
+            if (topRunningActivityLocked(null) == null) {
+                // If there are no more activities available to run, then
+                // do resume anyway to start something.
+                resumeTopActivityLocked(null);
+            }
         }
         
         if (prev != null) {
@@ -3413,6 +3418,7 @@
         IApplicationThread sendThumbnail = null;
         boolean booting = false;
         boolean enableScreen = false;
+        boolean activityRemoved = false;
 
         synchronized (mService) {
             ActivityRecord r = ActivityRecord.forToken(token);
@@ -3519,7 +3525,7 @@
         for (i=0; i<NF; i++) {
             ActivityRecord r = (ActivityRecord)finishes.get(i);
             synchronized (mService) {
-                destroyActivityLocked(r, true, false, "finish-idle");
+                activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
             }
         }
 
@@ -3541,6 +3547,10 @@
             mService.enableScreenAfterBoot();
         }
 
+        if (activityRemoved) {
+            resumeTopActivityLocked(null);
+        }
+
         return res;
     }
 
@@ -3780,7 +3790,11 @@
                 || prevState == ActivityState.INITIALIZING) {
             // If this activity is already stopped, we can just finish
             // it right now.
-            return destroyActivityLocked(r, true, true, "finish-imm") ? null : r;
+            boolean activityRemoved = destroyActivityLocked(r, true, true, "finish-imm");
+            if (activityRemoved) {
+                resumeTopActivityLocked(null);
+            }
+            return activityRemoved ? null : r;
         } else {
             // Need to go through the full pause cycle to get this
             // activity into the stopped state and then finish it.
@@ -3844,6 +3858,10 @@
         }
 
         // Get rid of any pending idle timeouts.
+        removeTimeoutsForActivityLocked(r);
+    }
+
+    private void removeTimeoutsForActivityLocked(ActivityRecord r) {
         mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
         mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
         mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
@@ -3897,6 +3915,7 @@
 
     final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
         boolean lastIsOpaque = false;
+        boolean activityRemoved = false;
         for (int i=mHistory.size()-1; i>=0; i--) {
             ActivityRecord r = mHistory.get(i);
             if (r.finishing) {
@@ -3920,9 +3939,14 @@
                 if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
                         + " resumed=" + mResumedActivity
                         + " pausing=" + mPausingActivity);
-                destroyActivityLocked(r, true, oomAdj, reason);
+                if (destroyActivityLocked(r, true, oomAdj, reason)) {
+                    activityRemoved = true;
+                }
             }
         }
+        if (activityRemoved) {
+            resumeTopActivityLocked(null);
+        }
     }
 
     /**
@@ -4027,23 +4051,28 @@
 
     final void activityDestroyed(IBinder token) {
         synchronized (mService) {
-            ActivityRecord r = ActivityRecord.forToken(token);
-            if (r != null) {
-                mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
-            }
-            
-            int index = indexOfActivityLocked(r);
-            if (index >= 0) {
-                if (r.state == ActivityState.DESTROYING) {
-                    final long origId = Binder.clearCallingIdentity();
-                    removeActivityFromHistoryLocked(r);
-                    Binder.restoreCallingIdentity(origId);
+            final long origId = Binder.clearCallingIdentity();
+            try {
+                ActivityRecord r = ActivityRecord.forToken(token);
+                if (r != null) {
+                    mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
                 }
+
+                int index = indexOfActivityLocked(r);
+                if (index >= 0) {
+                    if (r.state == ActivityState.DESTROYING) {
+                        cleanUpActivityLocked(r, true, true);
+                        removeActivityFromHistoryLocked(r);
+                    }
+                }
+                resumeTopActivityLocked(null);
+            } finally {
+                Binder.restoreCallingIdentity(origId);
             }
         }
     }
     
-    private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
+    private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
         int i = list.size();
         if (localLOGV) Slog.v(
             TAG, "Removing app " + app + " from list " + list
@@ -4056,6 +4085,7 @@
             if (r.app == app) {
                 if (localLOGV) Slog.v(TAG, "Removing this entry!");
                 list.remove(i);
+                removeTimeoutsForActivityLocked(r);
             }
         }
     }