Moved rebuilding of display WindowList to DisplayContent

Some of this is also in WindowContainer and its children.
However, I hope we can remove the concept of window list in
the future.

Bug: 30060889
Change-Id: I9e531327643c28a0ba35baa812b9c2942993d7b7
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index e176c44..9d29a22 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -984,6 +984,11 @@
         }
     }
 
+    @Override
+    void onAppTransitionDone() {
+        sendingToBottom = false;
+    }
+
     /**
      * We override because this class doesn't want its children affecting its reported orientation
      * in anyway.
@@ -997,6 +1002,14 @@
     }
 
     @Override
+    int rebuildWindowList(DisplayContent dc, int addIndex) {
+        if (mIsExiting && !waitingForReplacement()) {
+            return addIndex;
+        }
+        return super.rebuildWindowList(dc, addIndex);
+    }
+
+    @Override
     AppWindowToken asAppWindowToken() {
         // I am an app window token!
         return this;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b18f273..155c46f 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -45,6 +45,7 @@
 import android.graphics.Region;
 import android.graphics.Region.Op;
 import android.hardware.display.DisplayManagerInternal;
+import android.os.Debug;
 import android.util.DisplayMetrics;
 import android.util.Slog;
 import android.view.Display;
@@ -52,9 +53,12 @@
 import android.view.IWindow;
 import android.view.Surface;
 import android.view.animation.Animation;
+import com.android.internal.util.FastPrintWriter;
 
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 class DisplayContentList extends ArrayList<DisplayContent> {
 }
@@ -87,7 +91,7 @@
     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
 
     Rect mBaseDisplayRect = new Rect();
-    Rect mContentRect = new Rect();
+    private Rect mContentRect = new Rect();
 
     // Accessed directly by all users.
     boolean layoutNeeded;
@@ -109,7 +113,7 @@
     TaskTapPointerEventListener mTapDetector;
 
     /** Detect user tapping outside of current focused stack bounds .*/
-    Region mTouchExcludeRegion = new Region();
+    private Region mTouchExcludeRegion = new Region();
 
     /** Save allocating when calculating rects */
     private final Rect mTmpRect = new Rect();
@@ -117,7 +121,7 @@
     private final Region mTmpRegion = new Region();
 
     /** For gathering Task objects in order. */
-    final ArrayList<Task> mTmpTaskHistory = new ArrayList<Task>();
+    private final ArrayList<Task> mTmpTaskHistory = new ArrayList<Task>();
 
     final WindowManagerService mService;
 
@@ -130,6 +134,9 @@
 
     final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
 
+    /** Used when rebuilding window list to keep track of windows that have been removed. */
+    private WindowState[] mRebuildTmp = new WindowState[20];
+
     /**
      * @param display May not be null.
      * @param service You know.
@@ -215,6 +222,15 @@
         return null;
     }
 
+    void onAppTransitionDone() {
+        for (int i = mStacks.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mStacks.get(i);
+            stack.onAppTransitionDone();
+        }
+
+        rebuildAppWindowList();
+    }
+
     int getOrientation() {
         // TODO: Most of the logic here can be removed once this class is converted to use
         // WindowContainer which has an abstract implementation of getOrientation that
@@ -515,6 +531,8 @@
         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
             mStacks.get(stackNdx).switchUser();
         }
+
+        rebuildAppWindowList();
     }
 
     void resetAnimationBackgroundAnimator() {
@@ -675,7 +693,11 @@
 
     @Override
     public String toString() {
-        return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks;
+        return getName() + " stacks=" + mStacks;
+    }
+
+    String getName() {
+        return "Display " + mDisplayId + " info=" + mDisplayInfo;
     }
 
     /**
@@ -695,9 +717,7 @@
         return (stack != null && stack.isVisible(true /* ignoreKeyguard */)) ? stack : null;
     }
 
-    /**
-     * Find the visible, touch-deliverable window under the given point
-     */
+    /** Find the visible, touch-deliverable window under the given point */
     WindowState getTouchableWinAtPointLocked(float xf, float yf) {
         WindowState touchedWin = null;
         final int x = (int) xf;
@@ -996,6 +1016,98 @@
         }
     }
 
+    /**
+     * Z-orders the display window list so that:
+     * <ul>
+     * <li>Any windows that are currently below the wallpaper window stay below the wallpaper
+     *      window.
+     * <li>Exiting application windows are at the bottom, but above the wallpaper window.
+     * <li>All other application windows are above the exiting application windows and ordered based
+     *      on the ordering of their stacks and tasks on the display.
+     * <li>Non-application windows are at the very top.
+     * </ul>
+     * <p>
+     * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window
+     *       surface layering is done in {@link WindowLayersController}.
+     */
+    void rebuildAppWindowList() {
+        int count = mWindows.size();
+        int i;
+        int lastBelow = -1;
+        int numRemoved = 0;
+
+        if (mRebuildTmp.length < count) {
+            mRebuildTmp = new WindowState[count + 10];
+        }
+
+        // First remove all existing app windows.
+        i = 0;
+        while (i < count) {
+            final WindowState w = mWindows.get(i);
+            if (w.mAppToken != null) {
+                final WindowState win = mWindows.remove(i);
+                win.mRebuilding = true;
+                mRebuildTmp[numRemoved] = win;
+                mService.mWindowsChanged = true;
+                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
+                count--;
+                numRemoved++;
+                continue;
+            } else if (lastBelow == i-1) {
+                if (w.mAttrs.type == TYPE_WALLPAPER) {
+                    lastBelow = i;
+                }
+            }
+            i++;
+        }
+
+        // Keep whatever windows were below the app windows still below, by skipping them.
+        lastBelow++;
+        i = lastBelow;
+
+        // First add all of the exiting app tokens...  these are no longer 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.
+        final int numStacks = mStacks.size();
+        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+            AppTokenList exitingAppTokens = mStacks.get(stackNdx).mExitingAppTokens;
+            int NT = exitingAppTokens.size();
+            for (int j = 0; j < NT; j++) {
+                i = exitingAppTokens.get(j).rebuildWindowList(this, i);
+            }
+        }
+
+        // And add in the still active app tokens in Z order.
+        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+            i = mStacks.get(stackNdx).rebuildWindowList(this, i);
+        }
+
+        i -= lastBelow;
+        if (i != numRemoved) {
+            layoutNeeded = true;
+            Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved
+                    + " windows but added " + i + " rebuildAppWindowListLocked() "
+                    + " callers=" + Debug.getCallers(10));
+            for (i = 0; i < numRemoved; i++) {
+                WindowState ws = mRebuildTmp[i];
+                if (ws.mRebuilding) {
+                    StringWriter sw = new StringWriter();
+                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
+                    ws.dump(pw, "", true);
+                    pw.flush();
+                    Slog.w(TAG_WM, "This window was lost: " + ws);
+                    Slog.w(TAG_WM, sw.toString());
+                    ws.mWinAnimator.destroySurfaceLocked();
+                }
+            }
+            Slog.w(TAG_WM, "Current app token list:");
+            dumpChildrenNames();
+            Slog.w(TAG_WM, "Final window list:");
+            dumpWindows();
+        }
+        Arrays.fill(mRebuildTmp, null);
+    }
+
     /** Return the list of Windows on this display associated with the input token. */
     WindowList getTokenWindowsOnDisplay(WindowToken token) {
         final WindowList windowList = new WindowList();
@@ -1085,6 +1197,33 @@
         return -1;
     }
 
+    private void dumpChildrenNames() {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
+        dumpChildrenNames(pw, "  ");
+    }
+
+    private void dumpChildrenNames(PrintWriter pw, String prefix) {
+        final String childPrefix = prefix + prefix;
+        for (int j = mStacks.size() - 1; j >= 0; j--) {
+            final TaskStack stack = mStacks.get(j);
+            pw.println("#" + j + " " + getName());
+            stack.dumpChildrenNames(pw, childPrefix);
+        }
+    }
+
+    private void dumpWindows() {
+        final int numDisplays = mService.mDisplayContents.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
+            Slog.v(TAG_WM, " Display #" + displayContent.getDisplayId());
+            final WindowList windows = displayContent.getWindowList();
+            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+                Slog.v(TAG_WM, "  #" + winNdx + ": " + windows.get(winNdx));
+            }
+        }
+    }
+
     static final class GetWindowOnDisplaySearchResults {
         boolean reachedToken;
         WindowState foundWindow;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 154bdf5..5c6cb6b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -684,11 +684,27 @@
         return false;
     }
 
+    void onAppTransitionDone() {
+        for (int i = mAppTokens.size() - 1; i >= 0; --i) {
+            final AppWindowToken token = mAppTokens.get(i);
+            token.onAppTransitionDone();
+        }
+    }
+
     // TODO: Use WindowContainer.compareTo() once everything is using WindowContainer
     boolean isFirstGreaterThanSecond(AppWindowToken first, AppWindowToken second) {
         return mAppTokens.indexOf(first) > mAppTokens.indexOf(second);
     }
 
+    int rebuildWindowList(DisplayContent dc, int addIndex) {
+        final int count = mAppTokens.size();
+        for (int i = 0; i < count; i++) {
+            final AppWindowToken token = mAppTokens.get(i);
+            addIndex = token.rebuildWindowList(dc, addIndex);
+        }
+        return addIndex;
+    }
+
     void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
             DisplayContent.GetWindowOnDisplaySearchResults result) {
         for (int i = mAppTokens.size() - 1; i >= 0; --i) {
@@ -761,11 +777,24 @@
         return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
     }
 
+    String getName() {
+        return toShortString();
+    }
+
     @Override
     public String toShortString() {
         return "Task=" + mTaskId;
     }
 
+    void dumpChildrenNames(PrintWriter pw, String prefix) {
+        final String childPrefix = prefix + prefix;
+        for (int i = mAppTokens.size() - 1; i >= 0; --i) {
+            final AppWindowToken token = mAppTokens.get(i);
+            pw.println("#" + i + " " + getName());
+            token.dumpChildrenNames(pw, childPrefix);
+        }
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         final String doublePrefix = prefix + "  ";
 
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 505cb56..25f3c0a 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1083,6 +1083,15 @@
         return mMinimizeAmount != 0f;
     }
 
+    void dumpChildrenNames(PrintWriter pw, String prefix) {
+        final String childPrefix = prefix + prefix;
+        for (int j = mTasks.size() - 1; j >= 0; j--) {
+            final Task task = mTasks.get(j);
+            pw.println("#" + j + " " + getName());
+            task.dumpChildrenNames(pw, childPrefix);
+        }
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "mStackId=" + mStackId);
         pw.println(prefix + "mDeferDetach=" + mDeferDetach);
@@ -1152,6 +1161,10 @@
         return "{stackId=" + mStackId + " tasks=" + mTasks + "}";
     }
 
+    String getName() {
+        return toShortString();
+    }
+
     @Override
     public String toShortString() {
         return "Stack=" + mStackId;
@@ -1309,6 +1322,13 @@
         }
     }
 
+    void onAppTransitionDone() {
+        for (int i = mTasks.size() - 1; i >= 0; --i) {
+            final Task task = mTasks.get(i);
+            task.onAppTransitionDone();
+        }
+    }
+
     // TODO: Use WindowContainer.compareTo() once everything is using WindowContainer
     boolean isFirstGreaterThanSecond(AppWindowToken first, AppWindowToken second) {
         final Task firstTask = first.mTask;
@@ -1320,6 +1340,15 @@
         return mTasks.indexOf(first) > mTasks.indexOf(second);
     }
 
+    int rebuildWindowList(DisplayContent dc, int addIndex) {
+        final int count = mTasks.size();
+        for (int i = 0; i < count; i++) {
+            final Task task = mTasks.get(i);
+            addIndex = task.rebuildWindowList(dc, addIndex);
+        }
+        return addIndex;
+    }
+
     void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
             DisplayContent.GetWindowOnDisplaySearchResults result) {
         for (int i = mTasks.size() - 1; i >= 0; --i) {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 176663d..eaf6aaa 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -18,6 +18,7 @@
 
 import android.annotation.CallSuper;
 
+import java.io.PrintWriter;
 import java.util.Comparator;
 import java.util.LinkedList;
 
@@ -250,6 +251,13 @@
         return mChildren.isEmpty() ? this : mChildren.peekLast();
     }
 
+    void onAppTransitionDone() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            wc.onAppTransitionDone();
+        }
+    }
+
     void setOrientation(int orientation) {
         mOrientation = orientation;
     }
@@ -317,6 +325,22 @@
     }
 
     /**
+     * Rebuilds the WindowList for the input display content.
+     * @param dc The display content to rebuild the window list for.
+     * @param addIndex The index in the window list to add the next entry to.
+     * @return The next index in the window list to.
+     */
+    // TODO: Hoping we can get rid of WindowList so this method wouldn't be needed.
+    int rebuildWindowList(DisplayContent dc, int addIndex) {
+        final int count = mChildren.size();
+        for (int i = 0; i < count; i++) {
+            final WindowContainer wc = mChildren.get(i);
+            addIndex = wc.rebuildWindowList(dc, addIndex);
+        }
+        return addIndex;
+    }
+
+    /**
      * Returns -1, 0, or 1 depending on if the input container is greater than, equal to, or lesser
      * than the input container in terms of z-order.
      */
@@ -376,4 +400,22 @@
             current = current.mParent;
         } while (current != null);
     }
+
+    /**
+     * Dumps the names of this container children in the input print writer indenting each
+     * level with the input prefix.
+     */
+    void dumpChildrenNames(PrintWriter pw, String prefix) {
+        final String childPrefix = prefix + prefix;
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            pw.println("#" + i + " " + getName());
+            wc.dumpChildrenNames(pw, childPrefix);
+        }
+    }
+
+    String getName() {
+        return toString();
+    }
+
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 85cbd72..39544c0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -497,12 +497,6 @@
     Runnable mWaitingForDrawnCallback;
 
     /**
-     * Used when rebuilding window list to keep track of windows that have
-     * been removed.
-     */
-    WindowState[] mRebuildTmp = new WindowState[20];
-
-    /**
      * Stores for each user whether screencapture is disabled
      * This array is essentially a cache for all userId for
      * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
@@ -3805,42 +3799,12 @@
         mH.sendMessage(m);
     }
 
-    void dumpAppTokensLocked() {
-        final int numStacks = mStackIdToStack.size();
-        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
-            Slog.v(TAG_WM, "  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_WM, "    Task #" + task.mTaskId + " activities from bottom to top:");
-                AppTokenList tokens = task.mAppTokens;
-                final int numTokens = tokens.size();
-                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
-                    Slog.v(TAG_WM, "      activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token);
-                }
-            }
-        }
-    }
-
-    void dumpWindowsLocked() {
-        final int numDisplays = mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-            Slog.v(TAG_WM, " Display #" + displayContent.getDisplayId());
-            final WindowList windows = displayContent.getWindowList();
-            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-                Slog.v(TAG_WM, "  #" + winNdx + ": " + windows.get(winNdx));
-            }
-        }
-    }
-
-    void moveStackWindowsLocked(DisplayContent displayContent) {
+    /** Rebuilds the input display's window list and does a relayout if something changed. */
+    private void rebuildAppWindowsAndLayoutIfNeededLocked(DisplayContent displayContent) {
         final WindowList windows = displayContent.getWindowList();
         mTmpWindows.addAll(windows);
 
-        rebuildAppWindowListLocked(displayContent);
+        displayContent.rebuildAppWindowList();
 
         // Set displayContent.layoutNeeded if window order changed.
         final int tmpSize = mTmpWindows.size();
@@ -3904,7 +3868,7 @@
                 if (mAppTransition.isTransitionSet()) {
                     task.setSendingToBottom(false);
                 }
-                moveStackWindowsLocked(displayContent);
+                rebuildAppWindowsAndLayoutIfNeededLocked(displayContent);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -3926,7 +3890,7 @@
                 if (mAppTransition.isTransitionSet()) {
                     task.setSendingToBottom(true);
                 }
-                moveStackWindowsLocked(stack.getDisplayContent());
+                rebuildAppWindowsAndLayoutIfNeededLocked(stack.getDisplayContent());
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -4692,7 +4656,6 @@
             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
                 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
                 displayContent.switchUserStacks();
-                rebuildAppWindowListLocked(displayContent);
             }
             mWindowPlacerLocked.performSurfacePlacement();
 
@@ -8236,102 +8199,6 @@
         return win;
     }
 
-    final void rebuildAppWindowListLocked() {
-        rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
-    }
-
-    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
-        final WindowList windows = displayContent.getWindowList();
-        int NW = windows.size();
-        int i;
-        int lastBelow = -1;
-        int numRemoved = 0;
-
-        if (mRebuildTmp.length < NW) {
-            mRebuildTmp = new WindowState[NW+10];
-        }
-
-        // First remove all existing app windows.
-        i=0;
-        while (i < NW) {
-            WindowState w = windows.get(i);
-            if (w.mAppToken != null) {
-                WindowState win = windows.remove(i);
-                win.mRebuilding = true;
-                mRebuildTmp[numRemoved] = win;
-                mWindowsChanged = true;
-                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
-                NW--;
-                numRemoved++;
-                continue;
-            } else if (lastBelow == i-1) {
-                if (w.mAttrs.type == TYPE_WALLPAPER) {
-                    lastBelow = i;
-                }
-            }
-            i++;
-        }
-
-        // Keep whatever windows were below the app windows still below, by skipping them.
-        lastBelow++;
-        i = lastBelow;
-
-        // First add all of the exiting app tokens...  these are no longer 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.
-        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 = exitingAppTokens.get(j).reAddAppWindows(displayContent, i);
-            }
-        }
-
-        // And add in the still active app tokens in Z order.
-        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);
-                    if (wtoken.mIsExiting && !wtoken.waitingForReplacement()) {
-                        continue;
-                    }
-                    i = wtoken.reAddAppWindows(displayContent, i);
-                }
-            }
-        }
-
-        i -= lastBelow;
-        if (i != numRemoved) {
-            displayContent.layoutNeeded = true;
-            Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed "
-                    + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() "
-                    + " callers=" + Debug.getCallers(10));
-            for (i = 0; i < numRemoved; i++) {
-                WindowState ws = mRebuildTmp[i];
-                if (ws.mRebuilding) {
-                    StringWriter sw = new StringWriter();
-                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
-                    ws.dump(pw, "", true);
-                    pw.flush();
-                    Slog.w(TAG_WM, "This window was lost: " + ws);
-                    Slog.w(TAG_WM, sw.toString());
-                    ws.mWinAnimator.destroySurfaceLocked();
-                }
-            }
-            Slog.w(TAG_WM, "Current app token list:");
-            dumpAppTokensLocked();
-            Slog.w(TAG_WM, "Final window list:");
-            dumpWindowsLocked();
-        }
-        Arrays.fill(mRebuildTmp, null);
-    }
-
     void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
         // If the screen is currently frozen or off, then keep
         // it frozen/off until this window draws at its new
@@ -8368,27 +8235,15 @@
 
         mWallpaperControllerLocked.hideDeferredWallpapersIfNeeded();
 
-        // Restore window app tokens to the ActivityManager views
-        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();
+        getDefaultDisplayContentLocked().onAppTransitionDone();
 
         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
                 "Wallpaper layer changed: assigning layers + relayout");
         moveInputMethodWindowsIfNeededLocked(true);
         mWindowPlacerLocked.mWallpaperMayChange = true;
-        // Since the window list has been rebuilt, focus might
-        // have to be recomputed since the actual order of windows
-        // might have changed again.
+        // Since the window list has been rebuilt, focus might have to be recomputed since the
+        // actual order of windows might have changed again.
         mFocusMayChange = true;
 
         return changes;
@@ -8398,30 +8253,25 @@
         final WindowStateAnimator winAnimator = w.mWinAnimator;
         if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq && !w.isGoneForLayoutLw()) {
             final Task task = w.getTask();
-            // In the case of stack bound animations, the window frames
-            // will update (unlike other animations which just modifiy
-            // various transformation properties). We don't want to
-            // notify the client of frame changes in this case. Not only
-            // is it a lot of churn, but the frame may not correspond
-            // to the surface size or the onscreen area at various
-            // phases in the animation, and the client will become
-            // sad and confused.
+            // In the case of stack bound animations, the window frames will update (unlike other
+            // animations which just modify various transformation properties). We don't want to
+            // notify the client of frame changes in this case. Not only is it a lot of churn, but
+            // the frame may not correspond to the surface size or the onscreen area at various
+            // phases in the animation, and the client will become sad and confused.
             if (task != null && task.mStack.getBoundsAnimating()) {
                 return;
             }
             w.setReportResizeHints();
             boolean configChanged = w.isConfigChanged();
             if (DEBUG_CONFIGURATION && configChanged) {
-                Slog.v(TAG_WM, "Win " + w + " config changed: "
-                        + mCurConfiguration);
+                Slog.v(TAG_WM, "Win " + w + " config changed: " + mCurConfiguration);
             }
             final boolean dragResizingChanged = w.isDragResizeChanged()
                     && !w.isDragResizingChangeReported();
 
-            if (localLOGV) Slog.v(TAG_WM, "Resizing " + w
-                    + ": configChanged=" + configChanged
-                    + " dragResizingChanged=" + dragResizingChanged
-                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
+            if (localLOGV) Slog.v(TAG_WM, "Resizing " + w + ": configChanged=" + configChanged
+                    + " dragResizingChanged=" + dragResizingChanged + " last=" + w.mLastFrame
+                    + " frame=" + w.mFrame);
 
             // We update mLastFrame always rather than in the conditional with the
             // last inset variables, because mFrameSizeChanged only tracks the
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 30e1929..a917011 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1935,7 +1935,7 @@
         if (mInputChannel != null) {
             throw new IllegalStateException("Window already has an input channel.");
         }
-        String name = makeInputChannelName();
+        String name = getName();
         InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
         mInputChannel = inputChannels[0];
         mClientChannel = inputChannels[1];
@@ -2843,6 +2843,8 @@
         region.op(mTmpRect, Region.Op.INTERSECT);
     }
 
+    // TODO: This is one reason why WindowList are bad...prime candidate for removal once we
+    // figure-out a good way to replace WindowList with WindowContainer hierarchy.
     WindowList getWindowList() {
         final DisplayContent displayContent = getDisplayContent();
         return displayContent == null ? null : displayContent.getWindowList();
@@ -3329,7 +3331,8 @@
         }
     }
 
-    String makeInputChannelName() {
+    @Override
+    String getName() {
         return Integer.toHexString(System.identityHashCode(this))
             + " " + getWindowTag();
     }
@@ -3743,6 +3746,16 @@
         return highestAnimLayer;
     }
 
+    @Override
+    int rebuildWindowList(DisplayContent dc, int addIndex) {
+        final DisplayContent winDisplayContent = getDisplayContent();
+        if (winDisplayContent == dc || winDisplayContent == null) {
+            mDisplayContent = dc;
+            return reAddWindow(addIndex);
+        }
+        return addIndex;
+    }
+
     // TODO: come-up with a better name for this method that represents what it does.
     // Or, it is probably not going to matter anyways if we are successful in getting rid of
     // the WindowList concept.
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 8bfcf52..f128cf9 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1079,7 +1079,8 @@
 
         mService.mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
 
-        mService.rebuildAppWindowListLocked();
+        final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
+        displayContent.rebuildAppWindowList();
 
         mWallpaperMayChange = false;
 
@@ -1103,7 +1104,6 @@
         }
         // Adjust wallpaper before we pull the lower/upper target, since pending changes
         // (like the clearAnimatingFlags() above) might affect wallpaper target result.
-        final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
         if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
                 mWallpaperControllerLocked.adjustWallpaperWindows()) {
             mService.mLayersController.assignLayersLocked(windows);
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 941a9a9..d1d612b 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -430,4 +430,9 @@
         }
         return stringName;
     }
+
+    @Override
+    String getName() {
+        return toString();
+    }
 }