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