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

Commit 481b54be authored by Craig Mautner's avatar Craig Mautner Committed by Android Git Automerger
Browse files

am dc548483: Move activities from DisplayContent to TaskStack

* commit 'dc548483':
  Move activities from DisplayContent to TaskStack
parents 2c764b20 dc548483
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)) {