Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.wm;
     18 
     19 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
     20 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
     21 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
     22 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
     23 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
     24 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
     25 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
     26 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
     27 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
     28 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
     29 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
     30 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
     31 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
     32 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
     33 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
     34 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
     35 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
     36 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
     37 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
     38 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
     39 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
     40 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
     41 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
     42 import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
     43 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
     44 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
     45 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
     46 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
     47 
     48 import android.content.Context;
     49 import android.os.Trace;
     50 import android.util.Slog;
     51 import android.util.SparseArray;
     52 import android.util.TimeUtils;
     53 import android.view.Choreographer;
     54 import android.view.Display;
     55 import android.view.SurfaceControl;
     56 import android.view.WindowManagerPolicy;
     57 import android.view.animation.AlphaAnimation;
     58 import android.view.animation.Animation;
     59 
     60 import java.io.PrintWriter;
     61 import java.util.ArrayList;
     62 
     63 /**
     64  * Singleton class that carries out the animations and Surface operations in a separate task
     65  * on behalf of WindowManagerService.
     66  */
     67 public class WindowAnimator {
     68     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowAnimator" : TAG_WM;
     69 
     70     /** How long to give statusbar to clear the private keyguard flag when animating out */
     71     private static final long KEYGUARD_ANIM_TIMEOUT_MS = 1000;
     72 
     73     final WindowManagerService mService;
     74     final Context mContext;
     75     final WindowManagerPolicy mPolicy;
     76     private final WindowSurfacePlacer mWindowPlacerLocked;
     77 
     78     /** Is any window animating? */
     79     private boolean mAnimating;
     80 
     81     /** Is any app window animating? */
     82     boolean mAppWindowAnimating;
     83 
     84     final Choreographer.FrameCallback mAnimationFrameCallback;
     85 
     86     /** Time of current animation step. Reset on each iteration */
     87     long mCurrentTime;
     88 
     89     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
     90      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
     91     private int mAnimTransactionSequence;
     92 
     93     /** Window currently running an animation that has requested it be detached
     94      * from the wallpaper.  This means we need to ensure the wallpaper is
     95      * visible behind it in case it animates in a way that would allow it to be
     96      * seen. If multiple windows satisfy this, use the lowest window. */
     97     WindowState mWindowDetachedWallpaper = null;
     98 
     99     int mBulkUpdateParams = 0;
    100     Object mLastWindowFreezeSource;
    101 
    102     SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
    103 
    104     boolean mInitialized = false;
    105 
    106     boolean mKeyguardGoingAway;
    107     int mKeyguardGoingAwayFlags;
    108 
    109     /** Use one animation for all entering activities after keyguard is dismissed. */
    110     Animation mPostKeyguardExitAnimation;
    111 
    112     // forceHiding states.
    113     static final int KEYGUARD_NOT_SHOWN     = 0;
    114     static final int KEYGUARD_SHOWN         = 1;
    115     static final int KEYGUARD_ANIMATING_OUT = 2;
    116     int mForceHiding = KEYGUARD_NOT_SHOWN;
    117 
    118     // When set to true the animator will go over all windows after an animation frame is posted and
    119     // check if some got replaced and can be removed.
    120     private boolean mRemoveReplacedWindows = false;
    121 
    122     private final AppTokenList mTmpExitingAppTokens = new AppTokenList();
    123 
    124     /** The window that was previously hiding the Keyguard. */
    125     private WindowState mLastShowWinWhenLocked;
    126 
    127     private String forceHidingToString() {
    128         switch (mForceHiding) {
    129             case KEYGUARD_NOT_SHOWN:    return "KEYGUARD_NOT_SHOWN";
    130             case KEYGUARD_SHOWN:        return "KEYGUARD_SHOWN";
    131             case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
    132             default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
    133         }
    134     }
    135 
    136     WindowAnimator(final WindowManagerService service) {
    137         mService = service;
    138         mContext = service.mContext;
    139         mPolicy = service.mPolicy;
    140         mWindowPlacerLocked = service.mWindowPlacerLocked;
    141 
    142         mAnimationFrameCallback = new Choreographer.FrameCallback() {
    143             public void doFrame(long frameTimeNs) {
    144                 synchronized (mService.mWindowMap) {
    145                     mService.mAnimationScheduled = false;
    146                     animateLocked(frameTimeNs);
    147                 }
    148             }
    149         };
    150     }
    151 
    152     void addDisplayLocked(final int displayId) {
    153         // Create the DisplayContentsAnimator object by retrieving it.
    154         getDisplayContentsAnimatorLocked(displayId);
    155         if (displayId == Display.DEFAULT_DISPLAY) {
    156             mInitialized = true;
    157         }
    158     }
    159 
    160     void removeDisplayLocked(final int displayId) {
    161         final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
    162         if (displayAnimator != null) {
    163             if (displayAnimator.mScreenRotationAnimation != null) {
    164                 displayAnimator.mScreenRotationAnimation.kill();
    165                 displayAnimator.mScreenRotationAnimation = null;
    166             }
    167         }
    168 
    169         mDisplayContentsAnimators.delete(displayId);
    170     }
    171 
    172     private void updateAppWindowsLocked(int displayId) {
    173         ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks();
    174         for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
    175             final TaskStack stack = stacks.get(stackNdx);
    176             final ArrayList<Task> tasks = stack.getTasks();
    177             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
    178                 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
    179                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
    180                     final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
    181                     appAnimator.wasAnimating = appAnimator.animating;
    182                     if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
    183                         appAnimator.animating = true;
    184                         setAnimating(true);
    185                         mAppWindowAnimating = true;
    186                     } else if (appAnimator.wasAnimating) {
    187                         // stopped animating, do one more pass through the layout
    188                         setAppLayoutChanges(appAnimator,
    189                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
    190                                 "appToken " + appAnimator.mAppToken + " done", displayId);
    191                         if (DEBUG_ANIM) Slog.v(TAG,
    192                                 "updateWindowsApps...: done animating " + appAnimator.mAppToken);
    193                     }
    194                 }
    195             }
    196 
    197             mTmpExitingAppTokens.clear();
    198             mTmpExitingAppTokens.addAll(stack.mExitingAppTokens);
    199 
    200             final int exitingCount = mTmpExitingAppTokens.size();
    201             for (int i = 0; i < exitingCount; i++) {
    202                 final AppWindowAnimator appAnimator = mTmpExitingAppTokens.get(i).mAppAnimator;
    203                 // stepAnimation can trigger finishExit->removeWindowInnerLocked
    204                 // ->performSurfacePlacement
    205                 // performSurfacePlacement will directly manipulate the mExitingAppTokens list
    206                 // so we need to iterate over a copy and check for modifications.
    207                 if (!stack.mExitingAppTokens.contains(appAnimator)) {
    208                     continue;
    209                 }
    210                 appAnimator.wasAnimating = appAnimator.animating;
    211                 if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
    212                     setAnimating(true);
    213                     mAppWindowAnimating = true;
    214                 } else if (appAnimator.wasAnimating) {
    215                     // stopped animating, do one more pass through the layout
    216                     setAppLayoutChanges(appAnimator,
    217                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
    218                             "exiting appToken " + appAnimator.mAppToken + " done", displayId);
    219                     if (DEBUG_ANIM) Slog.v(TAG,
    220                             "updateWindowsApps...: done animating exiting "
    221                                     + appAnimator.mAppToken);
    222                 }
    223             }
    224         }
    225     }
    226 
    227     /**
    228      * @return The window that is currently hiding the Keyguard, or if it was hiding the Keyguard,
    229      *         and it's still animating.
    230      */
    231     private WindowState getWinShowWhenLockedOrAnimating() {
    232         final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
    233         if (winShowWhenLocked != null) {
    234             return winShowWhenLocked;
    235         }
    236         if (mLastShowWinWhenLocked != null && mLastShowWinWhenLocked.isOnScreen()
    237                 && mLastShowWinWhenLocked.isAnimatingLw()
    238                 && (mLastShowWinWhenLocked.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
    239             return mLastShowWinWhenLocked;
    240         }
    241         return null;
    242     }
    243 
    244     private boolean shouldForceHide(WindowState win) {
    245         final WindowState imeTarget = mService.mInputMethodTarget;
    246         final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
    247                 ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
    248                         || !mPolicy.canBeForceHidden(imeTarget, imeTarget.mAttrs));
    249 
    250         final WindowState winShowWhenLocked = getWinShowWhenLockedOrAnimating();
    251         final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
    252                 null : winShowWhenLocked.mAppToken;
    253 
    254         boolean allowWhenLocked = false;
    255         // Show IME over the keyguard if the target allows it
    256         allowWhenLocked |= (win.mIsImWindow || imeTarget == win) && showImeOverKeyguard;
    257         // Show SHOW_WHEN_LOCKED windows that turn on the screen
    258         allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen;
    259 
    260         if (appShowWhenLocked != null) {
    261             allowWhenLocked |= appShowWhenLocked == win.mAppToken
    262                     // Show all SHOW_WHEN_LOCKED windows if some apps are shown over lockscreen
    263                     || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
    264                     // Show error dialogs over apps that are shown on lockscreen
    265                     || (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
    266         }
    267 
    268         // Allow showing a window that dismisses Keyguard if the policy allows it. This is used for
    269         // when the policy knows that the Keyguard can be dismissed without user interaction to
    270         // provide a smooth transition in that case.
    271         allowWhenLocked |= (win.mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0
    272                 && mPolicy.canShowDismissingWindowWhileLockedLw();
    273 
    274         // Only hide windows if the keyguard is active and not animating away.
    275         boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded()
    276                 && mForceHiding != KEYGUARD_ANIMATING_OUT;
    277         boolean hideDockDivider = win.mAttrs.type == TYPE_DOCK_DIVIDER
    278                 && win.getDisplayContent().getDockedStackLocked() == null;
    279         return keyguardOn && !allowWhenLocked && (win.getDisplayId() == Display.DEFAULT_DISPLAY)
    280                 || hideDockDivider;
    281     }
    282 
    283     private void updateWindowsLocked(final int displayId) {
    284         ++mAnimTransactionSequence;
    285 
    286         final WindowList windows = mService.getWindowListLocked(displayId);
    287 
    288         final boolean keyguardGoingAwayToShade =
    289                 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0;
    290         final boolean keyguardGoingAwayNoAnimation =
    291                 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0;
    292         final boolean keyguardGoingAwayWithWallpaper =
    293                 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0;
    294 
    295         if (mKeyguardGoingAway) {
    296             for (int i = windows.size() - 1; i >= 0; i--) {
    297                 WindowState win = windows.get(i);
    298                 if (!mPolicy.isKeyguardHostWindow(win.mAttrs)) {
    299                     continue;
    300                 }
    301                 final WindowStateAnimator winAnimator = win.mWinAnimator;
    302                 if ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
    303                     if (!winAnimator.mAnimating) {
    304                         if (DEBUG_KEYGUARD) Slog.d(TAG,
    305                                 "updateWindowsLocked: creating delay animation");
    306 
    307                         // Create a new animation to delay until keyguard is gone on its own.
    308                         winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
    309                         winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
    310                         winAnimator.mAnimationIsEntrance = false;
    311                         winAnimator.mAnimationStartTime = -1;
    312                         winAnimator.mKeyguardGoingAwayAnimation = true;
    313                         winAnimator.mKeyguardGoingAwayWithWallpaper
    314                                 = keyguardGoingAwayWithWallpaper;
    315                     }
    316                 } else {
    317                     if (DEBUG_KEYGUARD) Slog.d(TAG,
    318                             "updateWindowsLocked: StatusBar is no longer keyguard");
    319                     mKeyguardGoingAway = false;
    320                     winAnimator.clearAnimation();
    321                 }
    322                 break;
    323             }
    324         }
    325 
    326         mForceHiding = KEYGUARD_NOT_SHOWN;
    327 
    328         boolean wallpaperInUnForceHiding = false;
    329         boolean startingInUnForceHiding = false;
    330         ArrayList<WindowStateAnimator> unForceHiding = null;
    331         WindowState wallpaper = null;
    332         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
    333         for (int i = windows.size() - 1; i >= 0; i--) {
    334             WindowState win = windows.get(i);
    335             WindowStateAnimator winAnimator = win.mWinAnimator;
    336             final int flags = win.mAttrs.flags;
    337             boolean canBeForceHidden = mPolicy.canBeForceHidden(win, win.mAttrs);
    338             boolean shouldBeForceHidden = shouldForceHide(win);
    339             if (winAnimator.hasSurface()) {
    340                 final boolean wasAnimating = winAnimator.mWasAnimating;
    341                 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
    342                 winAnimator.mWasAnimating = nowAnimating;
    343                 orAnimating(nowAnimating);
    344 
    345                 if (DEBUG_WALLPAPER) {
    346                     Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
    347                             ", nowAnimating=" + nowAnimating);
    348                 }
    349 
    350                 if (wasAnimating && !winAnimator.mAnimating
    351                         && wallpaperController.isWallpaperTarget(win)) {
    352                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
    353                     setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
    354                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    355                     if (DEBUG_LAYOUT_REPEATS) {
    356                         mWindowPlacerLocked.debugLayoutRepeats(
    357                                 "updateWindowsAndWallpaperLocked 2",
    358                                 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
    359                     }
    360                 }
    361 
    362                 if (mPolicy.isForceHiding(win.mAttrs)) {
    363                     if (!wasAnimating && nowAnimating) {
    364                         if (DEBUG_KEYGUARD || DEBUG_ANIM ||
    365                                 DEBUG_VISIBILITY) Slog.v(TAG,
    366                                 "Animation started that could impact force hide: " + win);
    367                         mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
    368                         setPendingLayoutChanges(displayId,
    369                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    370                         if (DEBUG_LAYOUT_REPEATS) {
    371                             mWindowPlacerLocked.debugLayoutRepeats(
    372                                     "updateWindowsAndWallpaperLocked 3",
    373                                     getPendingLayoutChanges(displayId));
    374                         }
    375                         mService.mFocusMayChange = true;
    376                     } else if (mKeyguardGoingAway && !nowAnimating) {
    377                         // Timeout!!
    378                         Slog.e(TAG, "Timeout waiting for animation to startup");
    379                         mPolicy.startKeyguardExitAnimation(0, 0);
    380                         mKeyguardGoingAway = false;
    381                     }
    382                     if (win.isReadyForDisplay()) {
    383                         if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) {
    384                             mForceHiding = KEYGUARD_ANIMATING_OUT;
    385                         } else {
    386                             mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
    387                         }
    388                     }
    389                     if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
    390                             "Force hide " + forceHidingToString()
    391                             + " hasSurface=" + win.mHasSurface
    392                             + " policyVis=" + win.mPolicyVisibility
    393                             + " destroying=" + win.mDestroying
    394                             + " attHidden=" + win.mAttachedHidden
    395                             + " vis=" + win.mViewVisibility
    396                             + " hidden=" + win.mRootToken.hidden
    397                             + " anim=" + win.mWinAnimator.mAnimation);
    398                 } else if (canBeForceHidden) {
    399                     if (shouldBeForceHidden) {
    400                         if (!win.hideLw(false, false)) {
    401                             // Was already hidden
    402                             continue;
    403                         }
    404                         if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
    405                                 "Now policy hidden: " + win);
    406                     } else {
    407                         boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
    408                                 && !mPostKeyguardExitAnimation.hasEnded()
    409                                 && !winAnimator.mKeyguardGoingAwayAnimation
    410                                 && win.hasDrawnLw()
    411                                 && win.mAttachedWindow == null
    412                                 && !win.mIsImWindow
    413                                 && displayId == Display.DEFAULT_DISPLAY;
    414 
    415                         // If the window is already showing and we don't need to apply an existing
    416                         // Keyguard exit animation, skip.
    417                         if (!win.showLw(false, false) && !applyExistingExitAnimation) {
    418                             continue;
    419                         }
    420                         final boolean visibleNow = win.isVisibleNow();
    421                         if (!visibleNow) {
    422                             // Couldn't really show, must showLw() again when win becomes visible.
    423                             win.hideLw(false, false);
    424                             continue;
    425                         }
    426                         if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
    427                                 "Now policy shown: " + win);
    428                         if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
    429                                 && win.mAttachedWindow == null) {
    430                             if (unForceHiding == null) {
    431                                 unForceHiding = new ArrayList<>();
    432                             }
    433                             unForceHiding.add(winAnimator);
    434                             if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
    435                                 wallpaperInUnForceHiding = true;
    436                             }
    437                             if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
    438                                 startingInUnForceHiding = true;
    439                             }
    440                         } else if (applyExistingExitAnimation) {
    441                             // We're already in the middle of an animation. Use the existing
    442                             // animation to bring in this window.
    443                             if (DEBUG_KEYGUARD) Slog.v(TAG,
    444                                     "Applying existing Keyguard exit animation to new window: win="
    445                                             + win);
    446 
    447                             Animation a = mPolicy.createForceHideEnterAnimation(false,
    448                                     keyguardGoingAwayToShade);
    449                             winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime(),
    450                                     STACK_CLIP_BEFORE_ANIM);
    451                             winAnimator.mKeyguardGoingAwayAnimation = true;
    452                             winAnimator.mKeyguardGoingAwayWithWallpaper
    453                                     = keyguardGoingAwayWithWallpaper;
    454                         }
    455                         final WindowState currentFocus = mService.mCurrentFocus;
    456                         if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
    457                             // We are showing on top of the current
    458                             // focus, so re-evaluate focus to make
    459                             // sure it is correct.
    460                             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG,
    461                                     "updateWindowsLocked: setting mFocusMayChange true");
    462                             mService.mFocusMayChange = true;
    463                         }
    464                     }
    465                     if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
    466                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
    467                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
    468                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    469                         if (DEBUG_LAYOUT_REPEATS) {
    470                             mWindowPlacerLocked.debugLayoutRepeats(
    471                                     "updateWindowsAndWallpaperLocked 4",
    472                                     getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
    473                         }
    474                     }
    475                 }
    476             }
    477 
    478             // If the window doesn't have a surface, the only thing we care about is the correct
    479             // policy visibility.
    480             else if (canBeForceHidden) {
    481                 if (shouldBeForceHidden) {
    482                     win.hideLw(false, false);
    483                 } else {
    484                     win.showLw(false, false);
    485                 }
    486             }
    487 
    488             final AppWindowToken atoken = win.mAppToken;
    489             if (winAnimator.mDrawState == READY_TO_SHOW) {
    490                 if (atoken == null || atoken.allDrawn) {
    491                     if (winAnimator.performShowLocked()) {
    492                         setPendingLayoutChanges(displayId,
    493                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
    494                         if (DEBUG_LAYOUT_REPEATS) {
    495                             mWindowPlacerLocked.debugLayoutRepeats(
    496                                     "updateWindowsAndWallpaperLocked 5",
    497                                     getPendingLayoutChanges(displayId));
    498                         }
    499                     }
    500                 }
    501             }
    502             final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
    503             if (appAnimator != null && appAnimator.thumbnail != null) {
    504                 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
    505                     appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
    506                     appAnimator.thumbnailLayer = 0;
    507                 }
    508                 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
    509                     appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
    510                 }
    511             }
    512             if (win.mIsWallpaper) {
    513                 wallpaper = win;
    514             }
    515         } // end forall windows
    516 
    517         // If we have windows that are being show due to them no longer
    518         // being force-hidden, apply the appropriate animation to them if animations are not
    519         // disabled.
    520         if (unForceHiding != null) {
    521             if (!keyguardGoingAwayNoAnimation) {
    522                 boolean first = true;
    523                 for (int i=unForceHiding.size()-1; i>=0; i--) {
    524                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
    525                     Animation a = mPolicy.createForceHideEnterAnimation(
    526                             wallpaperInUnForceHiding && !startingInUnForceHiding,
    527                             keyguardGoingAwayToShade);
    528                     if (a != null) {
    529                         if (DEBUG_KEYGUARD) Slog.v(TAG,
    530                                 "Starting keyguard exit animation on window " + winAnimator.mWin);
    531                         winAnimator.setAnimation(a, STACK_CLIP_BEFORE_ANIM);
    532                         winAnimator.mKeyguardGoingAwayAnimation = true;
    533                         winAnimator.mKeyguardGoingAwayWithWallpaper
    534                                 = keyguardGoingAwayWithWallpaper;
    535                         if (first) {
    536                             mPostKeyguardExitAnimation = a;
    537                             mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
    538                             first = false;
    539                         }
    540                     }
    541                 }
    542             } else if (mKeyguardGoingAway) {
    543                 mPolicy.startKeyguardExitAnimation(mCurrentTime, 0 /* duration */);
    544                 mKeyguardGoingAway = false;
    545             }
    546 
    547 
    548             // Wallpaper is going away in un-force-hide motion, animate it as well.
    549             if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) {
    550                 if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
    551                 Animation a = mPolicy.createForceHideWallpaperExitAnimation(
    552                         keyguardGoingAwayToShade);
    553                 if (a != null) {
    554                     wallpaper.mWinAnimator.setAnimation(a);
    555                 }
    556             }
    557         }
    558 
    559         if (mPostKeyguardExitAnimation != null) {
    560             // We're in the midst of a keyguard exit animation.
    561             if (mKeyguardGoingAway) {
    562                 mPolicy.startKeyguardExitAnimation(mCurrentTime +
    563                         mPostKeyguardExitAnimation.getStartOffset(),
    564                         mPostKeyguardExitAnimation.getDuration());
    565                 mKeyguardGoingAway = false;
    566             }
    567             // mPostKeyguardExitAnimation might either be ended normally, cancelled, or "orphaned",
    568             // meaning that the window it was running on was removed. We check for hasEnded() for
    569             // ended normally and cancelled case, and check the time for the "orphaned" case.
    570             else if (mPostKeyguardExitAnimation.hasEnded()
    571                     || mCurrentTime - mPostKeyguardExitAnimation.getStartTime()
    572                             > mPostKeyguardExitAnimation.getDuration()) {
    573                 // Done with the animation, reset.
    574                 if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations.");
    575                 mPostKeyguardExitAnimation = null;
    576             }
    577         }
    578 
    579         final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
    580         if (winShowWhenLocked != null) {
    581             mLastShowWinWhenLocked = winShowWhenLocked;
    582         }
    583     }
    584 
    585     private void updateWallpaperLocked(int displayId) {
    586         mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
    587 
    588         final WindowList windows = mService.getWindowListLocked(displayId);
    589         WindowState detachedWallpaper = null;
    590 
    591         for (int i = windows.size() - 1; i >= 0; i--) {
    592             final WindowState win = windows.get(i);
    593             WindowStateAnimator winAnimator = win.mWinAnimator;
    594             if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
    595                 continue;
    596             }
    597 
    598             final int flags = win.mAttrs.flags;
    599 
    600             // If this window is animating, make a note that we have
    601             // an animating window and take care of a request to run
    602             // a detached wallpaper animation.
    603             if (winAnimator.mAnimating) {
    604                 if (winAnimator.mAnimation != null) {
    605                     if ((flags & FLAG_SHOW_WALLPAPER) != 0
    606                             && winAnimator.mAnimation.getDetachWallpaper()) {
    607                         detachedWallpaper = win;
    608                     }
    609                     final int color = winAnimator.mAnimation.getBackgroundColor();
    610                     if (color != 0) {
    611                         final TaskStack stack = win.getStack();
    612                         if (stack != null) {
    613                             stack.setAnimationBackground(winAnimator, color);
    614                         }
    615                     }
    616                 }
    617                 setAnimating(true);
    618             }
    619 
    620             // If this window's app token is running a detached wallpaper
    621             // animation, make a note so we can ensure the wallpaper is
    622             // displayed behind it.
    623             final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
    624             if (appAnimator != null && appAnimator.animation != null
    625                     && appAnimator.animating) {
    626                 if ((flags & FLAG_SHOW_WALLPAPER) != 0
    627                         && appAnimator.animation.getDetachWallpaper()) {
    628                     detachedWallpaper = win;
    629                 }
    630 
    631                 final int color = appAnimator.animation.getBackgroundColor();
    632                 if (color != 0) {
    633                     final TaskStack stack = win.getStack();
    634                     if (stack != null) {
    635                         stack.setAnimationBackground(winAnimator, color);
    636                     }
    637                 }
    638             }
    639         } // end forall windows
    640 
    641         if (mWindowDetachedWallpaper != detachedWallpaper) {
    642             if (DEBUG_WALLPAPER) Slog.v(TAG,
    643                     "Detached wallpaper changed from " + mWindowDetachedWallpaper
    644                     + " to " + detachedWallpaper);
    645             mWindowDetachedWallpaper = detachedWallpaper;
    646             mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
    647         }
    648     }
    649 
    650     /** See if any windows have been drawn, so they (and others associated with them) can now be
    651      *  shown. */
    652     private void testTokenMayBeDrawnLocked(int displayId) {
    653         // See if any windows have been drawn, so they (and others
    654         // associated with them) can now be shown.
    655         final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks();
    656         final int numTasks = tasks.size();
    657         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
    658             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
    659             final int numTokens = tokens.size();
    660             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
    661                 final AppWindowToken wtoken = tokens.get(tokenNdx);
    662                 AppWindowAnimator appAnimator = wtoken.mAppAnimator;
    663                 final boolean allDrawn = wtoken.allDrawn;
    664                 if (allDrawn != appAnimator.allDrawn) {
    665                     appAnimator.allDrawn = allDrawn;
    666                     if (allDrawn) {
    667                         // The token has now changed state to having all
    668                         // windows shown...  what to do, what to do?
    669                         if (appAnimator.freezingScreen) {
    670                             appAnimator.showAllWindowsLocked();
    671                             mService.unsetAppFreezingScreenLocked(wtoken, false, true);
    672                             if (DEBUG_ORIENTATION) Slog.i(TAG,
    673                                     "Setting mOrientationChangeComplete=true because wtoken "
    674                                     + wtoken + " numInteresting=" + wtoken.numInterestingWindows
    675                                     + " numDrawn=" + wtoken.numDrawnWindows);
    676                             // This will set mOrientationChangeComplete and cause a pass through
    677                             // layout.
    678                             setAppLayoutChanges(appAnimator,
    679                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
    680                                     "testTokenMayBeDrawnLocked: freezingScreen", displayId);
    681                         } else {
    682                             setAppLayoutChanges(appAnimator,
    683                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
    684                                     "testTokenMayBeDrawnLocked", displayId);
    685 
    686                             // We can now show all of the drawn windows!
    687                             if (!mService.mOpeningApps.contains(wtoken)) {
    688                                 orAnimating(appAnimator.showAllWindowsLocked());
    689                             }
    690                         }
    691                     }
    692                 }
    693             }
    694         }
    695     }
    696 
    697 
    698     /** Locked on mService.mWindowMap. */
    699     private void animateLocked(long frameTimeNs) {
    700         if (!mInitialized) {
    701             return;
    702         }
    703 
    704         mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
    705         mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
    706         boolean wasAnimating = mAnimating;
    707         setAnimating(false);
    708         mAppWindowAnimating = false;
    709         if (DEBUG_WINDOW_TRACE) {
    710             Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
    711         }
    712 
    713         if (SHOW_TRANSACTIONS) Slog.i(
    714                 TAG, ">>> OPEN TRANSACTION animateLocked");
    715         SurfaceControl.openTransaction();
    716         SurfaceControl.setAnimationTransaction();
    717         try {
    718             final int numDisplays = mDisplayContentsAnimators.size();
    719             for (int i = 0; i < numDisplays; i++) {
    720                 final int displayId = mDisplayContentsAnimators.keyAt(i);
    721                 updateAppWindowsLocked(displayId);
    722                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
    723 
    724                 final ScreenRotationAnimation screenRotationAnimation =
    725                         displayAnimator.mScreenRotationAnimation;
    726                 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
    727                     if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
    728                         setAnimating(true);
    729                     } else {
    730                         mBulkUpdateParams |= SET_UPDATE_ROTATION;
    731                         screenRotationAnimation.kill();
    732                         displayAnimator.mScreenRotationAnimation = null;
    733 
    734                         //TODO (multidisplay): Accessibility supported only for the default display.
    735                         if (mService.mAccessibilityController != null
    736                                 && displayId == Display.DEFAULT_DISPLAY) {
    737                             // We just finished rotation animation which means we did not
    738                             // anounce the rotation and waited for it to end, announce now.
    739                             mService.mAccessibilityController.onRotationChangedLocked(
    740                                     mService.getDefaultDisplayContentLocked(), mService.mRotation);
    741                         }
    742                     }
    743                 }
    744 
    745                 // Update animations of all applications, including those
    746                 // associated with exiting/removed apps
    747                 updateWindowsLocked(displayId);
    748                 updateWallpaperLocked(displayId);
    749 
    750                 final WindowList windows = mService.getWindowListLocked(displayId);
    751                 final int N = windows.size();
    752                 for (int j = 0; j < N; j++) {
    753                     windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
    754                 }
    755             }
    756 
    757             for (int i = 0; i < numDisplays; i++) {
    758                 final int displayId = mDisplayContentsAnimators.keyAt(i);
    759 
    760                 testTokenMayBeDrawnLocked(displayId);
    761 
    762                 final ScreenRotationAnimation screenRotationAnimation =
    763                         mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
    764                 if (screenRotationAnimation != null) {
    765                     screenRotationAnimation.updateSurfacesInTransaction();
    766                 }
    767 
    768                 orAnimating(mService.getDisplayContentLocked(displayId).animateDimLayers());
    769                 orAnimating(mService.getDisplayContentLocked(displayId).getDockedDividerController()
    770                         .animate(mCurrentTime));
    771                 //TODO (multidisplay): Magnification is supported only for the default display.
    772                 if (mService.mAccessibilityController != null
    773                         && displayId == Display.DEFAULT_DISPLAY) {
    774                     mService.mAccessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
    775                 }
    776             }
    777 
    778             if (mService.mDragState != null) {
    779                 mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
    780             }
    781 
    782             if (mAnimating) {
    783                 mService.scheduleAnimationLocked();
    784             }
    785 
    786             if (mService.mWatermark != null) {
    787                 mService.mWatermark.drawIfNeeded();
    788             }
    789         } catch (RuntimeException e) {
    790             Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
    791         } finally {
    792             SurfaceControl.closeTransaction();
    793             if (SHOW_TRANSACTIONS) Slog.i(
    794                     TAG, "<<< CLOSE TRANSACTION animateLocked");
    795         }
    796 
    797         boolean hasPendingLayoutChanges = false;
    798         final int numDisplays = mService.mDisplayContents.size();
    799         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
    800             final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
    801             final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
    802             if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
    803                 mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
    804             }
    805             if (pendingChanges != 0) {
    806                 hasPendingLayoutChanges = true;
    807             }
    808         }
    809 
    810         boolean doRequest = false;
    811         if (mBulkUpdateParams != 0) {
    812             doRequest = mWindowPlacerLocked.copyAnimToLayoutParamsLocked();
    813         }
    814 
    815         if (hasPendingLayoutChanges || doRequest) {
    816             mWindowPlacerLocked.requestTraversal();
    817         }
    818 
    819         if (mAnimating && !wasAnimating && Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
    820             Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
    821         }
    822 
    823         if (!mAnimating && wasAnimating) {
    824             mWindowPlacerLocked.requestTraversal();
    825             if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
    826                 Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
    827             }
    828         }
    829 
    830         if (mRemoveReplacedWindows) {
    831             removeReplacedWindowsLocked();
    832         }
    833 
    834         mService.stopUsingSavedSurfaceLocked();
    835         mService.destroyPreservedSurfaceLocked();
    836         mService.mWindowPlacerLocked.destroyPendingSurfaces();
    837 
    838         if (DEBUG_WINDOW_TRACE) {
    839             Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
    840                     + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
    841                     + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
    842                     + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
    843         }
    844     }
    845 
    846     private void removeReplacedWindowsLocked() {
    847         if (SHOW_TRANSACTIONS) Slog.i(
    848                 TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
    849         SurfaceControl.openTransaction();
    850         try {
    851             for (int i = mService.mDisplayContents.size() - 1; i >= 0; i--) {
    852                 DisplayContent display = mService.mDisplayContents.valueAt(i);
    853                 final WindowList windows = mService.getWindowListLocked(display.getDisplayId());
    854                 for (int j = windows.size() - 1; j >= 0; j--) {
    855                     windows.get(j).maybeRemoveReplacedWindow();
    856                 }
    857             }
    858         } finally {
    859             SurfaceControl.closeTransaction();
    860             if (SHOW_TRANSACTIONS) Slog.i(
    861                     TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
    862         }
    863         mRemoveReplacedWindows = false;
    864     }
    865 
    866     private static String bulkUpdateParamsToString(int bulkUpdateParams) {
    867         StringBuilder builder = new StringBuilder(128);
    868         if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) {
    869             builder.append(" UPDATE_ROTATION");
    870         }
    871         if ((bulkUpdateParams & WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE) != 0) {
    872             builder.append(" WALLPAPER_MAY_CHANGE");
    873         }
    874         if ((bulkUpdateParams & WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED) != 0) {
    875             builder.append(" FORCE_HIDING_CHANGED");
    876         }
    877         if ((bulkUpdateParams & WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
    878             builder.append(" ORIENTATION_CHANGE_COMPLETE");
    879         }
    880         if ((bulkUpdateParams & WindowSurfacePlacer.SET_TURN_ON_SCREEN) != 0) {
    881             builder.append(" TURN_ON_SCREEN");
    882         }
    883         return builder.toString();
    884     }
    885 
    886     public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
    887         final String subPrefix = "  " + prefix;
    888         final String subSubPrefix = "  " + subPrefix;
    889 
    890         for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
    891             pw.print(prefix); pw.print("DisplayContentsAnimator #");
    892                     pw.print(mDisplayContentsAnimators.keyAt(i));
    893                     pw.println(":");
    894             DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
    895             final WindowList windows =
    896                     mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i));
    897             final int N = windows.size();
    898             for (int j = 0; j < N; j++) {
    899                 WindowStateAnimator wanim = windows.get(j).mWinAnimator;
    900                 pw.print(subPrefix); pw.print("Window #"); pw.print(j);
    901                         pw.print(": "); pw.println(wanim);
    902             }
    903             if (displayAnimator.mScreenRotationAnimation != null) {
    904                 pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
    905                 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
    906             } else if (dumpAll) {
    907                 pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
    908             }
    909             pw.println();
    910         }
    911 
    912         pw.println();
    913 
    914         if (dumpAll) {
    915             pw.print(prefix); pw.print("mAnimTransactionSequence=");
    916                     pw.print(mAnimTransactionSequence);
    917                     pw.print(" mForceHiding="); pw.println(forceHidingToString());
    918             pw.print(prefix); pw.print("mCurrentTime=");
    919                     pw.println(TimeUtils.formatUptime(mCurrentTime));
    920         }
    921         if (mBulkUpdateParams != 0) {
    922             pw.print(prefix); pw.print("mBulkUpdateParams=0x");
    923                     pw.print(Integer.toHexString(mBulkUpdateParams));
    924                     pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
    925         }
    926         if (mWindowDetachedWallpaper != null) {
    927             pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
    928                 pw.println(mWindowDetachedWallpaper);
    929         }
    930     }
    931 
    932     int getPendingLayoutChanges(final int displayId) {
    933         if (displayId < 0) {
    934             return 0;
    935         }
    936         final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
    937         return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
    938     }
    939 
    940     void setPendingLayoutChanges(final int displayId, final int changes) {
    941         if (displayId < 0) {
    942             return;
    943         }
    944         final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
    945         if (displayContent != null) {
    946             displayContent.pendingLayoutChanges |= changes;
    947         }
    948     }
    949 
    950     void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason,
    951             final int displayId) {
    952         WindowList windows = appAnimator.mAppToken.allAppWindows;
    953         for (int i = windows.size() - 1; i >= 0; i--) {
    954             if (displayId == windows.get(i).getDisplayId()) {
    955                 setPendingLayoutChanges(displayId, changes);
    956                 if (DEBUG_LAYOUT_REPEATS) {
    957                     mWindowPlacerLocked.debugLayoutRepeats(reason,
    958                             getPendingLayoutChanges(displayId));
    959                 }
    960                 break;
    961             }
    962         }
    963     }
    964 
    965     private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
    966         DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
    967         if (displayAnimator == null) {
    968             displayAnimator = new DisplayContentsAnimator();
    969             mDisplayContentsAnimators.put(displayId, displayAnimator);
    970         }
    971         return displayAnimator;
    972     }
    973 
    974     void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
    975         if (displayId >= 0) {
    976             getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
    977         }
    978     }
    979 
    980     ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
    981         if (displayId < 0) {
    982             return null;
    983         }
    984         return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
    985     }
    986 
    987     void requestRemovalOfReplacedWindows(WindowState win) {
    988         mRemoveReplacedWindows = true;
    989     }
    990 
    991     private class DisplayContentsAnimator {
    992         ScreenRotationAnimation mScreenRotationAnimation = null;
    993     }
    994 
    995     boolean isAnimating() {
    996         return mAnimating;
    997     }
    998 
    999     void setAnimating(boolean animating) {
   1000         mAnimating = animating;
   1001     }
   1002 
   1003     void orAnimating(boolean animating) {
   1004         mAnimating |= animating;
   1005     }
   1006 }
   1007