OSDN Git Service

DO NOT MERGE fix build breakage on k am: 4e33c4f8b1 am: 07c994012c am: 84f479f6b5...
[android-x86/frameworks-base.git] / services / core / java / com / android / server / wm / WindowAnimator.java
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.android.server.wm;
18
19 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
20 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
21
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;
31
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;
44
45 import com.android.server.wm.WindowManagerService.LayoutFields;
46
47 import java.io.PrintWriter;
48 import java.util.ArrayList;
49
50 /**
51  * Singleton class that carries out the animations and Surface operations in a separate task
52  * on behalf of WindowManagerService.
53  */
54 public class WindowAnimator {
55     private static final String TAG = "WindowAnimator";
56
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;
59
60     final WindowManagerService mService;
61     final Context mContext;
62     final WindowManagerPolicy mPolicy;
63
64     boolean mAnimating;
65
66     final Runnable mAnimationRunnable;
67
68     /** Time of current animation step. Reset on each iteration */
69     long mCurrentTime;
70
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;
74
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;
80
81     WindowStateAnimator mUniverseBackground = null;
82     int mAboveUniverseLayer = 0;
83
84     int mBulkUpdateParams = 0;
85     Object mLastWindowFreezeSource;
86
87     SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
88             new SparseArray<DisplayContentsAnimator>(2);
89
90     boolean mInitialized = false;
91
92     boolean mKeyguardGoingAway;
93     boolean mKeyguardGoingAwayToNotificationShade;
94     boolean mKeyguardGoingAwayDisableWindowAnimations;
95
96     /** Use one animation for all entering activities after keyguard is dismissed. */
97     Animation mPostKeyguardExitAnimation;
98
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;
105
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;
113         }
114     }
115
116     WindowAnimator(final WindowManagerService service) {
117         mService = service;
118         mContext = service.mContext;
119         mPolicy = service.mPolicy;
120
121         mAnimationRunnable = new Runnable() {
122             @Override
123             public void run() {
124                 synchronized (mService.mWindowMap) {
125                     mService.mAnimationScheduled = false;
126                     animateLocked();
127                 }
128             }
129         };
130     }
131
132     void addDisplayLocked(final int displayId) {
133         // Create the DisplayContentsAnimator object by retrieving it.
134         getDisplayContentsAnimatorLocked(displayId);
135         if (displayId == Display.DEFAULT_DISPLAY) {
136             mInitialized = true;
137         }
138     }
139
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;
146             }
147         }
148
149         mDisplayContentsAnimators.delete(displayId);
150     }
151
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;
156
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) {
166                         winAnimator.hide();
167                         mService.dispatchWallpaperVisibility(wallpaper, false);
168                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
169                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
170                     }
171                 }
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, "  "));
176                 token.hidden = true;
177             }
178         }
179     }
180
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)) {
193                         mAnimating = true;
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);
201                     }
202                 }
203             }
204
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)) {
212                     mAnimating = true;
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);
219                 }
220             }
221         }
222     }
223
224     private boolean shouldForceHide(WindowState win) {
225         final WindowState imeTarget = mService.mInputMethodTarget;
226         final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
227                 (imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
228
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);
240     }
241
242     private void updateWindowsLocked(final int displayId) {
243         ++mAnimTransactionSequence;
244
245         final WindowList windows = mService.getWindowListLocked(displayId);
246
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)) {
251                     continue;
252                 }
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");
258
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;
264                     }
265                 } else {
266                     if (DEBUG_KEYGUARD) Slog.d(TAG,
267                             "updateWindowsLocked: StatusBar is no longer keyguard");
268                     mKeyguardGoingAway = false;
269                     winAnimator.clearAnimation();
270                 }
271                 break;
272             }
273         }
274
275         mForceHiding = KEYGUARD_NOT_SHOWN;
276
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;
291
292                 if (WindowManagerService.DEBUG_WALLPAPER) {
293                     Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
294                             ", nowAnimating=" + nowAnimating);
295                 }
296
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));
304                     }
305                 }
306
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));
318                         }
319                         mService.mFocusMayChange = true;
320                     } else if (mKeyguardGoingAway && !nowAnimating) {
321                         // Timeout!!
322                         Slog.e(TAG, "Timeout waiting for animation to startup");
323                         mPolicy.startKeyguardExitAnimation(0, 0);
324                         mKeyguardGoingAway = false;
325                     }
326                     if (win.isReadyForDisplay()) {
327                         if (nowAnimating) {
328                             if (winAnimator.mAnimationIsEntrance) {
329                                 mForceHiding = KEYGUARD_ANIMATING_IN;
330                             } else {
331                                 mForceHiding = KEYGUARD_ANIMATING_OUT;
332                             }
333                         } else {
334                             mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
335                         }
336                     }
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
350                             continue;
351                         }
352                         if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
353                                 "Now policy hidden: " + win);
354                     } else {
355                         boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
356                                 && !winAnimator.mKeyguardGoingAwayAnimation
357                                 && win.hasDrawnLw()
358                                 && win.mAttachedWindow == null
359                                 && mForceHiding != KEYGUARD_NOT_SHOWN;
360
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) {
364                             continue;
365                         }
366                         final boolean visibleNow = win.isVisibleNow();
367                         if (!visibleNow) {
368                             // Couldn't really show, must showLw() again when win becomes visible.
369                             win.hideLw(false, false);
370                             continue;
371                         }
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<>();
378                             }
379                             unForceHiding.add(winAnimator);
380                             if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
381                                 wallpaperInUnForceHiding = true;
382                             }
383                             if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
384                                 startingInUnForceHiding = true;
385                             }
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="
391                                             + win);
392                             Animation a = mPolicy.createForceHideEnterAnimation(
393                                     false, mKeyguardGoingAwayToNotificationShade);
394                             winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime());
395                             winAnimator.mKeyguardGoingAwayAnimation = true;
396                         }
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;
405                         }
406                     }
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));
414                         }
415                     }
416                 }
417             }
418
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);
424                 } else {
425                     win.showLw(false, false);
426                 }
427             }
428
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));
438                         }
439                     }
440                 }
441             }
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;
447                 }
448                 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
449                     appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
450                 }
451             }
452             if (win.mIsWallpaper) {
453                 wallpaper = win;
454             }
455         } // end forall windows
456
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
459         // disabled.
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);
468                     if (a != null) {
469                         if (DEBUG_KEYGUARD) Slog.v(TAG,
470                                 "Starting keyguard exit animation on window " + winAnimator.mWin);
471                         winAnimator.setAnimation(a);
472                         winAnimator.mKeyguardGoingAwayAnimation = true;
473                         if (first) {
474                             mPostKeyguardExitAnimation = a;
475                             mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
476                             first = false;
477                         }
478                     }
479                 }
480             } else if (mKeyguardGoingAway) {
481                 mPolicy.startKeyguardExitAnimation(mCurrentTime, 0 /* duration */);
482                 mKeyguardGoingAway = false;
483             }
484
485
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);
492                 if (a != null) {
493                     wallpaper.mWinAnimator.setAnimation(a);
494                 }
495             }
496         }
497
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;
510             }
511         }
512     }
513
514     private void updateWallpaperLocked(int displayId) {
515         mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
516
517         final WindowList windows = mService.getWindowListLocked(displayId);
518         WindowState detachedWallpaper = null;
519
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) {
524                 continue;
525             }
526
527             final int flags = win.mAttrs.flags;
528
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;
537                     }
538                     final int color = winAnimator.mAnimation.getBackgroundColor();
539                     if (color != 0) {
540                         final TaskStack stack = win.getStack();
541                         if (stack != null) {
542                             stack.setAnimationBackground(winAnimator, color);
543                         }
544                     }
545                 }
546                 mAnimating = true;
547             }
548
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;
558                 }
559
560                 final int color = appAnimator.animation.getBackgroundColor();
561                 if (color != 0) {
562                     final TaskStack stack = win.getStack();
563                     if (stack != null) {
564                         stack.setAnimationBackground(winAnimator, color);
565                     }
566                 }
567             }
568         } // end forall windows
569
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;
576         }
577     }
578
579     /** See if any windows have been drawn, so they (and others associated with them) can now be
580      *  shown. */
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;
595                     if (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");
609                         } else {
610                             setAppLayoutChanges(appAnimator,
611                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
612                                     "testTokenMayBeDrawnLocked");
613
614                             // We can now show all of the drawn windows!
615                             if (!mService.mOpeningApps.contains(wtoken)) {
616                                 mAnimating |= appAnimator.showAllWindowsLocked();
617                             }
618                         }
619                     }
620                 }
621             }
622         }
623     }
624
625
626     /** Locked on mService.mWindowMap. */
627     private void animateLocked() {
628         if (!mInitialized) {
629             return;
630         }
631
632         mCurrentTime = SystemClock.uptimeMillis();
633         mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
634         boolean wasAnimating = mAnimating;
635         mAnimating = false;
636         if (WindowManagerService.DEBUG_WINDOW_TRACE) {
637             Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
638         }
639
640         if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
641                 TAG, ">>> OPEN TRANSACTION animateLocked");
642         SurfaceControl.openTransaction();
643         SurfaceControl.setAnimationTransaction();
644         try {
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);
650
651                 final ScreenRotationAnimation screenRotationAnimation =
652                         displayAnimator.mScreenRotationAnimation;
653                 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
654                     if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
655                         mAnimating = true;
656                     } else {
657                         mBulkUpdateParams |= SET_UPDATE_ROTATION;
658                         screenRotationAnimation.kill();
659                         displayAnimator.mScreenRotationAnimation = null;
660
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);
668                         }
669                     }
670                 }
671
672                 // Update animations of all applications, including those
673                 // associated with exiting/removed apps
674                 updateWindowsLocked(displayId);
675                 updateWallpaperLocked(displayId);
676
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);
681                 }
682             }
683
684             for (int i = 0; i < numDisplays; i++) {
685                 final int displayId = mDisplayContentsAnimators.keyAt(i);
686
687                 testTokenMayBeDrawnLocked(displayId);
688
689                 final ScreenRotationAnimation screenRotationAnimation =
690                         mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
691                 if (screenRotationAnimation != null) {
692                     screenRotationAnimation.updateSurfacesInTransaction();
693                 }
694
695                 mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();
696
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();
701                 }
702             }
703
704             if (mAnimating) {
705                 mService.scheduleAnimationLocked();
706             }
707
708             mService.setFocusedStackLayer();
709
710             if (mService.mWatermark != null) {
711                 mService.mWatermark.drawIfNeeded();
712             }
713         } catch (RuntimeException e) {
714             Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
715         } finally {
716             SurfaceControl.closeTransaction();
717             if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
718                     TAG, "<<< CLOSE TRANSACTION animateLocked");
719         }
720
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;
728             }
729             if (pendingChanges != 0) {
730                 hasPendingLayoutChanges = true;
731             }
732         }
733
734         boolean doRequest = false;
735         if (mBulkUpdateParams != 0) {
736             doRequest = mService.copyAnimToLayoutParamsLocked();
737         }
738
739         if (hasPendingLayoutChanges || doRequest) {
740             mService.requestTraversalLocked();
741         }
742
743         if (!mAnimating && wasAnimating) {
744             mService.requestTraversalLocked();
745         }
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)));
751         }
752     }
753
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");
758         }
759         if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
760             builder.append(" WALLPAPER_MAY_CHANGE");
761         }
762         if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
763             builder.append(" FORCE_HIDING_CHANGED");
764         }
765         if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
766             builder.append(" ORIENTATION_CHANGE_COMPLETE");
767         }
768         if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
769             builder.append(" TURN_ON_SCREEN");
770         }
771         return builder.toString();
772     }
773
774     public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
775         final String subPrefix = "  " + prefix;
776         final String subSubPrefix = "  " + subPrefix;
777
778         for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
779             pw.print(prefix); pw.print("DisplayContentsAnimator #");
780                     pw.print(mDisplayContentsAnimators.keyAt(i));
781                     pw.println(":");
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);
790             }
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 ");
796             }
797         }
798
799         pw.println();
800
801         if (dumpAll) {
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));
807         }
808         if (mBulkUpdateParams != 0) {
809             pw.print(prefix); pw.print("mBulkUpdateParams=0x");
810                     pw.print(Integer.toHexString(mBulkUpdateParams));
811                     pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
812         }
813         if (mWindowDetachedWallpaper != null) {
814             pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
815                 pw.println(mWindowDetachedWallpaper);
816         }
817         if (mUniverseBackground != null) {
818             pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
819                     pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
820         }
821     }
822
823     int getPendingLayoutChanges(final int displayId) {
824         if (displayId < 0) {
825             return 0;
826         }
827         DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
828         return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
829     }
830
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;
836             }
837         }
838     }
839
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));
850                 }
851                 // Keep from processing this display again.
852                 displays.put(displayId, changes);
853             }
854         }
855     }
856
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);
862         }
863         return displayAnimator;
864     }
865
866     void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
867         if (displayId >= 0) {
868             getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
869         }
870     }
871
872     ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
873         if (displayId < 0) {
874             return null;
875         }
876         return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
877     }
878
879     private class DisplayContentsAnimator {
880         ScreenRotationAnimation mScreenRotationAnimation = null;
881     }
882 }