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