WindowAnimator.java revision f12100e0255c86d0d05dba2e7ba87a745870423d
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;
11
12import static com.android.server.wm.WindowManagerService.H.SET_DIM_PARAMETERS;
13
14import android.content.Context;
15import android.os.SystemClock;
16import android.util.Log;
17import android.util.Slog;
18import android.view.Choreographer;
19import android.view.Surface;
20import android.view.WindowManager;
21import android.view.WindowManagerPolicy;
22import android.view.animation.Animation;
23
24import com.android.internal.policy.impl.PhoneWindowManager;
25
26import java.io.PrintWriter;
27import java.util.ArrayList;
28
29/**
30 * Singleton class that carries out the animations and Surface operations in a separate task
31 * on behalf of WindowManagerService.
32 */
33public class WindowAnimator {
34    private static final String TAG = "WindowAnimator";
35
36    final WindowManagerService mService;
37    final Context mContext;
38    final WindowManagerPolicy mPolicy;
39
40    final Choreographer mChoreographer = Choreographer.getInstance();
41
42    ArrayList<WindowStateAnimator> mWinAnimators = new ArrayList<WindowStateAnimator>();
43
44    boolean mAnimating;
45
46    /** Variables only intended to be valid within each pass through animate(). Does not contain
47     * persistent state. */
48    private class InnerLoopParams {
49        boolean mTokenMayBeDrawn;
50        boolean mForceHiding;
51    }
52    InnerLoopParams mInner = new InnerLoopParams();
53
54    static class LayoutToAnimatorParams {
55        boolean mAnimationScheduled;
56        ArrayList<WindowStateAnimator> mWinAnimators = new ArrayList<WindowStateAnimator>();
57        WindowState mWallpaperTarget;
58    }
59    /** Params from WindowManagerService. Do not modify or read without first locking on
60     * either WindowManagerService.mWindowMap or WindowManagerService.mAnimator.and then on
61     * mLayoutToAnim */
62    final LayoutToAnimatorParams mLayoutToAnim = new LayoutToAnimatorParams();
63
64    final Runnable mAnimationRunnable;
65
66    int mAdjResult;
67
68    int mPendingLayoutChanges;
69
70    /** Overall window dimensions */
71    int mDw, mDh;
72
73    /** Interior window dimensions */
74    int mInnerDw, mInnerDh;
75
76    /** Time of current animation step. Reset on each iteration */
77    long mCurrentTime;
78
79    /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
80     * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
81    private int mTransactionSequence;
82
83    /** The one and only screen rotation if one is happening */
84    ScreenRotationAnimation mScreenRotationAnimation = null;
85
86    // Window currently running an animation that has requested it be detached
87    // from the wallpaper.  This means we need to ensure the wallpaper is
88    // visible behind it in case it animates in a way that would allow it to be
89    // seen. If multiple windows satisfy this, use the lowest window.
90    WindowState mWindowDetachedWallpaper = null;
91
92    DimSurface mWindowAnimationBackgroundSurface = null;
93
94    int mBulkUpdateParams = 0;
95
96    DimAnimator mDimAnimator = null;
97    DimAnimator.Parameters mDimParams = null;
98
99    static final int WALLPAPER_ACTION_PENDING = 1;
100    int mPendingActions;
101
102    WindowState mWallpaperTarget = null;
103
104    WindowAnimator(final WindowManagerService service, final Context context,
105            final WindowManagerPolicy policy) {
106        mService = service;
107        mContext = context;
108        mPolicy = policy;
109
110        mAnimationRunnable = new Runnable() {
111            @Override
112            public void run() {
113                // TODO(cmautner): When full isolation is achieved for animation, the first lock
114                // goes away and only the WindowAnimator.this remains.
115                synchronized(mService.mWindowMap) {
116                    synchronized(WindowAnimator.this) {
117                        copyLayoutToAnimParamsLocked();
118                        animateLocked();
119                    }
120                }
121            }
122        };
123
124        mWindowAnimationBackgroundSurface = new DimSurface(mService.mFxSession);
125    }
126
127    /** Copy all WindowManagerService params into local params here. Locked on 'this'. */
128    private void copyLayoutToAnimParamsLocked() {
129        final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim;
130        synchronized(layoutToAnim) {
131            layoutToAnim.mAnimationScheduled = false;
132
133            mWinAnimators = new ArrayList<WindowStateAnimator>(layoutToAnim.mWinAnimators);
134            mWallpaperTarget = layoutToAnim.mWallpaperTarget;
135        }
136    }
137
138    /** Note that Locked in this case is on mLayoutToAnim */
139    void scheduleAnimationLocked() {
140        final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim;
141        if (!layoutToAnim.mAnimationScheduled) {
142            layoutToAnim.mAnimationScheduled = true;
143            mChoreographer.postCallback(
144                    Choreographer.CALLBACK_ANIMATION, mAnimationRunnable, null);
145        }
146    }
147
148    void hideWallpapersLocked(final WindowState w) {
149        if ((mService.mWallpaperTarget == w && mService.mLowerWallpaperTarget == null)
150                || mService.mWallpaperTarget == null) {
151            for (final WindowToken token : mService.mWallpaperTokens) {
152                for (final WindowState wallpaper : token.windows) {
153                    final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
154                    if (!winAnimator.mLastHidden) {
155                        winAnimator.hide();
156                        mService.dispatchWallpaperVisibility(wallpaper, false);
157                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
158                    }
159                }
160                token.hidden = true;
161            }
162        }
163    }
164
165    private void updateWindowsAppsAndRotationAnimationsLocked() {
166        final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
167        int i;
168        final int NAT = appTokens.size();
169        for (i=0; i<NAT; i++) {
170            final AppWindowAnimator appAnimator = appTokens.get(i).mAppAnimator;
171            final boolean wasAnimating = appAnimator.animation != null
172                    && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
173            if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
174                mAnimating = true;
175            } else if (wasAnimating) {
176                // stopped animating, do one more pass through the layout
177                mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
178                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
179                    mService.debugLayoutRepeats("appToken " + appAnimator.mAppToken + " done",
180                        mPendingLayoutChanges);
181                }
182                if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
183                        "updateWindowsApps...: done animating " + appAnimator.mAppToken);
184            }
185        }
186
187        final int NEAT = mService.mExitingAppTokens.size();
188        for (i=0; i<NEAT; i++) {
189            final AppWindowAnimator appAnimator = mService.mExitingAppTokens.get(i).mAppAnimator;
190            final boolean wasAnimating = appAnimator.animation != null
191                    && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
192            if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
193                mAnimating = true;
194            } else if (wasAnimating) {
195                // stopped animating, do one more pass through the layout
196                mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
197                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
198                    mService.debugLayoutRepeats("exiting appToken " + appAnimator.mAppToken
199                        + " done", mPendingLayoutChanges);
200                }
201                if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
202                        "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
203            }
204        }
205
206        if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) {
207            if (mScreenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
208                mAnimating = true;
209            } else {
210                mBulkUpdateParams |= SET_UPDATE_ROTATION;
211                mScreenRotationAnimation.kill();
212                mScreenRotationAnimation = null;
213            }
214        }
215    }
216
217    private void updateWindowsAndWallpaperLocked() {
218        ++mTransactionSequence;
219
220        ArrayList<WindowStateAnimator> unForceHiding = null;
221        boolean wallpaperInUnForceHiding = false;
222        WindowStateAnimator windowAnimationBackground = null;
223        int windowAnimationBackgroundColor = 0;
224        WindowState detachedWallpaper = null;
225
226        for (int i = mWinAnimators.size() - 1; i >= 0; i--) {
227            WindowStateAnimator winAnimator = mWinAnimators.get(i);
228            WindowState win = winAnimator.mWin;
229            final int flags = winAnimator.mAttrFlags;
230
231            if (winAnimator.mSurface != null) {
232                final boolean wasAnimating = winAnimator.mWasAnimating;
233                final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
234
235                if (WindowManagerService.DEBUG_WALLPAPER) {
236                    Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
237                            ", nowAnimating=" + nowAnimating);
238                }
239
240                // If this window is animating, make a note that we have
241                // an animating window and take care of a request to run
242                // a detached wallpaper animation.
243                if (nowAnimating) {
244                    if (winAnimator.mAnimation != null) {
245                        if ((flags & FLAG_SHOW_WALLPAPER) != 0
246                                && winAnimator.mAnimation.getDetachWallpaper()) {
247                            detachedWallpaper = win;
248                        }
249                        final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
250                        if (backgroundColor != 0) {
251                            if (windowAnimationBackground == null || (winAnimator.mAnimLayer <
252                                    windowAnimationBackground.mAnimLayer)) {
253                                windowAnimationBackground = winAnimator;
254                                windowAnimationBackgroundColor = backgroundColor;
255                            }
256                        }
257                    }
258                    mAnimating = true;
259                }
260
261                // If this window's app token is running a detached wallpaper
262                // animation, make a note so we can ensure the wallpaper is
263                // displayed behind it.
264                final AppWindowAnimator appAnimator =
265                        win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
266                if (appAnimator != null && appAnimator.animation != null
267                        && appAnimator.animating) {
268                    if ((flags & FLAG_SHOW_WALLPAPER) != 0
269                            && appAnimator.animation.getDetachWallpaper()) {
270                        detachedWallpaper = win;
271                    }
272                    final int backgroundColor = appAnimator.animation.getBackgroundColor();
273                    if (backgroundColor != 0) {
274                        if (windowAnimationBackground == null || (winAnimator.mAnimLayer <
275                                windowAnimationBackground.mAnimLayer)) {
276                            windowAnimationBackground = winAnimator;
277                            windowAnimationBackgroundColor = backgroundColor;
278                        }
279                    }
280                }
281
282                if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
283                    mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
284                    mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
285                    if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
286                        mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
287                            mPendingLayoutChanges);
288                    }
289                }
290
291                if (mPolicy.doesForceHide(win, win.mAttrs)) {
292                    if (!wasAnimating && nowAnimating) {
293                        if (WindowManagerService.DEBUG_ANIM ||
294                                WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
295                                "Animation started that could impact force hide: " + win);
296                        mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
297                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
298                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
299                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
300                                mPendingLayoutChanges);
301                        }
302                        mService.mFocusMayChange = true;
303                    }
304                    if (win.isReadyForDisplay() && winAnimator.mAnimationIsEntrance) {
305                        mInner.mForceHiding = true;
306                    }
307                    if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
308                            "Force hide " + mInner.mForceHiding
309                            + " hasSurface=" + win.mHasSurface
310                            + " policyVis=" + win.mPolicyVisibility
311                            + " destroying=" + win.mDestroying
312                            + " attHidden=" + win.mAttachedHidden
313                            + " vis=" + win.mViewVisibility
314                            + " hidden=" + win.mRootToken.hidden
315                            + " anim=" + win.mWinAnimator.mAnimation);
316                } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
317                    final boolean changed;
318                    if (mInner.mForceHiding && (!winAnimator.isAnimating()
319                            || (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0)) {
320                        changed = win.hideLw(false, false);
321                        if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
322                                "Now policy hidden: " + win);
323                    } else {
324                        changed = win.showLw(false, false);
325                        if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
326                                "Now policy shown: " + win);
327                        if (changed) {
328                            if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
329                                    && win.isVisibleNow() /*w.isReadyForDisplay()*/) {
330                                if (unForceHiding == null) {
331                                    unForceHiding = new ArrayList<WindowStateAnimator>();
332                                }
333                                unForceHiding.add(winAnimator);
334                                if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
335                                    wallpaperInUnForceHiding = true;
336                                }
337                            }
338                            if (mCurrentFocus == null || mCurrentFocus.mLayer < win.mLayer) {
339                                // We are showing on to of the current
340                                // focus, so re-evaluate focus to make
341                                // sure it is correct.
342                                mService.mFocusMayChange = true;
343                            }
344                        }
345                    }
346                    if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) {
347                        mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
348                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
349                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
350                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
351                                mPendingLayoutChanges);
352                        }
353                    }
354                }
355            }
356
357            final AppWindowToken atoken = win.mAppToken;
358            if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
359                if (atoken.lastTransactionSequence != mTransactionSequence) {
360                    atoken.lastTransactionSequence = mTransactionSequence;
361                    atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
362                    atoken.startingDisplayed = false;
363                }
364                if ((win.isOnScreen() || winAnimator.mAttrType
365                        == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
366                        && !win.mExiting && !win.mDestroying) {
367                    if (WindowManagerService.DEBUG_VISIBILITY ||
368                            WindowManagerService.DEBUG_ORIENTATION) {
369                        Slog.v(TAG, "Eval win " + win + ": isDrawn=" + win.isDrawnLw()
370                                + ", isAnimating=" + winAnimator.isAnimating());
371                        if (!win.isDrawnLw()) {
372                            Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface
373                                    + " pv=" + win.mPolicyVisibility
374                                    + " mDrawState=" + winAnimator.mDrawState
375                                    + " ah=" + win.mAttachedHidden
376                                    + " th=" + atoken.hiddenRequested
377                                    + " a=" + winAnimator.mAnimating);
378                        }
379                    }
380                    if (win != atoken.startingWindow) {
381                        if (!atoken.mAppAnimator.freezingScreen || !win.mAppFreezing) {
382                            atoken.numInterestingWindows++;
383                            if (win.isDrawnLw()) {
384                                atoken.numDrawnWindows++;
385                                if (WindowManagerService.DEBUG_VISIBILITY ||
386                                        WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
387                                        "tokenMayBeDrawn: " + atoken
388                                        + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
389                                        + " mAppFreezing=" + win.mAppFreezing);
390                                mInner.mTokenMayBeDrawn = true;
391                            }
392                        }
393                    } else if (win.isDrawnLw()) {
394                        atoken.startingDisplayed = true;
395                    }
396                }
397            } else if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
398                if (winAnimator.performShowLocked()) {
399                    mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
400                    if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
401                        mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
402                            mPendingLayoutChanges);
403                    }
404                }
405            }
406            final AppWindowAnimator appAnimator =
407                    atoken == null ? null : atoken.mAppAnimator;
408            if (appAnimator != null && appAnimator.thumbnail != null) {
409                if (appAnimator.thumbnailTransactionSeq != mTransactionSequence) {
410                    appAnimator.thumbnailTransactionSeq = mTransactionSequence;
411                    appAnimator.thumbnailLayer = 0;
412                }
413                if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
414                    appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
415                }
416            }
417        } // end forall windows
418
419        if (mWindowDetachedWallpaper != detachedWallpaper) {
420            if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
421                    "Detached wallpaper changed from " + mWindowDetachedWallpaper
422                    + " to " + detachedWallpaper);
423            mWindowDetachedWallpaper = detachedWallpaper;
424            mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
425        }
426
427        if (windowAnimationBackgroundColor != 0) {
428            // If the window that wants black is the current wallpaper
429            // target, then the black goes *below* the wallpaper so we
430            // don't cause the wallpaper to suddenly disappear.
431            int animLayer = windowAnimationBackground.mAnimLayer;
432            WindowState win = windowAnimationBackground.mWin;
433            if (windowAnimationBackground != null && mService.mWallpaperTarget == win
434                    || mService.mLowerWallpaperTarget == win
435                    || mService.mUpperWallpaperTarget == win) {
436                final int N = mWinAnimators.size();
437                for (int i = 0; i < N; i++) {
438                    WindowStateAnimator winAnimator = mWinAnimators.get(i);
439                    if (winAnimator.mWin.mIsWallpaper) {
440                        animLayer = winAnimator.mAnimLayer;
441                        break;
442                    }
443                }
444            }
445
446            final int dw = mDw;
447            final int dh = mDh;
448            mWindowAnimationBackgroundSurface.show(dw, dh,
449                    animLayer - WindowManagerService.LAYER_OFFSET_DIM,
450                    windowAnimationBackgroundColor);
451        } else {
452            mWindowAnimationBackgroundSurface.hide();
453        }
454
455        // If we have windows that are being show due to them no longer
456        // being force-hidden, apply the appropriate animation to them.
457        if (unForceHiding != null) {
458            for (int i=unForceHiding.size()-1; i>=0; i--) {
459                Animation a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding);
460                if (a != null) {
461                    final WindowStateAnimator winAnimator = unForceHiding.get(i);
462                    winAnimator.setAnimation(a);
463                    winAnimator.mAnimationIsEntrance = true;
464                }
465            }
466        }
467    }
468
469    private void testTokenMayBeDrawnLocked() {
470        // See if any windows have been drawn, so they (and others
471        // associated with them) can now be shown.
472        final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
473        final int NT = appTokens.size();
474        for (int i=0; i<NT; i++) {
475            AppWindowToken wtoken = appTokens.get(i);
476            if (wtoken.mAppAnimator.freezingScreen) {
477                int numInteresting = wtoken.numInterestingWindows;
478                if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
479                    if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
480                            "allDrawn: " + wtoken
481                            + " interesting=" + numInteresting
482                            + " drawn=" + wtoken.numDrawnWindows);
483                    wtoken.mAppAnimator.showAllWindowsLocked();
484                    mService.unsetAppFreezingScreenLocked(wtoken, false, true);
485                    if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
486                            "Setting mOrientationChangeComplete=true because wtoken "
487                            + wtoken + " numInteresting=" + numInteresting
488                            + " numDrawn=" + wtoken.numDrawnWindows);
489                    // This will set mOrientationChangeComplete and cause a pass through layout.
490                    mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
491                }
492            } else if (!wtoken.allDrawn) {
493                int numInteresting = wtoken.numInterestingWindows;
494                if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
495                    if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
496                            "allDrawn: " + wtoken
497                            + " interesting=" + numInteresting
498                            + " drawn=" + wtoken.numDrawnWindows);
499                    wtoken.allDrawn = true;
500                    mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
501                    if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
502                        mService.debugLayoutRepeats("testTokenMayBeDrawnLocked",
503                            mPendingLayoutChanges);
504                    }
505
506                    // We can now show all of the drawn windows!
507                    if (!mService.mOpeningApps.contains(wtoken)) {
508                        mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
509                    }
510                }
511            }
512        }
513    }
514
515    private void performAnimationsLocked() {
516        mInner.mTokenMayBeDrawn = false;
517        mInner.mForceHiding = false;
518
519        updateWindowsAndWallpaperLocked();
520        if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
521            mPendingActions |= WALLPAPER_ACTION_PENDING;
522        }
523
524        if (mInner.mTokenMayBeDrawn) {
525            testTokenMayBeDrawnLocked();
526        }
527    }
528
529    // TODO(cmautner): Change the following comment when no longer locked on mWindowMap */
530    /** Locked on mService.mWindowMap and this. */
531    private void animateLocked() {
532        mPendingLayoutChanges = 0;
533        mCurrentTime = SystemClock.uptimeMillis();
534        mBulkUpdateParams = 0;
535        boolean wasAnimating = mAnimating;
536        mAnimating = false;
537        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
538            Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
539        }
540
541        // Update animations of all applications, including those
542        // associated with exiting/removed apps
543        Surface.openTransaction();
544
545        try {
546            updateWindowsAppsAndRotationAnimationsLocked();
547            performAnimationsLocked();
548
549            // THIRD LOOP: Update the surfaces of all windows.
550
551            if (mScreenRotationAnimation != null) {
552                mScreenRotationAnimation.updateSurfaces();
553            }
554
555            final int N = mWinAnimators.size();
556            for (int i = 0; i < N; i++) {
557                mWinAnimators.get(i).prepareSurfaceLocked(true);
558            }
559
560            if (mDimParams != null) {
561                mDimAnimator.updateParameters(mContext.getResources(), mDimParams, mCurrentTime);
562            }
563            if (mDimAnimator != null && mDimAnimator.mDimShown) {
564                mAnimating |= mDimAnimator.updateSurface(isDimming(), mCurrentTime,
565                        !mService.okToDisplay());
566            }
567
568            if (mService.mBlackFrame != null) {
569                if (mScreenRotationAnimation != null) {
570                    mService.mBlackFrame.setMatrix(
571                            mScreenRotationAnimation.getEnterTransformation().getMatrix());
572                } else {
573                    mService.mBlackFrame.clearMatrix();
574                }
575            }
576
577            if (mService.mWatermark != null) {
578                mService.mWatermark.drawIfNeeded();
579            }
580        } catch (RuntimeException e) {
581            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
582        } finally {
583            Surface.closeTransaction();
584        }
585
586        if (mBulkUpdateParams != 0 || mPendingLayoutChanges != 0) {
587            final WindowManagerService.AnimatorToLayoutParams animToLayout = mService.mAnimToLayout;
588            synchronized (animToLayout) {
589                animToLayout.mBulkUpdateParams = mBulkUpdateParams;
590                animToLayout.mPendingLayoutChanges = mPendingLayoutChanges;
591                animToLayout.mWindowDetachedWallpaper = mWindowDetachedWallpaper;
592                mService.setAnimatorParametersLocked();
593            }
594        }
595
596        if (mAnimating) {
597            synchronized (mLayoutToAnim) {
598                scheduleAnimationLocked();
599            }
600        } else if (wasAnimating) {
601            mService.requestTraversalLocked();
602        }
603        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
604            Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
605                + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
606                + " mPendingLayoutChanges=" + Integer.toHexString(mPendingLayoutChanges));
607        }
608    }
609
610    WindowState mCurrentFocus;
611    void setCurrentFocus(final WindowState currentFocus) {
612        mCurrentFocus = currentFocus;
613    }
614
615    void setDisplayDimensions(final int curWidth, final int curHeight,
616                        final int appWidth, final int appHeight) {
617        mDw = curWidth;
618        mDh = curHeight;
619        mInnerDw = appWidth;
620        mInnerDh = appHeight;
621    }
622
623    void startDimming(final WindowStateAnimator winAnimator, final float target,
624                      final int width, final int height) {
625        if (mDimAnimator == null) {
626            mDimAnimator = new DimAnimator(mService.mFxSession);
627        }
628        // Only set dim params on the highest dimmed layer.
629        final WindowStateAnimator dimWinAnimator = mDimParams == null
630                ? null : mDimParams.mDimWinAnimator;
631        // Don't turn on for an unshown surface, or for any layer but the highest dimmed one.
632        if (winAnimator.mSurfaceShown &&
633                (dimWinAnimator == null || !dimWinAnimator.mSurfaceShown
634                || dimWinAnimator.mAnimLayer < winAnimator.mAnimLayer)) {
635            mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS,
636                    new DimAnimator.Parameters(winAnimator, width, height, target)));
637        }
638    }
639
640    // TODO(cmautner): Move into Handler
641    void stopDimming() {
642        mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS, null));
643    }
644
645    boolean isDimming() {
646        return mDimParams != null;
647    }
648
649    boolean isDimming(final WindowStateAnimator winAnimator) {
650        return mDimParams != null && mDimParams.mDimWinAnimator == winAnimator;
651    }
652
653    public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
654        if (mWindowDetachedWallpaper != null) {
655            pw.print("  mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper);
656        }
657        if (mWindowAnimationBackgroundSurface != null) {
658            pw.println("  mWindowAnimationBackgroundSurface:");
659            mWindowAnimationBackgroundSurface.printTo("    ", pw);
660        }
661        if (mDimAnimator != null) {
662            pw.println("  mDimAnimator:");
663            mDimAnimator.printTo("    ", pw);
664        } else {
665            pw.println( "  no DimAnimator ");
666        }
667    }
668
669    static class SetAnimationParams {
670        final WindowStateAnimator mWinAnimator;
671        final Animation mAnimation;
672        final int mAnimDw;
673        final int mAnimDh;
674        public SetAnimationParams(final WindowStateAnimator winAnimator,
675                                  final Animation animation, final int animDw, final int animDh) {
676            mWinAnimator = winAnimator;
677            mAnimation = animation;
678            mAnimDw = animDw;
679            mAnimDh = animDh;
680        }
681    }
682
683    synchronized void clearPendingActions() {
684        mPendingActions = 0;
685    }
686}
687