2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.wm;
19 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
20 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
21 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
22 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
23 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
24 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
25 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
26 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
27 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
28 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
29 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
30 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
31 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
32 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
33 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
34 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
35 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
36 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
37 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
38 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
39 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
40 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
41 import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
42 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
43 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
44 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
45 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
47 import android.content.Context;
48 import android.os.Trace;
49 import android.util.Slog;
50 import android.util.SparseArray;
51 import android.util.TimeUtils;
52 import android.view.Choreographer;
53 import android.view.Display;
54 import android.view.SurfaceControl;
55 import android.view.WindowManagerPolicy;
56 import android.view.animation.AlphaAnimation;
57 import android.view.animation.Animation;
59 import java.io.PrintWriter;
60 import java.util.ArrayList;
63 * Singleton class that carries out the animations and Surface operations in a separate task
64 * on behalf of WindowManagerService.
66 public class WindowAnimator {
67 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowAnimator" : TAG_WM;
69 /** How long to give statusbar to clear the private keyguard flag when animating out */
70 private static final long KEYGUARD_ANIM_TIMEOUT_MS = 1000;
72 final WindowManagerService mService;
73 final Context mContext;
74 final WindowManagerPolicy mPolicy;
75 private final WindowSurfacePlacer mWindowPlacerLocked;
77 /** Is any window animating? */
78 private boolean mAnimating;
80 /** Is any app window animating? */
81 boolean mAppWindowAnimating;
83 final Choreographer.FrameCallback mAnimationFrameCallback;
85 /** Time of current animation step. Reset on each iteration */
88 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
89 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
90 private int mAnimTransactionSequence;
92 /** Window currently running an animation that has requested it be detached
93 * from the wallpaper. This means we need to ensure the wallpaper is
94 * visible behind it in case it animates in a way that would allow it to be
95 * seen. If multiple windows satisfy this, use the lowest window. */
96 WindowState mWindowDetachedWallpaper = null;
98 int mBulkUpdateParams = 0;
99 Object mLastWindowFreezeSource;
101 SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
103 boolean mInitialized = false;
105 boolean mKeyguardGoingAway;
106 int mKeyguardGoingAwayFlags;
108 /** Use one animation for all entering activities after keyguard is dismissed. */
109 Animation mPostKeyguardExitAnimation;
111 // forceHiding states.
112 static final int KEYGUARD_NOT_SHOWN = 0;
113 static final int KEYGUARD_SHOWN = 1;
114 static final int KEYGUARD_ANIMATING_OUT = 2;
115 int mForceHiding = KEYGUARD_NOT_SHOWN;
117 // When set to true the animator will go over all windows after an animation frame is posted and
118 // check if some got replaced and can be removed.
119 private boolean mRemoveReplacedWindows = false;
121 private String forceHidingToString() {
122 switch (mForceHiding) {
123 case KEYGUARD_NOT_SHOWN: return "KEYGUARD_NOT_SHOWN";
124 case KEYGUARD_SHOWN: return "KEYGUARD_SHOWN";
125 case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
126 default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
130 WindowAnimator(final WindowManagerService service) {
132 mContext = service.mContext;
133 mPolicy = service.mPolicy;
134 mWindowPlacerLocked = service.mWindowPlacerLocked;
136 mAnimationFrameCallback = new Choreographer.FrameCallback() {
137 public void doFrame(long frameTimeNs) {
138 synchronized (mService.mWindowMap) {
139 mService.mAnimationScheduled = false;
140 animateLocked(frameTimeNs);
146 void addDisplayLocked(final int displayId) {
147 // Create the DisplayContentsAnimator object by retrieving it.
148 getDisplayContentsAnimatorLocked(displayId);
149 if (displayId == Display.DEFAULT_DISPLAY) {
154 void removeDisplayLocked(final int displayId) {
155 final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
156 if (displayAnimator != null) {
157 if (displayAnimator.mScreenRotationAnimation != null) {
158 displayAnimator.mScreenRotationAnimation.kill();
159 displayAnimator.mScreenRotationAnimation = null;
163 mDisplayContentsAnimators.delete(displayId);
166 private void updateAppWindowsLocked(int displayId) {
167 ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks();
168 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
169 final TaskStack stack = stacks.get(stackNdx);
170 final ArrayList<Task> tasks = stack.getTasks();
171 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
172 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
173 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
174 final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
175 appAnimator.wasAnimating = appAnimator.animating;
176 if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
177 appAnimator.animating = true;
179 mAppWindowAnimating = true;
180 } else if (appAnimator.wasAnimating) {
181 // stopped animating, do one more pass through the layout
182 setAppLayoutChanges(appAnimator,
183 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
184 "appToken " + appAnimator.mAppToken + " done", displayId);
185 if (DEBUG_ANIM) Slog.v(TAG,
186 "updateWindowsApps...: done animating " + appAnimator.mAppToken);
191 final AppTokenList exitingAppTokens = stack.mExitingAppTokens;
192 final int exitingCount = exitingAppTokens.size();
193 for (int i = 0; i < exitingCount; i++) {
194 final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
195 appAnimator.wasAnimating = appAnimator.animating;
196 if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
198 mAppWindowAnimating = true;
199 } else if (appAnimator.wasAnimating) {
200 // stopped animating, do one more pass through the layout
201 setAppLayoutChanges(appAnimator,
202 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
203 "exiting appToken " + appAnimator.mAppToken + " done", displayId);
204 if (DEBUG_ANIM) Slog.v(TAG,
205 "updateWindowsApps...: done animating exiting "
206 + appAnimator.mAppToken);
212 private boolean shouldForceHide(WindowState win) {
213 final WindowState imeTarget = mService.mInputMethodTarget;
214 final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
215 ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
216 || !mPolicy.canBeForceHidden(imeTarget, imeTarget.mAttrs));
218 final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
219 final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
220 null : winShowWhenLocked.mAppToken;
222 boolean allowWhenLocked = false;
223 // Show IME over the keyguard if the target allows it
224 allowWhenLocked |= (win.mIsImWindow || imeTarget == win) && showImeOverKeyguard;
225 // Show SHOW_WHEN_LOCKED windows that turn on the screen
226 allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen;
228 if (appShowWhenLocked != null) {
229 allowWhenLocked |= appShowWhenLocked == win.mAppToken
230 // Show all SHOW_WHEN_LOCKED windows if some apps are shown over lockscreen
231 || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
232 // Show error dialogs over apps that dismiss keyguard.
233 || (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
236 // Only hide windows if the keyguard is active and not animating away.
237 boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded()
238 && mForceHiding != KEYGUARD_ANIMATING_OUT;
239 boolean hideDockDivider = win.mAttrs.type == TYPE_DOCK_DIVIDER
240 && win.getDisplayContent().getDockedStackLocked() == null;
241 return keyguardOn && !allowWhenLocked && (win.getDisplayId() == Display.DEFAULT_DISPLAY)
245 private void updateWindowsLocked(final int displayId) {
246 ++mAnimTransactionSequence;
248 final WindowList windows = mService.getWindowListLocked(displayId);
250 final boolean keyguardGoingAwayToShade =
251 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0;
252 final boolean keyguardGoingAwayNoAnimation =
253 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0;
254 final boolean keyguardGoingAwayWithWallpaper =
255 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0;
257 if (mKeyguardGoingAway) {
258 for (int i = windows.size() - 1; i >= 0; i--) {
259 WindowState win = windows.get(i);
260 if (!mPolicy.isKeyguardHostWindow(win.mAttrs)) {
263 final WindowStateAnimator winAnimator = win.mWinAnimator;
264 if ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
265 if (!winAnimator.mAnimating) {
266 if (DEBUG_KEYGUARD) Slog.d(TAG,
267 "updateWindowsLocked: creating delay animation");
269 // Create a new animation to delay until keyguard is gone on its own.
270 winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
271 winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
272 winAnimator.mAnimationIsEntrance = false;
273 winAnimator.mAnimationStartTime = -1;
274 winAnimator.mKeyguardGoingAwayAnimation = true;
275 winAnimator.mKeyguardGoingAwayWithWallpaper
276 = keyguardGoingAwayWithWallpaper;
279 if (DEBUG_KEYGUARD) Slog.d(TAG,
280 "updateWindowsLocked: StatusBar is no longer keyguard");
281 mKeyguardGoingAway = false;
282 winAnimator.clearAnimation();
288 mForceHiding = KEYGUARD_NOT_SHOWN;
290 boolean wallpaperInUnForceHiding = false;
291 boolean startingInUnForceHiding = false;
292 ArrayList<WindowStateAnimator> unForceHiding = null;
293 WindowState wallpaper = null;
294 final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
295 for (int i = windows.size() - 1; i >= 0; i--) {
296 WindowState win = windows.get(i);
297 WindowStateAnimator winAnimator = win.mWinAnimator;
298 final int flags = win.mAttrs.flags;
299 boolean canBeForceHidden = mPolicy.canBeForceHidden(win, win.mAttrs);
300 boolean shouldBeForceHidden = shouldForceHide(win);
301 if (winAnimator.hasSurface()) {
302 final boolean wasAnimating = winAnimator.mWasAnimating;
303 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
304 winAnimator.mWasAnimating = nowAnimating;
305 orAnimating(nowAnimating);
307 if (DEBUG_WALLPAPER) {
308 Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
309 ", nowAnimating=" + nowAnimating);
312 if (wasAnimating && !winAnimator.mAnimating
313 && wallpaperController.isWallpaperTarget(win)) {
314 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
315 setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
316 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
317 if (DEBUG_LAYOUT_REPEATS) {
318 mWindowPlacerLocked.debugLayoutRepeats(
319 "updateWindowsAndWallpaperLocked 2",
320 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
324 if (mPolicy.isForceHiding(win.mAttrs)) {
325 if (!wasAnimating && nowAnimating) {
326 if (DEBUG_KEYGUARD || DEBUG_ANIM ||
327 DEBUG_VISIBILITY) Slog.v(TAG,
328 "Animation started that could impact force hide: " + win);
329 mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
330 setPendingLayoutChanges(displayId,
331 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
332 if (DEBUG_LAYOUT_REPEATS) {
333 mWindowPlacerLocked.debugLayoutRepeats(
334 "updateWindowsAndWallpaperLocked 3",
335 getPendingLayoutChanges(displayId));
337 mService.mFocusMayChange = true;
338 } else if (mKeyguardGoingAway && !nowAnimating) {
340 Slog.e(TAG, "Timeout waiting for animation to startup");
341 mPolicy.startKeyguardExitAnimation(0, 0);
342 mKeyguardGoingAway = false;
344 if (win.isReadyForDisplay()) {
345 if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) {
346 mForceHiding = KEYGUARD_ANIMATING_OUT;
348 mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
351 if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
352 "Force hide " + forceHidingToString()
353 + " hasSurface=" + win.mHasSurface
354 + " policyVis=" + win.mPolicyVisibility
355 + " destroying=" + win.mDestroying
356 + " attHidden=" + win.mAttachedHidden
357 + " vis=" + win.mViewVisibility
358 + " hidden=" + win.mRootToken.hidden
359 + " anim=" + win.mWinAnimator.mAnimation);
360 } else if (canBeForceHidden) {
361 if (shouldBeForceHidden) {
362 if (!win.hideLw(false, false)) {
363 // Was already hidden
366 if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
367 "Now policy hidden: " + win);
369 boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
370 && !mPostKeyguardExitAnimation.hasEnded()
371 && !winAnimator.mKeyguardGoingAwayAnimation
373 && win.mAttachedWindow == null
375 && displayId == Display.DEFAULT_DISPLAY;
377 // If the window is already showing and we don't need to apply an existing
378 // Keyguard exit animation, skip.
379 if (!win.showLw(false, false) && !applyExistingExitAnimation) {
382 final boolean visibleNow = win.isVisibleNow();
384 // Couldn't really show, must showLw() again when win becomes visible.
385 win.hideLw(false, false);
388 if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
389 "Now policy shown: " + win);
390 if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
391 && win.mAttachedWindow == null) {
392 if (unForceHiding == null) {
393 unForceHiding = new ArrayList<>();
395 unForceHiding.add(winAnimator);
396 if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
397 wallpaperInUnForceHiding = true;
399 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
400 startingInUnForceHiding = true;
402 } else if (applyExistingExitAnimation) {
403 // We're already in the middle of an animation. Use the existing
404 // animation to bring in this window.
405 if (DEBUG_KEYGUARD) Slog.v(TAG,
406 "Applying existing Keyguard exit animation to new window: win="
409 Animation a = mPolicy.createForceHideEnterAnimation(false,
410 keyguardGoingAwayToShade);
411 winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime(),
412 STACK_CLIP_BEFORE_ANIM);
413 winAnimator.mKeyguardGoingAwayAnimation = true;
414 winAnimator.mKeyguardGoingAwayWithWallpaper
415 = keyguardGoingAwayWithWallpaper;
417 final WindowState currentFocus = mService.mCurrentFocus;
418 if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
419 // We are showing on top of the current
420 // focus, so re-evaluate focus to make
421 // sure it is correct.
422 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG,
423 "updateWindowsLocked: setting mFocusMayChange true");
424 mService.mFocusMayChange = true;
427 if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
428 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
429 setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
430 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
431 if (DEBUG_LAYOUT_REPEATS) {
432 mWindowPlacerLocked.debugLayoutRepeats(
433 "updateWindowsAndWallpaperLocked 4",
434 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
440 // If the window doesn't have a surface, the only thing we care about is the correct
441 // policy visibility.
442 else if (canBeForceHidden) {
443 if (shouldBeForceHidden) {
444 win.hideLw(false, false);
446 win.showLw(false, false);
450 final AppWindowToken atoken = win.mAppToken;
451 if (winAnimator.mDrawState == READY_TO_SHOW) {
452 if (atoken == null || atoken.allDrawn) {
453 if (winAnimator.performShowLocked()) {
454 setPendingLayoutChanges(displayId,
455 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
456 if (DEBUG_LAYOUT_REPEATS) {
457 mWindowPlacerLocked.debugLayoutRepeats(
458 "updateWindowsAndWallpaperLocked 5",
459 getPendingLayoutChanges(displayId));
464 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
465 if (appAnimator != null && appAnimator.thumbnail != null) {
466 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
467 appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
468 appAnimator.thumbnailLayer = 0;
470 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
471 appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
474 if (win.mIsWallpaper) {
477 } // end forall windows
479 // If we have windows that are being show due to them no longer
480 // being force-hidden, apply the appropriate animation to them if animations are not
482 if (unForceHiding != null) {
483 if (!keyguardGoingAwayNoAnimation) {
484 boolean first = true;
485 for (int i=unForceHiding.size()-1; i>=0; i--) {
486 final WindowStateAnimator winAnimator = unForceHiding.get(i);
487 Animation a = mPolicy.createForceHideEnterAnimation(
488 wallpaperInUnForceHiding && !startingInUnForceHiding,
489 keyguardGoingAwayToShade);
491 if (DEBUG_KEYGUARD) Slog.v(TAG,
492 "Starting keyguard exit animation on window " + winAnimator.mWin);
493 winAnimator.setAnimation(a, STACK_CLIP_BEFORE_ANIM);
494 winAnimator.mKeyguardGoingAwayAnimation = true;
495 winAnimator.mKeyguardGoingAwayWithWallpaper
496 = keyguardGoingAwayWithWallpaper;
498 mPostKeyguardExitAnimation = a;
499 mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
504 } else if (mKeyguardGoingAway) {
505 mPolicy.startKeyguardExitAnimation(mCurrentTime, 0 /* duration */);
506 mKeyguardGoingAway = false;
510 // Wallpaper is going away in un-force-hide motion, animate it as well.
511 if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) {
512 if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
513 Animation a = mPolicy.createForceHideWallpaperExitAnimation(
514 keyguardGoingAwayToShade);
516 wallpaper.mWinAnimator.setAnimation(a);
521 if (mPostKeyguardExitAnimation != null) {
522 // We're in the midst of a keyguard exit animation.
523 if (mKeyguardGoingAway) {
524 mPolicy.startKeyguardExitAnimation(mCurrentTime +
525 mPostKeyguardExitAnimation.getStartOffset(),
526 mPostKeyguardExitAnimation.getDuration());
527 mKeyguardGoingAway = false;
529 // mPostKeyguardExitAnimation might either be ended normally, cancelled, or "orphaned",
530 // meaning that the window it was running on was removed. We check for hasEnded() for
531 // ended normally and cancelled case, and check the time for the "orphaned" case.
532 else if (mPostKeyguardExitAnimation.hasEnded()
533 || mCurrentTime - mPostKeyguardExitAnimation.getStartTime()
534 > mPostKeyguardExitAnimation.getDuration()) {
535 // Done with the animation, reset.
536 if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations.");
537 mPostKeyguardExitAnimation = null;
542 private void updateWallpaperLocked(int displayId) {
543 mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
545 final WindowList windows = mService.getWindowListLocked(displayId);
546 WindowState detachedWallpaper = null;
548 for (int i = windows.size() - 1; i >= 0; i--) {
549 final WindowState win = windows.get(i);
550 WindowStateAnimator winAnimator = win.mWinAnimator;
551 if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
555 final int flags = win.mAttrs.flags;
557 // If this window is animating, make a note that we have
558 // an animating window and take care of a request to run
559 // a detached wallpaper animation.
560 if (winAnimator.mAnimating) {
561 if (winAnimator.mAnimation != null) {
562 if ((flags & FLAG_SHOW_WALLPAPER) != 0
563 && winAnimator.mAnimation.getDetachWallpaper()) {
564 detachedWallpaper = win;
566 final int color = winAnimator.mAnimation.getBackgroundColor();
568 final TaskStack stack = win.getStack();
570 stack.setAnimationBackground(winAnimator, color);
577 // If this window's app token is running a detached wallpaper
578 // animation, make a note so we can ensure the wallpaper is
579 // displayed behind it.
580 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
581 if (appAnimator != null && appAnimator.animation != null
582 && appAnimator.animating) {
583 if ((flags & FLAG_SHOW_WALLPAPER) != 0
584 && appAnimator.animation.getDetachWallpaper()) {
585 detachedWallpaper = win;
588 final int color = appAnimator.animation.getBackgroundColor();
590 final TaskStack stack = win.getStack();
592 stack.setAnimationBackground(winAnimator, color);
596 } // end forall windows
598 if (mWindowDetachedWallpaper != detachedWallpaper) {
599 if (DEBUG_WALLPAPER) Slog.v(TAG,
600 "Detached wallpaper changed from " + mWindowDetachedWallpaper
601 + " to " + detachedWallpaper);
602 mWindowDetachedWallpaper = detachedWallpaper;
603 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
607 /** See if any windows have been drawn, so they (and others associated with them) can now be
609 private void testTokenMayBeDrawnLocked(int displayId) {
610 // See if any windows have been drawn, so they (and others
611 // associated with them) can now be shown.
612 final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks();
613 final int numTasks = tasks.size();
614 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
615 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
616 final int numTokens = tokens.size();
617 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
618 final AppWindowToken wtoken = tokens.get(tokenNdx);
619 AppWindowAnimator appAnimator = wtoken.mAppAnimator;
620 final boolean allDrawn = wtoken.allDrawn;
621 if (allDrawn != appAnimator.allDrawn) {
622 appAnimator.allDrawn = allDrawn;
624 // The token has now changed state to having all
625 // windows shown... what to do, what to do?
626 if (appAnimator.freezingScreen) {
627 appAnimator.showAllWindowsLocked();
628 mService.unsetAppFreezingScreenLocked(wtoken, false, true);
629 if (DEBUG_ORIENTATION) Slog.i(TAG,
630 "Setting mOrientationChangeComplete=true because wtoken "
631 + wtoken + " numInteresting=" + wtoken.numInterestingWindows
632 + " numDrawn=" + wtoken.numDrawnWindows);
633 // This will set mOrientationChangeComplete and cause a pass through
635 setAppLayoutChanges(appAnimator,
636 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
637 "testTokenMayBeDrawnLocked: freezingScreen", displayId);
639 setAppLayoutChanges(appAnimator,
640 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
641 "testTokenMayBeDrawnLocked", displayId);
643 // We can now show all of the drawn windows!
644 if (!mService.mOpeningApps.contains(wtoken)) {
645 orAnimating(appAnimator.showAllWindowsLocked());
655 /** Locked on mService.mWindowMap. */
656 private void animateLocked(long frameTimeNs) {
661 mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
662 mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
663 boolean wasAnimating = mAnimating;
665 mAppWindowAnimating = false;
666 if (DEBUG_WINDOW_TRACE) {
667 Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
670 if (SHOW_TRANSACTIONS) Slog.i(
671 TAG, ">>> OPEN TRANSACTION animateLocked");
672 SurfaceControl.openTransaction();
673 SurfaceControl.setAnimationTransaction();
675 final int numDisplays = mDisplayContentsAnimators.size();
676 for (int i = 0; i < numDisplays; i++) {
677 final int displayId = mDisplayContentsAnimators.keyAt(i);
678 updateAppWindowsLocked(displayId);
679 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
681 final ScreenRotationAnimation screenRotationAnimation =
682 displayAnimator.mScreenRotationAnimation;
683 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
684 if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
687 mBulkUpdateParams |= SET_UPDATE_ROTATION;
688 screenRotationAnimation.kill();
689 displayAnimator.mScreenRotationAnimation = null;
691 //TODO (multidisplay): Accessibility supported only for the default display.
692 if (mService.mAccessibilityController != null
693 && displayId == Display.DEFAULT_DISPLAY) {
694 // We just finished rotation animation which means we did not
695 // anounce the rotation and waited for it to end, announce now.
696 mService.mAccessibilityController.onRotationChangedLocked(
697 mService.getDefaultDisplayContentLocked(), mService.mRotation);
702 // Update animations of all applications, including those
703 // associated with exiting/removed apps
704 updateWindowsLocked(displayId);
705 updateWallpaperLocked(displayId);
707 final WindowList windows = mService.getWindowListLocked(displayId);
708 final int N = windows.size();
709 for (int j = 0; j < N; j++) {
710 windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
714 for (int i = 0; i < numDisplays; i++) {
715 final int displayId = mDisplayContentsAnimators.keyAt(i);
717 testTokenMayBeDrawnLocked(displayId);
719 final ScreenRotationAnimation screenRotationAnimation =
720 mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
721 if (screenRotationAnimation != null) {
722 screenRotationAnimation.updateSurfacesInTransaction();
725 orAnimating(mService.getDisplayContentLocked(displayId).animateDimLayers());
726 orAnimating(mService.getDisplayContentLocked(displayId).getDockedDividerController()
727 .animate(mCurrentTime));
728 //TODO (multidisplay): Magnification is supported only for the default display.
729 if (mService.mAccessibilityController != null
730 && displayId == Display.DEFAULT_DISPLAY) {
731 mService.mAccessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
735 if (mService.mDragState != null) {
736 mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
740 mService.scheduleAnimationLocked();
743 if (mService.mWatermark != null) {
744 mService.mWatermark.drawIfNeeded();
746 } catch (RuntimeException e) {
747 Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
749 SurfaceControl.closeTransaction();
750 if (SHOW_TRANSACTIONS) Slog.i(
751 TAG, "<<< CLOSE TRANSACTION animateLocked");
754 boolean hasPendingLayoutChanges = false;
755 final int numDisplays = mService.mDisplayContents.size();
756 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
757 final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
758 final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
759 if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
760 mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
762 if (pendingChanges != 0) {
763 hasPendingLayoutChanges = true;
767 boolean doRequest = false;
768 if (mBulkUpdateParams != 0) {
769 doRequest = mWindowPlacerLocked.copyAnimToLayoutParamsLocked();
772 if (hasPendingLayoutChanges || doRequest) {
773 mWindowPlacerLocked.requestTraversal();
776 if (mAnimating && !wasAnimating && Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
777 Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
780 if (!mAnimating && wasAnimating) {
781 mWindowPlacerLocked.requestTraversal();
782 if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
783 Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
787 if (mRemoveReplacedWindows) {
788 removeReplacedWindowsLocked();
791 mService.stopUsingSavedSurfaceLocked();
792 mService.destroyPreservedSurfaceLocked();
793 mService.mWindowPlacerLocked.destroyPendingSurfaces();
795 if (DEBUG_WINDOW_TRACE) {
796 Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
797 + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
798 + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
799 + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
803 private void removeReplacedWindowsLocked() {
804 if (SHOW_TRANSACTIONS) Slog.i(
805 TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
806 SurfaceControl.openTransaction();
808 for (int i = mService.mDisplayContents.size() - 1; i >= 0; i--) {
809 DisplayContent display = mService.mDisplayContents.valueAt(i);
810 final WindowList windows = mService.getWindowListLocked(display.getDisplayId());
811 for (int j = windows.size() - 1; j >= 0; j--) {
812 windows.get(j).maybeRemoveReplacedWindow();
816 SurfaceControl.closeTransaction();
817 if (SHOW_TRANSACTIONS) Slog.i(
818 TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
820 mRemoveReplacedWindows = false;
823 private static String bulkUpdateParamsToString(int bulkUpdateParams) {
824 StringBuilder builder = new StringBuilder(128);
825 if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) {
826 builder.append(" UPDATE_ROTATION");
828 if ((bulkUpdateParams & WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE) != 0) {
829 builder.append(" WALLPAPER_MAY_CHANGE");
831 if ((bulkUpdateParams & WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED) != 0) {
832 builder.append(" FORCE_HIDING_CHANGED");
834 if ((bulkUpdateParams & WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
835 builder.append(" ORIENTATION_CHANGE_COMPLETE");
837 if ((bulkUpdateParams & WindowSurfacePlacer.SET_TURN_ON_SCREEN) != 0) {
838 builder.append(" TURN_ON_SCREEN");
840 return builder.toString();
843 public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
844 final String subPrefix = " " + prefix;
845 final String subSubPrefix = " " + subPrefix;
847 for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
848 pw.print(prefix); pw.print("DisplayContentsAnimator #");
849 pw.print(mDisplayContentsAnimators.keyAt(i));
851 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
852 final WindowList windows =
853 mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i));
854 final int N = windows.size();
855 for (int j = 0; j < N; j++) {
856 WindowStateAnimator wanim = windows.get(j).mWinAnimator;
857 pw.print(subPrefix); pw.print("Window #"); pw.print(j);
858 pw.print(": "); pw.println(wanim);
860 if (displayAnimator.mScreenRotationAnimation != null) {
861 pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
862 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
863 } else if (dumpAll) {
864 pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
872 pw.print(prefix); pw.print("mAnimTransactionSequence=");
873 pw.print(mAnimTransactionSequence);
874 pw.print(" mForceHiding="); pw.println(forceHidingToString());
875 pw.print(prefix); pw.print("mCurrentTime=");
876 pw.println(TimeUtils.formatUptime(mCurrentTime));
878 if (mBulkUpdateParams != 0) {
879 pw.print(prefix); pw.print("mBulkUpdateParams=0x");
880 pw.print(Integer.toHexString(mBulkUpdateParams));
881 pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
883 if (mWindowDetachedWallpaper != null) {
884 pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
885 pw.println(mWindowDetachedWallpaper);
889 int getPendingLayoutChanges(final int displayId) {
893 final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
894 return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
897 void setPendingLayoutChanges(final int displayId, final int changes) {
901 final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
902 if (displayContent != null) {
903 displayContent.pendingLayoutChanges |= changes;
907 void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason,
908 final int displayId) {
909 WindowList windows = appAnimator.mAppToken.allAppWindows;
910 for (int i = windows.size() - 1; i >= 0; i--) {
911 if (displayId == windows.get(i).getDisplayId()) {
912 setPendingLayoutChanges(displayId, changes);
913 if (DEBUG_LAYOUT_REPEATS) {
914 mWindowPlacerLocked.debugLayoutRepeats(reason,
915 getPendingLayoutChanges(displayId));
922 private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
923 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
924 if (displayAnimator == null) {
925 displayAnimator = new DisplayContentsAnimator();
926 mDisplayContentsAnimators.put(displayId, displayAnimator);
928 return displayAnimator;
931 void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
932 if (displayId >= 0) {
933 getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
937 ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
941 return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
944 void requestRemovalOfReplacedWindows(WindowState win) {
945 mRemoveReplacedWindows = true;
948 private class DisplayContentsAnimator {
949 ScreenRotationAnimation mScreenRotationAnimation = null;
952 boolean isAnimating() {
956 void setAnimating(boolean animating) {
957 mAnimating = animating;
960 void orAnimating(boolean animating) {
961 mAnimating |= animating;