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