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