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