• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_DISMISS_KEYGUARD;
20 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
21 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
22 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
23 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
24 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
25 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
26 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
27 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
28 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
29 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
30 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
31 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
32 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
33 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
34 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
35 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
36 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
37 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
38 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
39 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
40 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
41 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
42 import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
43 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
44 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
45 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
46 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
47 
48 import android.content.Context;
49 import android.os.Trace;
50 import android.util.Slog;
51 import android.util.SparseArray;
52 import android.util.TimeUtils;
53 import android.view.Choreographer;
54 import android.view.Display;
55 import android.view.SurfaceControl;
56 import android.view.WindowManagerPolicy;
57 import android.view.animation.AlphaAnimation;
58 import android.view.animation.Animation;
59 
60 import java.io.PrintWriter;
61 import java.util.ArrayList;
62 
63 /**
64  * Singleton class that carries out the animations and Surface operations in a separate task
65  * on behalf of WindowManagerService.
66  */
67 public class WindowAnimator {
68     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowAnimator" : TAG_WM;
69 
70     /** How long to give statusbar to clear the private keyguard flag when animating out */
71     private static final long KEYGUARD_ANIM_TIMEOUT_MS = 1000;
72 
73     final WindowManagerService mService;
74     final Context mContext;
75     final WindowManagerPolicy mPolicy;
76     private final WindowSurfacePlacer mWindowPlacerLocked;
77 
78     /** Is any window animating? */
79     private boolean mAnimating;
80 
81     /** Is any app window animating? */
82     boolean mAppWindowAnimating;
83 
84     final Choreographer.FrameCallback mAnimationFrameCallback;
85 
86     /** Time of current animation step. Reset on each iteration */
87     long mCurrentTime;
88 
89     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
90      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
91     private int mAnimTransactionSequence;
92 
93     /** Window currently running an animation that has requested it be detached
94      * from the wallpaper.  This means we need to ensure the wallpaper is
95      * visible behind it in case it animates in a way that would allow it to be
96      * seen. If multiple windows satisfy this, use the lowest window. */
97     WindowState mWindowDetachedWallpaper = null;
98 
99     int mBulkUpdateParams = 0;
100     Object mLastWindowFreezeSource;
101 
102     SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
103 
104     boolean mInitialized = false;
105 
106     boolean mKeyguardGoingAway;
107     int mKeyguardGoingAwayFlags;
108 
109     /** Use one animation for all entering activities after keyguard is dismissed. */
110     Animation mPostKeyguardExitAnimation;
111 
112     // forceHiding states.
113     static final int KEYGUARD_NOT_SHOWN     = 0;
114     static final int KEYGUARD_SHOWN         = 1;
115     static final int KEYGUARD_ANIMATING_OUT = 2;
116     int mForceHiding = KEYGUARD_NOT_SHOWN;
117 
118     // When set to true the animator will go over all windows after an animation frame is posted and
119     // check if some got replaced and can be removed.
120     private boolean mRemoveReplacedWindows = false;
121 
122     private final AppTokenList mTmpExitingAppTokens = new AppTokenList();
123 
forceHidingToString()124     private String forceHidingToString() {
125         switch (mForceHiding) {
126             case KEYGUARD_NOT_SHOWN:    return "KEYGUARD_NOT_SHOWN";
127             case KEYGUARD_SHOWN:        return "KEYGUARD_SHOWN";
128             case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
129             default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
130         }
131     }
132 
WindowAnimator(final WindowManagerService service)133     WindowAnimator(final WindowManagerService service) {
134         mService = service;
135         mContext = service.mContext;
136         mPolicy = service.mPolicy;
137         mWindowPlacerLocked = service.mWindowPlacerLocked;
138 
139         mAnimationFrameCallback = new Choreographer.FrameCallback() {
140             public void doFrame(long frameTimeNs) {
141                 synchronized (mService.mWindowMap) {
142                     mService.mAnimationScheduled = false;
143                     animateLocked(frameTimeNs);
144                 }
145             }
146         };
147     }
148 
addDisplayLocked(final int displayId)149     void addDisplayLocked(final int displayId) {
150         // Create the DisplayContentsAnimator object by retrieving it.
151         getDisplayContentsAnimatorLocked(displayId);
152         if (displayId == Display.DEFAULT_DISPLAY) {
153             mInitialized = true;
154         }
155     }
156 
removeDisplayLocked(final int displayId)157     void removeDisplayLocked(final int displayId) {
158         final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
159         if (displayAnimator != null) {
160             if (displayAnimator.mScreenRotationAnimation != null) {
161                 displayAnimator.mScreenRotationAnimation.kill();
162                 displayAnimator.mScreenRotationAnimation = null;
163             }
164         }
165 
166         mDisplayContentsAnimators.delete(displayId);
167     }
168 
updateAppWindowsLocked(int displayId)169     private void updateAppWindowsLocked(int displayId) {
170         ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks();
171         for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
172             final TaskStack stack = stacks.get(stackNdx);
173             final ArrayList<Task> tasks = stack.getTasks();
174             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
175                 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
176                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
177                     final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
178                     appAnimator.wasAnimating = appAnimator.animating;
179                     if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
180                         appAnimator.animating = true;
181                         setAnimating(true);
182                         mAppWindowAnimating = true;
183                     } else if (appAnimator.wasAnimating) {
184                         // stopped animating, do one more pass through the layout
185                         setAppLayoutChanges(appAnimator,
186                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
187                                 "appToken " + appAnimator.mAppToken + " done", displayId);
188                         if (DEBUG_ANIM) Slog.v(TAG,
189                                 "updateWindowsApps...: done animating " + appAnimator.mAppToken);
190                     }
191                 }
192             }
193 
194             mTmpExitingAppTokens.clear();
195             mTmpExitingAppTokens.addAll(stack.mExitingAppTokens);
196 
197             final int exitingCount = mTmpExitingAppTokens.size();
198             for (int i = 0; i < exitingCount; i++) {
199                 final AppWindowAnimator appAnimator = mTmpExitingAppTokens.get(i).mAppAnimator;
200                 // stepAnimation can trigger finishExit->removeWindowInnerLocked
201                 // ->performSurfacePlacement
202                 // performSurfacePlacement will directly manipulate the mExitingAppTokens list
203                 // so we need to iterate over a copy and check for modifications.
204                 if (!stack.mExitingAppTokens.contains(appAnimator)) {
205                     continue;
206                 }
207                 appAnimator.wasAnimating = appAnimator.animating;
208                 if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
209                     setAnimating(true);
210                     mAppWindowAnimating = true;
211                 } else if (appAnimator.wasAnimating) {
212                     // stopped animating, do one more pass through the layout
213                     setAppLayoutChanges(appAnimator,
214                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
215                             "exiting appToken " + appAnimator.mAppToken + " done", displayId);
216                     if (DEBUG_ANIM) Slog.v(TAG,
217                             "updateWindowsApps...: done animating exiting "
218                                     + appAnimator.mAppToken);
219                 }
220             }
221         }
222     }
223 
shouldForceHide(WindowState win)224     private boolean shouldForceHide(WindowState win) {
225         final WindowState imeTarget = mService.mInputMethodTarget;
226         final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
227                 ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
228                         || !mPolicy.canBeForceHidden(imeTarget, imeTarget.mAttrs));
229 
230         final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
231         final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
232                 null : winShowWhenLocked.mAppToken;
233 
234         boolean allowWhenLocked = false;
235         // Show IME over the keyguard if the target allows it
236         allowWhenLocked |= (win.mIsImWindow || imeTarget == win) && showImeOverKeyguard;
237         // Show SHOW_WHEN_LOCKED windows that turn on the screen
238         allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen;
239 
240         if (appShowWhenLocked != null) {
241             allowWhenLocked |= appShowWhenLocked == win.mAppToken
242                     // Show all SHOW_WHEN_LOCKED windows if some apps are shown over lockscreen
243                     || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
244                     // Show error dialogs over apps that dismiss keyguard.
245                     || (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
246         }
247 
248         // Allow showing a window that dismisses Keyguard if the policy allows it. This is used for
249         // when the policy knows that the Keyguard can be dismissed without user interaction to
250         // provide a smooth transition in that case.
251         allowWhenLocked |= (win.mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0
252                 && mPolicy.canShowDismissingWindowWhileLockedLw();
253 
254         // Only hide windows if the keyguard is active and not animating away.
255         boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded()
256                 && mForceHiding != KEYGUARD_ANIMATING_OUT;
257         boolean hideDockDivider = win.mAttrs.type == TYPE_DOCK_DIVIDER
258                 && win.getDisplayContent().getDockedStackLocked() == null;
259         return keyguardOn && !allowWhenLocked && (win.getDisplayId() == Display.DEFAULT_DISPLAY)
260                 || hideDockDivider;
261     }
262 
updateWindowsLocked(final int displayId)263     private void updateWindowsLocked(final int displayId) {
264         ++mAnimTransactionSequence;
265 
266         final WindowList windows = mService.getWindowListLocked(displayId);
267 
268         final boolean keyguardGoingAwayToShade =
269                 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0;
270         final boolean keyguardGoingAwayNoAnimation =
271                 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0;
272         final boolean keyguardGoingAwayWithWallpaper =
273                 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0;
274 
275         if (mKeyguardGoingAway) {
276             for (int i = windows.size() - 1; i >= 0; i--) {
277                 WindowState win = windows.get(i);
278                 if (!mPolicy.isKeyguardHostWindow(win.mAttrs)) {
279                     continue;
280                 }
281                 final WindowStateAnimator winAnimator = win.mWinAnimator;
282                 if ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
283                     if (!winAnimator.mAnimating) {
284                         if (DEBUG_KEYGUARD) Slog.d(TAG,
285                                 "updateWindowsLocked: creating delay animation");
286 
287                         // Create a new animation to delay until keyguard is gone on its own.
288                         winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
289                         winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
290                         winAnimator.mAnimationIsEntrance = false;
291                         winAnimator.mAnimationStartTime = -1;
292                         winAnimator.mKeyguardGoingAwayAnimation = true;
293                         winAnimator.mKeyguardGoingAwayWithWallpaper
294                                 = keyguardGoingAwayWithWallpaper;
295                     }
296                 } else {
297                     if (DEBUG_KEYGUARD) Slog.d(TAG,
298                             "updateWindowsLocked: StatusBar is no longer keyguard");
299                     mKeyguardGoingAway = false;
300                     winAnimator.clearAnimation();
301                 }
302                 break;
303             }
304         }
305 
306         mForceHiding = KEYGUARD_NOT_SHOWN;
307 
308         boolean wallpaperInUnForceHiding = false;
309         boolean startingInUnForceHiding = false;
310         ArrayList<WindowStateAnimator> unForceHiding = null;
311         WindowState wallpaper = null;
312         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
313         for (int i = windows.size() - 1; i >= 0; i--) {
314             WindowState win = windows.get(i);
315             WindowStateAnimator winAnimator = win.mWinAnimator;
316             final int flags = win.mAttrs.flags;
317             boolean canBeForceHidden = mPolicy.canBeForceHidden(win, win.mAttrs);
318             boolean shouldBeForceHidden = shouldForceHide(win);
319             if (winAnimator.hasSurface()) {
320                 final boolean wasAnimating = winAnimator.mWasAnimating;
321                 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
322                 winAnimator.mWasAnimating = nowAnimating;
323                 orAnimating(nowAnimating);
324 
325                 if (DEBUG_WALLPAPER) {
326                     Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
327                             ", nowAnimating=" + nowAnimating);
328                 }
329 
330                 if (wasAnimating && !winAnimator.mAnimating
331                         && wallpaperController.isWallpaperTarget(win)) {
332                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
333                     setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
334                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
335                     if (DEBUG_LAYOUT_REPEATS) {
336                         mWindowPlacerLocked.debugLayoutRepeats(
337                                 "updateWindowsAndWallpaperLocked 2",
338                                 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
339                     }
340                 }
341 
342                 if (mPolicy.isForceHiding(win.mAttrs)) {
343                     if (!wasAnimating && nowAnimating) {
344                         if (DEBUG_KEYGUARD || DEBUG_ANIM ||
345                                 DEBUG_VISIBILITY) Slog.v(TAG,
346                                 "Animation started that could impact force hide: " + win);
347                         mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
348                         setPendingLayoutChanges(displayId,
349                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
350                         if (DEBUG_LAYOUT_REPEATS) {
351                             mWindowPlacerLocked.debugLayoutRepeats(
352                                     "updateWindowsAndWallpaperLocked 3",
353                                     getPendingLayoutChanges(displayId));
354                         }
355                         mService.mFocusMayChange = true;
356                     } else if (mKeyguardGoingAway && !nowAnimating) {
357                         // Timeout!!
358                         Slog.e(TAG, "Timeout waiting for animation to startup");
359                         mPolicy.startKeyguardExitAnimation(0, 0);
360                         mKeyguardGoingAway = false;
361                     }
362                     if (win.isReadyForDisplay()) {
363                         if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) {
364                             mForceHiding = KEYGUARD_ANIMATING_OUT;
365                         } else {
366                             mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
367                         }
368                     }
369                     if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
370                             "Force hide " + forceHidingToString()
371                             + " hasSurface=" + win.mHasSurface
372                             + " policyVis=" + win.mPolicyVisibility
373                             + " destroying=" + win.mDestroying
374                             + " attHidden=" + win.mAttachedHidden
375                             + " vis=" + win.mViewVisibility
376                             + " hidden=" + win.mRootToken.hidden
377                             + " anim=" + win.mWinAnimator.mAnimation);
378                 } else if (canBeForceHidden) {
379                     if (shouldBeForceHidden) {
380                         if (!win.hideLw(false, false)) {
381                             // Was already hidden
382                             continue;
383                         }
384                         if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
385                                 "Now policy hidden: " + win);
386                     } else {
387                         boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
388                                 && !mPostKeyguardExitAnimation.hasEnded()
389                                 && !winAnimator.mKeyguardGoingAwayAnimation
390                                 && win.hasDrawnLw()
391                                 && win.mAttachedWindow == null
392                                 && !win.mIsImWindow
393                                 && displayId == Display.DEFAULT_DISPLAY;
394 
395                         // If the window is already showing and we don't need to apply an existing
396                         // Keyguard exit animation, skip.
397                         if (!win.showLw(false, false) && !applyExistingExitAnimation) {
398                             continue;
399                         }
400                         final boolean visibleNow = win.isVisibleNow();
401                         if (!visibleNow) {
402                             // Couldn't really show, must showLw() again when win becomes visible.
403                             win.hideLw(false, false);
404                             continue;
405                         }
406                         if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
407                                 "Now policy shown: " + win);
408                         if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
409                                 && win.mAttachedWindow == null) {
410                             if (unForceHiding == null) {
411                                 unForceHiding = new ArrayList<>();
412                             }
413                             unForceHiding.add(winAnimator);
414                             if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
415                                 wallpaperInUnForceHiding = true;
416                             }
417                             if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
418                                 startingInUnForceHiding = true;
419                             }
420                         } else if (applyExistingExitAnimation) {
421                             // We're already in the middle of an animation. Use the existing
422                             // animation to bring in this window.
423                             if (DEBUG_KEYGUARD) Slog.v(TAG,
424                                     "Applying existing Keyguard exit animation to new window: win="
425                                             + win);
426 
427                             Animation a = mPolicy.createForceHideEnterAnimation(false,
428                                     keyguardGoingAwayToShade);
429                             winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime(),
430                                     STACK_CLIP_BEFORE_ANIM);
431                             winAnimator.mKeyguardGoingAwayAnimation = true;
432                             winAnimator.mKeyguardGoingAwayWithWallpaper
433                                     = keyguardGoingAwayWithWallpaper;
434                         }
435                         final WindowState currentFocus = mService.mCurrentFocus;
436                         if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
437                             // We are showing on top of the current
438                             // focus, so re-evaluate focus to make
439                             // sure it is correct.
440                             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG,
441                                     "updateWindowsLocked: setting mFocusMayChange true");
442                             mService.mFocusMayChange = true;
443                         }
444                     }
445                     if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
446                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
447                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
448                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
449                         if (DEBUG_LAYOUT_REPEATS) {
450                             mWindowPlacerLocked.debugLayoutRepeats(
451                                     "updateWindowsAndWallpaperLocked 4",
452                                     getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
453                         }
454                     }
455                 }
456             }
457 
458             // If the window doesn't have a surface, the only thing we care about is the correct
459             // policy visibility.
460             else if (canBeForceHidden) {
461                 if (shouldBeForceHidden) {
462                     win.hideLw(false, false);
463                 } else {
464                     win.showLw(false, false);
465                 }
466             }
467 
468             final AppWindowToken atoken = win.mAppToken;
469             if (winAnimator.mDrawState == READY_TO_SHOW) {
470                 if (atoken == null || atoken.allDrawn) {
471                     if (winAnimator.performShowLocked()) {
472                         setPendingLayoutChanges(displayId,
473                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
474                         if (DEBUG_LAYOUT_REPEATS) {
475                             mWindowPlacerLocked.debugLayoutRepeats(
476                                     "updateWindowsAndWallpaperLocked 5",
477                                     getPendingLayoutChanges(displayId));
478                         }
479                     }
480                 }
481             }
482             final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
483             if (appAnimator != null && appAnimator.thumbnail != null) {
484                 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
485                     appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
486                     appAnimator.thumbnailLayer = 0;
487                 }
488                 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
489                     appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
490                 }
491             }
492             if (win.mIsWallpaper) {
493                 wallpaper = win;
494             }
495         } // end forall windows
496 
497         // If we have windows that are being show due to them no longer
498         // being force-hidden, apply the appropriate animation to them if animations are not
499         // disabled.
500         if (unForceHiding != null) {
501             if (!keyguardGoingAwayNoAnimation) {
502                 boolean first = true;
503                 for (int i=unForceHiding.size()-1; i>=0; i--) {
504                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
505                     Animation a = mPolicy.createForceHideEnterAnimation(
506                             wallpaperInUnForceHiding && !startingInUnForceHiding,
507                             keyguardGoingAwayToShade);
508                     if (a != null) {
509                         if (DEBUG_KEYGUARD) Slog.v(TAG,
510                                 "Starting keyguard exit animation on window " + winAnimator.mWin);
511                         winAnimator.setAnimation(a, STACK_CLIP_BEFORE_ANIM);
512                         winAnimator.mKeyguardGoingAwayAnimation = true;
513                         winAnimator.mKeyguardGoingAwayWithWallpaper
514                                 = keyguardGoingAwayWithWallpaper;
515                         if (first) {
516                             mPostKeyguardExitAnimation = a;
517                             mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
518                             first = false;
519                         }
520                     }
521                 }
522             } else if (mKeyguardGoingAway) {
523                 mPolicy.startKeyguardExitAnimation(mCurrentTime, 0 /* duration */);
524                 mKeyguardGoingAway = false;
525             }
526 
527 
528             // Wallpaper is going away in un-force-hide motion, animate it as well.
529             if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) {
530                 if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
531                 Animation a = mPolicy.createForceHideWallpaperExitAnimation(
532                         keyguardGoingAwayToShade);
533                 if (a != null) {
534                     wallpaper.mWinAnimator.setAnimation(a);
535                 }
536             }
537         }
538 
539         if (mPostKeyguardExitAnimation != null) {
540             // We're in the midst of a keyguard exit animation.
541             if (mKeyguardGoingAway) {
542                 mPolicy.startKeyguardExitAnimation(mCurrentTime +
543                         mPostKeyguardExitAnimation.getStartOffset(),
544                         mPostKeyguardExitAnimation.getDuration());
545                 mKeyguardGoingAway = false;
546             }
547             // mPostKeyguardExitAnimation might either be ended normally, cancelled, or "orphaned",
548             // meaning that the window it was running on was removed. We check for hasEnded() for
549             // ended normally and cancelled case, and check the time for the "orphaned" case.
550             else if (mPostKeyguardExitAnimation.hasEnded()
551                     || mCurrentTime - mPostKeyguardExitAnimation.getStartTime()
552                             > mPostKeyguardExitAnimation.getDuration()) {
553                 // Done with the animation, reset.
554                 if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations.");
555                 mPostKeyguardExitAnimation = null;
556             }
557         }
558     }
559 
updateWallpaperLocked(int displayId)560     private void updateWallpaperLocked(int displayId) {
561         mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
562 
563         final WindowList windows = mService.getWindowListLocked(displayId);
564         WindowState detachedWallpaper = null;
565 
566         for (int i = windows.size() - 1; i >= 0; i--) {
567             final WindowState win = windows.get(i);
568             WindowStateAnimator winAnimator = win.mWinAnimator;
569             if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
570                 continue;
571             }
572 
573             final int flags = win.mAttrs.flags;
574 
575             // If this window is animating, make a note that we have
576             // an animating window and take care of a request to run
577             // a detached wallpaper animation.
578             if (winAnimator.mAnimating) {
579                 if (winAnimator.mAnimation != null) {
580                     if ((flags & FLAG_SHOW_WALLPAPER) != 0
581                             && winAnimator.mAnimation.getDetachWallpaper()) {
582                         detachedWallpaper = win;
583                     }
584                     final int color = winAnimator.mAnimation.getBackgroundColor();
585                     if (color != 0) {
586                         final TaskStack stack = win.getStack();
587                         if (stack != null) {
588                             stack.setAnimationBackground(winAnimator, color);
589                         }
590                     }
591                 }
592                 setAnimating(true);
593             }
594 
595             // If this window's app token is running a detached wallpaper
596             // animation, make a note so we can ensure the wallpaper is
597             // displayed behind it.
598             final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
599             if (appAnimator != null && appAnimator.animation != null
600                     && appAnimator.animating) {
601                 if ((flags & FLAG_SHOW_WALLPAPER) != 0
602                         && appAnimator.animation.getDetachWallpaper()) {
603                     detachedWallpaper = win;
604                 }
605 
606                 final int color = appAnimator.animation.getBackgroundColor();
607                 if (color != 0) {
608                     final TaskStack stack = win.getStack();
609                     if (stack != null) {
610                         stack.setAnimationBackground(winAnimator, color);
611                     }
612                 }
613             }
614         } // end forall windows
615 
616         if (mWindowDetachedWallpaper != detachedWallpaper) {
617             if (DEBUG_WALLPAPER) Slog.v(TAG,
618                     "Detached wallpaper changed from " + mWindowDetachedWallpaper
619                     + " to " + detachedWallpaper);
620             mWindowDetachedWallpaper = detachedWallpaper;
621             mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
622         }
623     }
624 
625     /** See if any windows have been drawn, so they (and others associated with them) can now be
626      *  shown. */
testTokenMayBeDrawnLocked(int displayId)627     private void testTokenMayBeDrawnLocked(int displayId) {
628         // See if any windows have been drawn, so they (and others
629         // associated with them) can now be shown.
630         final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks();
631         final int numTasks = tasks.size();
632         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
633             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
634             final int numTokens = tokens.size();
635             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
636                 final AppWindowToken wtoken = tokens.get(tokenNdx);
637                 AppWindowAnimator appAnimator = wtoken.mAppAnimator;
638                 final boolean allDrawn = wtoken.allDrawn;
639                 if (allDrawn != appAnimator.allDrawn) {
640                     appAnimator.allDrawn = allDrawn;
641                     if (allDrawn) {
642                         // The token has now changed state to having all
643                         // windows shown...  what to do, what to do?
644                         if (appAnimator.freezingScreen) {
645                             appAnimator.showAllWindowsLocked();
646                             mService.unsetAppFreezingScreenLocked(wtoken, false, true);
647                             if (DEBUG_ORIENTATION) Slog.i(TAG,
648                                     "Setting mOrientationChangeComplete=true because wtoken "
649                                     + wtoken + " numInteresting=" + wtoken.numInterestingWindows
650                                     + " numDrawn=" + wtoken.numDrawnWindows);
651                             // This will set mOrientationChangeComplete and cause a pass through
652                             // layout.
653                             setAppLayoutChanges(appAnimator,
654                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
655                                     "testTokenMayBeDrawnLocked: freezingScreen", displayId);
656                         } else {
657                             setAppLayoutChanges(appAnimator,
658                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
659                                     "testTokenMayBeDrawnLocked", displayId);
660 
661                             // We can now show all of the drawn windows!
662                             if (!mService.mOpeningApps.contains(wtoken)) {
663                                 orAnimating(appAnimator.showAllWindowsLocked());
664                             }
665                         }
666                     }
667                 }
668             }
669         }
670     }
671 
672 
673     /** Locked on mService.mWindowMap. */
animateLocked(long frameTimeNs)674     private void animateLocked(long frameTimeNs) {
675         if (!mInitialized) {
676             return;
677         }
678 
679         mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
680         mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
681         boolean wasAnimating = mAnimating;
682         setAnimating(false);
683         mAppWindowAnimating = false;
684         if (DEBUG_WINDOW_TRACE) {
685             Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
686         }
687 
688         if (SHOW_TRANSACTIONS) Slog.i(
689                 TAG, ">>> OPEN TRANSACTION animateLocked");
690         SurfaceControl.openTransaction();
691         SurfaceControl.setAnimationTransaction();
692         try {
693             final int numDisplays = mDisplayContentsAnimators.size();
694             for (int i = 0; i < numDisplays; i++) {
695                 final int displayId = mDisplayContentsAnimators.keyAt(i);
696                 updateAppWindowsLocked(displayId);
697                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
698 
699                 final ScreenRotationAnimation screenRotationAnimation =
700                         displayAnimator.mScreenRotationAnimation;
701                 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
702                     if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
703                         setAnimating(true);
704                     } else {
705                         mBulkUpdateParams |= SET_UPDATE_ROTATION;
706                         screenRotationAnimation.kill();
707                         displayAnimator.mScreenRotationAnimation = null;
708 
709                         //TODO (multidisplay): Accessibility supported only for the default display.
710                         if (mService.mAccessibilityController != null
711                                 && displayId == Display.DEFAULT_DISPLAY) {
712                             // We just finished rotation animation which means we did not
713                             // anounce the rotation and waited for it to end, announce now.
714                             mService.mAccessibilityController.onRotationChangedLocked(
715                                     mService.getDefaultDisplayContentLocked(), mService.mRotation);
716                         }
717                     }
718                 }
719 
720                 // Update animations of all applications, including those
721                 // associated with exiting/removed apps
722                 updateWindowsLocked(displayId);
723                 updateWallpaperLocked(displayId);
724 
725                 final WindowList windows = mService.getWindowListLocked(displayId);
726                 final int N = windows.size();
727                 for (int j = 0; j < N; j++) {
728                     windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
729                 }
730             }
731 
732             for (int i = 0; i < numDisplays; i++) {
733                 final int displayId = mDisplayContentsAnimators.keyAt(i);
734 
735                 testTokenMayBeDrawnLocked(displayId);
736 
737                 final ScreenRotationAnimation screenRotationAnimation =
738                         mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
739                 if (screenRotationAnimation != null) {
740                     screenRotationAnimation.updateSurfacesInTransaction();
741                 }
742 
743                 orAnimating(mService.getDisplayContentLocked(displayId).animateDimLayers());
744                 orAnimating(mService.getDisplayContentLocked(displayId).getDockedDividerController()
745                         .animate(mCurrentTime));
746                 //TODO (multidisplay): Magnification is supported only for the default display.
747                 if (mService.mAccessibilityController != null
748                         && displayId == Display.DEFAULT_DISPLAY) {
749                     mService.mAccessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
750                 }
751             }
752 
753             if (mService.mDragState != null) {
754                 mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
755             }
756 
757             if (mAnimating) {
758                 mService.scheduleAnimationLocked();
759             }
760 
761             if (mService.mWatermark != null) {
762                 mService.mWatermark.drawIfNeeded();
763             }
764         } catch (RuntimeException e) {
765             Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
766         } finally {
767             SurfaceControl.closeTransaction();
768             if (SHOW_TRANSACTIONS) Slog.i(
769                     TAG, "<<< CLOSE TRANSACTION animateLocked");
770         }
771 
772         boolean hasPendingLayoutChanges = false;
773         final int numDisplays = mService.mDisplayContents.size();
774         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
775             final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
776             final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
777             if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
778                 mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
779             }
780             if (pendingChanges != 0) {
781                 hasPendingLayoutChanges = true;
782             }
783         }
784 
785         boolean doRequest = false;
786         if (mBulkUpdateParams != 0) {
787             doRequest = mWindowPlacerLocked.copyAnimToLayoutParamsLocked();
788         }
789 
790         if (hasPendingLayoutChanges || doRequest) {
791             mWindowPlacerLocked.requestTraversal();
792         }
793 
794         if (mAnimating && !wasAnimating && Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
795             Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
796         }
797 
798         if (!mAnimating && wasAnimating) {
799             mWindowPlacerLocked.requestTraversal();
800             if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
801                 Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
802             }
803         }
804 
805         if (mRemoveReplacedWindows) {
806             removeReplacedWindowsLocked();
807         }
808 
809         mService.stopUsingSavedSurfaceLocked();
810         mService.destroyPreservedSurfaceLocked();
811         mService.mWindowPlacerLocked.destroyPendingSurfaces();
812 
813         if (DEBUG_WINDOW_TRACE) {
814             Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
815                     + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
816                     + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
817                     + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
818         }
819     }
820 
removeReplacedWindowsLocked()821     private void removeReplacedWindowsLocked() {
822         if (SHOW_TRANSACTIONS) Slog.i(
823                 TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
824         SurfaceControl.openTransaction();
825         try {
826             for (int i = mService.mDisplayContents.size() - 1; i >= 0; i--) {
827                 DisplayContent display = mService.mDisplayContents.valueAt(i);
828                 final WindowList windows = mService.getWindowListLocked(display.getDisplayId());
829                 for (int j = windows.size() - 1; j >= 0; j--) {
830                     windows.get(j).maybeRemoveReplacedWindow();
831                 }
832             }
833         } finally {
834             SurfaceControl.closeTransaction();
835             if (SHOW_TRANSACTIONS) Slog.i(
836                     TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
837         }
838         mRemoveReplacedWindows = false;
839     }
840 
bulkUpdateParamsToString(int bulkUpdateParams)841     private static String bulkUpdateParamsToString(int bulkUpdateParams) {
842         StringBuilder builder = new StringBuilder(128);
843         if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) {
844             builder.append(" UPDATE_ROTATION");
845         }
846         if ((bulkUpdateParams & WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE) != 0) {
847             builder.append(" WALLPAPER_MAY_CHANGE");
848         }
849         if ((bulkUpdateParams & WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED) != 0) {
850             builder.append(" FORCE_HIDING_CHANGED");
851         }
852         if ((bulkUpdateParams & WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
853             builder.append(" ORIENTATION_CHANGE_COMPLETE");
854         }
855         if ((bulkUpdateParams & WindowSurfacePlacer.SET_TURN_ON_SCREEN) != 0) {
856             builder.append(" TURN_ON_SCREEN");
857         }
858         return builder.toString();
859     }
860 
dumpLocked(PrintWriter pw, String prefix, boolean dumpAll)861     public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
862         final String subPrefix = "  " + prefix;
863         final String subSubPrefix = "  " + subPrefix;
864 
865         for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
866             pw.print(prefix); pw.print("DisplayContentsAnimator #");
867                     pw.print(mDisplayContentsAnimators.keyAt(i));
868                     pw.println(":");
869             DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
870             final WindowList windows =
871                     mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i));
872             final int N = windows.size();
873             for (int j = 0; j < N; j++) {
874                 WindowStateAnimator wanim = windows.get(j).mWinAnimator;
875                 pw.print(subPrefix); pw.print("Window #"); pw.print(j);
876                         pw.print(": "); pw.println(wanim);
877             }
878             if (displayAnimator.mScreenRotationAnimation != null) {
879                 pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
880                 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
881             } else if (dumpAll) {
882                 pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
883             }
884             pw.println();
885         }
886 
887         pw.println();
888 
889         if (dumpAll) {
890             pw.print(prefix); pw.print("mAnimTransactionSequence=");
891                     pw.print(mAnimTransactionSequence);
892                     pw.print(" mForceHiding="); pw.println(forceHidingToString());
893             pw.print(prefix); pw.print("mCurrentTime=");
894                     pw.println(TimeUtils.formatUptime(mCurrentTime));
895         }
896         if (mBulkUpdateParams != 0) {
897             pw.print(prefix); pw.print("mBulkUpdateParams=0x");
898                     pw.print(Integer.toHexString(mBulkUpdateParams));
899                     pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
900         }
901         if (mWindowDetachedWallpaper != null) {
902             pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
903                 pw.println(mWindowDetachedWallpaper);
904         }
905     }
906 
getPendingLayoutChanges(final int displayId)907     int getPendingLayoutChanges(final int displayId) {
908         if (displayId < 0) {
909             return 0;
910         }
911         final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
912         return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
913     }
914 
setPendingLayoutChanges(final int displayId, final int changes)915     void setPendingLayoutChanges(final int displayId, final int changes) {
916         if (displayId < 0) {
917             return;
918         }
919         final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
920         if (displayContent != null) {
921             displayContent.pendingLayoutChanges |= changes;
922         }
923     }
924 
setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason, final int displayId)925     void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason,
926             final int displayId) {
927         WindowList windows = appAnimator.mAppToken.allAppWindows;
928         for (int i = windows.size() - 1; i >= 0; i--) {
929             if (displayId == windows.get(i).getDisplayId()) {
930                 setPendingLayoutChanges(displayId, changes);
931                 if (DEBUG_LAYOUT_REPEATS) {
932                     mWindowPlacerLocked.debugLayoutRepeats(reason,
933                             getPendingLayoutChanges(displayId));
934                 }
935                 break;
936             }
937         }
938     }
939 
getDisplayContentsAnimatorLocked(int displayId)940     private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
941         DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
942         if (displayAnimator == null) {
943             displayAnimator = new DisplayContentsAnimator();
944             mDisplayContentsAnimators.put(displayId, displayAnimator);
945         }
946         return displayAnimator;
947     }
948 
setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation)949     void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
950         if (displayId >= 0) {
951             getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
952         }
953     }
954 
getScreenRotationAnimationLocked(int displayId)955     ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
956         if (displayId < 0) {
957             return null;
958         }
959         return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
960     }
961 
requestRemovalOfReplacedWindows(WindowState win)962     void requestRemovalOfReplacedWindows(WindowState win) {
963         mRemoveReplacedWindows = true;
964     }
965 
966     private class DisplayContentsAnimator {
967         ScreenRotationAnimation mScreenRotationAnimation = null;
968     }
969 
isAnimating()970     boolean isAnimating() {
971         return mAnimating;
972     }
973 
setAnimating(boolean animating)974     void setAnimating(boolean animating) {
975         mAnimating = animating;
976     }
977 
orAnimating(boolean animating)978     void orAnimating(boolean animating) {
979         mAnimating |= animating;
980     }
981 }
982