WindowAnimator.java revision dc548483ae90ba26ad9e2e2cb79f4673140edb49
1// Copyright 2012 Google Inc. All Rights Reserved.
2
3package com.android.server.wm;
4
5import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
6import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
7
8import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
9import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
10import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
11import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
12import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING;
13
14import android.content.Context;
15import android.os.Debug;
16import android.os.SystemClock;
17import android.util.Log;
18import android.util.Slog;
19import android.util.SparseArray;
20import android.util.SparseIntArray;
21import android.util.TimeUtils;
22import android.view.Display;
23import android.view.SurfaceControl;
24import android.view.WindowManagerPolicy;
25import android.view.animation.Animation;
26
27import com.android.server.wm.WindowManagerService.LayoutFields;
28
29import java.io.PrintWriter;
30import java.util.ArrayList;
31
32/**
33 * Singleton class that carries out the animations and Surface operations in a separate task
34 * on behalf of WindowManagerService.
35 */
36public class WindowAnimator {
37    private static final String TAG = "WindowAnimator";
38
39    final WindowManagerService mService;
40    final Context mContext;
41    final WindowManagerPolicy mPolicy;
42
43    boolean mAnimating;
44
45    final Runnable mAnimationRunnable;
46
47    /** Time of current animation step. Reset on each iteration */
48    long mCurrentTime;
49
50    /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
51     * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
52    private int mAnimTransactionSequence;
53
54    /** Window currently running an animation that has requested it be detached
55     * from the wallpaper.  This means we need to ensure the wallpaper is
56     * visible behind it in case it animates in a way that would allow it to be
57     * seen. If multiple windows satisfy this, use the lowest window. */
58    WindowState mWindowDetachedWallpaper = null;
59
60    WindowStateAnimator mUniverseBackground = null;
61    int mAboveUniverseLayer = 0;
62
63    int mBulkUpdateParams = 0;
64    Object mLastWindowFreezeSource;
65
66    SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators =
67            new SparseArray<WindowAnimator.DisplayContentsAnimator>(2);
68
69    boolean mInitialized = false;
70
71    // forceHiding states.
72    static final int KEYGUARD_NOT_SHOWN     = 0;
73    static final int KEYGUARD_ANIMATING_IN  = 1;
74    static final int KEYGUARD_SHOWN         = 2;
75    static final int KEYGUARD_ANIMATING_OUT = 3;
76    int mForceHiding = KEYGUARD_NOT_SHOWN;
77
78    private String forceHidingToString() {
79        switch (mForceHiding) {
80            case KEYGUARD_NOT_SHOWN:    return "KEYGUARD_NOT_SHOWN";
81            case KEYGUARD_ANIMATING_IN: return "KEYGUARD_ANIMATING_IN";
82            case KEYGUARD_SHOWN:        return "KEYGUARD_SHOWN";
83            case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
84            default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
85        }
86    }
87
88    WindowAnimator(final WindowManagerService service) {
89        mService = service;
90        mContext = service.mContext;
91        mPolicy = service.mPolicy;
92
93        mAnimationRunnable = new Runnable() {
94            @Override
95            public void run() {
96                synchronized (mService.mWindowMap) {
97                    mService.mAnimationScheduled = false;
98                    animateLocked();
99                }
100            }
101        };
102    }
103
104    void addDisplayLocked(final int displayId) {
105        // Create the DisplayContentsAnimator object by retrieving it.
106        getDisplayContentsAnimatorLocked(displayId);
107        if (displayId == Display.DEFAULT_DISPLAY) {
108            mInitialized = true;
109        }
110    }
111
112    void removeDisplayLocked(final int displayId) {
113        final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
114        if (displayAnimator != null) {
115            if (displayAnimator.mScreenRotationAnimation != null) {
116                displayAnimator.mScreenRotationAnimation.kill();
117                displayAnimator.mScreenRotationAnimation = null;
118            }
119        }
120
121        mDisplayContentsAnimators.delete(displayId);
122    }
123
124    void hideWallpapersLocked(final WindowState w) {
125        final WindowState wallpaperTarget = mService.mWallpaperTarget;
126        final WindowState lowerWallpaperTarget = mService.mLowerWallpaperTarget;
127        final ArrayList<WindowToken> wallpaperTokens = mService.mWallpaperTokens;
128
129        if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) {
130            final int numTokens = wallpaperTokens.size();
131            for (int i = numTokens - 1; i >= 0; i--) {
132                final WindowToken token = wallpaperTokens.get(i);
133                final int numWindows = token.windows.size();
134                for (int j = numWindows - 1; j >= 0; j--) {
135                    final WindowState wallpaper = token.windows.get(j);
136                    final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
137                    if (!winAnimator.mLastHidden) {
138                        winAnimator.hide();
139                        mService.dispatchWallpaperVisibility(wallpaper, false);
140                        setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
141                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
142                    }
143                }
144                if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG,
145                        "Hiding wallpaper " + token + " from " + w
146                        + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget
147                        + "\n" + Debug.getCallers(5, "  "));
148                token.hidden = true;
149            }
150        }
151    }
152
153    private void updateAppWindowsLocked(int displayId) {
154        ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks();
155        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
156            final TaskStack stack = stacks.get(stackNdx);
157            final ArrayList<Task> tasks = stack.getTasks();
158            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
159                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
160                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
161                    final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
162                    final boolean wasAnimating = appAnimator.animation != null
163                            && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
164                    if (appAnimator.stepAnimationLocked(mCurrentTime)) {
165                        mAnimating = true;
166                    } else if (wasAnimating) {
167                        // stopped animating, do one more pass through the layout
168                        setAppLayoutChanges(appAnimator,
169                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
170                                "appToken " + appAnimator.mAppToken + " done");
171                        if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
172                                "updateWindowsApps...: done animating " + appAnimator.mAppToken);
173                    }
174                }
175            }
176
177            final AppTokenList exitingAppTokens = stack.mExitingAppTokens;
178            final int NEAT = exitingAppTokens.size();
179            for (int i = 0; i < NEAT; i++) {
180                final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
181                final boolean wasAnimating = appAnimator.animation != null
182                        && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
183                if (appAnimator.stepAnimationLocked(mCurrentTime)) {
184                    mAnimating = true;
185                } else if (wasAnimating) {
186                    // stopped animating, do one more pass through the layout
187                    setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
188                        "exiting appToken " + appAnimator.mAppToken + " done");
189                    if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
190                            "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
191                }
192            }
193        }
194    }
195
196    private void updateWindowsLocked(final int displayId) {
197        ++mAnimTransactionSequence;
198
199        final WindowList windows = mService.getWindowListLocked(displayId);
200        ArrayList<WindowStateAnimator> unForceHiding = null;
201        boolean wallpaperInUnForceHiding = false;
202        mForceHiding = KEYGUARD_NOT_SHOWN;
203
204        for (int i = windows.size() - 1; i >= 0; i--) {
205            WindowState win = windows.get(i);
206            WindowStateAnimator winAnimator = win.mWinAnimator;
207            final int flags = winAnimator.mAttrFlags;
208
209            if (winAnimator.mSurfaceControl != null) {
210                final boolean wasAnimating = winAnimator.mWasAnimating;
211                final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
212
213                if (WindowManagerService.DEBUG_WALLPAPER) {
214                    Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
215                            ", nowAnimating=" + nowAnimating);
216                }
217
218                if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
219                    mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
220                    setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
221                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
222                    if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
223                        mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
224                                getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
225                    }
226                }
227
228                if (mPolicy.doesForceHide(win, win.mAttrs)) {
229                    if (!wasAnimating && nowAnimating) {
230                        if (WindowManagerService.DEBUG_ANIM ||
231                                WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
232                                "Animation started that could impact force hide: " + win);
233                        mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
234                        setPendingLayoutChanges(displayId,
235                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
236                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
237                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
238                                    getPendingLayoutChanges(displayId));
239                        }
240                        mService.mFocusMayChange = true;
241                    }
242                    if (win.isReadyForDisplay()) {
243                        if (nowAnimating) {
244                            if (winAnimator.mAnimationIsEntrance) {
245                                mForceHiding = KEYGUARD_ANIMATING_IN;
246                            } else {
247                                mForceHiding = KEYGUARD_ANIMATING_OUT;
248                            }
249                        } else {
250                            mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
251                        }
252                    }
253                    if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
254                            "Force hide " + mForceHiding
255                            + " hasSurface=" + win.mHasSurface
256                            + " policyVis=" + win.mPolicyVisibility
257                            + " destroying=" + win.mDestroying
258                            + " attHidden=" + win.mAttachedHidden
259                            + " vis=" + win.mViewVisibility
260                            + " hidden=" + win.mRootToken.hidden
261                            + " anim=" + win.mWinAnimator.mAnimation);
262                } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
263                    final boolean hideWhenLocked =
264                            (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0;
265                    final boolean changed;
266                    if (((mForceHiding == KEYGUARD_ANIMATING_IN)
267                                && (!winAnimator.isAnimating() || hideWhenLocked))
268                            || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
269                        changed = win.hideLw(false, false);
270                        if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
271                                "Now policy hidden: " + win);
272                    } else {
273                        changed = win.showLw(false, false);
274                        if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
275                                "Now policy shown: " + win);
276                        if (changed) {
277                            if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
278                                    && win.isVisibleNow() /*w.isReadyForDisplay()*/) {
279                                if (unForceHiding == null) {
280                                    unForceHiding = new ArrayList<WindowStateAnimator>();
281                                }
282                                unForceHiding.add(winAnimator);
283                                if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
284                                    wallpaperInUnForceHiding = true;
285                                }
286                            }
287                            final WindowState currentFocus = mService.mCurrentFocus;
288                            if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
289                                // We are showing on to of the current
290                                // focus, so re-evaluate focus to make
291                                // sure it is correct.
292                                if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG,
293                                        "updateWindowsLocked: setting mFocusMayChange true");
294                                mService.mFocusMayChange = true;
295                            }
296                        }
297                    }
298                    if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) {
299                        mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
300                        setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
301                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
302                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
303                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
304                                    getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
305                        }
306                    }
307                }
308            }
309
310            final AppWindowToken atoken = win.mAppToken;
311            if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
312                if (atoken == null || atoken.allDrawn) {
313                    if (winAnimator.performShowLocked()) {
314                        setPendingLayoutChanges(displayId,
315                                WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
316                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
317                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
318                                    getPendingLayoutChanges(displayId));
319                        }
320                    }
321                }
322            }
323            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
324            if (appAnimator != null && appAnimator.thumbnail != null) {
325                if (appAnimator.thumbnailTransactionSeq != mAnimTransactionSequence) {
326                    appAnimator.thumbnailTransactionSeq = mAnimTransactionSequence;
327                    appAnimator.thumbnailLayer = 0;
328                }
329                if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
330                    appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
331                }
332            }
333        } // end forall windows
334
335        // If we have windows that are being show due to them no longer
336        // being force-hidden, apply the appropriate animation to them.
337        if (unForceHiding != null) {
338            for (int i=unForceHiding.size()-1; i>=0; i--) {
339                Animation a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding);
340                if (a != null) {
341                    final WindowStateAnimator winAnimator = unForceHiding.get(i);
342                    winAnimator.setAnimation(a);
343                    winAnimator.mAnimationIsEntrance = true;
344                }
345            }
346        }
347    }
348
349    private void updateWallpaperLocked(int displayId) {
350        mService.getDisplayContentLocked(displayId).resetAnimationBackgroundAnimator();
351
352        final WindowList windows = mService.getWindowListLocked(displayId);
353        WindowState detachedWallpaper = null;
354
355        for (int i = windows.size() - 1; i >= 0; i--) {
356            final WindowState win = windows.get(i);
357            WindowStateAnimator winAnimator = win.mWinAnimator;
358            if (winAnimator.mSurfaceControl == null) {
359                continue;
360            }
361
362            final int flags = winAnimator.mAttrFlags;
363
364            // If this window is animating, make a note that we have
365            // an animating window and take care of a request to run
366            // a detached wallpaper animation.
367            if (winAnimator.mAnimating) {
368                if (winAnimator.mAnimation != null) {
369                    if ((flags & FLAG_SHOW_WALLPAPER) != 0
370                            && winAnimator.mAnimation.getDetachWallpaper()) {
371                        detachedWallpaper = win;
372                    }
373                    final int color = winAnimator.mAnimation.getBackgroundColor();
374                    if (color != 0) {
375                        win.getStack().setAnimationBackground(winAnimator, color);
376                    }
377                }
378                mAnimating = true;
379            }
380
381            // If this window's app token is running a detached wallpaper
382            // animation, make a note so we can ensure the wallpaper is
383            // displayed behind it.
384            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
385            if (appAnimator != null && appAnimator.animation != null
386                    && appAnimator.animating) {
387                if ((flags & FLAG_SHOW_WALLPAPER) != 0
388                        && appAnimator.animation.getDetachWallpaper()) {
389                    detachedWallpaper = win;
390                }
391
392                final int color = appAnimator.animation.getBackgroundColor();
393                if (color != 0) {
394                    win.getStack().setAnimationBackground(winAnimator, color);
395                }
396            }
397        } // end forall windows
398
399        if (mWindowDetachedWallpaper != detachedWallpaper) {
400            if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
401                    "Detached wallpaper changed from " + mWindowDetachedWallpaper
402                    + " to " + detachedWallpaper);
403            mWindowDetachedWallpaper = detachedWallpaper;
404            mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
405        }
406    }
407
408    /** See if any windows have been drawn, so they (and others associated with them) can now be
409     *  shown. */
410    private void testTokenMayBeDrawnLocked(int displayId) {
411        // See if any windows have been drawn, so they (and others
412        // associated with them) can now be shown.
413        final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks();
414        final int numTasks = tasks.size();
415        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
416            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
417            final int numTokens = tokens.size();
418            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
419                final AppWindowToken wtoken = tokens.get(tokenNdx);
420                AppWindowAnimator appAnimator = wtoken.mAppAnimator;
421                final boolean allDrawn = wtoken.allDrawn;
422                if (allDrawn != appAnimator.allDrawn) {
423                    appAnimator.allDrawn = allDrawn;
424                    if (allDrawn) {
425                        // The token has now changed state to having all
426                        // windows shown...  what to do, what to do?
427                        if (appAnimator.freezingScreen) {
428                            appAnimator.showAllWindowsLocked();
429                            mService.unsetAppFreezingScreenLocked(wtoken, false, true);
430                            if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
431                                    "Setting mOrientationChangeComplete=true because wtoken "
432                                    + wtoken + " numInteresting=" + wtoken.numInterestingWindows
433                                    + " numDrawn=" + wtoken.numDrawnWindows);
434                            // This will set mOrientationChangeComplete and cause a pass through layout.
435                            setAppLayoutChanges(appAnimator,
436                                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
437                                    "testTokenMayBeDrawnLocked: freezingScreen");
438                        } else {
439                            setAppLayoutChanges(appAnimator,
440                                    WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
441                                    "testTokenMayBeDrawnLocked");
442
443                            // We can now show all of the drawn windows!
444                            if (!mService.mOpeningApps.contains(wtoken)) {
445                                mAnimating |= appAnimator.showAllWindowsLocked();
446                            }
447                        }
448                    }
449                }
450            }
451        }
452    }
453
454    private void performAnimationsLocked(final int displayId) {
455        updateWindowsLocked(displayId);
456        updateWallpaperLocked(displayId);
457    }
458
459
460    /** Locked on mService.mWindowMap. */
461    private void animateLocked() {
462        if (!mInitialized) {
463            return;
464        }
465
466        mCurrentTime = SystemClock.uptimeMillis();
467        mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
468        boolean wasAnimating = mAnimating;
469        mAnimating = false;
470        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
471            Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
472        }
473
474        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
475                TAG, ">>> OPEN TRANSACTION animateLocked");
476        SurfaceControl.openTransaction();
477        SurfaceControl.setAnimationTransaction();
478        try {
479            final int numDisplays = mDisplayContentsAnimators.size();
480            for (int i = 0; i < numDisplays; i++) {
481                final int displayId = mDisplayContentsAnimators.keyAt(i);
482                updateAppWindowsLocked(displayId);
483                DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
484
485                final ScreenRotationAnimation screenRotationAnimation =
486                        displayAnimator.mScreenRotationAnimation;
487                if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
488                    if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
489                        mAnimating = true;
490                    } else {
491                        mBulkUpdateParams |= SET_UPDATE_ROTATION;
492                        screenRotationAnimation.kill();
493                        displayAnimator.mScreenRotationAnimation = null;
494                    }
495                }
496
497                // Update animations of all applications, including those
498                // associated with exiting/removed apps
499                performAnimationsLocked(displayId);
500
501                final WindowList windows = mService.getWindowListLocked(displayId);
502                final int N = windows.size();
503                for (int j = 0; j < N; j++) {
504                    windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
505                }
506            }
507
508            for (int i = 0; i < numDisplays; i++) {
509                final int displayId = mDisplayContentsAnimators.keyAt(i);
510
511                testTokenMayBeDrawnLocked(displayId);
512
513                final ScreenRotationAnimation screenRotationAnimation =
514                        mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
515                if (screenRotationAnimation != null) {
516                    screenRotationAnimation.updateSurfacesInTransaction();
517                }
518
519                mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();
520
521                //TODO (multidisplay): Magnification is supported only for the default display.
522                if (mService.mDisplayMagnifier != null && displayId == Display.DEFAULT_DISPLAY) {
523                    mService.mDisplayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
524                }
525            }
526
527            if (mAnimating) {
528                mService.scheduleAnimationLocked();
529            }
530
531            mService.setFocusedStackLayer();
532
533            if (mService.mWatermark != null) {
534                mService.mWatermark.drawIfNeeded();
535            }
536        } catch (RuntimeException e) {
537            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
538        } finally {
539            SurfaceControl.closeTransaction();
540            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
541                    TAG, "<<< CLOSE TRANSACTION animateLocked");
542        }
543
544        boolean hasPendingLayoutChanges = false;
545        final int numDisplays = mService.mDisplayContents.size();
546        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
547            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
548            final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
549            if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
550                mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
551            }
552            if (pendingChanges != 0) {
553                hasPendingLayoutChanges = true;
554            }
555        }
556
557        boolean doRequest = false;
558        if (mBulkUpdateParams != 0) {
559            doRequest = mService.copyAnimToLayoutParamsLocked();
560        }
561
562        if (hasPendingLayoutChanges || doRequest) {
563            mService.requestTraversalLocked();
564        }
565
566        if (!mAnimating && wasAnimating) {
567            mService.requestTraversalLocked();
568        }
569        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
570            Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
571                + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
572                + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
573                + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
574        }
575    }
576
577    static String bulkUpdateParamsToString(int bulkUpdateParams) {
578        StringBuilder builder = new StringBuilder(128);
579        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
580            builder.append(" UPDATE_ROTATION");
581        }
582        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
583            builder.append(" WALLPAPER_MAY_CHANGE");
584        }
585        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
586            builder.append(" FORCE_HIDING_CHANGED");
587        }
588        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
589            builder.append(" ORIENTATION_CHANGE_COMPLETE");
590        }
591        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
592            builder.append(" TURN_ON_SCREEN");
593        }
594        return builder.toString();
595    }
596
597    public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
598        final String subPrefix = "  " + prefix;
599        final String subSubPrefix = "  " + subPrefix;
600
601        for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
602            pw.print(prefix); pw.print("DisplayContentsAnimator #");
603                    pw.print(mDisplayContentsAnimators.keyAt(i));
604                    pw.println(":");
605            DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
606            final WindowList windows =
607                    mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i));
608            final int N = windows.size();
609            for (int j = 0; j < N; j++) {
610                WindowStateAnimator wanim = windows.get(j).mWinAnimator;
611                pw.print(subPrefix); pw.print("Window #"); pw.print(j);
612                        pw.print(": "); pw.println(wanim);
613            }
614            if (displayAnimator.mScreenRotationAnimation != null) {
615                pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
616                displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
617            } else if (dumpAll) {
618                pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
619            }
620        }
621
622        pw.println();
623
624        if (dumpAll) {
625            pw.print(prefix); pw.print("mAnimTransactionSequence=");
626                    pw.print(mAnimTransactionSequence);
627                    pw.print(" mForceHiding="); pw.println(forceHidingToString());
628            pw.print(prefix); pw.print("mCurrentTime=");
629                    pw.println(TimeUtils.formatUptime(mCurrentTime));
630        }
631        if (mBulkUpdateParams != 0) {
632            pw.print(prefix); pw.print("mBulkUpdateParams=0x");
633                    pw.print(Integer.toHexString(mBulkUpdateParams));
634                    pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
635        }
636        if (mWindowDetachedWallpaper != null) {
637            pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
638                pw.println(mWindowDetachedWallpaper);
639        }
640        if (mUniverseBackground != null) {
641            pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
642                    pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
643        }
644    }
645
646    int getPendingLayoutChanges(final int displayId) {
647        if (displayId < 0) {
648            return 0;
649        }
650        return mService.getDisplayContentLocked(displayId).pendingLayoutChanges;
651    }
652
653    void setPendingLayoutChanges(final int displayId, final int changes) {
654        if (displayId >= 0) {
655            mService.getDisplayContentLocked(displayId).pendingLayoutChanges |= changes;
656        }
657    }
658
659    void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) {
660        // Used to track which displays layout changes have been done.
661        SparseIntArray displays = new SparseIntArray(2);
662        WindowList windows = appAnimator.mAppToken.allAppWindows;
663        for (int i = windows.size() - 1; i >= 0; i--) {
664            final int displayId = windows.get(i).getDisplayId();
665            if (displayId >= 0 && displays.indexOfKey(displayId) < 0) {
666                setPendingLayoutChanges(displayId, changes);
667                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
668                    mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId));
669                }
670                // Keep from processing this display again.
671                displays.put(displayId, changes);
672            }
673        }
674    }
675
676    private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
677        DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
678        if (displayAnimator == null) {
679            displayAnimator = new DisplayContentsAnimator();
680            mDisplayContentsAnimators.put(displayId, displayAnimator);
681        }
682        return displayAnimator;
683    }
684
685    void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
686        if (displayId >= 0) {
687            getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
688        }
689    }
690
691    ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
692        if (displayId < 0) {
693            return null;
694        }
695        return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
696    }
697
698    private class DisplayContentsAnimator {
699        ScreenRotationAnimation mScreenRotationAnimation = null;
700    }
701}
702