Move activities from DisplayContent to TaskStack

Now that activities and tasks can be detached from a display do not
keep their state within the DisplayContent class. All such state is
now moved to the TaskStack class with this change.

Change-Id: Ie6b1811e9ec3f545782bad8c3461bd4f2d336b93
diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
index 30eaf45..574ae2d 100644
--- a/services/core/java/com/android/server/wm/DimLayer.java
+++ b/services/core/java/com/android/server/wm/DimLayer.java
@@ -170,7 +170,7 @@
             dw = mBounds.width();
             dh = mBounds.height();
             xPos = mBounds.left;
-            yPos = mBounds.right;
+            yPos = mBounds.top;
         } else {
             // Set surface size to screen size.
             final DisplayInfo info = mDisplayContent.getDisplayInfo();
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9f45e88..ee478a5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -22,12 +22,10 @@
 
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.util.EventLog;
 import android.util.Slog;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
-import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -49,7 +47,7 @@
 
     /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
      * from mDisplayWindows; */
-    private WindowList mWindows = new WindowList();
+    private final WindowList mWindows = new WindowList();
 
     // This protects the following display size properties, so that
     // getDisplaySize() doesn't need to acquire the global lock.  This is
@@ -79,21 +77,12 @@
     int pendingLayoutChanges;
     final boolean isDefaultDisplay;
 
-    /**
-     * Window tokens that are in the process of exiting, but still
-     * on screen for animations.
-     */
+    /** Window tokens that are in the process of exiting, but still on screen for animations. */
     final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
 
-    /**
-     * Application tokens that are in the process of exiting, but still
-     * on screen for animations.
-     */
-    final AppTokenList mExitingAppTokens = new AppTokenList();
-
     /** Array containing all TaskStacks on this display.  Array
      * is stored in display order with the current bottom stack at 0. */
-    private ArrayList<TaskStack> mStacks = new ArrayList<TaskStack>();
+    private final ArrayList<TaskStack> mStacks = new ArrayList<TaskStack>();
 
     /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
      * (except a future lockscreen TaskStack) moves to the top. */
@@ -105,12 +94,12 @@
     /** Detect user tapping outside of current focused stack bounds .*/
     Region mTouchExcludeRegion = new Region();
 
-    /** Save allocating when retrieving tasks */
-    private ArrayList<Task> mTaskHistory = new ArrayList<Task>();
-
     /** Save allocating when calculating rects */
     Rect mTmpRect = new Rect();
 
+    /** For gathering Task objects in order. */
+    final ArrayList<Task> mTmpTaskHistory = new ArrayList<Task>();
+
     final WindowManagerService mService;
 
     /**
@@ -152,41 +141,21 @@
         return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0;
     }
 
+    ArrayList<TaskStack> getStacks() {
+        return mStacks;
+    }
+
     /**
      * Retrieve the tasks on this display in stack order from the bottommost TaskStack up.
      * @return All the Tasks, in order, on this display.
      */
     ArrayList<Task> getTasks() {
-        return mTaskHistory;
-    }
-
-    void addTask(Task task, boolean toTop) {
-        mTaskHistory.remove(task);
-
-        final int userId = task.mUserId;
-        int taskNdx;
-        final int numTasks = mTaskHistory.size();
-        if (toTop) {
-            for (taskNdx = numTasks - 1; taskNdx >= 0; --taskNdx) {
-                if (mTaskHistory.get(taskNdx).mUserId == userId) {
-                    break;
-                }
-            }
-            ++taskNdx;
-        } else {
-            for (taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
-                if (mTaskHistory.get(taskNdx).mUserId == userId) {
-                    break;
-                }
-            }
+        mTmpTaskHistory.clear();
+        final int numStacks = mStacks.size();
+        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+            mTmpTaskHistory.addAll(mStacks.get(stackNdx).getTasks());
         }
-
-        mTaskHistory.add(taskNdx, task);
-        EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, taskNdx);
-    }
-
-    void removeTask(Task task) {
-        mTaskHistory.remove(task);
+        return mTmpTaskHistory;
     }
 
     TaskStack getHomeStack() {
@@ -226,15 +195,6 @@
         out.set(left, top, left + width, top + height);
     }
 
-    /** @return The number of tokens in all of the Tasks on this display. */
-    int numTokens() {
-        int count = 0;
-        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            count += mTaskHistory.get(taskNdx).mAppTokens.size();
-        }
-        return count;
-    }
-
     /** Refer to {@link WindowManagerService#attachStack(int, int)} */
     void attachStack(TaskStack stack) {
         if (stack.mStackId == HOME_STACK_ID) {
@@ -253,13 +213,6 @@
     }
 
     void detachStack(TaskStack stack) {
-        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = mTaskHistory.get(taskNdx);
-            if (task.mStack == stack) {
-                mService.tmpRemoveTaskWindowsLocked(task);
-                mTaskHistory.remove(taskNdx);
-            }
-        }
         mStacks.remove(stack);
     }
 
@@ -271,17 +224,6 @@
         mContentRect.set(contentRect);
     }
 
-    boolean getStackBounds(int stackId, Rect bounds) {
-        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mStacks.get(stackNdx);
-            if (stackId == stack.mStackId) {
-                bounds.set(stack.mBounds);
-                return true;
-            }
-        }
-        return false;
-    }
-
     int stackIdFromPoint(int x, int y) {
         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
             final TaskStack stack = mStacks.get(stackNdx);
@@ -307,7 +249,7 @@
         }
     }
 
-    void switchUserStacks(int oldUserId, int newUserId) {
+    void switchUserStacks(int newUserId) {
         final WindowList windows = getWindowList();
         for (int i = 0; i < windows.size(); i++) {
             final WindowState win = windows.get(i);
@@ -393,22 +335,27 @@
             pw.print(prefix); pw.print("mStacks[" + stackNdx + "]"); pw.println(stack.mStackId);
             stack.dump(prefix + "  ", pw);
         }
-        int ndx = numTokens();
-        if (ndx > 0) {
-            pw.println();
-            pw.println("  Application tokens in Z order:");
-            getTasks();
-            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-                AppTokenList tokens = mTaskHistory.get(taskNdx).mAppTokens;
+        pw.println();
+        pw.println("  Application tokens in bottom up Z order:");
+        int ndx = 0;
+        final int numStacks = mStacks.size();
+        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+            ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks();
+            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
                     final AppWindowToken wtoken = tokens.get(tokenNdx);
-                    pw.print("  App #"); pw.print(ndx--);
+                    pw.print("  App #"); pw.print(ndx++);
                             pw.print(' '); pw.print(wtoken); pw.println(":");
                     wtoken.dump(pw, "    ");
                 }
             }
         }
-        if (mExitingTokens.size() > 0) {
+        if (ndx == 0) {
+            pw.println("    None");
+        }
+        pw.println();
+        if (!mExitingTokens.isEmpty()) {
             pw.println();
             pw.println("  Exiting tokens:");
             for (int i=mExitingTokens.size()-1; i>=0; i--) {
@@ -419,17 +366,6 @@
                 token.dump(pw, "    ");
             }
         }
-        if (mExitingAppTokens.size() > 0) {
-            pw.println();
-            pw.println("  Exiting application tokens:");
-            for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
-                WindowToken token = mExitingAppTokens.get(i);
-                pw.print("  Exiting App #"); pw.print(i);
-                  pw.print(' '); pw.print(token);
-                  pw.println(':');
-                  token.dump(pw, "    ");
-            }
-        }
         pw.println();
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 1ada6c2..ce493d4 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -67,6 +67,9 @@
      * then stop any dimming. */
     boolean mDimmingTag;
 
+    /** Application tokens that are exiting, but still on screen for animations. */
+    final AppTokenList mExitingAppTokens = new AppTokenList();
+
     TaskStack(WindowManagerService service, int stackId) {
         mService = service;
         mStackId = stackId;
@@ -174,8 +177,8 @@
         mTasks.add(stackNdx, task);
 
         task.mStack = this;
-        mDisplayContent.addTask(task, toTop);
         mDisplayContent.moveStack(this, true);
+        EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, stackNdx);
     }
 
     void moveTaskToTop(Task task) {
@@ -200,7 +203,6 @@
         if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "removeTask: task=" + task);
         mTasks.remove(task);
         if (mDisplayContent != null) {
-            mDisplayContent.removeTask(task);
             if (mTasks.isEmpty()) {
                 mDisplayContent.moveStack(this, false);
             }
@@ -216,15 +218,13 @@
         mDisplayContent = displayContent;
         mDimLayer = new DimLayer(mService, this, displayContent);
         mAnimationBackgroundSurface = new DimLayer(mService, this, displayContent);
-
-        for (int taskNdx = 0; taskNdx < mTasks.size(); ++taskNdx) {
-            Task task = mTasks.get(taskNdx);
-            displayContent.addTask(task, true);
-        }
     }
 
-    void detach() {
+    void detachDisplay() {
         EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
+        for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
+            mService.tmpRemoveTaskWindowsLocked(mTasks.get(taskNdx));
+        }
         mAnimationBackgroundSurface.destroySurface();
         mAnimationBackgroundSurface = null;
         mDimLayer.destroySurface();
@@ -365,6 +365,17 @@
             mDimLayer.printTo(prefix, pw);
             pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator);
         }
+        if (!mExitingAppTokens.isEmpty()) {
+            pw.println();
+            pw.println("  Exiting application tokens:");
+            for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
+                WindowToken token = mExitingAppTokens.get(i);
+                pw.print("  Exiting App #"); pw.print(i);
+                pw.print(' '); pw.print(token);
+                pw.println(':');
+                token.dump(pw, "    ");
+            }
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index b4285c6..15f8af0 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -151,14 +151,33 @@
     }
 
     private void updateAppWindowsLocked(int displayId) {
-        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
-        final ArrayList<Task> tasks = displayContent.getTasks();
-        final int numTasks = tasks.size();
-        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
-            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
-            final int numTokens = tokens.size();
-            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
-                final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
+        ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks();
+        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = stacks.get(stackNdx);
+            final ArrayList<Task> tasks = stack.getTasks();
+            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                    final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
+                    final boolean wasAnimating = appAnimator.animation != null
+                            && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
+                    if (appAnimator.stepAnimationLocked(mCurrentTime)) {
+                        mAnimating = true;
+                    } else if (wasAnimating) {
+                        // stopped animating, do one more pass through the layout
+                        setAppLayoutChanges(appAnimator,
+                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
+                                "appToken " + appAnimator.mAppToken + " done");
+                        if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
+                                "updateWindowsApps...: done animating " + appAnimator.mAppToken);
+                    }
+                }
+            }
+
+            final AppTokenList exitingAppTokens = stack.mExitingAppTokens;
+            final int NEAT = exitingAppTokens.size();
+            for (int i = 0; i < NEAT; i++) {
+                final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
                 final boolean wasAnimating = appAnimator.animation != null
                         && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
                 if (appAnimator.stepAnimationLocked(mCurrentTime)) {
@@ -166,29 +185,12 @@
                 } else if (wasAnimating) {
                     // stopped animating, do one more pass through the layout
                     setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                            "appToken " + appAnimator.mAppToken + " done");
+                        "exiting appToken " + appAnimator.mAppToken + " done");
                     if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
-                            "updateWindowsApps...: done animating " + appAnimator.mAppToken);
+                            "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
                 }
             }
         }
-
-        final AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
-        final int NEAT = exitingAppTokens.size();
-        for (int i = 0; i < NEAT; i++) {
-            final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
-            final boolean wasAnimating = appAnimator.animation != null
-                    && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
-            if (appAnimator.stepAnimationLocked(mCurrentTime)) {
-                mAnimating = true;
-            } else if (wasAnimating) {
-                // stopped animating, do one more pass through the layout
-                setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                    "exiting appToken " + appAnimator.mAppToken + " done");
-                if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
-                        "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
-            }
-        }
     }
 
     private void updateWindowsLocked(final int displayId) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2cd8bb1..6f6b67e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -598,6 +598,9 @@
     final WindowAnimator mAnimator;
 
     SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
+
+    /** All of the TaskStacks in the window manager, unordered. For an ordered list call
+     * DisplayContent.getStacks(). */
     SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
 
     private final PointerEventDispatcher mPointerEventDispatcher;
@@ -4554,13 +4557,12 @@
                         TAG, "Removing app " + wtoken + " delayed=" + delayed
                         + " animation=" + wtoken.mAppAnimator.animation
                         + " animating=" + wtoken.mAppAnimator.animating);
-                final Task task = mTaskIdToTask.get(wtoken.groupId);
-                DisplayContent displayContent = task.getDisplayContent();
-                if (displayContent != null && delayed) {
+                final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
+                if (delayed) {
                     // set the token aside because it has an active animation to be finished
                     if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
                             "removeAppToken make exiting: " + wtoken);
-                    displayContent.mExitingAppTokens.add(wtoken);
+                    stack.mExitingAppTokens.add(wtoken);
                 } else {
                     // Make sure there is no animation running on this token,
                     // so any windows associated with it will be removed as
@@ -4641,17 +4643,19 @@
     }
 
     void dumpAppTokensLocked() {
-        final int numDisplays = mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-            Slog.v(TAG, "  Display " + displayContent.getDisplayId());
-            final ArrayList<Task> tasks = displayContent.getTasks();
-            int i = displayContent.numTokens();
-            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
-                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
-                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
-                    final AppWindowToken wtoken = tokens.get(tokenNdx);
-                    Slog.v(TAG, "  #" + --i + ": " + wtoken.token);
+        final int numStacks = mStackIdToStack.size();
+        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
+            Slog.v(TAG, "  Stack #" + stack.mStackId + " tasks from bottom to top:");
+            final ArrayList<Task> tasks = stack.getTasks();
+            final int numTasks = tasks.size();
+            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+                final Task task = tasks.get(taskNdx);
+                Slog.v(TAG, "    Task #" + task.taskId + " activities from bottom to top:");
+                AppTokenList tokens = task.mAppTokens;
+                final int numTokens = tokens.size();
+                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
+                    Slog.v(TAG, "      activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token);
                 }
             }
         }
@@ -4914,7 +4918,7 @@
                 final DisplayContent displayContent = stack.getDisplayContent();
                 if (displayContent != null) {
                     displayContent.detachStack(stack);
-                    stack.detach();
+                    stack.detachDisplay();
                 }
             }
         }
@@ -5243,7 +5247,7 @@
             final int numDisplays = mDisplayContents.size();
             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-                displayContent.switchUserStacks(oldUserId, newUserId);
+                displayContent.switchUserStacks(newUserId);
                 rebuildAppWindowListLocked(displayContent);
             }
             performLayoutAndPlaceSurfacesLocked();
@@ -7396,15 +7400,18 @@
                 case APP_FREEZE_TIMEOUT: {
                     synchronized (mWindowMap) {
                         Slog.w(TAG, "App freeze timeout expired.");
-                        DisplayContent displayContent = getDefaultDisplayContentLocked();
-                        final ArrayList<Task> tasks = displayContent.getTasks();
-                        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
-                            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
-                            for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
-                                AppWindowToken tok = tokens.get(tokenNdx);
-                                if (tok.mAppAnimator.freezingScreen) {
-                                    Slog.w(TAG, "Force clearing freeze: " + tok);
-                                    unsetAppFreezingScreenLocked(tok, true, true);
+                        final int numStacks = mStackIdToStack.size();
+                        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+                            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
+                            final ArrayList<Task> tasks = stack.getTasks();
+                            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+                                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+                                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                                    AppWindowToken tok = tokens.get(tokenNdx);
+                                    if (tok.mAppAnimator.freezingScreen) {
+                                        Slog.w(TAG, "Force clearing freeze: " + tok);
+                                        unsetAppFreezingScreenLocked(tok, true, true);
+                                    }
                                 }
                             }
                         }
@@ -8014,21 +8021,27 @@
         // in the main app list, but still have windows shown.  We put them
         // in the back because now that the animation is over we no longer
         // will care about them.
-        AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
-        int NT = exitingAppTokens.size();
-        for (int j=0; j<NT; j++) {
-            i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
+        final ArrayList<TaskStack> stacks = displayContent.getStacks();
+        final int numStacks = stacks.size();
+        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+            AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
+            int NT = exitingAppTokens.size();
+            for (int j = 0; j < NT; j++) {
+                i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
+            }
         }
 
         // And add in the still active app tokens in Z order.
-        final ArrayList<Task> tasks = displayContent.getTasks();
-        final int numTasks = tasks.size();
-        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
-            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
-            final int numTokens = tokens.size();
-            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
-                final AppWindowToken wtoken = tokens.get(tokenNdx);
-                i = reAddAppWindowsLocked(displayContent, i, wtoken);
+        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
+            final int numTasks = tasks.size();
+            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+                final int numTokens = tokens.size();
+                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
+                    final AppWindowToken wtoken = tokens.get(tokenNdx);
+                    i = reAddAppWindowsLocked(displayContent, i, wtoken);
+                }
             }
         }
 
@@ -8703,15 +8716,14 @@
 
         mAppTransition.setIdle();
         // Restore window app tokens to the ActivityManager views
-        final DisplayContent displayContent = getDefaultDisplayContentLocked();
-        final ArrayList<Task> tasks = displayContent.getTasks();
-        final int numTasks = tasks.size();
-        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
-            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
-            final int numTokens = tokens.size();
-            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
-                final AppWindowToken wtoken = tokens.get(tokenNdx);
-                wtoken.sendingToBottom = false;
+        ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
+        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
+            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                    tokens.get(tokenNdx).sendingToBottom = false;
+                }
             }
         }
         rebuildAppWindowListLocked();
@@ -8865,7 +8877,7 @@
         }
     }
 
-    private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) {
+    private void handleFlagDimBehind(WindowState w) {
         final WindowManager.LayoutParams attrs = w.mAttrs;
         if ((attrs.flags & FLAG_DIM_BEHIND) != 0
                 && w.isDisplayedLw()
@@ -8883,22 +8895,23 @@
     private void updateAllDrawnLocked(DisplayContent displayContent) {
         // See if any windows have been drawn, so they (and others
         // associated with them) can now be shown.
-        final ArrayList<Task> tasks = displayContent.getTasks();
-        final int numTasks = tasks.size();
-        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
-            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
-            final int numTokens = tokens.size();
-            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
-                final AppWindowToken wtoken = tokens.get(tokenNdx);
-                if (!wtoken.allDrawn) {
-                    int numInteresting = wtoken.numInterestingWindows;
-                    if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
-                        if (DEBUG_VISIBILITY) Slog.v(TAG,
-                                "allDrawn: " + wtoken
-                                + " interesting=" + numInteresting
-                                + " drawn=" + wtoken.numDrawnWindows);
-                        wtoken.allDrawn = true;
-                        mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
+        ArrayList<TaskStack> stacks = displayContent.getStacks();
+        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
+            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                    final AppWindowToken wtoken = tokens.get(tokenNdx);
+                    if (!wtoken.allDrawn) {
+                        int numInteresting = wtoken.numInterestingWindows;
+                        if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
+                            if (DEBUG_VISIBILITY) Slog.v(TAG,
+                                    "allDrawn: " + wtoken
+                                    + " interesting=" + numInteresting
+                                    + " drawn=" + wtoken.numDrawnWindows);
+                            wtoken.allDrawn = true;
+                            mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
+                        }
                     }
                 }
             }
@@ -8929,10 +8942,14 @@
             for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
                 displayContent.mExitingTokens.get(i).hasVisible = false;
             }
+        }
 
+        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
             // Initialize state of exiting applications.
-            for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) {
-                displayContent.mExitingAppTokens.get(i).hasVisible = false;
+            final AppTokenList exitingAppTokens =
+                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
+            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                exitingAppTokens.get(tokenNdx).hasVisible = false;
             }
         }
 
@@ -9065,7 +9082,7 @@
                     }
 
                     if (!stack.testDimmingTag()) {
-                        handleFlagDimBehind(w, innerDw, innerDh);
+                        handleFlagDimBehind(w);
                     }
 
                     if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
@@ -9345,9 +9362,13 @@
                     }
                 }
             }
+        }
 
-            // Time to remove any exiting applications?
-            AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
+        // Time to remove any exiting applications?
+        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
+            // Initialize state of exiting applications.
+            final AppTokenList exitingAppTokens =
+                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
             for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
                 AppWindowToken token = exitingAppTokens.get(i);
                 if (!token.hasVisible && !mClosingApps.contains(token)) {