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 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
22 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
23 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
24 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
25 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
26 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
27 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
28 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
29 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
30 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
31 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
32 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
33 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
34 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
35 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
36 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
37 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
38 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
39 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
40 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
41 import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
42 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
43 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
44 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
45 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
46 
47 import android.content.Context;
48 import android.os.Trace;
49 import android.util.Slog;
50 import android.util.SparseArray;
51 import android.util.TimeUtils;
52 import android.view.Choreographer;
53 import android.view.Display;
54 import android.view.SurfaceControl;
55 import android.view.WindowManagerPolicy;
56 import android.view.animation.AlphaAnimation;
57 import android.view.animation.Animation;
58 
59 import java.io.PrintWriter;
60 import java.util.ArrayList;
61 
62 /**
63  * Singleton class that carries out the animations and Surface operations in a separate task
64  * on behalf of WindowManagerService.
65  */
66 public class WindowAnimator {
67     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowAnimator" : TAG_WM;
68 
69     /** How long to give statusbar to clear the private keyguard flag when animating out */
70     private static final long KEYGUARD_ANIM_TIMEOUT_MS = 1000;
71 
72     final WindowManagerService mService;
73     final Context mContext;
74     final WindowManagerPolicy mPolicy;
75     private final WindowSurfacePlacer mWindowPlacerLocked;
76 
77     /** Is any window animating? */
78     private boolean mAnimating;
79 
80     /** Is any app window animating? */
81     boolean mAppWindowAnimating;
82 
83     final Choreographer.FrameCallback mAnimationFrameCallback;
84 
85     /** Time of current animation step. Reset on each iteration */
86     long mCurrentTime;
87 
88     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
89      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
90     private int mAnimTransactionSequence;
91 
92     /** Window currently running an animation that has requested it be detached
93      * from the wallpaper.  This means we need to ensure the wallpaper is
94      * visible behind it in case it animates in a way that would allow it to be
95      * seen. If multiple windows satisfy this, use the lowest window. */
96     WindowState mWindowDetachedWallpaper = null;
97 
98     int mBulkUpdateParams = 0;
99     Object mLastWindowFreezeSource;
100 
101     SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
102 
103     boolean mInitialized = false;
104 
105     boolean mKeyguardGoingAway;
106     int mKeyguardGoingAwayFlags;
107 
108     /** Use one animation for all entering activities after keyguard is dismissed. */
109     Animation mPostKeyguardExitAnimation;
110 
111     // forceHiding states.
112     static final int KEYGUARD_NOT_SHOWN     = 0;
113     static final int KEYGUARD_SHOWN         = 1;
114     static final int KEYGUARD_ANIMATING_OUT = 2;
115     int mForceHiding = KEYGUARD_NOT_SHOWN;
116 
117     // When set to true the animator will go over all windows after an animation frame is posted and
118     // check if some got replaced and can be removed.
119     private boolean mRemoveReplacedWindows = false;
120 
forceHidingToString()121     private String forceHidingToString() {
122         switch (mForceHiding) {
123             case KEYGUARD_NOT_SHOWN:    return "KEYGUARD_NOT_SHOWN";
124             case KEYGUARD_SHOWN:        return "KEYGUARD_SHOWN";
125             case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
126             default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
127         }
128     }
129 
WindowAnimator(final WindowManagerService service)130     WindowAnimator(final WindowManagerService service) {
131         mService = service;
132         mContext = service.mContext;
133         mPolicy = service.mPolicy;
134         mWindowPlacerLocked = service.mWindowPlacerLocked;
135 
136         mAnimationFrameCallback = new Choreographer.FrameCallback() {
137             public void doFrame(long frameTimeNs) {
138                 synchronized (mService.mWindowMap) {
139                     mService.mAnimationScheduled = false;
140                     animateLocked(frameTimeNs);
141                 }
142             }
143         };
144     }
145 
addDisplayLocked(final int displayId)146     void addDisplayLocked(final int displayId) {
147         // Create the DisplayContentsAnimator object by retrieving it.
148         getDisplayContentsAnimatorLocked(displayId);
149         if (displayId == Display.DEFAULT_DISPLAY) {
150             mInitialized = true;
151         }
152     }
153 
removeDisplayLocked(final int displayId)154     void removeDisplayLocked(final int displayId) {
155         final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
156         if (displayAnimator != null) {
157             if (displayAnimator.mScreenRotationAnimation != null) {
158                 displayAnimator.mScreenRotationAnimation.kill();
159                 displayAnimator.mScreenRotationAnimation = null;
160             }
161         }
162 
163         mDisplayContentsAnimators.delete(displayId);
164     }
165 
updateAppWindowsLocked(int displayId)166     private void updateAppWindowsLocked(int displayId) {
167         ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks();
168         for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
169             final TaskStack stack = stacks.get(stackNdx);
170             final ArrayList<Task> tasks = stack.getTasks();
171             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
172                 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
173                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
174                     final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
175                     appAnimator.wasAnimating = appAnimator.animating;
176                     if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
177                         appAnimator.animating = true;
178                         setAnimating(true);
179                         mAppWindowAnimating = true;
180                     } else if (appAnimator.wasAnimating) {
181                         // stopped animating, do one more pass through the layout
182                         setAppLayoutChanges(appAnimator,
183                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
184                                 "appToken " + appAnimator.mAppToken + " done", displayId);
185                         if (DEBUG_ANIM) Slog.v(TAG,
186                                 "updateWindowsApps...: done animating " + appAnimator.mAppToken);
187                     }
188                 }
189             }
190 
191             final AppTokenList exitingAppTokens = stack.mExitingAppTokens;
192             final int exitingCount = exitingAppTokens.size();
193             for (int i = 0; i < exitingCount; i++) {
194                 final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
195                 appAnimator.wasAnimating = appAnimator.animating;
196                 if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
197                     setAnimating(true);
198                     mAppWindowAnimating = true;
199                 } else if (appAnimator.wasAnimating) {
200                     // stopped animating, do one more pass through the layout
201                     setAppLayoutChanges(appAnimator,
202                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
203                             "exiting appToken " + appAnimator.mAppToken + " done", displayId);
204                     if (DEBUG_ANIM) Slog.v(TAG,
205                             "updateWindowsApps...: done animating exiting "
206                                     + appAnimator.mAppToken);
207                 }
208             }
209         }
210     }
211 
shouldForceHide(WindowState win)212     private boolean shouldForceHide(WindowState win) {
213         final WindowState imeTarget = mService.mInputMethodTarget;
214         final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
215                 ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
216                         || !mPolicy.canBeForceHidden(imeTarget, imeTarget.mAttrs));
217 
218         final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
219         final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
220                 null : winShowWhenLocked.mAppToken;
221 
222         boolean allowWhenLocked = false;
223         // Show IME over the keyguard if the target allows it
224         allowWhenLocked |= (win.mIsImWindow || imeTarget == win) && showImeOverKeyguard;
225         // Show SHOW_WHEN_LOCKED windows that turn on the screen
226         allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen;
227 
228         if (appShowWhenLocked != null) {
229             allowWhenLocked |= appShowWhenLocked == win.mAppToken
230                     // Show all SHOW_WHEN_LOCKED windows if some apps are shown over lockscreen
231                     || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
232                     // Show error dialogs over apps that dismiss keyguard.
233                     || (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
234         }
235 
236         // Only hide windows if the keyguard is active and not animating away.
237         boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded()
238                 && mForceHiding != KEYGUARD_ANIMATING_OUT;
239         boolean hideDockDivider = win.mAttrs.type == TYPE_DOCK_DIVIDER
240                 && win.getDisplayContent().getDockedStackLocked() == null;
241         return keyguardOn && !allowWhenLocked && (win.getDisplayId() == Display.DEFAULT_DISPLAY)
242                 || hideDockDivider;
243     }
244 
updateWindowsLocked(final int displayId)245     private void updateWindowsLocked(final int displayId) {
246         ++mAnimTransactionSequence;
247 
248         final WindowList windows = mService.getWindowListLocked(displayId);
249 
250         final boolean keyguardGoingAwayToShade =
251                 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0;
252         final boolean keyguardGoingAwayNoAnimation =
253                 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0;
254         final boolean keyguardGoingAwayWithWallpaper =
255                 (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0;
256 
257         if (mKeyguardGoingAway) {
258             for (int i = windows.size() - 1; i >= 0; i--) {
259                 WindowState win = windows.get(i);
260                 if (!mPolicy.isKeyguardHostWindow(win.mAttrs)) {
261                     continue;
262                 }
263                 final WindowStateAnimator winAnimator = win.mWinAnimator;
264                 if ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
265                     if (!winAnimator.mAnimating) {
266                         if (DEBUG_KEYGUARD) Slog.d(TAG,
267                                 "updateWindowsLocked: creating delay animation");
268 
269                         // Create a new animation to delay until keyguard is gone on its own.
270                         winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
271                         winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
272                         winAnimator.mAnimationIsEntrance = false;
273                         winAnimator.mAnimationStartTime = -1;
274                         winAnimator.mKeyguardGoingAwayAnimation = true;
275                         winAnimator.mKeyguardGoingAwayWithWallpaper
276                                 = keyguardGoingAwayWithWallpaper;
277                     }
278                 } else {
279                     if (DEBUG_KEYGUARD) Slog.d(TAG,
280                             "updateWindowsLocked: StatusBar is no longer keyguard");
281                     mKeyguardGoingAway = false;
282                     winAnimator.clearAnimation();
283                 }
284                 break;
285             }
286         }
287 
288         mForceHiding = KEYGUARD_NOT_SHOWN;
289 
290         boolean wallpaperInUnForceHiding = false;
291         boolean startingInUnForceHiding = false;
292         ArrayList<WindowStateAnimator> unForceHiding = null;
293         WindowState wallpaper = null;
294         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
295         for (int i = windows.size() - 1; i >= 0; i--) {
296             WindowState win = windows.get(i);
297             WindowStateAnimator winAnimator = win.mWinAnimator;
298             final int flags = win.mAttrs.flags;
299             boolean canBeForceHidden = mPolicy.canBeForceHidden(win, win.mAttrs);
300             boolean shouldBeForceHidden = shouldForceHide(win);
301             if (winAnimator.hasSurface()) {
302                 final boolean wasAnimating = winAnimator.mWasAnimating;
303                 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
304                 winAnimator.mWasAnimating = nowAnimating;
305                 orAnimating(nowAnimating);
306 
307                 if (DEBUG_WALLPAPER) {
308                     Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
309                             ", nowAnimating=" + nowAnimating);
310                 }
311 
312                 if (wasAnimating && !winAnimator.mAnimating
313                         && wallpaperController.isWallpaperTarget(win)) {
314                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
315                     setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
316                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
317                     if (DEBUG_LAYOUT_REPEATS) {
318                         mWindowPlacerLocked.debugLayoutRepeats(
319                                 "updateWindowsAndWallpaperLocked 2",
320                                 getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
321                     }
322                 }
323 
324                 if (mPolicy.isForceHiding(win.mAttrs)) {
325                     if (!wasAnimating && nowAnimating) {
326                         if (DEBUG_KEYGUARD || DEBUG_ANIM ||
327                                 DEBUG_VISIBILITY) Slog.v(TAG,
328                                 "Animation started that could impact force hide: " + win);
329                         mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
330                         setPendingLayoutChanges(displayId,
331                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
332                         if (DEBUG_LAYOUT_REPEATS) {
333                             mWindowPlacerLocked.debugLayoutRepeats(
334                                     "updateWindowsAndWallpaperLocked 3",
335                                     getPendingLayoutChanges(displayId));
336                         }
337                         mService.mFocusMayChange = true;
338                     } else if (mKeyguardGoingAway && !nowAnimating) {
339                         // Timeout!!
340                         Slog.e(TAG, "Timeout waiting for animation to startup");
341                         mPolicy.startKeyguardExitAnimation(0, 0);
342                         mKeyguardGoingAway = false;
343                     }
344                     if (win.isReadyForDisplay()) {
345                         if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) {
346                             mForceHiding = KEYGUARD_ANIMATING_OUT;
347                         } else {
348                             mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
349                         }
350                     }
351                     if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
352                             "Force hide " + forceHidingToString()
353                             + " hasSurface=" + win.mHasSurface
354                             + " policyVis=" + win.mPolicyVisibility
355                             + " destroying=" + win.mDestroying
356                             + " attHidden=" + win.mAttachedHidden
357                             + " vis=" + win.mViewVisibility
358                             + " hidden=" + win.mRootToken.hidden
359                             + " anim=" + win.mWinAnimator.mAnimation);
360                 } else if (canBeForceHidden) {
361                     if (shouldBeForceHidden) {
362                         if (!win.hideLw(false, false)) {
363                             // Was already hidden
364                             continue;
365                         }
366                         if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
367                                 "Now policy hidden: " + win);
368                     } else {
369                         boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
370                                 && !mPostKeyguardExitAnimation.hasEnded()
371                                 && !winAnimator.mKeyguardGoingAwayAnimation
372                                 && win.hasDrawnLw()
373                                 && win.mAttachedWindow == null
374                                 && !win.mIsImWindow
375                                 && displayId == Display.DEFAULT_DISPLAY;
376 
377                         // If the window is already showing and we don't need to apply an existing
378                         // Keyguard exit animation, skip.
379                         if (!win.showLw(false, false) && !applyExistingExitAnimation) {
380                             continue;
381                         }
382                         final boolean visibleNow = win.isVisibleNow();
383                         if (!visibleNow) {
384                             // Couldn't really show, must showLw() again when win becomes visible.
385                             win.hideLw(false, false);
386                             continue;
387                         }
388                         if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
389                                 "Now policy shown: " + win);
390                         if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
391                                 && win.mAttachedWindow == null) {
392                             if (unForceHiding == null) {
393                                 unForceHiding = new ArrayList<>();
394                             }
395                             unForceHiding.add(winAnimator);
396                             if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
397                                 wallpaperInUnForceHiding = true;
398                             }
399                             if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
400                                 startingInUnForceHiding = true;
401                             }
402                         } else if (applyExistingExitAnimation) {
403                             // We're already in the middle of an animation. Use the existing
404                             // animation to bring in this window.
405                             if (DEBUG_KEYGUARD) Slog.v(TAG,
406                                     "Applying existing Keyguard exit animation to new window: win="
407                                             + win);
408 
409                             Animation a = mPolicy.createForceHideEnterAnimation(false,
410                                     keyguardGoingAwayToShade);
411                             winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime(),
412                                     STACK_CLIP_BEFORE_ANIM);
413                             winAnimator.mKeyguardGoingAwayAnimation = true;
414                             winAnimator.mKeyguardGoingAwayWithWallpaper
415                                     = keyguardGoingAwayWithWallpaper;
416                         }
417                         final WindowState currentFocus = mService.mCurrentFocus;
418                         if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
419                             // We are showing on top of the current
420                             // focus, so re-evaluate focus to make
421                             // sure it is correct.
422                             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG,
423                                     "updateWindowsLocked: setting mFocusMayChange true");
424                             mService.mFocusMayChange = true;
425                         }
426                     }
427                     if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
428                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
429                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
430                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
431                         if (DEBUG_LAYOUT_REPEATS) {
432                             mWindowPlacerLocked.debugLayoutRepeats(
433                                     "updateWindowsAndWallpaperLocked 4",
434                                     getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
435                         }
436                     }
437                 }
438             }
439 
440             // If the window doesn't have a surface, the only thing we care about is the correct
441             // policy visibility.
442             else if (canBeForceHidden) {
443                 if (shouldBeForceHidden) {
444                     win.hideLw(false, false);
445                 } else {
446                     win.showLw(false, false);
447                 }
448             }
449 
450             final AppWindowToken atoken = win.mAppToken;
451             if (winAnimator.mDrawState == READY_TO_SHOW) {
452                 if (atoken == null || atoken.allDrawn) {
453                     if (winAnimator.performShowLocked()) {
454                         setPendingLayoutChanges(displayId,
455                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
456                         if (DEBUG_LAYOUT_REPEATS) {
457                             mWindowPlacerLocked.debugLayoutRepeats(
458                                     "updateWindowsAndWallpaperLocked 5",
459                                     getPendingLayoutChanges(displayId));
460                         }
461                     }
462                 }
463             }
464             final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
465             if (appAnimator != null && appAnimator.thumbnail != null) {
466                 if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
467                     appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
468                     appAnimator.thumbnailLayer = 0;
469                 }
470                 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
471                     appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
472                 }
473             }
474             if (win.mIsWallpaper) {
475                 wallpaper = win;
476             }
477         } // end forall windows
478 
479         // If we have windows that are being show due to them no longer
480         // being force-hidden, apply the appropriate animation to them if animations are not
481         // disabled.
482         if (unForceHiding != null) {
483             if (!keyguardGoingAwayNoAnimation) {
484                 boolean first = true;
485                 for (int i=unForceHiding.size()-1; i>=0; i--) {
486                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
487                     Animation a = mPolicy.createForceHideEnterAnimation(
488                             wallpaperInUnForceHiding && !startingInUnForceHiding,
489                             keyguardGoingAwayToShade);
490                     if (a != null) {
491                         if (DEBUG_KEYGUARD) Slog.v(TAG,
492                                 "Starting keyguard exit animation on window " + winAnimator.mWin);
493                         winAnimator.setAnimation(a, STACK_CLIP_BEFORE_ANIM);
494                         winAnimator.mKeyguardGoingAwayAnimation = true;
495                         winAnimator.mKeyguardGoingAwayWithWallpaper
496                                 = keyguardGoingAwayWithWallpaper;
497                         if (first) {
498                             mPostKeyguardExitAnimation = a;
499                             mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
500                             first = false;
501                         }
502                     }
503                 }
504             } else if (mKeyguardGoingAway) {
505                 mPolicy.startKeyguardExitAnimation(mCurrentTime, 0 /* duration */);
506                 mKeyguardGoingAway = false;
507             }
508 
509 
510             // Wallpaper is going away in un-force-hide motion, animate it as well.
511             if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) {
512                 if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
513                 Animation a = mPolicy.createForceHideWallpaperExitAnimation(
514                         keyguardGoingAwayToShade);
515                 if (a != null) {
516                     wallpaper.mWinAnimator.setAnimation(a);
517                 }
518             }
519         }
520 
521         if (mPostKeyguardExitAnimation != null) {
522             // We're in the midst of a keyguard exit animation.
523             if (mKeyguardGoingAway) {
524                 mPolicy.startKeyguardExitAnimation(mCurrentTime +
525                         mPostKeyguardExitAnimation.getStartOffset(),
526                         mPostKeyguardExitAnimation.getDuration());
527                 mKeyguardGoingAway = false;
528             }
529             // mPostKeyguardExitAnimation might either be ended normally, cancelled, or "orphaned",
530             // meaning that the window it was running on was removed. We check for hasEnded() for
531             // ended normally and cancelled case, and check the time for the "orphaned" case.
532             else if (mPostKeyguardExitAnimation.hasEnded()
533                     || mCurrentTime - mPostKeyguardExitAnimation.getStartTime()
534                             > mPostKeyguardExitAnimation.getDuration()) {
535                 // Done with the animation, reset.
536                 if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations.");
537                 mPostKeyguardExitAnimation = null;
538             }
539         }
540     }
541 
updateWallpaperLocked(int displayId)542     private void updateWallpaperLocked(int displayId) {
543         mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
544 
545         final WindowList windows = mService.getWindowListLocked(displayId);
546         WindowState detachedWallpaper = null;
547 
548         for (int i = windows.size() - 1; i >= 0; i--) {
549             final WindowState win = windows.get(i);
550             WindowStateAnimator winAnimator = win.mWinAnimator;
551             if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
552                 continue;
553             }
554 
555             final int flags = win.mAttrs.flags;
556 
557             // If this window is animating, make a note that we have
558             // an animating window and take care of a request to run
559             // a detached wallpaper animation.
560             if (winAnimator.mAnimating) {
561                 if (winAnimator.mAnimation != null) {
562                     if ((flags & FLAG_SHOW_WALLPAPER) != 0
563                             && winAnimator.mAnimation.getDetachWallpaper()) {
564                         detachedWallpaper = win;
565                     }
566                     final int color = winAnimator.mAnimation.getBackgroundColor();
567                     if (color != 0) {
568                         final TaskStack stack = win.getStack();
569                         if (stack != null) {
570                             stack.setAnimationBackground(winAnimator, color);
571                         }
572                     }
573                 }
574                 setAnimating(true);
575             }
576 
577             // If this window's app token is running a detached wallpaper
578             // animation, make a note so we can ensure the wallpaper is
579             // displayed behind it.
580             final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
581             if (appAnimator != null && appAnimator.animation != null
582                     && appAnimator.animating) {
583                 if ((flags & FLAG_SHOW_WALLPAPER) != 0
584                         && appAnimator.animation.getDetachWallpaper()) {
585                     detachedWallpaper = win;
586                 }
587 
588                 final int color = appAnimator.animation.getBackgroundColor();
589                 if (color != 0) {
590                     final TaskStack stack = win.getStack();
591                     if (stack != null) {
592                         stack.setAnimationBackground(winAnimator, color);
593                     }
594                 }
595             }
596         } // end forall windows
597 
598         if (mWindowDetachedWallpaper != detachedWallpaper) {
599             if (DEBUG_WALLPAPER) Slog.v(TAG,
600                     "Detached wallpaper changed from " + mWindowDetachedWallpaper
601                     + " to " + detachedWallpaper);
602             mWindowDetachedWallpaper = detachedWallpaper;
603             mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
604         }
605     }
606 
607     /** See if any windows have been drawn, so they (and others associated with them) can now be
608      *  shown. */
testTokenMayBeDrawnLocked(int displayId)609     private void testTokenMayBeDrawnLocked(int displayId) {
610         // See if any windows have been drawn, so they (and others
611         // associated with them) can now be shown.
612         final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks();
613         final int numTasks = tasks.size();
614         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
615             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
616             final int numTokens = tokens.size();
617             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
618                 final AppWindowToken wtoken = tokens.get(tokenNdx);
619                 AppWindowAnimator appAnimator = wtoken.mAppAnimator;
620                 final boolean allDrawn = wtoken.allDrawn;
621                 if (allDrawn != appAnimator.allDrawn) {
622                     appAnimator.allDrawn = allDrawn;
623                     if (allDrawn) {
624                         // The token has now changed state to having all
625                         // windows shown...  what to do, what to do?
626                         if (appAnimator.freezingScreen) {
627                             appAnimator.showAllWindowsLocked();
628                             mService.unsetAppFreezingScreenLocked(wtoken, false, true);
629                             if (DEBUG_ORIENTATION) Slog.i(TAG,
630                                     "Setting mOrientationChangeComplete=true because wtoken "
631                                     + wtoken + " numInteresting=" + wtoken.numInterestingWindows
632                                     + " numDrawn=" + wtoken.numDrawnWindows);
633                             // This will set mOrientationChangeComplete and cause a pass through
634                             // layout.
635                             setAppLayoutChanges(appAnimator,
636                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
637                                     "testTokenMayBeDrawnLocked: freezingScreen", displayId);
638                         } else {
639                             setAppLayoutChanges(appAnimator,
640                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
641                                     "testTokenMayBeDrawnLocked", displayId);
642 
643                             // We can now show all of the drawn windows!
644                             if (!mService.mOpeningApps.contains(wtoken)) {
645                                 orAnimating(appAnimator.showAllWindowsLocked());
646                             }
647                         }
648                     }
649                 }
650             }
651         }
652     }
653 
654 
655     /** Locked on mService.mWindowMap. */
animateLocked(long frameTimeNs)656     private void animateLocked(long frameTimeNs) {
657         if (!mInitialized) {
658             return;
659         }
660 
661         mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
662         mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
663         boolean wasAnimating = mAnimating;
664         setAnimating(false);
665         mAppWindowAnimating = false;
666         if (DEBUG_WINDOW_TRACE) {
667             Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
668         }
669 
670         if (SHOW_TRANSACTIONS) Slog.i(
671                 TAG, ">>> OPEN TRANSACTION animateLocked");
672         SurfaceControl.openTransaction();
673         SurfaceControl.setAnimationTransaction();
674         try {
675             final int numDisplays = mDisplayContentsAnimators.size();
676             for (int i = 0; i < numDisplays; i++) {
677                 final int displayId = mDisplayContentsAnimators.keyAt(i);
678                 updateAppWindowsLocked(displayId);
679                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
680 
681                 final ScreenRotationAnimation screenRotationAnimation =
682                         displayAnimator.mScreenRotationAnimation;
683                 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
684                     if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
685                         setAnimating(true);
686                     } else {
687                         mBulkUpdateParams |= SET_UPDATE_ROTATION;
688                         screenRotationAnimation.kill();
689                         displayAnimator.mScreenRotationAnimation = null;
690 
691                         //TODO (multidisplay): Accessibility supported only for the default display.
692                         if (mService.mAccessibilityController != null
693                                 && displayId == Display.DEFAULT_DISPLAY) {
694                             // We just finished rotation animation which means we did not
695                             // anounce the rotation and waited for it to end, announce now.
696                             mService.mAccessibilityController.onRotationChangedLocked(
697                                     mService.getDefaultDisplayContentLocked(), mService.mRotation);
698                         }
699                     }
700                 }
701 
702                 // Update animations of all applications, including those
703                 // associated with exiting/removed apps
704                 updateWindowsLocked(displayId);
705                 updateWallpaperLocked(displayId);
706 
707                 final WindowList windows = mService.getWindowListLocked(displayId);
708                 final int N = windows.size();
709                 for (int j = 0; j < N; j++) {
710                     windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
711                 }
712             }
713 
714             for (int i = 0; i < numDisplays; i++) {
715                 final int displayId = mDisplayContentsAnimators.keyAt(i);
716 
717                 testTokenMayBeDrawnLocked(displayId);
718 
719                 final ScreenRotationAnimation screenRotationAnimation =
720                         mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
721                 if (screenRotationAnimation != null) {
722                     screenRotationAnimation.updateSurfacesInTransaction();
723                 }
724 
725                 orAnimating(mService.getDisplayContentLocked(displayId).animateDimLayers());
726                 orAnimating(mService.getDisplayContentLocked(displayId).getDockedDividerController()
727                         .animate(mCurrentTime));
728                 //TODO (multidisplay): Magnification is supported only for the default display.
729                 if (mService.mAccessibilityController != null
730                         && displayId == Display.DEFAULT_DISPLAY) {
731                     mService.mAccessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
732                 }
733             }
734 
735             if (mService.mDragState != null) {
736                 mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
737             }
738 
739             if (mAnimating) {
740                 mService.scheduleAnimationLocked();
741             }
742 
743             if (mService.mWatermark != null) {
744                 mService.mWatermark.drawIfNeeded();
745             }
746         } catch (RuntimeException e) {
747             Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
748         } finally {
749             SurfaceControl.closeTransaction();
750             if (SHOW_TRANSACTIONS) Slog.i(
751                     TAG, "<<< CLOSE TRANSACTION animateLocked");
752         }
753 
754         boolean hasPendingLayoutChanges = false;
755         final int numDisplays = mService.mDisplayContents.size();
756         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
757             final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
758             final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
759             if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
760                 mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
761             }
762             if (pendingChanges != 0) {
763                 hasPendingLayoutChanges = true;
764             }
765         }
766 
767         boolean doRequest = false;
768         if (mBulkUpdateParams != 0) {
769             doRequest = mWindowPlacerLocked.copyAnimToLayoutParamsLocked();
770         }
771 
772         if (hasPendingLayoutChanges || doRequest) {
773             mWindowPlacerLocked.requestTraversal();
774         }
775 
776         if (mAnimating && !wasAnimating && Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
777             Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
778         }
779 
780         if (!mAnimating && wasAnimating) {
781             mWindowPlacerLocked.requestTraversal();
782             if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
783                 Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
784             }
785         }
786 
787         if (mRemoveReplacedWindows) {
788             removeReplacedWindowsLocked();
789         }
790 
791         mService.stopUsingSavedSurfaceLocked();
792         mService.destroyPreservedSurfaceLocked();
793         mService.mWindowPlacerLocked.destroyPendingSurfaces();
794 
795         if (DEBUG_WINDOW_TRACE) {
796             Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
797                     + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
798                     + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
799                     + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
800         }
801     }
802 
removeReplacedWindowsLocked()803     private void removeReplacedWindowsLocked() {
804         if (SHOW_TRANSACTIONS) Slog.i(
805                 TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
806         SurfaceControl.openTransaction();
807         try {
808             for (int i = mService.mDisplayContents.size() - 1; i >= 0; i--) {
809                 DisplayContent display = mService.mDisplayContents.valueAt(i);
810                 final WindowList windows = mService.getWindowListLocked(display.getDisplayId());
811                 for (int j = windows.size() - 1; j >= 0; j--) {
812                     windows.get(j).maybeRemoveReplacedWindow();
813                 }
814             }
815         } finally {
816             SurfaceControl.closeTransaction();
817             if (SHOW_TRANSACTIONS) Slog.i(
818                     TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
819         }
820         mRemoveReplacedWindows = false;
821     }
822 
bulkUpdateParamsToString(int bulkUpdateParams)823     private static String bulkUpdateParamsToString(int bulkUpdateParams) {
824         StringBuilder builder = new StringBuilder(128);
825         if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) {
826             builder.append(" UPDATE_ROTATION");
827         }
828         if ((bulkUpdateParams & WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE) != 0) {
829             builder.append(" WALLPAPER_MAY_CHANGE");
830         }
831         if ((bulkUpdateParams & WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED) != 0) {
832             builder.append(" FORCE_HIDING_CHANGED");
833         }
834         if ((bulkUpdateParams & WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
835             builder.append(" ORIENTATION_CHANGE_COMPLETE");
836         }
837         if ((bulkUpdateParams & WindowSurfacePlacer.SET_TURN_ON_SCREEN) != 0) {
838             builder.append(" TURN_ON_SCREEN");
839         }
840         return builder.toString();
841     }
842 
dumpLocked(PrintWriter pw, String prefix, boolean dumpAll)843     public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
844         final String subPrefix = "  " + prefix;
845         final String subSubPrefix = "  " + subPrefix;
846 
847         for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
848             pw.print(prefix); pw.print("DisplayContentsAnimator #");
849                     pw.print(mDisplayContentsAnimators.keyAt(i));
850                     pw.println(":");
851             DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
852             final WindowList windows =
853                     mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i));
854             final int N = windows.size();
855             for (int j = 0; j < N; j++) {
856                 WindowStateAnimator wanim = windows.get(j).mWinAnimator;
857                 pw.print(subPrefix); pw.print("Window #"); pw.print(j);
858                         pw.print(": "); pw.println(wanim);
859             }
860             if (displayAnimator.mScreenRotationAnimation != null) {
861                 pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
862                 displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
863             } else if (dumpAll) {
864                 pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
865             }
866             pw.println();
867         }
868 
869         pw.println();
870 
871         if (dumpAll) {
872             pw.print(prefix); pw.print("mAnimTransactionSequence=");
873                     pw.print(mAnimTransactionSequence);
874                     pw.print(" mForceHiding="); pw.println(forceHidingToString());
875             pw.print(prefix); pw.print("mCurrentTime=");
876                     pw.println(TimeUtils.formatUptime(mCurrentTime));
877         }
878         if (mBulkUpdateParams != 0) {
879             pw.print(prefix); pw.print("mBulkUpdateParams=0x");
880                     pw.print(Integer.toHexString(mBulkUpdateParams));
881                     pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
882         }
883         if (mWindowDetachedWallpaper != null) {
884             pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
885                 pw.println(mWindowDetachedWallpaper);
886         }
887     }
888 
getPendingLayoutChanges(final int displayId)889     int getPendingLayoutChanges(final int displayId) {
890         if (displayId < 0) {
891             return 0;
892         }
893         final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
894         return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
895     }
896 
setPendingLayoutChanges(final int displayId, final int changes)897     void setPendingLayoutChanges(final int displayId, final int changes) {
898         if (displayId < 0) {
899             return;
900         }
901         final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
902         if (displayContent != null) {
903             displayContent.pendingLayoutChanges |= changes;
904         }
905     }
906 
setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason, final int displayId)907     void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason,
908             final int displayId) {
909         WindowList windows = appAnimator.mAppToken.allAppWindows;
910         for (int i = windows.size() - 1; i >= 0; i--) {
911             if (displayId == windows.get(i).getDisplayId()) {
912                 setPendingLayoutChanges(displayId, changes);
913                 if (DEBUG_LAYOUT_REPEATS) {
914                     mWindowPlacerLocked.debugLayoutRepeats(reason,
915                             getPendingLayoutChanges(displayId));
916                 }
917                 break;
918             }
919         }
920     }
921 
getDisplayContentsAnimatorLocked(int displayId)922     private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
923         DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
924         if (displayAnimator == null) {
925             displayAnimator = new DisplayContentsAnimator();
926             mDisplayContentsAnimators.put(displayId, displayAnimator);
927         }
928         return displayAnimator;
929     }
930 
setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation)931     void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
932         if (displayId >= 0) {
933             getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
934         }
935     }
936 
getScreenRotationAnimationLocked(int displayId)937     ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
938         if (displayId < 0) {
939             return null;
940         }
941         return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
942     }
943 
requestRemovalOfReplacedWindows(WindowState win)944     void requestRemovalOfReplacedWindows(WindowState win) {
945         mRemoveReplacedWindows = true;
946     }
947 
948     private class DisplayContentsAnimator {
949         ScreenRotationAnimation mScreenRotationAnimation = null;
950     }
951 
isAnimating()952     boolean isAnimating() {
953         return mAnimating;
954     }
955 
setAnimating(boolean animating)956     void setAnimating(boolean animating) {
957         mAnimating = animating;
958     }
959 
orAnimating(boolean animating)960     void orAnimating(boolean animating) {
961         mAnimating |= animating;
962     }
963 }
964