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