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