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