OSDN Git Service

054a0759658aaf74e9e5ea7b2a73f21f8d698c78
[android-x86/frameworks-base.git] / services / java / com / android / server / wm / WindowAnimator.java
1 // Copyright 2012 Google Inc. All Rights Reserved.
2
3 package com.android.server.wm;
4
5 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
6 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
7
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;
13
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;
28
29 import com.android.server.wm.WindowManagerService.DisplayContentsIterator;
30 import com.android.server.wm.WindowManagerService.LayoutFields;
31
32 import java.io.PrintWriter;
33 import java.util.ArrayList;
34
35 /**
36  * Singleton class that carries out the animations and Surface operations in a separate task
37  * on behalf of WindowManagerService.
38  */
39 public class WindowAnimator {
40     private static final String TAG = "WindowAnimator";
41
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;
45
46     final WindowManagerService mService;
47     final Context mContext;
48     final WindowManagerPolicy mPolicy;
49
50     boolean mAnimating;
51
52     final Runnable mAnimationRunnable;
53
54     int mAdjResult;
55
56     /** Time of current animation step. Reset on each iteration */
57     long mCurrentTime;
58
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;
62
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;
68
69     WindowStateAnimator mUniverseBackground = null;
70     int mAboveUniverseLayer = 0;
71
72     int mBulkUpdateParams = 0;
73     Object mLastWindowFreezeSource;
74
75     SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
76             new SparseArray<WindowAnimator.DisplayContentsAnimator>();
77
78     boolean mInitialized = false;
79
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;
86
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;
94         }
95     }
96
97     WindowAnimator(final WindowManagerService service) {
98         mService = service;
99         mContext = service.mContext;
100         mPolicy = service.mPolicy;
101
102         mAnimationRunnable = new Runnable() {
103             @Override
104             public void run() {
105                 synchronized (mService.mWindowMap) {
106                     mService.mAnimationScheduled = false;
107                     animateLocked();
108                 }
109             }
110         };
111     }
112
113     void addDisplayLocked(final int displayId) {
114         // Create the DisplayContentsAnimator object by retrieving it.
115         getDisplayContentsAnimatorLocked(displayId);
116         if (displayId == Display.DEFAULT_DISPLAY) {
117             mInitialized = true;
118         }
119     }
120
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;
127             }
128             if (displayAnimator.mScreenRotationAnimation != null) {
129                 displayAnimator.mScreenRotationAnimation.kill();
130                 displayAnimator.mScreenRotationAnimation = null;
131             }
132             if (displayAnimator.mDimAnimator != null) {
133                 displayAnimator.mDimAnimator.destroySurface();
134                 displayAnimator.mDimAnimator = null;
135             }
136         }
137
138         mDisplayContentsAnimators.delete(displayId);
139     }
140
141     AppWindowAnimator getWallpaperAppAnimator() {
142         return mService.mWallpaperTarget == null
143                 ? null : mService.mWallpaperTarget.mAppToken == null
144                         ? null : mService.mWallpaperTarget.mAppToken.mAppAnimator;
145     }
146
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;
151
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) {
161                         winAnimator.hide();
162                         mService.dispatchWallpaperVisibility(wallpaper, false);
163                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
164                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
165                     }
166                 }
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, "  "));
171                 token.hidden = true;
172             }
173         }
174     }
175
176     private void updateAppWindowsLocked() {
177         int i;
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)) {
185                 mAnimating = true;
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);
192             }
193         }
194
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)) {
201                 mAnimating = true;
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);
208             }
209         }
210     }
211
212     private void updateWindowsLocked(final int displayId) {
213         ++mAnimTransactionSequence;
214
215         final WindowList windows = mService.getWindowListLocked(displayId);
216         ArrayList<WindowStateAnimator> unForceHiding = null;
217         boolean wallpaperInUnForceHiding = false;
218         mForceHiding = KEYGUARD_NOT_SHOWN;
219
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;
224
225             if (winAnimator.mSurfaceControl != null) {
226                 final boolean wasAnimating = winAnimator.mWasAnimating;
227                 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
228
229                 if (WindowManagerService.DEBUG_WALLPAPER) {
230                     Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
231                             ", nowAnimating=" + nowAnimating);
232                 }
233
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));
241                     }
242                 }
243
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));
255                         }
256                         mService.mFocusMayChange = true;
257                     }
258                     if (win.isReadyForDisplay()) {
259                         if (nowAnimating) {
260                             if (winAnimator.mAnimationIsEntrance) {
261                                 mForceHiding = KEYGUARD_ANIMATING_IN;
262                             } else {
263                                 mForceHiding = KEYGUARD_ANIMATING_OUT;
264                             }
265                         } else {
266                             mForceHiding = KEYGUARD_SHOWN;
267                         }
268                     }
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);
288                     } else {
289                         changed = win.showLw(false, false);
290                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
291                                 "Now policy shown: " + win);
292                         if (changed) {
293                             if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
294                                     && win.isVisibleNow() /*w.isReadyForDisplay()*/) {
295                                 if (unForceHiding == null) {
296                                     unForceHiding = new ArrayList<WindowStateAnimator>();
297                                 }
298                                 unForceHiding.add(winAnimator);
299                                 if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
300                                     wallpaperInUnForceHiding = true;
301                                 }
302                             }
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;
308                             }
309                         }
310                     }
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));
318                         }
319                     }
320                 }
321             }
322
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));
332                         }
333                     }
334                 }
335             }
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;
341                 }
342                 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
343                     appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
344                 }
345             }
346         } // end forall windows
347
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);
353                 if (a != null) {
354                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
355                     winAnimator.setAnimation(a);
356                     winAnimator.mAnimationIsEntrance = true;
357                 }
358             }
359         }
360     }
361
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;
369
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) {
374                 continue;
375             }
376
377             final int flags = winAnimator.mAttrFlags;
378
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;
387                     }
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;
394                         }
395                     }
396                 }
397                 mAnimating = true;
398             }
399
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;
409                 }
410
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;
417                     }
418                 }
419             }
420         } // end forall windows
421
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;
428         }
429
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;
443                         break;
444                     }
445                 }
446             }
447
448             displayAnimator.mWindowAnimationBackgroundSurface.show(
449                     animLayer - WindowManagerService.LAYER_OFFSET_DIM,
450                     ((windowAnimationBackgroundColor >> 24) & 0xff) / 255f, 0);
451         } else {
452             displayAnimator.mWindowAnimationBackgroundSurface.hide();
453         }
454     }
455
456     /** See if any windows have been drawn, so they (and others associated with them) can now be
457      *  shown. */
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;
469                 if (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");
483                     } else {
484                         setAppLayoutChanges(appAnimator,
485                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
486                                 "testTokenMayBeDrawnLocked");
487
488                         // We can now show all of the drawn windows!
489                         if (!mService.mOpeningApps.contains(wtoken)) {
490                             mAnimating |= appAnimator.showAllWindowsLocked();
491                         }
492                     }
493                 }
494             }
495         }
496     }
497
498     private void performAnimationsLocked(final int displayId) {
499         updateWindowsLocked(displayId);
500         updateWallpaperLocked(displayId);
501     }
502
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) {
510             duration = tv.data;
511         }
512         return duration;
513     }
514
515     /** Locked on mService.mWindowMap. */
516     private void animateLocked() {
517         if (!mInitialized) {
518             return;
519         }
520
521         mCurrentTime = SystemClock.uptimeMillis();
522         mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
523         boolean wasAnimating = mAnimating;
524         mAnimating = false;
525         if (WindowManagerService.DEBUG_WINDOW_TRACE) {
526             Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
527         }
528
529         if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
530                 TAG, ">>> OPEN TRANSACTION animateLocked");
531         SurfaceControl.openTransaction();
532         SurfaceControl.setAnimationTransaction();
533         try {
534             updateAppWindowsLocked();
535
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);
540
541                 final ScreenRotationAnimation screenRotationAnimation =
542                         displayAnimator.mScreenRotationAnimation;
543                 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
544                     if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
545                         mAnimating = true;
546                     } else {
547                         mBulkUpdateParams |= SET_UPDATE_ROTATION;
548                         screenRotationAnimation.kill();
549                         displayAnimator.mScreenRotationAnimation = null;
550                     }
551                 }
552
553                 // Update animations of all applications, including those
554                 // associated with exiting/removed apps
555                 performAnimationsLocked(displayId);
556
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);
561                 }
562             }
563
564             testTokenMayBeDrawnLocked();
565
566             for (int i = 0; i < numDisplays; i++) {
567                 final int displayId = mDisplayContentsAnimators.keyAt(i);
568                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
569
570                 final ScreenRotationAnimation screenRotationAnimation =
571                         displayAnimator.mScreenRotationAnimation;
572                 if (screenRotationAnimation != null) {
573                     screenRotationAnimation.updateSurfacesInTransaction();
574                 }
575
576                 final DimLayer dimAnimator = displayAnimator.mDimAnimator;
577                 final WindowStateAnimator winAnimator = displayAnimator.mDimWinAnimator;
578                 final int dimLayer;
579                 final float dimAmount;
580                 if (winAnimator == null) {
581                     dimLayer = dimAnimator.getLayer();
582                     dimAmount = 0;
583                 } else {
584                     dimLayer = winAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM;
585                     dimAmount = winAnimator.mWin.mAttrs.dimAmount;
586                 }
587                 final float targetAlpha = dimAnimator.getTargetAlpha();
588                 if (targetAlpha != dimAmount) {
589                     if (winAnimator == null) {
590                         dimAnimator.hide(DEFAULT_DIM_DURATION);
591                     } else {
592                         long duration = (winAnimator.mAnimating && winAnimator.mAnimation != null)
593                                 ? winAnimator.mAnimation.computeDurationHint()
594                                 : DEFAULT_DIM_DURATION;
595                         if (targetAlpha > dimAmount) {
596                             duration = getDimBehindFadeDuration(duration);
597                         }
598                         dimAnimator.show(dimLayer, dimAmount, duration);
599                     }
600                 } else if (dimAnimator.getLayer() != dimLayer) {
601                     dimAnimator.setLayer(dimLayer);
602                 }
603                 if (dimAnimator.isAnimating()) {
604                     if (!mService.okToDisplay()) {
605                         // Jump to the end of the animation.
606                         dimAnimator.show();
607                     } else {
608                         mAnimating |= dimAnimator.stepAnimation();
609                     }
610                 }
611
612                 //TODO (multidisplay): Magnification is supported only for the default display.
613                 if (mService.mDisplayMagnifier != null && displayId == Display.DEFAULT_DISPLAY) {
614                     mService.mDisplayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
615                 }
616             }
617
618             if (mService.mWatermark != null) {
619                 mService.mWatermark.drawIfNeeded();
620             }
621         } catch (RuntimeException e) {
622             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
623         } finally {
624             SurfaceControl.closeTransaction();
625             if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
626                     TAG, "<<< CLOSE TRANSACTION animateLocked");
627         }
628
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;
636             }
637             if (pendingChanges != 0) {
638                 hasPendingLayoutChanges = true;
639             }
640         }
641
642         boolean doRequest = false;
643         if (mBulkUpdateParams != 0) {
644             doRequest = mService.copyAnimToLayoutParamsLocked();
645         }
646
647         if (hasPendingLayoutChanges || doRequest) {
648             mService.requestTraversalLocked();
649         }
650
651         if (mAnimating) {
652             mService.scheduleAnimationLocked();
653         } else if (wasAnimating) {
654             mService.requestTraversalLocked();
655         }
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)));
661         }
662     }
663
664     WindowState mCurrentFocus;
665     void setCurrentFocus(final WindowState currentFocus) {
666         mCurrentFocus = currentFocus;
667     }
668
669     boolean isDimmingLocked(int displayId) {
670         return getDisplayContentsAnimatorLocked(displayId).mDimAnimator.isDimming();
671     }
672
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();
680         }
681         return false;
682     }
683
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");
688         }
689         if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
690             builder.append(" WALLPAPER_MAY_CHANGE");
691         }
692         if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
693             builder.append(" FORCE_HIDING_CHANGED");
694         }
695         if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
696             builder.append(" ORIENTATION_CHANGE_COMPLETE");
697         }
698         if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
699             builder.append(" TURN_ON_SCREEN");
700         }
701         return builder.toString();
702     }
703
704     public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
705         final String subPrefix = "  " + prefix;
706         final String subSubPrefix = "  " + subPrefix;
707
708         for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
709             pw.print(prefix); pw.print("DisplayContentsAnimator #");
710                     pw.print(mDisplayContentsAnimators.keyAt(i));
711                     pw.println(":");
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);
720             }
721             if (displayAnimator.mWindowAnimationBackgroundSurface != null) {
722                 if (dumpAll || displayAnimator.mWindowAnimationBackgroundSurface.isDimming()) {
723                     pw.print(subPrefix); pw.println("mWindowAnimationBackgroundSurface:");
724                     displayAnimator.mWindowAnimationBackgroundSurface.printTo(subSubPrefix, pw);
725                 }
726             }
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);
732             }
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 ");
738             }
739         }
740
741         pw.println();
742
743         if (dumpAll) {
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));
749         }
750         if (mBulkUpdateParams != 0) {
751             pw.print(prefix); pw.print("mBulkUpdateParams=0x");
752                     pw.print(Integer.toHexString(mBulkUpdateParams));
753                     pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
754         }
755         if (mWindowDetachedWallpaper != null) {
756             pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
757                 pw.println(mWindowDetachedWallpaper);
758         }
759         if (mUniverseBackground != null) {
760             pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
761                     pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
762         }
763     }
764
765     int getPendingLayoutChanges(final int displayId) {
766         return mService.getDisplayContentLocked(displayId).pendingLayoutChanges;
767     }
768
769     void setPendingLayoutChanges(final int displayId, final int changes) {
770         mService.getDisplayContentLocked(displayId).pendingLayoutChanges |= changes;
771     }
772
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));
783                 }
784                 // Keep from processing this display again.
785                 displays.put(displayId, changes);
786             }
787         }
788     }
789
790     void setDimWinAnimatorLocked(int displayId, WindowStateAnimator newWinAnimator) {
791         DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
792         if (newWinAnimator == null) {
793             displayAnimator.mDimWinAnimator = null;
794         } else {
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;
802             }
803         }
804     }
805
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);
811         }
812         return displayAnimator;
813     }
814
815     void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
816         getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
817     }
818
819     ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
820         return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
821     }
822
823     private class DisplayContentsAnimator {
824         DimLayer mDimAnimator = null;
825         WindowStateAnimator mDimWinAnimator = null;
826         DimLayer mWindowAnimationBackgroundSurface = null;
827         ScreenRotationAnimation mScreenRotationAnimation = null;
828
829         public DisplayContentsAnimator(int displayId) {
830             mDimAnimator = new DimLayer(mService, displayId);
831             mWindowAnimationBackgroundSurface = new DimLayer(mService, displayId);
832         }
833     }
834 }