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;
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 com.android.server.wm.WindowManagerService.DEBUG_KEYGUARD;
26 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
27 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
28 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
29 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
30 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING;
32 import android.content.Context;
33 import android.os.Debug;
34 import android.os.SystemClock;
35 import android.util.Slog;
36 import android.util.SparseArray;
37 import android.util.SparseIntArray;
38 import android.util.TimeUtils;
39 import android.view.Display;
40 import android.view.SurfaceControl;
41 import android.view.WindowManagerPolicy;
42 import android.view.animation.AlphaAnimation;
43 import android.view.animation.Animation;
45 import com.android.server.wm.WindowManagerService.LayoutFields;
47 import java.io.PrintWriter;
48 import java.util.ArrayList;
51 * Singleton class that carries out the animations and Surface operations in a separate task
52 * on behalf of WindowManagerService.
54 public class WindowAnimator {
55 private static final String TAG = "WindowAnimator";
57 /** How long to give statusbar to clear the private keyguard flag when animating out */
58 private static final long KEYGUARD_ANIM_TIMEOUT_MS = 1000;
60 final WindowManagerService mService;
61 final Context mContext;
62 final WindowManagerPolicy mPolicy;
66 final Runnable mAnimationRunnable;
68 /** Time of current animation step. Reset on each iteration */
71 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
72 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
73 private int mAnimTransactionSequence;
75 /** Window currently running an animation that has requested it be detached
76 * from the wallpaper. This means we need to ensure the wallpaper is
77 * visible behind it in case it animates in a way that would allow it to be
78 * seen. If multiple windows satisfy this, use the lowest window. */
79 WindowState mWindowDetachedWallpaper = null;
81 WindowStateAnimator mUniverseBackground = null;
82 int mAboveUniverseLayer = 0;
84 int mBulkUpdateParams = 0;
85 Object mLastWindowFreezeSource;
87 SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
88 new SparseArray<DisplayContentsAnimator>(2);
90 boolean mInitialized = false;
92 boolean mKeyguardGoingAway;
93 boolean mKeyguardGoingAwayToNotificationShade;
94 boolean mKeyguardGoingAwayDisableWindowAnimations;
96 /** Use one animation for all entering activities after keyguard is dismissed. */
97 Animation mPostKeyguardExitAnimation;
99 // forceHiding states.
100 static final int KEYGUARD_NOT_SHOWN = 0;
101 static final int KEYGUARD_ANIMATING_IN = 1;
102 static final int KEYGUARD_SHOWN = 2;
103 static final int KEYGUARD_ANIMATING_OUT = 3;
104 int mForceHiding = KEYGUARD_NOT_SHOWN;
106 private String forceHidingToString() {
107 switch (mForceHiding) {
108 case KEYGUARD_NOT_SHOWN: return "KEYGUARD_NOT_SHOWN";
109 case KEYGUARD_ANIMATING_IN: return "KEYGUARD_ANIMATING_IN";
110 case KEYGUARD_SHOWN: return "KEYGUARD_SHOWN";
111 case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
112 default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
116 WindowAnimator(final WindowManagerService service) {
118 mContext = service.mContext;
119 mPolicy = service.mPolicy;
121 mAnimationRunnable = new Runnable() {
124 synchronized (mService.mWindowMap) {
125 mService.mAnimationScheduled = false;
132 void addDisplayLocked(final int displayId) {
133 // Create the DisplayContentsAnimator object by retrieving it.
134 getDisplayContentsAnimatorLocked(displayId);
135 if (displayId == Display.DEFAULT_DISPLAY) {
140 void removeDisplayLocked(final int displayId) {
141 final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
142 if (displayAnimator != null) {
143 if (displayAnimator.mScreenRotationAnimation != null) {
144 displayAnimator.mScreenRotationAnimation.kill();
145 displayAnimator.mScreenRotationAnimation = null;
149 mDisplayContentsAnimators.delete(displayId);
152 void hideWallpapersLocked(final WindowState w) {
153 final WindowState wallpaperTarget = mService.mWallpaperTarget;
154 final WindowState lowerWallpaperTarget = mService.mLowerWallpaperTarget;
155 final ArrayList<WindowToken> wallpaperTokens = mService.mWallpaperTokens;
157 if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) {
158 final int numTokens = wallpaperTokens.size();
159 for (int i = numTokens - 1; i >= 0; i--) {
160 final WindowToken token = wallpaperTokens.get(i);
161 final int numWindows = token.windows.size();
162 for (int j = numWindows - 1; j >= 0; j--) {
163 final WindowState wallpaper = token.windows.get(j);
164 final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
165 if (!winAnimator.mLastHidden) {
167 mService.dispatchWallpaperVisibility(wallpaper, false);
168 setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
169 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
172 if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG,
173 "Hiding wallpaper " + token + " from " + w
174 + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget
175 + "\n" + Debug.getCallers(5, " "));
181 private void updateAppWindowsLocked(int displayId) {
182 ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks();
183 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
184 final TaskStack stack = stacks.get(stackNdx);
185 final ArrayList<Task> tasks = stack.getTasks();
186 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
187 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
188 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
189 final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
190 final boolean wasAnimating = appAnimator.animation != null
191 && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
192 if (appAnimator.stepAnimationLocked(mCurrentTime)) {
194 } else if (wasAnimating) {
195 // stopped animating, do one more pass through the layout
196 setAppLayoutChanges(appAnimator,
197 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
198 "appToken " + appAnimator.mAppToken + " done");
199 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
200 "updateWindowsApps...: done animating " + appAnimator.mAppToken);
205 final AppTokenList exitingAppTokens = stack.mExitingAppTokens;
206 final int NEAT = exitingAppTokens.size();
207 for (int i = 0; i < NEAT; i++) {
208 final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
209 final boolean wasAnimating = appAnimator.animation != null
210 && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
211 if (appAnimator.stepAnimationLocked(mCurrentTime)) {
213 } else if (wasAnimating) {
214 // stopped animating, do one more pass through the layout
215 setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
216 "exiting appToken " + appAnimator.mAppToken + " done");
217 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
218 "updateWindowsApps...: done animating exiting " + 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;
229 final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
230 final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
231 null : winShowWhenLocked.mAppToken;
232 final boolean hideWhenLocked =
233 !(((win.mIsImWindow || imeTarget == win) && showImeOverKeyguard)
234 || (appShowWhenLocked != null && (appShowWhenLocked == win.mAppToken ||
235 // Show error dialogs over apps that dismiss keyguard.
236 (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0)));
237 return ((mForceHiding == KEYGUARD_ANIMATING_IN)
238 && (!win.mWinAnimator.isAnimating() || hideWhenLocked))
239 || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked);
242 private void updateWindowsLocked(final int displayId) {
243 ++mAnimTransactionSequence;
245 final WindowList windows = mService.getWindowListLocked(displayId);
247 if (mKeyguardGoingAway) {
248 for (int i = windows.size() - 1; i >= 0; i--) {
249 WindowState win = windows.get(i);
250 if (!mPolicy.isKeyguardHostWindow(win.mAttrs)) {
253 final WindowStateAnimator winAnimator = win.mWinAnimator;
254 if ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
255 if (!winAnimator.mAnimating) {
256 if (DEBUG_KEYGUARD) Slog.d(TAG,
257 "updateWindowsLocked: creating delay animation");
259 // Create a new animation to delay until keyguard is gone on its own.
260 winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
261 winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
262 winAnimator.mAnimationIsEntrance = false;
263 winAnimator.mAnimationStartTime = -1;
266 if (DEBUG_KEYGUARD) Slog.d(TAG,
267 "updateWindowsLocked: StatusBar is no longer keyguard");
268 mKeyguardGoingAway = false;
269 winAnimator.clearAnimation();
275 mForceHiding = KEYGUARD_NOT_SHOWN;
277 boolean wallpaperInUnForceHiding = false;
278 boolean startingInUnForceHiding = false;
279 ArrayList<WindowStateAnimator> unForceHiding = null;
280 WindowState wallpaper = null;
281 for (int i = windows.size() - 1; i >= 0; i--) {
282 WindowState win = windows.get(i);
283 WindowStateAnimator winAnimator = win.mWinAnimator;
284 final int flags = win.mAttrs.flags;
285 boolean canBeForceHidden = mPolicy.canBeForceHidden(win, win.mAttrs);
286 boolean shouldBeForceHidden = shouldForceHide(win);
287 if (winAnimator.mSurfaceControl != null) {
288 final boolean wasAnimating = winAnimator.mWasAnimating;
289 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
290 mAnimating |= nowAnimating;
292 if (WindowManagerService.DEBUG_WALLPAPER) {
293 Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
294 ", nowAnimating=" + nowAnimating);
297 if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
298 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
299 setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
300 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
301 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
302 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
303 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
307 if (mPolicy.isForceHiding(win.mAttrs)) {
308 if (!wasAnimating && nowAnimating) {
309 if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_ANIM ||
310 WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
311 "Animation started that could impact force hide: " + win);
312 mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
313 setPendingLayoutChanges(displayId,
314 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
315 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
316 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
317 getPendingLayoutChanges(displayId));
319 mService.mFocusMayChange = true;
320 } else if (mKeyguardGoingAway && !nowAnimating) {
322 Slog.e(TAG, "Timeout waiting for animation to startup");
323 mPolicy.startKeyguardExitAnimation(0, 0);
324 mKeyguardGoingAway = false;
326 if (win.isReadyForDisplay()) {
328 if (winAnimator.mAnimationIsEntrance) {
329 mForceHiding = KEYGUARD_ANIMATING_IN;
331 mForceHiding = KEYGUARD_ANIMATING_OUT;
334 mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
337 if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
338 "Force hide " + forceHidingToString()
339 + " hasSurface=" + win.mHasSurface
340 + " policyVis=" + win.mPolicyVisibility
341 + " destroying=" + win.mDestroying
342 + " attHidden=" + win.mAttachedHidden
343 + " vis=" + win.mViewVisibility
344 + " hidden=" + win.mRootToken.hidden
345 + " anim=" + win.mWinAnimator.mAnimation);
346 } else if (canBeForceHidden) {
347 if (shouldBeForceHidden) {
348 if (!win.hideLw(false, false)) {
349 // Was already hidden
352 if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
353 "Now policy hidden: " + win);
355 boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
356 && !winAnimator.mKeyguardGoingAwayAnimation
358 && win.mAttachedWindow == null
359 && mForceHiding != KEYGUARD_NOT_SHOWN;
361 // If the window is already showing and we don't need to apply an existing
362 // Keyguard exit animation, skip.
363 if (!win.showLw(false, false) && !applyExistingExitAnimation) {
366 final boolean visibleNow = win.isVisibleNow();
368 // Couldn't really show, must showLw() again when win becomes visible.
369 win.hideLw(false, false);
372 if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
373 "Now policy shown: " + win);
374 if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
375 && win.mAttachedWindow == null) {
376 if (unForceHiding == null) {
377 unForceHiding = new ArrayList<>();
379 unForceHiding.add(winAnimator);
380 if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
381 wallpaperInUnForceHiding = true;
383 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
384 startingInUnForceHiding = true;
386 } else if (applyExistingExitAnimation) {
387 // We're already in the middle of an animation. Use the existing
388 // animation to bring in this window.
389 if (DEBUG_KEYGUARD) Slog.v(TAG,
390 "Applying existing Keyguard exit animation to new window: win="
392 Animation a = mPolicy.createForceHideEnterAnimation(
393 false, mKeyguardGoingAwayToNotificationShade);
394 winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime());
395 winAnimator.mKeyguardGoingAwayAnimation = true;
397 final WindowState currentFocus = mService.mCurrentFocus;
398 if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
399 // We are showing on top of the current
400 // focus, so re-evaluate focus to make
401 // sure it is correct.
402 if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG,
403 "updateWindowsLocked: setting mFocusMayChange true");
404 mService.mFocusMayChange = true;
407 if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
408 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
409 setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
410 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
411 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
412 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
413 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
419 // If the window doesn't have a surface, the only thing we care about is the correct
420 // policy visibility.
421 else if (canBeForceHidden) {
422 if (shouldBeForceHidden) {
423 win.hideLw(false, false);
425 win.showLw(false, false);
429 final AppWindowToken atoken = win.mAppToken;
430 if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
431 if (atoken == null || atoken.allDrawn) {
432 if (winAnimator.performShowLocked()) {
433 setPendingLayoutChanges(displayId,
434 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
435 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
436 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
437 getPendingLayoutChanges(displayId));
442 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
443 if (appAnimator != null && appAnimator.thumbnail != null) {
444 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
445 appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
446 appAnimator.thumbnailLayer = 0;
448 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
449 appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
452 if (win.mIsWallpaper) {
455 } // end forall windows
457 // If we have windows that are being show due to them no longer
458 // being force-hidden, apply the appropriate animation to them if animations are not
460 if (unForceHiding != null) {
461 if (!mKeyguardGoingAwayDisableWindowAnimations) {
462 boolean first = true;
463 for (int i=unForceHiding.size()-1; i>=0; i--) {
464 final WindowStateAnimator winAnimator = unForceHiding.get(i);
465 Animation a = mPolicy.createForceHideEnterAnimation(
466 wallpaperInUnForceHiding && !startingInUnForceHiding,
467 mKeyguardGoingAwayToNotificationShade);
469 if (DEBUG_KEYGUARD) Slog.v(TAG,
470 "Starting keyguard exit animation on window " + winAnimator.mWin);
471 winAnimator.setAnimation(a);
472 winAnimator.mKeyguardGoingAwayAnimation = true;
474 mPostKeyguardExitAnimation = a;
475 mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
480 } else if (mKeyguardGoingAway) {
481 mPolicy.startKeyguardExitAnimation(mCurrentTime, 0 /* duration */);
482 mKeyguardGoingAway = false;
486 // Wallpaper is going away in un-force-hide motion, animate it as well.
487 if (!wallpaperInUnForceHiding && wallpaper != null
488 && !mKeyguardGoingAwayDisableWindowAnimations) {
489 if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
490 Animation a = mPolicy.createForceHideWallpaperExitAnimation(
491 mKeyguardGoingAwayToNotificationShade);
493 wallpaper.mWinAnimator.setAnimation(a);
498 if (mPostKeyguardExitAnimation != null) {
499 // We're in the midst of a keyguard exit animation.
500 if (mKeyguardGoingAway) {
501 mPolicy.startKeyguardExitAnimation(mCurrentTime +
502 mPostKeyguardExitAnimation.getStartOffset(),
503 mPostKeyguardExitAnimation.getDuration());
504 mKeyguardGoingAway = false;
505 } else if (mCurrentTime - mPostKeyguardExitAnimation.getStartTime()
506 > mPostKeyguardExitAnimation.getDuration()) {
507 // Done with the animation, reset.
508 if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations.");
509 mPostKeyguardExitAnimation = null;
514 private void updateWallpaperLocked(int displayId) {
515 mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
517 final WindowList windows = mService.getWindowListLocked(displayId);
518 WindowState detachedWallpaper = null;
520 for (int i = windows.size() - 1; i >= 0; i--) {
521 final WindowState win = windows.get(i);
522 WindowStateAnimator winAnimator = win.mWinAnimator;
523 if (winAnimator.mSurfaceControl == null) {
527 final int flags = win.mAttrs.flags;
529 // If this window is animating, make a note that we have
530 // an animating window and take care of a request to run
531 // a detached wallpaper animation.
532 if (winAnimator.mAnimating) {
533 if (winAnimator.mAnimation != null) {
534 if ((flags & FLAG_SHOW_WALLPAPER) != 0
535 && winAnimator.mAnimation.getDetachWallpaper()) {
536 detachedWallpaper = win;
538 final int color = winAnimator.mAnimation.getBackgroundColor();
540 final TaskStack stack = win.getStack();
542 stack.setAnimationBackground(winAnimator, color);
549 // If this window's app token is running a detached wallpaper
550 // animation, make a note so we can ensure the wallpaper is
551 // displayed behind it.
552 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
553 if (appAnimator != null && appAnimator.animation != null
554 && appAnimator.animating) {
555 if ((flags & FLAG_SHOW_WALLPAPER) != 0
556 && appAnimator.animation.getDetachWallpaper()) {
557 detachedWallpaper = win;
560 final int color = appAnimator.animation.getBackgroundColor();
562 final TaskStack stack = win.getStack();
564 stack.setAnimationBackground(winAnimator, color);
568 } // end forall windows
570 if (mWindowDetachedWallpaper != detachedWallpaper) {
571 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
572 "Detached wallpaper changed from " + mWindowDetachedWallpaper
573 + " to " + detachedWallpaper);
574 mWindowDetachedWallpaper = detachedWallpaper;
575 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
579 /** See if any windows have been drawn, so they (and others associated with them) can now be
581 private void testTokenMayBeDrawnLocked(int displayId) {
582 // See if any windows have been drawn, so they (and others
583 // associated with them) can now be shown.
584 final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks();
585 final int numTasks = tasks.size();
586 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
587 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
588 final int numTokens = tokens.size();
589 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
590 final AppWindowToken wtoken = tokens.get(tokenNdx);
591 AppWindowAnimator appAnimator = wtoken.mAppAnimator;
592 final boolean allDrawn = wtoken.allDrawn;
593 if (allDrawn != appAnimator.allDrawn) {
594 appAnimator.allDrawn = allDrawn;
596 // The token has now changed state to having all
597 // windows shown... what to do, what to do?
598 if (appAnimator.freezingScreen) {
599 appAnimator.showAllWindowsLocked();
600 mService.unsetAppFreezingScreenLocked(wtoken, false, true);
601 if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
602 "Setting mOrientationChangeComplete=true because wtoken "
603 + wtoken + " numInteresting=" + wtoken.numInterestingWindows
604 + " numDrawn=" + wtoken.numDrawnWindows);
605 // This will set mOrientationChangeComplete and cause a pass through layout.
606 setAppLayoutChanges(appAnimator,
607 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
608 "testTokenMayBeDrawnLocked: freezingScreen");
610 setAppLayoutChanges(appAnimator,
611 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
612 "testTokenMayBeDrawnLocked");
614 // We can now show all of the drawn windows!
615 if (!mService.mOpeningApps.contains(wtoken)) {
616 mAnimating |= appAnimator.showAllWindowsLocked();
626 /** Locked on mService.mWindowMap. */
627 private void animateLocked() {
632 mCurrentTime = SystemClock.uptimeMillis();
633 mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
634 boolean wasAnimating = mAnimating;
636 if (WindowManagerService.DEBUG_WINDOW_TRACE) {
637 Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
640 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
641 TAG, ">>> OPEN TRANSACTION animateLocked");
642 SurfaceControl.openTransaction();
643 SurfaceControl.setAnimationTransaction();
645 final int numDisplays = mDisplayContentsAnimators.size();
646 for (int i = 0; i < numDisplays; i++) {
647 final int displayId = mDisplayContentsAnimators.keyAt(i);
648 updateAppWindowsLocked(displayId);
649 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
651 final ScreenRotationAnimation screenRotationAnimation =
652 displayAnimator.mScreenRotationAnimation;
653 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
654 if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
657 mBulkUpdateParams |= SET_UPDATE_ROTATION;
658 screenRotationAnimation.kill();
659 displayAnimator.mScreenRotationAnimation = null;
661 //TODO (multidisplay): Accessibility supported only for the default display.
662 if (mService.mAccessibilityController != null
663 && displayId == Display.DEFAULT_DISPLAY) {
664 // We just finished rotation animation which means we did not
665 // anounce the rotation and waited for it to end, announce now.
666 mService.mAccessibilityController.onRotationChangedLocked(
667 mService.getDefaultDisplayContentLocked(), mService.mRotation);
672 // Update animations of all applications, including those
673 // associated with exiting/removed apps
674 updateWindowsLocked(displayId);
675 updateWallpaperLocked(displayId);
677 final WindowList windows = mService.getWindowListLocked(displayId);
678 final int N = windows.size();
679 for (int j = 0; j < N; j++) {
680 windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
684 for (int i = 0; i < numDisplays; i++) {
685 final int displayId = mDisplayContentsAnimators.keyAt(i);
687 testTokenMayBeDrawnLocked(displayId);
689 final ScreenRotationAnimation screenRotationAnimation =
690 mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
691 if (screenRotationAnimation != null) {
692 screenRotationAnimation.updateSurfacesInTransaction();
695 mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();
697 //TODO (multidisplay): Magnification is supported only for the default display.
698 if (mService.mAccessibilityController != null
699 && displayId == Display.DEFAULT_DISPLAY) {
700 mService.mAccessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
705 mService.scheduleAnimationLocked();
708 mService.setFocusedStackLayer();
710 if (mService.mWatermark != null) {
711 mService.mWatermark.drawIfNeeded();
713 } catch (RuntimeException e) {
714 Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
716 SurfaceControl.closeTransaction();
717 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
718 TAG, "<<< CLOSE TRANSACTION animateLocked");
721 boolean hasPendingLayoutChanges = false;
722 final int numDisplays = mService.mDisplayContents.size();
723 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
724 final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
725 final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
726 if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
727 mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
729 if (pendingChanges != 0) {
730 hasPendingLayoutChanges = true;
734 boolean doRequest = false;
735 if (mBulkUpdateParams != 0) {
736 doRequest = mService.copyAnimToLayoutParamsLocked();
739 if (hasPendingLayoutChanges || doRequest) {
740 mService.requestTraversalLocked();
743 if (!mAnimating && wasAnimating) {
744 mService.requestTraversalLocked();
746 if (WindowManagerService.DEBUG_WINDOW_TRACE) {
747 Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
748 + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
749 + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
750 + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
754 static String bulkUpdateParamsToString(int bulkUpdateParams) {
755 StringBuilder builder = new StringBuilder(128);
756 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
757 builder.append(" UPDATE_ROTATION");
759 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
760 builder.append(" WALLPAPER_MAY_CHANGE");
762 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
763 builder.append(" FORCE_HIDING_CHANGED");
765 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
766 builder.append(" ORIENTATION_CHANGE_COMPLETE");
768 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
769 builder.append(" TURN_ON_SCREEN");
771 return builder.toString();
774 public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
775 final String subPrefix = " " + prefix;
776 final String subSubPrefix = " " + subPrefix;
778 for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
779 pw.print(prefix); pw.print("DisplayContentsAnimator #");
780 pw.print(mDisplayContentsAnimators.keyAt(i));
782 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
783 final WindowList windows =
784 mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i));
785 final int N = windows.size();
786 for (int j = 0; j < N; j++) {
787 WindowStateAnimator wanim = windows.get(j).mWinAnimator;
788 pw.print(subPrefix); pw.print("Window #"); pw.print(j);
789 pw.print(": "); pw.println(wanim);
791 if (displayAnimator.mScreenRotationAnimation != null) {
792 pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
793 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
794 } else if (dumpAll) {
795 pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
802 pw.print(prefix); pw.print("mAnimTransactionSequence=");
803 pw.print(mAnimTransactionSequence);
804 pw.print(" mForceHiding="); pw.println(forceHidingToString());
805 pw.print(prefix); pw.print("mCurrentTime=");
806 pw.println(TimeUtils.formatUptime(mCurrentTime));
808 if (mBulkUpdateParams != 0) {
809 pw.print(prefix); pw.print("mBulkUpdateParams=0x");
810 pw.print(Integer.toHexString(mBulkUpdateParams));
811 pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
813 if (mWindowDetachedWallpaper != null) {
814 pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
815 pw.println(mWindowDetachedWallpaper);
817 if (mUniverseBackground != null) {
818 pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
819 pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
823 int getPendingLayoutChanges(final int displayId) {
827 DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
828 return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
831 void setPendingLayoutChanges(final int displayId, final int changes) {
832 if (displayId >= 0) {
833 DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
834 if (displayContent != null) {
835 displayContent.pendingLayoutChanges |= changes;
840 void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) {
841 // Used to track which displays layout changes have been done.
842 SparseIntArray displays = new SparseIntArray(2);
843 WindowList windows = appAnimator.mAppToken.allAppWindows;
844 for (int i = windows.size() - 1; i >= 0; i--) {
845 final int displayId = windows.get(i).getDisplayId();
846 if (displayId >= 0 && displays.indexOfKey(displayId) < 0) {
847 setPendingLayoutChanges(displayId, changes);
848 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
849 mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId));
851 // Keep from processing this display again.
852 displays.put(displayId, changes);
857 private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
858 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
859 if (displayAnimator == null) {
860 displayAnimator = new DisplayContentsAnimator();
861 mDisplayContentsAnimators.put(displayId, displayAnimator);
863 return displayAnimator;
866 void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
867 if (displayId >= 0) {
868 getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
872 ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
876 return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
879 private class DisplayContentsAnimator {
880 ScreenRotationAnimation mScreenRotationAnimation = null;