FileDocCategorySizeDatePackage
WindowAnimator.javaAPI DocAndroid 5.1 API42441Thu Mar 12 22:22:42 GMT 2015com.android.server.wm

WindowAnimator

public class WindowAnimator extends Object
Singleton class that carries out the animations and Surface operations in a separate task on behalf of WindowManagerService.

Fields Summary
private static final String
TAG
private static final long
KEYGUARD_ANIM_TIMEOUT_MS
How long to give statusbar to clear the private keyguard flag when animating out
final WindowManagerService
mService
final android.content.Context
mContext
final android.view.WindowManagerPolicy
mPolicy
boolean
mAnimating
final Runnable
mAnimationRunnable
long
mCurrentTime
Time of current animation step. Reset on each iteration
private int
mAnimTransactionSequence
Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup.
WindowState
mWindowDetachedWallpaper
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.
WindowStateAnimator
mUniverseBackground
int
mAboveUniverseLayer
int
mBulkUpdateParams
Object
mLastWindowFreezeSource
android.util.SparseArray
mDisplayContentsAnimators
boolean
mInitialized
boolean
mKeyguardGoingAway
boolean
mKeyguardGoingAwayToNotificationShade
boolean
mKeyguardGoingAwayDisableWindowAnimations
android.view.animation.Animation
mPostKeyguardExitAnimation
Use one animation for all entering activities after keyguard is dismissed.
static final int
KEYGUARD_NOT_SHOWN
static final int
KEYGUARD_ANIMATING_IN
static final int
KEYGUARD_SHOWN
static final int
KEYGUARD_ANIMATING_OUT
int
mForceHiding
Constructors Summary
WindowAnimator(WindowManagerService service)

        mService = service;
        mContext = service.mContext;
        mPolicy = service.mPolicy;

        mAnimationRunnable = new Runnable() {
            @Override
            public void run() {
                synchronized (mService.mWindowMap) {
                    mService.mAnimationScheduled = false;
                    animateLocked();
                }
            }
        };
    
Methods Summary
voidaddDisplayLocked(int displayId)

        // Create the DisplayContentsAnimator object by retrieving it.
        getDisplayContentsAnimatorLocked(displayId);
        if (displayId == Display.DEFAULT_DISPLAY) {
            mInitialized = true;
        }
    
private voidanimateLocked()
Locked on mService.mWindowMap.

        if (!mInitialized) {
            return;
        }

        mCurrentTime = SystemClock.uptimeMillis();
        mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
        boolean wasAnimating = mAnimating;
        mAnimating = false;
        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
            Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
        }

        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
                TAG, ">>> OPEN TRANSACTION animateLocked");
        SurfaceControl.openTransaction();
        SurfaceControl.setAnimationTransaction();
        try {
            final int numDisplays = mDisplayContentsAnimators.size();
            for (int i = 0; i < numDisplays; i++) {
                final int displayId = mDisplayContentsAnimators.keyAt(i);
                updateAppWindowsLocked(displayId);
                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;

                        //TODO (multidisplay): Accessibility supported only for the default display.
                        if (mService.mAccessibilityController != null
                                && displayId == Display.DEFAULT_DISPLAY) {
                            // We just finished rotation animation which means we did not
                            // anounce the rotation and waited for it to end, announce now.
                            mService.mAccessibilityController.onRotationChangedLocked(
                                    mService.getDefaultDisplayContentLocked(), mService.mRotation);
                        }
                    }
                }

                // Update animations of all applications, including those
                // associated with exiting/removed apps
                updateWindowsLocked(displayId);
                updateWallpaperLocked(displayId);

                final WindowList windows = mService.getWindowListLocked(displayId);
                final int N = windows.size();
                for (int j = 0; j < N; j++) {
                    windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
                }
            }

            for (int i = 0; i < numDisplays; i++) {
                final int displayId = mDisplayContentsAnimators.keyAt(i);

                testTokenMayBeDrawnLocked(displayId);

                final ScreenRotationAnimation screenRotationAnimation =
                        mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
                if (screenRotationAnimation != null) {
                    screenRotationAnimation.updateSurfacesInTransaction();
                }

                mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();

                //TODO (multidisplay): Magnification is supported only for the default display.
                if (mService.mAccessibilityController != null
                        && displayId == Display.DEFAULT_DISPLAY) {
                    mService.mAccessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
                }
            }

            if (mAnimating) {
                mService.scheduleAnimationLocked();
            }

            mService.setFocusedStackLayer();

            if (mService.mWatermark != null) {
                mService.mWatermark.drawIfNeeded();
            }
        } catch (RuntimeException e) {
            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
        } finally {
            SurfaceControl.closeTransaction();
            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
                    TAG, "<<< CLOSE TRANSACTION animateLocked");
        }

        boolean hasPendingLayoutChanges = false;
        final int numDisplays = mService.mDisplayContents.size();
        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
            final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
            if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
                mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
            }
            if (pendingChanges != 0) {
                hasPendingLayoutChanges = true;
            }
        }

        boolean doRequest = false;
        if (mBulkUpdateParams != 0) {
            doRequest = mService.copyAnimToLayoutParamsLocked();
        }

        if (hasPendingLayoutChanges || doRequest) {
            mService.requestTraversalLocked();
        }

        if (!mAnimating && wasAnimating) {
            mService.requestTraversalLocked();
        }
        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
            Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
                + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
                + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
                + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
        }
    
static java.lang.StringbulkUpdateParamsToString(int bulkUpdateParams)

        StringBuilder builder = new StringBuilder(128);
        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
            builder.append(" UPDATE_ROTATION");
        }
        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
            builder.append(" WALLPAPER_MAY_CHANGE");
        }
        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
            builder.append(" FORCE_HIDING_CHANGED");
        }
        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
            builder.append(" ORIENTATION_CHANGE_COMPLETE");
        }
        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
            builder.append(" TURN_ON_SCREEN");
        }
        return builder.toString();
    
public voiddumpLocked(java.io.PrintWriter pw, java.lang.String prefix, boolean dumpAll)

        final String subPrefix = "  " + prefix;
        final String subSubPrefix = "  " + subPrefix;

        for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
            pw.print(prefix); pw.print("DisplayContentsAnimator #");
                    pw.print(mDisplayContentsAnimators.keyAt(i));
                    pw.println(":");
            DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
            final WindowList windows =
                    mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i));
            final int N = windows.size();
            for (int j = 0; j < N; j++) {
                WindowStateAnimator wanim = windows.get(j).mWinAnimator;
                pw.print(subPrefix); pw.print("Window #"); pw.print(j);
                        pw.print(": "); pw.println(wanim);
            }
            if (displayAnimator.mScreenRotationAnimation != null) {
                pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
                displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
            } else if (dumpAll) {
                pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
            }
        }

        pw.println();

        if (dumpAll) {
            pw.print(prefix); pw.print("mAnimTransactionSequence=");
                    pw.print(mAnimTransactionSequence);
                    pw.print(" mForceHiding="); pw.println(forceHidingToString());
            pw.print(prefix); pw.print("mCurrentTime=");
                    pw.println(TimeUtils.formatUptime(mCurrentTime));
        }
        if (mBulkUpdateParams != 0) {
            pw.print(prefix); pw.print("mBulkUpdateParams=0x");
                    pw.print(Integer.toHexString(mBulkUpdateParams));
                    pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
        }
        if (mWindowDetachedWallpaper != null) {
            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);
        }
    
private java.lang.StringforceHidingToString()


       
        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;
        }
    
private com.android.server.wm.WindowAnimator$DisplayContentsAnimatorgetDisplayContentsAnimatorLocked(int displayId)

        DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
        if (displayAnimator == null) {
            displayAnimator = new DisplayContentsAnimator();
            mDisplayContentsAnimators.put(displayId, displayAnimator);
        }
        return displayAnimator;
    
intgetPendingLayoutChanges(int displayId)

        if (displayId < 0) {
            return 0;
        }
        return mService.getDisplayContentLocked(displayId).pendingLayoutChanges;
    
ScreenRotationAnimationgetScreenRotationAnimationLocked(int displayId)

        if (displayId < 0) {
            return null;
        }
        return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
    
voidhideWallpapersLocked(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;
            }
        }
    
voidremoveDisplayLocked(int displayId)

        final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
        if (displayAnimator != null) {
            if (displayAnimator.mScreenRotationAnimation != null) {
                displayAnimator.mScreenRotationAnimation.kill();
                displayAnimator.mScreenRotationAnimation = null;
            }
        }

        mDisplayContentsAnimators.delete(displayId);
    
voidsetAppLayoutChanges(AppWindowAnimator appAnimator, int changes, java.lang.String s)

        // Used to track which displays layout changes have been done.
        SparseIntArray displays = new SparseIntArray(2);
        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) {
                setPendingLayoutChanges(displayId, changes);
                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                    mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId));
                }
                // Keep from processing this display again.
                displays.put(displayId, changes);
            }
        }
    
voidsetPendingLayoutChanges(int displayId, int changes)

        if (displayId >= 0) {
            mService.getDisplayContentLocked(displayId).pendingLayoutChanges |= changes;
        }
    
voidsetScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation)

        if (displayId >= 0) {
            getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
        }
    
private booleanshouldForceHide(WindowState win)

        final WindowState imeTarget = mService.mInputMethodTarget;
        final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
                (imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;

        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);
    
private voidtestTokenMayBeDrawnLocked(int displayId)
See if any windows have been drawn, so they (and others associated with them) can now be shown.

        // See if any windows have been drawn, so they (and others
        // associated with them) can now be shown.
        final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks();
        final int numTasks = tasks.size();
        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
            final int numTokens = tokens.size();
            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
                final AppWindowToken wtoken = tokens.get(tokenNdx);
                AppWindowAnimator appAnimator = wtoken.mAppAnimator;
                final boolean allDrawn = wtoken.allDrawn;
                if (allDrawn != appAnimator.allDrawn) {
                    appAnimator.allDrawn = allDrawn;
                    if (allDrawn) {
                        // The token has now changed state to having all
                        // windows shown...  what to do, what to do?
                        if (appAnimator.freezingScreen) {
                            appAnimator.showAllWindowsLocked();
                            mService.unsetAppFreezingScreenLocked(wtoken, false, true);
                            if (WindowManagerService.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.
                            setAppLayoutChanges(appAnimator,
                                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
                                    "testTokenMayBeDrawnLocked: freezingScreen");
                        } else {
                            setAppLayoutChanges(appAnimator,
                                    WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
                                    "testTokenMayBeDrawnLocked");

                            // We can now show all of the drawn windows!
                            if (!mService.mOpeningApps.contains(wtoken)) {
                                mAnimating |= appAnimator.showAllWindowsLocked();
                            }
                        }
                    }
                }
            }
        }
    
private voidupdateAppWindowsLocked(int displayId)

        ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks();
        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final TaskStack stack = stacks.get(stackNdx);
            final ArrayList<Task> tasks = stack.getTasks();
            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
                    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) {
                        // 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,
                                "updateWindowsApps...: done animating " + appAnimator.mAppToken);
                    }
                }
            }

            final AppTokenList exitingAppTokens = stack.mExitingAppTokens;
            final int NEAT = exitingAppTokens.size();
            for (int i = 0; i < NEAT; 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) {
                    // 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);
                }
            }
        }
    
private voidupdateWallpaperLocked(int displayId)

        mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();

        final WindowList windows = mService.getWindowListLocked(displayId);
        WindowState detachedWallpaper = null;

        for (int i = windows.size() - 1; i >= 0; i--) {
            final WindowState win = windows.get(i);
            WindowStateAnimator winAnimator = win.mWinAnimator;
            if (winAnimator.mSurfaceControl == null) {
                continue;
            }

            final int flags = win.mAttrs.flags;

            // If this window is animating, make a note that we have
            // an animating window and take care of a request to run
            // a detached wallpaper animation.
            if (winAnimator.mAnimating) {
                if (winAnimator.mAnimation != null) {
                    if ((flags & FLAG_SHOW_WALLPAPER) != 0
                            && winAnimator.mAnimation.getDetachWallpaper()) {
                        detachedWallpaper = win;
                    }
                    final int color = winAnimator.mAnimation.getBackgroundColor();
                    if (color != 0) {
                        final TaskStack stack = win.getStack();
                        if (stack != null) {
                            stack.setAnimationBackground(winAnimator, color);
                        }
                    }
                }
                mAnimating = true;
            }

            // If this window's app token is running a detached wallpaper
            // animation, make a note so we can ensure the wallpaper is
            // displayed behind it.
            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
            if (appAnimator != null && appAnimator.animation != null
                    && appAnimator.animating) {
                if ((flags & FLAG_SHOW_WALLPAPER) != 0
                        && appAnimator.animation.getDetachWallpaper()) {
                    detachedWallpaper = win;
                }

                final int color = appAnimator.animation.getBackgroundColor();
                if (color != 0) {
                    final TaskStack stack = win.getStack();
                    if (stack != null) {
                        stack.setAnimationBackground(winAnimator, color);
                    }
                }
            }
        } // end forall windows

        if (mWindowDetachedWallpaper != detachedWallpaper) {
            if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
                    "Detached wallpaper changed from " + mWindowDetachedWallpaper
                    + " to " + detachedWallpaper);
            mWindowDetachedWallpaper = detachedWallpaper;
            mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
        }
    
private voidupdateWindowsLocked(int displayId)

        ++mAnimTransactionSequence;

        final WindowList windows = mService.getWindowListLocked(displayId);

        if (mKeyguardGoingAway) {
            for (int i = windows.size() - 1; i >= 0; i--) {
                WindowState win = windows.get(i);
                if (!mPolicy.isKeyguardHostWindow(win.mAttrs)) {
                    continue;
                }
                final WindowStateAnimator winAnimator = win.mWinAnimator;
                if ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                    if (!winAnimator.mAnimating) {
                        if (DEBUG_KEYGUARD) Slog.d(TAG,
                                "updateWindowsLocked: creating delay animation");

                        // Create a new animation to delay until keyguard is gone on its own.
                        winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
                        winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
                        winAnimator.mAnimationIsEntrance = false;
                        winAnimator.mAnimationStartTime = -1;
                    }
                } else {
                    if (DEBUG_KEYGUARD) Slog.d(TAG,
                            "updateWindowsLocked: StatusBar is no longer keyguard");
                    mKeyguardGoingAway = false;
                    winAnimator.clearAnimation();
                }
                break;
            }
        }

        mForceHiding = KEYGUARD_NOT_SHOWN;

        boolean wallpaperInUnForceHiding = false;
        boolean startingInUnForceHiding = false;
        ArrayList<WindowStateAnimator> unForceHiding = null;
        WindowState wallpaper = null;
        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) {
                final boolean wasAnimating = winAnimator.mWasAnimating;
                final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
                mAnimating |= nowAnimating;

                if (WindowManagerService.DEBUG_WALLPAPER) {
                    Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
                            ", nowAnimating=" + nowAnimating);
                }

                if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
                    mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                    setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                    if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                        mService.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,
                                "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",
                                    getPendingLayoutChanges(displayId));
                        }
                        mService.mFocusMayChange = true;
                    } else if (mKeyguardGoingAway && !nowAnimating) {
                        // Timeout!!
                        Slog.e(TAG, "Timeout waiting for animation to startup");
                        mPolicy.startKeyguardExitAnimation(0, 0);
                        mKeyguardGoingAway = false;
                    }
                    if (win.isReadyForDisplay()) {
                        if (nowAnimating) {
                            if (winAnimator.mAnimationIsEntrance) {
                                mForceHiding = KEYGUARD_ANIMATING_IN;
                            } else {
                                mForceHiding = KEYGUARD_ANIMATING_OUT;
                            }
                        } else {
                            mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
                        }
                    }
                    if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                            "Force hide " + forceHidingToString()
                            + " hasSurface=" + win.mHasSurface
                            + " policyVis=" + win.mPolicyVisibility
                            + " destroying=" + win.mDestroying
                            + " attHidden=" + win.mAttachedHidden
                            + " vis=" + win.mViewVisibility
                            + " hidden=" + win.mRootToken.hidden
                            + " anim=" + win.mWinAnimator.mAnimation);
                } else if (canBeForceHidden) {
                    if (shouldBeForceHidden) {
                        if (!win.hideLw(false, false)) {
                            // Was already hidden
                            continue;
                        }
                        if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                                "Now policy hidden: " + win);
                    } else {
                        boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
                                && !winAnimator.mKeyguardGoingAwayAnimation
                                && win.hasDrawnLw()
                                && win.mAttachedWindow == null
                                && mForceHiding != KEYGUARD_NOT_SHOWN;

                        // If the window is already showing and we don't need to apply an existing
                        // Keyguard exit animation, skip.
                        if (!win.showLw(false, false) && !applyExistingExitAnimation) {
                            continue;
                        }
                        final boolean visibleNow = win.isVisibleNow();
                        if (!visibleNow) {
                            // Couldn't really show, must showLw() again when win becomes visible.
                            win.hideLw(false, false);
                            continue;
                        }
                        if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                                "Now policy shown: " + win);
                        if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
                                && win.mAttachedWindow == null) {
                            if (unForceHiding == null) {
                                unForceHiding = new ArrayList<>();
                            }
                            unForceHiding.add(winAnimator);
                            if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
                                wallpaperInUnForceHiding = true;
                            }
                            if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
                                startingInUnForceHiding = true;
                            }
                        } else if (applyExistingExitAnimation) {
                            // We're already in the middle of an animation. Use the existing
                            // animation to bring in this window.
                            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());
                            winAnimator.mKeyguardGoingAwayAnimation = true;
                        }
                        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,
                                    "updateWindowsLocked: setting mFocusMayChange true");
                            mService.mFocusMayChange = true;
                        }
                    }
                    if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
                        mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                        setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
                                    getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
                        }
                    }
                }
            }

            // If the window doesn't have a surface, the only thing we care about is the correct
            // policy visibility.
            else if (canBeForceHidden) {
                if (shouldBeForceHidden) {
                    win.hideLw(false, false);
                } else {
                    win.showLw(false, false);
                }
            }

            final AppWindowToken atoken = win.mAppToken;
            if (winAnimator.mDrawState == WindowStateAnimator.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",
                                    getPendingLayoutChanges(displayId));
                        }
                    }
                }
            }
            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
            if (appAnimator != null && appAnimator.thumbnail != null) {
                if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
                    appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
                    appAnimator.thumbnailLayer = 0;
                }
                if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
                    appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
                }
            }
            if (win.mIsWallpaper) {
                wallpaper = win;
            }
        } // end forall windows

        // If we have windows that are being show due to them no longer
        // being force-hidden, apply the appropriate animation to them if animations are not
        // disabled.
        if (unForceHiding != null) {
            if (!mKeyguardGoingAwayDisableWindowAnimations) {
                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);
                    if (a != null) {
                        if (DEBUG_KEYGUARD) Slog.v(TAG,
                                "Starting keyguard exit animation on window " + winAnimator.mWin);
                        winAnimator.setAnimation(a);
                        winAnimator.mKeyguardGoingAwayAnimation = true;
                        if (first) {
                            mPostKeyguardExitAnimation = a;
                            mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
                            first = false;
                        }
                    }
                }
            } else if (mKeyguardGoingAway) {
                mPolicy.startKeyguardExitAnimation(mCurrentTime, 0 /* duration */);
                mKeyguardGoingAway = false;
            }


            // Wallpaper is going away in un-force-hide motion, animate it as well.
            if (!wallpaperInUnForceHiding && wallpaper != null
                    && !mKeyguardGoingAwayDisableWindowAnimations) {
                if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
                Animation a = mPolicy.createForceHideWallpaperExitAnimation(
                        mKeyguardGoingAwayToNotificationShade);
                if (a != null) {
                    wallpaper.mWinAnimator.setAnimation(a);
                }
            }
        }

        if (mPostKeyguardExitAnimation != null) {
            // We're in the midst of a keyguard exit animation.
            if (mKeyguardGoingAway) {
                mPolicy.startKeyguardExitAnimation(mCurrentTime +
                        mPostKeyguardExitAnimation.getStartOffset(),
                        mPostKeyguardExitAnimation.getDuration());
                mKeyguardGoingAway = false;
            } else if (mCurrentTime - mPostKeyguardExitAnimation.getStartTime()
                    > mPostKeyguardExitAnimation.getDuration()) {
                // Done with the animation, reset.
                if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations.");
                mPostKeyguardExitAnimation = null;
            }
        }