OSDN Git Service

Lockscreen: Introduce window type TYPE_KEYGUARD_PANEL
[android-x86/frameworks-base.git] / services / core / java / com / android / server / wm / WindowAnimator.java
index e833511..e044f1b 100644 (file)
@@ -18,32 +18,45 @@ package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
-
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static com.android.server.wm.WindowManagerService.DEBUG_KEYGUARD;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
-import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
+import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
+import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
+import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
 
 import android.content.Context;
-import android.os.Debug;
-import android.os.SystemClock;
+import android.os.Trace;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.SparseIntArray;
 import android.util.TimeUtils;
+import android.view.Choreographer;
 import android.view.Display;
 import android.view.SurfaceControl;
+import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
 
-import com.android.server.wm.WindowManagerService.LayoutFields;
-
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
@@ -52,7 +65,7 @@ import java.util.ArrayList;
  * on behalf of WindowManagerService.
  */
 public class WindowAnimator {
-    private static final String TAG = "WindowAnimator";
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowAnimator" : TAG_WM;
 
     /** How long to give statusbar to clear the private keyguard flag when animating out */
     private static final long KEYGUARD_ANIM_TIMEOUT_MS = 1000;
@@ -60,10 +73,15 @@ public class WindowAnimator {
     final WindowManagerService mService;
     final Context mContext;
     final WindowManagerPolicy mPolicy;
+    private final WindowSurfacePlacer mWindowPlacerLocked;
 
-    boolean mAnimating;
+    /** Is any window animating? */
+    private boolean mAnimating;
 
-    final Runnable mAnimationRunnable;
+    /** Is any app window animating? */
+    boolean mAppWindowAnimating;
+
+    final Choreographer.FrameCallback mAnimationFrameCallback;
 
     /** Time of current animation step. Reset on each iteration */
     long mCurrentTime;
@@ -78,35 +96,32 @@ public class WindowAnimator {
      * seen. If multiple windows satisfy this, use the lowest window. */
     WindowState mWindowDetachedWallpaper = null;
 
-    WindowStateAnimator mUniverseBackground = null;
-    int mAboveUniverseLayer = 0;
-
     int mBulkUpdateParams = 0;
     Object mLastWindowFreezeSource;
 
-    SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
-            new SparseArray<DisplayContentsAnimator>(2);
+    SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
 
     boolean mInitialized = false;
 
     boolean mKeyguardGoingAway;
-    boolean mKeyguardGoingAwayToNotificationShade;
-    boolean mKeyguardGoingAwayDisableWindowAnimations;
+    int mKeyguardGoingAwayFlags;
 
     /** Use one animation for all entering activities after keyguard is dismissed. */
     Animation mPostKeyguardExitAnimation;
 
     // forceHiding states.
     static final int KEYGUARD_NOT_SHOWN     = 0;
-    static final int KEYGUARD_ANIMATING_IN  = 1;
-    static final int KEYGUARD_SHOWN         = 2;
-    static final int KEYGUARD_ANIMATING_OUT = 3;
+    static final int KEYGUARD_SHOWN         = 1;
+    static final int KEYGUARD_ANIMATING_OUT = 2;
     int mForceHiding = KEYGUARD_NOT_SHOWN;
 
+    // When set to true the animator will go over all windows after an animation frame is posted and
+    // check if some got replaced and can be removed.
+    private boolean mRemoveReplacedWindows = false;
+
     private String forceHidingToString() {
         switch (mForceHiding) {
             case KEYGUARD_NOT_SHOWN:    return "KEYGUARD_NOT_SHOWN";
-            case KEYGUARD_ANIMATING_IN: return "KEYGUARD_ANIMATING_IN";
             case KEYGUARD_SHOWN:        return "KEYGUARD_SHOWN";
             case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
             default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
@@ -117,13 +132,13 @@ public class WindowAnimator {
         mService = service;
         mContext = service.mContext;
         mPolicy = service.mPolicy;
+        mWindowPlacerLocked = service.mWindowPlacerLocked;
 
-        mAnimationRunnable = new Runnable() {
-            @Override
-            public void run() {
+        mAnimationFrameCallback = new Choreographer.FrameCallback() {
+            public void doFrame(long frameTimeNs) {
                 synchronized (mService.mWindowMap) {
                     mService.mAnimationScheduled = false;
-                    animateLocked();
+                    animateLocked(frameTimeNs);
                 }
             }
         };
@@ -149,35 +164,6 @@ public class WindowAnimator {
         mDisplayContentsAnimators.delete(displayId);
     }
 
-    void hideWallpapersLocked(final WindowState w) {
-        final WindowState wallpaperTarget = mService.mWallpaperTarget;
-        final WindowState lowerWallpaperTarget = mService.mLowerWallpaperTarget;
-        final ArrayList<WindowToken> wallpaperTokens = mService.mWallpaperTokens;
-
-        if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) {
-            final int numTokens = wallpaperTokens.size();
-            for (int i = numTokens - 1; i >= 0; i--) {
-                final WindowToken token = wallpaperTokens.get(i);
-                final int numWindows = token.windows.size();
-                for (int j = numWindows - 1; j >= 0; j--) {
-                    final WindowState wallpaper = token.windows.get(j);
-                    final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
-                    if (!winAnimator.mLastHidden) {
-                        winAnimator.hide();
-                        mService.dispatchWallpaperVisibility(wallpaper, false);
-                        setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
-                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
-                    }
-                }
-                if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG,
-                        "Hiding wallpaper " + token + " from " + w
-                        + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget
-                        + "\n" + Debug.getCallers(5, "  "));
-                token.hidden = true;
-            }
-        }
-    }
-
     private void updateAppWindowsLocked(int displayId) {
         ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks();
         for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
@@ -187,35 +173,38 @@ public class WindowAnimator {
                 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
                     final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
-                    final boolean wasAnimating = appAnimator.animation != null
-                            && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
-                    if (appAnimator.stepAnimationLocked(mCurrentTime)) {
-                        mAnimating = true;
-                    } else if (wasAnimating) {
+                    appAnimator.wasAnimating = appAnimator.animating;
+                    if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
+                        appAnimator.animating = true;
+                        setAnimating(true);
+                        mAppWindowAnimating = true;
+                    } else if (appAnimator.wasAnimating) {
                         // stopped animating, do one more pass through the layout
                         setAppLayoutChanges(appAnimator,
                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                                "appToken " + appAnimator.mAppToken + " done");
-                        if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
+                                "appToken " + appAnimator.mAppToken + " done", displayId);
+                        if (DEBUG_ANIM) Slog.v(TAG,
                                 "updateWindowsApps...: done animating " + appAnimator.mAppToken);
                     }
                 }
             }
 
             final AppTokenList exitingAppTokens = stack.mExitingAppTokens;
-            final int NEAT = exitingAppTokens.size();
-            for (int i = 0; i < NEAT; i++) {
+            final int exitingCount = exitingAppTokens.size();
+            for (int i = 0; i < exitingCount; i++) {
                 final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
-                final boolean wasAnimating = appAnimator.animation != null
-                        && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
-                if (appAnimator.stepAnimationLocked(mCurrentTime)) {
-                    mAnimating = true;
-                } else if (wasAnimating) {
+                appAnimator.wasAnimating = appAnimator.animating;
+                if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
+                    setAnimating(true);
+                    mAppWindowAnimating = true;
+                } else if (appAnimator.wasAnimating) {
                     // stopped animating, do one more pass through the layout
-                    setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                        "exiting appToken " + appAnimator.mAppToken + " done");
-                    if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
-                            "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
+                    setAppLayoutChanges(appAnimator,
+                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
+                            "exiting appToken " + appAnimator.mAppToken + " done", displayId);
+                    if (DEBUG_ANIM) Slog.v(TAG,
+                            "updateWindowsApps...: done animating exiting "
+                                    + appAnimator.mAppToken);
                 }
             }
         }
@@ -224,19 +213,36 @@ public class WindowAnimator {
     private boolean shouldForceHide(WindowState win) {
         final WindowState imeTarget = mService.mInputMethodTarget;
         final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
-                (imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
+                ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
+                        || !mPolicy.canBeForceHidden(imeTarget, imeTarget.mAttrs));
 
         final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
         final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
                 null : winShowWhenLocked.mAppToken;
-        final boolean hideWhenLocked =
-                !(((win.mIsImWindow || imeTarget == win) && showImeOverKeyguard)
-                        || (appShowWhenLocked != null && (appShowWhenLocked == win.mAppToken ||
-                        // Show error dialogs over apps that dismiss keyguard.
-                        (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0)));
-        return ((mForceHiding == KEYGUARD_ANIMATING_IN)
-                && (!win.mWinAnimator.isAnimating() || hideWhenLocked))
-                || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked);
+
+        boolean allowWhenLocked = false;
+        // Show IME over the keyguard if the target allows it
+        allowWhenLocked |= (win.mIsImWindow || imeTarget == win) && showImeOverKeyguard;
+        // Show SHOW_WHEN_LOCKED windows that turn on the screen
+        allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen;
+        // Show windows that use TYPE_STATUS_BAR_SUB_PANEL when locked
+        allowWhenLocked |= win.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD_PANEL;
+
+        if (appShowWhenLocked != null) {
+            allowWhenLocked |= appShowWhenLocked == win.mAppToken
+                    // Show all SHOW_WHEN_LOCKED windows if some apps are shown over lockscreen
+                    || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
+                    // Show error dialogs over apps that dismiss keyguard.
+                    || (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
+        }
+
+        // Only hide windows if the keyguard is active and not animating away.
+        boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded()
+                && mForceHiding != KEYGUARD_ANIMATING_OUT;
+        boolean hideDockDivider = win.mAttrs.type == TYPE_DOCK_DIVIDER
+                && win.getDisplayContent().getDockedStackLocked() == null;
+        return keyguardOn && !allowWhenLocked && (win.getDisplayId() == Display.DEFAULT_DISPLAY)
+                || hideDockDivider;
     }
 
     private void updateWindowsLocked(final int displayId) {
@@ -244,6 +250,13 @@ public class WindowAnimator {
 
         final WindowList windows = mService.getWindowListLocked(displayId);
 
+        final boolean keyguardGoingAwayToShade =
+                (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0;
+        final boolean keyguardGoingAwayNoAnimation =
+                (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0;
+        final boolean keyguardGoingAwayWithWallpaper =
+                (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0;
+
         if (mKeyguardGoingAway) {
             for (int i = windows.size() - 1; i >= 0; i--) {
                 WindowState win = windows.get(i);
@@ -261,6 +274,9 @@ public class WindowAnimator {
                         winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
                         winAnimator.mAnimationIsEntrance = false;
                         winAnimator.mAnimationStartTime = -1;
+                        winAnimator.mKeyguardGoingAwayAnimation = true;
+                        winAnimator.mKeyguardGoingAwayWithWallpaper
+                                = keyguardGoingAwayWithWallpaper;
                     }
                 } else {
                     if (DEBUG_KEYGUARD) Slog.d(TAG,
@@ -278,42 +294,47 @@ public class WindowAnimator {
         boolean startingInUnForceHiding = false;
         ArrayList<WindowStateAnimator> unForceHiding = null;
         WindowState wallpaper = null;
+        final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
         for (int i = windows.size() - 1; i >= 0; i--) {
             WindowState win = windows.get(i);
             WindowStateAnimator winAnimator = win.mWinAnimator;
             final int flags = win.mAttrs.flags;
             boolean canBeForceHidden = mPolicy.canBeForceHidden(win, win.mAttrs);
             boolean shouldBeForceHidden = shouldForceHide(win);
-            if (winAnimator.mSurfaceControl != null) {
+            if (winAnimator.hasSurface()) {
                 final boolean wasAnimating = winAnimator.mWasAnimating;
                 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
-                mAnimating |= nowAnimating;
+                winAnimator.mWasAnimating = nowAnimating;
+                orAnimating(nowAnimating);
 
-                if (WindowManagerService.DEBUG_WALLPAPER) {
+                if (DEBUG_WALLPAPER) {
                     Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
                             ", nowAnimating=" + nowAnimating);
                 }
 
-                if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
+                if (wasAnimating && !winAnimator.mAnimating
+                        && wallpaperController.isWallpaperTarget(win)) {
                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                     setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
-                    if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                        mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
+                    if (DEBUG_LAYOUT_REPEATS) {
+                        mWindowPlacerLocked.debugLayoutRepeats(
+                                "updateWindowsAndWallpaperLocked 2",
                                 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
                     }
                 }
 
                 if (mPolicy.isForceHiding(win.mAttrs)) {
                     if (!wasAnimating && nowAnimating) {
-                        if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_ANIM ||
-                                WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+                        if (DEBUG_KEYGUARD || DEBUG_ANIM ||
+                                DEBUG_VISIBILITY) Slog.v(TAG,
                                 "Animation started that could impact force hide: " + win);
                         mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
                         setPendingLayoutChanges(displayId,
                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
-                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
+                        if (DEBUG_LAYOUT_REPEATS) {
+                            mWindowPlacerLocked.debugLayoutRepeats(
+                                    "updateWindowsAndWallpaperLocked 3",
                                     getPendingLayoutChanges(displayId));
                         }
                         mService.mFocusMayChange = true;
@@ -324,17 +345,13 @@ public class WindowAnimator {
                         mKeyguardGoingAway = false;
                     }
                     if (win.isReadyForDisplay()) {
-                        if (nowAnimating) {
-                            if (winAnimator.mAnimationIsEntrance) {
-                                mForceHiding = KEYGUARD_ANIMATING_IN;
-                            } else {
-                                mForceHiding = KEYGUARD_ANIMATING_OUT;
-                            }
+                        if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) {
+                            mForceHiding = KEYGUARD_ANIMATING_OUT;
                         } else {
                             mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
                         }
                     }
-                    if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+                    if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
                             "Force hide " + forceHidingToString()
                             + " hasSurface=" + win.mHasSurface
                             + " policyVis=" + win.mPolicyVisibility
@@ -349,14 +366,16 @@ public class WindowAnimator {
                             // Was already hidden
                             continue;
                         }
-                        if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+                        if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
                                 "Now policy hidden: " + win);
                     } else {
                         boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
+                                && !mPostKeyguardExitAnimation.hasEnded()
                                 && !winAnimator.mKeyguardGoingAwayAnimation
                                 && win.hasDrawnLw()
                                 && win.mAttachedWindow == null
-                                && mForceHiding != KEYGUARD_NOT_SHOWN;
+                                && !win.mIsImWindow
+                                && displayId == Display.DEFAULT_DISPLAY;
 
                         // If the window is already showing and we don't need to apply an existing
                         // Keyguard exit animation, skip.
@@ -369,7 +388,7 @@ public class WindowAnimator {
                             win.hideLw(false, false);
                             continue;
                         }
-                        if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+                        if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
                                 "Now policy shown: " + win);
                         if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
                                 && win.mAttachedWindow == null) {
@@ -389,17 +408,21 @@ public class WindowAnimator {
                             if (DEBUG_KEYGUARD) Slog.v(TAG,
                                     "Applying existing Keyguard exit animation to new window: win="
                                             + win);
-                            Animation a = mPolicy.createForceHideEnterAnimation(
-                                    false, mKeyguardGoingAwayToNotificationShade);
-                            winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime());
+
+                            Animation a = mPolicy.createForceHideEnterAnimation(false,
+                                    keyguardGoingAwayToShade);
+                            winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime(),
+                                    STACK_CLIP_BEFORE_ANIM);
                             winAnimator.mKeyguardGoingAwayAnimation = true;
+                            winAnimator.mKeyguardGoingAwayWithWallpaper
+                                    = keyguardGoingAwayWithWallpaper;
                         }
                         final WindowState currentFocus = mService.mCurrentFocus;
                         if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
                             // We are showing on top of the current
                             // focus, so re-evaluate focus to make
                             // sure it is correct.
-                            if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG,
+                            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG,
                                     "updateWindowsLocked: setting mFocusMayChange true");
                             mService.mFocusMayChange = true;
                         }
@@ -408,8 +431,9 @@ public class WindowAnimator {
                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
-                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
+                        if (DEBUG_LAYOUT_REPEATS) {
+                            mWindowPlacerLocked.debugLayoutRepeats(
+                                    "updateWindowsAndWallpaperLocked 4",
                                     getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
                         }
                     }
@@ -427,13 +451,14 @@ public class WindowAnimator {
             }
 
             final AppWindowToken atoken = win.mAppToken;
-            if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
+            if (winAnimator.mDrawState == READY_TO_SHOW) {
                 if (atoken == null || atoken.allDrawn) {
                     if (winAnimator.performShowLocked()) {
                         setPendingLayoutChanges(displayId,
                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
-                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
+                        if (DEBUG_LAYOUT_REPEATS) {
+                            mWindowPlacerLocked.debugLayoutRepeats(
+                                    "updateWindowsAndWallpaperLocked 5",
                                     getPendingLayoutChanges(displayId));
                         }
                     }
@@ -458,18 +483,20 @@ public class WindowAnimator {
         // being force-hidden, apply the appropriate animation to them if animations are not
         // disabled.
         if (unForceHiding != null) {
-            if (!mKeyguardGoingAwayDisableWindowAnimations) {
+            if (!keyguardGoingAwayNoAnimation) {
                 boolean first = true;
                 for (int i=unForceHiding.size()-1; i>=0; i--) {
                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
                     Animation a = mPolicy.createForceHideEnterAnimation(
                             wallpaperInUnForceHiding && !startingInUnForceHiding,
-                            mKeyguardGoingAwayToNotificationShade);
+                            keyguardGoingAwayToShade);
                     if (a != null) {
                         if (DEBUG_KEYGUARD) Slog.v(TAG,
                                 "Starting keyguard exit animation on window " + winAnimator.mWin);
-                        winAnimator.setAnimation(a);
+                        winAnimator.setAnimation(a, STACK_CLIP_BEFORE_ANIM);
                         winAnimator.mKeyguardGoingAwayAnimation = true;
+                        winAnimator.mKeyguardGoingAwayWithWallpaper
+                                = keyguardGoingAwayWithWallpaper;
                         if (first) {
                             mPostKeyguardExitAnimation = a;
                             mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
@@ -484,11 +511,10 @@ public class WindowAnimator {
 
 
             // Wallpaper is going away in un-force-hide motion, animate it as well.
-            if (!wallpaperInUnForceHiding && wallpaper != null
-                    && !mKeyguardGoingAwayDisableWindowAnimations) {
+            if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) {
                 if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
                 Animation a = mPolicy.createForceHideWallpaperExitAnimation(
-                        mKeyguardGoingAwayToNotificationShade);
+                        keyguardGoingAwayToShade);
                 if (a != null) {
                     wallpaper.mWinAnimator.setAnimation(a);
                 }
@@ -502,8 +528,13 @@ public class WindowAnimator {
                         mPostKeyguardExitAnimation.getStartOffset(),
                         mPostKeyguardExitAnimation.getDuration());
                 mKeyguardGoingAway = false;
-            } else if (mCurrentTime - mPostKeyguardExitAnimation.getStartTime()
-                    > mPostKeyguardExitAnimation.getDuration()) {
+            }
+            // mPostKeyguardExitAnimation might either be ended normally, cancelled, or "orphaned",
+            // meaning that the window it was running on was removed. We check for hasEnded() for
+            // ended normally and cancelled case, and check the time for the "orphaned" case.
+            else if (mPostKeyguardExitAnimation.hasEnded()
+                    || mCurrentTime - mPostKeyguardExitAnimation.getStartTime()
+                            > mPostKeyguardExitAnimation.getDuration()) {
                 // Done with the animation, reset.
                 if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations.");
                 mPostKeyguardExitAnimation = null;
@@ -520,7 +551,7 @@ public class WindowAnimator {
         for (int i = windows.size() - 1; i >= 0; i--) {
             final WindowState win = windows.get(i);
             WindowStateAnimator winAnimator = win.mWinAnimator;
-            if (winAnimator.mSurfaceControl == null) {
+            if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
                 continue;
             }
 
@@ -543,7 +574,7 @@ public class WindowAnimator {
                         }
                     }
                 }
-                mAnimating = true;
+                setAnimating(true);
             }
 
             // If this window's app token is running a detached wallpaper
@@ -568,7 +599,7 @@ public class WindowAnimator {
         } // end forall windows
 
         if (mWindowDetachedWallpaper != detachedWallpaper) {
-            if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
+            if (DEBUG_WALLPAPER) Slog.v(TAG,
                     "Detached wallpaper changed from " + mWindowDetachedWallpaper
                     + " to " + detachedWallpaper);
             mWindowDetachedWallpaper = detachedWallpaper;
@@ -598,22 +629,23 @@ public class WindowAnimator {
                         if (appAnimator.freezingScreen) {
                             appAnimator.showAllWindowsLocked();
                             mService.unsetAppFreezingScreenLocked(wtoken, false, true);
-                            if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
+                            if (DEBUG_ORIENTATION) Slog.i(TAG,
                                     "Setting mOrientationChangeComplete=true because wtoken "
                                     + wtoken + " numInteresting=" + wtoken.numInterestingWindows
                                     + " numDrawn=" + wtoken.numDrawnWindows);
-                            // This will set mOrientationChangeComplete and cause a pass through layout.
+                            // This will set mOrientationChangeComplete and cause a pass through
+                            // layout.
                             setAppLayoutChanges(appAnimator,
                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                                    "testTokenMayBeDrawnLocked: freezingScreen");
+                                    "testTokenMayBeDrawnLocked: freezingScreen", displayId);
                         } else {
                             setAppLayoutChanges(appAnimator,
                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
-                                    "testTokenMayBeDrawnLocked");
+                                    "testTokenMayBeDrawnLocked", displayId);
 
                             // We can now show all of the drawn windows!
                             if (!mService.mOpeningApps.contains(wtoken)) {
-                                mAnimating |= appAnimator.showAllWindowsLocked();
+                                orAnimating(appAnimator.showAllWindowsLocked());
                             }
                         }
                     }
@@ -624,20 +656,21 @@ public class WindowAnimator {
 
 
     /** Locked on mService.mWindowMap. */
-    private void animateLocked() {
+    private void animateLocked(long frameTimeNs) {
         if (!mInitialized) {
             return;
         }
 
-        mCurrentTime = SystemClock.uptimeMillis();
+        mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
         mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
         boolean wasAnimating = mAnimating;
-        mAnimating = false;
-        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
+        setAnimating(false);
+        mAppWindowAnimating = false;
+        if (DEBUG_WINDOW_TRACE) {
             Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
         }
 
-        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
+        if (SHOW_TRANSACTIONS) Slog.i(
                 TAG, ">>> OPEN TRANSACTION animateLocked");
         SurfaceControl.openTransaction();
         SurfaceControl.setAnimationTransaction();
@@ -652,7 +685,7 @@ public class WindowAnimator {
                         displayAnimator.mScreenRotationAnimation;
                 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
                     if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
-                        mAnimating = true;
+                        setAnimating(true);
                     } else {
                         mBulkUpdateParams |= SET_UPDATE_ROTATION;
                         screenRotationAnimation.kill();
@@ -692,8 +725,9 @@ public class WindowAnimator {
                     screenRotationAnimation.updateSurfacesInTransaction();
                 }
 
-                mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();
-
+                orAnimating(mService.getDisplayContentLocked(displayId).animateDimLayers());
+                orAnimating(mService.getDisplayContentLocked(displayId).getDockedDividerController()
+                        .animate(mCurrentTime));
                 //TODO (multidisplay): Magnification is supported only for the default display.
                 if (mService.mAccessibilityController != null
                         && displayId == Display.DEFAULT_DISPLAY) {
@@ -701,12 +735,14 @@ public class WindowAnimator {
                 }
             }
 
+            if (mService.mDragState != null) {
+                mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
+            }
+
             if (mAnimating) {
                 mService.scheduleAnimationLocked();
             }
 
-            mService.setFocusedStackLayer();
-
             if (mService.mWatermark != null) {
                 mService.mWatermark.drawIfNeeded();
             }
@@ -714,7 +750,7 @@ public class WindowAnimator {
             Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
             SurfaceControl.closeTransaction();
-            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
+            if (SHOW_TRANSACTIONS) Slog.i(
                     TAG, "<<< CLOSE TRANSACTION animateLocked");
         }
 
@@ -733,39 +769,75 @@ public class WindowAnimator {
 
         boolean doRequest = false;
         if (mBulkUpdateParams != 0) {
-            doRequest = mService.copyAnimToLayoutParamsLocked();
+            doRequest = mWindowPlacerLocked.copyAnimToLayoutParamsLocked();
         }
 
         if (hasPendingLayoutChanges || doRequest) {
-            mService.requestTraversalLocked();
+            mWindowPlacerLocked.requestTraversal();
+        }
+
+        if (mAnimating && !wasAnimating && Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+            Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
         }
 
         if (!mAnimating && wasAnimating) {
-            mService.requestTraversalLocked();
+            mWindowPlacerLocked.requestTraversal();
+            if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+                Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
+            }
+        }
+
+        if (mRemoveReplacedWindows) {
+            removeReplacedWindowsLocked();
         }
-        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
+
+        mService.stopUsingSavedSurfaceLocked();
+        mService.destroyPreservedSurfaceLocked();
+        mService.mWindowPlacerLocked.destroyPendingSurfaces();
+
+        if (DEBUG_WINDOW_TRACE) {
             Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
-                + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
-                + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
-                + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
+                    + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
+                    + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
+                    + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
+        }
+    }
+
+    private void removeReplacedWindowsLocked() {
+        if (SHOW_TRANSACTIONS) Slog.i(
+                TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
+        SurfaceControl.openTransaction();
+        try {
+            for (int i = mService.mDisplayContents.size() - 1; i >= 0; i--) {
+                DisplayContent display = mService.mDisplayContents.valueAt(i);
+                final WindowList windows = mService.getWindowListLocked(display.getDisplayId());
+                for (int j = windows.size() - 1; j >= 0; j--) {
+                    windows.get(j).maybeRemoveReplacedWindow();
+                }
+            }
+        } finally {
+            SurfaceControl.closeTransaction();
+            if (SHOW_TRANSACTIONS) Slog.i(
+                    TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
         }
+        mRemoveReplacedWindows = false;
     }
 
-    static String bulkUpdateParamsToString(int bulkUpdateParams) {
+    private static String bulkUpdateParamsToString(int bulkUpdateParams) {
         StringBuilder builder = new StringBuilder(128);
-        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
+        if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) {
             builder.append(" UPDATE_ROTATION");
         }
-        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
+        if ((bulkUpdateParams & WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE) != 0) {
             builder.append(" WALLPAPER_MAY_CHANGE");
         }
-        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
+        if ((bulkUpdateParams & WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED) != 0) {
             builder.append(" FORCE_HIDING_CHANGED");
         }
-        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
+        if ((bulkUpdateParams & WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
             builder.append(" ORIENTATION_CHANGE_COMPLETE");
         }
-        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
+        if ((bulkUpdateParams & WindowSurfacePlacer.SET_TURN_ON_SCREEN) != 0) {
             builder.append(" TURN_ON_SCREEN");
         }
         return builder.toString();
@@ -794,6 +866,7 @@ public class WindowAnimator {
             } else if (dumpAll) {
                 pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
             }
+            pw.println();
         }
 
         pw.println();
@@ -814,42 +887,37 @@ public class WindowAnimator {
             pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
                 pw.println(mWindowDetachedWallpaper);
         }
-        if (mUniverseBackground != null) {
-            pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
-                    pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
-        }
     }
 
     int getPendingLayoutChanges(final int displayId) {
         if (displayId < 0) {
             return 0;
         }
-        DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
         return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
     }
 
     void setPendingLayoutChanges(final int displayId, final int changes) {
-        if (displayId >= 0) {
-            DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
-            if (displayContent != null) {
-                displayContent.pendingLayoutChanges |= changes;
-            }
+        if (displayId < 0) {
+            return;
+        }
+        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+        if (displayContent != null) {
+            displayContent.pendingLayoutChanges |= changes;
         }
     }
 
-    void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) {
-        // Used to track which displays layout changes have been done.
-        SparseIntArray displays = new SparseIntArray(2);
+    void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason,
+            final int displayId) {
         WindowList windows = appAnimator.mAppToken.allAppWindows;
         for (int i = windows.size() - 1; i >= 0; i--) {
-            final int displayId = windows.get(i).getDisplayId();
-            if (displayId >= 0 && displays.indexOfKey(displayId) < 0) {
+            if (displayId == windows.get(i).getDisplayId()) {
                 setPendingLayoutChanges(displayId, changes);
-                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                    mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId));
+                if (DEBUG_LAYOUT_REPEATS) {
+                    mWindowPlacerLocked.debugLayoutRepeats(reason,
+                            getPendingLayoutChanges(displayId));
                 }
-                // Keep from processing this display again.
-                displays.put(displayId, changes);
+                break;
             }
         }
     }
@@ -876,7 +944,23 @@ public class WindowAnimator {
         return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
     }
 
+    void requestRemovalOfReplacedWindows(WindowState win) {
+        mRemoveReplacedWindows = true;
+    }
+
     private class DisplayContentsAnimator {
         ScreenRotationAnimation mScreenRotationAnimation = null;
     }
+
+    boolean isAnimating() {
+        return mAnimating;
+    }
+
+    void setAnimating(boolean animating) {
+        mAnimating = animating;
+    }
+
+    void orAnimating(boolean animating) {
+        mAnimating |= animating;
+    }
 }