Home | History | Annotate | Download | only in wm
      1 // Copyright 2012 Google Inc. All Rights Reserved.
      2 
      3 package com.android.server.wm;
      4 
      5 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
      6 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
      7 
      8 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
      9 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
     10 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
     11 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
     12 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING;
     13 
     14 import android.content.Context;
     15 import android.os.Debug;
     16 import android.os.SystemClock;
     17 import android.util.Log;
     18 import android.util.Slog;
     19 import android.util.SparseArray;
     20 import android.util.SparseIntArray;
     21 import android.util.TimeUtils;
     22 import android.view.Display;
     23 import android.view.SurfaceControl;
     24 import android.view.WindowManagerPolicy;
     25 import android.view.animation.Animation;
     26 
     27 import com.android.server.wm.WindowManagerService.LayoutFields;
     28 
     29 import java.io.PrintWriter;
     30 import java.util.ArrayList;
     31 
     32 /**
     33  * Singleton class that carries out the animations and Surface operations in a separate task
     34  * on behalf of WindowManagerService.
     35  */
     36 public class WindowAnimator {
     37     private static final String TAG = "WindowAnimator";
     38 
     39     final WindowManagerService mService;
     40     final Context mContext;
     41     final WindowManagerPolicy mPolicy;
     42 
     43     boolean mAnimating;
     44 
     45     final Runnable mAnimationRunnable;
     46 
     47     /** Time of current animation step. Reset on each iteration */
     48     long mCurrentTime;
     49 
     50     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
     51      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
     52     private int mAnimTransactionSequence;
     53 
     54     /** Window currently running an animation that has requested it be detached
     55      * from the wallpaper.  This means we need to ensure the wallpaper is
     56      * visible behind it in case it animates in a way that would allow it to be
     57      * seen. If multiple windows satisfy this, use the lowest window. */
     58     WindowState mWindowDetachedWallpaper = null;
     59 
     60     WindowStateAnimator mUniverseBackground = null;
     61     int mAboveUniverseLayer = 0;
     62 
     63     int mBulkUpdateParams = 0;
     64     Object mLastWindowFreezeSource;
     65 
     66     SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
     67             new SparseArray<WindowAnimator.DisplayContentsAnimator>(2);
     68 
     69     boolean mInitialized = false;
     70 
     71     // forceHiding states.
     72     static final int KEYGUARD_NOT_SHOWN     = 0;
     73     static final int KEYGUARD_ANIMATING_IN  = 1;
     74     static final int KEYGUARD_SHOWN         = 2;
     75     static final int KEYGUARD_ANIMATING_OUT = 3;
     76     int mForceHiding = KEYGUARD_NOT_SHOWN;
     77 
     78     private String forceHidingToString() {
     79         switch (mForceHiding) {
     80             case KEYGUARD_NOT_SHOWN:    return "KEYGUARD_NOT_SHOWN";
     81             case KEYGUARD_ANIMATING_IN: return "KEYGUARD_ANIMATING_IN";
     82             case KEYGUARD_SHOWN:        return "KEYGUARD_SHOWN";
     83             case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
     84             default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
     85         }
     86     }
     87 
     88     WindowAnimator(final WindowManagerService service) {
     89         mService = service;
     90         mContext = service.mContext;
     91         mPolicy = service.mPolicy;
     92 
     93         mAnimationRunnable = new Runnable() {
     94             @Override
     95             public void run() {
     96                 synchronized (mService.mWindowMap) {
     97                     mService.mAnimationScheduled = false;
     98                     animateLocked();
     99                 }
    100             }
    101         };
    102     }
    103 
    104     void addDisplayLocked(final int displayId) {
    105         // Create the DisplayContentsAnimator object by retrieving it.
    106         getDisplayContentsAnimatorLocked(displayId);
    107         if (displayId == Display.DEFAULT_DISPLAY) {
    108             mInitialized = true;
    109         }
    110     }
    111 
    112     void removeDisplayLocked(final int displayId) {
    113         final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
    114         if (displayAnimator != null) {
    115             if (displayAnimator.mScreenRotationAnimation != null) {
    116                 displayAnimator.mScreenRotationAnimation.kill();
    117                 displayAnimator.mScreenRotationAnimation = null;
    118             }
    119         }
    120 
    121         mDisplayContentsAnimators.delete(displayId);
    122     }
    123 
    124     void hideWallpapersLocked(final WindowState w) {
    125         final WindowState wallpaperTarget = mService.mWallpaperTarget;
    126         final WindowState lowerWallpaperTarget = mService.mLowerWallpaperTarget;
    127         final ArrayList<WindowToken> wallpaperTokens = mService.mWallpaperTokens;
    128 
    129         if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) {
    130             final int numTokens = wallpaperTokens.size();
    131             for (int i = numTokens - 1; i >= 0; i--) {
    132                 final WindowToken token = wallpaperTokens.get(i);
    133                 final int numWindows = token.windows.size();
    134                 for (int j = numWindows - 1; j >= 0; j--) {
    135                     final WindowState wallpaper = token.windows.get(j);
    136                     final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
    137                     if (!winAnimator.mLastHidden) {
    138                         winAnimator.hide();
    139                         mService.dispatchWallpaperVisibility(wallpaper, false);
    140                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
    141                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    142                     }
    143                 }
    144                 if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG,
    145                         "Hiding wallpaper " + token + " from " + w
    146                         + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget
    147                         + "\n" + Debug.getCallers(5, "  "));
    148                 token.hidden = true;
    149             }
    150         }
    151     }
    152 
    153     private void updateAppWindowsLocked(int displayId) {
    154         final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
    155         final ArrayList<Task> tasks = displayContent.getTasks();
    156         final int numTasks = tasks.size();
    157         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
    158             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
    159             final int numTokens = tokens.size();
    160             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
    161                 final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
    162                 final boolean wasAnimating = appAnimator.animation != null
    163                         && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
    164                 if (appAnimator.stepAnimationLocked(mCurrentTime)) {
    165                     mAnimating = true;
    166                 } else if (wasAnimating) {
    167                     // stopped animating, do one more pass through the layout
    168                     setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
    169                             "appToken " + appAnimator.mAppToken + " done");
    170                     if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
    171                             "updateWindowsApps...: done animating " + appAnimator.mAppToken);
    172                 }
    173             }
    174         }
    175 
    176         final AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
    177         final int NEAT = exitingAppTokens.size();
    178         for (int i = 0; i < NEAT; i++) {
    179             final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
    180             final boolean wasAnimating = appAnimator.animation != null
    181                     && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
    182             if (appAnimator.stepAnimationLocked(mCurrentTime)) {
    183                 mAnimating = true;
    184             } else if (wasAnimating) {
    185                 // stopped animating, do one more pass through the layout
    186                 setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
    187                     "exiting appToken " + appAnimator.mAppToken + " done");
    188                 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
    189                         "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
    190             }
    191         }
    192     }
    193 
    194     private void updateWindowsLocked(final int displayId) {
    195         ++mAnimTransactionSequence;
    196 
    197         final WindowList windows = mService.getWindowListLocked(displayId);
    198         ArrayList<WindowStateAnimator> unForceHiding = null;
    199         boolean wallpaperInUnForceHiding = false;
    200         mForceHiding = KEYGUARD_NOT_SHOWN;
    201 
    202         for (int i = windows.size() - 1; i >= 0; i--) {
    203             WindowState win = windows.get(i);
    204             WindowStateAnimator winAnimator = win.mWinAnimator;
    205             final int flags = winAnimator.mAttrFlags;
    206 
    207             if (winAnimator.mSurfaceControl != null) {
    208                 final boolean wasAnimating = winAnimator.mWasAnimating;
    209                 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
    210 
    211                 if (WindowManagerService.DEBUG_WALLPAPER) {
    212                     Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
    213                             ", nowAnimating=" + nowAnimating);
    214                 }
    215 
    216                 if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
    217                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
    218                     setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
    219                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    220                     if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
    221                         mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
    222                                 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
    223                     }
    224                 }
    225 
    226                 if (mPolicy.doesForceHide(win, win.mAttrs)) {
    227                     if (!wasAnimating && nowAnimating) {
    228                         if (WindowManagerService.DEBUG_ANIM ||
    229                                 WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
    230                                 "Animation started that could impact force hide: " + win);
    231                         mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
    232                         setPendingLayoutChanges(displayId,
    233                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    234                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
    235                             mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
    236                                     getPendingLayoutChanges(displayId));
    237                         }
    238                         mService.mFocusMayChange = true;
    239                     }
    240                     if (win.isReadyForDisplay()) {
    241                         if (nowAnimating) {
    242                             if (winAnimator.mAnimationIsEntrance) {
    243                                 mForceHiding = KEYGUARD_ANIMATING_IN;
    244                             } else {
    245                                 mForceHiding = KEYGUARD_ANIMATING_OUT;
    246                             }
    247                         } else {
    248                             mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
    249                         }
    250                     }
    251                     if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
    252                             "Force hide " + mForceHiding
    253                             + " hasSurface=" + win.mHasSurface
    254                             + " policyVis=" + win.mPolicyVisibility
    255                             + " destroying=" + win.mDestroying
    256                             + " attHidden=" + win.mAttachedHidden
    257                             + " vis=" + win.mViewVisibility
    258                             + " hidden=" + win.mRootToken.hidden
    259                             + " anim=" + win.mWinAnimator.mAnimation);
    260                 } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
    261                     final boolean hideWhenLocked =
    262                             (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0;
    263                     final boolean changed;
    264                     if (((mForceHiding == KEYGUARD_ANIMATING_IN)
    265                                 && (!winAnimator.isAnimating() || hideWhenLocked))
    266                             || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
    267                         changed = win.hideLw(false, false);
    268                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
    269                                 "Now policy hidden: " + win);
    270                     } else {
    271                         changed = win.showLw(false, false);
    272                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
    273                                 "Now policy shown: " + win);
    274                         if (changed) {
    275                             if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
    276                                     && win.isVisibleNow() /*w.isReadyForDisplay()*/) {
    277                                 if (unForceHiding == null) {
    278                                     unForceHiding = new ArrayList<WindowStateAnimator>();
    279                                 }
    280                                 unForceHiding.add(winAnimator);
    281                                 if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
    282                                     wallpaperInUnForceHiding = true;
    283                                 }
    284                             }
    285                             final WindowState currentFocus = mService.mCurrentFocus;
    286                             if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
    287                                 // We are showing on to of the current
    288                                 // focus, so re-evaluate focus to make
    289                                 // sure it is correct.
    290                                 if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG,
    291                                         "updateWindowsLocked: setting mFocusMayChange true");
    292                                 mService.mFocusMayChange = true;
    293                             }
    294                         }
    295                     }
    296                     if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) {
    297                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
    298                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
    299                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    300                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
    301                             mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
    302                                     getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
    303                         }
    304                     }
    305                 }
    306             }
    307 
    308             final AppWindowToken atoken = win.mAppToken;
    309             if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
    310                 if (atoken == null || atoken.allDrawn) {
    311                     if (winAnimator.performShowLocked()) {
    312                         setPendingLayoutChanges(displayId,
    313                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
    314                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
    315                             mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
    316                                     getPendingLayoutChanges(displayId));
    317                         }
    318                     }
    319                 }
    320             }
    321             final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
    322             if (appAnimator != null && appAnimator.thumbnail != null) {
    323                 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
    324                     appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
    325                     appAnimator.thumbnailLayer = 0;
    326                 }
    327                 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
    328                     appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
    329                 }
    330             }
    331         } // end forall windows
    332 
    333         // If we have windows that are being show due to them no longer
    334         // being force-hidden, apply the appropriate animation to them.
    335         if (unForceHiding != null) {
    336             for (int i=unForceHiding.size()-1; i>=0; i--) {
    337                 Animation a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding);
    338                 if (a != null) {
    339                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
    340                     winAnimator.setAnimation(a);
    341                     winAnimator.mAnimationIsEntrance = true;
    342                 }
    343             }
    344         }
    345     }
    346 
    347     private void updateWallpaperLocked(int displayId) {
    348         mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
    349 
    350         final WindowList windows = mService.getWindowListLocked(displayId);
    351         WindowState detachedWallpaper = null;
    352 
    353         for (int i = windows.size() - 1; i >= 0; i--) {
    354             final WindowState win = windows.get(i);
    355             WindowStateAnimator winAnimator = win.mWinAnimator;
    356             if (winAnimator.mSurfaceControl == null) {
    357                 continue;
    358             }
    359 
    360             final int flags = winAnimator.mAttrFlags;
    361 
    362             // If this window is animating, make a note that we have
    363             // an animating window and take care of a request to run
    364             // a detached wallpaper animation.
    365             if (winAnimator.mAnimating) {
    366                 if (winAnimator.mAnimation != null) {
    367                     if ((flags & FLAG_SHOW_WALLPAPER) != 0
    368                             && winAnimator.mAnimation.getDetachWallpaper()) {
    369                         detachedWallpaper = win;
    370                     }
    371                     final int color = winAnimator.mAnimation.getBackgroundColor();
    372                     if (color != 0) {
    373                         win.getStack().setAnimationBackground(winAnimator, color);
    374                     }
    375                 }
    376                 mAnimating = true;
    377             }
    378 
    379             // If this window's app token is running a detached wallpaper
    380             // animation, make a note so we can ensure the wallpaper is
    381             // displayed behind it.
    382             final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
    383             if (appAnimator != null && appAnimator.animation != null
    384                     && appAnimator.animating) {
    385                 if ((flags & FLAG_SHOW_WALLPAPER) != 0
    386                         && appAnimator.animation.getDetachWallpaper()) {
    387                     detachedWallpaper = win;
    388                 }
    389 
    390                 final int color = appAnimator.animation.getBackgroundColor();
    391                 if (color != 0) {
    392                     win.getStack().setAnimationBackground(winAnimator, color);
    393                 }
    394             }
    395         } // end forall windows
    396 
    397         if (mWindowDetachedWallpaper != detachedWallpaper) {
    398             if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
    399                     "Detached wallpaper changed from " + mWindowDetachedWallpaper
    400                     + " to " + detachedWallpaper);
    401             mWindowDetachedWallpaper = detachedWallpaper;
    402             mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
    403         }
    404     }
    405 
    406     /** See if any windows have been drawn, so they (and others associated with them) can now be
    407      *  shown. */
    408     private void testTokenMayBeDrawnLocked(int displayId) {
    409         // See if any windows have been drawn, so they (and others
    410         // associated with them) can now be shown.
    411         final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks();
    412         final int numTasks = tasks.size();
    413         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
    414             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
    415             final int numTokens = tokens.size();
    416             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
    417                 final AppWindowToken wtoken = tokens.get(tokenNdx);
    418                 AppWindowAnimator appAnimator = wtoken.mAppAnimator;
    419                 final boolean allDrawn = wtoken.allDrawn;
    420                 if (allDrawn != appAnimator.allDrawn) {
    421                     appAnimator.allDrawn = allDrawn;
    422                     if (allDrawn) {
    423                         // The token has now changed state to having all
    424                         // windows shown...  what to do, what to do?
    425                         if (appAnimator.freezingScreen) {
    426                             appAnimator.showAllWindowsLocked();
    427                             mService.unsetAppFreezingScreenLocked(wtoken, false, true);
    428                             if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
    429                                     "Setting mOrientationChangeComplete=true because wtoken "
    430                                     + wtoken + " numInteresting=" + wtoken.numInterestingWindows
    431                                     + " numDrawn=" + wtoken.numDrawnWindows);
    432                             // This will set mOrientationChangeComplete and cause a pass through layout.
    433                             setAppLayoutChanges(appAnimator,
    434                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
    435                                     "testTokenMayBeDrawnLocked: freezingScreen");
    436                         } else {
    437                             setAppLayoutChanges(appAnimator,
    438                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
    439                                     "testTokenMayBeDrawnLocked");
    440 
    441                             // We can now show all of the drawn windows!
    442                             if (!mService.mOpeningApps.contains(wtoken)) {
    443                                 mAnimating |= appAnimator.showAllWindowsLocked();
    444                             }
    445                         }
    446                     }
    447                 }
    448             }
    449         }
    450     }
    451 
    452     private void performAnimationsLocked(final int displayId) {
    453         updateWindowsLocked(displayId);
    454         updateWallpaperLocked(displayId);
    455     }
    456 
    457 
    458     /** Locked on mService.mWindowMap. */
    459     private void animateLocked() {
    460         if (!mInitialized) {
    461             return;
    462         }
    463 
    464         mCurrentTime = SystemClock.uptimeMillis();
    465         mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
    466         boolean wasAnimating = mAnimating;
    467         mAnimating = false;
    468         if (WindowManagerService.DEBUG_WINDOW_TRACE) {
    469             Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
    470         }
    471 
    472         if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
    473                 TAG, ">>> OPEN TRANSACTION animateLocked");
    474         SurfaceControl.openTransaction();
    475         SurfaceControl.setAnimationTransaction();
    476         try {
    477             final int numDisplays = mDisplayContentsAnimators.size();
    478             for (int i = 0; i < numDisplays; i++) {
    479                 final int displayId = mDisplayContentsAnimators.keyAt(i);
    480                 updateAppWindowsLocked(displayId);
    481                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
    482 
    483                 final ScreenRotationAnimation screenRotationAnimation =
    484                         displayAnimator.mScreenRotationAnimation;
    485                 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
    486                     if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
    487                         mAnimating = true;
    488                     } else {
    489                         mBulkUpdateParams |= SET_UPDATE_ROTATION;
    490                         screenRotationAnimation.kill();
    491                         displayAnimator.mScreenRotationAnimation = null;
    492                     }
    493                 }
    494 
    495                 // Update animations of all applications, including those
    496                 // associated with exiting/removed apps
    497                 performAnimationsLocked(displayId);
    498 
    499                 final WindowList windows = mService.getWindowListLocked(displayId);
    500                 final int N = windows.size();
    501                 for (int j = 0; j < N; j++) {
    502                     windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
    503                 }
    504             }
    505 
    506             for (int i = 0; i < numDisplays; i++) {
    507                 final int displayId = mDisplayContentsAnimators.keyAt(i);
    508 
    509                 testTokenMayBeDrawnLocked(displayId);
    510 
    511                 final ScreenRotationAnimation screenRotationAnimation =
    512                         mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
    513                 if (screenRotationAnimation != null) {
    514                     screenRotationAnimation.updateSurfacesInTransaction();
    515                 }
    516 
    517                 mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();
    518 
    519                 //TODO (multidisplay): Magnification is supported only for the default display.
    520                 if (mService.mDisplayMagnifier != null && displayId == Display.DEFAULT_DISPLAY) {
    521                     mService.mDisplayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
    522                 }
    523             }
    524 
    525             if (mAnimating) {
    526                 mService.scheduleAnimationLocked();
    527             }
    528 
    529             mService.setFocusedStackLayer();
    530 
    531             if (mService.mWatermark != null) {
    532                 mService.mWatermark.drawIfNeeded();
    533             }
    534         } catch (RuntimeException e) {
    535             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
    536         } finally {
    537             SurfaceControl.closeTransaction();
    538             if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
    539                     TAG, "<<< CLOSE TRANSACTION animateLocked");
    540         }
    541 
    542         boolean hasPendingLayoutChanges = false;
    543         final int numDisplays = mService.mDisplayContents.size();
    544         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
    545             final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
    546             final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
    547             if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
    548                 mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
    549             }
    550             if (pendingChanges != 0) {
    551                 hasPendingLayoutChanges = true;
    552             }
    553         }
    554 
    555         boolean doRequest = false;
    556         if (mBulkUpdateParams != 0) {
    557             doRequest = mService.copyAnimToLayoutParamsLocked();
    558         }
    559 
    560         if (hasPendingLayoutChanges || doRequest) {
    561             mService.requestTraversalLocked();
    562         }
    563 
    564         if (!mAnimating && wasAnimating) {
    565             mService.requestTraversalLocked();
    566         }
    567         if (WindowManagerService.DEBUG_WINDOW_TRACE) {
    568             Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
    569                 + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
    570                 + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
    571                 + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
    572         }
    573     }
    574 
    575     static String bulkUpdateParamsToString(int bulkUpdateParams) {
    576         StringBuilder builder = new StringBuilder(128);
    577         if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
    578             builder.append(" UPDATE_ROTATION");
    579         }
    580         if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
    581             builder.append(" WALLPAPER_MAY_CHANGE");
    582         }
    583         if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
    584             builder.append(" FORCE_HIDING_CHANGED");
    585         }
    586         if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
    587             builder.append(" ORIENTATION_CHANGE_COMPLETE");
    588         }
    589         if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
    590             builder.append(" TURN_ON_SCREEN");
    591         }
    592         return builder.toString();
    593     }
    594 
    595     public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
    596         final String subPrefix = "  " + prefix;
    597         final String subSubPrefix = "  " + subPrefix;
    598 
    599         for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
    600             pw.print(prefix); pw.print("DisplayContentsAnimator #");
    601                     pw.print(mDisplayContentsAnimators.keyAt(i));
    602                     pw.println(":");
    603             DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
    604             final WindowList windows =
    605                     mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i));
    606             final int N = windows.size();
    607             for (int j = 0; j < N; j++) {
    608                 WindowStateAnimator wanim = windows.get(j).mWinAnimator;
    609                 pw.print(subPrefix); pw.print("Window #"); pw.print(j);
    610                         pw.print(": "); pw.println(wanim);
    611             }
    612             if (displayAnimator.mScreenRotationAnimation != null) {
    613                 pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
    614                 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
    615             } else if (dumpAll) {
    616                 pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
    617             }
    618         }
    619 
    620         pw.println();
    621 
    622         if (dumpAll) {
    623             pw.print(prefix); pw.print("mAnimTransactionSequence=");
    624                     pw.print(mAnimTransactionSequence);
    625                     pw.print(" mForceHiding="); pw.println(forceHidingToString());
    626             pw.print(prefix); pw.print("mCurrentTime=");
    627                     pw.println(TimeUtils.formatUptime(mCurrentTime));
    628         }
    629         if (mBulkUpdateParams != 0) {
    630             pw.print(prefix); pw.print("mBulkUpdateParams=0x");
    631                     pw.print(Integer.toHexString(mBulkUpdateParams));
    632                     pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
    633         }
    634         if (mWindowDetachedWallpaper != null) {
    635             pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
    636                 pw.println(mWindowDetachedWallpaper);
    637         }
    638         if (mUniverseBackground != null) {
    639             pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
    640                     pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
    641         }
    642     }
    643 
    644     int getPendingLayoutChanges(final int displayId) {
    645         return mService.getDisplayContentLocked(displayId).pendingLayoutChanges;
    646     }
    647 
    648     void setPendingLayoutChanges(final int displayId, final int changes) {
    649         mService.getDisplayContentLocked(displayId).pendingLayoutChanges |= changes;
    650     }
    651 
    652     void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) {
    653         // Used to track which displays layout changes have been done.
    654         SparseIntArray displays = new SparseIntArray(2);
    655         WindowList windows = appAnimator.mAppToken.allAppWindows;
    656         for (int i = windows.size() - 1; i >= 0; i--) {
    657             final int displayId = windows.get(i).getDisplayId();
    658             if (displays.indexOfKey(displayId) < 0) {
    659                 setPendingLayoutChanges(displayId, changes);
    660                 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
    661                     mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId));
    662                 }
    663                 // Keep from processing this display again.
    664                 displays.put(displayId, changes);
    665             }
    666         }
    667     }
    668 
    669     private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
    670         DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
    671         if (displayAnimator == null) {
    672             displayAnimator = new DisplayContentsAnimator();
    673             mDisplayContentsAnimators.put(displayId, displayAnimator);
    674         }
    675         return displayAnimator;
    676     }
    677 
    678     void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
    679         getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
    680     }
    681 
    682     ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
    683         return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
    684     }
    685 
    686     private class DisplayContentsAnimator {
    687         ScreenRotationAnimation mScreenRotationAnimation = null;
    688     }
    689 }
    690