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 
     13 import static com.android.server.wm.WindowManagerService.H.UPDATE_ANIM_PARAMETERS;
     14 
     15 import android.content.Context;
     16 import android.os.Debug;
     17 import android.os.SystemClock;
     18 import android.util.Log;
     19 import android.util.Slog;
     20 import android.util.SparseArray;
     21 import android.util.SparseIntArray;
     22 import android.util.TimeUtils;
     23 import android.view.Display;
     24 import android.view.Surface;
     25 import android.view.WindowManagerPolicy;
     26 import android.view.animation.Animation;
     27 
     28 import com.android.server.wm.WindowManagerService.AppWindowAnimParams;
     29 import com.android.server.wm.WindowManagerService.LayoutFields;
     30 import com.android.server.wm.WindowManagerService.LayoutToAnimatorParams;
     31 
     32 import java.io.PrintWriter;
     33 import java.util.ArrayList;
     34 
     35 /**
     36  * Singleton class that carries out the animations and Surface operations in a separate task
     37  * on behalf of WindowManagerService.
     38  */
     39 public class WindowAnimator {
     40     private static final String TAG = "WindowAnimator";
     41 
     42     final WindowManagerService mService;
     43     final Context mContext;
     44     final WindowManagerPolicy mPolicy;
     45 
     46     boolean mAnimating;
     47 
     48     final Runnable mAnimationRunnable;
     49 
     50     int mAdjResult;
     51 
     52     // Layout changes for individual Displays. Indexed by displayId.
     53     SparseIntArray mPendingLayoutChanges = new SparseIntArray();
     54 
     55     // TODO: Assign these from each iteration through DisplayContent. Only valid between loops.
     56     /** Overall window dimensions */
     57     int mDw, mDh;
     58 
     59     /** Interior window dimensions */
     60     int mInnerDw, mInnerDh;
     61 
     62     /** Time of current animation step. Reset on each iteration */
     63     long mCurrentTime;
     64 
     65     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
     66      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
     67     private int mAnimTransactionSequence;
     68 
     69     // Window currently running an animation that has requested it be detached
     70     // from the wallpaper.  This means we need to ensure the wallpaper is
     71     // visible behind it in case it animates in a way that would allow it to be
     72     // seen. If multiple windows satisfy this, use the lowest window.
     73     WindowState mWindowDetachedWallpaper = null;
     74 
     75     WindowStateAnimator mUniverseBackground = null;
     76     int mAboveUniverseLayer = 0;
     77 
     78     int mBulkUpdateParams = 0;
     79 
     80     SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
     81             new SparseArray<WindowAnimator.DisplayContentsAnimator>();
     82 
     83     static final int WALLPAPER_ACTION_PENDING = 1;
     84     int mPendingActions;
     85 
     86     WindowState mWallpaperTarget = null;
     87     AppWindowAnimator mWpAppAnimator = null;
     88     WindowState mLowerWallpaperTarget = null;
     89     WindowState mUpperWallpaperTarget = null;
     90 
     91     ArrayList<AppWindowAnimator> mAppAnimators = new ArrayList<AppWindowAnimator>();
     92 
     93     ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
     94 
     95     /** Parameters being passed from this into mService. */
     96     static class AnimatorToLayoutParams {
     97         boolean mUpdateQueued;
     98         int mBulkUpdateParams;
     99         SparseIntArray mPendingLayoutChanges;
    100         WindowState mWindowDetachedWallpaper;
    101     }
    102     /** Do not modify unless holding mService.mWindowMap or this and mAnimToLayout in that order */
    103     final AnimatorToLayoutParams mAnimToLayout = new AnimatorToLayoutParams();
    104 
    105     boolean mInitialized = false;
    106 
    107     // forceHiding states.
    108     static final int KEYGUARD_NOT_SHOWN     = 0;
    109     static final int KEYGUARD_ANIMATING_IN  = 1;
    110     static final int KEYGUARD_SHOWN         = 2;
    111     static final int KEYGUARD_ANIMATING_OUT = 3;
    112     int mForceHiding = KEYGUARD_NOT_SHOWN;
    113 
    114     private String forceHidingToString() {
    115         switch (mForceHiding) {
    116             case KEYGUARD_NOT_SHOWN:    return "KEYGUARD_NOT_SHOWN";
    117             case KEYGUARD_ANIMATING_IN: return "KEYGUARD_ANIMATING_IN";
    118             case KEYGUARD_SHOWN:        return "KEYGUARD_SHOWN";
    119             case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
    120             default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
    121         }
    122     }
    123 
    124     WindowAnimator(final WindowManagerService service) {
    125         mService = service;
    126         mContext = service.mContext;
    127         mPolicy = service.mPolicy;
    128 
    129         mAnimationRunnable = new Runnable() {
    130             @Override
    131             public void run() {
    132                 // TODO(cmautner): When full isolation is achieved for animation, the first lock
    133                 // goes away and only the WindowAnimator.this remains.
    134                 synchronized(mService.mWindowMap) {
    135                     synchronized(WindowAnimator.this) {
    136                         copyLayoutToAnimParamsLocked();
    137                         animateLocked();
    138                     }
    139                 }
    140             }
    141         };
    142     }
    143 
    144     void addDisplayLocked(final int displayId) {
    145         // Create the DisplayContentsAnimator object by retrieving it.
    146         getDisplayContentsAnimatorLocked(displayId);
    147         if (displayId == Display.DEFAULT_DISPLAY) {
    148             mInitialized = true;
    149         }
    150     }
    151 
    152     void removeDisplayLocked(final int displayId) {
    153         final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
    154         if (displayAnimator != null) {
    155             if (displayAnimator.mWindowAnimationBackgroundSurface != null) {
    156                 displayAnimator.mWindowAnimationBackgroundSurface.kill();
    157                 displayAnimator.mWindowAnimationBackgroundSurface = null;
    158             }
    159             if (displayAnimator.mScreenRotationAnimation != null) {
    160                 displayAnimator.mScreenRotationAnimation.kill();
    161                 displayAnimator.mScreenRotationAnimation = null;
    162             }
    163             if (displayAnimator.mDimAnimator != null) {
    164                 displayAnimator.mDimAnimator.kill();
    165                 displayAnimator.mDimAnimator = null;
    166             }
    167         }
    168 
    169         mDisplayContentsAnimators.delete(displayId);
    170     }
    171 
    172     /** Locked on mAnimToLayout */
    173     void updateAnimToLayoutLocked() {
    174         final AnimatorToLayoutParams animToLayout = mAnimToLayout;
    175         synchronized (animToLayout) {
    176             animToLayout.mBulkUpdateParams = mBulkUpdateParams;
    177             animToLayout.mPendingLayoutChanges = mPendingLayoutChanges.clone();
    178             animToLayout.mWindowDetachedWallpaper = mWindowDetachedWallpaper;
    179 
    180             if (!animToLayout.mUpdateQueued) {
    181                 animToLayout.mUpdateQueued = true;
    182                 mService.mH.sendMessage(mService.mH.obtainMessage(UPDATE_ANIM_PARAMETERS));
    183             }
    184         }
    185     }
    186 
    187     /** Copy all WindowManagerService params into local params here. Locked on 'this'. */
    188     private void copyLayoutToAnimParamsLocked() {
    189         final LayoutToAnimatorParams layoutToAnim = mService.mLayoutToAnim;
    190         synchronized(layoutToAnim) {
    191             layoutToAnim.mAnimationScheduled = false;
    192 
    193             if (!layoutToAnim.mParamsModified) {
    194                 return;
    195             }
    196             layoutToAnim.mParamsModified = false;
    197 
    198             if ((layoutToAnim.mChanges & LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED) != 0) {
    199                 layoutToAnim.mChanges &= ~LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED;
    200                 mWallpaperTokens = new ArrayList<WindowToken>(layoutToAnim.mWallpaperTokens);
    201             }
    202 
    203             if (WindowManagerService.DEBUG_WALLPAPER_LIGHT) {
    204                 if (mWallpaperTarget != layoutToAnim.mWallpaperTarget
    205                         || mLowerWallpaperTarget != layoutToAnim.mLowerWallpaperTarget
    206                         || mUpperWallpaperTarget != layoutToAnim.mUpperWallpaperTarget) {
    207                     Slog.d(TAG, "Pulling anim wallpaper: target=" + layoutToAnim.mWallpaperTarget
    208                             + " lower=" + layoutToAnim.mLowerWallpaperTarget + " upper="
    209                             + layoutToAnim.mUpperWallpaperTarget);
    210                 }
    211             }
    212             mWallpaperTarget = layoutToAnim.mWallpaperTarget;
    213             mWpAppAnimator = mWallpaperTarget == null
    214                     ? null : mWallpaperTarget.mAppToken == null
    215                             ? null : mWallpaperTarget.mAppToken.mAppAnimator;
    216             mLowerWallpaperTarget = layoutToAnim.mLowerWallpaperTarget;
    217             mUpperWallpaperTarget = layoutToAnim.mUpperWallpaperTarget;
    218 
    219             // Set the new DimAnimator params.
    220             final int numDisplays = mDisplayContentsAnimators.size();
    221             for (int i = 0; i < numDisplays; i++) {
    222                 final int displayId = mDisplayContentsAnimators.keyAt(i);
    223                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
    224 
    225                 displayAnimator.mWinAnimators.clear();
    226                 final WinAnimatorList winAnimators = layoutToAnim.mWinAnimatorLists.get(displayId);
    227                 if (winAnimators != null) {
    228                     displayAnimator.mWinAnimators.addAll(winAnimators);
    229                 }
    230 
    231                 DimAnimator.Parameters dimParams = layoutToAnim.mDimParams.get(displayId);
    232                 if (dimParams == null) {
    233                     displayAnimator.mDimParams = null;
    234                 } else {
    235                     final WindowStateAnimator newWinAnimator = dimParams.mDimWinAnimator;
    236 
    237                     // Only set dim params on the highest dimmed layer.
    238                     final WindowStateAnimator existingDimWinAnimator =
    239                             displayAnimator.mDimParams == null ?
    240                                     null : displayAnimator.mDimParams.mDimWinAnimator;
    241                     // Don't turn on for an unshown surface, or for any layer but the highest
    242                     // dimmed layer.
    243                     if (newWinAnimator.mSurfaceShown && (existingDimWinAnimator == null
    244                             || !existingDimWinAnimator.mSurfaceShown
    245                             || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
    246                         displayAnimator.mDimParams = new DimAnimator.Parameters(dimParams);
    247                     }
    248                 }
    249             }
    250 
    251             mAppAnimators.clear();
    252             final int N = layoutToAnim.mAppWindowAnimParams.size();
    253             for (int i = 0; i < N; i++) {
    254                 final AppWindowAnimParams params = layoutToAnim.mAppWindowAnimParams.get(i);
    255                 AppWindowAnimator appAnimator = params.mAppAnimator;
    256                 appAnimator.mAllAppWinAnimators.clear();
    257                 appAnimator.mAllAppWinAnimators.addAll(params.mWinAnimators);
    258                 mAppAnimators.add(appAnimator);
    259             }
    260         }
    261     }
    262 
    263     void hideWallpapersLocked(final WindowState w, boolean fromAnimator) {
    264         // There is an issue where this function can be called either from
    265         // the animation or the layout side of the window manager.  The problem
    266         // is that if it is called from the layout side, we may not yet have
    267         // propagated the current layout wallpaper state over into the animation
    268         // state.  If that is the case, we can do bad things like hide the
    269         // wallpaper when we had just made it shown because the animation side
    270         // doesn't yet see that there is now a wallpaper target.  As a temporary
    271         // work-around, we tell the function here which side of the window manager
    272         // is calling so it can use the right state.
    273         if (fromAnimator) {
    274             hideWallpapersLocked(w, mWallpaperTarget, mLowerWallpaperTarget, mWallpaperTokens);
    275         } else {
    276             hideWallpapersLocked(w, mService.mWallpaperTarget,
    277                     mService.mLowerWallpaperTarget, mService.mWallpaperTokens);
    278         }
    279     }
    280 
    281     void hideWallpapersLocked(final WindowState w, final WindowState wallpaperTarget,
    282             final WindowState lowerWallpaperTarget, final ArrayList<WindowToken> wallpaperTokens) {
    283         if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) {
    284             final int numTokens = wallpaperTokens.size();
    285             for (int i = numTokens - 1; i >= 0; i--) {
    286                 final WindowToken token = wallpaperTokens.get(i);
    287                 final int numWindows = token.windows.size();
    288                 for (int j = numWindows - 1; j >= 0; j--) {
    289                     final WindowState wallpaper = token.windows.get(j);
    290                     final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
    291                     if (!winAnimator.mLastHidden) {
    292                         winAnimator.hide();
    293                         mService.dispatchWallpaperVisibility(wallpaper, false);
    294                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
    295                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    296                     }
    297                 }
    298                 if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG,
    299                         "Hiding wallpaper " + token + " from " + w
    300                         + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget
    301                         + "\n" + Debug.getCallers(5, "  "));
    302                 token.hidden = true;
    303             }
    304         }
    305     }
    306 
    307     private void updateAppWindowsLocked() {
    308         int i;
    309         final int NAT = mAppAnimators.size();
    310         for (i=0; i<NAT; i++) {
    311             final AppWindowAnimator appAnimator = mAppAnimators.get(i);
    312             final boolean wasAnimating = appAnimator.animation != null
    313                     && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
    314             if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
    315                 mAnimating = true;
    316             } else if (wasAnimating) {
    317                 // stopped animating, do one more pass through the layout
    318                 setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
    319                         "appToken " + appAnimator.mAppToken + " done");
    320                 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
    321                         "updateWindowsApps...: done animating " + appAnimator.mAppToken);
    322             }
    323         }
    324 
    325         final int NEAT = mService.mExitingAppTokens.size();
    326         for (i=0; i<NEAT; i++) {
    327             final AppWindowAnimator appAnimator = mService.mExitingAppTokens.get(i).mAppAnimator;
    328             final boolean wasAnimating = appAnimator.animation != null
    329                     && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
    330             if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
    331                 mAnimating = true;
    332             } else if (wasAnimating) {
    333                 // stopped animating, do one more pass through the layout
    334                 setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
    335                     "exiting appToken " + appAnimator.mAppToken + " done");
    336                 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
    337                         "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
    338             }
    339         }
    340     }
    341 
    342     private void updateWindowsLocked(final int displayId) {
    343         ++mAnimTransactionSequence;
    344 
    345         final WinAnimatorList winAnimatorList =
    346                 getDisplayContentsAnimatorLocked(displayId).mWinAnimators;
    347         ArrayList<WindowStateAnimator> unForceHiding = null;
    348         boolean wallpaperInUnForceHiding = false;
    349         mForceHiding = KEYGUARD_NOT_SHOWN;
    350 
    351         for (int i = winAnimatorList.size() - 1; i >= 0; i--) {
    352             WindowStateAnimator winAnimator = winAnimatorList.get(i);
    353             WindowState win = winAnimator.mWin;
    354             final int flags = winAnimator.mAttrFlags;
    355 
    356             if (winAnimator.mSurface != null) {
    357                 final boolean wasAnimating = winAnimator.mWasAnimating;
    358                 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
    359 
    360                 if (WindowManagerService.DEBUG_WALLPAPER) {
    361                     Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
    362                             ", nowAnimating=" + nowAnimating);
    363                 }
    364 
    365                 if (wasAnimating && !winAnimator.mAnimating && mWallpaperTarget == win) {
    366                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
    367                     setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
    368                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    369                     if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
    370                         mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
    371                             mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY));
    372                     }
    373                 }
    374 
    375                 if (mPolicy.doesForceHide(win, win.mAttrs)) {
    376                     if (!wasAnimating && nowAnimating) {
    377                         if (WindowManagerService.DEBUG_ANIM ||
    378                                 WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
    379                                 "Animation started that could impact force hide: " + win);
    380                         mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
    381                         setPendingLayoutChanges(displayId,
    382                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    383                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
    384                             mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
    385                                 mPendingLayoutChanges.get(displayId));
    386                         }
    387                         mService.mFocusMayChange = true;
    388                     }
    389                     if (win.isReadyForDisplay()) {
    390                         if (nowAnimating) {
    391                             if (winAnimator.mAnimationIsEntrance) {
    392                                 mForceHiding = KEYGUARD_ANIMATING_IN;
    393                             } else {
    394                                 mForceHiding = KEYGUARD_ANIMATING_OUT;
    395                             }
    396                         } else {
    397                             mForceHiding = KEYGUARD_SHOWN;
    398                         }
    399                     }
    400                     if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
    401                             "Force hide " + mForceHiding
    402                             + " hasSurface=" + win.mHasSurface
    403                             + " policyVis=" + win.mPolicyVisibility
    404                             + " destroying=" + win.mDestroying
    405                             + " attHidden=" + win.mAttachedHidden
    406                             + " vis=" + win.mViewVisibility
    407                             + " hidden=" + win.mRootToken.hidden
    408                             + " anim=" + win.mWinAnimator.mAnimation);
    409                 } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
    410                     final boolean hideWhenLocked =
    411                             (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0;
    412                     final boolean changed;
    413                     if (((mForceHiding == KEYGUARD_ANIMATING_IN)
    414                                 && (!winAnimator.isAnimating() || hideWhenLocked))
    415                             || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
    416                         changed = win.hideLw(false, false);
    417                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
    418                                 "Now policy hidden: " + win);
    419                     } else {
    420                         changed = win.showLw(false, false);
    421                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
    422                                 "Now policy shown: " + win);
    423                         if (changed) {
    424                             if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
    425                                     && win.isVisibleNow() /*w.isReadyForDisplay()*/) {
    426                                 if (unForceHiding == null) {
    427                                     unForceHiding = new ArrayList<WindowStateAnimator>();
    428                                 }
    429                                 unForceHiding.add(winAnimator);
    430                                 if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
    431                                     wallpaperInUnForceHiding = true;
    432                                 }
    433                             }
    434                             if (mCurrentFocus == null || mCurrentFocus.mLayer < win.mLayer) {
    435                                 // We are showing on to of the current
    436                                 // focus, so re-evaluate focus to make
    437                                 // sure it is correct.
    438                                 mService.mFocusMayChange = true;
    439                             }
    440                         }
    441                     }
    442                     if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) {
    443                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
    444                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
    445                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
    446                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
    447                             mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
    448                                 mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY));
    449                         }
    450                     }
    451                 }
    452             }
    453 
    454             final AppWindowToken atoken = win.mAppToken;
    455             if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
    456                 if (atoken == null || atoken.allDrawn) {
    457                     if (winAnimator.performShowLocked()) {
    458                         mPendingLayoutChanges.put(displayId,
    459                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
    460                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
    461                             mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
    462                                 mPendingLayoutChanges.get(displayId));
    463                         }
    464                     }
    465                 }
    466             }
    467             final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
    468             if (appAnimator != null && appAnimator.thumbnail != null) {
    469                 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
    470                     appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
    471                     appAnimator.thumbnailLayer = 0;
    472                 }
    473                 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
    474                     appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
    475                 }
    476             }
    477         } // end forall windows
    478 
    479         // If we have windows that are being show due to them no longer
    480         // being force-hidden, apply the appropriate animation to them.
    481         if (unForceHiding != null) {
    482             for (int i=unForceHiding.size()-1; i>=0; i--) {
    483                 Animation a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding);
    484                 if (a != null) {
    485                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
    486                     winAnimator.setAnimation(a);
    487                     winAnimator.mAnimationIsEntrance = true;
    488                 }
    489             }
    490         }
    491     }
    492 
    493     private void updateWallpaperLocked(int displayId) {
    494         final DisplayContentsAnimator displayAnimator =
    495                 getDisplayContentsAnimatorLocked(displayId);
    496         final WinAnimatorList winAnimatorList = displayAnimator.mWinAnimators;
    497         WindowStateAnimator windowAnimationBackground = null;
    498         int windowAnimationBackgroundColor = 0;
    499         WindowState detachedWallpaper = null;
    500         final DimSurface windowAnimationBackgroundSurface =
    501                 displayAnimator.mWindowAnimationBackgroundSurface;
    502 
    503         for (int i = winAnimatorList.size() - 1; i >= 0; i--) {
    504             WindowStateAnimator winAnimator = winAnimatorList.get(i);
    505             if (winAnimator.mSurface == null) {
    506                 continue;
    507             }
    508 
    509             final int flags = winAnimator.mAttrFlags;
    510             final WindowState win = winAnimator.mWin;
    511 
    512             // If this window is animating, make a note that we have
    513             // an animating window and take care of a request to run
    514             // a detached wallpaper animation.
    515             if (winAnimator.mAnimating) {
    516                 if (winAnimator.mAnimation != null) {
    517                     if ((flags & FLAG_SHOW_WALLPAPER) != 0
    518                             && winAnimator.mAnimation.getDetachWallpaper()) {
    519                         detachedWallpaper = win;
    520                     }
    521                     final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
    522                     if (backgroundColor != 0) {
    523                         if (windowAnimationBackground == null || (winAnimator.mAnimLayer <
    524                                 windowAnimationBackground.mAnimLayer)) {
    525                             windowAnimationBackground = winAnimator;
    526                             windowAnimationBackgroundColor = backgroundColor;
    527                         }
    528                     }
    529                 }
    530                 mAnimating = true;
    531             }
    532 
    533             // If this window's app token is running a detached wallpaper
    534             // animation, make a note so we can ensure the wallpaper is
    535             // displayed behind it.
    536             final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
    537             if (appAnimator != null && appAnimator.animation != null
    538                     && appAnimator.animating) {
    539                 if ((flags & FLAG_SHOW_WALLPAPER) != 0
    540                         && appAnimator.animation.getDetachWallpaper()) {
    541                     detachedWallpaper = win;
    542                 }
    543 
    544                 final int backgroundColor = appAnimator.animation.getBackgroundColor();
    545                 if (backgroundColor != 0) {
    546                     if (windowAnimationBackground == null || (winAnimator.mAnimLayer <
    547                             windowAnimationBackground.mAnimLayer)) {
    548                         windowAnimationBackground = winAnimator;
    549                         windowAnimationBackgroundColor = backgroundColor;
    550                     }
    551                 }
    552             }
    553         } // end forall windows
    554 
    555         if (mWindowDetachedWallpaper != detachedWallpaper) {
    556             if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
    557                     "Detached wallpaper changed from " + mWindowDetachedWallpaper
    558                     + " to " + detachedWallpaper);
    559             mWindowDetachedWallpaper = detachedWallpaper;
    560             mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
    561         }
    562 
    563         if (windowAnimationBackgroundColor != 0) {
    564             // If the window that wants black is the current wallpaper
    565             // target, then the black goes *below* the wallpaper so we
    566             // don't cause the wallpaper to suddenly disappear.
    567             int animLayer = windowAnimationBackground.mAnimLayer;
    568             WindowState win = windowAnimationBackground.mWin;
    569             if (mWallpaperTarget == win
    570                     || mLowerWallpaperTarget == win || mUpperWallpaperTarget == win) {
    571                 final int N = winAnimatorList.size();
    572                 for (int i = 0; i < N; i++) {
    573                     WindowStateAnimator winAnimator = winAnimatorList.get(i);
    574                     if (winAnimator.mIsWallpaper) {
    575                         animLayer = winAnimator.mAnimLayer;
    576                         break;
    577                     }
    578                 }
    579             }
    580 
    581             if (windowAnimationBackgroundSurface != null) {
    582                 windowAnimationBackgroundSurface.show(mDw, mDh,
    583                         animLayer - WindowManagerService.LAYER_OFFSET_DIM,
    584                         windowAnimationBackgroundColor);
    585             }
    586         } else {
    587             if (windowAnimationBackgroundSurface != null) {
    588                 windowAnimationBackgroundSurface.hide();
    589             }
    590         }
    591     }
    592 
    593     private void testTokenMayBeDrawnLocked() {
    594         // See if any windows have been drawn, so they (and others
    595         // associated with them) can now be shown.
    596         final int NT = mAppAnimators.size();
    597         for (int i=0; i<NT; i++) {
    598             AppWindowAnimator appAnimator = mAppAnimators.get(i);
    599             AppWindowToken wtoken = appAnimator.mAppToken;
    600             final boolean allDrawn = wtoken.allDrawn;
    601             if (allDrawn != appAnimator.allDrawn) {
    602                 appAnimator.allDrawn = allDrawn;
    603                 if (allDrawn) {
    604                     // The token has now changed state to having all
    605                     // windows shown...  what to do, what to do?
    606                     if (appAnimator.freezingScreen) {
    607                         appAnimator.showAllWindowsLocked();
    608                         mService.unsetAppFreezingScreenLocked(wtoken, false, true);
    609                         if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
    610                                 "Setting mOrientationChangeComplete=true because wtoken "
    611                                 + wtoken + " numInteresting=" + wtoken.numInterestingWindows
    612                                 + " numDrawn=" + wtoken.numDrawnWindows);
    613                         // This will set mOrientationChangeComplete and cause a pass through layout.
    614                         setAppLayoutChanges(appAnimator,
    615                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
    616                                 "testTokenMayBeDrawnLocked: freezingScreen");
    617                     } else {
    618                         setAppLayoutChanges(appAnimator,
    619                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
    620                                 "testTokenMayBeDrawnLocked");
    621 
    622                         // We can now show all of the drawn windows!
    623                         if (!mService.mOpeningApps.contains(wtoken)) {
    624                             mAnimating |= appAnimator.showAllWindowsLocked();
    625                         }
    626                     }
    627                 }
    628             }
    629         }
    630     }
    631 
    632     private void performAnimationsLocked(final int displayId) {
    633         updateWindowsLocked(displayId);
    634         updateWallpaperLocked(displayId);
    635     }
    636 
    637     // TODO(cmautner): Change the following comment when no longer locked on mWindowMap */
    638     /** Locked on mService.mWindowMap and this. */
    639     private void animateLocked() {
    640         if (!mInitialized) {
    641             return;
    642         }
    643 
    644         mPendingLayoutChanges.clear();
    645         mCurrentTime = SystemClock.uptimeMillis();
    646         mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
    647         boolean wasAnimating = mAnimating;
    648         mAnimating = false;
    649         if (WindowManagerService.DEBUG_WINDOW_TRACE) {
    650             Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
    651         }
    652 
    653         if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
    654                 TAG, ">>> OPEN TRANSACTION animateLocked");
    655         Surface.openTransaction();
    656         Surface.setAnimationTransaction();
    657         try {
    658             updateAppWindowsLocked();
    659 
    660             final int numDisplays = mDisplayContentsAnimators.size();
    661             for (int i = 0; i < numDisplays; i++) {
    662                 final int displayId = mDisplayContentsAnimators.keyAt(i);
    663                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
    664 
    665                 final ScreenRotationAnimation screenRotationAnimation =
    666                         displayAnimator.mScreenRotationAnimation;
    667                 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
    668                     if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
    669                         mAnimating = true;
    670                     } else {
    671                         mBulkUpdateParams |= SET_UPDATE_ROTATION;
    672                         screenRotationAnimation.kill();
    673                         displayAnimator.mScreenRotationAnimation = null;
    674                     }
    675                 }
    676 
    677                 // Update animations of all applications, including those
    678                 // associated with exiting/removed apps
    679                 performAnimationsLocked(displayId);
    680 
    681                 final WinAnimatorList winAnimatorList = displayAnimator.mWinAnimators;
    682                 final int N = winAnimatorList.size();
    683                 for (int j = 0; j < N; j++) {
    684                     winAnimatorList.get(j).prepareSurfaceLocked(true);
    685                 }
    686             }
    687 
    688             testTokenMayBeDrawnLocked();
    689 
    690             for (int i = 0; i < numDisplays; i++) {
    691                 final int displayId = mDisplayContentsAnimators.keyAt(i);
    692                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
    693 
    694                 final ScreenRotationAnimation screenRotationAnimation =
    695                         displayAnimator.mScreenRotationAnimation;
    696                 if (screenRotationAnimation != null) {
    697                     screenRotationAnimation.updateSurfacesInTransaction();
    698                 }
    699 
    700                 final DimAnimator.Parameters dimParams = displayAnimator.mDimParams;
    701                 final DimAnimator dimAnimator = displayAnimator.mDimAnimator;
    702                 if (dimAnimator != null && dimParams != null) {
    703                     dimAnimator.updateParameters(mContext.getResources(), dimParams, mCurrentTime);
    704                 }
    705                 if (dimAnimator != null && dimAnimator.mDimShown) {
    706                     mAnimating |= dimAnimator.updateSurface(isDimmingLocked(displayId),
    707                             mCurrentTime, !mService.okToDisplay());
    708                 }
    709             }
    710 
    711             if (mService.mWatermark != null) {
    712                 mService.mWatermark.drawIfNeeded();
    713             }
    714         } catch (RuntimeException e) {
    715             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
    716         } finally {
    717             Surface.closeTransaction();
    718             if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
    719                     TAG, "<<< CLOSE TRANSACTION animateLocked");
    720         }
    721 
    722         for (int i = mPendingLayoutChanges.size() - 1; i >= 0; i--) {
    723             if ((mPendingLayoutChanges.valueAt(i)
    724                     & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
    725                 mPendingActions |= WALLPAPER_ACTION_PENDING;
    726             }
    727         }
    728 
    729         if (mBulkUpdateParams != 0 || mPendingLayoutChanges.size() > 0) {
    730             updateAnimToLayoutLocked();
    731         }
    732 
    733         if (mAnimating) {
    734             synchronized (mService.mLayoutToAnim) {
    735                 mService.scheduleAnimationLocked();
    736             }
    737         } else if (wasAnimating) {
    738             mService.requestTraversalLocked();
    739         }
    740         if (WindowManagerService.DEBUG_WINDOW_TRACE) {
    741             Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
    742                 + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
    743                 + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
    744                 + Integer.toHexString(mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY)));
    745         }
    746     }
    747 
    748     WindowState mCurrentFocus;
    749     void setCurrentFocus(final WindowState currentFocus) {
    750         mCurrentFocus = currentFocus;
    751     }
    752 
    753     void setDisplayDimensions(final int curWidth, final int curHeight,
    754                         final int appWidth, final int appHeight) {
    755         mDw = curWidth;
    756         mDh = curHeight;
    757         mInnerDw = appWidth;
    758         mInnerDh = appHeight;
    759     }
    760 
    761     boolean isDimmingLocked(int displayId) {
    762         return getDisplayContentsAnimatorLocked(displayId).mDimParams != null;
    763     }
    764 
    765     boolean isDimmingLocked(final WindowStateAnimator winAnimator) {
    766         DimAnimator.Parameters dimParams =
    767                 getDisplayContentsAnimatorLocked(winAnimator.mWin.getDisplayId()).mDimParams;
    768         return dimParams != null && dimParams.mDimWinAnimator == winAnimator;
    769     }
    770 
    771     static String bulkUpdateParamsToString(int bulkUpdateParams) {
    772         StringBuilder builder = new StringBuilder(128);
    773         if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
    774             builder.append(" UPDATE_ROTATION");
    775         }
    776         if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
    777             builder.append(" WALLPAPER_MAY_CHANGE");
    778         }
    779         if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
    780             builder.append(" FORCE_HIDING_CHANGED");
    781         }
    782         if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
    783             builder.append(" ORIENTATION_CHANGE_COMPLETE");
    784         }
    785         if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
    786             builder.append(" TURN_ON_SCREEN");
    787         }
    788         return builder.toString();
    789     }
    790 
    791     public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
    792         final String subPrefix = "  " + prefix;
    793         final String subSubPrefix = "  " + subPrefix;
    794 
    795         boolean needSep = false;
    796         if (mAppAnimators.size() > 0) {
    797             needSep = true;
    798             pw.println("  App Animators:");
    799             for (int i=mAppAnimators.size()-1; i>=0; i--) {
    800                 AppWindowAnimator anim = mAppAnimators.get(i);
    801                 pw.print(prefix); pw.print("App Animator #"); pw.print(i);
    802                         pw.print(' '); pw.print(anim);
    803                 if (dumpAll) {
    804                     pw.println(':');
    805                     anim.dump(pw, subPrefix, dumpAll);
    806                 } else {
    807                     pw.println();
    808                 }
    809             }
    810         }
    811         if (mWallpaperTokens.size() > 0) {
    812             if (needSep) {
    813                 pw.println();
    814             }
    815             needSep = true;
    816             pw.print(prefix); pw.println("Wallpaper tokens:");
    817             for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
    818                 WindowToken token = mWallpaperTokens.get(i);
    819                 pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
    820                         pw.print(' '); pw.print(token);
    821                 if (dumpAll) {
    822                     pw.println(':');
    823                     token.dump(pw, subPrefix);
    824                 } else {
    825                     pw.println();
    826                 }
    827             }
    828         }
    829 
    830         if (needSep) {
    831             pw.println();
    832         }
    833         for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
    834             pw.print(prefix); pw.print("DisplayContentsAnimator #");
    835                     pw.print(mDisplayContentsAnimators.keyAt(i));
    836                     pw.println(":");
    837             DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
    838             for (int j=0; j<displayAnimator.mWinAnimators.size(); j++) {
    839                 WindowStateAnimator wanim = displayAnimator.mWinAnimators.get(j);
    840                 pw.print(subPrefix); pw.print("Window #"); pw.print(j);
    841                         pw.print(": "); pw.println(wanim);
    842             }
    843             if (displayAnimator.mWindowAnimationBackgroundSurface != null) {
    844                 if (dumpAll || displayAnimator.mWindowAnimationBackgroundSurface.mDimShown) {
    845                     pw.print(subPrefix); pw.println("mWindowAnimationBackgroundSurface:");
    846                     displayAnimator.mWindowAnimationBackgroundSurface.printTo(subSubPrefix, pw);
    847                 }
    848             }
    849             if (displayAnimator.mDimAnimator != null) {
    850                 if (dumpAll || displayAnimator.mDimAnimator.mDimShown) {
    851                     pw.print(subPrefix); pw.println("mDimAnimator:");
    852                     displayAnimator.mDimAnimator.printTo(subSubPrefix, pw);
    853                 }
    854             } else if (dumpAll) {
    855                 pw.print(subPrefix); pw.println("no DimAnimator ");
    856             }
    857             if (displayAnimator.mDimParams != null) {
    858                 pw.print(subPrefix); pw.println("mDimParams:");
    859                 displayAnimator.mDimParams.printTo(subSubPrefix, pw);
    860             } else if (dumpAll) {
    861                 pw.print(subPrefix); pw.println("no DimParams ");
    862             }
    863             if (displayAnimator.mScreenRotationAnimation != null) {
    864                 pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
    865                 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
    866             } else if (dumpAll) {
    867                 pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
    868             }
    869         }
    870 
    871         pw.println();
    872 
    873         if (dumpAll) {
    874             pw.print(prefix); pw.print("mAnimTransactionSequence=");
    875                     pw.print(mAnimTransactionSequence);
    876                     pw.print(" mForceHiding="); pw.println(forceHidingToString());
    877             pw.print(prefix); pw.print("mCurrentTime=");
    878                     pw.println(TimeUtils.formatUptime(mCurrentTime));
    879             pw.print(prefix); pw.print("mDw=");
    880                     pw.print(mDw); pw.print(" mDh="); pw.print(mDh);
    881                     pw.print(" mInnerDw="); pw.print(mInnerDw);
    882                     pw.print(" mInnerDh="); pw.println(mInnerDh);
    883         }
    884         if (mBulkUpdateParams != 0) {
    885             pw.print(prefix); pw.print("mBulkUpdateParams=0x");
    886                     pw.print(Integer.toHexString(mBulkUpdateParams));
    887                     pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
    888         }
    889         if (mPendingActions != 0) {
    890             pw.print(prefix); pw.print("mPendingActions=0x");
    891                     pw.println(Integer.toHexString(mPendingActions));
    892         }
    893         if (mWindowDetachedWallpaper != null) {
    894             pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
    895                 pw.println(mWindowDetachedWallpaper);
    896         }
    897         pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget);
    898         pw.print(prefix); pw.print("mWpAppAnimator="); pw.println(mWpAppAnimator);
    899         if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
    900             pw.print(prefix); pw.print("mLowerWallpaperTarget=");
    901                     pw.println(mLowerWallpaperTarget);
    902             pw.print(prefix); pw.print("mUpperWallpaperTarget=");
    903                     pw.println(mUpperWallpaperTarget);
    904         }
    905         if (mUniverseBackground != null) {
    906             pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
    907                     pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
    908         }
    909     }
    910 
    911     void clearPendingActions() {
    912         synchronized (this) {
    913             mPendingActions = 0;
    914         }
    915     }
    916 
    917     void setPendingLayoutChanges(final int displayId, final int changes) {
    918         mPendingLayoutChanges.put(displayId, mPendingLayoutChanges.get(displayId) | changes);
    919     }
    920 
    921     void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) {
    922         // Used to track which displays layout changes have been done.
    923         SparseIntArray displays = new SparseIntArray();
    924         for (int i = appAnimator.mAllAppWinAnimators.size() - 1; i >= 0; i--) {
    925             WindowStateAnimator winAnimator = appAnimator.mAllAppWinAnimators.get(i);
    926             final int displayId = winAnimator.mWin.mDisplayContent.getDisplayId();
    927             if (displays.indexOfKey(displayId) < 0) {
    928                 setPendingLayoutChanges(displayId, changes);
    929                 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
    930                     mService.debugLayoutRepeats(s, mPendingLayoutChanges.get(displayId));
    931                 }
    932                 // Keep from processing this display again.
    933                 displays.put(displayId, changes);
    934             }
    935         }
    936     }
    937 
    938     private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
    939         DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
    940         if (displayAnimator == null) {
    941             displayAnimator = new DisplayContentsAnimator(displayId);
    942             mDisplayContentsAnimators.put(displayId, displayAnimator);
    943         }
    944         return displayAnimator;
    945     }
    946 
    947     void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
    948         getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
    949     }
    950 
    951     ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
    952         return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
    953     }
    954 
    955     private class DisplayContentsAnimator {
    956         WinAnimatorList mWinAnimators = new WinAnimatorList();
    957         DimAnimator mDimAnimator = null;
    958         DimAnimator.Parameters mDimParams = null;
    959         DimSurface mWindowAnimationBackgroundSurface = null;
    960         ScreenRotationAnimation mScreenRotationAnimation = null;
    961 
    962         public DisplayContentsAnimator(int displayId) {
    963             mDimAnimator = new DimAnimator(mService.mFxSession, displayId);
    964             mWindowAnimationBackgroundSurface =
    965                     new DimSurface(mService.mFxSession, displayId);
    966         }
    967     }
    968 }
    969