1 // Copyright 2012 Google Inc. All Rights Reserved.
3 package com.android.server.wm;
5 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
6 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
8 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
9 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
10 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
11 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
12 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING;
14 import android.content.Context;
15 import android.os.Debug;
16 import android.os.SystemClock;
17 import android.util.Log;
18 import android.util.Slog;
19 import android.util.SparseArray;
20 import android.util.SparseIntArray;
21 import android.util.TimeUtils;
22 import android.util.TypedValue;
23 import android.view.Display;
24 import android.view.Surface;
25 import android.view.SurfaceControl;
26 import android.view.WindowManagerPolicy;
27 import android.view.animation.Animation;
29 import com.android.server.wm.WindowManagerService.DisplayContentsIterator;
30 import com.android.server.wm.WindowManagerService.LayoutFields;
32 import java.io.PrintWriter;
33 import java.util.ArrayList;
36 * Singleton class that carries out the animations and Surface operations in a separate task
37 * on behalf of WindowManagerService.
39 public class WindowAnimator {
40 private static final String TAG = "WindowAnimator";
42 /** Amount of time in milliseconds to animate the dim surface from one value to another,
43 * when no window animation is driving it. */
44 static final int DEFAULT_DIM_DURATION = 200;
46 final WindowManagerService mService;
47 final Context mContext;
48 final WindowManagerPolicy mPolicy;
52 final Runnable mAnimationRunnable;
56 /** Time of current animation step. Reset on each iteration */
59 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
60 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
61 private int mAnimTransactionSequence;
63 /** Window currently running an animation that has requested it be detached
64 * from the wallpaper. This means we need to ensure the wallpaper is
65 * visible behind it in case it animates in a way that would allow it to be
66 * seen. If multiple windows satisfy this, use the lowest window. */
67 WindowState mWindowDetachedWallpaper = null;
69 WindowStateAnimator mUniverseBackground = null;
70 int mAboveUniverseLayer = 0;
72 int mBulkUpdateParams = 0;
73 Object mLastWindowFreezeSource;
75 SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
76 new SparseArray<WindowAnimator.DisplayContentsAnimator>();
78 boolean mInitialized = false;
80 // forceHiding states.
81 static final int KEYGUARD_NOT_SHOWN = 0;
82 static final int KEYGUARD_ANIMATING_IN = 1;
83 static final int KEYGUARD_SHOWN = 2;
84 static final int KEYGUARD_ANIMATING_OUT = 3;
85 int mForceHiding = KEYGUARD_NOT_SHOWN;
87 private String forceHidingToString() {
88 switch (mForceHiding) {
89 case KEYGUARD_NOT_SHOWN: return "KEYGUARD_NOT_SHOWN";
90 case KEYGUARD_ANIMATING_IN: return "KEYGUARD_ANIMATING_IN";
91 case KEYGUARD_SHOWN: return "KEYGUARD_SHOWN";
92 case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
93 default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
97 WindowAnimator(final WindowManagerService service) {
99 mContext = service.mContext;
100 mPolicy = service.mPolicy;
102 mAnimationRunnable = new Runnable() {
105 synchronized (mService.mWindowMap) {
106 mService.mAnimationScheduled = false;
113 void addDisplayLocked(final int displayId) {
114 // Create the DisplayContentsAnimator object by retrieving it.
115 getDisplayContentsAnimatorLocked(displayId);
116 if (displayId == Display.DEFAULT_DISPLAY) {
121 void removeDisplayLocked(final int displayId) {
122 final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
123 if (displayAnimator != null) {
124 if (displayAnimator.mWindowAnimationBackgroundSurface != null) {
125 displayAnimator.mWindowAnimationBackgroundSurface.destroySurface();
126 displayAnimator.mWindowAnimationBackgroundSurface = null;
128 if (displayAnimator.mScreenRotationAnimation != null) {
129 displayAnimator.mScreenRotationAnimation.kill();
130 displayAnimator.mScreenRotationAnimation = null;
132 if (displayAnimator.mDimAnimator != null) {
133 displayAnimator.mDimAnimator.destroySurface();
134 displayAnimator.mDimAnimator = null;
138 mDisplayContentsAnimators.delete(displayId);
141 AppWindowAnimator getWallpaperAppAnimator() {
142 return mService.mWallpaperTarget == null
143 ? null : mService.mWallpaperTarget.mAppToken == null
144 ? null : mService.mWallpaperTarget.mAppToken.mAppAnimator;
147 void hideWallpapersLocked(final WindowState w) {
148 final WindowState wallpaperTarget = mService.mWallpaperTarget;
149 final WindowState lowerWallpaperTarget = mService.mLowerWallpaperTarget;
150 final ArrayList<WindowToken> wallpaperTokens = mService.mWallpaperTokens;
152 if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) {
153 final int numTokens = wallpaperTokens.size();
154 for (int i = numTokens - 1; i >= 0; i--) {
155 final WindowToken token = wallpaperTokens.get(i);
156 final int numWindows = token.windows.size();
157 for (int j = numWindows - 1; j >= 0; j--) {
158 final WindowState wallpaper = token.windows.get(j);
159 final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
160 if (!winAnimator.mLastHidden) {
162 mService.dispatchWallpaperVisibility(wallpaper, false);
163 setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
164 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
167 if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG,
168 "Hiding wallpaper " + token + " from " + w
169 + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget
170 + "\n" + Debug.getCallers(5, " "));
176 private void updateAppWindowsLocked() {
178 final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
179 final int NAT = appTokens.size();
180 for (i=0; i<NAT; i++) {
181 final AppWindowAnimator appAnimator = appTokens.get(i).mAppAnimator;
182 final boolean wasAnimating = appAnimator.animation != null
183 && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
184 if (appAnimator.stepAnimationLocked(mCurrentTime)) {
186 } else if (wasAnimating) {
187 // stopped animating, do one more pass through the layout
188 setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
189 "appToken " + appAnimator.mAppToken + " done");
190 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
191 "updateWindowsApps...: done animating " + appAnimator.mAppToken);
195 final int NEAT = mService.mExitingAppTokens.size();
196 for (i=0; i<NEAT; i++) {
197 final AppWindowAnimator appAnimator = mService.mExitingAppTokens.get(i).mAppAnimator;
198 final boolean wasAnimating = appAnimator.animation != null
199 && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
200 if (appAnimator.stepAnimationLocked(mCurrentTime)) {
202 } else if (wasAnimating) {
203 // stopped animating, do one more pass through the layout
204 setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
205 "exiting appToken " + appAnimator.mAppToken + " done");
206 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
207 "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
212 private void updateWindowsLocked(final int displayId) {
213 ++mAnimTransactionSequence;
215 final WindowList windows = mService.getWindowListLocked(displayId);
216 ArrayList<WindowStateAnimator> unForceHiding = null;
217 boolean wallpaperInUnForceHiding = false;
218 mForceHiding = KEYGUARD_NOT_SHOWN;
220 for (int i = windows.size() - 1; i >= 0; i--) {
221 WindowState win = windows.get(i);
222 WindowStateAnimator winAnimator = win.mWinAnimator;
223 final int flags = winAnimator.mAttrFlags;
225 if (winAnimator.mSurfaceControl != null) {
226 final boolean wasAnimating = winAnimator.mWasAnimating;
227 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
229 if (WindowManagerService.DEBUG_WALLPAPER) {
230 Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
231 ", nowAnimating=" + nowAnimating);
234 if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
235 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
236 setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
237 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
238 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
239 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
240 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
244 if (mPolicy.doesForceHide(win, win.mAttrs)) {
245 if (!wasAnimating && nowAnimating) {
246 if (WindowManagerService.DEBUG_ANIM ||
247 WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
248 "Animation started that could impact force hide: " + win);
249 mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
250 setPendingLayoutChanges(displayId,
251 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
252 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
253 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
254 getPendingLayoutChanges(displayId));
256 mService.mFocusMayChange = true;
258 if (win.isReadyForDisplay()) {
260 if (winAnimator.mAnimationIsEntrance) {
261 mForceHiding = KEYGUARD_ANIMATING_IN;
263 mForceHiding = KEYGUARD_ANIMATING_OUT;
266 mForceHiding = KEYGUARD_SHOWN;
269 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
270 "Force hide " + mForceHiding
271 + " hasSurface=" + win.mHasSurface
272 + " policyVis=" + win.mPolicyVisibility
273 + " destroying=" + win.mDestroying
274 + " attHidden=" + win.mAttachedHidden
275 + " vis=" + win.mViewVisibility
276 + " hidden=" + win.mRootToken.hidden
277 + " anim=" + win.mWinAnimator.mAnimation);
278 } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
279 final boolean hideWhenLocked =
280 (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0;
281 final boolean changed;
282 if (((mForceHiding == KEYGUARD_ANIMATING_IN)
283 && (!winAnimator.isAnimating() || hideWhenLocked))
284 || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
285 changed = win.hideLw(false, false);
286 if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
287 "Now policy hidden: " + win);
289 changed = win.showLw(false, false);
290 if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
291 "Now policy shown: " + win);
293 if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
294 && win.isVisibleNow() /*w.isReadyForDisplay()*/) {
295 if (unForceHiding == null) {
296 unForceHiding = new ArrayList<WindowStateAnimator>();
298 unForceHiding.add(winAnimator);
299 if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
300 wallpaperInUnForceHiding = true;
303 if (mCurrentFocus == null || mCurrentFocus.mLayer < win.mLayer) {
304 // We are showing on to of the current
305 // focus, so re-evaluate focus to make
306 // sure it is correct.
307 mService.mFocusMayChange = true;
311 if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) {
312 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
313 setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
314 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
315 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
316 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
317 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
323 final AppWindowToken atoken = win.mAppToken;
324 if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
325 if (atoken == null || atoken.allDrawn) {
326 if (winAnimator.performShowLocked()) {
327 setPendingLayoutChanges(displayId,
328 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
329 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
330 mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
331 getPendingLayoutChanges(displayId));
336 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
337 if (appAnimator != null && appAnimator.thumbnail != null) {
338 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
339 appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
340 appAnimator.thumbnailLayer = 0;
342 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
343 appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
346 } // end forall windows
348 // If we have windows that are being show due to them no longer
349 // being force-hidden, apply the appropriate animation to them.
350 if (unForceHiding != null) {
351 for (int i=unForceHiding.size()-1; i>=0; i--) {
352 Animation a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding);
354 final WindowStateAnimator winAnimator = unForceHiding.get(i);
355 winAnimator.setAnimation(a);
356 winAnimator.mAnimationIsEntrance = true;
362 private void updateWallpaperLocked(int displayId) {
363 final DisplayContentsAnimator displayAnimator =
364 getDisplayContentsAnimatorLocked(displayId);
365 final WindowList windows = mService.getWindowListLocked(displayId);
366 WindowStateAnimator windowAnimationBackground = null;
367 int windowAnimationBackgroundColor = 0;
368 WindowState detachedWallpaper = null;
370 for (int i = windows.size() - 1; i >= 0; i--) {
371 final WindowState win = windows.get(i);
372 WindowStateAnimator winAnimator = win.mWinAnimator;
373 if (winAnimator.mSurfaceControl == null) {
377 final int flags = winAnimator.mAttrFlags;
379 // If this window is animating, make a note that we have
380 // an animating window and take care of a request to run
381 // a detached wallpaper animation.
382 if (winAnimator.mAnimating) {
383 if (winAnimator.mAnimation != null) {
384 if ((flags & FLAG_SHOW_WALLPAPER) != 0
385 && winAnimator.mAnimation.getDetachWallpaper()) {
386 detachedWallpaper = win;
388 final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
389 if (backgroundColor != 0) {
390 if (windowAnimationBackground == null || (winAnimator.mAnimLayer <
391 windowAnimationBackground.mAnimLayer)) {
392 windowAnimationBackground = winAnimator;
393 windowAnimationBackgroundColor = backgroundColor;
400 // If this window's app token is running a detached wallpaper
401 // animation, make a note so we can ensure the wallpaper is
402 // displayed behind it.
403 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
404 if (appAnimator != null && appAnimator.animation != null
405 && appAnimator.animating) {
406 if ((flags & FLAG_SHOW_WALLPAPER) != 0
407 && appAnimator.animation.getDetachWallpaper()) {
408 detachedWallpaper = win;
411 final int backgroundColor = appAnimator.animation.getBackgroundColor();
412 if (backgroundColor != 0) {
413 if (windowAnimationBackground == null || (winAnimator.mAnimLayer <
414 windowAnimationBackground.mAnimLayer)) {
415 windowAnimationBackground = winAnimator;
416 windowAnimationBackgroundColor = backgroundColor;
420 } // end forall windows
422 if (mWindowDetachedWallpaper != detachedWallpaper) {
423 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
424 "Detached wallpaper changed from " + mWindowDetachedWallpaper
425 + " to " + detachedWallpaper);
426 mWindowDetachedWallpaper = detachedWallpaper;
427 mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
430 if (windowAnimationBackgroundColor != 0) {
431 // If the window that wants black is the current wallpaper
432 // target, then the black goes *below* the wallpaper so we
433 // don't cause the wallpaper to suddenly disappear.
434 int animLayer = windowAnimationBackground.mAnimLayer;
435 WindowState win = windowAnimationBackground.mWin;
436 if (mService.mWallpaperTarget == win || mService.mLowerWallpaperTarget == win
437 || mService.mUpperWallpaperTarget == win) {
438 final int N = windows.size();
439 for (int i = 0; i < N; i++) {
440 WindowStateAnimator winAnimator = windows.get(i).mWinAnimator;
441 if (winAnimator.mIsWallpaper) {
442 animLayer = winAnimator.mAnimLayer;
448 displayAnimator.mWindowAnimationBackgroundSurface.show(
449 animLayer - WindowManagerService.LAYER_OFFSET_DIM,
450 ((windowAnimationBackgroundColor >> 24) & 0xff) / 255f, 0);
452 displayAnimator.mWindowAnimationBackgroundSurface.hide();
456 /** See if any windows have been drawn, so they (and others associated with them) can now be
458 private void testTokenMayBeDrawnLocked() {
459 // See if any windows have been drawn, so they (and others
460 // associated with them) can now be shown.
461 final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
462 final int NT = appTokens.size();
463 for (int i=0; i<NT; i++) {
464 AppWindowToken wtoken = appTokens.get(i);
465 AppWindowAnimator appAnimator = wtoken.mAppAnimator;
466 final boolean allDrawn = wtoken.allDrawn;
467 if (allDrawn != appAnimator.allDrawn) {
468 appAnimator.allDrawn = allDrawn;
470 // The token has now changed state to having all
471 // windows shown... what to do, what to do?
472 if (appAnimator.freezingScreen) {
473 appAnimator.showAllWindowsLocked();
474 mService.unsetAppFreezingScreenLocked(wtoken, false, true);
475 if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
476 "Setting mOrientationChangeComplete=true because wtoken "
477 + wtoken + " numInteresting=" + wtoken.numInterestingWindows
478 + " numDrawn=" + wtoken.numDrawnWindows);
479 // This will set mOrientationChangeComplete and cause a pass through layout.
480 setAppLayoutChanges(appAnimator,
481 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
482 "testTokenMayBeDrawnLocked: freezingScreen");
484 setAppLayoutChanges(appAnimator,
485 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
486 "testTokenMayBeDrawnLocked");
488 // We can now show all of the drawn windows!
489 if (!mService.mOpeningApps.contains(wtoken)) {
490 mAnimating |= appAnimator.showAllWindowsLocked();
498 private void performAnimationsLocked(final int displayId) {
499 updateWindowsLocked(displayId);
500 updateWallpaperLocked(displayId);
503 private long getDimBehindFadeDuration(long duration) {
504 TypedValue tv = new TypedValue();
505 mContext.getResources().getValue(
506 com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true);
507 if (tv.type == TypedValue.TYPE_FRACTION) {
508 duration = (long)tv.getFraction(duration, duration);
509 } else if (tv.type >= TypedValue.TYPE_FIRST_INT && tv.type <= TypedValue.TYPE_LAST_INT) {
515 /** Locked on mService.mWindowMap. */
516 private void animateLocked() {
521 mCurrentTime = SystemClock.uptimeMillis();
522 mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
523 boolean wasAnimating = mAnimating;
525 if (WindowManagerService.DEBUG_WINDOW_TRACE) {
526 Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
529 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
530 TAG, ">>> OPEN TRANSACTION animateLocked");
531 SurfaceControl.openTransaction();
532 SurfaceControl.setAnimationTransaction();
534 updateAppWindowsLocked();
536 final int numDisplays = mDisplayContentsAnimators.size();
537 for (int i = 0; i < numDisplays; i++) {
538 final int displayId = mDisplayContentsAnimators.keyAt(i);
539 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
541 final ScreenRotationAnimation screenRotationAnimation =
542 displayAnimator.mScreenRotationAnimation;
543 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
544 if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
547 mBulkUpdateParams |= SET_UPDATE_ROTATION;
548 screenRotationAnimation.kill();
549 displayAnimator.mScreenRotationAnimation = null;
553 // Update animations of all applications, including those
554 // associated with exiting/removed apps
555 performAnimationsLocked(displayId);
557 final WindowList windows = mService.getWindowListLocked(displayId);
558 final int N = windows.size();
559 for (int j = 0; j < N; j++) {
560 windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
564 testTokenMayBeDrawnLocked();
566 for (int i = 0; i < numDisplays; i++) {
567 final int displayId = mDisplayContentsAnimators.keyAt(i);
568 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
570 final ScreenRotationAnimation screenRotationAnimation =
571 displayAnimator.mScreenRotationAnimation;
572 if (screenRotationAnimation != null) {
573 screenRotationAnimation.updateSurfacesInTransaction();
576 final DimLayer dimAnimator = displayAnimator.mDimAnimator;
577 final WindowStateAnimator winAnimator = displayAnimator.mDimWinAnimator;
579 final float dimAmount;
580 if (winAnimator == null) {
581 dimLayer = dimAnimator.getLayer();
584 dimLayer = winAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM;
585 dimAmount = winAnimator.mWin.mAttrs.dimAmount;
587 final float targetAlpha = dimAnimator.getTargetAlpha();
588 if (targetAlpha != dimAmount) {
589 if (winAnimator == null) {
590 dimAnimator.hide(DEFAULT_DIM_DURATION);
592 long duration = (winAnimator.mAnimating && winAnimator.mAnimation != null)
593 ? winAnimator.mAnimation.computeDurationHint()
594 : DEFAULT_DIM_DURATION;
595 if (targetAlpha > dimAmount) {
596 duration = getDimBehindFadeDuration(duration);
598 dimAnimator.show(dimLayer, dimAmount, duration);
600 } else if (dimAnimator.getLayer() != dimLayer) {
601 dimAnimator.setLayer(dimLayer);
603 if (dimAnimator.isAnimating()) {
604 if (!mService.okToDisplay()) {
605 // Jump to the end of the animation.
608 mAnimating |= dimAnimator.stepAnimation();
612 //TODO (multidisplay): Magnification is supported only for the default display.
613 if (mService.mDisplayMagnifier != null && displayId == Display.DEFAULT_DISPLAY) {
614 mService.mDisplayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
618 if (mService.mWatermark != null) {
619 mService.mWatermark.drawIfNeeded();
621 } catch (RuntimeException e) {
622 Log.wtf(TAG, "Unhandled exception in Window Manager", e);
624 SurfaceControl.closeTransaction();
625 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
626 TAG, "<<< CLOSE TRANSACTION animateLocked");
629 boolean hasPendingLayoutChanges = false;
630 DisplayContentsIterator iterator = mService.new DisplayContentsIterator();
631 while (iterator.hasNext()) {
632 final DisplayContent displayContent = iterator.next();
633 final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
634 if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
635 mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
637 if (pendingChanges != 0) {
638 hasPendingLayoutChanges = true;
642 boolean doRequest = false;
643 if (mBulkUpdateParams != 0) {
644 doRequest = mService.copyAnimToLayoutParamsLocked();
647 if (hasPendingLayoutChanges || doRequest) {
648 mService.requestTraversalLocked();
652 mService.scheduleAnimationLocked();
653 } else if (wasAnimating) {
654 mService.requestTraversalLocked();
656 if (WindowManagerService.DEBUG_WINDOW_TRACE) {
657 Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
658 + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
659 + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
660 + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
664 WindowState mCurrentFocus;
665 void setCurrentFocus(final WindowState currentFocus) {
666 mCurrentFocus = currentFocus;
669 boolean isDimmingLocked(int displayId) {
670 return getDisplayContentsAnimatorLocked(displayId).mDimAnimator.isDimming();
673 boolean isDimmingLocked(final WindowStateAnimator winAnimator) {
674 final int displayId = winAnimator.mWin.getDisplayId();
675 DisplayContentsAnimator displayAnimator =
676 getDisplayContentsAnimatorLocked(displayId);
677 if (displayAnimator != null) {
678 return displayAnimator.mDimWinAnimator == winAnimator
679 && displayAnimator.mDimAnimator.isDimming();
684 static String bulkUpdateParamsToString(int bulkUpdateParams) {
685 StringBuilder builder = new StringBuilder(128);
686 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
687 builder.append(" UPDATE_ROTATION");
689 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
690 builder.append(" WALLPAPER_MAY_CHANGE");
692 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
693 builder.append(" FORCE_HIDING_CHANGED");
695 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
696 builder.append(" ORIENTATION_CHANGE_COMPLETE");
698 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
699 builder.append(" TURN_ON_SCREEN");
701 return builder.toString();
704 public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
705 final String subPrefix = " " + prefix;
706 final String subSubPrefix = " " + subPrefix;
708 for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
709 pw.print(prefix); pw.print("DisplayContentsAnimator #");
710 pw.print(mDisplayContentsAnimators.keyAt(i));
712 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
713 final WindowList windows =
714 mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i));
715 final int N = windows.size();
716 for (int j = 0; j < N; j++) {
717 WindowStateAnimator wanim = windows.get(j).mWinAnimator;
718 pw.print(subPrefix); pw.print("Window #"); pw.print(j);
719 pw.print(": "); pw.println(wanim);
721 if (displayAnimator.mWindowAnimationBackgroundSurface != null) {
722 if (dumpAll || displayAnimator.mWindowAnimationBackgroundSurface.isDimming()) {
723 pw.print(subPrefix); pw.println("mWindowAnimationBackgroundSurface:");
724 displayAnimator.mWindowAnimationBackgroundSurface.printTo(subSubPrefix, pw);
727 if (dumpAll || displayAnimator.mDimAnimator.isDimming()) {
728 pw.print(subPrefix); pw.println("mDimAnimator:");
729 displayAnimator.mDimAnimator.printTo(subSubPrefix, pw);
730 pw.print(subPrefix); pw.print("mDimWinAnimator=");
731 pw.println(displayAnimator.mDimWinAnimator);
733 if (displayAnimator.mScreenRotationAnimation != null) {
734 pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
735 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
736 } else if (dumpAll) {
737 pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
744 pw.print(prefix); pw.print("mAnimTransactionSequence=");
745 pw.print(mAnimTransactionSequence);
746 pw.print(" mForceHiding="); pw.println(forceHidingToString());
747 pw.print(prefix); pw.print("mCurrentTime=");
748 pw.println(TimeUtils.formatUptime(mCurrentTime));
750 if (mBulkUpdateParams != 0) {
751 pw.print(prefix); pw.print("mBulkUpdateParams=0x");
752 pw.print(Integer.toHexString(mBulkUpdateParams));
753 pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
755 if (mWindowDetachedWallpaper != null) {
756 pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
757 pw.println(mWindowDetachedWallpaper);
759 if (mUniverseBackground != null) {
760 pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
761 pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
765 int getPendingLayoutChanges(final int displayId) {
766 return mService.getDisplayContentLocked(displayId).pendingLayoutChanges;
769 void setPendingLayoutChanges(final int displayId, final int changes) {
770 mService.getDisplayContentLocked(displayId).pendingLayoutChanges |= changes;
773 void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) {
774 // Used to track which displays layout changes have been done.
775 SparseIntArray displays = new SparseIntArray();
776 WindowList windows = appAnimator.mAppToken.allAppWindows;
777 for (int i = windows.size() - 1; i >= 0; i--) {
778 final int displayId = windows.get(i).getDisplayId();
779 if (displays.indexOfKey(displayId) < 0) {
780 setPendingLayoutChanges(displayId, changes);
781 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
782 mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId));
784 // Keep from processing this display again.
785 displays.put(displayId, changes);
790 void setDimWinAnimatorLocked(int displayId, WindowStateAnimator newWinAnimator) {
791 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
792 if (newWinAnimator == null) {
793 displayAnimator.mDimWinAnimator = null;
795 // Only set dim params on the highest dimmed layer.
796 final WindowStateAnimator existingDimWinAnimator = displayAnimator.mDimWinAnimator;
797 // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer.
798 if (newWinAnimator.mSurfaceShown && (existingDimWinAnimator == null
799 || !existingDimWinAnimator.mSurfaceShown
800 || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
801 displayAnimator.mDimWinAnimator = newWinAnimator;
806 private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
807 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
808 if (displayAnimator == null) {
809 displayAnimator = new DisplayContentsAnimator(displayId);
810 mDisplayContentsAnimators.put(displayId, displayAnimator);
812 return displayAnimator;
815 void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
816 getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
819 ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
820 return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
823 private class DisplayContentsAnimator {
824 DimLayer mDimAnimator = null;
825 WindowStateAnimator mDimWinAnimator = null;
826 DimLayer mWindowAnimationBackgroundSurface = null;
827 ScreenRotationAnimation mScreenRotationAnimation = null;
829 public DisplayContentsAnimator(int displayId) {
830 mDimAnimator = new DimLayer(mService, displayId);
831 mWindowAnimationBackgroundSurface = new DimLayer(mService, displayId);