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