Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc548483 authored by Craig Mautner's avatar Craig Mautner
Browse files

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
parent df88d730
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -170,7 +170,7 @@ public class DimLayer {
            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();
+30 −94
Original line number Diff line number Diff line
@@ -22,12 +22,10 @@ import static com.android.server.wm.WindowManagerService.TAG;

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 @@ class DisplayContent {

    /** 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 @@ class DisplayContent {
    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 @@ class DisplayContent {
    /** 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 @@ class DisplayContent {
        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;
        mTmpTaskHistory.clear();
        final int numStacks = mStacks.size();
        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
            mTmpTaskHistory.addAll(mStacks.get(stackNdx).getTasks());
        }

    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;
                }
            }
        }

        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 @@ class DisplayContent {
        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 @@ class DisplayContent {
    }

    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 @@ class DisplayContent {
        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 @@ class DisplayContent {
        }
    }

    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 @@ class DisplayContent {
            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("  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 @@ class DisplayContent {
                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();
    }

+19 −8
Original line number Diff line number Diff line
@@ -67,6 +67,9 @@ public class TaskStack {
     * 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 @@ public class TaskStack {
        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 @@ public class TaskStack {
        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 @@ public class TaskStack {
        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 @@ public class TaskStack {
            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
+29 −27
Original line number Diff line number Diff line
@@ -151,13 +151,13 @@ public class WindowAnimator {
    }

    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) {
        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;
            final int numTokens = tokens.size();
            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
                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;
@@ -165,7 +165,8 @@ public class WindowAnimator {
                        mAnimating = true;
                    } else if (wasAnimating) {
                        // stopped animating, do one more pass through the layout
                    setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
                        setAppLayoutChanges(appAnimator,
                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
                                "appToken " + appAnimator.mAppToken + " done");
                        if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
                                "updateWindowsApps...: done animating " + appAnimator.mAppToken);
@@ -173,7 +174,7 @@ public class WindowAnimator {
                }
            }

        final AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
            final AppTokenList exitingAppTokens = stack.mExitingAppTokens;
            final int NEAT = exitingAppTokens.size();
            for (int i = 0; i < NEAT; i++) {
                final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
@@ -190,6 +191,7 @@ public class WindowAnimator {
                }
            }
        }
    }

    private void updateWindowsLocked(final int displayId) {
        ++mAnimTransactionSequence;
+90 −69
Original line number Diff line number Diff line
@@ -598,6 +598,9 @@ public class WindowManagerService extends IWindowManager.Stub
    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 @@ public class WindowManagerService extends IWindowManager.Stub
                        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 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    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 @@ public class WindowManagerService extends IWindowManager.Stub
                final DisplayContent displayContent = stack.getDisplayContent();
                if (displayContent != null) {
                    displayContent.detachStack(stack);
                    stack.detach();
                    stack.detachDisplay();
                }
            }
        }
@@ -5243,7 +5247,7 @@ public class WindowManagerService extends IWindowManager.Stub
            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,8 +7400,10 @@ public class WindowManagerService extends IWindowManager.Stub
                case APP_FREEZE_TIMEOUT: {
                    synchronized (mWindowMap) {
                        Slog.w(TAG, "App freeze timeout expired.");
                        DisplayContent displayContent = getDefaultDisplayContentLocked();
                        final ArrayList<Task> tasks = displayContent.getTasks();
                        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) {
@@ -7409,6 +7415,7 @@ public class WindowManagerService extends IWindowManager.Stub
                                }
                            }
                        }
                    }
                    break;
                }

@@ -8014,14 +8021,19 @@ public class WindowManagerService extends IWindowManager.Stub
        // 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;
        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();
        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;
@@ -8031,6 +8043,7 @@ public class WindowManagerService extends IWindowManager.Stub
                    i = reAddAppWindowsLocked(displayContent, i, wtoken);
                }
            }
        }

        i -= lastBelow;
        if (i != numRemoved) {
@@ -8703,15 +8716,14 @@ public class WindowManagerService extends IWindowManager.Stub

        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) {
        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;
            final int numTokens = tokens.size();
            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
                final AppWindowToken wtoken = tokens.get(tokenNdx);
                wtoken.sendingToBottom = false;
                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
                    tokens.get(tokenNdx).sendingToBottom = false;
                }
            }
        }
        rebuildAppWindowListLocked();
@@ -8865,7 +8877,7 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    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,12 +8895,12 @@ public class WindowManagerService extends IWindowManager.Stub
    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) {
        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;
            final int numTokens = tokens.size();
            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
                    final AppWindowToken wtoken = tokens.get(tokenNdx);
                    if (!wtoken.allDrawn) {
                        int numInteresting = wtoken.numInterestingWindows;
@@ -8904,6 +8916,7 @@ public class WindowManagerService extends IWindowManager.Stub
                }
            }
        }
    }

    // "Something has changed!  Let's make it correct now."
    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
@@ -8929,10 +8942,14 @@ public class WindowManagerService extends IWindowManager.Stub
            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 @@ public class WindowManagerService extends IWindowManager.Stub
                    }

                    if (!stack.testDimmingTag()) {
                        handleFlagDimBehind(w, innerDw, innerDh);
                        handleFlagDimBehind(w);
                    }

                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
@@ -9345,9 +9362,13 @@ public class WindowManagerService extends IWindowManager.Stub
                    }
                }
            }
        }

        // Time to remove any exiting applications?
            AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
        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)) {