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