Added RootWindowContainer

RootWindowContainer will be the root/head of the window hierarchy.
Also, moved all access of DisplayContent into RootWindowContainer.

Bug: 30060889
Test: Manual testing and existing tests still pass.
Change-Id: Icdf80a4c053578fb91221e6f2b672e197054a6bf
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 4d12ba9..2ae4b2a 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1055,7 +1055,7 @@
 
     @Override
     void updateAllDrawn(int displayId) {
-        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mService.mRoot.getDisplayContent(displayId);
 
         if (!allDrawn) {
             final int numInteresting = numInterestingWindows;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 1c83a9b..54e3058 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -432,7 +432,7 @@
         }
     }
 
-    void switchUserStacks() {
+    void switchUser() {
         final WindowList windows = getWindowList();
         for (int i = 0; i < windows.size(); i++) {
             final WindowState win = windows.get(i);
@@ -485,7 +485,8 @@
     void removeImmediately() {
         super.removeImmediately();
         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
-        mService.mDisplayContents.delete(mDisplayId);
+        // TODO: remove this line once RootWindowContainer is online.
+        mService.mRoot.mDisplayContents.delete(mDisplayId);
         mDimLayerController.close();
         if (mDisplayId == Display.DEFAULT_DISPLAY) {
             mService.unregisterPointerEventListener(mTapDetector);
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 535ce9d..a5387bd 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -165,7 +165,7 @@
         return 0; // abort dispatching
     }
 
-    private void addInputWindowHandleLw(final InputWindowHandle windowHandle) {
+    void addInputWindowHandle(final InputWindowHandle windowHandle) {
         if (mInputWindowHandles == null) {
             mInputWindowHandles = new InputWindowHandle[16];
         }
@@ -176,7 +176,7 @@
         mInputWindowHandles[mInputWindowHandleCount++] = windowHandle;
     }
 
-    private void addInputWindowHandleLw(final InputWindowHandle inputWindowHandle,
+    void addInputWindowHandle(final InputWindowHandle inputWindowHandle,
             final WindowState child, int flags, final int type, final boolean isVisible,
             final boolean hasFocus, final boolean hasWallpaper) {
         // Add a window to our list of input windows.
@@ -214,7 +214,7 @@
             Slog.d(TAG_WM, "addInputWindowHandle: "
                     + child + ", " + inputWindowHandle);
         }
-        addInputWindowHandleLw(inputWindowHandle);
+        addInputWindowHandle(inputWindowHandle);
     }
 
     private void clearInputWindowHandlesLw() {
@@ -241,9 +241,8 @@
         // As an optimization, we could try to prune the list of windows but this turns
         // out to be difficult because only the native code knows for sure which window
         // currently has touch focus.
-        boolean disableWallpaperTouchEvents = false;
 
-        // If there's a drag in flight, provide a pseudowindow to catch drag input
+        // If there's a drag in flight, provide a pseudo-window to catch drag input
         final boolean inDrag = (mService.mDragState != null);
         if (inDrag) {
             if (DEBUG_DRAG) {
@@ -251,7 +250,7 @@
             }
             final InputWindowHandle dragWindowHandle = mService.mDragState.getInputWindowHandle();
             if (dragWindowHandle != null) {
-                addInputWindowHandleLw(dragWindowHandle);
+                addInputWindowHandle(dragWindowHandle);
             } else {
                 Slog.w(TAG_WM, "Drag is in progress but there is no "
                         + "drag window handle.");
@@ -265,78 +264,15 @@
             }
             final InputWindowHandle dragWindowHandle = mService.mTaskPositioner.mDragWindowHandle;
             if (dragWindowHandle != null) {
-                addInputWindowHandleLw(dragWindowHandle);
+                addInputWindowHandle(dragWindowHandle);
             } else {
                 Slog.e(TAG_WM,
                         "Repositioning is in progress but there is no drag window handle.");
             }
         }
 
-        boolean addInputConsumerHandle = mService.mInputConsumer != null;
-
-        boolean addWallpaperInputConsumerHandle = mService.mWallpaperInputConsumer != null;
-
         // Add all windows on the default display.
-        final int numDisplays = mService.mDisplayContents.size();
-        final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            final WindowList windows = displayContent.getWindowList();
-            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-                final WindowState child = windows.get(winNdx);
-                final InputChannel inputChannel = child.mInputChannel;
-                final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
-                if (inputChannel == null || inputWindowHandle == null || child.mRemoved
-                        || child.isAdjustedForMinimizedDock()) {
-                    // Skip this window because it cannot possibly receive input.
-                    continue;
-                }
-                if (addInputConsumerHandle
-                        && inputWindowHandle.layer <= mService.mInputConsumer.mWindowHandle.layer) {
-                    addInputWindowHandleLw(mService.mInputConsumer.mWindowHandle);
-                    addInputConsumerHandle = false;
-                }
-
-                if (addWallpaperInputConsumerHandle) {
-                    if (child.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER &&
-                            child.isVisibleLw()) {
-                        // Add the wallpaper input consumer above the first visible wallpaper.
-                        addInputWindowHandleLw(mService.mWallpaperInputConsumer.mWindowHandle);
-                        addWallpaperInputConsumerHandle = false;
-                    }
-                }
-
-                final int flags = child.mAttrs.flags;
-                final int privateFlags = child.mAttrs.privateFlags;
-                final int type = child.mAttrs.type;
-
-                final boolean hasFocus = (child == mInputFocus);
-                final boolean isVisible = child.isVisibleLw();
-                if ((privateFlags
-                        & WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS)
-                            != 0) {
-                    disableWallpaperTouchEvents = true;
-                }
-                final boolean hasWallpaper = wallpaperController.isWallpaperTarget(child)
-                        && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0
-                        && !disableWallpaperTouchEvents;
-                final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
-
-                // If there's a drag in progress and 'child' is a potential drop target,
-                // make sure it's been told about the drag
-                if (inDrag && isVisible && onDefaultDisplay) {
-                    mService.mDragState.sendDragStartedIfNeededLw(child);
-                }
-
-                addInputWindowHandleLw(
-                        inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
-            }
-        }
-
-        if (addWallpaperInputConsumerHandle) {
-            // No visible wallpaper found, add the wallpaper input consumer at the end.
-            addInputWindowHandleLw(mService.mWallpaperInputConsumer.mWindowHandle);
-        }
+        mService.mRoot.updateInputWindows(this, mInputFocus, inDrag);
 
         // Send windows to native code.
         mService.mInputManager.setInputWindows(mInputWindowHandles);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
new file mode 100644
index 0000000..d119fb7a
--- /dev/null
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -0,0 +1,1419 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.app.AppOpsManager;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.Debug;
+import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.EventLog;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.InputChannel;
+import android.view.WindowManager;
+import com.android.internal.util.ArrayUtils;
+import com.android.server.EventLogTags;
+import com.android.server.input.InputWindowHandle;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN;
+import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
+import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
+import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
+import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
+import static com.android.server.wm.WindowManagerService.logSurface;
+import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
+import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
+import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;
+import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
+
+/** Root {@link WindowContainer} for the device. */
+// TODO: Several methods in here are accessing children of this container's children through various
+// references (WindowList I am looking at you :/). See if we can delegate instead.
+class RootWindowContainer {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
+
+    WindowManagerService mService;
+
+    /** All DisplayContents in the world, kept here */
+    SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2);
+
+    private boolean mWallpaperForceHidingChanged = false;
+    private Object mLastWindowFreezeSource = null;
+    private Session mHoldScreen = null;
+    private float mScreenBrightness = -1;
+    private float mButtonBrightness = -1;
+    private long mUserActivityTimeout = -1;
+    private boolean mUpdateRotation = false;
+    private boolean mObscured = false;
+    boolean mSyswin = false;
+    // Set to true when the display contains content to show the user.
+    // When false, the display manager may choose to mirror or blank the display.
+    private boolean mDisplayHasContent = false;
+    private float mPreferredRefreshRate = 0;
+    private int mPreferredModeId = 0;
+    // Following variables are for debugging screen wakelock only.
+    // Last window that requires screen wakelock
+    WindowState mHoldScreenWindow = null;
+    // Last window that obscures all windows below
+    WindowState mObsuringWindow = null;
+    // Only set while traversing the default display based on its content.
+    // Affects the behavior of mirroring on secondary displays.
+    private boolean mObscureApplicationContentOnSecondaryDisplays = false;
+
+    private boolean mSustainedPerformanceModeEnabled = false;
+    private boolean mSustainedPerformanceModeCurrent = false;
+
+    boolean mWallpaperMayChange = false;
+    boolean mOrientationChangeComplete = true;
+    boolean mWallpaperActionPending = false;
+
+    private final ArrayList<Integer> mChangedStackList = new ArrayList();
+
+    // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl
+    // instances will be replaced with an instance that writes a binary representation of all
+    // commands to mSurfaceTraceFd.
+    boolean mSurfaceTraceEnabled;
+    ParcelFileDescriptor mSurfaceTraceFd;
+    RemoteEventTrace mRemoteEventTrace;
+
+    RootWindowContainer(WindowManagerService service) {
+        mService = service;
+    }
+
+    WindowState computeFocusedWindow() {
+        final int count = mDisplayContents.size();
+        for (int i = 0; i < count; i++) {
+            final DisplayContent dc = mDisplayContents.valueAt(i);
+            final WindowState win = dc.findFocusedWindow();
+            if (win != null) {
+                return win;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
+     * there is a Display for the displayId.
+     *
+     * @param displayId The display the caller is interested in.
+     * @return The DisplayContent associated with displayId or null if there is no Display for it.
+     */
+    DisplayContent getDisplayContent(final int displayId) {
+        DisplayContent dc = mDisplayContents.get(displayId);
+        if (dc == null) {
+            final Display display = mService.mDisplayManager.getDisplay(displayId);
+            if (display != null) {
+                dc = createDisplayContent(display);
+            }
+        }
+        return dc;
+    }
+
+    private DisplayContent createDisplayContent(final Display display) {
+        DisplayContent displayContent = new DisplayContent(display, mService);
+        final int displayId = display.getDisplayId();
+        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
+        mDisplayContents.put(displayId, displayContent);
+
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final Rect rect = new Rect();
+        mService.mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
+        displayInfo.overscanLeft = rect.left;
+        displayInfo.overscanTop = rect.top;
+        displayInfo.overscanRight = rect.right;
+        displayInfo.overscanBottom = rect.bottom;
+        if (mService.mDisplayManagerInternal != null) {
+            mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
+                    displayId, displayInfo);
+            mService.configureDisplayPolicyLocked(displayContent);
+
+            // TODO(multi-display): Create an input channel for each display with touch capability.
+            if (displayId == Display.DEFAULT_DISPLAY) {
+                displayContent.mTapDetector = new TaskTapPointerEventListener(
+                        mService, displayContent);
+                mService.registerPointerEventListener(displayContent.mTapDetector);
+                mService.registerPointerEventListener(mService.mMousePositionTracker);
+            }
+        }
+
+        return displayContent;
+    }
+
+    /** Adds the input stack id to the input display id and returns the bounds of the added stack.*/
+    Rect addStackToDisplay(int stackId, int displayId, boolean onTop) {
+        final DisplayContent dc = mDisplayContents.get(displayId);
+        if (dc == null) {
+            Slog.w(TAG_WM, "addStackToDisplay: Trying to add stackId=" + stackId
+                    + " to unknown displayId=" + displayId + " callers=" + Debug.getCallers(6));
+            return null;
+        }
+
+        boolean attachedToDisplay = false;
+        TaskStack stack = mService.mStackIdToStack.get(stackId);
+        if (stack == null) {
+            if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId);
+
+            stack = dc.getStackById(stackId);
+            if (stack != null) {
+                // It's already attached to the display...clear mDeferRemoval!
+                stack.mDeferRemoval = false;
+                attachedToDisplay = true;
+            } else {
+                stack = new TaskStack(mService, stackId);
+            }
+
+            mService.mStackIdToStack.put(stackId, stack);
+            if (stackId == DOCKED_STACK_ID) {
+                mService.getDefaultDisplayContentLocked().mDividerControllerLocked
+                        .notifyDockedStackExistsChanged(true);
+            }
+        }
+        if (!attachedToDisplay) {
+            stack.attachDisplayContent(dc);
+        }
+        dc.attachStack(stack, onTop);
+        if (stack.getRawFullscreen()) {
+            return null;
+        }
+        Rect bounds = new Rect();
+        stack.getRawBounds(bounds);
+        return bounds;
+    }
+
+    boolean layoutNeeded() {
+        final int numDisplays = mDisplayContents.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
+            if (displayContent.layoutNeeded) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void getWindows(WindowList output) {
+        final int count = mDisplayContents.size();
+        for (int i = 0; i < count; ++i) {
+            final DisplayContent dc = mDisplayContents.valueAt(i);
+            output.addAll(dc.getWindowList());
+        }
+    }
+
+    void getWindows(WindowList output, boolean visibleOnly, boolean appsOnly) {
+        final int numDisplays = mDisplayContents.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
+            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
+                final WindowState w = windowList.get(winNdx);
+                if ((!visibleOnly || w.mWinAnimator.getShown())
+                        && (!appsOnly || w.mAppToken != null)) {
+                    output.add(w);
+                }
+            }
+        }
+    }
+
+    void getWindowsByName(WindowList output, String name) {
+        int objectId = 0;
+        // See if this is an object ID.
+        try {
+            objectId = Integer.parseInt(name, 16);
+            name = null;
+        } catch (RuntimeException e) {
+        }
+        final int numDisplays = mDisplayContents.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
+            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
+                final WindowState w = windowList.get(winNdx);
+                if (name != null) {
+                    if (w.mAttrs.getTitle().toString().contains(name)) {
+                        output.add(w);
+                    }
+                } else if (System.identityHashCode(w) == objectId) {
+                    output.add(w);
+                }
+            }
+        }
+    }
+
+    WindowState findWindow(int hashCode) {
+        final int numDisplays = mDisplayContents.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
+            final int numWindows = windows.size();
+            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
+                final WindowState w = windows.get(winNdx);
+                if (System.identityHashCode(w) == hashCode) {
+                    return w;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    // TODO: Users would have their own window containers under the display container?
+    void switchUser() {
+        final int count = mDisplayContents.size();
+        for (int i = 0; i < count; ++i) {
+            final DisplayContent dc = mDisplayContents.valueAt(i);
+            dc.switchUser();
+        }
+    }
+
+    int[] onConfigurationChanged(Configuration config) {
+        prepareFreezingTaskBounds();
+        mService.mGlobalConfiguration = new Configuration(config);
+
+        mService.mPolicy.onConfigurationChanged();
+
+        mChangedStackList.clear();
+
+        final int numDisplays = mDisplayContents.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
+            displayContent.onConfigurationChanged(mChangedStackList);
+        }
+
+        return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
+    }
+
+    private void prepareFreezingTaskBounds() {
+        for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
+            mDisplayContents.valueAt(i).prepareFreezingTaskBounds();
+        }
+    }
+
+    void setSecureSurfaceState(int userId, boolean disabled) {
+        for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
+            final WindowList windows = mDisplayContents.valueAt(i).getWindowList();
+            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+                final WindowState win = windows.get(winNdx);
+                if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) {
+                    win.mWinAnimator.setSecureLocked(disabled);
+                }
+            }
+        }
+    }
+
+    void updateAppOpsState() {
+        final int count = mDisplayContents.size();
+        for (int i = 0; i < count; ++i) {
+            final WindowList windows = mDisplayContents.valueAt(i).getWindowList();
+            final int numWindows = windows.size();
+            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
+                final WindowState win = windows.get(winNdx);
+                if (win.mAppOp == AppOpsManager.OP_NONE) {
+                    continue;
+                }
+                final int mode = mService.mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
+                        win.getOwningPackage());
+                win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED ||
+                        mode == AppOpsManager.MODE_DEFAULT);
+            }
+        }
+    }
+
+    boolean canShowStrictModeViolation(int pid) {
+        final int count = mDisplayContents.size();
+        for (int i = 0; i < count; ++i) {
+            final WindowList windows = mDisplayContents.valueAt(i).getWindowList();
+            final int numWindows = windows.size();
+            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
+                final WindowState ws = windows.get(winNdx);
+                if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    void closeSystemDialogs(String reason) {
+        final int count = mDisplayContents.size();
+        for (int i = 0; i < count; ++i) {
+            final WindowList windows = mDisplayContents.valueAt(i).getWindowList();
+            final int numWindows = windows.size();
+            for (int j = 0; j < numWindows; ++j) {
+                final WindowState w = windows.get(j);
+                if (w.mHasSurface) {
+                    try {
+                        w.mClient.closeSystemDialogs(reason);
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+        }
+    }
+
+    void removeReplacedWindows() {
+        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
+        mService.openSurfaceTransaction();
+        try {
+            for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
+                DisplayContent dc = mDisplayContents.valueAt(i);
+                final WindowList windows = dc.getWindowList();
+                for (int j = windows.size() - 1; j >= 0; j--) {
+                    final WindowState win = windows.get(j);
+                    final AppWindowToken aToken = win.mAppToken;
+                    if (aToken != null) {
+                        aToken.removeReplacedWindowIfNeeded(win);
+                    }
+                }
+            }
+        } finally {
+            mService.closeSurfaceTransaction();
+            if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
+        }
+    }
+
+    boolean hasPendingLayoutChanges(WindowAnimator animator) {
+        boolean hasChanges = false;
+
+        final int count = mDisplayContents.size();
+        for (int i = 0; i < count; ++i) {
+            final DisplayContent dc = mDisplayContents.valueAt(i);
+            final int pendingChanges = animator.getPendingLayoutChanges(dc.getDisplayId());
+            if ((pendingChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
+                animator.mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
+            }
+            if (pendingChanges != 0) {
+                hasChanges = true;
+            }
+        }
+
+        return hasChanges;
+    }
+
+    void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
+        boolean addInputConsumerHandle = mService.mInputConsumer != null;
+        boolean addWallpaperInputConsumerHandle = mService.mWallpaperInputConsumer != null;
+        final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
+        boolean disableWallpaperTouchEvents = false;
+
+        final int count = mDisplayContents.size();
+        for (int i = 0; i < count; ++i) {
+            final DisplayContent dc = mDisplayContents.valueAt(i);
+            final WindowList windows = dc.getWindowList();
+            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+                final WindowState child = windows.get(winNdx);
+                final InputChannel inputChannel = child.mInputChannel;
+                final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
+                if (inputChannel == null || inputWindowHandle == null || child.mRemoved
+                        || child.isAdjustedForMinimizedDock()) {
+                    // Skip this window because it cannot possibly receive input.
+                    continue;
+                }
+                if (addInputConsumerHandle
+                        && inputWindowHandle.layer <= mService.mInputConsumer.mWindowHandle.layer) {
+                    inputMonitor.addInputWindowHandle(mService.mInputConsumer.mWindowHandle);
+                    addInputConsumerHandle = false;
+                }
+
+                if (addWallpaperInputConsumerHandle) {
+                    if (child.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER &&
+                            child.isVisibleLw()) {
+                        // Add the wallpaper input consumer above the first visible wallpaper.
+                        inputMonitor.addInputWindowHandle(
+                                mService.mWallpaperInputConsumer.mWindowHandle);
+                        addWallpaperInputConsumerHandle = false;
+                    }
+                }
+
+                final int flags = child.mAttrs.flags;
+                final int privateFlags = child.mAttrs.privateFlags;
+                final int type = child.mAttrs.type;
+
+                final boolean hasFocus = child == inputFocus;
+                final boolean isVisible = child.isVisibleLw();
+                if ((privateFlags
+                        & WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS)
+                        != 0) {
+                    disableWallpaperTouchEvents = true;
+                }
+                final boolean hasWallpaper = wallpaperController.isWallpaperTarget(child)
+                        && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0
+                        && !disableWallpaperTouchEvents;
+                final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
+
+                // If there's a drag in progress and 'child' is a potential drop target,
+                // make sure it's been told about the drag
+                if (inDrag && isVisible && onDefaultDisplay) {
+                    mService.mDragState.sendDragStartedIfNeededLw(child);
+                }
+
+                inputMonitor.addInputWindowHandle(
+                        inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
+            }
+        }
+
+        if (addWallpaperInputConsumerHandle) {
+            // No visible wallpaper found, add the wallpaper input consumer at the end.
+            inputMonitor.addInputWindowHandle(mService.mWallpaperInputConsumer.mWindowHandle);
+        }
+    }
+
+    boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
+            boolean secure) {
+        final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
+        boolean leakedSurface = false;
+        boolean killedApps = false;
+
+        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
+                winAnimator.mSession.mPid, operation);
+
+        final long callingIdentity = Binder.clearCallingIdentity();
+        try {
+            // There was some problem...   first, do a sanity check of the window list to make sure
+            // we haven't left any dangling surfaces around.
+
+            Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
+            final int numDisplays = mDisplayContents.size();
+            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
+                final int numWindows = windows.size();
+                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
+                    final WindowState ws = windows.get(winNdx);
+                    final WindowStateAnimator wsa = ws.mWinAnimator;
+                    if (wsa.mSurfaceController == null) {
+                        continue;
+                    }
+                    if (!mService.mSessions.contains(wsa.mSession)) {
+                        Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
+                                + ws + " surface=" + wsa.mSurfaceController
+                                + " token=" + ws.mToken
+                                + " pid=" + ws.mSession.mPid
+                                + " uid=" + ws.mSession.mUid);
+                        wsa.destroySurface();
+                        mService.mForceRemoves.add(ws);
+                        leakedSurface = true;
+                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
+                        Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
+                                + ws + " surface=" + wsa.mSurfaceController
+                                + " token=" + ws.mAppToken
+                                + " saved=" + ws.hasSavedSurface());
+                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
+                        wsa.destroySurface();
+                        leakedSurface = true;
+                    }
+                }
+            }
+
+            if (!leakedSurface) {
+                Slog.w(TAG_WM, "No leaked surfaces; killing applications!");
+                SparseIntArray pidCandidates = new SparseIntArray();
+                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
+                    final int numWindows = windows.size();
+                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
+                        final WindowState ws = windows.get(winNdx);
+                        if (mService.mForceRemoves.contains(ws)) {
+                            continue;
+                        }
+                        WindowStateAnimator wsa = ws.mWinAnimator;
+                        if (wsa.mSurfaceController != null) {
+                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
+                        }
+                    }
+                    if (pidCandidates.size() > 0) {
+                        int[] pids = new int[pidCandidates.size()];
+                        for (int i = 0; i < pids.length; i++) {
+                            pids[i] = pidCandidates.keyAt(i);
+                        }
+                        try {
+                            if (mService.mActivityManager.killPids(pids, "Free memory", secure)) {
+                                killedApps = true;
+                            }
+                        } catch (RemoteException e) {
+                        }
+                    }
+                }
+            }
+
+            if (leakedSurface || killedApps) {
+                // We managed to reclaim some memory, so get rid of the trouble surface and ask the
+                // app to request another one.
+                Slog.w(TAG_WM,
+                        "Looks like we have reclaimed some memory, clearing surface for retry.");
+                if (surfaceController != null) {
+                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
+                            "RECOVER DESTROY", false);
+                    winAnimator.destroySurface();
+                    mService.scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
+                }
+
+                try {
+                    winAnimator.mWin.mClient.dispatchGetNewSurface();
+                } catch (RemoteException e) {
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingIdentity);
+        }
+
+        return leakedSurface || killedApps;
+    }
+
+    // "Something has changed!  Let's make it correct now."
+    // TODO: Super crazy long method that should be broken down...
+    void performSurfacePlacement(boolean recoveringMemory) {
+        if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
+                + Debug.getCallers(3));
+
+        int i;
+        boolean updateInputWindowsNeeded = false;
+
+        if (mService.mFocusMayChange) {
+            mService.mFocusMayChange = false;
+            updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
+                    UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
+        }
+
+        // Initialize state of exiting tokens.
+        final int numDisplays = mDisplayContents.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
+            for (i = displayContent.mExitingTokens.size() - 1; i >= 0; i--) {
+                displayContent.mExitingTokens.get(i).hasVisible = false;
+            }
+        }
+
+        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
+            // Initialize state of exiting applications.
+            final AppTokenList exitingAppTokens =
+                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
+            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                exitingAppTokens.get(tokenNdx).hasVisible = false;
+            }
+        }
+
+        mHoldScreen = null;
+        mScreenBrightness = -1;
+        mButtonBrightness = -1;
+        mUserActivityTimeout = -1;
+        mObscureApplicationContentOnSecondaryDisplays = false;
+        mSustainedPerformanceModeCurrent = false;
+        mService.mTransactionSequence++;
+
+        // TODO(multi-display):
+        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
+        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
+        final int defaultDw = defaultInfo.logicalWidth;
+        final int defaultDh = defaultInfo.logicalHeight;
+
+        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
+        mService.openSurfaceTransaction();
+        try {
+            mService.mRoot.applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh);
+        } catch (RuntimeException e) {
+            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
+        } finally {
+            mService.closeSurfaceTransaction();
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
+        }
+
+        final WindowList defaultWindows = defaultDisplay.getWindowList();
+        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
+
+        // If we are ready to perform an app transition, check through all of the app tokens to be
+        // shown and see if they are ready to go.
+        if (mService.mAppTransition.isReady()) {
+            defaultDisplay.pendingLayoutChanges |=
+                    surfacePlacer.handleAppTransitionReadyLocked(defaultWindows);
+            if (DEBUG_LAYOUT_REPEATS)
+                surfacePlacer.debugLayoutRepeats("after handleAppTransitionReadyLocked",
+                        defaultDisplay.pendingLayoutChanges);
+        }
+
+        if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
+            // We have finished the animation of an app transition. To do this, we have delayed a
+            // lot of operations like showing and hiding apps, moving apps in Z-order, etc. The app
+            // token list reflects the correct Z-order, but the window list may now be out of sync
+            // with it. So here we will just rebuild the entire app window list. Fun!
+            defaultDisplay.pendingLayoutChanges |=
+                    mService.handleAnimatingStoppedAndTransitionLocked();
+            if (DEBUG_LAYOUT_REPEATS)
+                surfacePlacer.debugLayoutRepeats("after handleAnimStopAndXitionLock",
+                        defaultDisplay.pendingLayoutChanges);
+        }
+
+        if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
+                && !mService.mAppTransition.isReady()) {
+            // At this point, there was a window with a wallpaper that was force hiding other
+            // windows behind it, but now it is going away. This may be simple -- just animate away
+            // the wallpaper and its window -- or it may be hard -- the wallpaper now needs to be
+            // shown behind something that was hidden.
+            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
+            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
+                    "after animateAwayWallpaperLocked", defaultDisplay.pendingLayoutChanges);
+        }
+        mWallpaperForceHidingChanged = false;
+
+        if (mWallpaperMayChange) {
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
+            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("WallpaperMayChange",
+                    defaultDisplay.pendingLayoutChanges);
+        }
+
+        if (mService.mFocusMayChange) {
+            mService.mFocusMayChange = false;
+            if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
+                    false /*updateInputWindows*/)) {
+                updateInputWindowsNeeded = true;
+                defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
+            }
+        }
+
+        if (layoutNeeded()) {
+            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
+            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("mLayoutNeeded",
+                    defaultDisplay.pendingLayoutChanges);
+        }
+
+        for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
+            WindowState win = mService.mResizingWindows.get(i);
+            if (win.mAppFreezing) {
+                // Don't remove this window until rotation has completed.
+                continue;
+            }
+            // Discard the saved surface if window size is changed, it can't be reused.
+            if (win.mAppToken != null) {
+                win.mAppToken.destroySavedSurfaces();
+            }
+            win.reportResized();
+            mService.mResizingWindows.remove(i);
+        }
+
+        if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG,
+                "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete);
+        if (mOrientationChangeComplete) {
+            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
+                mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
+                mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
+                mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
+            }
+            mService.stopFreezingDisplayLocked();
+        }
+
+        // Destroy the surface of any windows that are no longer visible.
+        boolean wallpaperDestroyed = false;
+        i = mService.mDestroySurface.size();
+        if (i > 0) {
+            do {
+                i--;
+                WindowState win = mService.mDestroySurface.get(i);
+                win.mDestroying = false;
+                if (mService.mInputMethodWindow == win) {
+                    mService.mInputMethodWindow = null;
+                }
+                if (mService.mWallpaperControllerLocked.isWallpaperTarget(win)) {
+                    wallpaperDestroyed = true;
+                }
+                win.destroyOrSaveSurface();
+            } while (i > 0);
+            mService.mDestroySurface.clear();
+        }
+
+        // Time to remove any exiting tokens?
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
+            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
+            for (i = exitingTokens.size() - 1; i >= 0; i--) {
+                WindowToken token = exitingTokens.get(i);
+                if (!token.hasVisible) {
+                    exitingTokens.remove(i);
+                    if (token.windowType == TYPE_WALLPAPER) {
+                        mService.mWallpaperControllerLocked.removeWallpaperToken(token);
+                    }
+                }
+            }
+        }
+
+        // Time to remove any exiting applications?
+        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
+            // Initialize state of exiting applications.
+            final AppTokenList exitingAppTokens =
+                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
+            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
+                final AppWindowToken token = exitingAppTokens.get(i);
+                if (!token.hasVisible && !mService.mClosingApps.contains(token) &&
+                        (!token.mIsExiting || token.isEmpty())) {
+                    // Make sure there is no animation running on this token, so any windows
+                    // associated with it will be removed as soon as their animations are complete
+                    token.mAppAnimator.clearAnimation();
+                    token.mAppAnimator.animating = false;
+                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                            "performLayout: App token exiting now removed" + token);
+                    token.removeIfPossible();
+                }
+            }
+        }
+
+        if (wallpaperDestroyed) {
+            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+            defaultDisplay.layoutNeeded = true;
+        }
+
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
+            if (displayContent.pendingLayoutChanges != 0) {
+                displayContent.layoutNeeded = true;
+            }
+        }
+
+        // Finally update all input windows now that the window changes have stabilized.
+        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+        mService.setHoldScreenLocked(mHoldScreen);
+        if (!mService.mDisplayFrozen) {
+            if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) {
+                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
+            } else {
+                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
+                        toBrightnessOverride(mScreenBrightness));
+            }
+            if (mButtonBrightness < 0 || mButtonBrightness > 1.0f) {
+                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
+            } else {
+                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
+                        toBrightnessOverride(mButtonBrightness));
+            }
+            mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
+                    mUserActivityTimeout);
+        }
+
+        if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
+            mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
+            mService.mPowerManagerInternal.powerHint(
+                    mService.mPowerManagerInternal.POWER_HINT_SUSTAINED_PERFORMANCE_MODE,
+                    (mSustainedPerformanceModeEnabled ? 1 : 0));
+        }
+
+        if (mService.mTurnOnScreen) {
+            if (mService.mAllowTheaterModeWakeFromLayout
+                    || Settings.Global.getInt(mService.mContext.getContentResolver(),
+                    Settings.Global.THEATER_MODE_ON, 0) == 0) {
+                if (DEBUG_VISIBILITY || DEBUG_POWER) {
+                    Slog.v(TAG, "Turning screen on after layout!");
+                }
+                mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
+                        "android.server.wm:TURN_ON");
+            }
+            mService.mTurnOnScreen = false;
+        }
+
+        if (mUpdateRotation) {
+            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
+            if (mService.updateRotationUncheckedLocked(false)) {
+                mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
+            } else {
+                mUpdateRotation = false;
+            }
+        }
+
+        if (mService.mWaitingForDrawnCallback != null ||
+                (mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
+                        !mUpdateRotation)) {
+            mService.checkDrawnWindowsLocked();
+        }
+
+        final int N = mService.mPendingRemove.size();
+        if (N > 0) {
+            if (mService.mPendingRemoveTmp.length < N) {
+                mService.mPendingRemoveTmp = new WindowState[N+10];
+            }
+            mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
+            mService.mPendingRemove.clear();
+            DisplayContentList displayList = new DisplayContentList();
+            for (i = 0; i < N; i++) {
+                final WindowState w = mService.mPendingRemoveTmp[i];
+                w.removeImmediately();
+                final DisplayContent displayContent = w.getDisplayContent();
+                if (displayContent != null && !displayList.contains(displayContent)) {
+                    displayList.add(displayContent);
+                }
+            }
+
+            for (DisplayContent displayContent : displayList) {
+                mService.mLayersController.assignLayersLocked(displayContent.getWindowList());
+                displayContent.layoutNeeded = true;
+            }
+        }
+
+        // Remove all deferred displays stacks, tasks, and activities.
+        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+            mDisplayContents.valueAt(displayNdx).checkCompleteDeferredRemoval();
+        }
+
+        if (updateInputWindowsNeeded) {
+            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+        }
+        mService.setFocusTaskRegionLocked();
+
+        // Check to see if we are now in a state where the screen should
+        // be enabled, because the window obscured flags have changed.
+        mService.enableScreenIfNeededLocked();
+
+        mService.scheduleAnimationLocked();
+        mService.mWindowPlacerLocked.destroyPendingSurfaces();
+
+        if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
+                "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
+    }
+
+    // TODO: Super crazy long method that should be broken down...
+    void applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw, int defaultDh) {
+        mHoldScreenWindow = null;
+        mObsuringWindow = null;
+
+        if (mService.mWatermark != null) {
+            mService.mWatermark.positionSurface(defaultDw, defaultDh);
+        }
+        if (mService.mStrictModeFlash != null) {
+            mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
+        }
+        if (mService.mCircularDisplayMask != null) {
+            mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mService.mRotation);
+        }
+        if (mService.mEmulatorDisplayOverlay != null) {
+            mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
+                    mService.mRotation);
+        }
+
+        boolean focusDisplayed = false;
+
+        final int count = mDisplayContents.size();
+        for (int j = 0; j < count; ++j) {
+            final DisplayContent dc = mDisplayContents.valueAt(j);
+            boolean updateAllDrawn = false;
+            WindowList windows = dc.getWindowList();
+            DisplayInfo displayInfo = dc.getDisplayInfo();
+            final int displayId = dc.getDisplayId();
+            final int dw = displayInfo.logicalWidth;
+            final int dh = displayInfo.logicalHeight;
+            final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+            final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
+
+            // Reset for each display.
+            mDisplayHasContent = false;
+            mPreferredRefreshRate = 0;
+            mPreferredModeId = 0;
+
+            int repeats = 0;
+            do {
+                repeats++;
+                if (repeats > 6) {
+                    Slog.w(TAG, "Animation repeat aborted after too many iterations");
+                    dc.layoutNeeded = false;
+                    break;
+                }
+
+                if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
+                        "On entry to LockedInner", dc.pendingLayoutChanges);
+
+                if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0
+                        && mService.mWallpaperControllerLocked.adjustWallpaperWindows()) {
+                    mService.mLayersController.assignLayersLocked(windows);
+                    dc.layoutNeeded = true;
+                }
+
+                if (isDefaultDisplay
+                        && (dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
+                    if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
+                    if (mService.updateOrientationFromAppTokensLocked(true)) {
+                        dc.layoutNeeded = true;
+                        mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
+                    }
+                }
+
+                if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+                    dc.layoutNeeded = true;
+                }
+
+                // FIRST LOOP: Perform a layout, if needed.
+                if (repeats < LAYOUT_REPEAT_THRESHOLD) {
+                    surfacePlacer.performLayoutLockedInner(dc, repeats == 1,
+                            false /* updateInputWindows */);
+                } else {
+                    Slog.w(TAG, "Layout repeat skipped after too many iterations");
+                }
+
+                // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
+                // it is animating.
+                dc.pendingLayoutChanges = 0;
+
+                if (isDefaultDisplay) {
+                    mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
+                    for (int i = windows.size() - 1; i >= 0; i--) {
+                        WindowState w = windows.get(i);
+                        if (w.mHasSurface) {
+                            mService.mPolicy.applyPostLayoutPolicyLw(
+                                    w, w.mAttrs, w.getParentWindow());
+                        }
+                    }
+                    dc.pendingLayoutChanges |=
+                            mService.mPolicy.finishPostLayoutPolicyLw();
+                    if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
+                            "after finishPostLayoutPolicyLw", dc.pendingLayoutChanges);
+                }
+            } while (dc.pendingLayoutChanges != 0);
+
+            mObscured = false;
+            mSyswin = false;
+            dc.resetDimming();
+
+            // Only used if default window
+            final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
+
+            for (int i = windows.size() - 1; i >= 0; i--) {
+                WindowState w = windows.get(i);
+                final Task task = w.getTask();
+                final boolean obscuredChanged = w.mObscured != mObscured;
+
+                // Update effect.
+                w.mObscured = mObscured;
+                if (!mObscured) {
+                    handleNotObscuredLocked(w, displayInfo);
+                }
+
+                w.applyDimLayerIfNeeded();
+
+                if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
+                        && mService.mWallpaperControllerLocked.isWallpaperTarget(w)) {
+                    // This is the wallpaper target and its obscured state changed... make sure the
+                    // current wallaper's visibility has been updated accordingly.
+                    mService.mWallpaperControllerLocked.updateWallpaperVisibility();
+                }
+
+                final WindowStateAnimator winAnimator = w.mWinAnimator;
+
+                // If the window has moved due to its containing content frame changing, then
+                // notify the listeners and optionally animate it. Simply checking a change of
+                // position is not enough, because being move due to dock divider is not a trigger
+                // for animation.
+                if (w.hasMoved()) {
+                    // Frame has moved, containing content frame has also moved, and we're not
+                    // currently animating... let's do something.
+                    final int left = w.mFrame.left;
+                    final int top = w.mFrame.top;
+                    final boolean adjustedForMinimizedDockOrIme = task != null
+                            && (task.mStack.isAdjustedForMinimizedDockedStack()
+                            || task.mStack.isAdjustedForIme());
+                    if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
+                            && !w.isDragResizing() && !adjustedForMinimizedDockOrIme
+                            && (task == null || w.getTask().mStack.hasMovementAnimations())
+                            && !w.mWinAnimator.mLastHidden) {
+                        winAnimator.setMoveAnimation(left, top);
+                    }
+
+                    //TODO (multidisplay): Accessibility supported only for the default display.
+                    if (mService.mAccessibilityController != null
+                            && displayId == Display.DEFAULT_DISPLAY) {
+                        mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
+                    }
+
+                    try {
+                        w.mClient.moved(left, top);
+                    } catch (RemoteException e) {
+                    }
+                    w.mMovedByResize = false;
+                }
+
+                //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
+                w.mContentChanged = false;
+
+                // Moved from updateWindowsAndWallpaperLocked().
+                if (w.mHasSurface) {
+                    // Take care of the window being ready to display.
+                    final boolean committed = winAnimator.commitFinishDrawingLocked();
+                    if (isDefaultDisplay && committed) {
+                        if (w.mAttrs.type == TYPE_DREAM) {
+                            // HACK: When a dream is shown, it may at that point hide the lock
+                            // screen. So we need to redo the layout to let the phone window manager
+                            // make this happen.
+                            dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
+                            if (DEBUG_LAYOUT_REPEATS) {
+                                surfacePlacer.debugLayoutRepeats(
+                                        "dream and commitFinishDrawingLocked true",
+                                        dc.pendingLayoutChanges);
+                            }
+                        }
+                        if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
+                            if (DEBUG_WALLPAPER_LIGHT)
+                                Slog.v(TAG, "First draw done in potential wallpaper target " + w);
+                            mWallpaperMayChange = true;
+                            dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+                            if (DEBUG_LAYOUT_REPEATS) {
+                                surfacePlacer.debugLayoutRepeats(
+                                        "wallpaper and commitFinishDrawingLocked true",
+                                        dc.pendingLayoutChanges);
+                            }
+                        }
+                    }
+                    if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
+                        // Updates the shown frame before we set up the surface. This is needed
+                        // because the resizing could change the top-left position (in addition to
+                        // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
+                        // position the surface.
+                        //
+                        // If an animation is being started, we can't call this method because the
+                        // animation hasn't processed its initial transformation yet, but in general
+                        // we do want to update the position if the window is animating.
+                        winAnimator.computeShownFrameLocked();
+                    }
+                    winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
+                }
+
+                final AppWindowToken atoken = w.mAppToken;
+                if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) {
+                    Slog.d(TAG, "updateWindows: starting " + w
+                            + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
+                            + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
+                }
+                if (atoken != null && (!atoken.allDrawn || !atoken.allDrawnExcludingSaved
+                        || atoken.mAppAnimator.freezingScreen)) {
+                    if (atoken.lastTransactionSequence != mService.mTransactionSequence) {
+                        atoken.lastTransactionSequence = mService.mTransactionSequence;
+                        atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
+                        atoken.numInterestingWindowsExcludingSaved = 0;
+                        atoken.numDrawnWindowsExcludingSaved = 0;
+                        atoken.startingDisplayed = false;
+                    }
+                    if (!atoken.allDrawn && w.mightAffectAllDrawn(false /* visibleOnly */)) {
+                        if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
+                            Slog.v(TAG, "Eval win " + w + ": isDrawn="
+                                    + w.isDrawnLw()
+                                    + ", isAnimationSet=" + winAnimator.isAnimationSet());
+                            if (!w.isDrawnLw()) {
+                                Slog.v(TAG, "Not displayed: s="
+                                        + winAnimator.mSurfaceController
+                                        + " pv=" + w.mPolicyVisibility
+                                        + " mDrawState=" + winAnimator.drawStateToString()
+                                        + " ph=" + w.isParentWindowHidden()
+                                        + " th=" + atoken.hiddenRequested
+                                        + " a=" + winAnimator.mAnimating);
+                            }
+                        }
+                        if (w != atoken.startingWindow) {
+                            if (w.isInteresting()) {
+                                atoken.numInterestingWindows++;
+                                if (w.isDrawnLw()) {
+                                    atoken.numDrawnWindows++;
+                                    if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
+                                        Slog.v(TAG, "tokenMayBeDrawn: " + atoken
+                                                + " w=" + w + " numInteresting="
+                                                + atoken.numInterestingWindows
+                                                + " freezingScreen="
+                                                + atoken.mAppAnimator.freezingScreen
+                                                + " mAppFreezing=" + w.mAppFreezing);
+                                    updateAllDrawn = true;
+                                }
+                            }
+                        } else if (w.isDrawnLw()) {
+                            mService.mH.sendEmptyMessage(NOTIFY_STARTING_WINDOW_DRAWN);
+                            atoken.startingDisplayed = true;
+                        }
+                    }
+                    if (!atoken.allDrawnExcludingSaved
+                            && w.mightAffectAllDrawn(true /* visibleOnly */)) {
+                        if (w != atoken.startingWindow && w.isInteresting()) {
+                            atoken.numInterestingWindowsExcludingSaved++;
+                            if (w.isDrawnLw() && !w.isAnimatingWithSavedSurface()) {
+                                atoken.numDrawnWindowsExcludingSaved++;
+                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
+                                    Slog.v(TAG, "tokenMayBeDrawnExcludingSaved: " + atoken
+                                            + " w=" + w + " numInteresting="
+                                            + atoken.numInterestingWindowsExcludingSaved
+                                            + " freezingScreen="
+                                            + atoken.mAppAnimator.freezingScreen
+                                            + " mAppFreezing=" + w.mAppFreezing);
+                                updateAllDrawn = true;
+                            }
+                        }
+                    }
+                }
+
+                if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
+                        && w.isDisplayedLw()) {
+                    focusDisplayed = true;
+                }
+
+                mService.updateResizingWindows(w);
+            }
+
+            mService.mDisplayManagerInternal.setDisplayProperties(displayId,
+                    mDisplayHasContent,
+                    mPreferredRefreshRate,
+                    mPreferredModeId,
+                    true /* inTraversal, must call performTraversalInTrans... below */);
+
+            dc.stopDimmingIfNeeded();
+
+            if (updateAllDrawn) {
+                // See if any windows have been drawn, so they (and others associated with them)
+                // can now be shown.
+                dc.updateAllDrawn();
+            }
+        }
+
+        if (focusDisplayed) {
+            mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
+        }
+
+        // Give the display manager a chance to adjust properties
+        // like display rotation if it needs to.
+        mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
+    }
+
+    /**
+     * @param w WindowState this method is applied to.
+     * @param dispInfo info of the display that the window's obscuring state is checked against.
+     */
+    private void handleNotObscuredLocked(final WindowState w, final DisplayInfo dispInfo) {
+        final WindowManager.LayoutParams attrs = w.mAttrs;
+        final int attrFlags = attrs.flags;
+        final boolean canBeSeen = w.isDisplayedLw();
+        final int privateflags = attrs.privateFlags;
+
+        if (canBeSeen && w.isObscuringFullscreen(dispInfo)) {
+            // This window completely covers everything behind it,
+            // so we want to leave all of them as undimmed (for
+            // performance reasons).
+            if (!mObscured) {
+                mObsuringWindow = w;
+            }
+
+            mObscured = true;
+        }
+
+        if (w.mHasSurface && canBeSeen) {
+            if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
+                mHoldScreen = w.mSession;
+                mHoldScreenWindow = w;
+            } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) {
+                Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding "
+                        + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by"
+                        + Debug.getCallers(10));
+            }
+            if (!mSyswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
+                mScreenBrightness = w.mAttrs.screenBrightness;
+            }
+            if (!mSyswin && w.mAttrs.buttonBrightness >= 0 && mButtonBrightness < 0) {
+                mButtonBrightness = w.mAttrs.buttonBrightness;
+            }
+            if (!mSyswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
+                mUserActivityTimeout = w.mAttrs.userActivityTimeout;
+            }
+
+            final int type = attrs.type;
+            if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
+                    || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+                mSyswin = true;
+            }
+
+            // This function assumes that the contents of the default display are processed first
+            // before secondary displays.
+            final DisplayContent displayContent = w.getDisplayContent();
+            if (displayContent != null && displayContent.isDefaultDisplay) {
+                // While a dream or keyguard is showing, obscure ordinary application content on
+                // secondary displays (by forcibly enabling mirroring unless there is other content
+                // we want to show) but still allow opaque keyguard dialogs to be shown.
+                if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+                    mObscureApplicationContentOnSecondaryDisplays = true;
+                }
+                mDisplayHasContent = true;
+            } else if (displayContent != null &&
+                    (!mObscureApplicationContentOnSecondaryDisplays
+                            || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
+                // Allow full screen keyguard presentation dialogs to be seen.
+                mDisplayHasContent = true;
+            }
+            if (mPreferredRefreshRate == 0 && w.mAttrs.preferredRefreshRate != 0) {
+                mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
+            }
+            if (mPreferredModeId == 0 && w.mAttrs.preferredDisplayModeId != 0) {
+                mPreferredModeId = w.mAttrs.preferredDisplayModeId;
+            }
+            if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
+                mSustainedPerformanceModeCurrent = true;
+            }
+        }
+    }
+
+    boolean copyAnimToLayoutParams() {
+        boolean doRequest = false;
+
+        final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams;
+        if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
+            mUpdateRotation = true;
+            doRequest = true;
+        }
+        if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) {
+            mWallpaperMayChange = true;
+            doRequest = true;
+        }
+        if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
+            mWallpaperForceHidingChanged = true;
+            doRequest = true;
+        }
+        if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
+            mOrientationChangeComplete = false;
+        } else {
+            mOrientationChangeComplete = true;
+            mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource;
+            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
+                doRequest = true;
+            }
+        }
+        if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) {
+            mService.mTurnOnScreen = true;
+        }
+        if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) {
+            mWallpaperActionPending = true;
+        }
+
+        return doRequest;
+    }
+
+    private static int toBrightnessOverride(float value) {
+        return (int)(value * PowerManager.BRIGHTNESS_ON);
+    }
+
+    void enableSurfaceTrace(ParcelFileDescriptor pfd) {
+        final FileDescriptor fd = pfd.getFileDescriptor();
+        if (mSurfaceTraceEnabled) {
+            disableSurfaceTrace();
+        }
+        mSurfaceTraceEnabled = true;
+        mRemoteEventTrace = new RemoteEventTrace(mService, fd);
+        mSurfaceTraceFd = pfd;
+        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+            DisplayContent dc = mDisplayContents.valueAt(displayNdx);
+            dc.enableSurfaceTrace(fd);
+        }
+    }
+
+    void disableSurfaceTrace() {
+        mSurfaceTraceEnabled = false;
+        mRemoteEventTrace = null;
+        mSurfaceTraceFd = null;
+        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+            DisplayContent dc = mDisplayContents.valueAt(displayNdx);
+            dc.disableSurfaceTrace();
+        }
+    }
+
+    void dumpDisplayContents(PrintWriter pw) {
+        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
+        if (mService.mDisplayReady) {
+            final int count = mDisplayContents.size();
+            for (int i = 0; i < count; ++i) {
+                final DisplayContent displayContent = mDisplayContents.valueAt(i);
+                displayContent.dump("  ", pw);
+            }
+        } else {
+            pw.println("  NO DISPLAY");
+        }
+    }
+
+    void dumpLayoutNeededDisplayIds(PrintWriter pw) {
+        if (!layoutNeeded()) {
+            return;
+        }
+        pw.print("  layoutNeeded on displays=");
+        final int count = mDisplayContents.size();
+        for (int displayNdx = 0; displayNdx < count; ++displayNdx) {
+            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
+            if (displayContent.layoutNeeded) {
+                pw.print(displayContent.getDisplayId());
+            }
+        }
+        pw.println();
+    }
+
+    void dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) {
+        final int numDisplays = mDisplayContents.size();
+        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
+            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
+                final WindowState w = windowList.get(winNdx);
+                if (windows == null || windows.contains(w)) {
+                    pw.println("  Window #" + winNdx + " " + w + ":");
+                    w.dump(pw, "    ", dumpAll || windows != null);
+                }
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index b269d4c..58439eb 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -641,7 +641,7 @@
     }
 
     boolean adjustWallpaperWindows() {
-        mService.mWindowPlacerLocked.mWallpaperMayChange = false;
+        mService.mRoot.mWallpaperMayChange = false;
 
         final WindowList windows = mService.getDefaultWindowListLocked();
         // First find top-most window that has asked to be on top of the wallpaper;
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index a13b6a1..28b5424 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -528,7 +528,7 @@
     }
 
     private void updateWallpaperLocked(int displayId) {
-        mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
+        mService.mRoot.getDisplayContent(displayId).resetAnimationBackgroundAnimator();
 
         final WindowList windows = mService.getWindowListLocked(displayId);
         WindowState detachedWallpaper = null;
@@ -615,7 +615,7 @@
             final int numDisplays = mDisplayContentsAnimators.size();
             for (int i = 0; i < numDisplays; i++) {
                 final int displayId = mDisplayContentsAnimators.keyAt(i);
-                final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mService.mRoot.getDisplayContent(displayId);
                 displayContent.stepAppWindowsAnimation(mCurrentTime);
                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
 
@@ -654,7 +654,7 @@
 
             for (int i = 0; i < numDisplays; i++) {
                 final int displayId = mDisplayContentsAnimators.keyAt(i);
-                final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mService.mRoot.getDisplayContent(displayId);
 
                 displayContent.checkAppWindowsReadyToShow();
 
@@ -691,22 +691,10 @@
                     TAG, "<<< CLOSE TRANSACTION animateLocked");
         }
 
-        boolean hasPendingLayoutChanges = false;
-        final int numDisplays = mService.mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
-            if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
-                mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
-            }
-            if (pendingChanges != 0) {
-                hasPendingLayoutChanges = true;
-            }
-        }
-
+        boolean hasPendingLayoutChanges = mService.mRoot.hasPendingLayoutChanges(this);
         boolean doRequest = false;
         if (mBulkUpdateParams != 0) {
-            doRequest = mWindowPlacerLocked.copyAnimToLayoutParamsLocked();
+            doRequest = mService.mRoot.copyAnimToLayoutParams();
         }
 
         if (hasPendingLayoutChanges || doRequest) {
@@ -725,7 +713,8 @@
         }
 
         if (mRemoveReplacedWindows) {
-            removeReplacedWindowsLocked();
+            mService.mRoot.removeReplacedWindows();
+            mRemoveReplacedWindows = false;
         }
 
         mService.stopUsingSavedSurfaceLocked();
@@ -740,28 +729,6 @@
         }
     }
 
-    private void removeReplacedWindowsLocked() {
-        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
-        mService.openSurfaceTransaction();
-        try {
-            for (int i = mService.mDisplayContents.size() - 1; i >= 0; i--) {
-                DisplayContent display = mService.mDisplayContents.valueAt(i);
-                final WindowList windows = mService.getWindowListLocked(display.getDisplayId());
-                for (int j = windows.size() - 1; j >= 0; j--) {
-                    final WindowState win = windows.get(j);
-                    final AppWindowToken aToken = win.mAppToken;
-                    if (aToken != null) {
-                        aToken.removeReplacedWindowIfNeeded(win);
-                    }
-                }
-            }
-        } finally {
-            mService.closeSurfaceTransaction();
-            if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
-        }
-        mRemoveReplacedWindows = false;
-    }
-
     private static String bulkUpdateParamsToString(int bulkUpdateParams) {
         StringBuilder builder = new StringBuilder(128);
         if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) {
@@ -832,7 +799,7 @@
         if (displayId < 0) {
             return 0;
         }
-        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mService.mRoot.getDisplayContent(displayId);
         return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
     }
 
@@ -840,7 +807,7 @@
         if (displayId < 0) {
             return;
         }
-        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mService.mRoot.getDisplayContent(displayId);
         if (displayContent != null) {
             displayContent.pendingLayoutChanges |= changes;
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e4f6c27..f54add1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -129,7 +129,6 @@
 import com.android.internal.app.IAssistScreenshotReceiver;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.policy.IShortcutService;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
@@ -215,7 +214,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
@@ -238,7 +236,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
@@ -532,9 +529,10 @@
      * LAST_ANR_LIFETIME_DURATION_MSECS */
     String mLastANRState;
 
-    /** All DisplayContents in the world, kept here */
-    SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2);
+    // The root of the device window hierarchy.
+    RootWindowContainer mRoot;
 
+    // TODO: Move several of this states to the RootWindowContainer
     int mRotation = 0;
     int mLastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mAltOrientation = false;
@@ -546,8 +544,6 @@
 
     private final SparseIntArray mTmpTaskIds = new SparseIntArray();
 
-    private final ArrayList<Integer> mChangedStackList = new ArrayList();
-
     boolean mForceResizableTasks = false;
 
     int getDragLayerLocked() {
@@ -701,6 +697,7 @@
 
     boolean mAnimateWallpaperWithTarget;
 
+    // TODO: Move to RootWindowContainer
     AppWindowToken mFocusedApp = null;
 
     PowerManager mPowerManager;
@@ -745,6 +742,7 @@
 
     /** All of the TaskStacks in the window manager, unordered. For an ordered list call
      * DisplayContent.getStacks(). */
+    // TODO: Don't believe this is needed with the WindowContainer model.
     SparseArray<TaskStack> mStackIdToStack = new SparseArray<>();
 
     private final PointerEventDispatcher mPointerEventDispatcher;
@@ -884,17 +882,11 @@
     // since they won't be notified through the app window animator.
     final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
 
-    // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl
-    // instances will be replaced with an instance that writes a binary representation of all
-    // commands to mSurfaceTraceFd.
-    boolean mSurfaceTraceEnabled;
-    ParcelFileDescriptor mSurfaceTraceFd;
-    RemoteEventTrace mRemoteEventTrace;
 
     void openSurfaceTransaction() {
         synchronized (mWindowMap) {
-            if (mSurfaceTraceEnabled) {
-                mRemoteEventTrace.openSurfaceTransaction();
+            if (mRoot.mSurfaceTraceEnabled) {
+                mRoot.mRemoteEventTrace.openSurfaceTransaction();
             }
             SurfaceControl.openTransaction();
         }
@@ -902,8 +894,8 @@
 
     void closeSurfaceTransaction() {
         synchronized (mWindowMap) {
-            if (mSurfaceTraceEnabled) {
-                mRemoteEventTrace.closeSurfaceTransaction();
+            if (mRoot.mSurfaceTraceEnabled) {
+                mRoot.mRemoteEventTrace.closeSurfaceTransaction();
             }
             SurfaceControl.closeTransaction();
         }
@@ -976,6 +968,7 @@
     private WindowManagerService(Context context, InputManagerService inputManager,
             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
             WindowManagerPolicy policy) {
+        mRoot = new RootWindowContainer(this);
         mContext = context;
         mHaveInputMethods = haveInputMethods;
         mAllowBootMessages = showBootMsgs;
@@ -1502,7 +1495,7 @@
                 throw new IllegalStateException("Display has not been initialialized");
             }
 
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent == null) {
                 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
                         + displayId + ".  Aborting.");
@@ -1953,39 +1946,25 @@
 
     @Override
     public void enableSurfaceTrace(ParcelFileDescriptor pfd) {
-        int callingUid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
         if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
             throw new SecurityException("Only shell can call enableSurfaceTrace");
         }
-        final FileDescriptor fd = pfd.getFileDescriptor();
 
         synchronized (mWindowMap) {
-            if (mSurfaceTraceEnabled) {
-                disableSurfaceTrace();
-            }
-            mSurfaceTraceEnabled = true;
-            mRemoteEventTrace = new RemoteEventTrace(this, fd);
-            mSurfaceTraceFd = pfd;
-            for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
-                DisplayContent dc = mDisplayContents.valueAt(displayNdx);
-                dc.enableSurfaceTrace(fd);
-            }
+            mRoot.enableSurfaceTrace(pfd);
         }
     }
 
     @Override
     public void disableSurfaceTrace() {
-        int callingUid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
         if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID &&
             callingUid != Process.SYSTEM_UID) {
             throw new SecurityException("Only shell can call disableSurfaceTrace");
         }
-        mSurfaceTraceEnabled = false;
-        mRemoteEventTrace = null;
-        mSurfaceTraceFd = null;
-        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
-            DisplayContent dc = mDisplayContents.valueAt(displayNdx);
-            dc.disableSurfaceTrace();
+        synchronized (mWindowMap) {
+            mRoot.disableSurfaceTrace();
         }
     }
 
@@ -2002,15 +1981,7 @@
         synchronized(mWindowMap) {
             mScreenCaptureDisabled.put(userId, disabled);
             // Update secure surface for all windows belonging to this user.
-            for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
-                WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-                    final WindowState win = windows.get(winNdx);
-                    if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) {
-                        win.mWinAnimator.setSecureLocked(disabled);
-                    }
-                }
-            }
+            mRoot.setSecureSurfaceState(userId, disabled);
         }
     }
 
@@ -2093,20 +2064,7 @@
 
     public void updateAppOpsState() {
         synchronized(mWindowMap) {
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                final int numWindows = windows.size();
-                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                    final WindowState win = windows.get(winNdx);
-                    if (win.mAppOp != AppOpsManager.OP_NONE) {
-                        final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
-                                win.getOwningPackage());
-                        win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED ||
-                                mode == AppOpsManager.MODE_DEFAULT);
-                    }
-                }
-            }
+            mRoot.updateAppOpsState();
         }
     }
 
@@ -2672,7 +2630,7 @@
     }
 
     public boolean outOfMemoryWindow(Session session, IWindow client) {
-        long origId = Binder.clearCallingIdentity();
+        final long origId = Binder.clearCallingIdentity();
 
         try {
             synchronized (mWindowMap) {
@@ -2680,7 +2638,7 @@
                 if (win == null) {
                     return false;
                 }
-                return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
+                return mRoot.reclaimSomeSurfaceMemory(win.mWinAnimator, "from-client", false);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -3129,13 +3087,11 @@
                 mWaitingForConfig = false;
                 mLastFinishedFreezeSource = "new-config";
             }
-            boolean configChanged = mGlobalConfiguration.diff(config) != 0;
+            final boolean configChanged = mGlobalConfiguration.diff(config) != 0;
             if (!configChanged) {
                 return null;
             }
-            prepareFreezingAllTaskBounds();
-            mGlobalConfiguration = new Configuration(config);
-            return onConfigurationChanged();
+            return mRoot.onConfigurationChanged(config);
         }
     }
 
@@ -3149,26 +3105,6 @@
         }
     }
 
-    private void prepareFreezingAllTaskBounds() {
-        for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
-            mDisplayContents.valueAt(i).prepareFreezingTaskBounds();
-        }
-    }
-
-    private int[] onConfigurationChanged() {
-        mPolicy.onConfigurationChanged();
-
-        mChangedStackList.clear();
-
-        final int numDisplays = mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-            displayContent.onConfigurationChanged(mChangedStackList);
-        }
-
-        return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
-    }
-
     @Override
     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@@ -3970,44 +3906,11 @@
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mWindowMap) {
-                final DisplayContent displayContent = mDisplayContents.get(displayId);
-                boolean attachedToDisplay = false;
-                if (displayContent != null) {
-                    TaskStack stack = mStackIdToStack.get(stackId);
-                    if (stack == null) {
-                        if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId);
-
-                        stack = displayContent.getStackById(stackId);
-                        if (stack != null) {
-                            // It's already attached to the display...clear mDeferRemoval!
-                            stack.mDeferRemoval = false;
-                            attachedToDisplay = true;
-                        } else {
-                            stack = new TaskStack(this, stackId);
-                        }
-
-                        mStackIdToStack.put(stackId, stack);
-                        if (stackId == DOCKED_STACK_ID) {
-                            getDefaultDisplayContentLocked().mDividerControllerLocked
-                                    .notifyDockedStackExistsChanged(true);
-                        }
-                    }
-                    if (!attachedToDisplay) {
-                        stack.attachDisplayContent(displayContent);
-                    }
-                    displayContent.attachStack(stack, onTop);
-                    if (stack.getRawFullscreen()) {
-                        return null;
-                    }
-                    Rect bounds = new Rect();
-                    stack.getRawBounds(bounds);
-                    return bounds;
-                }
+                return mRoot.addStackToDisplay(stackId, displayId, onTop);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
-        return null;
     }
 
     public void detachStack(int stackId) {
@@ -4475,20 +4378,7 @@
     @Override
     public void closeSystemDialogs(String reason) {
         synchronized(mWindowMap) {
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                final int numWindows = windows.size();
-                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                    final WindowState w = windows.get(winNdx);
-                    if (w.mHasSurface) {
-                        try {
-                            w.mClient.closeSystemDialogs(reason);
-                        } catch (RemoteException e) {
-                        }
-                    }
-                }
-            }
+            mRoot.closeSystemDialogs(reason);
         }
     }
 
@@ -4677,11 +4567,7 @@
             mPolicy.enableKeyguard(true);
 
             // Hide windows that should not be seen by the new user.
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-                displayContent.switchUserStacks();
-            }
+            mRoot.switchUser();
             mWindowPlacerLocked.performSurfacePlacement();
 
             // Notify whether the docked stack exists for the current user
@@ -5066,26 +4952,10 @@
     private void showStrictModeViolation(int arg, int pid) {
         final boolean on = arg != 0;
         synchronized(mWindowMap) {
-            // Ignoring requests to enable the red border from clients
-            // which aren't on screen.  (e.g. Broadcast Receivers in
-            // the background..)
-            if (on) {
-                boolean isVisible = false;
-                final int numDisplays = mDisplayContents.size();
-                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                    final int numWindows = windows.size();
-                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                        final WindowState ws = windows.get(winNdx);
-                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
-                            isVisible = true;
-                            break;
-                        }
-                    }
-                }
-                if (!isVisible) {
-                    return;
-                }
+            // Ignoring requests to enable the red border from clients which aren't on screen.
+            // (e.g. Broadcast Receivers in the background..)
+            if (on && !mRoot.canShowStrictModeViolation(pid)) {
+                return;
             }
 
             if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
@@ -5220,7 +5090,7 @@
             boolean wallpaperOnly) {
         final DisplayContent displayContent;
         synchronized(mWindowMap) {
-            displayContent = getDisplayContentLocked(displayId);
+            displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent == null) {
                 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
                         + ": returning null. No Display for displayId=" + displayId);
@@ -5773,7 +5643,7 @@
             if (w.mHasSurface && !rotateSeamlessly) {
                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
                 w.mOrientationChanging = true;
-                mWindowPlacerLocked.mOrientationChangeComplete = false;
+                mRoot.mOrientationChangeComplete = false;
                 w.mLastFreezeDuration = 0;
             }
         }
@@ -6010,13 +5880,12 @@
     }
 
     /**
-     * Lists all availble windows in the system. The listing is written in the
-     * specified Socket's output stream with the following syntax:
-     * windowHashCodeInHexadecimal windowName
-     * Each line of the ouput represents a different window.
+     * Lists all available windows in the system. The listing is written in the specified Socket's
+     * output stream with the following syntax: windowHashCodeInHexadecimal windowName
+     * Each line of the output represents a different window.
      *
      * @param client The remote client to send the listing to.
-     * @return False if an error occured, true otherwise.
+     * @return false if an error occurred, true otherwise.
      */
     boolean viewServerListWindows(Socket client) {
         if (isSystemSecure()) {
@@ -6025,14 +5894,9 @@
 
         boolean result = true;
 
-        WindowList windows = new WindowList();
+        final WindowList windows = new WindowList();
         synchronized (mWindowMap) {
-            //noinspection unchecked
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-                windows.addAll(displayContent.getWindowList());
-            }
+            mRoot.getWindows(windows);
         }
 
         BufferedWriter out = null;
@@ -6259,20 +6123,8 @@
         }
 
         synchronized (mWindowMap) {
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                final int numWindows = windows.size();
-                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                    final WindowState w = windows.get(winNdx);
-                    if (System.identityHashCode(w) == hashCode) {
-                        return w;
-                    }
-                }
-            }
+            return mRoot.findWindow(hashCode);
         }
-
-        return null;
     }
 
     /**
@@ -6930,7 +6782,7 @@
 
     private void displayReady(int displayId) {
         synchronized(mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null) {
                 mAnimator.addDisplayLocked(displayId);
                 displayContent.initializeDisplayBaseInfo();
@@ -7771,7 +7623,7 @@
     @Override
     public void getInitialDisplaySize(int displayId, Point size) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 size.x = displayContent.mInitialDisplayWidth;
                 size.y = displayContent.mInitialDisplayHeight;
@@ -7782,7 +7634,7 @@
     @Override
     public void getBaseDisplaySize(int displayId, Point size) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 size.x = displayContent.mBaseDisplayWidth;
                 size.y = displayContent.mBaseDisplayHeight;
@@ -7809,7 +7661,7 @@
                 final int MIN_WIDTH = 200;
                 final int MIN_HEIGHT = 200;
                 final int MAX_SCALE = 2;
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
                     width = Math.min(Math.max(width, MIN_WIDTH),
                             displayContent.mInitialDisplayWidth * MAX_SCALE);
@@ -7839,7 +7691,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
                     if (mode < 0 || mode > 1) {
                         mode = 0;
@@ -7922,7 +7774,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
                     setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
                             displayContent.mInitialDisplayHeight);
@@ -7938,7 +7790,7 @@
     @Override
     public int getInitialDisplayDensity(int displayId) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 return displayContent.mInitialDisplayDensity;
             }
@@ -7949,7 +7801,7 @@
     @Override
     public int getBaseDisplayDensity(int displayId) {
         synchronized (mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
             if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
                 return displayContent.mBaseDisplayDensity;
             }
@@ -7975,7 +7827,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null && mCurrentUserId == targetUserId) {
                     setForcedDisplayDensityLocked(displayContent, density);
                 }
@@ -8006,7 +7858,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null && mCurrentUserId == callingUserId) {
                     setForcedDisplayDensityLocked(displayContent,
                             displayContent.mInitialDisplayDensity);
@@ -8072,7 +7924,7 @@
         mWindowPlacerLocked.performSurfacePlacement();
     }
 
-    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
+    void configureDisplayPolicyLocked(DisplayContent displayContent) {
         mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
                 displayContent.mBaseDisplayWidth,
                 displayContent.mBaseDisplayHeight,
@@ -8095,7 +7947,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                DisplayContent displayContent = getDisplayContentLocked(displayId);
+                DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
                     setOverscanLocked(displayContent, left, top, right, bottom);
                 }
@@ -8162,7 +8014,7 @@
             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
             w.mOrientationChanging = true;
             w.mLastFreezeDuration = 0;
-            mWindowPlacerLocked.mOrientationChangeComplete = false;
+            mRoot.mOrientationChangeComplete = false;
             if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
                 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
                 // XXX should probably keep timeout from
@@ -8196,7 +8048,7 @@
         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
                 "Wallpaper layer changed: assigning layers + relayout");
         moveInputMethodWindowsIfNeededLocked(true);
-        mWindowPlacerLocked.mWallpaperMayChange = true;
+        mRoot.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.
         mFocusMayChange = true;
@@ -8345,20 +8197,20 @@
         if (hold != state) {
             if (hold) {
                 if (DEBUG_KEEP_SCREEN_ON) {
-                    Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to " +
-                            mWindowPlacerLocked.mHoldScreenWindow);
+                    Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to "
+                            + mRoot.mHoldScreenWindow);
                 }
-                mLastWakeLockHoldingWindow = mWindowPlacerLocked.mHoldScreenWindow;
+                mLastWakeLockHoldingWindow = mRoot.mHoldScreenWindow;
                 mLastWakeLockObscuringWindow = null;
                 mHoldingScreenWakeLock.acquire();
                 mPolicy.keepScreenOnStartedLw();
             } else {
                 if (DEBUG_KEEP_SCREEN_ON) {
-                    Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by " +
-                            mWindowPlacerLocked.mObsuringWindow);
+                    Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by "
+                            + mRoot.mObsuringWindow);
                 }
                 mLastWakeLockHoldingWindow = null;
-                mLastWakeLockObscuringWindow = mWindowPlacerLocked.mObsuringWindow;
+                mLastWakeLockObscuringWindow = mRoot.mObsuringWindow;
                 mPolicy.keepScreenOnStoppedLw();
                 mHoldingScreenWakeLock.release();
             }
@@ -8379,17 +8231,6 @@
         }
     }
 
-    boolean needsLayout() {
-        final int numDisplays = mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-            if (displayContent.layoutNeeded) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     /** If a window that has an animation specifying a colored background and the current wallpaper
      * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
      * suddenly disappear. */
@@ -8404,108 +8245,8 @@
         return winAnimator.mAnimLayer;
     }
 
-    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
-                                           boolean secure) {
-        final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
-        boolean leakedSurface = false;
-        boolean killedApps = false;
-
-        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
-                winAnimator.mSession.mPid, operation);
-
-        final long callingIdentity = Binder.clearCallingIdentity();
-        try {
-            // There was some problem...   first, do a sanity check of the window list to make sure
-            // we haven't left any dangling surfaces around.
-
-            Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                final int numWindows = windows.size();
-                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                    final WindowState ws = windows.get(winNdx);
-                    final WindowStateAnimator wsa = ws.mWinAnimator;
-                    if (wsa.mSurfaceController == null) {
-                        continue;
-                    }
-                    if (!mSessions.contains(wsa.mSession)) {
-                        Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
-                                + ws + " surface=" + wsa.mSurfaceController
-                                + " token=" + ws.mToken
-                                + " pid=" + ws.mSession.mPid
-                                + " uid=" + ws.mSession.mUid);
-                        wsa.destroySurface();
-                        mForceRemoves.add(ws);
-                        leakedSurface = true;
-                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
-                        Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
-                                + ws + " surface=" + wsa.mSurfaceController
-                                + " token=" + ws.mAppToken
-                                + " saved=" + ws.hasSavedSurface());
-                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
-                        wsa.destroySurface();
-                        leakedSurface = true;
-                    }
-                }
-            }
-
-            if (!leakedSurface) {
-                Slog.w(TAG_WM, "No leaked surfaces; killing applicatons!");
-                SparseIntArray pidCandidates = new SparseIntArray();
-                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-                    final int numWindows = windows.size();
-                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                        final WindowState ws = windows.get(winNdx);
-                        if (mForceRemoves.contains(ws)) {
-                            continue;
-                        }
-                        WindowStateAnimator wsa = ws.mWinAnimator;
-                        if (wsa.mSurfaceController != null) {
-                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
-                        }
-                    }
-                    if (pidCandidates.size() > 0) {
-                        int[] pids = new int[pidCandidates.size()];
-                        for (int i=0; i<pids.length; i++) {
-                            pids[i] = pidCandidates.keyAt(i);
-                        }
-                        try {
-                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
-                                killedApps = true;
-                            }
-                        } catch (RemoteException e) {
-                        }
-                    }
-                }
-            }
-
-            if (leakedSurface || killedApps) {
-                // We managed to reclaim some memory, so get rid of the trouble
-                // surface and ask the app to request another one.
-                Slog.w(TAG_WM, "Looks like we have reclaimed some memory, clearing surface for retry.");
-                if (surfaceController != null) {
-                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
-                            "RECOVER DESTROY", false);
-                    winAnimator.destroySurface();
-                    scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
-                }
-
-                try {
-                    winAnimator.mWin.mClient.dispatchGetNewSurface();
-                } catch (RemoteException e) {
-                }
-            }
-        } finally {
-            Binder.restoreCallingIdentity(callingIdentity);
-        }
-
-        return leakedSurface || killedApps;
-    }
-
     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
-        WindowState newFocus = computeFocusedWindowLocked();
+        WindowState newFocus = mRoot.computeFocusedWindow();
         if (mCurrentFocus != newFocus) {
             Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
             // This check makes sure that we don't already have the focus
@@ -8519,7 +8260,7 @@
                             && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
             if (imWindowChanged) {
                 displayContent.layoutNeeded = true;
-                newFocus = computeFocusedWindowLocked();
+                newFocus = mRoot.computeFocusedWindow();
             }
 
             if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " +
@@ -8572,18 +8313,6 @@
         return false;
     }
 
-    private WindowState computeFocusedWindowLocked() {
-        final int displayCount = mDisplayContents.size();
-        for (int i = 0; i < displayCount; i++) {
-            final DisplayContent displayContent = mDisplayContents.valueAt(i);
-            final WindowState win = displayContent.findFocusedWindow();
-            if (win != null) {
-                return win;
-            }
-        }
-        return null;
-    }
-
     void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
         if (mDisplayFrozen) {
             return;
@@ -9118,19 +8847,6 @@
         }
     }
 
-    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
-        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
-        if (mDisplayReady) {
-            final int numDisplays = mDisplayContents.size();
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-                displayContent.dump("  ", pw);
-            }
-        } else {
-            pw.println("  NO DISPLAY");
-        }
-    }
-
     void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
         pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
@@ -9139,18 +8855,8 @@
 
     void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
-        final int numDisplays = mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
-            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
-                final WindowState w = windowList.get(winNdx);
-                if (windows == null || windows.contains(w)) {
-                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
-                            pw.print(w); pw.println(":");
-                    w.dump(pw, "    ", dumpAll || windows != null);
-                }
-            }
-        }
+        mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
+
         if (mInputMethodDialogs.size() > 0) {
             pw.println();
             pw.println("  Input method dialogs:");
@@ -9293,16 +8999,9 @@
             mLayersController.dump(pw, "  ");
             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
-            if (needsLayout()) {
-                pw.print("  layoutNeeded on displays=");
-                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
-                    if (displayContent.layoutNeeded) {
-                        pw.print(displayContent.getDisplayId());
-                    }
-                }
-                pw.println();
-            }
+
+            mRoot.dumpLayoutNeededDisplayIds(pw);
+
             pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
                     pw.print(" windows="); pw.print(mWindowsFreezingScreen);
@@ -9324,54 +9023,21 @@
         }
     }
 
-    boolean dumpWindows(PrintWriter pw, String name, String[] args,
-            int opti, boolean dumpAll) {
+    boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti, boolean dumpAll) {
         WindowList windows = new WindowList();
         if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
             final boolean appsOnly = name.contains("apps");
             final boolean visibleOnly = name.contains("visible");
             synchronized(mWindowMap) {
                 if (appsOnly) {
-                    dumpDisplayContentsLocked(pw, true);
+                    mRoot.dumpDisplayContents(pw);
                 }
 
-                final int numDisplays = mDisplayContents.size();
-                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                    final WindowList windowList =
-                            mDisplayContents.valueAt(displayNdx).getWindowList();
-                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
-                        final WindowState w = windowList.get(winNdx);
-                        if ((!visibleOnly || w.mWinAnimator.getShown())
-                                && (!appsOnly || w.mAppToken != null)) {
-                            windows.add(w);
-                        }
-                    }
-                }
+                mRoot.getWindows(windows, visibleOnly, appsOnly);
             }
         } else {
-            int objectId = 0;
-            // See if this is an object ID.
-            try {
-                objectId = Integer.parseInt(name, 16);
-                name = null;
-            } catch (RuntimeException e) {
-            }
             synchronized(mWindowMap) {
-                final int numDisplays = mDisplayContents.size();
-                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                    final WindowList windowList =
-                            mDisplayContents.valueAt(displayNdx).getWindowList();
-                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
-                        final WindowState w = windowList.get(winNdx);
-                        if (name != null) {
-                            if (w.mAttrs.getTitle().toString().contains(name)) {
-                                windows.add(w);
-                            }
-                        } else if (System.identityHashCode(w) == objectId) {
-                            windows.add(w);
-                        }
-                    }
-                }
+                mRoot.getWindowsByName(windows, name);
             }
         }
 
@@ -9421,7 +9087,7 @@
         dumpWindowsNoHeaderLocked(pw, true, null);
         pw.println();
         pw.println("Last ANR continued");
-        dumpDisplayContentsLocked(pw, true);
+        mRoot.dumpDisplayContents(pw);
         pw.close();
         mLastANRState = sw.toString();
 
@@ -9506,7 +9172,7 @@
                 return;
             } else if ("displays".equals(cmd) || "d".equals(cmd)) {
                 synchronized(mWindowMap) {
-                    dumpDisplayContentsLocked(pw, true);
+                    mRoot.dumpDisplayContents(pw);
                 }
                 return;
             } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
@@ -9566,7 +9232,7 @@
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
             }
-            dumpDisplayContentsLocked(pw, dumpAll);
+            mRoot.dumpDisplayContents(pw);
             pw.println();
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
@@ -9586,61 +9252,17 @@
         synchronized (mWindowMap) { }
     }
 
-    private DisplayContent newDisplayContentLocked(final Display display) {
-        DisplayContent displayContent = new DisplayContent(display, this);
-        final int displayId = display.getDisplayId();
-        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
-        mDisplayContents.put(displayId, displayContent);
-
-        DisplayInfo displayInfo = displayContent.getDisplayInfo();
-        final Rect rect = new Rect();
-        mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
-        displayInfo.overscanLeft = rect.left;
-        displayInfo.overscanTop = rect.top;
-        displayInfo.overscanRight = rect.right;
-        displayInfo.overscanBottom = rect.bottom;
-        if (mDisplayManagerInternal != null) {
-            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId, displayInfo);
-            configureDisplayPolicyLocked(displayContent);
-
-            // TODO: Create an input channel for each display with touch capability.
-            if (displayId == Display.DEFAULT_DISPLAY) {
-                displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent);
-                registerPointerEventListener(displayContent.mTapDetector);
-                registerPointerEventListener(mMousePositionTracker);
-            }
-        }
-
-        return displayContent;
-    }
-
+    // TODO: All the display method below should probably be moved into the RootWindowContainer...
     public void createDisplayContentLocked(final Display display) {
         if (display == null) {
             throw new IllegalArgumentException("getDisplayContent: display must not be null");
         }
-        getDisplayContentLocked(display.getDisplayId());
-    }
-
-    /**
-     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
-     * there is a Display for the displayId.
-     * @param displayId The display the caller is interested in.
-     * @return The DisplayContent associated with displayId or null if there is no Display for it.
-     */
-    public DisplayContent getDisplayContentLocked(final int displayId) {
-        DisplayContent displayContent = mDisplayContents.get(displayId);
-        if (displayContent == null) {
-            final Display display = mDisplayManager.getDisplay(displayId);
-            if (display != null) {
-                displayContent = newDisplayContentLocked(display);
-            }
-        }
-        return displayContent;
+        mRoot.getDisplayContent(display.getDisplayId());
     }
 
     // There is an inherent assumption that this will never return null.
     public DisplayContent getDefaultDisplayContentLocked() {
-        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
+        return mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
     }
 
     public WindowList getDefaultWindowListLocked() {
@@ -9653,20 +9275,11 @@
 
     /**
      * Return the list of WindowStates associated on the passed display.
-     * @param display The screen to return windows from.
-     * @return The list of WindowStates on the screen, or null if the there is no screen.
-     */
-    public WindowList getWindowListLocked(final Display display) {
-        return getWindowListLocked(display.getDisplayId());
-    }
-
-    /**
-     * Return the list of WindowStates associated on the passed display.
      * @param displayId The screen to return windows from.
      * @return The list of WindowStates on the screen, or null if the there is no screen.
      */
-    public WindowList getWindowListLocked(final int displayId) {
-        final DisplayContent displayContent = getDisplayContentLocked(displayId);
+    WindowList getWindowListLocked(final int displayId) {
+        final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
         return displayContent != null ? displayContent.getWindowList() : null;
     }
 
@@ -9690,7 +9303,7 @@
     }
 
     private void handleDisplayRemovedLocked(int displayId) {
-        final DisplayContent displayContent = getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
         if (displayContent != null) {
             displayContent.removeIfPossible();
         }
@@ -9703,7 +9316,7 @@
     }
 
     private void handleDisplayChangedLocked(int displayId) {
-        final DisplayContent displayContent = getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
         if (displayContent != null) {
             displayContent.updateDisplayInfo();
         }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 1c0d830..637adb9 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2507,7 +2507,7 @@
                 && mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + this);
             mOrientationChanging = true;
-            mService.mWindowPlacerLocked.mOrientationChangeComplete = false;
+            mService.mRoot.mOrientationChangeComplete = false;
         }
         mLastFreezeDuration = 0;
         setDisplayLayoutNeeded();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index ce101e7..cbb5040 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -685,7 +685,7 @@
             }
         } catch (OutOfResourcesException e) {
             Slog.w(TAG, "OutOfResourcesException creating surface");
-            mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
+            mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
             mDrawState = NO_SURFACE;
             return null;
         } catch (Exception e) {
@@ -1020,7 +1020,7 @@
                     + " screen=" + (screenAnimation ?
                             screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
             return;
-        } else if (mIsWallpaper && mService.mWindowPlacerLocked.mWallpaperActionPending) {
+        } else if (mIsWallpaper && mService.mRoot.mWallpaperActionPending) {
             return;
         } else if (mWin.isDragResizeChanged()) {
             // This window is awaiting a relayout because user just started (or ended)
@@ -1850,7 +1850,7 @@
     }
 
     void reclaimSomeSurfaceMemory(String operation, boolean secure) {
-        mService.reclaimSomeSurfaceMemoryLocked(this, operation, secure);
+        mService.mRoot.reclaimSomeSurfaceMemory(this, operation, secure);
     }
 
     boolean getShown() {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index cc72352..368484a 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -101,8 +101,9 @@
                     s, name, w, h, format, flags);
         }
 
-        if (mService.mSurfaceTraceEnabled) {
-            mSurfaceControl = new RemoteSurfaceTrace(mService.mSurfaceTraceFd.getFileDescriptor(),
+        if (mService.mRoot.mSurfaceTraceEnabled) {
+            mSurfaceControl = new RemoteSurfaceTrace(
+                    mService.mRoot.mSurfaceTraceFd.getFileDescriptor(),
                     mSurfaceControl, animator.mWin);
         }
     }
@@ -116,7 +117,7 @@
     }
 
 
-    void logSurface(String msg, RuntimeException where) {
+    private void logSurface(String msg, RuntimeException where) {
         String str = "  SURFACE " + msg + ": " + title;
         if (where != null) {
             Slog.i(TAG, str, where);
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 13d3501..a66a49b 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1,65 +1,36 @@
+
 package com.android.server.wm;
 
 import static android.app.ActivityManagerInternal.APP_TRANSITION_SAVED_SURFACE;
 import static android.app.ActivityManagerInternal.APP_TRANSITION_STARTING_WINDOW;
 import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
 import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
-import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.DO_TRAVERSAL;
 import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION_STARTING;
-import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN;
-import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
 import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE;
-import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
 import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
-import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
-import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.Debug;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
 import android.os.Trace;
-import android.provider.Settings;
 import android.util.ArraySet;
 import android.util.Slog;
 import android.view.Display;
@@ -98,46 +69,12 @@
     static final int SET_TURN_ON_SCREEN                 = 1 << 4;
     static final int SET_WALLPAPER_ACTION_PENDING       = 1 << 5;
 
-    boolean mWallpaperMayChange = false;
-    boolean mOrientationChangeComplete = true;
-    boolean mWallpaperActionPending = false;
-
-    private boolean mWallpaperForceHidingChanged = false;
-    private Object mLastWindowFreezeSource = null;
-    private Session mHoldScreen = null;
-    private boolean mObscured = false;
-    private boolean mSyswin = false;
-    private float mScreenBrightness = -1;
-    private float mButtonBrightness = -1;
-    private long mUserActivityTimeout = -1;
-    private boolean mUpdateRotation = false;
     private final Rect mTmpStartRect = new Rect();
     private final Rect mTmpContentRect = new Rect();
 
-    // Set to true when the display contains content to show the user.
-    // When false, the display manager may choose to mirror or blank the display.
-    private boolean mDisplayHasContent = false;
-
-    // Only set while traversing the default display based on its content.
-    // Affects the behavior of mirroring on secondary displays.
-    private boolean mObscureApplicationContentOnSecondaryDisplays = false;
-
-    private float mPreferredRefreshRate = 0;
-
-    private int mPreferredModeId = 0;
-
     private boolean mTraversalScheduled;
     private int mDeferDepth = 0;
 
-    private boolean mSustainedPerformanceModeEnabled = false;
-    private boolean mSustainedPerformanceModeCurrent = false;
-
-    // Following variables are for debugging screen wakelock only.
-    // Last window that requires screen wakelock
-    WindowState mHoldScreenWindow = null;
-    // Last window that obscures all windows below
-    WindowState mObsuringWindow = null;
-
     private static final class LayerAndToken {
         public int layer;
         public AppWindowToken token;
@@ -179,7 +116,7 @@
             mService.mH.removeMessages(DO_TRAVERSAL);
             loopCount--;
         } while (mTraversalScheduled && loopCount > 0);
-        mWallpaperActionPending = false;
+        mService.mRoot.mWallpaperActionPending = false;
     }
 
     private void performSurfacePlacementLoop() {
@@ -227,11 +164,11 @@
         }
 
         try {
-            performSurfacePlacementInner(recoveringMemory);
+            mService.mRoot.performSurfacePlacement(recoveringMemory);
 
             mInLayout = false;
 
-            if (mService.needsLayout()) {
+            if (mService.mRoot.layoutNeeded()) {
                 if (++mLayoutRepeatCount < 6) {
                     requestTraversal();
                 } else {
@@ -261,625 +198,6 @@
         }
     }
 
-    // "Something has changed!  Let's make it correct now."
-    private void performSurfacePlacementInner(boolean recoveringMemory) {
-        if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
-                + Debug.getCallers(3));
-
-        int i;
-        boolean updateInputWindowsNeeded = false;
-
-        if (mService.mFocusMayChange) {
-            mService.mFocusMayChange = false;
-            updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
-                    UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
-        }
-
-        // Initialize state of exiting tokens.
-        final int numDisplays = mService.mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
-                displayContent.mExitingTokens.get(i).hasVisible = false;
-            }
-        }
-
-        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
-            // Initialize state of exiting applications.
-            final AppTokenList exitingAppTokens =
-                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
-            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
-                exitingAppTokens.get(tokenNdx).hasVisible = false;
-            }
-        }
-
-        mHoldScreen = null;
-        mHoldScreenWindow = null;
-        mObsuringWindow = null;
-        mScreenBrightness = -1;
-        mButtonBrightness = -1;
-        mUserActivityTimeout = -1;
-        mObscureApplicationContentOnSecondaryDisplays = false;
-        mSustainedPerformanceModeCurrent = false;
-        mService.mTransactionSequence++;
-
-        // TODO(multi-display): Perform same actions on all displays.
-        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
-        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
-        final int defaultDw = defaultInfo.logicalWidth;
-        final int defaultDh = defaultInfo.logicalHeight;
-
-        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
-                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
-        mService.openSurfaceTransaction();
-        try {
-            applySurfaceChangesTransaction(recoveringMemory, numDisplays, defaultDw, defaultDh);
-        } catch (RuntimeException e) {
-            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
-        } finally {
-            mService.closeSurfaceTransaction();
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
-                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
-        }
-
-        final WindowList defaultWindows = defaultDisplay.getWindowList();
-
-        // If we are ready to perform an app transition, check through
-        // all of the app tokens to be shown and see if they are ready
-        // to go.
-        if (mService.mAppTransition.isReady()) {
-            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
-            if (DEBUG_LAYOUT_REPEATS)
-                debugLayoutRepeats("after handleAppTransitionReadyLocked",
-                        defaultDisplay.pendingLayoutChanges);
-        }
-
-        if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
-            // We have finished the animation of an app transition.  To do
-            // this, we have delayed a lot of operations like showing and
-            // hiding apps, moving apps in Z-order, etc.  The app token list
-            // reflects the correct Z-order, but the window list may now
-            // be out of sync with it.  So here we will just rebuild the
-            // entire app window list.  Fun!
-            defaultDisplay.pendingLayoutChanges |=
-                    mService.handleAnimatingStoppedAndTransitionLocked();
-            if (DEBUG_LAYOUT_REPEATS)
-                debugLayoutRepeats("after handleAnimStopAndXitionLock",
-                        defaultDisplay.pendingLayoutChanges);
-        }
-
-        if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
-                && !mService.mAppTransition.isReady()) {
-            // At this point, there was a window with a wallpaper that
-            // was force hiding other windows behind it, but now it
-            // is going away.  This may be simple -- just animate
-            // away the wallpaper and its window -- or it may be
-            // hard -- the wallpaper now needs to be shown behind
-            // something that was hidden.
-            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
-            if (DEBUG_LAYOUT_REPEATS)
-                debugLayoutRepeats("after animateAwayWallpaperLocked",
-                        defaultDisplay.pendingLayoutChanges);
-        }
-        mWallpaperForceHidingChanged = false;
-
-        if (mWallpaperMayChange) {
-            if (DEBUG_WALLPAPER_LIGHT)
-                Slog.v(TAG, "Wallpaper may change!  Adjusting");
-            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
-                    defaultDisplay.pendingLayoutChanges);
-        }
-
-        if (mService.mFocusMayChange) {
-            mService.mFocusMayChange = false;
-            if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
-                    false /*updateInputWindows*/)) {
-                updateInputWindowsNeeded = true;
-                defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
-            }
-        }
-
-        if (mService.needsLayout()) {
-            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
-            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
-                    defaultDisplay.pendingLayoutChanges);
-        }
-
-        for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
-            WindowState win = mService.mResizingWindows.get(i);
-            if (win.mAppFreezing) {
-                // Don't remove this window until rotation has completed.
-                continue;
-            }
-            // Discard the saved surface if window size is changed, it can't be reused.
-            if (win.mAppToken != null) {
-                win.mAppToken.destroySavedSurfaces();
-            }
-            win.reportResized();
-            mService.mResizingWindows.remove(i);
-        }
-
-        if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG,
-                "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete);
-        if (mOrientationChangeComplete) {
-            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
-                mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
-                mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
-                mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
-            }
-            mService.stopFreezingDisplayLocked();
-        }
-
-        // Destroy the surface of any windows that are no longer visible.
-        boolean wallpaperDestroyed = false;
-        i = mService.mDestroySurface.size();
-        if (i > 0) {
-            do {
-                i--;
-                WindowState win = mService.mDestroySurface.get(i);
-                win.mDestroying = false;
-                if (mService.mInputMethodWindow == win) {
-                    mService.mInputMethodWindow = null;
-                }
-                if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
-                    wallpaperDestroyed = true;
-                }
-                win.destroyOrSaveSurface();
-            } while (i > 0);
-            mService.mDestroySurface.clear();
-        }
-
-        // Time to remove any exiting tokens?
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
-            for (i = exitingTokens.size() - 1; i >= 0; i--) {
-                WindowToken token = exitingTokens.get(i);
-                if (!token.hasVisible) {
-                    exitingTokens.remove(i);
-                    if (token.windowType == TYPE_WALLPAPER) {
-                        mWallpaperControllerLocked.removeWallpaperToken(token);
-                    }
-                }
-            }
-        }
-
-        // Time to remove any exiting applications?
-        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
-            // Initialize state of exiting applications.
-            final AppTokenList exitingAppTokens =
-                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
-            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
-                AppWindowToken token = exitingAppTokens.get(i);
-                if (!token.hasVisible && !mService.mClosingApps.contains(token) &&
-                        (!token.mIsExiting || token.isEmpty())) {
-                    // Make sure there is no animation running on this token,
-                    // so any windows associated with it will be removed as
-                    // soon as their animations are complete
-                    token.mAppAnimator.clearAnimation();
-                    token.mAppAnimator.animating = false;
-                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
-                            "performLayout: App token exiting now removed" + token);
-                    token.removeIfPossible();
-                }
-            }
-        }
-
-        if (wallpaperDestroyed) {
-            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-            defaultDisplay.layoutNeeded = true;
-        }
-
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            if (displayContent.pendingLayoutChanges != 0) {
-                displayContent.layoutNeeded = true;
-            }
-        }
-
-        // Finally update all input windows now that the window changes have stabilized.
-        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
-
-        mService.setHoldScreenLocked(mHoldScreen);
-        if (!mService.mDisplayFrozen) {
-            if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) {
-                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
-            } else {
-                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
-                        toBrightnessOverride(mScreenBrightness));
-            }
-            if (mButtonBrightness < 0
-                    || mButtonBrightness > 1.0f) {
-                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
-            } else {
-                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
-                        toBrightnessOverride(mButtonBrightness));
-            }
-            mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
-                    mUserActivityTimeout);
-        }
-
-        if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
-            mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
-            mService.mPowerManagerInternal.powerHint(
-                    mService.mPowerManagerInternal.POWER_HINT_SUSTAINED_PERFORMANCE_MODE,
-                    (mSustainedPerformanceModeEnabled ? 1 : 0));
-        }
-
-        if (mService.mTurnOnScreen) {
-            if (mService.mAllowTheaterModeWakeFromLayout
-                    || Settings.Global.getInt(mService.mContext.getContentResolver(),
-                        Settings.Global.THEATER_MODE_ON, 0) == 0) {
-                if (DEBUG_VISIBILITY || DEBUG_POWER) {
-                    Slog.v(TAG, "Turning screen on after layout!");
-                }
-                mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
-                        "android.server.wm:TURN_ON");
-            }
-            mService.mTurnOnScreen = false;
-        }
-
-        if (mUpdateRotation) {
-            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
-            if (mService.updateRotationUncheckedLocked(false)) {
-                mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
-            } else {
-                mUpdateRotation = false;
-            }
-        }
-
-        if (mService.mWaitingForDrawnCallback != null ||
-                (mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
-                        !mUpdateRotation)) {
-            mService.checkDrawnWindowsLocked();
-        }
-
-        final int N = mService.mPendingRemove.size();
-        if (N > 0) {
-            if (mService.mPendingRemoveTmp.length < N) {
-                mService.mPendingRemoveTmp = new WindowState[N+10];
-            }
-            mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
-            mService.mPendingRemove.clear();
-            DisplayContentList displayList = new DisplayContentList();
-            for (i = 0; i < N; i++) {
-                final WindowState w = mService.mPendingRemoveTmp[i];
-                w.removeImmediately();
-                final DisplayContent displayContent = w.getDisplayContent();
-                if (displayContent != null && !displayList.contains(displayContent)) {
-                    displayList.add(displayContent);
-                }
-            }
-
-            for (DisplayContent displayContent : displayList) {
-                mService.mLayersController.assignLayersLocked(displayContent.getWindowList());
-                displayContent.layoutNeeded = true;
-            }
-        }
-
-        // Remove all deferred displays stacks, tasks, and activities.
-        for (int displayNdx = mService.mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
-            mService.mDisplayContents.valueAt(displayNdx).checkCompleteDeferredRemoval();
-        }
-
-        if (updateInputWindowsNeeded) {
-            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
-        }
-        mService.setFocusTaskRegionLocked();
-
-        // Check to see if we are now in a state where the screen should
-        // be enabled, because the window obscured flags have changed.
-        mService.enableScreenIfNeededLocked();
-
-        mService.scheduleAnimationLocked();
-        mService.mWindowPlacerLocked.destroyPendingSurfaces();
-
-        if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
-                "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
-    }
-
-    private void applySurfaceChangesTransaction(boolean recoveringMemory, int numDisplays,
-            int defaultDw, int defaultDh) {
-        if (mService.mWatermark != null) {
-            mService.mWatermark.positionSurface(defaultDw, defaultDh);
-        }
-        if (mService.mStrictModeFlash != null) {
-            mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
-        }
-        if (mService.mCircularDisplayMask != null) {
-            mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
-                    mService.mRotation);
-        }
-        if (mService.mEmulatorDisplayOverlay != null) {
-            mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
-                    mService.mRotation);
-        }
-
-        boolean focusDisplayed = false;
-
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
-            boolean updateAllDrawn = false;
-            WindowList windows = displayContent.getWindowList();
-            DisplayInfo displayInfo = displayContent.getDisplayInfo();
-            final int displayId = displayContent.getDisplayId();
-            final int dw = displayInfo.logicalWidth;
-            final int dh = displayInfo.logicalHeight;
-            final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
-
-            // Reset for each display.
-            mDisplayHasContent = false;
-            mPreferredRefreshRate = 0;
-            mPreferredModeId = 0;
-
-            int repeats = 0;
-            do {
-                repeats++;
-                if (repeats > 6) {
-                    Slog.w(TAG, "Animation repeat aborted after too many iterations");
-                    displayContent.layoutNeeded = false;
-                    break;
-                }
-
-                if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
-                        "On entry to LockedInner", displayContent.pendingLayoutChanges);
-
-                if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
-                        mWallpaperControllerLocked.adjustWallpaperWindows()) {
-                    mService.mLayersController.assignLayersLocked(windows);
-                    displayContent.layoutNeeded = true;
-                }
-
-                if (isDefaultDisplay
-                        && (displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
-                    if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
-                    if (mService.updateOrientationFromAppTokensLocked(true)) {
-                        displayContent.layoutNeeded = true;
-                        mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
-                    }
-                }
-
-                if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
-                    displayContent.layoutNeeded = true;
-                }
-
-                // FIRST LOOP: Perform a layout, if needed.
-                if (repeats < LAYOUT_REPEAT_THRESHOLD) {
-                    performLayoutLockedInner(displayContent, repeats == 1,
-                            false /* updateInputWindows */);
-                } else {
-                    Slog.w(TAG, "Layout repeat skipped after too many iterations");
-                }
-
-                // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
-                // it is animating.
-                displayContent.pendingLayoutChanges = 0;
-
-                if (isDefaultDisplay) {
-                    mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
-                    for (int i = windows.size() - 1; i >= 0; i--) {
-                        WindowState w = windows.get(i);
-                        if (w.mHasSurface) {
-                            mService.mPolicy.applyPostLayoutPolicyLw(
-                                    w, w.mAttrs, w.getParentWindow());
-                        }
-                    }
-                    displayContent.pendingLayoutChanges |=
-                            mService.mPolicy.finishPostLayoutPolicyLw();
-                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishPostLayoutPolicyLw",
-                            displayContent.pendingLayoutChanges);
-                }
-            } while (displayContent.pendingLayoutChanges != 0);
-
-            mObscured = false;
-            mSyswin = false;
-            displayContent.resetDimming();
-
-            // Only used if default window
-            final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
-
-            for (int i = windows.size() - 1; i >= 0; i--) {
-                WindowState w = windows.get(i);
-                final Task task = w.getTask();
-                final boolean obscuredChanged = w.mObscured != mObscured;
-
-                // Update effect.
-                w.mObscured = mObscured;
-                if (!mObscured) {
-                    handleNotObscuredLocked(w, displayInfo);
-                }
-
-                w.applyDimLayerIfNeeded();
-
-                if (isDefaultDisplay && obscuredChanged
-                        && mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) {
-                    // This is the wallpaper target and its obscured state
-                    // changed... make sure the current wallaper's visibility
-                    // has been updated accordingly.
-                    mWallpaperControllerLocked.updateWallpaperVisibility();
-                }
-
-                final WindowStateAnimator winAnimator = w.mWinAnimator;
-
-                // If the window has moved due to its containing content frame changing, then
-                // notify the listeners and optionally animate it. Simply checking a change of
-                // position is not enough, because being move due to dock divider is not a trigger
-                // for animation.
-                if (w.hasMoved()) {
-                    // Frame has moved, containing content frame has also moved, and we're not
-                    // currently animating... let's do something.
-                    final int left = w.mFrame.left;
-                    final int top = w.mFrame.top;
-                    final boolean adjustedForMinimizedDockOrIme = task != null
-                                && (task.mStack.isAdjustedForMinimizedDockedStack()
-                                    || task.mStack.isAdjustedForIme());
-                    if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
-                            && !w.isDragResizing() && !adjustedForMinimizedDockOrIme
-                            && (task == null || w.getTask().mStack.hasMovementAnimations())
-                            && !w.mWinAnimator.mLastHidden) {
-                        winAnimator.setMoveAnimation(left, top);
-                    }
-
-                    //TODO (multidisplay): Accessibility supported only for the default display.
-                    if (mService.mAccessibilityController != null
-                            && displayId == Display.DEFAULT_DISPLAY) {
-                        mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
-                    }
-
-                    try {
-                        w.mClient.moved(left, top);
-                    } catch (RemoteException e) {
-                    }
-                    w.mMovedByResize = false;
-                }
-
-                //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
-                w.mContentChanged = false;
-
-                // Moved from updateWindowsAndWallpaperLocked().
-                if (w.mHasSurface) {
-                    // Take care of the window being ready to display.
-                    final boolean committed = winAnimator.commitFinishDrawingLocked();
-                    if (isDefaultDisplay && committed) {
-                        if (w.mAttrs.type == TYPE_DREAM) {
-                            // HACK: When a dream is shown, it may at that
-                            // point hide the lock screen.  So we need to
-                            // redo the layout to let the phone window manager
-                            // make this happen.
-                            displayContent.pendingLayoutChanges |=
-                                    FINISH_LAYOUT_REDO_LAYOUT;
-                            if (DEBUG_LAYOUT_REPEATS) {
-                                debugLayoutRepeats("dream and commitFinishDrawingLocked true",
-                                        displayContent.pendingLayoutChanges);
-                            }
-                        }
-                        if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
-                            if (DEBUG_WALLPAPER_LIGHT)
-                                Slog.v(TAG, "First draw done in potential wallpaper target " + w);
-                            mWallpaperMayChange = true;
-                            displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-                            if (DEBUG_LAYOUT_REPEATS) {
-                                debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true",
-                                        displayContent.pendingLayoutChanges);
-                            }
-                        }
-                    }
-                    if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
-                        // Updates the shown frame before we set up the surface. This is needed
-                        // because the resizing could change the top-left position (in addition to
-                        // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
-                        // position the surface.
-                        //
-                        // If an animation is being started, we can't call this method because the
-                        // animation hasn't processed its initial transformation yet, but in general
-                        // we do want to update the position if the window is animating.
-                        winAnimator.computeShownFrameLocked();
-                    }
-                    winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
-                }
-
-                final AppWindowToken atoken = w.mAppToken;
-                if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) {
-                    Slog.d(TAG, "updateWindows: starting " + w
-                            + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
-                            + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
-                }
-                if (atoken != null && (!atoken.allDrawn || !atoken.allDrawnExcludingSaved
-                        || atoken.mAppAnimator.freezingScreen)) {
-                    if (atoken.lastTransactionSequence != mService.mTransactionSequence) {
-                        atoken.lastTransactionSequence = mService.mTransactionSequence;
-                        atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
-                        atoken.numInterestingWindowsExcludingSaved = 0;
-                        atoken.numDrawnWindowsExcludingSaved = 0;
-                        atoken.startingDisplayed = false;
-                    }
-                    if (!atoken.allDrawn && w.mightAffectAllDrawn(false /* visibleOnly */)) {
-                        if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
-                            Slog.v(TAG, "Eval win " + w + ": isDrawn="
-                                    + w.isDrawnLw()
-                                    + ", isAnimationSet=" + winAnimator.isAnimationSet());
-                            if (!w.isDrawnLw()) {
-                                Slog.v(TAG, "Not displayed: s="
-                                        + winAnimator.mSurfaceController
-                                        + " pv=" + w.mPolicyVisibility
-                                        + " mDrawState=" + winAnimator.drawStateToString()
-                                        + " ph=" + w.isParentWindowHidden()
-                                        + " th=" + atoken.hiddenRequested
-                                        + " a=" + winAnimator.mAnimating);
-                            }
-                        }
-                        if (w != atoken.startingWindow) {
-                            if (w.isInteresting()) {
-                                atoken.numInterestingWindows++;
-                                if (w.isDrawnLw()) {
-                                    atoken.numDrawnWindows++;
-                                    if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
-                                        Slog.v(TAG, "tokenMayBeDrawn: " + atoken
-                                                + " w=" + w + " numInteresting="
-                                                + atoken.numInterestingWindows
-                                                + " freezingScreen="
-                                                + atoken.mAppAnimator.freezingScreen
-                                                + " mAppFreezing=" + w.mAppFreezing);
-                                    updateAllDrawn = true;
-                                }
-                            }
-                        } else if (w.isDrawnLw()) {
-                            mService.mH.sendEmptyMessage(NOTIFY_STARTING_WINDOW_DRAWN);
-                            atoken.startingDisplayed = true;
-                        }
-                    }
-                    if (!atoken.allDrawnExcludingSaved
-                            && w.mightAffectAllDrawn(true /* visibleOnly */)) {
-                        if (w != atoken.startingWindow && w.isInteresting()) {
-                            atoken.numInterestingWindowsExcludingSaved++;
-                            if (w.isDrawnLw() && !w.isAnimatingWithSavedSurface()) {
-                                atoken.numDrawnWindowsExcludingSaved++;
-                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
-                                    Slog.v(TAG, "tokenMayBeDrawnExcludingSaved: " + atoken
-                                            + " w=" + w + " numInteresting="
-                                            + atoken.numInterestingWindowsExcludingSaved
-                                            + " freezingScreen="
-                                            + atoken.mAppAnimator.freezingScreen
-                                            + " mAppFreezing=" + w.mAppFreezing);
-                                updateAllDrawn = true;
-                            }
-                        }
-                    }
-                }
-
-                if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
-                        && w.isDisplayedLw()) {
-                    focusDisplayed = true;
-                }
-
-                mService.updateResizingWindows(w);
-            }
-
-            mService.mDisplayManagerInternal.setDisplayProperties(displayId,
-                    mDisplayHasContent,
-                    mPreferredRefreshRate,
-                    mPreferredModeId,
-                    true /* inTraversal, must call performTraversalInTrans... below */);
-
-            displayContent.stopDimmingIfNeeded();
-
-            if (updateAllDrawn) {
-                // See if any windows have been drawn, so they (and others associated with them)
-                // can now be shown.
-                displayContent.updateAllDrawn();
-            }
-        }
-
-        if (focusDisplayed) {
-            mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
-        }
-
-        // Give the display manager a chance to adjust properties
-        // like display rotation if it needs to.
-        mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
-    }
-
     boolean isInLayout() {
         return mInLayout;
     }
@@ -1064,7 +382,7 @@
      * @param windows List of windows on default display.
      * @return bitmap indicating if another pass through layout must be made.
      */
-    private int handleAppTransitionReadyLocked(WindowList windows) {
+    int handleAppTransitionReadyLocked(WindowList windows) {
         int appsCount = mService.mOpeningApps.size();
         if (!transitionGoodToGo(appsCount)) {
             return 0;
@@ -1084,7 +402,7 @@
         final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
         displayContent.rebuildAppWindowList();
 
-        mWallpaperMayChange = false;
+        mService.mRoot.mWallpaperMayChange = false;
 
         // The top-most window will supply the layout params,
         // and we will determine it below.
@@ -1437,91 +755,6 @@
         return transit;
     }
 
-    /**
-     * @param w WindowState this method is applied to.
-     * @param dispInfo info of the display that the window's obscuring state is checked against.
-     */
-    private void handleNotObscuredLocked(final WindowState w, final DisplayInfo dispInfo) {
-        final LayoutParams attrs = w.mAttrs;
-        final int attrFlags = attrs.flags;
-        final boolean canBeSeen = w.isDisplayedLw();
-        final int privateflags = attrs.privateFlags;
-
-        if (canBeSeen && w.isObscuringFullscreen(dispInfo)) {
-            // This window completely covers everything behind it,
-            // so we want to leave all of them as undimmed (for
-            // performance reasons).
-            if (!mObscured) {
-                mObsuringWindow = w;
-            }
-
-            mObscured = true;
-        }
-
-        if (w.mHasSurface && canBeSeen) {
-            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
-                mHoldScreen = w.mSession;
-                mHoldScreenWindow = w;
-            } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) {
-                Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding "
-                        + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by"
-                        + Debug.getCallers(10));
-            }
-            if (!mSyswin && w.mAttrs.screenBrightness >= 0
-                    && mScreenBrightness < 0) {
-                mScreenBrightness = w.mAttrs.screenBrightness;
-            }
-            if (!mSyswin && w.mAttrs.buttonBrightness >= 0
-                    && mButtonBrightness < 0) {
-                mButtonBrightness = w.mAttrs.buttonBrightness;
-            }
-            if (!mSyswin && w.mAttrs.userActivityTimeout >= 0
-                    && mUserActivityTimeout < 0) {
-                mUserActivityTimeout = w.mAttrs.userActivityTimeout;
-            }
-
-            final int type = attrs.type;
-            if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
-                    || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
-                mSyswin = true;
-            }
-
-            // This function assumes that the contents of the default display are
-            // processed first before secondary displays.
-            final DisplayContent displayContent = w.getDisplayContent();
-            if (displayContent != null && displayContent.isDefaultDisplay) {
-                // While a dream or keyguard is showing, obscure ordinary application
-                // content on secondary displays (by forcibly enabling mirroring unless
-                // there is other content we want to show) but still allow opaque
-                // keyguard dialogs to be shown.
-                if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
-                    mObscureApplicationContentOnSecondaryDisplays = true;
-                }
-                mDisplayHasContent = true;
-            } else if (displayContent != null &&
-                    (!mObscureApplicationContentOnSecondaryDisplays
-                            || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
-                // Allow full screen keyguard presentation dialogs to be seen.
-                mDisplayHasContent = true;
-            }
-            if (mPreferredRefreshRate == 0
-                    && w.mAttrs.preferredRefreshRate != 0) {
-                mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
-            }
-            if (mPreferredModeId == 0
-                    && w.mAttrs.preferredDisplayModeId != 0) {
-                mPreferredModeId = w.mAttrs.preferredDisplayModeId;
-            }
-            if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
-                mSustainedPerformanceModeCurrent = true;
-            }
-        }
-    }
-
-    private static int toBrightnessOverride(float value) {
-        return (int)(value * PowerManager.BRIGHTNESS_ON);
-    }
-
     private void processApplicationsAnimatingInPlace(int transit) {
         if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
             // Find the focused window
@@ -1618,41 +851,6 @@
         }
     }
 
-    boolean copyAnimToLayoutParamsLocked() {
-        boolean doRequest = false;
-
-        final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams;
-        if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
-            mUpdateRotation = true;
-            doRequest = true;
-        }
-        if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) {
-            mWallpaperMayChange = true;
-            doRequest = true;
-        }
-        if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
-            mWallpaperForceHidingChanged = true;
-            doRequest = true;
-        }
-        if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
-            mOrientationChangeComplete = false;
-        } else {
-            mOrientationChangeComplete = true;
-            mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource;
-            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
-                doRequest = true;
-            }
-        }
-        if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) {
-            mService.mTurnOnScreen = true;
-        }
-        if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) {
-            mWallpaperActionPending = true;
-        }
-
-        return doRequest;
-    }
-
     void requestTraversal() {
         if (!mTraversalScheduled) {
             mTraversalScheduled = true;
@@ -1680,8 +878,8 @@
     }
 
     public void dump(PrintWriter pw, String prefix) {
-        pw.print(prefix); pw.print("mTraversalScheduled="); pw.println(mTraversalScheduled);
-        pw.print(prefix); pw.print("mHoldScreenWindow="); pw.println(mHoldScreenWindow);
-        pw.print(prefix); pw.print("mObsuringWindow="); pw.println(mObsuringWindow);
+        pw.println(prefix + "mTraversalScheduled=" + mTraversalScheduled);
+        pw.println(prefix + "mHoldScreenWindow=" + mService.mRoot.mHoldScreenWindow);
+        pw.println(prefix + "mObsuringWindow=" + mService.mRoot.mObsuringWindow);
     }
 }