Merge "Introduce multiple displays with DisplayContent." into jb-mr1-dev
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 54b5836..f42fd2a 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -38,6 +38,7 @@
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.util.AndroidException;
+import android.view.Display;
 import android.view.IWindowManager;
 
 import java.io.BufferedReader;
@@ -1117,9 +1118,10 @@
 
         try {
             if (m >= 0 && n >= 0) {
-                wm.setForcedDisplaySize(m, n);
+                // TODO(multidisplay): For now Configuration only applies to main screen.
+                wm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, m, n);
             } else {
-                wm.clearForcedDisplaySize();
+                wm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY);
             }
         } catch (RemoteException e) {
         }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index f8d9378..f58cd83 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -57,8 +57,8 @@
             in IInputContext inputContext);
     boolean inputMethodClientHasFocus(IInputMethodClient client);
 
-    void setForcedDisplaySize(int longDimen, int shortDimen);
-    void clearForcedDisplaySize();
+    void setForcedDisplaySize(int displayId, int longDimen, int shortDimen);
+    void clearForcedDisplaySize(int displayId);
 
     // Is the device configured to have a full system bar for larger screens?
     boolean hasSystemNavBar();
@@ -184,7 +184,7 @@
 	/**
 	 * Create a screenshot of the applications currently displayed.
 	 */
-	Bitmap screenshotApplications(IBinder appToken, int maxWidth, int maxHeight);
+	Bitmap screenshotApplications(IBinder appToken, int displayId, int maxWidth, int maxHeight);
 
     /**
      * Called by the status bar to notify Views of changes to System UI visiblity.
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index cd00255..f604d44 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -42,6 +42,7 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
+import android.view.Display;
 import android.view.WindowManager;
 
 import com.android.internal.os.BinderInternal;
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 9171e47..a1ff9c4 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -59,6 +59,7 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
+import android.view.Display;
 import android.view.WindowManagerPolicy;
 
 import java.io.IOException;
@@ -902,7 +903,7 @@
             mService.notifyAll();
         }
     }
-    
+
     public final Bitmap screenshotActivities(ActivityRecord who) {
         if (who.noDisplay) {
             return null;
@@ -919,7 +920,8 @@
         }
 
         if (w > 0) {
-            return mService.mWindowManager.screenshotApplications(who.appToken, w, h);
+            return mService.mWindowManager.screenshotApplications(who.appToken,
+                    Display.DEFAULT_DISPLAY, w, h);
         }
         return null;
     }
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java
index af7b314..afc060e 100644
--- a/services/java/com/android/server/am/ProcessList.java
+++ b/services/java/com/android/server/am/ProcessList.java
@@ -24,6 +24,7 @@
 
 import android.graphics.Point;
 import android.util.Slog;
+import android.view.Display;
 
 /**
  * Activity manager code dealing with processes.
@@ -146,7 +147,7 @@
     void applyDisplaySize(WindowManagerService wm) {
         if (!mHaveDisplaySize) {
             Point p = new Point();
-            wm.getInitialDisplaySize(p);
+            wm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, p);
             if (p.x != 0 && p.y != 0) {
                 updateOomLevels(p.x, p.y, true);
                 mHaveDisplaySize = true;
diff --git a/services/java/com/android/server/input/InputWindowHandle.java b/services/java/com/android/server/input/InputWindowHandle.java
index 03d66af..ad4fdd1 100644
--- a/services/java/com/android/server/input/InputWindowHandle.java
+++ b/services/java/com/android/server/input/InputWindowHandle.java
@@ -87,12 +87,16 @@
     // Window input features.
     public int inputFeatures;
 
+    // Display this input is on.
+    public final int displayId;
+
     private native void nativeDispose();
 
     public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
-            Object windowState) {
+            Object windowState, int displayId) {
         this.inputApplicationHandle = inputApplicationHandle;
         this.windowState = windowState;
+        this.displayId = displayId;
     }
 
     @Override
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
new file mode 100644
index 0000000..d4c17c5
--- /dev/null
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2012 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.view.DisplayInfo;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+class DisplayContentList extends ArrayList<DisplayContent> {
+}
+
+/**
+ * Utility class for keeping track of the WindowStates and other pertinent contents of a
+ * particular Display.
+ *
+ * IMPORTANT: No method from this class should ever be used without holding
+ * WindowManagerService.mWindowMap.
+ */
+class DisplayContent {
+
+    /** Unique identifier of this stack. */
+    private final int mDisplayId;
+
+    /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
+     * from mDisplayWindows; */
+    private WindowList mWindows = new WindowList();
+
+
+    // This protects the following display size properties, so that
+    // getDisplaySize() doesn't need to acquire the global lock.  This is
+    // needed because the window manager sometimes needs to use ActivityThread
+    // while it has its global state locked (for example to load animation
+    // resources), but the ActivityThread also needs get the current display
+    // size sometimes when it has its package lock held.
+    //
+    // These will only be modified with both mWindowMap and mDisplaySizeLock
+    // held (in that order) so the window manager doesn't need to acquire this
+    // lock when needing these values in its normal operation.
+    final Object mDisplaySizeLock = new Object();
+    int mInitialDisplayWidth = 0;
+    int mInitialDisplayHeight = 0;
+    int mBaseDisplayWidth = 0;
+    int mBaseDisplayHeight = 0;
+    final DisplayInfo mDisplayInfo = new DisplayInfo();
+
+    DisplayContent(final int displayId) {
+        mDisplayId = displayId;
+    }
+
+    int getDisplayId() {
+        return mDisplayId;
+    }
+
+    WindowList getWindowList() {
+        return mWindows;
+    }
+
+    DisplayInfo getDisplayInfo() {
+        return mDisplayInfo;
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.print("  Display: mDisplayId="); pw.println(mDisplayId);
+        pw.print("  init="); pw.print(mInitialDisplayWidth); pw.print("x");
+        pw.print(mInitialDisplayHeight);
+        if (mInitialDisplayWidth != mBaseDisplayWidth
+                || mInitialDisplayHeight != mBaseDisplayHeight) {
+            pw.print(" base=");
+            pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
+        }
+        if (mInitialDisplayWidth != mDisplayInfo.logicalWidth
+                || mInitialDisplayHeight != mDisplayInfo.logicalHeight) {
+            pw.print(" init="); pw.print(mInitialDisplayWidth);
+            pw.print("x"); pw.print(mInitialDisplayHeight);
+        }
+        pw.print(" cur=");
+        pw.print(mDisplayInfo.logicalWidth);
+        pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
+        pw.print(" app=");
+        pw.print(mDisplayInfo.appWidth);
+        pw.print("x"); pw.print(mDisplayInfo.appHeight);
+        pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
+        pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
+        pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
+        pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
+        pw.println();
+    }
+}
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index f0b0e1f..26ea7c1 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -29,6 +29,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Slog;
+import android.view.DisplayInfo;
 import android.view.DragEvent;
 import android.view.InputChannel;
 import android.view.Surface;
@@ -58,6 +59,7 @@
     WindowState mTargetWindow;
     ArrayList<WindowState> mNotifiedWindows;
     boolean mDragInProgress;
+    DisplayContent mDisplayContent;
 
     private final Region mTmpRegion = new Region();
 
@@ -69,6 +71,12 @@
         mFlags = flags;
         mLocalWin = localWin;
         mNotifiedWindows = new ArrayList<WindowState>();
+        WindowState win = service.mWindowMap.get(token);
+        if (win != null) {
+            mDisplayContent = win.mDisplayContent;
+        } else {
+            Slog.e(WindowManagerService.TAG, "No window associated with token");
+        }
     }
 
     void reset() {
@@ -101,7 +109,8 @@
             mDragApplicationHandle.dispatchingTimeoutNanos =
                     WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null);
+            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
+                    mDisplayContent.getDisplayId());
             mDragWindowHandle.name = "drag";
             mDragWindowHandle.inputChannel = mServerChannel;
             mDragWindowHandle.layer = getDragLayerLw();
@@ -125,8 +134,9 @@
             // The drag window covers the entire display
             mDragWindowHandle.frameLeft = 0;
             mDragWindowHandle.frameTop = 0;
-            mDragWindowHandle.frameRight = mService.mDisplayInfo.logicalWidth;
-            mDragWindowHandle.frameBottom = mService.mDisplayInfo.logicalHeight;
+            DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+            mDragWindowHandle.frameRight = displayInfo.logicalWidth;
+            mDragWindowHandle.frameBottom = displayInfo.logicalHeight;
 
             // Pause rotations before a drag.
             if (WindowManagerService.DEBUG_ORIENTATION) {
@@ -179,9 +189,10 @@
             Slog.d(WindowManagerService.TAG, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
         }
 
-        final int N = mService.mWindows.size();
+        final WindowList windows = mDisplayContent.getWindowList();
+        final int N = windows.size();
         for (int i = 0; i < N; i++) {
-            sendDragStartedLw(mService.mWindows.get(i), touchX, touchY, mDataDescription);
+            sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
         }
     }
 
@@ -380,7 +391,8 @@
         WindowState touchedWin = null;
         final int x = (int) xf;
         final int y = (int) yf;
-        final ArrayList<WindowState> windows = mService.mWindows;
+
+        final WindowList windows = mDisplayContent.getWindowList();
         final int N = windows.size();
         for (int i = N - 1; i >= 0; i--) {
             WindowState child = windows.get(i);
diff --git a/services/java/com/android/server/wm/FakeWindowImpl.java b/services/java/com/android/server/wm/FakeWindowImpl.java
index 2527f46..5ec72cc 100644
--- a/services/java/com/android/server/wm/FakeWindowImpl.java
+++ b/services/java/com/android/server/wm/FakeWindowImpl.java
@@ -22,6 +22,7 @@
 import android.os.Looper;
 import android.os.Process;
 import android.util.Slog;
+import android.view.Display;
 import android.view.InputChannel;
 import android.view.InputEventReceiver;
 import android.view.InputQueue;
@@ -56,7 +57,7 @@
         mApplicationHandle.dispatchingTimeoutNanos =
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-        mWindowHandle = new InputWindowHandle(mApplicationHandle, null);
+        mWindowHandle = new InputWindowHandle(mApplicationHandle, null, Display.DEFAULT_DISPLAY);
         mWindowHandle.name = name;
         mWindowHandle.inputChannel = mServerChannel;
         mWindowLayer = getLayerLw(windowType);
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 595cc47..5ff8a9b 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -201,7 +201,6 @@
         // 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.
-        final ArrayList<WindowState> windows = mService.mWindows;
         final WindowStateAnimator universeBackground = mService.mAnimator.mUniverseBackground;
         final int aboveUniverseLayer = mService.mAnimator.mAboveUniverseLayer;
         boolean addedUniverse = false;
@@ -226,8 +225,9 @@
             addInputWindowHandleLw(mService.mFakeWindows.get(i).mWindowHandle);
         }
 
-        final int N = windows.size();
-        for (int i = N - 1; i >= 0; i--) {
+        // TODO(multidisplay): Input only occurs on the default display.
+        final WindowList windows = mService.getDefaultWindowList();
+        for (int i = windows.size() - 1; i >= 0; i--) {
             final WindowState child = windows.get(i);
             final InputChannel inputChannel = child.mInputChannel;
             final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index b0c858c..0dbe692 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -39,7 +39,7 @@
     final Context mContext;
     final WindowManagerPolicy mPolicy;
 
-    ArrayList<WindowStateAnimator> mWinAnimators = new ArrayList<WindowStateAnimator>();
+    ArrayList<WinAnimatorList> mWinAnimatorLists = new ArrayList<WinAnimatorList>();
 
     boolean mAnimating;
 
@@ -158,7 +158,8 @@
                 mWallpaperTokens = new ArrayList<WindowToken>(layoutToAnim.mWallpaperTokens);
             }
 
-            mWinAnimators = new ArrayList<WindowStateAnimator>(layoutToAnim.mWinAnimators);
+            mWinAnimatorLists =
+                    new ArrayList<WinAnimatorList>(layoutToAnim.mWinAnimatorLists);
             mWallpaperTarget = layoutToAnim.mWallpaperTarget;
             mWpAppAnimator = mWallpaperTarget == null
                     ? null : mWallpaperTarget.mAppToken == null
@@ -267,7 +268,7 @@
         }
     }
 
-    private void updateWindowsLocked() {
+    private void updateWindowsLocked(final WinAnimatorList winAnimatorList) {
         ++mAnimTransactionSequence;
 
         ArrayList<WindowStateAnimator> unForceHiding = null;
@@ -280,8 +281,8 @@
         final int KEYGUARD_ANIMATING_OUT = 3;
         int forceHiding = KEYGUARD_NOT_SHOWN;
 
-        for (int i = mWinAnimators.size() - 1; i >= 0; i--) {
-            WindowStateAnimator winAnimator = mWinAnimators.get(i);
+        for (int i = winAnimatorList.size() - 1; i >= 0; i--) {
+            WindowStateAnimator winAnimator = winAnimatorList.get(i);
             WindowState win = winAnimator.mWin;
             final int flags = winAnimator.mAttrFlags;
 
@@ -418,13 +419,13 @@
         }
     }
 
-    private void updateWallpaperLocked() {
+    private void updateWallpaperLocked(final WinAnimatorList winAnimatorList) {
         WindowStateAnimator windowAnimationBackground = null;
         int windowAnimationBackgroundColor = 0;
         WindowState detachedWallpaper = null;
 
-        for (int i = mWinAnimators.size() - 1; i >= 0; i--) {
-            WindowStateAnimator winAnimator = mWinAnimators.get(i);
+        for (int i = winAnimatorList.size() - 1; i >= 0; i--) {
+            WindowStateAnimator winAnimator = winAnimatorList.get(i);
             if (winAnimator.mSurface == null) {
                 continue;
             }
@@ -489,11 +490,11 @@
             // don't cause the wallpaper to suddenly disappear.
             int animLayer = windowAnimationBackground.mAnimLayer;
             WindowState win = windowAnimationBackground.mWin;
-            if (windowAnimationBackground != null && mWallpaperTarget == win
+            if (mWallpaperTarget == win
                     || mLowerWallpaperTarget == win || mUpperWallpaperTarget == win) {
-                final int N = mWinAnimators.size();
+                final int N = winAnimatorList.size();
                 for (int i = 0; i < N; i++) {
-                    WindowStateAnimator winAnimator = mWinAnimators.get(i);
+                    WindowStateAnimator winAnimator = winAnimatorList.get(i);
                     if (winAnimator.mIsWallpaper) {
                         animLayer = winAnimator.mAnimLayer;
                         break;
@@ -548,9 +549,9 @@
         }
     }
 
-    private void performAnimationsLocked() {
-        updateWindowsLocked();
-        updateWallpaperLocked();
+    private void performAnimationsLocked(final WinAnimatorList winAnimatorList) {
+        updateWindowsLocked(winAnimatorList);
+        updateWallpaperLocked(winAnimatorList);
 
         if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
             mPendingActions |= WALLPAPER_ACTION_PENDING;
@@ -562,6 +563,12 @@
     // TODO(cmautner): Change the following comment when no longer locked on mWindowMap */
     /** Locked on mService.mWindowMap and this. */
     private void animateLocked() {
+        for (int i = mWinAnimatorLists.size() - 1; i >= 0; i--) {
+            animateLocked(mWinAnimatorLists.get(i));
+        }
+    }
+
+    private void animateLocked(final WinAnimatorList winAnimatorList) {
         mPendingLayoutChanges = 0;
         mCurrentTime = SystemClock.uptimeMillis();
         mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
@@ -577,7 +584,7 @@
 
         try {
             updateWindowsAppsAndRotationAnimationsLocked();
-            performAnimationsLocked();
+            performAnimationsLocked(winAnimatorList);
 
             // THIRD LOOP: Update the surfaces of all windows.
 
@@ -585,9 +592,9 @@
                 mScreenRotationAnimation.updateSurfaces();
             }
 
-            final int N = mWinAnimators.size();
+            final int N = winAnimatorList.size();
             for (int i = 0; i < N; i++) {
-                mWinAnimators.get(i).prepareSurfaceLocked(true);
+                winAnimatorList.get(i).prepareSurfaceLocked(true);
             }
 
             if (mDimParams != null) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 1283da3..8b5c923 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -98,6 +98,7 @@
 import android.util.EventLog;
 import android.util.FloatMath;
 import android.util.Log;
+import android.util.SparseArray;
 //import android.util.LogPrinter;
 import android.util.Pair;
 import android.util.Slog;
@@ -157,6 +158,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 /** {@hide} */
 public class WindowManagerService extends IWindowManager.Stub
@@ -388,11 +390,6 @@
     final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
 
     /**
-     * Z-ordered (bottom-most first) list of all Window objects.
-     */
-    final ArrayList<WindowState> mWindows = new ArrayList<WindowState>();
-
-    /**
      * Fake windows added to the window manager.  Note: ordered from top to
      * bottom, opposite of mWindows.
      */
@@ -468,22 +465,8 @@
 
     String mLastANRState;
 
-    // This protects the following display size properties, so that
-    // getDisplaySize() doesn't need to acquire the global lock.  This is
-    // needed because the window manager sometimes needs to use ActivityThread
-    // while it has its global state locked (for example to load animation
-    // resources), but the ActivityThread also needs get the current display
-    // size sometimes when it has its package lock held.
-    //
-    // These will only be modified with both mWindowMap and mDisplaySizeLock
-    // held (in that order) so the window manager doesn't need to acquire this
-    // lock when needing these values in its normal operation.
-    final Object mDisplaySizeLock = new Object();
-    int mInitialDisplayWidth = 0;
-    int mInitialDisplayHeight = 0;
-    int mBaseDisplayWidth = 0;
-    int mBaseDisplayHeight = 0;
-    final DisplayInfo mDisplayInfo = new DisplayInfo();
+    /** All DisplayDontents in the world, kept here */
+    private SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>();
 
     int mRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -666,7 +649,7 @@
         long mChanges;
 
         boolean mAnimationScheduled;
-        ArrayList<WindowStateAnimator> mWinAnimators = new ArrayList<WindowStateAnimator>();
+        ArrayList<WinAnimatorList> mWinAnimatorLists = new ArrayList<WinAnimatorList>();
         WindowState mWallpaperTarget;
         WindowState mLowerWallpaperTarget;
         WindowState mUpperWallpaperTarget;
@@ -975,34 +958,31 @@
     }
 
     private void placeWindowAfter(WindowState pos, WindowState window) {
-        final int i = mWindows.indexOf(pos);
+        final WindowList windows = pos.getWindowList();
+        final int i = windows.indexOf(pos);
         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
             TAG, "Adding window " + window + " at "
-            + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
-        mWindows.add(i+1, window);
+            + (i+1) + " of " + windows.size() + " (after " + pos + ")");
+        windows.add(i+1, window);
         mWindowsChanged = true;
     }
 
     private void placeWindowBefore(WindowState pos, WindowState window) {
-        final int i = mWindows.indexOf(pos);
+        final WindowList windows = pos.getWindowList();
+        final int i = windows.indexOf(pos);
         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
             TAG, "Adding window " + window + " at "
-            + i + " of " + mWindows.size() + " (before " + pos + ")");
-        mWindows.add(i, window);
+            + i + " of " + windows.size() + " (before " + pos + ")");
+        windows.add(i, window);
         mWindowsChanged = true;
     }
 
     //This method finds out the index of a window that has the same app token as
     //win. used for z ordering the windows in mWindows
     private int findIdxBasedOnAppTokens(WindowState win) {
-        //use a local variable to cache mWindows
-        ArrayList<WindowState> localmWindows = mWindows;
-        int jmax = localmWindows.size();
-        if(jmax == 0) {
-            return -1;
-        }
-        for(int j = (jmax-1); j >= 0; j--) {
-            WindowState wentry = localmWindows.get(j);
+        WindowList windows = win.getWindowList();
+        for(int j = windows.size() - 1; j >= 0; j--) {
+            WindowState wentry = windows.get(j);
             if(wentry.mAppToken == win.mAppToken) {
                 return j;
             }
@@ -1013,9 +993,9 @@
     private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
         final IWindow client = win.mClient;
         final WindowToken token = win.mToken;
-        final ArrayList<WindowState> localmWindows = mWindows;
 
-        final int N = localmWindows.size();
+        final WindowList windows = win.getWindowList();
+        final int N = windows.size();
         final WindowState attached = win.mAttachedWindow;
         int i;
         if (attached == null) {
@@ -1047,7 +1027,7 @@
                                     Slog.v(TAG, "Adding window " + win + " at "
                                             + (newIdx+1) + " of " + N);
                                 }
-                                localmWindows.add(newIdx+1, win);
+                                windows.add(newIdx+1, win);
                                 mWindowsChanged = true;
                             }
                         }
@@ -1120,7 +1100,7 @@
                             // Just search for the start of this layer.
                             final int myLayer = win.mBaseLayer;
                             for (i=0; i<N; i++) {
-                                WindowState w = localmWindows.get(i);
+                                WindowState w = windows.get(i);
                                 if (w.mBaseLayer > myLayer) {
                                     break;
                                 }
@@ -1129,7 +1109,7 @@
                                 Slog.v(TAG, "Adding window " + win + " at "
                                         + i + " of " + N);
                             }
-                            localmWindows.add(i, win);
+                            windows.add(i, win);
                             mWindowsChanged = true;
                         }
                     }
@@ -1138,7 +1118,7 @@
                 // Figure out where window should go, based on layer.
                 final int myLayer = win.mBaseLayer;
                 for (i=N-1; i>=0; i--) {
-                    if (localmWindows.get(i).mBaseLayer <= myLayer) {
+                    if (windows.get(i).mBaseLayer <= myLayer) {
                         i++;
                         break;
                     }
@@ -1147,9 +1127,10 @@
                 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
                         TAG, "Adding window " + win + " at "
                         + i + " of " + N);
-                localmWindows.add(i, win);
+                windows.add(i, win);
                 mWindowsChanged = true;
             }
+
             if (addToToken) {
                 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                 token.windows.add(tokenWindowsPos, win);
@@ -1177,8 +1158,7 @@
                             if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                             token.windows.add(i, win);
                         }
-                        placeWindowBefore(
-                            wSublayer >= 0 ? attached : w, win);
+                        placeWindowBefore(wSublayer >= 0 ? attached : w, win);
                         break;
                     }
                 } else {
@@ -1243,16 +1223,20 @@
     /**
      * Dig through the WindowStates and find the one that the Input Method will target.
      * @param willMove
+     * @param windows TODO(cmautner):
      * @return The index+1 in mWindows of the discovered target.
      */
     int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
-        final ArrayList<WindowState> localmWindows = mWindows;
-        final int N = localmWindows.size();
+        // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
+        // same display. Or even when the current IME/target are not on the same screen as the next
+        // IME/target. For now only look for input windows on the main screen.
+        WindowList windows = getDefaultWindowList();
+        final int N = windows.size();
         WindowState w = null;
         int i = N;
         while (i > 0) {
             i--;
-            w = localmWindows.get(i);
+            w = windows.get(i);
 
             if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i
                     + " " + w + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
@@ -1267,7 +1251,7 @@
                 if (!willMove
                         && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
                         && i > 0) {
-                    WindowState wb = localmWindows.get(i-1);
+                    WindowState wb = windows.get(i-1);
                     if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
                         i--;
                         w = wb;
@@ -1287,12 +1271,13 @@
         // the IME shown: when the Dialog is dismissed, we want to keep
         // the IME above it until it is completely gone so it doesn't drop
         // behind the dialog or its full-screen scrim.
-        if (mInputMethodTarget != null && w != null
-                && mInputMethodTarget.isDisplayedLw()
-                && mInputMethodTarget.mExiting) {
-            if (mInputMethodTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
-                w = mInputMethodTarget;
-                i = localmWindows.indexOf(w);
+        final WindowState curTarget = mInputMethodTarget;
+        if (curTarget != null && w != null
+                && curTarget.isDisplayedLw()
+                && curTarget.mExiting) {
+            if (curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
+                w = curTarget;
+                i = windows.indexOf(w);
                 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, switching to: " + w);
             }
         }
@@ -1301,20 +1286,20 @@
                 + w + " willMove=" + willMove);
 
         if (willMove && w != null) {
-            final WindowState curTarget = mInputMethodTarget;
-            if (curTarget != null && curTarget.mAppToken != null) {
+            AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
+            if (token != null) {
 
                 // Now some fun for dealing with window animations that
                 // modify the Z order.  We need to look at all windows below
                 // the current target that are in this app, finding the highest
                 // visible one in layering.
-                AppWindowToken token = curTarget.mAppToken;
                 WindowState highestTarget = null;
                 int highestPos = 0;
                 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
-                    int pos = localmWindows.indexOf(curTarget);
+                    WindowList curWindows = curTarget.getWindowList();
+                    int pos = curWindows.indexOf(curTarget);
                     while (pos >= 0) {
-                        WindowState win = localmWindows.get(pos);
+                        WindowState win = curWindows.get(pos);
                         if (win.mAppToken != token) {
                             break;
                         }
@@ -1359,15 +1344,8 @@
         //Slog.i(TAG, "Placing input method @" + (i+1));
         if (w != null) {
             if (willMove) {
-                if (DEBUG_INPUT_METHOD) {
-                    RuntimeException e = null;
-                    if (!HIDE_STACK_CRAWLS) {
-                        e = new RuntimeException();
-                        e.fillInStackTrace();
-                    }
-                    Slog.w(TAG, "Moving IM target from "
-                            + mInputMethodTarget + " to " + w, e);
-                }
+                if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to "
+                        + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
                 mInputMethodTarget = w;
                 mInputMethodTargetWaitingAnim = false;
                 if (w.mAppToken != null) {
@@ -1379,15 +1357,8 @@
             return i+1;
         }
         if (willMove) {
-            if (DEBUG_INPUT_METHOD) {
-                RuntimeException e = null;
-                if (!HIDE_STACK_CRAWLS) {
-                    e = new RuntimeException();
-                    e.fillInStackTrace();
-                }
-                Slog.w(TAG, "Moving IM target from "
-                        + mInputMethodTarget + " to null", e);
-            }
+            if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null."
+                    + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
             mInputMethodTarget = null;
             setInputMethodAnimLayerAdjustment(0);
         }
@@ -1400,7 +1371,8 @@
             win.mTargetAppToken = mInputMethodTarget.mAppToken;
             if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
                     TAG, "Adding input method window " + win + " at " + pos);
-            mWindows.add(pos, win);
+            // TODO(multidisplay): IMEs are only supported on the default display.
+            getDefaultWindowList().add(pos, win);
             mWindowsChanged = true;
             moveInputMethodDialogsLocked(pos+1);
             return;
@@ -1438,22 +1410,23 @@
     }
 
     private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
-        int wpos = mWindows.indexOf(win);
+        WindowList windows = win.getWindowList();
+        int wpos = windows.indexOf(win);
         if (wpos >= 0) {
             if (wpos < interestingPos) interestingPos--;
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
-            mWindows.remove(wpos);
+            windows.remove(wpos);
             mWindowsChanged = true;
             int NC = win.mChildWindows.size();
             while (NC > 0) {
                 NC--;
                 WindowState cw = win.mChildWindows.get(NC);
-                int cpos = mWindows.indexOf(cw);
+                int cpos = windows.indexOf(cw);
                 if (cpos >= 0) {
                     if (cpos < interestingPos) interestingPos--;
                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
                             + cpos + ": " + cw);
-                    mWindows.remove(cpos);
+                    windows.remove(cpos);
                 }
             }
         }
@@ -1465,27 +1438,29 @@
         // This is a hack to get all of the child windows added as well
         // at the right position.  Child windows should be rare and
         // this case should be rare, so it shouldn't be that big a deal.
-        int wpos = mWindows.indexOf(win);
+        WindowList windows = win.getWindowList();
+        int wpos = windows.indexOf(win);
         if (wpos >= 0) {
-            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos
-                    + ": " + win);
-            mWindows.remove(wpos);
+            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win);
+            windows.remove(wpos);
             mWindowsChanged = true;
             reAddWindowLocked(wpos, win);
         }
     }
 
-    void logWindowList(String prefix) {
-        int N = mWindows.size();
+    void logWindowList(final WindowList windows, String prefix) {
+        int N = windows.size();
         while (N > 0) {
             N--;
-            Slog.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
+            Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N));
         }
     }
 
     void moveInputMethodDialogsLocked(int pos) {
         ArrayList<WindowState> dialogs = mInputMethodDialogs;
 
+        // TODO(multidisplay): IMEs are only supported on the default display.
+        WindowList windows = getDefaultWindowList();
         final int N = dialogs.size();
         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
         for (int i=0; i<N; i++) {
@@ -1493,13 +1468,13 @@
         }
         if (DEBUG_INPUT_METHOD) {
             Slog.v(TAG, "Window list w/pos=" + pos);
-            logWindowList("  ");
+            logWindowList(windows, "  ");
         }
 
         if (pos >= 0) {
             final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
-            if (pos < mWindows.size()) {
-                WindowState wp = mWindows.get(pos);
+            if (pos < windows.size()) {
+                WindowState wp = windows.get(pos);
                 if (wp == mInputMethodWindow) {
                     pos++;
                 }
@@ -1512,7 +1487,7 @@
             }
             if (DEBUG_INPUT_METHOD) {
                 Slog.v(TAG, "Final window list:");
-                logWindowList("  ");
+                logWindowList(windows, "  ");
             }
             return;
         }
@@ -1522,7 +1497,7 @@
             reAddWindowToListInOrderLocked(win);
             if (DEBUG_INPUT_METHOD) {
                 Slog.v(TAG, "No IM target, final list:");
-                logWindowList("  ");
+                logWindowList(windows, "  ");
             }
         }
     }
@@ -1534,6 +1509,9 @@
             return false;
         }
 
+        // TODO(multidisplay): IMEs are only supported on the default display.
+        WindowList windows = getDefaultWindowList();
+
         int imPos = findDesiredInputMethodWindowIndexLocked(true);
         if (imPos >= 0) {
             // In this case, the input method windows are to be placed
@@ -1541,9 +1519,9 @@
 
             // First check to see if the input method windows are already
             // located here, and contiguous.
-            final int N = mWindows.size();
+            final int N = windows.size();
             WindowState firstImWin = imPos < N
-                    ? mWindows.get(imPos) : null;
+                    ? windows.get(imPos) : null;
 
             // Figure out the actual input method window that should be
             // at the bottom of their stack.
@@ -1559,7 +1537,7 @@
                 // First find the top IM window.
                 int pos = imPos+1;
                 while (pos < N) {
-                    if (!(mWindows.get(pos)).mIsImWindow) {
+                    if (!(windows.get(pos)).mIsImWindow) {
                         break;
                     }
                     pos++;
@@ -1567,7 +1545,7 @@
                 pos++;
                 // Now there should be no more input method windows above.
                 while (pos < N) {
-                    if ((mWindows.get(pos)).mIsImWindow) {
+                    if ((windows.get(pos)).mIsImWindow) {
                         break;
                     }
                     pos++;
@@ -1581,18 +1559,18 @@
             if (imWin != null) {
                 if (DEBUG_INPUT_METHOD) {
                     Slog.v(TAG, "Moving IM from " + imPos);
-                    logWindowList("  ");
+                    logWindowList(windows, "  ");
                 }
                 imPos = tmpRemoveWindowLocked(imPos, imWin);
                 if (DEBUG_INPUT_METHOD) {
                     Slog.v(TAG, "List after removing with new pos " + imPos + ":");
-                    logWindowList("  ");
+                    logWindowList(windows, "  ");
                 }
                 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
                 reAddWindowLocked(imPos, imWin);
                 if (DEBUG_INPUT_METHOD) {
                     Slog.v(TAG, "List after moving IM to " + imPos + ":");
-                    logWindowList("  ");
+                    logWindowList(windows, "  ");
                 }
                 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
             } else {
@@ -1610,7 +1588,7 @@
                 reAddWindowToListInOrderLocked(imWin);
                 if (DEBUG_INPUT_METHOD) {
                     Slog.v(TAG, "List with no IM target:");
-                    logWindowList("  ");
+                    logWindowList(windows, "  ");
                 }
                 if (DN > 0) moveInputMethodDialogsLocked(-1);
             } else {
@@ -1620,7 +1598,7 @@
         }
 
         if (needAssignLayers) {
-            assignLayersLocked();
+            assignLayersLocked(windows);
         }
 
         return true;
@@ -1651,13 +1629,15 @@
         mInnerFields.mWallpaperMayChange = false;
         int changed = 0;
 
-        final int dw = mDisplayInfo.appWidth;
-        final int dh = mDisplayInfo.appHeight;
+        // TODO(multidisplay): Wallpapers on main screen only.
+        final DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo();
+        final int dw = displayInfo.appWidth;
+        final int dh = displayInfo.appHeight;
 
         // First find top-most window that has asked to be on top of the
         // wallpaper; all wallpapers go behind it.
-        final ArrayList<WindowState> localmWindows = mWindows;
-        int N = localmWindows.size();
+        final WindowList windows = getDefaultWindowList();
+        int N = windows.size();
         WindowState w = null;
         WindowState foundW = null;
         int foundI = 0;
@@ -1667,7 +1647,7 @@
         int i = N;
         while (i > 0) {
             i--;
-            w = localmWindows.get(i);
+            w = windows.get(i);
             if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
                 if (topCurW == null) {
                     topCurW = w;
@@ -1761,7 +1741,7 @@
                             + " old animation: " + oldAnim);
                 }
                 if (foundAnim && oldAnim) {
-                    int oldI = localmWindows.indexOf(oldW);
+                    int oldI = windows.indexOf(oldW);
                     if (DEBUG_WALLPAPER) {
                         Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
                     }
@@ -1845,7 +1825,7 @@
             // AND any starting window associated with it, AND below the
             // maximum layer the policy allows for wallpapers.
             while (foundI > 0) {
-                WindowState wb = localmWindows.get(foundI-1);
+                WindowState wb = windows.get(foundI-1);
                 if (wb.mBaseLayer < maxLayer &&
                         wb.mAttachedWindow != foundW &&
                         (foundW.mAttachedWindow == null ||
@@ -1871,7 +1851,7 @@
         } else {
             // Okay i is the position immediately above the wallpaper.  Look at
             // what is below it for later.
-            foundW = foundI > 0 ? localmWindows.get(foundI-1) : null;
+            foundW = foundI > 0 ? windows.get(foundI-1) : null;
         }
 
         if (visible) {
@@ -1921,18 +1901,18 @@
                 if (wallpaper == foundW) {
                     foundI--;
                     foundW = foundI > 0
-                            ? localmWindows.get(foundI-1) : null;
+                            ? windows.get(foundI-1) : null;
                     continue;
                 }
 
                 // The window didn't match...  the current wallpaper window,
                 // wherever it is, is in the wrong place, so make sure it is
                 // not in the list.
-                int oldIndex = localmWindows.indexOf(wallpaper);
+                int oldIndex = windows.indexOf(wallpaper);
                 if (oldIndex >= 0) {
                     if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
                             + oldIndex + ": " + wallpaper);
-                    localmWindows.remove(oldIndex);
+                    windows.remove(oldIndex);
                     mWindowsChanged = true;
                     if (oldIndex < foundI) {
                         foundI--;
@@ -1945,7 +1925,7 @@
                             + " from " + oldIndex + " to " + foundI);
                 }
 
-                localmWindows.add(foundI, wallpaper);
+                windows.add(foundI, wallpaper);
                 mWindowsChanged = true;
                 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
             }
@@ -2061,8 +2041,10 @@
     }
 
     void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
-        final int dw = mDisplayInfo.appWidth;
-        final int dh = mDisplayInfo.appHeight;
+        final DisplayContent displayContent = changingTarget.mDisplayContent;
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int dw = displayInfo.appWidth;
+        final int dh = displayInfo.appHeight;
 
         WindowState target = mWallpaperTarget;
         if (target != null) {
@@ -2124,8 +2106,10 @@
 
     void updateWallpaperVisibilityLocked() {
         final boolean visible = isWallpaperVisible(mWallpaperTarget);
-        final int dw = mDisplayInfo.appWidth;
-        final int dh = mDisplayInfo.appHeight;
+        final DisplayContent displayContent = mWallpaperTarget.mDisplayContent;
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int dw = displayInfo.appWidth;
+        final int dh = displayInfo.appHeight;
 
         int curTokenIndex = mWallpaperTokens.size();
         while (curTokenIndex > 0) {
@@ -2253,8 +2237,9 @@
                 }
             }
 
+            final DisplayContent displayContent = getDisplayContent(displayId);
             win = new WindowState(this, session, client, token,
-                    attachedWindow, seq, attrs, viewVisibility, displayId);
+                    attachedWindow, seq, attrs, viewVisibility, displayContent);
             if (win.mDeathRecipient == null) {
                 // Client has apparently died, so there is no reason to
                 // continue.
@@ -2347,7 +2332,7 @@
                 moveInputMethodWindowsIfNeededLocked(false);
             }
 
-            assignLayersLocked();
+            assignLayersLocked(displayContent.getWindowList());
             // Don't do layout here, the window must call
             // relayout to be displayed, so we'll do it there.
 
@@ -2489,7 +2474,9 @@
 
         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
         mWindowMap.remove(win.mClient.asBinder());
-        mWindows.remove(win);
+
+        final WindowList windows = win.getWindowList();
+        windows.remove(win);
         mPendingRemove.remove(win);
         mWindowsChanged = true;
         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
@@ -2547,7 +2534,7 @@
         }
 
         if (!mInLayout) {
-            assignLayersLocked();
+            assignLayersLocked(windows);
             mLayoutNeeded = true;
             performLayoutAndPlaceSurfacesLocked();
             if (win.mAppToken != null) {
@@ -2700,11 +2687,12 @@
         mTmpFloats[Matrix.MSKEW_X] = dsdy;
         mTmpFloats[Matrix.MSCALE_Y] = dtdy;
         matrix.setValues(mTmpFloats);
+        final DisplayInfo displayInfo = window.mDisplayContent.getDisplayInfo();
         final RectF dispRect = new RectF(0, 0,
-                mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+                displayInfo.logicalWidth, displayInfo.logicalHeight);
         matrix.mapRect(dispRect);
         window.mGivenTouchableRegion.set(0, 0,
-                mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+                displayInfo.logicalWidth, displayInfo.logicalHeight);
         window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
                 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
         window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
@@ -2979,13 +2967,14 @@
             mLayoutNeeded = true;
             win.mGivenInsetsPending = (flags&WindowManagerImpl.RELAYOUT_INSETS_PENDING) != 0;
             if (assignLayers) {
-                assignLayersLocked();
+                assignLayersLocked(win.getWindowList());
             }
             configChanged = updateOrientationFromAppTokensLocked(false);
             performLayoutAndPlaceSurfacesLocked();
             if (toBeDisplayed && win.mIsWallpaper) {
+                DisplayInfo displayInfo = getDefaultDisplayInfo();
                 updateWallpaperOffsetLocked(win,
-                        mDisplayInfo.appWidth, mDisplayInfo.appHeight, false);
+                        displayInfo.appWidth, displayInfo.appHeight, false);
             }
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
@@ -3203,10 +3192,12 @@
                 duration = 300;
                 break;
         }
+        // TODO(multidisplay): For now assume all app animation is on main display.
+        final DisplayInfo displayInfo = getDefaultDisplayInfo();
         if (enter) {
             // Entering app zooms out from the center of the initial rect.
-            float scaleW = mNextAppTransitionStartWidth / (float) mDisplayInfo.appWidth;
-            float scaleH = mNextAppTransitionStartHeight / (float) mDisplayInfo.appHeight;
+            float scaleW = mNextAppTransitionStartWidth / (float) displayInfo.appWidth;
+            float scaleH = mNextAppTransitionStartHeight / (float) displayInfo.appHeight;
             Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
                     computePivot(mNextAppTransitionStartX, scaleW),
                     computePivot(mNextAppTransitionStartY, scaleH));
@@ -3226,8 +3217,8 @@
         final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
                 com.android.internal.R.interpolator.decelerate_cubic);
         a.setInterpolator(interpolator);
-        a.initialize(mDisplayInfo.appWidth, mDisplayInfo.appHeight,
-                mDisplayInfo.appWidth, mDisplayInfo.appHeight);
+        a.initialize(displayInfo.appWidth, displayInfo.appHeight,
+                displayInfo.appWidth, displayInfo.appHeight);
         return a;
     }
 
@@ -3253,11 +3244,13 @@
                 duration = delayed ? 250 : 300;
                 break;
         }
+        // TOOD(multidisplay): For now assume all app animation is on the main screen.
+        DisplayInfo displayInfo = getDefaultDisplayInfo();
         if (thumb) {
             // Animation for zooming thumbnail from its initial size to
             // filling the screen.
-            float scaleW = mDisplayInfo.appWidth/thumbWidth;
-            float scaleH = mDisplayInfo.appHeight/thumbHeight;
+            float scaleW = displayInfo.appWidth/thumbWidth;
+            float scaleH = displayInfo.appHeight/thumbHeight;
 
             Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
                     computePivot(mNextAppTransitionStartX, 1/scaleW),
@@ -3277,8 +3270,8 @@
             a = set;
         } else if (enter) {
             // Entering app zooms out from the center of the thumbnail.
-            float scaleW = thumbWidth / mDisplayInfo.appWidth;
-            float scaleH = thumbHeight / mDisplayInfo.appHeight;
+            float scaleW = thumbWidth / displayInfo.appWidth;
+            float scaleH = thumbHeight / displayInfo.appHeight;
             Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
                     computePivot(mNextAppTransitionStartX, scaleW),
                     computePivot(mNextAppTransitionStartY, scaleH));
@@ -3304,8 +3297,8 @@
         final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
                 com.android.internal.R.interpolator.decelerate_quad);
         a.setInterpolator(interpolator);
-        a.initialize(mDisplayInfo.appWidth, mDisplayInfo.appHeight,
-                mDisplayInfo.appWidth, mDisplayInfo.appHeight);
+        a.initialize(displayInfo.appWidth, displayInfo.appHeight,
+                displayInfo.appWidth, displayInfo.appHeight);
         return a;
     }
 
@@ -3534,7 +3527,8 @@
                         }
 
                         if (win.isVisibleNow()) {
-                            win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false);
+                            win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
+                                    false);
                             changed = true;
                         }
                     }
@@ -3654,9 +3648,11 @@
             return mLastWindowForcedOrientation;
         }
 
-        int pos = mWindows.size() - 1;
+        // TODO(multidisplay): Change to the correct display.
+        final WindowList windows = getDefaultWindowList();
+        int pos = windows.size() - 1;
         while (pos >= 0) {
-            WindowState wtoken = mWindows.get(pos);
+            WindowState wtoken = windows.get(pos);
             pos--;
             if (wtoken.mAppToken != null) {
                 // We hit an application window. so the orientation will be determined by the
@@ -4115,7 +4111,7 @@
                         if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
                             Slog.v(TAG, "Removing starting window: " + startingWindow);
                         }
-                        mWindows.remove(startingWindow);
+                        startingWindow.getWindowList().remove(startingWindow);
                         mWindowsChanged = true;
                         if (DEBUG_ADD_REMOVE) Slog.v(TAG,
                                 "Removing starting " + startingWindow + " from " + ttoken);
@@ -4652,14 +4648,14 @@
         for (int i=0; i<NW; i++) {
             WindowState win = token.windows.get(i);
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
-            mWindows.remove(win);
+            win.getWindowList().remove(win);
             int j = win.mChildWindows.size();
             while (j > 0) {
                 j--;
                 WindowState cwin = win.mChildWindows.get(j);
                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
                         "Tmp removing child window " + cwin);
-                mWindows.remove(cwin);
+                cwin.getWindowList().remove(cwin);
             }
         }
         return NW > 0;
@@ -4678,19 +4674,22 @@
     }
 
     void dumpWindowsLocked() {
-        for (int i=mWindows.size()-1; i>=0; i--) {
-            Slog.v(TAG, "  #" + i + ": " + mWindows.get(i));
+        int i = 0;
+        final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+        while (iterator.hasNext()) {
+            final WindowState w = iterator.next();
+            Slog.v(TAG, "  #" + i++ + ": " + w);
         }
     }
 
-    private int findWindowOffsetLocked(int tokenPos) {
-        final int NW = mWindows.size();
+    private int findWindowOffsetLocked(WindowList windows, int tokenPos) {
+        final int NW = windows.size();
 
         if (tokenPos >= mAnimatingAppTokens.size()) {
             int i = NW;
             while (i > 0) {
                 i--;
-                WindowState win = mWindows.get(i);
+                WindowState win = windows.get(i);
                 if (win.getAppToken() != null) {
                     return i+1;
                 }
@@ -4700,7 +4699,7 @@
         while (tokenPos > 0) {
             // Find the first app token below the new position that has
             // a window displayed.
-            final AppWindowToken wtoken = mAnimatingAppTokens.get(tokenPos-1);
+            final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
             if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
                     + tokenPos + " -- " + wtoken.token);
             if (wtoken.sendingToBottom) {
@@ -4719,7 +4718,7 @@
                     WindowState cwin = win.mChildWindows.get(j);
                     if (cwin.mSubLayer >= 0) {
                         for (int pos=NW-1; pos>=0; pos--) {
-                            if (mWindows.get(pos) == cwin) {
+                            if (windows.get(pos) == cwin) {
                                 if (DEBUG_REORDER) Slog.v(TAG,
                                         "Found child win @" + (pos+1));
                                 return pos+1;
@@ -4728,7 +4727,7 @@
                     }
                 }
                 for (int pos=NW-1; pos>=0; pos--) {
-                    if (mWindows.get(pos) == win) {
+                    if (windows.get(pos) == win) {
                         if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1));
                         return pos+1;
                     }
@@ -4741,6 +4740,7 @@
     }
 
     private final int reAddWindowLocked(int index, WindowState win) {
+        final WindowList windows = win.getWindowList();
         final int NCW = win.mChildWindows.size();
         boolean added = false;
         for (int j=0; j<NCW; j++) {
@@ -4749,31 +4749,35 @@
                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
                         + index + ": " + cwin);
                 win.mRebuilding = false;
-                mWindows.add(index, win);
+                windows.add(index, win);
                 index++;
                 added = true;
             }
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
                     + index + ": " + cwin);
             cwin.mRebuilding = false;
-            mWindows.add(index, cwin);
+            windows.add(index, cwin);
             index++;
         }
         if (!added) {
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
                     + index + ": " + win);
             win.mRebuilding = false;
-            mWindows.add(index, win);
+            windows.add(index, win);
             index++;
         }
         mWindowsChanged = true;
         return index;
     }
 
-    private final int reAddAppWindowsLocked(int index, WindowToken token) {
+    private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
+                                            WindowToken token) {
         final int NW = token.windows.size();
         for (int i=0; i<NW; i++) {
-            index = reAddWindowLocked(index, token.windows.get(i));
+            final WindowState win = token.windows.get(i);
+            if (win.mDisplayContent == displayContent) {
+                index = reAddWindowLocked(index, token.windows.get(i));
+            }
         }
         return index;
     }
@@ -4819,7 +4823,13 @@
                 if (tmpRemoveAppWindowsLocked(wtoken)) {
                     if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
                     if (DEBUG_REORDER) dumpWindowsLocked();
-                    reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
+                    DisplayContentsIterator iterator = new DisplayContentsIterator();
+                    while(iterator.hasNext()) {
+                        final DisplayContent displayContent = iterator.next();
+                        final WindowList windows = displayContent.getWindowList();
+                        final int pos = findWindowOffsetLocked(windows, index);
+                        reAddAppWindowsLocked(displayContent, pos, wtoken);
+                    }
                     if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
                     if (DEBUG_REORDER) dumpWindowsLocked();
                     updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
@@ -4858,18 +4868,25 @@
         // First remove all of the windows from the list.
         tmpRemoveAppWindowsLocked(wtoken);
 
-        // Where to start adding?
-        int pos = findWindowOffsetLocked(tokenPos);
-
         // And now add them back at the correct place.
-        pos = reAddAppWindowsLocked(pos, wtoken);
+        DisplayContentsIterator iterator = new DisplayContentsIterator();
+        while (iterator.hasNext()) {
+            final DisplayContent displayContent = iterator.next();
+            final WindowList windows = displayContent.getWindowList();
+            final int pos = findWindowOffsetLocked(windows, tokenPos);
+            reAddAppWindowsLocked(displayContent, pos, wtoken);
+
+            if (updateFocusAndLayout && !updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 
+                    false /*updateInputWindows*/)) {
+                assignLayersLocked(windows);
+            }
+        }
 
         if (updateFocusAndLayout) {
             mInputMonitor.setUpdateInputWindowsNeededLw();
-            if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                    false /*updateInputWindows*/)) {
-                assignLayersLocked();
-            }
+
+            // Note that the above updateFocusedWindowLocked conditional used to sit here.
+
             mLayoutNeeded = true;
             if (!mInLayout) {
                 performLayoutAndPlaceSurfacesLocked();
@@ -4889,22 +4906,29 @@
             }
         }
 
-        // Where to start adding?
-        int pos = findWindowOffsetLocked(tokenPos);
-
         // And now add them back at the correct place.
-        for (i=0; i<N; i++) {
-            WindowToken token = mTokenMap.get(tokens.get(i));
-            if (token != null) {
-                pos = reAddAppWindowsLocked(pos, token);
+        DisplayContentsIterator iterator = new DisplayContentsIterator();
+        while (iterator.hasNext()) {
+            final DisplayContent displayContent = iterator.next();
+            final WindowList windows = displayContent.getWindowList();
+            // Where to start adding?
+            int pos = findWindowOffsetLocked(windows, tokenPos);
+            for (i=0; i<N; i++) {
+                WindowToken token = mTokenMap.get(tokens.get(i));
+                if (token != null) {
+                    pos = reAddAppWindowsLocked(displayContent, pos, token);
+                }
+            }
+            if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                    false /*updateInputWindows*/)) {
+                assignLayersLocked(windows);
             }
         }
 
         mInputMonitor.setUpdateInputWindowsNeededLw();
-        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                false /*updateInputWindows*/)) {
-            assignLayersLocked();
-        }
+
+        // Note that the above updateFocusedWindowLocked used to sit here. 
+
         mLayoutNeeded = true;
         performLayoutAndPlaceSurfacesLocked();
         mInputMonitor.updateInputWindowsLw(false /*force*/);
@@ -5084,8 +5108,9 @@
 
     public void closeSystemDialogs(String reason) {
         synchronized(mWindowMap) {
-            for (int i=mWindows.size()-1; i>=0; i--) {
-                WindowState w = mWindows.get(i);
+            final AllWindowsIterator iterator = new AllWindowsIterator();
+            while (iterator.hasNext()) {
+                final WindowState w = iterator.next();
                 if (w.mHasSurface) {
                     try {
                         w.mClient.closeSystemDialogs(reason);
@@ -5290,9 +5315,11 @@
                         com.android.internal.R.bool.config_enableWallpaperService)
                         && !mOnlyCore;
                 boolean haveKeyguard = true;
-                final int N = mWindows.size();
+                // TODO(multidisplay): Expand to all displays?
+                final WindowList windows = getDefaultWindowList();
+                final int N = windows.size();
                 for (int i=0; i<N; i++) {
-                    WindowState w = mWindows.get(i);
+                    WindowState w = windows.get(i);
                     if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) {
                         // Only if there is a keyguard attached to the window manager
                         // will we consider ourselves as having a keyguard.  If it
@@ -5444,8 +5471,9 @@
             // the background..)
             if (on) {
                 boolean isVisible = false;
-                for (int i = mWindows.size() - 1; i >= 0; i--) {
-                    final WindowState ws = mWindows.get(i);
+                final AllWindowsIterator iterator = new AllWindowsIterator();
+                while (iterator.hasNext()) {
+                    final WindowState ws = iterator.next();
                     if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
                         isVisible = true;
                         break;
@@ -5481,10 +5509,11 @@
      * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
      * of the target image.
      * 
+     * @param displayId the Display to take a screenshot of.
      * @param width the width of the target bitmap
      * @param height the height of the target bitmap
      */
-    public Bitmap screenshotApplications(IBinder appToken, int width, int height) {
+    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height) {
         if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
                 "screenshotApplications()")) {
             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
@@ -5502,8 +5531,10 @@
         synchronized(mWindowMap) {
             long ident = Binder.clearCallingIdentity();
 
-            dw = mDisplayInfo.logicalWidth;
-            dh = mDisplayInfo.logicalHeight;
+            final DisplayContent displayContent = getDisplayContent(displayId);
+            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+            dw = displayInfo.logicalWidth;
+            dh = displayInfo.logicalHeight;
 
             int aboveAppLayer = mPolicy.windowTypeToLayerLw(
                     WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
@@ -5517,8 +5548,9 @@
 
             // Figure out the part of the screen that is actually the app.
             boolean including = false;
-            for (int i=mWindows.size()-1; i>=0; i--) {
-                WindowState ws = mWindows.get(i);
+            final WindowList windows = displayContent.getWindowList();
+            for (int i = windows.size() - 1; i >= 0; i--) {
+                WindowState ws = windows.get(i);
                 if (!ws.mHasSurface) {
                     continue;
                 }
@@ -5605,10 +5637,11 @@
             }
             if (DEBUG_SCREENSHOT) {
                 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from 0 to " + maxLayer);
-                for (int i=0; i<mWindows.size(); i++) {
-                    Slog.i(TAG, mWindows.get(i) + ": " + mWindows.get(i).mLayer
-                            + " animLayer=" + mWindows.get(i).mWinAnimator.mAnimLayer
-                            + " surfaceLayer=" + mWindows.get(i).mWinAnimator.mSurfaceLayer);
+                for (int i = 0; i < windows.size(); i++) {
+                    WindowState win = windows.get(i);
+                    Slog.i(TAG, win + ": " + win.mLayer
+                            + " animLayer=" + win.mWinAnimator.mAnimLayer
+                            + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
                 }
             }
             rawss = Surface.screenshot(dw, dh, 0, maxLayer);
@@ -5730,6 +5763,7 @@
         Binder.restoreCallingIdentity(origId);
     }
 
+    // TODO(multidisplay): Rotate any display?
     /**
      * Updates the current rotation.
      *
@@ -5812,6 +5846,8 @@
                     ">>> OPEN TRANSACTION setRotationUnchecked");
             Surface.openTransaction();
         }
+        final DisplayContent displayContent = getDefaultDisplayContent();
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
         try {
             // NOTE: We disable the rotation in the emulator because
             //       it doesn't support hardware OpenGL emulation yet.
@@ -5819,7 +5855,7 @@
                     && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
                 if (mAnimator.mScreenRotationAnimation.setRotation(rotation, mFxSession,
                         MAX_ANIMATION_DURATION, mTransitionAnimationScale,
-                        mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
+                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
                     updateLayoutToAnimationLocked();
                 }
             }
@@ -5834,8 +5870,9 @@
 
         rebuildBlackFrame();
 
-        for (int i=mWindows.size()-1; i>=0; i--) {
-            WindowState w = mWindows.get(i);
+        final WindowList windows = displayContent.getWindowList();
+        for (int i = windows.size() - 1; i >= 0; i--) {
+            WindowState w = windows.get(i);
             if (w.mHasSurface) {
                 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
                 w.mOrientationChanging = true;
@@ -5906,7 +5943,9 @@
         synchronized (mWindowMap) {
             final int rotation = getRotation();
 
-            if (mInitialDisplayWidth < mInitialDisplayHeight) {
+            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
+            final DisplayContent displayContent = getDefaultDisplayContent();
+            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
                 // On devices with a natural orientation of portrait
                 switch (rotation) {
                     default:
@@ -6042,10 +6081,13 @@
 
         boolean result = true;
 
-        WindowState[] windows;
+        WindowList windows = new WindowList();
         synchronized (mWindowMap) {
             //noinspection unchecked
-            windows = mWindows.toArray(new WindowState[mWindows.size()]);
+            DisplayContentsIterator iterator = new DisplayContentsIterator();
+            while(iterator.hasNext()) {
+                windows.addAll(iterator.next().getWindowList());
+            }
         }
 
         BufferedWriter out = null;
@@ -6055,9 +6097,9 @@
             OutputStream clientStream = client.getOutputStream();
             out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
 
-            final int count = windows.length;
+            final int count = windows.size();
             for (int i = 0; i < count; i++) {
-                final WindowState w = windows[i];
+                final WindowState w = windows.get(i);
                 out.write(Integer.toHexString(System.identityHashCode(w)));
                 out.write(' ');
                 out.append(w.mAttrs.getTitle());
@@ -6081,6 +6123,7 @@
         return result;
     }
 
+    // TODO(multidisplay): Extend to multiple displays.
     /**
      * Returns the focused window in the following format:
      * windowHashCodeInHexadecimal windowName
@@ -6266,15 +6309,14 @@
 
     private WindowState findWindow(int hashCode) {
         if (hashCode == -1) {
+            // TODO(multidisplay): Extend to multiple displays.
             return getFocusedWindow();
         }
 
         synchronized (mWindowMap) {
-            final ArrayList<WindowState> windows = mWindows;
-            final int count = windows.size();
-
-            for (int i = 0; i < count; i++) {
-                WindowState w = windows.get(i);
+            final AllWindowsIterator iterator = new AllWindowsIterator();
+            while (iterator.hasNext()) {
+                final WindowState w = iterator.next();
                 if (System.identityHashCode(w) == hashCode) {
                     return w;
                 }
@@ -6316,20 +6358,20 @@
         return config;
     }
 
-    private void adjustDisplaySizeRanges(int rotation, int dw, int dh) {
+    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
         final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
-        if (width < mDisplayInfo.smallestNominalAppWidth) {
-            mDisplayInfo.smallestNominalAppWidth = width;
+        if (width < displayInfo.smallestNominalAppWidth) {
+            displayInfo.smallestNominalAppWidth = width;
         }
-        if (width > mDisplayInfo.largestNominalAppWidth) {
-            mDisplayInfo.largestNominalAppWidth = width;
+        if (width > displayInfo.largestNominalAppWidth) {
+            displayInfo.largestNominalAppWidth = width;
         }
         final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
-        if (height < mDisplayInfo.smallestNominalAppHeight) {
-            mDisplayInfo.smallestNominalAppHeight = height;
+        if (height < displayInfo.smallestNominalAppHeight) {
+            displayInfo.smallestNominalAppHeight = height;
         }
-        if (height > mDisplayInfo.largestNominalAppHeight) {
-            mDisplayInfo.largestNominalAppHeight = height;
+        if (height > displayInfo.largestNominalAppHeight) {
+            displayInfo.largestNominalAppHeight = height;
         }
     }
 
@@ -6412,8 +6454,8 @@
         return curLayout;
     }
 
-    private void computeSizeRangesAndScreenLayout(boolean rotated, int dw, int dh,
-            float density, Configuration outConfig) {
+    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
+                  int dw, int dh, float density, Configuration outConfig) {
         // We need to determine the smallest width that will occur under normal
         // operation.  To this, start with the base screen size and compute the
         // width under the different possible rotations.  We need to un-rotate
@@ -6426,21 +6468,21 @@
             unrotDw = dw;
             unrotDh = dh;
         }
-        mDisplayInfo.smallestNominalAppWidth = 1<<30;
-        mDisplayInfo.smallestNominalAppHeight = 1<<30;
-        mDisplayInfo.largestNominalAppWidth = 0;
-        mDisplayInfo.largestNominalAppHeight = 0;
-        adjustDisplaySizeRanges(Surface.ROTATION_0, unrotDw, unrotDh);
-        adjustDisplaySizeRanges(Surface.ROTATION_90, unrotDh, unrotDw);
-        adjustDisplaySizeRanges(Surface.ROTATION_180, unrotDw, unrotDh);
-        adjustDisplaySizeRanges(Surface.ROTATION_270, unrotDh, unrotDw);
+        displayInfo.smallestNominalAppWidth = 1<<30;
+        displayInfo.smallestNominalAppHeight = 1<<30;
+        displayInfo.largestNominalAppWidth = 0;
+        displayInfo.largestNominalAppHeight = 0;
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
+        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
         int sl = Configuration.SCREENLAYOUT_SIZE_XLARGE
                 | Configuration.SCREENLAYOUT_LONG_YES;
         sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
         sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
         sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
         sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
-        outConfig.smallestScreenWidthDp = (int)(mDisplayInfo.smallestNominalAppWidth / density);
+        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
         outConfig.screenLayout = sl;
     }
 
@@ -6479,11 +6521,16 @@
             return false;
         }
 
+        // TODO(multidisplay): For now, apply Configuration to main screen only.
+        final DisplayContent displayContent = getDefaultDisplayContent();
+
         // Use the effective "visual" dimensions based on current rotation
         final boolean rotated = (mRotation == Surface.ROTATION_90
                 || mRotation == Surface.ROTATION_270);
-        final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
-        final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
+        final int realdw = rotated ?
+                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
+        final int realdh = rotated ?
+                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
         int dw = realdw;
         int dh = realdh;
 
@@ -6516,15 +6563,16 @@
         // Update application display metrics.
         final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
         final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
-        synchronized(mDisplaySizeLock) {
-            mDisplayInfo.rotation = mRotation;
-            mDisplayInfo.logicalWidth = dw;
-            mDisplayInfo.logicalHeight = dh;
-            mDisplayInfo.appWidth = appWidth;
-            mDisplayInfo.appHeight = appHeight;
-            mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics, null);
-            mDisplayInfo.getAppMetrics(mDisplayMetrics, null);
-            mDisplayManager.setDefaultDisplayInfo(mDisplayInfo);
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        synchronized(displayContent.mDisplaySizeLock) {
+            displayInfo.rotation = mRotation;
+            displayInfo.logicalWidth = dw;
+            displayInfo.logicalHeight = dh;
+            displayInfo.appWidth = appWidth;
+            displayInfo.appHeight = appHeight;
+            displayInfo.getLogicalMetrics(mRealDisplayMetrics, null);
+            displayInfo.getAppMetrics(mDisplayMetrics, null);
+            mDisplayManager.setDefaultDisplayInfo(displayInfo);
 
             mAnimator.setDisplayDimensions(dw, dh, appWidth, appHeight);
         }
@@ -6541,7 +6589,7 @@
                     / dm.density);
             config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
                     / dm.density);
-            computeSizeRangesAndScreenLayout(rotated, dw, dh, dm.density, config);
+            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
 
             config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
             config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
@@ -6833,6 +6881,10 @@
     }
 
     public void displayReady() {
+        displayReady(Display.DEFAULT_DISPLAY);
+    }
+
+    public void displayReady(int displayId) {
         synchronized(mWindowMap) {
             if (mDisplay != null) {
                 throw new IllegalStateException("Display already initialized");
@@ -6842,26 +6894,29 @@
             mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_TOUCHSCREEN);
 
-            synchronized(mDisplaySizeLock) {
+            final DisplayContent displayContent = getDisplayContent(displayId);
+            synchronized(displayContent.mDisplaySizeLock) {
                 // Bootstrap the default logical display from the display manager.
-                mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY, mDisplayInfo);
-                mInitialDisplayWidth = mDisplayInfo.logicalWidth;
-                mInitialDisplayHeight = mDisplayInfo.logicalHeight;
-                mBaseDisplayWidth = mInitialDisplayWidth;
-                mBaseDisplayHeight = mInitialDisplayHeight;
+                final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+                mDisplayManager.getDisplayInfo(displayId, displayInfo);
+                displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
+                displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
+                displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
+                displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
 
-                mAnimator.setDisplayDimensions(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
-                        mDisplayInfo.appWidth, mDisplayInfo.appHeight);
+                mAnimator.setDisplayDimensions(displayInfo.logicalWidth, displayInfo.logicalHeight,
+                        displayInfo.appWidth, displayInfo.appHeight);
             }
 
             DisplayDeviceInfo info = new DisplayDeviceInfo();
             mDisplayManager.getDefaultExternalDisplayDeviceInfo(info);
-            mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
-                    mInitialDisplayWidth, mInitialDisplayHeight,
+            mInputManager.setDisplaySize(displayId,
+                    displayContent.mInitialDisplayWidth, displayContent.mInitialDisplayHeight,
                     info.width, info.height);
-            mInputManager.setDisplayOrientation(Display.DEFAULT_DISPLAY,
+            mInputManager.setDisplayOrientation(displayId,
                     mDisplay.getRotation(), Surface.ROTATION_0);
-            mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight);
+            mPolicy.setInitialDisplaySize(mDisplay,
+                    displayContent.mInitialDisplayWidth, displayContent.mInitialDisplayHeight);
         }
 
         try {
@@ -6870,7 +6925,7 @@
         }
         
         synchronized (mWindowMap) {
-            readForcedDisplaySizeLocked();
+            readForcedDisplaySizeLocked(getDisplayContent(displayId));
         }
     }
 
@@ -6878,14 +6933,13 @@
         mPolicy.systemReady();
     }
 
+    // TODO(multidisplay): Call isScreenOn for each display.
     private void sendScreenStatusToClientsLocked() {
-        final ArrayList<WindowState> windows = mWindows;
-        final int count = windows.size();
-        boolean on = mPowerManager.isScreenOn();
-        for (int i = count - 1; i >= 0; i--) {
-            WindowState win = mWindows.get(i);
+        final boolean on = mPowerManager.isScreenOn();
+        final AllWindowsIterator iterator = new AllWindowsIterator();
+        while (iterator.hasNext()) {
             try {
-                win.mClient.dispatchScreenState(on);
+                iterator.next().mClient.dispatchScreenState(on);
             } catch (RemoteException e) {
                 // Ignored
             }
@@ -7162,12 +7216,14 @@
                 } break;
 
                 case WINDOW_FREEZE_TIMEOUT: {
+                    // TODO(multidisplay): Can non-default displays rotate?
                     synchronized (mWindowMap) {
                         Slog.w(TAG, "Window freeze timeout expired.");
-                        int i = mWindows.size();
+                        final WindowList windows = getDefaultWindowList();
+                        int i = windows.size();
                         while (i > 0) {
                             i--;
-                            WindowState w = mWindows.get(i);
+                            WindowState w = windows.get(i);
                             if (w.mOrientationChanging) {
                                 w.mOrientationChanging = false;
                                 Slog.w(TAG, "Force clearing orientation change: " + w);
@@ -7413,13 +7469,13 @@
             // The focus for the client is the window immediately below
             // where we would place the input method window.
             int idx = findDesiredInputMethodWindowIndexLocked(false);
-            WindowState imFocus;
             if (idx > 0) {
-                imFocus = mWindows.get(idx-1);
+                // TODO(multidisplay): IMEs are only supported on the default display.
+                WindowState imFocus = getDefaultWindowList().get(idx-1);
                 if (DEBUG_INPUT_METHOD) {
                     Slog.i(TAG, "Desired input method target: " + imFocus);
-                    Slog.i(TAG, "Current focus: " + this.mCurrentFocus);
-                    Slog.i(TAG, "Last focus: " + this.mLastFocus);
+                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
+                    Slog.i(TAG, "Last focus: " + mLastFocus);
                 }
                 if (imFocus != null) {
                     // This may be a starting window, in which case we still want
@@ -7449,47 +7505,51 @@
                             imFocus.mSession.mClient.asBinder() == client.asBinder()) {
                         return true;
                     }
-                    
-                    // Okay, how about this...  what is the current focus?
-                    // It seems in some cases we may not have moved the IM
-                    // target window, such as when it was in a pop-up window,
-                    // so let's also look at the current focus.  (An example:
-                    // go to Gmail, start searching so the keyboard goes up,
-                    // press home.  Sometimes the IME won't go down.)
-                    // Would be nice to fix this more correctly, but it's
-                    // way at the end of a release, and this should be good enough.
-                    if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null &&
-                            mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
-                        return true;
-                    }
                 }
             }
+
+            // Okay, how about this...  what is the current focus?
+            // It seems in some cases we may not have moved the IM
+            // target window, such as when it was in a pop-up window,
+            // so let's also look at the current focus.  (An example:
+            // go to Gmail, start searching so the keyboard goes up,
+            // press home.  Sometimes the IME won't go down.)
+            // Would be nice to fix this more correctly, but it's
+            // way at the end of a release, and this should be good enough.
+            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
+                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
+                return true;
+            }
         }
         return false;
     }
 
-    public void getInitialDisplaySize(Point size) {
-        synchronized(mDisplaySizeLock) {
-            size.x = mInitialDisplayWidth;
-            size.y = mInitialDisplayHeight;
+    public void getInitialDisplaySize(int displayId, Point size) {
+        // TODO(cmautner): Access to DisplayContent should be locked on mWindowMap. Doing that
+        //  could lead to deadlock since this is called from ActivityManager.
+        final DisplayContent displayContent = getDisplayContent(displayId);
+        synchronized(displayContent.mDisplaySizeLock) {
+            size.x = displayContent.mInitialDisplayWidth;
+            size.y = displayContent.mInitialDisplayHeight;
         }
     }
 
-    public void setForcedDisplaySize(int longDimen, int shortDimen) {
+    public void setForcedDisplaySize(int displayId, int longDimen, int shortDimen) {
         synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContent(displayId);
             int width, height;
-            if (mInitialDisplayWidth < mInitialDisplayHeight) {
-                width = shortDimen < mInitialDisplayWidth
-                        ? shortDimen : mInitialDisplayWidth;
-                height = longDimen < mInitialDisplayHeight
-                        ? longDimen : mInitialDisplayHeight;
+            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
+                width = shortDimen < displayContent.mInitialDisplayWidth
+                        ? shortDimen : displayContent.mInitialDisplayWidth;
+                height = longDimen < displayContent.mInitialDisplayHeight
+                        ? longDimen : displayContent.mInitialDisplayHeight;
             } else {
-                width = longDimen < mInitialDisplayWidth
-                        ? longDimen : mInitialDisplayWidth;
-                height = shortDimen < mInitialDisplayHeight
-                        ? shortDimen : mInitialDisplayHeight;
+                width = longDimen < displayContent.mInitialDisplayWidth
+                        ? longDimen : displayContent.mInitialDisplayWidth;
+                height = shortDimen < displayContent.mInitialDisplayHeight
+                        ? shortDimen : displayContent.mInitialDisplayHeight;
             }
-            setForcedDisplaySizeLocked(width, height);
+            setForcedDisplaySizeLocked(displayContent, width, height);
             Settings.Secure.putString(mContext.getContentResolver(),
                     Settings.Secure.DISPLAY_SIZE_FORCED, width + "," + height);
         }
@@ -7500,21 +7560,23 @@
             mBlackFrame.kill();
             mBlackFrame = null;
         }
-        if (mBaseDisplayWidth < mInitialDisplayWidth
-                || mBaseDisplayHeight < mInitialDisplayHeight) {
+        // TODO(multidisplay): For now rotations are only main screen.
+        final DisplayContent displayContent = getDefaultDisplayContent();
+        if (displayContent.mBaseDisplayWidth < displayContent.mInitialDisplayWidth
+                || displayContent.mBaseDisplayHeight < displayContent.mInitialDisplayHeight) {
             int initW, initH, baseW, baseH;
             final boolean rotated = (mRotation == Surface.ROTATION_90
                     || mRotation == Surface.ROTATION_270);
             if (rotated) {
-                initW = mInitialDisplayHeight;
-                initH = mInitialDisplayWidth;
-                baseW = mBaseDisplayHeight;
-                baseH = mBaseDisplayWidth;
+                initW = displayContent.mInitialDisplayHeight;
+                initH = displayContent.mInitialDisplayWidth;
+                baseW = displayContent.mBaseDisplayHeight;
+                baseH = displayContent.mBaseDisplayWidth;
             } else {
-                initW = mInitialDisplayWidth;
-                initH = mInitialDisplayHeight;
-                baseW = mBaseDisplayWidth;
-                baseH = mBaseDisplayHeight;
+                initW = displayContent.mInitialDisplayWidth;
+                initH = displayContent.mInitialDisplayHeight;
+                baseW = displayContent.mBaseDisplayWidth;
+                baseH = displayContent.mBaseDisplayHeight;
             }
             Rect outer = new Rect(0, 0, initW, initH);
             Rect inner = new Rect(0, 0, baseW, baseH);
@@ -7525,7 +7587,7 @@
         }
     }
 
-    private void readForcedDisplaySizeLocked() {
+    private void readForcedDisplaySizeLocked(final DisplayContent displayContent) {
         final String str = Settings.Secure.getString(mContext.getContentResolver(),
                 Settings.Secure.DISPLAY_SIZE_FORCED);
         if (str == null || str.length() == 0) {
@@ -7542,17 +7604,18 @@
         } catch (NumberFormatException ex) {
             return;
         }
-        setForcedDisplaySizeLocked(width, height);
+        setForcedDisplaySizeLocked(displayContent, width, height);
     }
 
-    private void setForcedDisplaySizeLocked(int width, int height) {
+    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
         Slog.i(TAG, "Using new display size: " + width + "x" + height);
 
-        synchronized(mDisplaySizeLock) {
-            mBaseDisplayWidth = width;
-            mBaseDisplayHeight = height;
+        synchronized(displayContent.mDisplaySizeLock) {
+            displayContent.mBaseDisplayWidth = width;
+            displayContent.mBaseDisplayHeight = height;
         }
-        mPolicy.setInitialDisplaySize(mDisplay, mBaseDisplayWidth, mBaseDisplayHeight);
+        mPolicy.setInitialDisplaySize(mDisplay, displayContent.mBaseDisplayWidth,
+                displayContent.mBaseDisplayHeight);
 
         mLayoutNeeded = true;
 
@@ -7576,9 +7639,11 @@
         performLayoutAndPlaceSurfacesLocked();
     }
 
-    public void clearForcedDisplaySize() {
+    public void clearForcedDisplaySize(int displayId) {
         synchronized(mWindowMap) {
-            setForcedDisplaySizeLocked(mInitialDisplayWidth, mInitialDisplayHeight);
+            final DisplayContent displayContent = getDisplayContent(displayId);
+            setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
+                    displayContent.mInitialDisplayHeight);
             Settings.Secure.putString(mContext.getContentResolver(),
                     Settings.Secure.DISPLAY_SIZE_FORCED, "");
         }
@@ -7626,7 +7691,15 @@
     }
 
     final void rebuildAppWindowListLocked() {
-        int NW = mWindows.size();
+        DisplayContentsIterator iterator = new DisplayContentsIterator();
+        while (iterator.hasNext()) {
+            rebuildAppWindowListLocked(iterator.next());
+        }
+    }
+
+    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
+        final WindowList windows = displayContent.getWindowList();
+        int NW = windows.size();
         int i;
         int lastBelow = -1;
         int numRemoved = 0;
@@ -7638,9 +7711,9 @@
         // First remove all existing app windows.
         i=0;
         while (i < NW) {
-            WindowState w = mWindows.get(i);
+            WindowState w = windows.get(i);
             if (w.mAppToken != null) {
-                WindowState win = mWindows.remove(i);
+                WindowState win = windows.remove(i);
                 win.mRebuilding = true;
                 mRebuildTmp[numRemoved] = win;
                 mWindowsChanged = true;
@@ -7669,13 +7742,13 @@
         // will care about them.
         int NT = mExitingAppTokens.size();
         for (int j=0; j<NT; j++) {
-            i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
+            i = reAddAppWindowsLocked(displayContent, i, mExitingAppTokens.get(j));
         }
 
         // And add in the still active app tokens in Z order.
         NT = mAnimatingAppTokens.size();
         for (int j=0; j<NT; j++) {
-            i = reAddAppWindowsLocked(i, mAnimatingAppTokens.get(j));
+            i = reAddAppWindowsLocked(displayContent, i, mAnimatingAppTokens.get(j));
         }
 
         i -= lastBelow;
@@ -7701,8 +7774,8 @@
         }
     }
 
-    private final void assignLayersLocked() {
-        int N = mWindows.size();
+    private final void assignLayersLocked(WindowList windows) {
+        int N = windows.size();
         int curBaseLayer = 0;
         int curLayer = 0;
         int i;
@@ -7714,7 +7787,7 @@
         }
 
         for (i=0; i<N; i++) {
-            final WindowState w = mWindows.get(i);
+            final WindowState w = windows.get(i);
             final WindowStateAnimator winAnimator = w.mWinAnimator;
             boolean layerChanged = false;
             int oldLayer = w.mLayer;
@@ -7807,34 +7880,32 @@
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
         }
-        
+
         try {
-            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
+            DisplayContentsIterator iterator = new DisplayContentsIterator();
+            while (iterator.hasNext()) {
+                final DisplayContent displayContent = iterator.next();
+                performLayoutAndPlaceSurfacesLockedInner(displayContent, recoveringMemory);
 
-            final int N = mPendingRemove.size();
-            if (N > 0) {
-                if (mPendingRemoveTmp.length < N) {
-                    mPendingRemoveTmp = new WindowState[N+10];
+                final int N = mPendingRemove.size();
+                if (N > 0) {
+                    if (mPendingRemoveTmp.length < N) {
+                        mPendingRemoveTmp = new WindowState[N+10];
+                    }
+                    mPendingRemove.toArray(mPendingRemoveTmp);
+                    mPendingRemove.clear();
+                    for (int i=0; i<N; i++) {
+                        WindowState w = mPendingRemoveTmp[i];
+                        removeWindowInnerLocked(w.mSession, w);
+                    }
+
+                    assignLayersLocked(displayContent.getWindowList());
+                    mLayoutNeeded = true;
                 }
-                mPendingRemove.toArray(mPendingRemoveTmp);
-                mPendingRemove.clear();
-                for (int i=0; i<N; i++) {
-                    WindowState w = mPendingRemoveTmp[i];
-                    removeWindowInnerLocked(w.mSession, w);
-                }
-
-                mInLayout = false;
-                assignLayersLocked();
-                mLayoutNeeded = true;
-                // XXX this recursion seems broken!
-                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
-                performLayoutAndPlaceSurfacesLocked();
-                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
-
-            } else {
-                mInLayout = false;
             }
 
+            mInLayout = false;
+
             if (mLayoutNeeded) {
                 if (++mLayoutRepeatCount < 6) {
                     requestTraversalLocked();
@@ -7858,22 +7929,24 @@
         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
     }
 
-    private final void performLayoutLockedInner(boolean initial, boolean updateInputWindows) {
+    private final void performLayoutLockedInner(final DisplayContent displayContent,
+                                    boolean initial, boolean updateInputWindows) {
         if (!mLayoutNeeded) {
             return;
         }
-        
+        WindowList windows = displayContent.getWindowList();
         mLayoutNeeded = false;
-        
-        final int dw = mDisplayInfo.logicalWidth;
-        final int dh = mDisplayInfo.logicalHeight;
+
+        DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
 
         final int NFW = mFakeWindows.size();
         for (int i=0; i<NFW; i++) {
             mFakeWindows.get(i).layout(dw, dh);
         }
 
-        final int N = mWindows.size();
+        final int N = windows.size();
         int i;
 
         if (DEBUG_LAYOUT) {
@@ -7896,7 +7969,7 @@
         // to another window).
         int topAttached = -1;
         for (i = N-1; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
+            final WindowState win = windows.get(i);
 
             // Don't do layout of a window if it is not visible, or
             // soon won't be visible, to avoid wasting time and funky
@@ -7963,7 +8036,7 @@
         // XXX does not deal with windows that are attached to windows
         // that are themselves attached.
         for (i = topAttached; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
+            final WindowState win = windows.get(i);
 
             if (win.mLayoutAttached) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
@@ -8024,10 +8097,11 @@
 
     /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
+     * @param windows TODO(cmautner):
      *
      * @return bitmap indicating if another pass through layout must be made.
      */
-    public int handleAppTransitionReadyLocked() {
+    public int handleAppTransitionReadyLocked(WindowList windows) {
         int changes = 0;
         int i;
         int NN = mOpeningApps.size();
@@ -8272,11 +8346,12 @@
             changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT
                     | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
             mLayoutNeeded = true;
-            if (!moveInputMethodWindowsIfNeededLocked(true)) {
-                assignLayersLocked();
+
+            // TODO(multidisplay): IMEs are only supported on the default display.
+            if (windows == getDefaultWindowList() && !moveInputMethodWindowsIfNeededLocked(true)) {
+                assignLayersLocked(windows);
             }
-            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
-                    false /*updateInputWindows*/);
+            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
             mFocusMayChange = false;
         }
 
@@ -8285,7 +8360,6 @@
 
     /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
-     *
      * @return bitmap indicating if another pass through layout must be made.
      */
     private int handleAnimatingStoppedAndTransitionLocked() {
@@ -8459,8 +8533,9 @@
                 if (!mAnimator.isDimming(winAnimator)) {
                     final int width, height;
                     if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) {
-                        width = mDisplayInfo.logicalWidth;
-                        height = mDisplayInfo.logicalHeight;
+                        final DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo();
+                        width = displayInfo.logicalWidth;
+                        height = displayInfo.logicalHeight;
                     } else {
                         width = innerDw;
                         height = innerDh;
@@ -8493,7 +8568,7 @@
 
     // "Something has changed!  Let's make it correct now."
     private final void performLayoutAndPlaceSurfacesLockedInner(
-            boolean recoveringMemory) {
+            final DisplayContent displayContent, boolean recoveringMemory) {
         if (DEBUG_WINDOW_TRACE) {
             Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
                     + Debug.getCallers(3));
@@ -8503,11 +8578,13 @@
             return;
         }
 
+        final WindowList windows = displayContent.getWindowList();
         final long currentTime = SystemClock.uptimeMillis();
-        final int dw = mDisplayInfo.logicalWidth;
-        final int dh = mDisplayInfo.logicalHeight;
-        final int innerDw = mDisplayInfo.appWidth;
-        final int innerDh = mDisplayInfo.appHeight;
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
+        final int innerDw = displayInfo.appWidth;
+        final int innerDh = displayInfo.appHeight;
 
         int i;
 
@@ -8559,8 +8636,8 @@
                     mPendingLayoutChanges);
 
                 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
-                    if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
-                        assignLayersLocked();
+                    if ((adjustWallpaperWindowsLocked() & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
+                        assignLayersLocked(windows);
                         mLayoutNeeded = true;
                     }
                 }
@@ -8579,7 +8656,7 @@
 
                 // FIRST LOOP: Perform a layout, if needed.
                 if (repeats < 4) {
-                    performLayoutLockedInner(repeats == 1, false /*updateInputWindows*/);
+                    performLayoutLockedInner(displayContent, repeats == 1, false /*updateInputWindows*/);
                 } else {
                     Slog.w(TAG, "Layout repeat skipped after too many iterations");
                 }
@@ -8590,8 +8667,8 @@
                 if (DEBUG_LAYOUT_REPEATS)  debugLayoutRepeats("loop number " + mLayoutRepeatCount,
                     mPendingLayoutChanges);
                 mPolicy.beginAnimationLw(dw, dh);
-                for (i = mWindows.size() - 1; i >= 0; i--) {
-                    WindowState w = mWindows.get(i);
+                for (i = windows.size() - 1; i >= 0; i--) {
+                    WindowState w = windows.get(i);
                     if (w.mHasSurface) {
                         mPolicy.animatingWindowLw(w, w.mAttrs);
                     }
@@ -8609,9 +8686,9 @@
 
             boolean focusDisplayed = false;
             boolean updateAllDrawn = false;
-            final int N = mWindows.size();
+            final int N = windows.size();
             for (i=N-1; i>=0; i--) {
-                WindowState w = mWindows.get(i);
+                WindowState w = windows.get(i);
 
                 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
 
@@ -8747,7 +8824,7 @@
         // all of the app tokens to be shown and see if they are ready
         // to go.
         if (mAppTransitionReady) {
-            mPendingLayoutChanges |= handleAppTransitionReadyLocked();
+            mPendingLayoutChanges |= handleAppTransitionReadyLocked(windows);
             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
                 mPendingLayoutChanges);
         }
@@ -8790,7 +8867,7 @@
             if (DEBUG_WALLPAPER) Slog.v(TAG,
                     "Wallpaper layer changed: assigning layers + relayout");
             mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
-            assignLayersLocked();
+            assignLayersLocked(windows);
         } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
             if (DEBUG_WALLPAPER) Slog.v(TAG,
                     "Wallpaper visibility changed: relayout");
@@ -9065,14 +9142,21 @@
         final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim;
         synchronized (layoutToAnim) {
             // Copy local params to transfer params.
-            ArrayList<WindowStateAnimator> winAnimators = layoutToAnim.mWinAnimators;
-            winAnimators.clear();
-            int N = mWindows.size();
-            for (int i = 0; i < N; i++) {
-                final WindowStateAnimator winAnimator = mWindows.get(i).mWinAnimator;
-                if (winAnimator.mSurface != null) {
-                    winAnimators.add(winAnimator);
+            ArrayList<WinAnimatorList> allWinAnimatorLists = layoutToAnim.mWinAnimatorLists;
+            allWinAnimatorLists.clear();
+            DisplayContentsIterator iterator = new DisplayContentsIterator();
+            while (iterator.hasNext()) {
+                final DisplayContent displayContent = iterator.next();
+                WinAnimatorList winAnimatorList = new WinAnimatorList();
+                final WindowList windows = displayContent.getWindowList();
+                int N = windows.size();
+                for (int i = 0; i < N; i++) {
+                    final WindowStateAnimator winAnimator = windows.get(i).mWinAnimator;
+                    if (winAnimator.mSurface != null) {
+                        winAnimatorList.add(winAnimator);
+                    }
                 }
+                allWinAnimatorLists.add(winAnimatorList);
             }
 
             layoutToAnim.mWallpaperTarget = mWallpaperTarget;
@@ -9081,7 +9165,7 @@
 
             final ArrayList<AppWindowAnimParams> paramList = layoutToAnim.mAppWindowAnimParams;
             paramList.clear();
-            N = mAnimatingAppTokens.size();
+            int N = mAnimatingAppTokens.size();
             for (int i = 0; i < N; i++) {
                 paramList.add(new AppWindowAnimParams(mAnimatingAppTokens.get(i).mAppAnimator));
             }
@@ -9174,10 +9258,11 @@
             // There was some problem...   first, do a sanity check of the
             // window list to make sure we haven't left any dangling surfaces
             // around.
-            int N = mWindows.size();
+
+            AllWindowsIterator iterator = new AllWindowsIterator();
             Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
-            for (int i=0; i<N; i++) {
-                WindowState ws = mWindows.get(i);
+            while (iterator.hasNext()) {
+                WindowState ws = iterator.next();
                 WindowStateAnimator wsa = ws.mWinAnimator;
                 if (wsa.mSurface != null) {
                     if (!mSessions.contains(wsa.mSession)) {
@@ -9192,8 +9277,6 @@
                         wsa.mSurface = null;
                         ws.mHasSurface = false;
                         mForceRemoves.add(ws);
-                        i--;
-                        N--;
                         leakedSurface = true;
                     } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
                         Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
@@ -9212,8 +9295,13 @@
             if (!leakedSurface) {
                 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
                 SparseIntArray pidCandidates = new SparseIntArray();
-                for (int i=0; i<N; i++) {
-                    WindowStateAnimator wsa = mWindows.get(i).mWinAnimator;
+                iterator = new AllWindowsIterator();
+                while (iterator.hasNext()) {
+                    WindowState ws = iterator.next();
+                    if (mForceRemoves.contains(ws)) {
+                        continue;
+                    }
+                    WindowStateAnimator wsa = ws.mWinAnimator;
                     if (wsa.mSurface != null) {
                         pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
                     }
@@ -9273,6 +9361,9 @@
             mLosingFocus.remove(newFocus);
             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
 
+            // TODO(multidisplay): Focused windows on default display only.
+            final DisplayContent displayContent = getDefaultDisplayContent();
+
             final WindowState imWindow = mInputMethodWindow;
             if (newFocus != imWindow && oldFocus != imWindow) {
                 if (moveInputMethodWindowsIfNeededLocked(
@@ -9281,12 +9372,12 @@
                     mLayoutNeeded = true;
                 }
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
-                    performLayoutLockedInner(true /*initial*/, updateInputWindows);
+                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
                     focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
                 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
                     // Client will do the layout, but we need to assign layers
                     // for handleNewWindowLocked() below.
-                    assignLayersLocked();
+                    assignLayersLocked(displayContent.getWindowList());
                 }
             }
 
@@ -9294,7 +9385,7 @@
                 // The change in focus caused us to need to do a layout.  Okay.
                 mLayoutNeeded = true;
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
-                    performLayoutLockedInner(true /*initial*/, updateInputWindows);
+                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
                 }
             }
 
@@ -9327,8 +9418,10 @@
         WindowToken nextApp = nextAppIndex >= 0
             ? mAppTokens.get(nextAppIndex) : null;
 
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            win = mWindows.get(i);
+        // TODO(multidisplay): IMEs are only supported on the default display.
+        WindowList windows = getDefaultWindowList();
+        for (int i = windows.size() - 1; i >= 0; i--) {
+            win = windows.get(i);
 
             if (localLOGV || DEBUG_FOCUS) Slog.v(
                 TAG, "Looking for focus: " + i
@@ -9422,8 +9515,10 @@
                 mAnimator.mScreenRotationAnimation = null;
             }
 
+            // TODO(multidisplay): rotation on main screen only.
+            DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo();
             mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
-                    mFxSession, inTransaction, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
+                    mFxSession, inTransaction, displayInfo.logicalWidth, displayInfo.logicalHeight,
                     mDisplay.getRotation());
         }
     }
@@ -9448,12 +9543,15 @@
         }
 
         boolean updateRotation = false;
-        
+
         if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null
                 && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
             if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
+            // TODO(multidisplay): rotation on main screen only.
+            DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo();
             if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
-                    mTransitionAnimationScale, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
+                    mTransitionAnimationScale, displayInfo.logicalWidth,
+                        displayInfo.logicalHeight)) {
                 updateLayoutToAnimationLocked();
             } else {
                 mAnimator.mScreenRotationAnimation.kill();
@@ -9562,11 +9660,13 @@
         }
     }
 
+    // TOOD(multidisplay): StatusBar on multiple screens?
     void updateStatusBarVisibilityLocked(int visibility) {
         mInputManager.setSystemUiVisibility(visibility);
-        final int N = mWindows.size();
+        final WindowList windows = getDefaultWindowList();
+        final int N = windows.size();
         for (int i = 0; i < N; i++) {
-            WindowState ws = mWindows.get(i);
+            WindowState ws = windows.get(i);
             try {
                 int curValue = ws.mSystemUiVisibility;
                 int diff = curValue ^ visibility;
@@ -9633,6 +9733,8 @@
     // It is assumed that this method is called only by InputMethodManagerService.
     public void saveLastInputMethodWindowForTransition() {
         synchronized (mWindowMap) {
+            // TODO(multidisplay): Pass in the displayID.
+            DisplayContent displayContent = getDefaultDisplayContent();
             if (mInputMethodWindow != null) {
                 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
             }
@@ -9783,10 +9885,12 @@
 
     void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
-        for (int i=mWindows.size()-1; i>=0; i--) {
-            WindowState w = mWindows.get(i);
+        int j = 0;
+        final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+        while (iterator.hasNext()) {
+            final WindowState w = iterator.next();
             if (windows == null || windows.contains(w)) {
-                pw.print("  Window #"); pw.print(i); pw.print(' ');
+                pw.print("  Window #"); pw.print(j++); pw.print(' ');
                         pw.print(w); pw.println(":");
                 w.dump(pw, "    ", dumpAll || windows != null);
             }
@@ -9895,28 +9999,10 @@
         }
         pw.println();
         if (mDisplay != null) {
-            pw.print("  Display: init="); pw.print(mInitialDisplayWidth); pw.print("x");
-                    pw.print(mInitialDisplayHeight);
-                    if (mInitialDisplayWidth != mBaseDisplayWidth
-                            || mInitialDisplayHeight != mBaseDisplayHeight) {
-                        pw.print(" base=");
-                        pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
-                    }
-                    if (mInitialDisplayWidth != mDisplayInfo.logicalWidth
-                            || mInitialDisplayHeight != mDisplayInfo.logicalHeight) {
-                        pw.print(" init="); pw.print(mInitialDisplayWidth);
-                        pw.print("x"); pw.print(mInitialDisplayHeight);
-                    }
-                    pw.print(" cur=");
-                    pw.print(mDisplayInfo.logicalWidth);
-                    pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
-                    pw.print(" app=");
-                    pw.print(mDisplayInfo.appWidth);
-                    pw.print("x"); pw.print(mDisplayInfo.appHeight);
-                    pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
-                    pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
-                    pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
-                    pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
+            DisplayContentsIterator dCIterator = new DisplayContentsIterator();
+            while (dCIterator.hasNext()) {
+                dCIterator.next().dump(pw);
+            }
         } else {
             pw.println("  NO DISPLAY");
         }
@@ -10030,8 +10116,9 @@
         ArrayList<WindowState> windows = new ArrayList<WindowState>();
         if ("visible".equals(name)) {
             synchronized(mWindowMap) {
-                for (int i=mWindows.size()-1; i>=0; i--) {
-                    WindowState w = mWindows.get(i);
+                final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+                while (iterator.hasNext()) {
+                    final WindowState w = iterator.next();
                     if (w.mWinAnimator.mSurfaceShown) {
                         windows.add(w);
                     }
@@ -10046,8 +10133,9 @@
             } catch (RuntimeException e) {
             }
             synchronized(mWindowMap) {
-                for (int i=mWindows.size()-1; i>=0; i--) {
-                    WindowState w = mWindows.get(i);
+                final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+                while (iterator.hasNext()) {
+                    final WindowState w = iterator.next();
                     if (name != null) {
                         if (w.mAttrs.getTitle().toString().contains(name)) {
                             windows.add(w);
@@ -10233,4 +10321,106 @@
                     Integer.toHexString(pendingLayoutChanges));
         }
     }
+
+    public DisplayContent getDisplayContent(final int displayId) {
+        DisplayContent displayContent = mDisplayContents.get(displayId);
+        if (displayContent == null) {
+            displayContent = new DisplayContent(displayId);
+            mDisplayContents.put(displayId, displayContent);
+        }
+        return displayContent;
+    }
+
+    class DisplayContentsIterator implements Iterator<DisplayContent> {
+        private int cur;
+
+        @Override
+        public boolean hasNext() {
+            return cur < mDisplayContents.size();
+        }
+
+        @Override
+        public DisplayContent next() {
+            if (hasNext()) {
+                return mDisplayContents.valueAt(cur++);
+            }
+            throw new NoSuchElementException();
+        }
+
+        @Override
+        public void remove() {
+            throw new IllegalArgumentException("AllDisplayContentIterator.remove not implemented");
+        }
+    }
+
+    boolean REVERSE_ITERATOR = true;
+    class AllWindowsIterator implements Iterator<WindowState> {
+        private DisplayContent mDisplayContent;
+        private DisplayContentsIterator mDisplayContentsIterator;
+        private WindowList mWindowList;
+        private int mWindowListIndex;
+        private boolean mReverse;
+
+        AllWindowsIterator() {
+            mDisplayContentsIterator = new DisplayContentsIterator();
+            mDisplayContent = mDisplayContentsIterator.next();
+            mWindowList = mDisplayContent.getWindowList();
+        }
+
+        AllWindowsIterator(boolean reverse) {
+            this();
+            mReverse = reverse;
+            mWindowListIndex = reverse ? mWindowList.size() - 1 : 0;
+        }
+
+        @Override
+        public boolean hasNext() {
+            if (mReverse) {
+                return mWindowListIndex >= 0;
+            }
+            return mWindowListIndex < mWindowList.size();
+        }
+
+        @Override
+        public WindowState next() {
+            if (hasNext()) {
+                WindowState win = mWindowList.get(mWindowListIndex);
+                if (mReverse) {
+                    mWindowListIndex--;
+                    if (mWindowListIndex < 0 && mDisplayContentsIterator.hasNext()) {
+                        mDisplayContent = mDisplayContentsIterator.next();
+                        mWindowList = mDisplayContent.getWindowList();
+                        mWindowListIndex = mWindowList.size() - 1;
+                    }
+                } else {
+                    mWindowListIndex++;
+                    if (mWindowListIndex >= mWindowList.size() && mDisplayContentsIterator.hasNext()) {
+                        mDisplayContent = mDisplayContentsIterator.next();
+                        mWindowList = mDisplayContent.getWindowList();
+                        mWindowListIndex = 0;
+                    }
+                }
+                return win;
+            }
+            throw new NoSuchElementException();
+        }
+
+        @Override
+        public void remove() {
+            throw new IllegalArgumentException("AllWindowsIterator.remove not implemented");
+        }
+    }
+
+    public DisplayContent getDefaultDisplayContent() {
+        return getDisplayContent(Display.DEFAULT_DISPLAY);
+    }
+
+    public WindowList getDefaultWindowList() {
+        return getDefaultDisplayContent().getWindowList();
+    }
+
+    public DisplayInfo getDefaultDisplayInfo() {
+        return getDefaultDisplayContent().getDisplayInfo();
+    }
+
 }
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index aff519e..43ff3987 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -35,6 +35,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
+import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.IApplicationToken;
 import android.view.IWindow;
@@ -47,6 +48,9 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
+class WindowList extends ArrayList<WindowState> {
+}
+
 /**
  * A window in the window manager.
  */
@@ -251,18 +255,18 @@
 
     boolean mHasSurface = false;
 
-    int mDisplayId;
+    DisplayContent  mDisplayContent;
 
     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
-           int viewVisibility, int displayId) {
+           int viewVisibility, final DisplayContent displayContent) {
         mService = service;
         mSession = s;
         mClient = c;
         mToken = token;
         mAttrs.copyFrom(a);
         mViewVisibility = viewVisibility;
-        mDisplayId = displayId;
+        mDisplayContent = displayContent;
         mPolicy = mService.mPolicy;
         mContext = mService.mContext;
         DeathRecipient deathRecipient = new DeathRecipient();
@@ -346,7 +350,8 @@
         mYOffset = 0;
         mLayer = 0;
         mInputWindowHandle = new InputWindowHandle(
-                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
+                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this,
+                displayContent.getDisplayId());
     }
 
     void attach() {
@@ -482,8 +487,9 @@
         }
 
         if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
-            mService.updateWallpaperOffsetLocked(this,
-                    mService.mDisplayInfo.appWidth, mService.mDisplayInfo.appHeight, false);
+            final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+            mService.updateWallpaperOffsetLocked(this, displayInfo.appWidth, displayInfo.appHeight,
+                    false);
         }
 
         if (WindowManagerService.localLOGV) {
@@ -547,6 +553,7 @@
     public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) {
         int index = -1;
         WindowState ws = this;
+        WindowList windows = getWindowList();
         while (true) {
             if ((ws.mAttrs.privateFlags
                     & WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY) != 0) {
@@ -561,13 +568,13 @@
             // look behind it.
             // First, we may need to determine the starting position.
             if (index < 0) {
-                index = mService.mWindows.indexOf(ws);
+                index = windows.indexOf(ws);
             }
             index--;
             if (index < 0) {
                 return false;
             }
-            ws = mService.mWindows.get(index);
+            ws = windows.get(index);
         }
     }
 
@@ -991,8 +998,13 @@
         }
     }
 
+    WindowList getWindowList() {
+        return mDisplayContent.getWindowList();
+    }
+
     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
-        pw.print(prefix); pw.print("mSession="); pw.print(mSession);
+        pw.print(prefix); pw.print("mDisplayId="); pw.print(mDisplayContent.getDisplayId());
+                pw.print(" mSession="); pw.print(mSession);
                 pw.print(" mClient="); pw.println(mClient.asBinder());
         pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
         pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 2af4eee..f1c69f2 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -16,6 +16,7 @@
 import android.graphics.Region;
 import android.os.Debug;
 import android.util.Slog;
+import android.view.DisplayInfo;
 import android.view.Surface;
 import android.view.SurfaceSession;
 import android.view.WindowManager;
@@ -30,6 +31,9 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
+class WinAnimatorList extends ArrayList<WindowStateAnimator> {
+}
+
 /**
  * Keep track of animations and surface operations for a single WindowState.
  **/
@@ -151,8 +155,9 @@
         mAnimator = service.mAnimator;
         mPolicy = service.mPolicy;
         mContext = service.mContext;
-        mAnimDw = service.mDisplayInfo.appWidth;
-        mAnimDh = service.mDisplayInfo.appHeight;
+        final DisplayInfo displayInfo = win.mDisplayContent.getDisplayInfo();
+        mAnimDw = displayInfo.appWidth;
+        mAnimDh = displayInfo.appHeight;
 
         mWin = win;
         mAttachedWinAnimator = win.mAttachedWindow == null
@@ -248,8 +253,9 @@
                         " scale=" + mService.mWindowAnimationScale);
                     mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
                             mAnimDw, mAnimDh);
-                    mAnimDw = mService.mDisplayInfo.appWidth;
-                    mAnimDh = mService.mDisplayInfo.appHeight;
+                    final DisplayInfo displayInfo = mWin.mDisplayContent.getDisplayInfo();
+                    mAnimDw = displayInfo.appWidth;
+                    mAnimDh = displayInfo.appHeight;
                     mAnimation.setStartTime(currentTime);
                     mLocalAnimating = true;
                     mAnimating = true;
@@ -646,12 +652,12 @@
                     mSurface = new SurfaceTrace(
                             mSession.mSurfaceSession, mSession.mPid,
                             attrs.getTitle().toString(),
-                            mWin.mDisplayId, w, h, format, flags);
+                            mWin.mDisplayContent.getDisplayId(), w, h, format, flags);
                 } else {
                     mSurface = new Surface(
                         mSession.mSurfaceSession, mSession.mPid,
                         attrs.getTitle().toString(),
-                        mWin.mDisplayId, w, h, format, flags);
+                        mWin.mDisplayContent.getDisplayId(), w, h, format, flags);
                 }
                 mWin.mHasSurface = true;
                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
@@ -1101,8 +1107,9 @@
                 mAnimator.mPendingLayoutChanges |=
                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                 if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) {
+                    final DisplayInfo displayInfo = mWin.mDisplayContent.getDisplayInfo();
                     mService.startDimming(this, w.mExiting ? 0 : w.mAttrs.dimAmount,
-                            mService.mDisplayInfo.appWidth, mService.mDisplayInfo.appHeight);
+                            displayInfo.appWidth, displayInfo.appHeight);
                 }
             } catch (RuntimeException e) {
                 // If something goes wrong with the surface (such
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index 2619dd8..67e51fa 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public void clearForcedDisplaySize() throws RemoteException {
+    public void clearForcedDisplaySize(int displayId) throws RemoteException {
         // TODO Auto-generated method stub
 
     }
@@ -262,7 +262,8 @@
     }
 
     @Override
-    public Bitmap screenshotApplications(IBinder arg0, int arg1, int arg2) throws RemoteException {
+    public Bitmap screenshotApplications(IBinder arg0, int displayId, int arg1, int arg2)
+            throws RemoteException {
         // TODO Auto-generated method stub
         return null;
     }
@@ -324,7 +325,7 @@
     }
 
     @Override
-    public void setForcedDisplaySize(int arg0, int arg1) throws RemoteException {
+    public void setForcedDisplaySize(int displayId, int arg0, int arg1) throws RemoteException {
         // TODO Auto-generated method stub
 
     }