Make more items per-Display.

Moving DimSurfaces, DimBackgrounds and Rotation surfaces into
per-display class.

Fixes bug 7167028.

Change-Id: I7408b3a27b5a7a8d0d59e9d6109c002fc627e536
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index c6b7e0d..2445b98 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -4,6 +4,7 @@
 
 import android.graphics.Matrix;
 import android.util.Slog;
+import android.view.Display;
 import android.view.Surface;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
@@ -134,11 +135,13 @@
         thumbnailTransformation.clear();
         thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation);
         thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY);
-        final boolean screenAnimation = mAnimator.mScreenRotationAnimation != null
-                && mAnimator.mScreenRotationAnimation.isAnimating();
+
+        ScreenRotationAnimation screenRotationAnimation =
+                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
+        final boolean screenAnimation = screenRotationAnimation != null
+                && screenRotationAnimation.isAnimating();
         if (screenAnimation) {
-            thumbnailTransformation.postCompose(
-                    mAnimator.mScreenRotationAnimation.getEnterTransformation());
+            thumbnailTransformation.postCompose(screenRotationAnimation.getEnterTransformation());
         }
         // cache often used attributes locally
         final float tmpFloats[] = mService.mTmpFloats;
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
index 87a2880..9bca834 100644
--- a/services/java/com/android/server/wm/DimAnimator.java
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -219,5 +219,13 @@
             mDimHeight = o.mDimHeight;
             mDimTarget = o.mDimTarget;
         }
+
+        public void printTo(String prefix, PrintWriter pw) {
+            pw.print(prefix);
+            pw.print("mDimWinAnimator="); pw.print(mDimWinAnimator.mWin.mAttrs.getTitle());
+                    pw.print(" "); pw.print(mDimWidth); pw.print(" x ");
+                    pw.print(mDimHeight);
+            pw.print(" mDimTarget="); pw.println(mDimTarget);
+        }
     }
 }
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index d1742ff..3898ebc 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -101,31 +101,32 @@
         mDisplay.getDisplayInfo(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); pw.print(" "); pw.print(mInitialDisplayDensity);
-        pw.print("dpi");
-        if (mInitialDisplayWidth != mBaseDisplayWidth
-                || mInitialDisplayHeight != mBaseDisplayHeight
-                || mInitialDisplayDensity != mBaseDisplayDensity) {
-            pw.print(" base=");
-            pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
-            pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
-        }
-        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.print("  layoutNeeded="); pw.println(layoutNeeded);
+    public void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
+        final String subPrefix = "  " + prefix;
+        pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
+            pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
+            pw.print("dpi");
+            if (mInitialDisplayWidth != mBaseDisplayWidth
+                    || mInitialDisplayHeight != mBaseDisplayHeight
+                    || mInitialDisplayDensity != mBaseDisplayDensity) {
+                pw.print(" base=");
+                pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
+                pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
+            }
+            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.print(subPrefix); pw.print("layoutNeeded="); pw.print(layoutNeeded);
         if (mMagnificationSpec != null) {
-            pw.print("  mMagnificationSpec="); pw.println(mMagnificationSpec);
+            pw.print(" mMagnificationSpec="); pw.print(mMagnificationSpec);
         }
         pw.println();
     }
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index cabe611..4494058 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -16,6 +16,7 @@
 import android.os.SystemClock;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.view.Display;
 import android.view.Surface;
@@ -39,8 +40,6 @@
     final Context mContext;
     final WindowManagerPolicy mPolicy;
 
-    ArrayList<WinAnimatorList> mWinAnimatorLists = new ArrayList<WinAnimatorList>();
-
     boolean mAnimating;
 
     final Runnable mAnimationRunnable;
@@ -64,24 +63,19 @@
      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
     private int mAnimTransactionSequence;
 
-    /** The one and only screen rotation if one is happening */
-    ScreenRotationAnimation mScreenRotationAnimation = null;
-
     // Window currently running an animation that has requested it be detached
     // from the wallpaper.  This means we need to ensure the wallpaper is
     // visible behind it in case it animates in a way that would allow it to be
     // seen. If multiple windows satisfy this, use the lowest window.
     WindowState mWindowDetachedWallpaper = null;
 
-    DimSurface mWindowAnimationBackgroundSurface = null;
-
     WindowStateAnimator mUniverseBackground = null;
     int mAboveUniverseLayer = 0;
 
     int mBulkUpdateParams = 0;
 
-    DimAnimator mDimAnimator = null;
-    DimAnimator.Parameters mDimParams = null;
+    SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
+            new SparseArray<WindowAnimator.DisplayContentsAnimator>();
 
     static final int WALLPAPER_ACTION_PENDING = 1;
     int mPendingActions;
@@ -127,11 +121,18 @@
         };
     }
 
-    void initializeLocked(final int layerStack) {
-        mWindowAnimationBackgroundSurface =
-                new DimSurface(mService.mFxSession, layerStack);
-        mDimAnimator = new DimAnimator(mService.mFxSession, layerStack);
-        mInitialized = true;
+    void addDisplayLocked(final int displayId) {
+        DisplayContentsAnimator displayAnimator = getDisplayContentsAnimatorLocked(displayId);
+        displayAnimator.mWindowAnimationBackgroundSurface =
+                new DimSurface(mService.mFxSession, displayId);
+        displayAnimator.mDimAnimator = new DimAnimator(mService.mFxSession, displayId);
+        if (displayId == Display.DEFAULT_DISPLAY) {
+            mInitialized = true;
+        }
+    }
+
+    void removeDisplayLocked(final int displayId) {
+        mDisplayContentsAnimators.delete(displayId);
     }
 
     /** Locked on mAnimToLayout */
@@ -165,8 +166,6 @@
                 mWallpaperTokens = new ArrayList<WindowToken>(layoutToAnim.mWallpaperTokens);
             }
 
-            mWinAnimatorLists =
-                    new ArrayList<WinAnimatorList>(layoutToAnim.mWinAnimatorLists);
             mWallpaperTarget = layoutToAnim.mWallpaperTarget;
             mWpAppAnimator = mWallpaperTarget == null
                     ? null : mWallpaperTarget.mAppToken == null
@@ -175,20 +174,34 @@
             mUpperWallpaperTarget = layoutToAnim.mUpperWallpaperTarget;
 
             // Set the new DimAnimator params.
-            DimAnimator.Parameters dimParams = layoutToAnim.mDimParams;
-            if (dimParams == null) {
-                mDimParams = null;
-            } else {
-                final WindowStateAnimator newWinAnimator = dimParams.mDimWinAnimator;
+            final int numDisplays = mDisplayContentsAnimators.size();
+            for (int i = 0; i < numDisplays; i++) {
+                final int displayId = mDisplayContentsAnimators.keyAt(i);
+                DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
 
-                // Only set dim params on the highest dimmed layer.
-                final WindowStateAnimator existingDimWinAnimator = mDimParams == null
-                        ? null : mDimParams.mDimWinAnimator;
-                // Don't turn on for an unshown surface, or for any layer but the highest dimmed one.
-                if (newWinAnimator.mSurfaceShown &&
-                        (existingDimWinAnimator == null || !existingDimWinAnimator.mSurfaceShown
-                        || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
-                    mDimParams = new DimAnimator.Parameters(dimParams);
+                displayAnimator.mWinAnimators.clear();
+                final WinAnimatorList winAnimators = layoutToAnim.mWinAnimatorLists.get(displayId);
+                if (winAnimators != null) {
+                    displayAnimator.mWinAnimators.addAll(winAnimators);
+                }
+
+                DimAnimator.Parameters dimParams = layoutToAnim.mDimParams.get(displayId);
+                if (dimParams == null) {
+                    displayAnimator.mDimParams = null;
+                } else {
+                    final WindowStateAnimator newWinAnimator = dimParams.mDimWinAnimator;
+
+                    // Only set dim params on the highest dimmed layer.
+                    final WindowStateAnimator existingDimWinAnimator =
+                            displayAnimator.mDimParams == null ?
+                                    null : displayAnimator.mDimParams.mDimWinAnimator;
+                    // Don't turn on for an unshown surface, or for any layer but the highest
+                    // dimmed layer.
+                    if (newWinAnimator.mSurfaceShown && (existingDimWinAnimator == null
+                            || !existingDimWinAnimator.mSurfaceShown
+                            || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
+                        displayAnimator.mDimParams = new DimAnimator.Parameters(dimParams);
+                    }
                 }
             }
 
@@ -225,7 +238,7 @@
         }
     }
 
-    private void updateWindowsAppsAndRotationAnimationsLocked() {
+    private void updateAppWindowsLocked() {
         int i;
         final int NAT = mAppAnimators.size();
         for (i=0; i<NAT; i++) {
@@ -258,21 +271,13 @@
                         "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
             }
         }
-
-        if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) {
-            if (mScreenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
-                mAnimating = true;
-            } else {
-                mBulkUpdateParams |= SET_UPDATE_ROTATION;
-                mScreenRotationAnimation.kill();
-                mScreenRotationAnimation = null;
-            }
-        }
     }
 
-    private void updateWindowsLocked(final WinAnimatorList winAnimatorList) {
+    private void updateWindowsLocked(final int displayId) {
         ++mAnimTransactionSequence;
 
+        final WinAnimatorList winAnimatorList =
+                getDisplayContentsAnimatorLocked(displayId).mWinAnimators;
         ArrayList<WindowStateAnimator> unForceHiding = null;
         boolean wallpaperInUnForceHiding = false;
 
@@ -313,7 +318,6 @@
                                 WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                                 "Animation started that could impact force hide: " + win);
                         mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
-                        final int displayId = win.mDisplayContent.getDisplayId();
                         setPendingLayoutChanges(displayId,
                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -391,7 +395,6 @@
             if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
                 if (atoken == null || atoken.allDrawn) {
                     if (winAnimator.performShowLocked()) {
-                        final int displayId = win.mDisplayContent.getDisplayId();
                         mPendingLayoutChanges.put(displayId,
                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -427,10 +430,15 @@
         }
     }
 
-    private void updateWallpaperLocked(final WinAnimatorList winAnimatorList) {
+    private void updateWallpaperLocked(int displayId) {
+        final DisplayContentsAnimator displayAnimator =
+                getDisplayContentsAnimatorLocked(displayId);
+        final WinAnimatorList winAnimatorList = displayAnimator.mWinAnimators;
         WindowStateAnimator windowAnimationBackground = null;
         int windowAnimationBackgroundColor = 0;
         WindowState detachedWallpaper = null;
+        final DimSurface windowAnimationBackgroundSurface =
+                displayAnimator.mWindowAnimationBackgroundSurface;
 
         for (int i = winAnimatorList.size() - 1; i >= 0; i--) {
             WindowStateAnimator winAnimator = winAnimatorList.get(i);
@@ -510,11 +518,11 @@
                 }
             }
 
-            mWindowAnimationBackgroundSurface.show(mDw, mDh,
+            windowAnimationBackgroundSurface.show(mDw, mDh,
                     animLayer - WindowManagerService.LAYER_OFFSET_DIM,
                     windowAnimationBackgroundColor);
         } else {
-            mWindowAnimationBackgroundSurface.hide();
+            windowAnimationBackgroundSurface.hide();
         }
     }
 
@@ -557,9 +565,9 @@
         }
     }
 
-    private void performAnimationsLocked(final WinAnimatorList winAnimatorList) {
-        updateWindowsLocked(winAnimatorList);
-        updateWallpaperLocked(winAnimatorList);
+    private void performAnimationsLocked(final int displayId) {
+        updateWindowsLocked(displayId);
+        updateWallpaperLocked(displayId);
     }
 
     // TODO(cmautner): Change the following comment when no longer locked on mWindowMap */
@@ -582,15 +590,30 @@
                 TAG, ">>> OPEN TRANSACTION animateLocked");
         Surface.openTransaction();
         try {
-            updateWindowsAppsAndRotationAnimationsLocked();
+            updateAppWindowsLocked();
 
-            for (int i = mWinAnimatorLists.size() - 1; i >= 0; i--) {
-                final WinAnimatorList winAnimatorList = mWinAnimatorLists.get(i);
+            final int numDisplays = mDisplayContentsAnimators.size();
+            for (int i = 0; i < numDisplays; i++) {
+                final int displayId = mDisplayContentsAnimators.keyAt(i);
+                DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
+
+                final ScreenRotationAnimation screenRotationAnimation =
+                        displayAnimator.mScreenRotationAnimation;
+                if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
+                    if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
+                        mAnimating = true;
+                    } else {
+                        mBulkUpdateParams |= SET_UPDATE_ROTATION;
+                        screenRotationAnimation.kill();
+                        displayAnimator.mScreenRotationAnimation = null;
+                    }
+                }
 
                 // Update animations of all applications, including those
                 // associated with exiting/removed apps
-                performAnimationsLocked(winAnimatorList);
+                performAnimationsLocked(displayId);
 
+                final WinAnimatorList winAnimatorList = displayAnimator.mWinAnimators;
                 final int N = winAnimatorList.size();
                 for (int j = 0; j < N; j++) {
                     winAnimatorList.get(j).prepareSurfaceLocked(true);
@@ -599,16 +622,26 @@
 
             testTokenMayBeDrawnLocked();
 
-            if (mScreenRotationAnimation != null) {
-                mScreenRotationAnimation.updateSurfacesInTransaction();
-            }
+            for (int i = 0; i < numDisplays; i++) {
+                final int displayId = mDisplayContentsAnimators.keyAt(i);
+                DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
 
-            if (mDimParams != null) {
-                mDimAnimator.updateParameters(mContext.getResources(), mDimParams, mCurrentTime);
-            }
-            if (mDimAnimator != null && mDimAnimator.mDimShown) {
-                mAnimating |= mDimAnimator.updateSurface(isDimming(), mCurrentTime,
-                        !mService.okToDisplay());
+                final ScreenRotationAnimation screenRotationAnimation =
+                        displayAnimator.mScreenRotationAnimation;
+                if (screenRotationAnimation != null) {
+                    screenRotationAnimation.updateSurfacesInTransaction();
+                }
+
+                final DimAnimator.Parameters dimParams = displayAnimator.mDimParams;
+                final DimAnimator dimAnimator = displayAnimator.mDimAnimator;
+                if (dimParams != null) {
+                    dimAnimator.updateParameters(
+                            mContext.getResources(), dimParams, mCurrentTime);
+                }
+                if (dimAnimator != null && dimAnimator.mDimShown) {
+                    mAnimating |= dimAnimator.updateSurface(isDimmingLocked(displayId),
+                            mCurrentTime, !mService.okToDisplay());
+                }
             }
 
             if (mService.mWatermark != null) {
@@ -661,15 +694,17 @@
         mInnerDh = appHeight;
     }
 
-    boolean isDimming() {
-        return mDimParams != null;
+    boolean isDimmingLocked(int displayId) {
+        return getDisplayContentsAnimatorLocked(displayId).mDimParams != null;
     }
 
-    boolean isDimming(final WindowStateAnimator winAnimator) {
-        return mDimParams != null && mDimParams.mDimWinAnimator == winAnimator;
+    boolean isDimmingLocked(final WindowStateAnimator winAnimator) {
+        DimAnimator.Parameters dimParams =
+                getDisplayContentsAnimatorLocked(winAnimator.mWin.getDisplayId()).mDimParams;
+        return dimParams != null && dimParams.mDimWinAnimator == winAnimator;
     }
 
-    public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+    public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
         if (dumpAll) {
             if (mWindowDetachedWallpaper != null) {
                 pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
@@ -677,16 +712,36 @@
             }
             pw.print(prefix); pw.print("mAnimTransactionSequence=");
                     pw.println(mAnimTransactionSequence);
-            if (mWindowAnimationBackgroundSurface != null) {
-                pw.print(prefix); pw.print("mWindowAnimationBackgroundSurface:");
-                        mWindowAnimationBackgroundSurface.printTo(prefix + "  ", pw);
+            for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
+                pw.print(prefix); pw.print("DisplayContentsAnimator #");
+                    pw.println(mDisplayContentsAnimators.keyAt(i));
+                DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
+                final String subPrefix = "  " + prefix;
+                final String subSubPrefix = "  " + subPrefix;
+                if (displayAnimator.mWindowAnimationBackgroundSurface != null) {
+                    pw.println(subPrefix + "mWindowAnimationBackgroundSurface:");
+                    displayAnimator.mWindowAnimationBackgroundSurface.printTo(subSubPrefix, pw);
+                }
+                if (displayAnimator.mDimAnimator != null) {
+                    pw.println(subPrefix + "mDimAnimator:");
+                    displayAnimator.mDimAnimator.printTo(subSubPrefix, pw);
+                } else {
+                    pw.println(subPrefix + "no DimAnimator ");
+                }
+                if (displayAnimator.mDimParams != null) {
+                    pw.println(subPrefix + "mDimParams:");
+                    displayAnimator.mDimParams.printTo(subSubPrefix, pw);
+                } else {
+                    pw.println(subPrefix + "no DimParams ");
+                }
+                if (displayAnimator.mScreenRotationAnimation != null) {
+                    pw.println(subPrefix + "mScreenRotationAnimation:");
+                    displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
+                } else {
+                    pw.print(subPrefix + "no ScreenRotationAnimation ");
+                }
             }
-            if (mDimAnimator != null) {
-                pw.print(prefix); pw.print("mDimAnimator:");
-                mDimAnimator.printTo(prefix + "  ", pw);
-            } else {
-                pw.print(prefix); pw.print("no DimAnimator ");
-            }
+            pw.println();
         }
     }
 
@@ -716,4 +771,29 @@
             }
         }
     }
+
+    private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
+        DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
+        if (displayAnimator == null) {
+            displayAnimator = new DisplayContentsAnimator();
+            mDisplayContentsAnimators.put(displayId, displayAnimator);
+        }
+        return displayAnimator;
+    }
+
+    void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
+        getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
+    }
+
+    ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
+        return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
+    }
+
+    private static class DisplayContentsAnimator {
+        WinAnimatorList mWinAnimators = new WinAnimatorList();
+        DimAnimator mDimAnimator = null;
+        DimAnimator.Parameters mDimParams = null;
+        DimSurface mWindowAnimationBackgroundSurface = null;
+        ScreenRotationAnimation mScreenRotationAnimation = null;
+    }
 }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 556613e..55a7c46 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -623,11 +623,11 @@
         long mChanges;
 
         boolean mAnimationScheduled;
-        ArrayList<WinAnimatorList> mWinAnimatorLists = new ArrayList<WinAnimatorList>();
+        SparseArray<WinAnimatorList> mWinAnimatorLists = new SparseArray<WinAnimatorList>();
         WindowState mWallpaperTarget;
         WindowState mLowerWallpaperTarget;
         WindowState mUpperWallpaperTarget;
-        DimAnimator.Parameters mDimParams;
+        SparseArray<DimAnimator.Parameters> mDimParams = new SparseArray<DimAnimator.Parameters>();
         ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
         ArrayList<AppWindowAnimParams> mAppWindowAnimParams = new ArrayList<AppWindowAnimParams>();
     }
@@ -4121,6 +4121,7 @@
         }
     }
 
+    @Override
     public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
             int startHeight) {
         synchronized(mWindowMap) {
@@ -4138,6 +4139,7 @@
         }
     }
 
+    @Override
     public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
             int startY, IRemoteCallback startedCallback, boolean scaleUp) {
         synchronized(mWindowMap) {
@@ -4157,6 +4159,7 @@
         }
     }
 
+    @Override
     public void executeAppTransition() {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "executeAppTransition()")) {
@@ -5943,8 +5946,9 @@
             return false;
         }
 
-        if (mAnimator.mScreenRotationAnimation != null &&
-                mAnimator.mScreenRotationAnimation.isAnimating()) {
+        ScreenRotationAnimation screenRotationAnimation =
+                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
+        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
             // Rotation updates cannot be performed while the previous rotation change
             // animation is still in progress.  Skip this update.  We will try updating
             // again after the animation is finished and the display is unfrozen.
@@ -5996,6 +6000,9 @@
         mWaitingForConfig = true;
         getDefaultDisplayContentLocked().layoutNeeded = true;
         startFreezingDisplayLocked(inTransaction, 0, 0);
+        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
+        screenRotationAnimation =
+                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
 
         // We need to update our screen size information to match the new
         // rotation.  Note that this is redundant with the later call to
@@ -6016,9 +6023,9 @@
         try {
             // NOTE: We disable the rotation in the emulator because
             //       it doesn't support hardware OpenGL emulation yet.
-            if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null
-                    && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
-                if (mAnimator.mScreenRotationAnimation.setRotationInTransaction(
+            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
+                    && screenRotationAnimation.hasScreenshot()) {
+                if (screenRotationAnimation.setRotationInTransaction(
                         rotation, mFxSession,
                         MAX_ANIMATION_DURATION, mTransitionAnimationScale,
                         displayInfo.logicalWidth, displayInfo.logicalHeight)) {
@@ -7158,8 +7165,6 @@
             mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_TOUCHSCREEN);
 
-            mAnimator.initializeLocked(display.getLayerStack());
-
             final DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
             mAnimator.setDisplayDimensions(
                     displayInfo.logicalWidth, displayInfo.logicalHeight,
@@ -7181,6 +7186,7 @@
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
             final DisplayInfo displayInfo;
+            mAnimator.addDisplayLocked(displayId);
             synchronized(displayContent.mDisplaySizeLock) {
                 // Bootstrap the default logical display from the display manager.
                 displayInfo = displayContent.getDisplayInfo();
@@ -8136,7 +8142,7 @@
             if (winAnimator.mAnimLayer != oldLayer) {
                 layerChanged = true;
             }
-            if (layerChanged && mAnimator.isDimming(winAnimator)) {
+            if (layerChanged && mAnimator.isDimmingLocked(winAnimator)) {
                 // Force an animation pass just to update the mDimAnimator layer.
                 updateLayoutToAnimationLocked();
             }
@@ -8842,7 +8848,7 @@
                 //Slog.i(TAG, "DIM BEHIND: " + w);
                 mInnerFields.mDimming = true;
                 final WindowStateAnimator winAnimator = w.mWinAnimator;
-                if (!mAnimator.isDimming(winAnimator)) {
+                if (!mAnimator.isDimmingLocked(winAnimator)) {
                     final int width, height;
                     if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) {
                         final DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo();
@@ -8852,7 +8858,8 @@
                         width = innerDw;
                         height = innerDh;
                     }
-                    startDimming(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height);
+                    startDimmingLocked(
+                        winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height);
                 }
             }
         }
@@ -9080,7 +9087,7 @@
                             }
                         }
 
-                        winAnimator.setSurfaceBoundaries(recoveringMemory);
+                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
 
                         final AppWindowToken atoken = w.mAppToken;
                         if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) {
@@ -9138,6 +9145,10 @@
 
                     updateResizingWindows(w);
                 }
+
+                if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) {
+                    stopDimmingLocked(displayId);
+                }
             }
 
             if (updateAllDrawn) {
@@ -9147,10 +9158,6 @@
             if (focusDisplayed) {
                 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
             }
-
-            if (!mInnerFields.mDimming && mAnimator.isDimming()) {
-                stopDimming();
-            }
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
@@ -9515,7 +9522,7 @@
         final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim;
         synchronized (layoutToAnim) {
             // Copy local params to transfer params.
-            ArrayList<WinAnimatorList> allWinAnimatorLists = layoutToAnim.mWinAnimatorLists;
+            SparseArray<WinAnimatorList> allWinAnimatorLists = layoutToAnim.mWinAnimatorLists;
             allWinAnimatorLists.clear();
             DisplayContentsIterator iterator = new DisplayContentsIterator();
             while (iterator.hasNext()) {
@@ -9529,7 +9536,7 @@
                         winAnimatorList.add(winAnimator);
                     }
                 }
-                allWinAnimatorLists.add(winAnimatorList);
+                allWinAnimatorLists.put(displayContent.getDisplayId(), winAnimatorList);
             }
 
             layoutToAnim.mWallpaperTarget = mWallpaperTarget;
@@ -9555,20 +9562,21 @@
         }
     }
 
-    void setAnimDimParams(DimAnimator.Parameters params) {
+    void setAnimDimParams(int displayId, DimAnimator.Parameters params) {
         synchronized (mLayoutToAnim) {
-            mLayoutToAnim.mDimParams = params;
+            mLayoutToAnim.mDimParams.put(displayId, params);
             scheduleAnimationLocked();
         }
     }
 
-    void startDimming(final WindowStateAnimator winAnimator, final float target,
+    void startDimmingLocked(final WindowStateAnimator winAnimator, final float target,
                       final int width, final int height) {
-        setAnimDimParams(new DimAnimator.Parameters(winAnimator, width, height, target));
+        setAnimDimParams(winAnimator.mWin.getDisplayId(),
+                new DimAnimator.Parameters(winAnimator, width, height, target));
     }
 
-    void stopDimming() {
-        setAnimDimParams(null);
+    void stopDimmingLocked(int displayId) {
+        setAnimDimParams(displayId, null);
     }
 
     private boolean needsLayout() {
@@ -9900,19 +9908,22 @@
         }
 
         if (CUSTOM_SCREEN_ROTATION) {
-            if (mAnimator.mScreenRotationAnimation != null) {
-                mAnimator.mScreenRotationAnimation.kill();
-                mAnimator.mScreenRotationAnimation = null;
+            final DisplayContent displayContent = getDefaultDisplayContentLocked();
+            final int displayId = displayContent.getDisplayId();
+            ScreenRotationAnimation screenRotationAnimation =
+                    mAnimator.getScreenRotationAnimationLocked(displayId);
+            if (screenRotationAnimation != null) {
+                screenRotationAnimation.kill();
             }
 
             // TODO(multidisplay): rotation on main screen only.
-            final DisplayContent displayContent = getDefaultDisplayContentLocked();
             final Display display = displayContent.getDisplay();
             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-            mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
+            screenRotationAnimation = new ScreenRotationAnimation(mContext,
                     display, mFxSession, inTransaction, displayInfo.logicalWidth,
                     displayInfo.logicalHeight, display.getRotation(),
                     exitAnim, enterAnim);
+            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
         }
     }
 
@@ -9940,24 +9951,30 @@
 
         boolean updateRotation = false;
 
-        if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null
-                && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
+        final DisplayContent displayContent = getDefaultDisplayContentLocked();
+        final int displayId = displayContent.getDisplayId();
+        ScreenRotationAnimation screenRotationAnimation =
+                mAnimator.getScreenRotationAnimationLocked(displayId);
+        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
+                && screenRotationAnimation.hasScreenshot()) {
             if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
             // TODO(multidisplay): rotation on main screen only.
-            DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
-            if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
+            DisplayInfo displayInfo = displayContent.getDisplayInfo();
+            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
                     mTransitionAnimationScale, displayInfo.logicalWidth,
                         displayInfo.logicalHeight)) {
                 updateLayoutToAnimationLocked();
             } else {
-                mAnimator.mScreenRotationAnimation.kill();
-                mAnimator.mScreenRotationAnimation = null;
+                screenRotationAnimation.kill();
+                screenRotationAnimation = null;
+                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
                 updateRotation = true;
             }
         } else {
-            if (mAnimator.mScreenRotationAnimation != null) {
-                mAnimator.mScreenRotationAnimation.kill();
-                mAnimator.mScreenRotationAnimation = null;
+            if (screenRotationAnimation != null) {
+                screenRotationAnimation.kill();
+                screenRotationAnimation = null;
+                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
             }
             updateRotation = true;
         }
@@ -10394,11 +10411,11 @@
                         pw.print(": "); pw.println(pair.second);
             }
         }
-        pw.println();
+        pw.println("  DisplayContents");
         if (mDisplayReady) {
             DisplayContentsIterator dCIterator = new DisplayContentsIterator();
             while (dCIterator.hasNext()) {
-                dCIterator.next().dump(pw);
+                dCIterator.next().dump("    ", pw);
             }
         } else {
             pw.println("  NO DISPLAY");
@@ -10463,10 +10480,6 @@
             pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
                     pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
             pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
-            if (mAnimator.mScreenRotationAnimation != null) {
-                pw.println("  mScreenRotationAnimation:");
-                mAnimator.mScreenRotationAnimation.printTo("    ", pw);
-            }
             pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
                     pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
                     pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
@@ -10515,7 +10528,7 @@
             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
                     pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
             pw.println("  Window Animator:");
-            mAnimator.dump(pw, "    ", dumpAll);
+            mAnimator.dumpLocked(pw, "    ", dumpAll);
         }
     }
 
@@ -10850,6 +10863,7 @@
 
     private void handleDisplayAddedLocked(int displayId) {
         createDisplayContentLocked(mDisplayManager.getDisplay(displayId));
+        displayReady(displayId);
     }
 
     @Override
@@ -10865,6 +10879,7 @@
             final WindowState win = windows.get(i);
             removeWindowLocked(win.mSession, win);
         }
+        mAnimator.removeDisplayLocked(displayId);
     }
 
     @Override
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 8912c73..000a191 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -31,6 +31,13 @@
 import java.util.ArrayList;
 
 class WinAnimatorList extends ArrayList<WindowStateAnimator> {
+    public WinAnimatorList() {
+        super();
+    }
+
+    public WinAnimatorList(WinAnimatorList other) {
+        super(other);
+    }
 }
 
 /**
@@ -840,8 +847,11 @@
             }
         }
 
-        final boolean screenAnimation = mService.mAnimator.mScreenRotationAnimation != null
-                && mService.mAnimator.mScreenRotationAnimation.isAnimating();
+        final int displayId = mWin.getDisplayId();
+        final ScreenRotationAnimation screenRotationAnimation =
+                mAnimator.getScreenRotationAnimationLocked(displayId);
+        final boolean screenAnimation =
+                screenRotationAnimation != null && screenRotationAnimation.isAnimating();
         if (selfTransformation || attachedTransformation != null
                 || appTransformation != null || screenAnimation) {
             // cache often used attributes locally
@@ -883,8 +893,7 @@
                 tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
             }
             if (screenAnimation) {
-                tmpMatrix.postConcat(
-                        mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getMatrix());
+                tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
             }
             MagnificationSpec spec = mWin.getWindowMagnificationSpecLocked();
             if (spec != null && !spec.isNop()) {
@@ -934,21 +943,21 @@
                     mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
                 }
                 if (screenAnimation) {
-                    mShownAlpha *=
-                        mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha();
+                    mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
                 }
             } else {
                 //Slog.i(TAG, "Not applying alpha transform");
             }
 
-            if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV) && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
-                TAG, "computeShownFrameLocked: Animating " + this +
-                " mAlpha=" + mAlpha +
-                " self=" + (selfTransformation ? mTransformation.getAlpha() : "null") +
-                " attached=" + (attachedTransformation == null ? "null" : attachedTransformation.getAlpha()) +
-                " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha()) +
-                " screen=" + (screenAnimation ? mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha()
-                        : "null"));
+            if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV)
+                    && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
+                    TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha
+                    + " self=" + (selfTransformation ? mTransformation.getAlpha() : "null")
+                    + " attached=" + (attachedTransformation == null ?
+                            "null" : attachedTransformation.getAlpha())
+                    + " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha())
+                    + " screen=" + (screenAnimation ?
+                            screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
             return;
         } else if (mIsWallpaper &&
                     (mAnimator.mPendingActions & WindowAnimator.WALLPAPER_ACTION_PENDING) != 0) {
@@ -1083,7 +1092,7 @@
         }
     }
 
-    void setSurfaceBoundaries(final boolean recoveringMemory) {
+    void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
         final WindowState w = mWin;
         int width, height;
         if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
@@ -1138,7 +1147,7 @@
                         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.startDimmingLocked(this, w.mExiting ? 0 : w.mAttrs.dimAmount,
                             displayInfo.appWidth, displayInfo.appHeight);
                 }
             } catch (RuntimeException e) {
@@ -1172,7 +1181,7 @@
 
         computeShownFrameLocked();
 
-        setSurfaceBoundaries(recoveringMemory);
+        setSurfaceBoundariesLocked(recoveringMemory);
 
         if (mIsWallpaper && !mWin.mWallpaperVisible) {
             // Wallpaper is no longer visible and there is no wp target => hide it.