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_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;
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;
60 import java.io.PrintWriter;
61 import java.util.ArrayList;
64 * Singleton class that carries out the animations and Surface operations in a separate task
65 * on behalf of WindowManagerService.
67 public class WindowAnimator {
68 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowAnimator" : TAG_WM;
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;
73 final WindowManagerService mService;
74 final Context mContext;
75 final WindowManagerPolicy mPolicy;
76 private final WindowSurfacePlacer mWindowPlacerLocked;
78 /** Is any window animating? */
79 private boolean mAnimating;
81 /** Is any app window animating? */
82 boolean mAppWindowAnimating;
84 final Choreographer.FrameCallback mAnimationFrameCallback;
86 /** Time of current animation step. Reset on each iteration */
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;
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;
99 int mBulkUpdateParams = 0;
100 Object mLastWindowFreezeSource;
102 SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
104 boolean mInitialized = false;
106 boolean mKeyguardGoingAway;
107 int mKeyguardGoingAwayFlags;
109 /** Use one animation for all entering activities after keyguard is dismissed. */
110 Animation mPostKeyguardExitAnimation;
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;
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;
122 private final AppTokenList mTmpExitingAppTokens = new AppTokenList();
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;
133 WindowAnimator(final WindowManagerService service) {
135 mContext = service.mContext;
136 mPolicy = service.mPolicy;
137 mWindowPlacerLocked = service.mWindowPlacerLocked;
139 mAnimationFrameCallback = new Choreographer.FrameCallback() {
140 public void doFrame(long frameTimeNs) {
141 synchronized (mService.mWindowMap) {
142 mService.mAnimationScheduled = false;
143 animateLocked(frameTimeNs);
149 void addDisplayLocked(final int displayId) {
150 // Create the DisplayContentsAnimator object by retrieving it.
151 getDisplayContentsAnimatorLocked(displayId);
152 if (displayId == Display.DEFAULT_DISPLAY) {
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;
166 mDisplayContentsAnimators.delete(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;
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);
194 mTmpExitingAppTokens.clear();
195 mTmpExitingAppTokens.addAll(stack.mExitingAppTokens);
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)) {
207 appAnimator.wasAnimating = appAnimator.animating;
208 if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
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);
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));
230 final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
231 final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
232 null : winShowWhenLocked.mAppToken;
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;
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;
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();
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)
263 private void updateWindowsLocked(final int displayId) {
264 ++mAnimTransactionSequence;
266 final WindowList windows = mService.getWindowListLocked(displayId);
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;
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)) {
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");
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;
297 if (DEBUG_KEYGUARD) Slog.d(TAG,
298 "updateWindowsLocked: StatusBar is no longer keyguard");
299 mKeyguardGoingAway = false;
300 winAnimator.clearAnimation();
306 mForceHiding = KEYGUARD_NOT_SHOWN;
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);
325 if (DEBUG_WALLPAPER) {
326 Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
327 ", nowAnimating=" + nowAnimating);
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));
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));
355 mService.mFocusMayChange = true;
356 } else if (mKeyguardGoingAway && !nowAnimating) {
358 Slog.e(TAG, "Timeout waiting for animation to startup");
359 mPolicy.startKeyguardExitAnimation(0, 0);
360 mKeyguardGoingAway = false;
362 if (win.isReadyForDisplay()) {
363 if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) {
364 mForceHiding = KEYGUARD_ANIMATING_OUT;
366 mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
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
384 if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
385 "Now policy hidden: " + win);
387 boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
388 && !mPostKeyguardExitAnimation.hasEnded()
389 && !winAnimator.mKeyguardGoingAwayAnimation
391 && win.mAttachedWindow == null
393 && displayId == Display.DEFAULT_DISPLAY;
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) {
400 final boolean visibleNow = win.isVisibleNow();
402 // Couldn't really show, must showLw() again when win becomes visible.
403 win.hideLw(false, false);
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<>();
413 unForceHiding.add(winAnimator);
414 if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
415 wallpaperInUnForceHiding = true;
417 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
418 startingInUnForceHiding = true;
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="
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;
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;
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));
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);
464 win.showLw(false, false);
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));
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;
488 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
489 appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
492 if (win.mIsWallpaper) {
495 } // end forall windows
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
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);
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;
516 mPostKeyguardExitAnimation = a;
517 mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
522 } else if (mKeyguardGoingAway) {
523 mPolicy.startKeyguardExitAnimation(mCurrentTime, 0 /* duration */);
524 mKeyguardGoingAway = false;
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);
534 wallpaper.mWinAnimator.setAnimation(a);
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;
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;
560 private void updateWallpaperLocked(int displayId) {
561 mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
563 final WindowList windows = mService.getWindowListLocked(displayId);
564 WindowState detachedWallpaper = null;
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()) {
573 final int flags = win.mAttrs.flags;
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;
584 final int color = winAnimator.mAnimation.getBackgroundColor();
586 final TaskStack stack = win.getStack();
588 stack.setAnimationBackground(winAnimator, color);
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;
606 final int color = appAnimator.animation.getBackgroundColor();
608 final TaskStack stack = win.getStack();
610 stack.setAnimationBackground(winAnimator, color);
614 } // end forall windows
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;
625 /** See if any windows have been drawn, so they (and others associated with them) can now be
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;
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
653 setAppLayoutChanges(appAnimator,
654 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
655 "testTokenMayBeDrawnLocked: freezingScreen", displayId);
657 setAppLayoutChanges(appAnimator,
658 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
659 "testTokenMayBeDrawnLocked", displayId);
661 // We can now show all of the drawn windows!
662 if (!mService.mOpeningApps.contains(wtoken)) {
663 orAnimating(appAnimator.showAllWindowsLocked());
673 /** Locked on mService.mWindowMap. */
674 private void animateLocked(long frameTimeNs) {
679 mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
680 mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
681 boolean wasAnimating = mAnimating;
683 mAppWindowAnimating = false;
684 if (DEBUG_WINDOW_TRACE) {
685 Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
688 if (SHOW_TRANSACTIONS) Slog.i(
689 TAG, ">>> OPEN TRANSACTION animateLocked");
690 SurfaceControl.openTransaction();
691 SurfaceControl.setAnimationTransaction();
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);
699 final ScreenRotationAnimation screenRotationAnimation =
700 displayAnimator.mScreenRotationAnimation;
701 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
702 if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
705 mBulkUpdateParams |= SET_UPDATE_ROTATION;
706 screenRotationAnimation.kill();
707 displayAnimator.mScreenRotationAnimation = null;
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);
720 // Update animations of all applications, including those
721 // associated with exiting/removed apps
722 updateWindowsLocked(displayId);
723 updateWallpaperLocked(displayId);
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);
732 for (int i = 0; i < numDisplays; i++) {
733 final int displayId = mDisplayContentsAnimators.keyAt(i);
735 testTokenMayBeDrawnLocked(displayId);
737 final ScreenRotationAnimation screenRotationAnimation =
738 mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
739 if (screenRotationAnimation != null) {
740 screenRotationAnimation.updateSurfacesInTransaction();
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();
753 if (mService.mDragState != null) {
754 mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
758 mService.scheduleAnimationLocked();
761 if (mService.mWatermark != null) {
762 mService.mWatermark.drawIfNeeded();
764 } catch (RuntimeException e) {
765 Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
767 SurfaceControl.closeTransaction();
768 if (SHOW_TRANSACTIONS) Slog.i(
769 TAG, "<<< CLOSE TRANSACTION animateLocked");
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;
780 if (pendingChanges != 0) {
781 hasPendingLayoutChanges = true;
785 boolean doRequest = false;
786 if (mBulkUpdateParams != 0) {
787 doRequest = mWindowPlacerLocked.copyAnimToLayoutParamsLocked();
790 if (hasPendingLayoutChanges || doRequest) {
791 mWindowPlacerLocked.requestTraversal();
794 if (mAnimating && !wasAnimating && Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
795 Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
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);
805 if (mRemoveReplacedWindows) {
806 removeReplacedWindowsLocked();
809 mService.stopUsingSavedSurfaceLocked();
810 mService.destroyPreservedSurfaceLocked();
811 mService.mWindowPlacerLocked.destroyPendingSurfaces();
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)));
821 private void removeReplacedWindowsLocked() {
822 if (SHOW_TRANSACTIONS) Slog.i(
823 TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
824 SurfaceControl.openTransaction();
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();
834 SurfaceControl.closeTransaction();
835 if (SHOW_TRANSACTIONS) Slog.i(
836 TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
838 mRemoveReplacedWindows = false;
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");
846 if ((bulkUpdateParams & WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE) != 0) {
847 builder.append(" WALLPAPER_MAY_CHANGE");
849 if ((bulkUpdateParams & WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED) != 0) {
850 builder.append(" FORCE_HIDING_CHANGED");
852 if ((bulkUpdateParams & WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
853 builder.append(" ORIENTATION_CHANGE_COMPLETE");
855 if ((bulkUpdateParams & WindowSurfacePlacer.SET_TURN_ON_SCREEN) != 0) {
856 builder.append(" TURN_ON_SCREEN");
858 return builder.toString();
861 public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
862 final String subPrefix = " " + prefix;
863 final String subSubPrefix = " " + subPrefix;
865 for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
866 pw.print(prefix); pw.print("DisplayContentsAnimator #");
867 pw.print(mDisplayContentsAnimators.keyAt(i));
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);
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 ");
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));
896 if (mBulkUpdateParams != 0) {
897 pw.print(prefix); pw.print("mBulkUpdateParams=0x");
898 pw.print(Integer.toHexString(mBulkUpdateParams));
899 pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
901 if (mWindowDetachedWallpaper != null) {
902 pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
903 pw.println(mWindowDetachedWallpaper);
907 int getPendingLayoutChanges(final int displayId) {
911 final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
912 return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
915 void setPendingLayoutChanges(final int displayId, final int changes) {
919 final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
920 if (displayContent != null) {
921 displayContent.pendingLayoutChanges |= changes;
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));
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);
946 return displayAnimator;
949 void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
950 if (displayId >= 0) {
951 getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
955 ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
959 return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
962 void requestRemovalOfReplacedWindows(WindowState win) {
963 mRemoveReplacedWindows = true;
966 private class DisplayContentsAnimator {
967 ScreenRotationAnimation mScreenRotationAnimation = null;
970 boolean isAnimating() {
974 void setAnimating(boolean animating) {
975 mAnimating = animating;
978 void orAnimating(boolean animating) {
979 mAnimating |= animating;