WindowAnimator.java revision 1bf2b873470d2ba8a4ac218da73516cc2b20aa76
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<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
455    /** Locked on mService.mWindowMap. */
456    private void animateLocked() {
457        if (!mInitialized) {
458            return;
459        }
460
461        mCurrentTime = SystemClock.uptimeMillis();
462        mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
463        boolean wasAnimating = mAnimating;
464        mAnimating = false;
465        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
466            Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
467        }
468
469        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
470                TAG, ">>> OPEN TRANSACTION animateLocked");
471        SurfaceControl.openTransaction();
472        SurfaceControl.setAnimationTransaction();
473        try {
474            final int numDisplays = mDisplayContentsAnimators.size();
475            for (int i = 0; i < numDisplays; i++) {
476                final int displayId = mDisplayContentsAnimators.keyAt(i);
477                updateAppWindowsLocked(displayId);
478                DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
479
480                final ScreenRotationAnimation screenRotationAnimation =
481                        displayAnimator.mScreenRotationAnimation;
482                if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
483                    if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
484                        mAnimating = true;
485                    } else {
486                        mBulkUpdateParams |= SET_UPDATE_ROTATION;
487                        screenRotationAnimation.kill();
488                        displayAnimator.mScreenRotationAnimation = null;
489                    }
490                }
491
492                // Update animations of all applications, including those
493                // associated with exiting/removed apps
494                updateWindowsLocked(displayId);
495                updateWallpaperLocked(displayId);
496
497                final WindowList windows = mService.getWindowListLocked(displayId);
498                final int N = windows.size();
499                for (int j = 0; j < N; j++) {
500                    windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
501                }
502            }
503
504            for (int i = 0; i < numDisplays; i++) {
505                final int displayId = mDisplayContentsAnimators.keyAt(i);
506
507                testTokenMayBeDrawnLocked(displayId);
508
509                final ScreenRotationAnimation screenRotationAnimation =
510                        mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
511                if (screenRotationAnimation != null) {
512                    screenRotationAnimation.updateSurfacesInTransaction();
513                }
514
515                mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();
516
517                //TODO (multidisplay): Magnification is supported only for the default display.
518                if (mService.mDisplayMagnifier != null && displayId == Display.DEFAULT_DISPLAY) {
519                    mService.mDisplayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
520                }
521            }
522
523            if (mAnimating) {
524                mService.scheduleAnimationLocked();
525            }
526
527            mService.setFocusedStackLayer();
528
529            if (mService.mWatermark != null) {
530                mService.mWatermark.drawIfNeeded();
531            }
532        } catch (RuntimeException e) {
533            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
534        } finally {
535            SurfaceControl.closeTransaction();
536            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
537                    TAG, "<<< CLOSE TRANSACTION animateLocked");
538        }
539
540        boolean hasPendingLayoutChanges = false;
541        final int numDisplays = mService.mDisplayContents.size();
542        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
543            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
544            final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
545            if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
546                mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
547            }
548            if (pendingChanges != 0) {
549                hasPendingLayoutChanges = true;
550            }
551        }
552
553        boolean doRequest = false;
554        if (mBulkUpdateParams != 0) {
555            doRequest = mService.copyAnimToLayoutParamsLocked();
556        }
557
558        if (hasPendingLayoutChanges || doRequest) {
559            mService.requestTraversalLocked();
560        }
561
562        if (!mAnimating && wasAnimating) {
563            mService.requestTraversalLocked();
564        }
565        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
566            Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
567                + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
568                + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
569                + Integer.toHexString(getPendingLayoutChanges(Display.DEFAULT_DISPLAY)));
570        }
571    }
572
573    static String bulkUpdateParamsToString(int bulkUpdateParams) {
574        StringBuilder builder = new StringBuilder(128);
575        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
576            builder.append(" UPDATE_ROTATION");
577        }
578        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
579            builder.append(" WALLPAPER_MAY_CHANGE");
580        }
581        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
582            builder.append(" FORCE_HIDING_CHANGED");
583        }
584        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
585            builder.append(" ORIENTATION_CHANGE_COMPLETE");
586        }
587        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
588            builder.append(" TURN_ON_SCREEN");
589        }
590        return builder.toString();
591    }
592
593    public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
594        final String subPrefix = "  " + prefix;
595        final String subSubPrefix = "  " + subPrefix;
596
597        for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
598            pw.print(prefix); pw.print("DisplayContentsAnimator #");
599                    pw.print(mDisplayContentsAnimators.keyAt(i));
600                    pw.println(":");
601            DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
602            final WindowList windows =
603                    mService.getWindowListLocked(mDisplayContentsAnimators.keyAt(i));
604            final int N = windows.size();
605            for (int j = 0; j < N; j++) {
606                WindowStateAnimator wanim = windows.get(j).mWinAnimator;
607                pw.print(subPrefix); pw.print("Window #"); pw.print(j);
608                        pw.print(": "); pw.println(wanim);
609            }
610            if (displayAnimator.mScreenRotationAnimation != null) {
611                pw.print(subPrefix); pw.println("mScreenRotationAnimation:");
612                displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
613            } else if (dumpAll) {
614                pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
615            }
616        }
617
618        pw.println();
619
620        if (dumpAll) {
621            pw.print(prefix); pw.print("mAnimTransactionSequence=");
622                    pw.print(mAnimTransactionSequence);
623                    pw.print(" mForceHiding="); pw.println(forceHidingToString());
624            pw.print(prefix); pw.print("mCurrentTime=");
625                    pw.println(TimeUtils.formatUptime(mCurrentTime));
626        }
627        if (mBulkUpdateParams != 0) {
628            pw.print(prefix); pw.print("mBulkUpdateParams=0x");
629                    pw.print(Integer.toHexString(mBulkUpdateParams));
630                    pw.println(bulkUpdateParamsToString(mBulkUpdateParams));
631        }
632        if (mWindowDetachedWallpaper != null) {
633            pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
634                pw.println(mWindowDetachedWallpaper);
635        }
636        if (mUniverseBackground != null) {
637            pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
638                    pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
639        }
640    }
641
642    int getPendingLayoutChanges(final int displayId) {
643        if (displayId < 0) {
644            return 0;
645        }
646        return mService.getDisplayContentLocked(displayId).pendingLayoutChanges;
647    }
648
649    void setPendingLayoutChanges(final int displayId, final int changes) {
650        if (displayId >= 0) {
651            mService.getDisplayContentLocked(displayId).pendingLayoutChanges |= changes;
652        }
653    }
654
655    void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) {
656        // Used to track which displays layout changes have been done.
657        SparseIntArray displays = new SparseIntArray(2);
658        WindowList windows = appAnimator.mAppToken.allAppWindows;
659        for (int i = windows.size() - 1; i >= 0; i--) {
660            final int displayId = windows.get(i).getDisplayId();
661            if (displayId >= 0 && displays.indexOfKey(displayId) < 0) {
662                setPendingLayoutChanges(displayId, changes);
663                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
664                    mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId));
665                }
666                // Keep from processing this display again.
667                displays.put(displayId, changes);
668            }
669        }
670    }
671
672    private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
673        DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
674        if (displayAnimator == null) {
675            displayAnimator = new DisplayContentsAnimator();
676            mDisplayContentsAnimators.put(displayId, displayAnimator);
677        }
678        return displayAnimator;
679    }
680
681    void setScreenRotationAnimationLocked(int displayId, ScreenRotationAnimation animation) {
682        if (displayId >= 0) {
683            getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation = animation;
684        }
685    }
686
687    ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) {
688        if (displayId < 0) {
689            return null;
690        }
691        return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
692    }
693
694    private class DisplayContentsAnimator {
695        ScreenRotationAnimation mScreenRotationAnimation = null;
696    }
697}
698