WindowSurfacePlacer.java revision 4ffc3180121b36eec2577b3c311ad4da44c3af56
1package com.android.server.wm;
2
3import static android.app.ActivityManagerInternal.APP_TRANSITION_SAVED_SURFACE;
4import static android.app.ActivityManagerInternal.APP_TRANSITION_STARTING_WINDOW;
5import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
6import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
7import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
8import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
9import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
10import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
11import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
12import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
13import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
14import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
15import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
16import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
17import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
18import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
19import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
20import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
21import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
22import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
23import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
24import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
25import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
26import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
27import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
28import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
29import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
30import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
31import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
32import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
33import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
34import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
35import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
36import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
37import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
38import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
39import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
40import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
41import static com.android.server.wm.WindowManagerService.H.DO_TRAVERSAL;
42import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
43import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION_STARTING;
44import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN;
45import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
46import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE;
47import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
48import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
49import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
50import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
51import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
52import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
53import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
54import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
55
56import android.graphics.Bitmap;
57import android.graphics.Canvas;
58import android.graphics.PixelFormat;
59import android.graphics.Rect;
60import android.os.Debug;
61import android.os.PowerManager;
62import android.os.RemoteException;
63import android.os.SystemClock;
64import android.os.Trace;
65import android.provider.Settings;
66import android.util.ArraySet;
67import android.util.Slog;
68import android.view.Display;
69import android.view.DisplayInfo;
70import android.view.Surface;
71import android.view.SurfaceControl;
72import android.view.View;
73import android.view.WindowManager.LayoutParams;
74import android.view.animation.Animation;
75
76import java.io.PrintWriter;
77import java.util.ArrayList;
78
79/**
80 * Positions windows and their surfaces.
81 *
82 * It sets positions of windows by calculating their frames and then applies this by positioning
83 * surfaces according to these frames. Z layer is still assigned withing WindowManagerService.
84 */
85class WindowSurfacePlacer {
86    private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfacePlacer" : TAG_WM;
87    private final WindowManagerService mService;
88    private final WallpaperController mWallpaperControllerLocked;
89
90    private boolean mInLayout = false;
91
92    /** Only do a maximum of 6 repeated layouts. After that quit */
93    private int mLayoutRepeatCount;
94
95    static final int SET_UPDATE_ROTATION                = 1 << 0;
96    static final int SET_WALLPAPER_MAY_CHANGE           = 1 << 1;
97    static final int SET_FORCE_HIDING_CHANGED           = 1 << 2;
98    static final int SET_ORIENTATION_CHANGE_COMPLETE    = 1 << 3;
99    static final int SET_TURN_ON_SCREEN                 = 1 << 4;
100    static final int SET_WALLPAPER_ACTION_PENDING       = 1 << 5;
101
102    boolean mWallpaperMayChange = false;
103    boolean mOrientationChangeComplete = true;
104    boolean mWallpaperActionPending = false;
105
106    private boolean mWallpaperForceHidingChanged = false;
107    private Object mLastWindowFreezeSource = null;
108    private Session mHoldScreen = null;
109    private boolean mObscured = false;
110    private boolean mSyswin = false;
111    private float mScreenBrightness = -1;
112    private float mButtonBrightness = -1;
113    private long mUserActivityTimeout = -1;
114    private boolean mUpdateRotation = false;
115    private final Rect mTmpStartRect = new Rect();
116    private final Rect mTmpContentRect = new Rect();
117
118    // Set to true when the display contains content to show the user.
119    // When false, the display manager may choose to mirror or blank the display.
120    private boolean mDisplayHasContent = false;
121
122    // Only set while traversing the default display based on its content.
123    // Affects the behavior of mirroring on secondary displays.
124    private boolean mObscureApplicationContentOnSecondaryDisplays = false;
125
126    private float mPreferredRefreshRate = 0;
127
128    private int mPreferredModeId = 0;
129
130    private boolean mTraversalScheduled;
131    private int mDeferDepth = 0;
132
133    private boolean mSustainedPerformanceModeEnabled = false;
134    private boolean mSustainedPerformanceModeCurrent = false;
135
136    // Following variables are for debugging screen wakelock only.
137    // Last window that requires screen wakelock
138    WindowState mHoldScreenWindow = null;
139    // Last window that obscures all windows below
140    WindowState mObsuringWindow = null;
141
142    private static final class LayerAndToken {
143        public int layer;
144        public AppWindowToken token;
145    }
146    private final LayerAndToken mTmpLayerAndToken = new LayerAndToken();
147
148    private final ArrayList<SurfaceControl> mPendingDestroyingSurfaces = new ArrayList<>();
149
150    public WindowSurfacePlacer(WindowManagerService service) {
151        mService = service;
152        mWallpaperControllerLocked = mService.mWallpaperControllerLocked;
153    }
154
155    /**
156     * See {@link WindowManagerService#deferSurfaceLayout()}
157     */
158    void deferLayout() {
159        mDeferDepth++;
160    }
161
162    /**
163     * See {@link WindowManagerService#continueSurfaceLayout()}
164     */
165    void continueLayout() {
166        mDeferDepth--;
167        if (mDeferDepth <= 0) {
168            performSurfacePlacement();
169        }
170    }
171
172    final void performSurfacePlacement() {
173        if (mDeferDepth > 0) {
174            return;
175        }
176        int loopCount = 6;
177        do {
178            mTraversalScheduled = false;
179            performSurfacePlacementLoop();
180            mService.mH.removeMessages(DO_TRAVERSAL);
181            loopCount--;
182        } while (mTraversalScheduled && loopCount > 0);
183        mWallpaperActionPending = false;
184    }
185
186    private void performSurfacePlacementLoop() {
187        if (mInLayout) {
188            if (DEBUG) {
189                throw new RuntimeException("Recursive call!");
190            }
191            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
192                    + Debug.getCallers(3));
193            return;
194        }
195
196        if (mService.mWaitingForConfig) {
197            // Our configuration has changed (most likely rotation), but we
198            // don't yet have the complete configuration to report to
199            // applications.  Don't do any window layout until we have it.
200            return;
201        }
202
203        if (!mService.mDisplayReady) {
204            // Not yet initialized, nothing to do.
205            return;
206        }
207
208        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
209        mInLayout = true;
210
211        boolean recoveringMemory = false;
212        if (!mService.mForceRemoves.isEmpty()) {
213            recoveringMemory = true;
214            // Wait a little bit for things to settle down, and off we go.
215            while (!mService.mForceRemoves.isEmpty()) {
216                WindowState ws = mService.mForceRemoves.remove(0);
217                Slog.i(TAG, "Force removing: " + ws);
218                mService.removeWindowInnerLocked(ws);
219            }
220            Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
221            Object tmp = new Object();
222            synchronized (tmp) {
223                try {
224                    tmp.wait(250);
225                } catch (InterruptedException e) {
226                }
227            }
228        }
229
230        try {
231            performSurfacePlacementInner(recoveringMemory);
232
233            mInLayout = false;
234
235            if (mService.needsLayout()) {
236                if (++mLayoutRepeatCount < 6) {
237                    requestTraversal();
238                } else {
239                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
240                    mLayoutRepeatCount = 0;
241                }
242            } else {
243                mLayoutRepeatCount = 0;
244            }
245
246            if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
247                mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
248                mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
249            }
250        } catch (RuntimeException e) {
251            mInLayout = false;
252            Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
253        }
254
255        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
256    }
257
258    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
259        if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
260            Slog.v(TAG, "Layouts looping: " + msg +
261                    ", mPendingLayoutChanges = 0x" + Integer.toHexString(pendingLayoutChanges));
262        }
263    }
264
265    // "Something has changed!  Let's make it correct now."
266    private void performSurfacePlacementInner(boolean recoveringMemory) {
267        if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
268                + Debug.getCallers(3));
269
270        int i;
271        boolean updateInputWindowsNeeded = false;
272
273        if (mService.mFocusMayChange) {
274            mService.mFocusMayChange = false;
275            updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
276                    UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
277        }
278
279        // Initialize state of exiting tokens.
280        final int numDisplays = mService.mDisplayContents.size();
281        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
282            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
283            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
284                displayContent.mExitingTokens.get(i).hasVisible = false;
285            }
286        }
287
288        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
289            // Initialize state of exiting applications.
290            final AppTokenList exitingAppTokens =
291                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
292            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
293                exitingAppTokens.get(tokenNdx).hasVisible = false;
294            }
295        }
296
297        mHoldScreen = null;
298        mHoldScreenWindow = null;
299        mObsuringWindow = null;
300        mScreenBrightness = -1;
301        mButtonBrightness = -1;
302        mUserActivityTimeout = -1;
303        mObscureApplicationContentOnSecondaryDisplays = false;
304        mSustainedPerformanceModeCurrent = false;
305        mService.mTransactionSequence++;
306
307        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
308        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
309        final int defaultDw = defaultInfo.logicalWidth;
310        final int defaultDh = defaultInfo.logicalHeight;
311
312        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
313                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
314        SurfaceControl.openTransaction();
315        try {
316            applySurfaceChangesTransaction(recoveringMemory, numDisplays, defaultDw, defaultDh);
317        } catch (RuntimeException e) {
318            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
319        } finally {
320            SurfaceControl.closeTransaction();
321            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
322                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
323        }
324
325        final WindowList defaultWindows = defaultDisplay.getWindowList();
326
327        // If we are ready to perform an app transition, check through
328        // all of the app tokens to be shown and see if they are ready
329        // to go.
330        if (mService.mAppTransition.isReady()) {
331            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
332            if (DEBUG_LAYOUT_REPEATS)
333                debugLayoutRepeats("after handleAppTransitionReadyLocked",
334                        defaultDisplay.pendingLayoutChanges);
335        }
336
337        if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
338            // We have finished the animation of an app transition.  To do
339            // this, we have delayed a lot of operations like showing and
340            // hiding apps, moving apps in Z-order, etc.  The app token list
341            // reflects the correct Z-order, but the window list may now
342            // be out of sync with it.  So here we will just rebuild the
343            // entire app window list.  Fun!
344            defaultDisplay.pendingLayoutChanges |=
345                    mService.handleAnimatingStoppedAndTransitionLocked();
346            if (DEBUG_LAYOUT_REPEATS)
347                debugLayoutRepeats("after handleAnimStopAndXitionLock",
348                        defaultDisplay.pendingLayoutChanges);
349        }
350
351        if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
352                && !mService.mAppTransition.isReady()) {
353            // At this point, there was a window with a wallpaper that
354            // was force hiding other windows behind it, but now it
355            // is going away.  This may be simple -- just animate
356            // away the wallpaper and its window -- or it may be
357            // hard -- the wallpaper now needs to be shown behind
358            // something that was hidden.
359            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
360            if (DEBUG_LAYOUT_REPEATS)
361                debugLayoutRepeats("after animateAwayWallpaperLocked",
362                        defaultDisplay.pendingLayoutChanges);
363        }
364        mWallpaperForceHidingChanged = false;
365
366        if (mWallpaperMayChange) {
367            if (DEBUG_WALLPAPER_LIGHT)
368                Slog.v(TAG, "Wallpaper may change!  Adjusting");
369            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
370            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
371                    defaultDisplay.pendingLayoutChanges);
372        }
373
374        if (mService.mFocusMayChange) {
375            mService.mFocusMayChange = false;
376            if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
377                    false /*updateInputWindows*/)) {
378                updateInputWindowsNeeded = true;
379                defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
380            }
381        }
382
383        if (mService.needsLayout()) {
384            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
385            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
386                    defaultDisplay.pendingLayoutChanges);
387        }
388
389        for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
390            WindowState win = mService.mResizingWindows.get(i);
391            if (win.mAppFreezing) {
392                // Don't remove this window until rotation has completed.
393                continue;
394            }
395            // Discard the saved surface if window size is changed, it can't be reused.
396            if (win.mAppToken != null) {
397                win.mAppToken.destroySavedSurfaces();
398            }
399            win.reportResized();
400            mService.mResizingWindows.remove(i);
401        }
402
403        if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG,
404                "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete);
405        if (mOrientationChangeComplete) {
406            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
407                mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
408                mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
409                mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
410            }
411            mService.stopFreezingDisplayLocked();
412        }
413
414        // Destroy the surface of any windows that are no longer visible.
415        boolean wallpaperDestroyed = false;
416        i = mService.mDestroySurface.size();
417        if (i > 0) {
418            do {
419                i--;
420                WindowState win = mService.mDestroySurface.get(i);
421                win.mDestroying = false;
422                if (mService.mInputMethodWindow == win) {
423                    mService.mInputMethodWindow = null;
424                }
425                if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
426                    wallpaperDestroyed = true;
427                }
428                win.destroyOrSaveSurface();
429            } while (i > 0);
430            mService.mDestroySurface.clear();
431        }
432
433        // Time to remove any exiting tokens?
434        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
435            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
436            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
437            for (i = exitingTokens.size() - 1; i >= 0; i--) {
438                WindowToken token = exitingTokens.get(i);
439                if (!token.hasVisible) {
440                    exitingTokens.remove(i);
441                    if (token.windowType == TYPE_WALLPAPER) {
442                        mWallpaperControllerLocked.removeWallpaperToken(token);
443                    }
444                }
445            }
446        }
447
448        // Time to remove any exiting applications?
449        for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
450            // Initialize state of exiting applications.
451            final AppTokenList exitingAppTokens =
452                    mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
453            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
454                AppWindowToken token = exitingAppTokens.get(i);
455                if (!token.hasVisible && !mService.mClosingApps.contains(token) &&
456                        (!token.mIsExiting || token.allAppWindows.isEmpty())) {
457                    // Make sure there is no animation running on this token,
458                    // so any windows associated with it will be removed as
459                    // soon as their animations are complete
460                    token.mAppAnimator.clearAnimation();
461                    token.mAppAnimator.animating = false;
462                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
463                            "performLayout: App token exiting now removed" + token);
464                    token.removeAppFromTaskLocked();
465                }
466            }
467        }
468
469        if (wallpaperDestroyed) {
470            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
471            defaultDisplay.layoutNeeded = true;
472        }
473
474        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
475            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
476            if (displayContent.pendingLayoutChanges != 0) {
477                displayContent.layoutNeeded = true;
478            }
479        }
480
481        // Finally update all input windows now that the window changes have stabilized.
482        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
483
484        mService.setHoldScreenLocked(mHoldScreen);
485        if (!mService.mDisplayFrozen) {
486            if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) {
487                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
488            } else {
489                mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
490                        toBrightnessOverride(mScreenBrightness));
491            }
492            if (mButtonBrightness < 0
493                    || mButtonBrightness > 1.0f) {
494                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
495            } else {
496                mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
497                        toBrightnessOverride(mButtonBrightness));
498            }
499            mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
500                    mUserActivityTimeout);
501        }
502
503        if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
504            mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
505            mService.mPowerManagerInternal.powerHint(
506                    mService.mPowerManagerInternal.POWER_HINT_SUSTAINED_PERFORMANCE_MODE,
507                    (mSustainedPerformanceModeEnabled ? 1 : 0));
508        }
509
510        if (mService.mTurnOnScreen) {
511            if (mService.mAllowTheaterModeWakeFromLayout
512                    || Settings.Global.getInt(mService.mContext.getContentResolver(),
513                        Settings.Global.THEATER_MODE_ON, 0) == 0) {
514                if (DEBUG_VISIBILITY || DEBUG_POWER) {
515                    Slog.v(TAG, "Turning screen on after layout!");
516                }
517                mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
518                        "android.server.wm:TURN_ON");
519            }
520            mService.mTurnOnScreen = false;
521        }
522
523        if (mUpdateRotation) {
524            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
525            if (mService.updateRotationUncheckedLocked(false)) {
526                mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
527            } else {
528                mUpdateRotation = false;
529            }
530        }
531
532        if (mService.mWaitingForDrawnCallback != null ||
533                (mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
534                        !mUpdateRotation)) {
535            mService.checkDrawnWindowsLocked();
536        }
537
538        final int N = mService.mPendingRemove.size();
539        if (N > 0) {
540            if (mService.mPendingRemoveTmp.length < N) {
541                mService.mPendingRemoveTmp = new WindowState[N+10];
542            }
543            mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
544            mService.mPendingRemove.clear();
545            DisplayContentList displayList = new DisplayContentList();
546            for (i = 0; i < N; i++) {
547                WindowState w = mService.mPendingRemoveTmp[i];
548                mService.removeWindowInnerLocked(w);
549                final DisplayContent displayContent = w.getDisplayContent();
550                if (displayContent != null && !displayList.contains(displayContent)) {
551                    displayList.add(displayContent);
552                }
553            }
554
555            for (DisplayContent displayContent : displayList) {
556                mService.mLayersController.assignLayersLocked(displayContent.getWindowList());
557                displayContent.layoutNeeded = true;
558            }
559        }
560
561        // Remove all deferred displays stacks, tasks, and activities.
562        for (int displayNdx = mService.mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
563            mService.mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
564        }
565
566        if (updateInputWindowsNeeded) {
567            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
568        }
569        mService.setFocusTaskRegionLocked();
570
571        // Check to see if we are now in a state where the screen should
572        // be enabled, because the window obscured flags have changed.
573        mService.enableScreenIfNeededLocked();
574
575        mService.scheduleAnimationLocked();
576        mService.mWindowPlacerLocked.destroyPendingSurfaces();
577
578        if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
579                "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
580    }
581
582    private void applySurfaceChangesTransaction(boolean recoveringMemory, int numDisplays,
583            int defaultDw, int defaultDh) {
584        if (mService.mWatermark != null) {
585            mService.mWatermark.positionSurface(defaultDw, defaultDh);
586        }
587        if (mService.mStrictModeFlash != null) {
588            mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
589        }
590        if (mService.mCircularDisplayMask != null) {
591            mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
592                    mService.mRotation);
593        }
594        if (mService.mEmulatorDisplayOverlay != null) {
595            mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
596                    mService.mRotation);
597        }
598
599        boolean focusDisplayed = false;
600
601        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
602            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
603            boolean updateAllDrawn = false;
604            WindowList windows = displayContent.getWindowList();
605            DisplayInfo displayInfo = displayContent.getDisplayInfo();
606            final int displayId = displayContent.getDisplayId();
607            final int dw = displayInfo.logicalWidth;
608            final int dh = displayInfo.logicalHeight;
609            final int innerDw = displayInfo.appWidth;
610            final int innerDh = displayInfo.appHeight;
611            final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
612
613            // Reset for each display.
614            mDisplayHasContent = false;
615            mPreferredRefreshRate = 0;
616            mPreferredModeId = 0;
617
618            int repeats = 0;
619            do {
620                repeats++;
621                if (repeats > 6) {
622                    Slog.w(TAG, "Animation repeat aborted after too many iterations");
623                    displayContent.layoutNeeded = false;
624                    break;
625                }
626
627                if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
628                        "On entry to LockedInner", displayContent.pendingLayoutChanges);
629
630                if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
631                        mWallpaperControllerLocked.adjustWallpaperWindows()) {
632                    mService.mLayersController.assignLayersLocked(windows);
633                    displayContent.layoutNeeded = true;
634                }
635
636                if (isDefaultDisplay
637                        && (displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
638                    if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
639                    if (mService.updateOrientationFromAppTokensLocked(true)) {
640                        displayContent.layoutNeeded = true;
641                        mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
642                    }
643                }
644
645                if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
646                    displayContent.layoutNeeded = true;
647                }
648
649                // FIRST LOOP: Perform a layout, if needed.
650                if (repeats < LAYOUT_REPEAT_THRESHOLD) {
651                    performLayoutLockedInner(displayContent, repeats == 1,
652                            false /* updateInputWindows */);
653                } else {
654                    Slog.w(TAG, "Layout repeat skipped after too many iterations");
655                }
656
657                // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
658                // it is animating.
659                displayContent.pendingLayoutChanges = 0;
660
661                if (isDefaultDisplay) {
662                    mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
663                    for (int i = windows.size() - 1; i >= 0; i--) {
664                        WindowState w = windows.get(i);
665                        if (w.mHasSurface) {
666                            mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs,
667                                    w.mAttachedWindow);
668                        }
669                    }
670                    displayContent.pendingLayoutChanges |=
671                            mService.mPolicy.finishPostLayoutPolicyLw();
672                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishPostLayoutPolicyLw",
673                            displayContent.pendingLayoutChanges);
674                }
675            } while (displayContent.pendingLayoutChanges != 0);
676
677            mObscured = false;
678            mSyswin = false;
679            displayContent.resetDimming();
680
681            // Only used if default window
682            final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
683
684            for (int i = windows.size() - 1; i >= 0; i--) {
685                WindowState w = windows.get(i);
686                final Task task = w.getTask();
687                final boolean obscuredChanged = w.mObscured != mObscured;
688
689                // Update effect.
690                w.mObscured = mObscured;
691                if (!mObscured) {
692                    handleNotObscuredLocked(w, displayInfo);
693                }
694
695                w.applyDimLayerIfNeeded();
696
697                if (isDefaultDisplay && obscuredChanged
698                        && mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) {
699                    // This is the wallpaper target and its obscured state
700                    // changed... make sure the current wallaper's visibility
701                    // has been updated accordingly.
702                    mWallpaperControllerLocked.updateWallpaperVisibility();
703                }
704
705                final WindowStateAnimator winAnimator = w.mWinAnimator;
706
707                // If the window has moved due to its containing content frame changing, then
708                // notify the listeners and optionally animate it. Simply checking a change of
709                // position is not enough, because being move due to dock divider is not a trigger
710                // for animation.
711                if (w.hasMoved()) {
712                    // Frame has moved, containing content frame has also moved, and we're not
713                    // currently animating... let's do something.
714                    final int left = w.mFrame.left;
715                    final int top = w.mFrame.top;
716                    final boolean adjustedForMinimizedDockOrIme = task != null
717                                && (task.mStack.isAdjustedForMinimizedDockedStack()
718                                    || task.mStack.isAdjustedForIme());
719                    if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
720                            && !w.isDragResizing() && !adjustedForMinimizedDockOrIme
721                            && (task == null || !w.getTask().mStack.getFreezeMovementAnimations())
722                            && !w.mWinAnimator.mLastHidden) {
723                        winAnimator.setMoveAnimation(left, top);
724                    }
725
726                    //TODO (multidisplay): Accessibility supported only for the default display.
727                    if (mService.mAccessibilityController != null
728                            && displayId == Display.DEFAULT_DISPLAY) {
729                        mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
730                    }
731
732                    try {
733                        w.mClient.moved(left, top);
734                    } catch (RemoteException e) {
735                    }
736                    w.mMovedByResize = false;
737                }
738
739                //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
740                w.mContentChanged = false;
741
742                // Moved from updateWindowsAndWallpaperLocked().
743                if (w.mHasSurface) {
744                    // If we have recently synchronized a previous transaction for this
745                    // window ensure we don't push through an unsynchronized one now.
746                    winAnimator.deferToPendingTransaction();
747
748                    // Take care of the window being ready to display.
749                    final boolean committed = winAnimator.commitFinishDrawingLocked();
750                    if (isDefaultDisplay && committed) {
751                        if (w.mAttrs.type == TYPE_DREAM) {
752                            // HACK: When a dream is shown, it may at that
753                            // point hide the lock screen.  So we need to
754                            // redo the layout to let the phone window manager
755                            // make this happen.
756                            displayContent.pendingLayoutChanges |=
757                                    FINISH_LAYOUT_REDO_LAYOUT;
758                            if (DEBUG_LAYOUT_REPEATS) {
759                                debugLayoutRepeats("dream and commitFinishDrawingLocked true",
760                                        displayContent.pendingLayoutChanges);
761                            }
762                        }
763                        if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
764                            if (DEBUG_WALLPAPER_LIGHT)
765                                Slog.v(TAG, "First draw done in potential wallpaper target " + w);
766                            mWallpaperMayChange = true;
767                            displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
768                            if (DEBUG_LAYOUT_REPEATS) {
769                                debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true",
770                                        displayContent.pendingLayoutChanges);
771                            }
772                        }
773                    }
774                    if (!winAnimator.isAnimationStarting()) {
775                        // Updates the shown frame before we set up the surface. This is needed
776                        // because the resizing could change the top-left position (in addition to
777                        // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
778                        // position the surface.
779                        //
780                        // If an animation is being started, we can't call this method because the
781                        // animation hasn't processed its initial transformation yet, but in general
782                        // we do want to update the position if the window is animating.
783                        winAnimator.computeShownFrameLocked();
784                    }
785                    winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
786                }
787
788                final AppWindowToken atoken = w.mAppToken;
789                if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) {
790                    Slog.d(TAG, "updateWindows: starting " + w
791                            + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
792                            + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
793                }
794                if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
795                    if (atoken.lastTransactionSequence != mService.mTransactionSequence) {
796                        atoken.lastTransactionSequence = mService.mTransactionSequence;
797                        atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
798                        atoken.startingDisplayed = false;
799                    }
800                    if ((w.isOnScreenIgnoringKeyguard()
801                            || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
802                            && !w.mAnimatingExit && !w.mDestroying) {
803                        if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
804                            Slog.v(TAG, "Eval win " + w + ": isDrawn="
805                                    + w.isDrawnLw()
806                                    + ", isAnimationSet=" + winAnimator.isAnimationSet());
807                            if (!w.isDrawnLw()) {
808                                Slog.v(TAG, "Not displayed: s="
809                                        + winAnimator.mSurfaceController
810                                        + " pv=" + w.mPolicyVisibility
811                                        + " mDrawState=" + winAnimator.drawStateToString()
812                                        + " ah=" + w.mAttachedHidden
813                                        + " th=" + atoken.hiddenRequested
814                                        + " a=" + winAnimator.mAnimating);
815                            }
816                        }
817                        if (w != atoken.startingWindow) {
818                            if (!w.mAppDied &&
819                                    (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing)) {
820                                atoken.numInterestingWindows++;
821                                if (w.isDrawnLw()) {
822                                    atoken.numDrawnWindows++;
823                                    if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
824                                        Slog.v(TAG, "tokenMayBeDrawn: " + atoken
825                                                + " freezingScreen="
826                                                + atoken.mAppAnimator.freezingScreen
827                                                + " mAppFreezing=" + w.mAppFreezing);
828                                    updateAllDrawn = true;
829                                }
830                            }
831                        } else if (w.isDrawnLw()) {
832                            mService.mH.sendEmptyMessage(NOTIFY_STARTING_WINDOW_DRAWN);
833                            atoken.startingDisplayed = true;
834                        }
835                    }
836                }
837
838                if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
839                        && w.isDisplayedLw()) {
840                    focusDisplayed = true;
841                }
842
843                mService.updateResizingWindows(w);
844            }
845
846            mService.mDisplayManagerInternal.setDisplayProperties(displayId,
847                    mDisplayHasContent,
848                    mPreferredRefreshRate,
849                    mPreferredModeId,
850                    true /* inTraversal, must call performTraversalInTrans... below */);
851
852            mService.getDisplayContentLocked(displayId).stopDimmingIfNeeded();
853
854            if (updateAllDrawn) {
855                updateAllDrawnLocked(displayContent);
856            }
857        }
858
859        if (focusDisplayed) {
860            mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
861        }
862
863        // Give the display manager a chance to adjust properties
864        // like display rotation if it needs to.
865        mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
866    }
867
868    boolean isInLayout() {
869        return mInLayout;
870    }
871
872    final void performLayoutLockedInner(final DisplayContent displayContent,
873            boolean initial, boolean updateInputWindows) {
874        if (!displayContent.layoutNeeded) {
875            return;
876        }
877        displayContent.layoutNeeded = false;
878        WindowList windows = displayContent.getWindowList();
879        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
880
881        DisplayInfo displayInfo = displayContent.getDisplayInfo();
882        final int dw = displayInfo.logicalWidth;
883        final int dh = displayInfo.logicalHeight;
884
885        if (mService.mInputConsumer != null) {
886            mService.mInputConsumer.layout(dw, dh);
887        }
888
889        if (mService.mWallpaperInputConsumer != null) {
890            mService.mWallpaperInputConsumer.layout(dw, dh);
891        }
892
893        final int N = windows.size();
894        int i;
895
896        if (DEBUG_LAYOUT) {
897            Slog.v(TAG, "-------------------------------------");
898            Slog.v(TAG, "performLayout: needed="
899                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
900        }
901
902        mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation,
903                mService.mCurConfiguration.uiMode);
904        if (isDefaultDisplay) {
905            // Not needed on non-default displays.
906            mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
907            mService.mScreenRect.set(0, 0, dw, dh);
908        }
909
910        mService.mPolicy.getContentRectLw(mTmpContentRect);
911        displayContent.resize(mTmpContentRect);
912
913        int seq = mService.mLayoutSeq+1;
914        if (seq < 0) seq = 0;
915        mService.mLayoutSeq = seq;
916
917        boolean behindDream = false;
918
919        // First perform layout of any root windows (not attached
920        // to another window).
921        int topAttached = -1;
922        for (i = N-1; i >= 0; i--) {
923            final WindowState win = windows.get(i);
924
925            // Don't do layout of a window if it is not visible, or
926            // soon won't be visible, to avoid wasting time and funky
927            // changes while a window is animating away.
928            final boolean gone = (behindDream && mService.mPolicy.canBeForceHidden(win, win.mAttrs))
929                    || win.isGoneForLayoutLw();
930
931            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
932                Slog.v(TAG, "1ST PASS " + win
933                        + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
934                        + " mLayoutAttached=" + win.mLayoutAttached
935                        + " screen changed=" + win.isConfigChanged());
936                final AppWindowToken atoken = win.mAppToken;
937                if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
938                        + win.mViewVisibility + " mRelayoutCalled="
939                        + win.mRelayoutCalled + " hidden="
940                        + win.mRootToken.hidden + " hiddenRequested="
941                        + (atoken != null && atoken.hiddenRequested)
942                        + " mAttachedHidden=" + win.mAttachedHidden);
943                else Slog.v(TAG, "  VIS: mViewVisibility="
944                        + win.mViewVisibility + " mRelayoutCalled="
945                        + win.mRelayoutCalled + " hidden="
946                        + win.mRootToken.hidden + " hiddenRequested="
947                        + (atoken != null && atoken.hiddenRequested)
948                        + " mAttachedHidden=" + win.mAttachedHidden);
949            }
950
951            // If this view is GONE, then skip it -- keep the current
952            // frame, and let the caller know so they can ignore it
953            // if they want.  (We do the normal layout for INVISIBLE
954            // windows, since that means "perform layout as normal,
955            // just don't display").
956            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
957                    || ((win.isConfigChanged() || win.setInsetsChanged())
958                            && !win.isGoneForLayoutLw() &&
959                            ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
960                            (win.mHasSurface && win.mAppToken != null &&
961                            win.mAppToken.layoutConfigChanges)))) {
962                if (!win.mLayoutAttached) {
963                    if (initial) {
964                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
965                        win.mContentChanged = false;
966                    }
967                    if (win.mAttrs.type == TYPE_DREAM) {
968                        // Don't layout windows behind a dream, so that if it
969                        // does stuff like hide the status bar we won't get a
970                        // bad transition when it goes away.
971                        behindDream = true;
972                    }
973                    win.mLayoutNeeded = false;
974                    win.prelayout();
975                    mService.mPolicy.layoutWindowLw(win, null);
976                    win.mLayoutSeq = seq;
977
978                    // Window frames may have changed. Update dim layer with the new bounds.
979                    final Task task = win.getTask();
980                    if (task != null) {
981                        displayContent.mDimLayerController.updateDimLayer(task);
982                    }
983
984                    if (DEBUG_LAYOUT) Slog.v(TAG,
985                            "  LAYOUT: mFrame="
986                            + win.mFrame + " mContainingFrame="
987                            + win.mContainingFrame + " mDisplayFrame="
988                            + win.mDisplayFrame);
989                } else {
990                    if (topAttached < 0) topAttached = i;
991                }
992            }
993        }
994
995        boolean attachedBehindDream = false;
996
997        // Now perform layout of attached windows, which usually
998        // depend on the position of the window they are attached to.
999        // XXX does not deal with windows that are attached to windows
1000        // that are themselves attached.
1001        for (i = topAttached; i >= 0; i--) {
1002            final WindowState win = windows.get(i);
1003
1004            if (win.mLayoutAttached) {
1005                if (DEBUG_LAYOUT) Slog.v(TAG,
1006                        "2ND PASS " + win + " mHaveFrame=" + win.mHaveFrame + " mViewVisibility="
1007                        + win.mViewVisibility + " mRelayoutCalled=" + win.mRelayoutCalled);
1008                // If this view is GONE, then skip it -- keep the current
1009                // frame, and let the caller know so they can ignore it
1010                // if they want.  (We do the normal layout for INVISIBLE
1011                // windows, since that means "perform layout as normal,
1012                // just don't display").
1013                if (attachedBehindDream && mService.mPolicy.canBeForceHidden(win, win.mAttrs)) {
1014                    continue;
1015                }
1016                if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
1017                        || !win.mHaveFrame || win.mLayoutNeeded) {
1018                    if (initial) {
1019                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
1020                        win.mContentChanged = false;
1021                    }
1022                    win.mLayoutNeeded = false;
1023                    win.prelayout();
1024                    mService.mPolicy.layoutWindowLw(win, win.mAttachedWindow);
1025                    win.mLayoutSeq = seq;
1026                    if (DEBUG_LAYOUT) Slog.v(TAG,
1027                            "  LAYOUT: mFrame=" + win.mFrame + " mContainingFrame="
1028                            + win.mContainingFrame + " mDisplayFrame=" + win.mDisplayFrame);
1029                }
1030            } else if (win.mAttrs.type == TYPE_DREAM) {
1031                // Don't layout windows behind a dream, so that if it
1032                // does stuff like hide the status bar we won't get a
1033                // bad transition when it goes away.
1034                attachedBehindDream = behindDream;
1035            }
1036        }
1037
1038        // Window frames may have changed. Tell the input dispatcher about it.
1039        mService.mInputMonitor.setUpdateInputWindowsNeededLw();
1040        if (updateInputWindows) {
1041            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
1042        }
1043
1044        mService.mPolicy.finishLayoutLw();
1045        mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
1046    }
1047
1048    /**
1049     * @param windows List of windows on default display.
1050     * @return bitmap indicating if another pass through layout must be made.
1051     */
1052    private int handleAppTransitionReadyLocked(WindowList windows) {
1053        int appsCount = mService.mOpeningApps.size();
1054        if (!transitionGoodToGo(appsCount)) {
1055            return 0;
1056        }
1057        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
1058        int transit = mService.mAppTransition.getAppTransition();
1059        if (mService.mSkipAppTransitionAnimation) {
1060            transit = AppTransition.TRANSIT_UNSET;
1061        }
1062        mService.mSkipAppTransitionAnimation = false;
1063        mService.mNoAnimationNotifyOnTransitionFinished.clear();
1064
1065        mService.mH.removeMessages(APP_TRANSITION_TIMEOUT);
1066
1067        mService.rebuildAppWindowListLocked();
1068
1069        mWallpaperMayChange = false;
1070
1071        // The top-most window will supply the layout params,
1072        // and we will determine it below.
1073        LayoutParams animLp = null;
1074        int bestAnimLayer = -1;
1075        boolean fullscreenAnim = false;
1076        boolean voiceInteraction = false;
1077
1078        final WindowState lowerWallpaperTarget =
1079                mWallpaperControllerLocked.getLowerWallpaperTarget();
1080        final WindowState upperWallpaperTarget =
1081                mWallpaperControllerLocked.getUpperWallpaperTarget();
1082
1083        boolean openingAppHasWallpaper = false;
1084        boolean closingAppHasWallpaper = false;
1085        final AppWindowToken lowerWallpaperAppToken;
1086        final AppWindowToken upperWallpaperAppToken;
1087        if (lowerWallpaperTarget == null) {
1088            lowerWallpaperAppToken = upperWallpaperAppToken = null;
1089        } else {
1090            lowerWallpaperAppToken = lowerWallpaperTarget.mAppToken;
1091            upperWallpaperAppToken = upperWallpaperTarget.mAppToken;
1092        }
1093
1094        int i;
1095        // Do a first pass through the tokens for two
1096        // things:
1097        // (1) Determine if both the closing and opening
1098        // app token sets are wallpaper targets, in which
1099        // case special animations are needed
1100        // (since the wallpaper needs to stay static
1101        // behind them).
1102        // (2) Find the layout params of the top-most
1103        // application window in the tokens, which is
1104        // what will control the animation theme.
1105        final int closingAppsCount = mService.mClosingApps.size();
1106        appsCount = closingAppsCount + mService.mOpeningApps.size();
1107        for (i = 0; i < appsCount; i++) {
1108            final AppWindowToken wtoken;
1109            if (i < closingAppsCount) {
1110                wtoken = mService.mClosingApps.valueAt(i);
1111                if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
1112                    closingAppHasWallpaper = true;
1113                }
1114            } else {
1115                wtoken = mService.mOpeningApps.valueAt(i - closingAppsCount);
1116                if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
1117                    openingAppHasWallpaper = true;
1118                }
1119            }
1120
1121            voiceInteraction |= wtoken.voiceInteraction;
1122
1123            if (wtoken.appFullscreen) {
1124                WindowState ws = wtoken.findMainWindow();
1125                if (ws != null) {
1126                    animLp = ws.mAttrs;
1127                    bestAnimLayer = ws.mLayer;
1128                    fullscreenAnim = true;
1129                }
1130            } else if (!fullscreenAnim) {
1131                WindowState ws = wtoken.findMainWindow();
1132                if (ws != null) {
1133                    if (ws.mLayer > bestAnimLayer) {
1134                        animLp = ws.mAttrs;
1135                        bestAnimLayer = ws.mLayer;
1136                    }
1137                }
1138            }
1139        }
1140
1141        transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
1142                closingAppHasWallpaper, lowerWallpaperTarget, upperWallpaperTarget);
1143
1144        // If all closing windows are obscured, then there is
1145        // no need to do an animation.  This is the case, for
1146        // example, when this transition is being done behind
1147        // the lock screen.
1148        if (!mService.mPolicy.allowAppAnimationsLw()) {
1149            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
1150                    "Animations disallowed by keyguard or dream.");
1151            animLp = null;
1152        }
1153
1154        processApplicationsAnimatingInPlace(transit);
1155
1156        mTmpLayerAndToken.token = null;
1157        handleClosingApps(transit, animLp, voiceInteraction, mTmpLayerAndToken);
1158        final AppWindowToken topClosingApp = mTmpLayerAndToken.token;
1159        final int topClosingLayer = mTmpLayerAndToken.layer;
1160
1161        final AppWindowToken topOpeningApp = handleOpeningApps(transit,
1162                animLp, voiceInteraction, topClosingLayer);
1163
1164        final AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ?  null :
1165                topOpeningApp.mAppAnimator;
1166        final AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
1167                topClosingApp.mAppAnimator;
1168
1169        mService.mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator,
1170                mService.mOpeningApps, mService.mClosingApps);
1171        mService.mAppTransition.postAnimationCallback();
1172        mService.mAppTransition.clear();
1173
1174        mService.mOpeningApps.clear();
1175        mService.mClosingApps.clear();
1176
1177        // This has changed the visibility of windows, so perform
1178        // a new layout to get them all up-to-date.
1179        mService.getDefaultDisplayContentLocked().layoutNeeded = true;
1180
1181        // TODO(multidisplay): IMEs are only supported on the default display.
1182        if (windows == mService.getDefaultWindowListLocked()
1183                && !mService.moveInputMethodWindowsIfNeededLocked(true)) {
1184            mService.mLayersController.assignLayersLocked(windows);
1185        }
1186        mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
1187                true /*updateInputWindows*/);
1188        mService.mFocusMayChange = false;
1189        mService.notifyActivityDrawnForKeyguard();
1190        return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
1191    }
1192
1193    private AppWindowToken handleOpeningApps(int transit, LayoutParams animLp,
1194            boolean voiceInteraction, int topClosingLayer) {
1195        AppWindowToken topOpeningApp = null;
1196        final int appsCount = mService.mOpeningApps.size();
1197        for (int i = 0; i < appsCount; i++) {
1198            AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
1199            final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
1200            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
1201
1202            if (!appAnimator.usingTransferredAnimation) {
1203                appAnimator.clearThumbnail();
1204                appAnimator.setNullAnimation();
1205            }
1206            wtoken.inPendingTransaction = false;
1207
1208            if (!mService.setTokenVisibilityLocked(
1209                    wtoken, animLp, true, transit, false, voiceInteraction)){
1210                // This token isn't going to be animating. Add it to the list of tokens to
1211                // be notified of app transition complete since the notification will not be
1212                // sent be the app window animator.
1213                mService.mNoAnimationNotifyOnTransitionFinished.add(wtoken.token);
1214            }
1215            wtoken.updateReportedVisibilityLocked();
1216            wtoken.waitingToShow = false;
1217
1218            appAnimator.mAllAppWinAnimators.clear();
1219            final int windowsCount = wtoken.allAppWindows.size();
1220            for (int j = 0; j < windowsCount; j++) {
1221                appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
1222            }
1223            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
1224                    ">>> OPEN TRANSACTION handleAppTransitionReadyLocked()");
1225            SurfaceControl.openTransaction();
1226            try {
1227                mService.mAnimator.orAnimating(appAnimator.showAllWindowsLocked());
1228            } finally {
1229                SurfaceControl.closeTransaction();
1230                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
1231                        "<<< CLOSE TRANSACTION handleAppTransitionReadyLocked()");
1232            }
1233            mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
1234
1235            int topOpeningLayer = 0;
1236            if (animLp != null) {
1237                int layer = -1;
1238                for (int j = 0; j < wtoken.windows.size(); j++) {
1239                    final WindowState win = wtoken.windows.get(j);
1240                    // Clearing the mAnimatingExit flag before entering animation. It will be set to true
1241                    // if app window is removed, or window relayout to invisible. We don't want to
1242                    // clear it out for windows that get replaced, because the animation depends on
1243                    // the flag to remove the replaced window.
1244                    //
1245                    // We also don't clear the mAnimatingExit flag for windows which have the
1246                    // mRemoveOnExit flag. This indicates an explicit remove request has been issued
1247                    // by the client. We should let animation proceed and not clear this flag or
1248                    // they won't eventually be removed by WindowStateAnimator#finishExit.
1249                    if (!win.mWillReplaceWindow && !win.mRemoveOnExit) {
1250                        win.mAnimatingExit = false;
1251                    }
1252                    if (win.mWinAnimator.mAnimLayer > layer) {
1253                        layer = win.mWinAnimator.mAnimLayer;
1254                    }
1255                }
1256                if (topOpeningApp == null || layer > topOpeningLayer) {
1257                    topOpeningApp = wtoken;
1258                    topOpeningLayer = layer;
1259                }
1260            }
1261            if (mService.mAppTransition.isNextAppTransitionThumbnailUp()) {
1262                createThumbnailAppAnimator(transit, wtoken, topOpeningLayer, topClosingLayer);
1263            }
1264        }
1265        return topOpeningApp;
1266    }
1267
1268    private void handleClosingApps(int transit, LayoutParams animLp, boolean voiceInteraction,
1269            LayerAndToken layerAndToken) {
1270        final int appsCount;
1271        appsCount = mService.mClosingApps.size();
1272        for (int i = 0; i < appsCount; i++) {
1273            AppWindowToken wtoken = mService.mClosingApps.valueAt(i);
1274            final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
1275            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
1276            appAnimator.clearThumbnail();
1277            appAnimator.setNullAnimation();
1278            wtoken.inPendingTransaction = false;
1279            mService.setTokenVisibilityLocked(wtoken, animLp, false, transit, false,
1280                    voiceInteraction);
1281            wtoken.updateReportedVisibilityLocked();
1282            // Force the allDrawn flag, because we want to start
1283            // this guy's animations regardless of whether it's
1284            // gotten drawn.
1285            wtoken.allDrawn = true;
1286            wtoken.deferClearAllDrawn = false;
1287            // Ensure that apps that are mid-starting are also scheduled to have their
1288            // starting windows removed after the animation is complete
1289            if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) {
1290                mService.scheduleRemoveStartingWindowLocked(wtoken);
1291            }
1292            mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
1293
1294            if (animLp != null) {
1295                int layer = -1;
1296                for (int j = 0; j < wtoken.windows.size(); j++) {
1297                    WindowState win = wtoken.windows.get(j);
1298                    if (win.mWinAnimator.mAnimLayer > layer) {
1299                        layer = win.mWinAnimator.mAnimLayer;
1300                    }
1301                }
1302                if (layerAndToken.token == null || layer > layerAndToken.layer) {
1303                    layerAndToken.token = wtoken;
1304                    layerAndToken.layer = layer;
1305                }
1306            }
1307            if (mService.mAppTransition.isNextAppTransitionThumbnailDown()) {
1308                createThumbnailAppAnimator(transit, wtoken, 0, layerAndToken.layer);
1309            }
1310        }
1311    }
1312
1313    private boolean transitionGoodToGo(int appsCount) {
1314        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
1315                "Checking " + appsCount + " opening apps (frozen="
1316                        + mService.mDisplayFrozen + " timeout="
1317                        + mService.mAppTransition.isTimeout() + ")...");
1318        int reason = APP_TRANSITION_TIMEOUT;
1319        if (!mService.mAppTransition.isTimeout()) {
1320            for (int i = 0; i < appsCount; i++) {
1321                AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
1322                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
1323                        "Check opening app=" + wtoken + ": allDrawn="
1324                        + wtoken.allDrawn + " startingDisplayed="
1325                        + wtoken.startingDisplayed + " startingMoved="
1326                        + wtoken.startingMoved + " isRelaunching()="
1327                        + wtoken.isRelaunching());
1328
1329                if (wtoken.isRelaunching()) {
1330                    return false;
1331                }
1332
1333                final boolean drawnBeforeRestoring = wtoken.allDrawn;
1334                wtoken.restoreSavedSurfaces();
1335
1336                if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
1337                    return false;
1338                }
1339                if (wtoken.allDrawn) {
1340                    reason = drawnBeforeRestoring ? APP_TRANSITION_WINDOWS_DRAWN
1341                            : APP_TRANSITION_SAVED_SURFACE;
1342                } else {
1343                    reason = APP_TRANSITION_STARTING_WINDOW;
1344                }
1345            }
1346
1347            // We also need to wait for the specs to be fetched, if needed.
1348            if (mService.mAppTransition.isFetchingAppTransitionsSpecs()) {
1349                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "isFetchingAppTransitionSpecs=true");
1350                return false;
1351            }
1352
1353            // If the wallpaper is visible, we need to check it's ready too.
1354            boolean wallpaperReady = !mWallpaperControllerLocked.isWallpaperVisible() ||
1355                    mWallpaperControllerLocked.wallpaperTransitionReady();
1356            if (wallpaperReady) {
1357                mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING, reason, 0).sendToTarget();
1358                return true;
1359            }
1360            return false;
1361        }
1362        mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING, reason, 0).sendToTarget();
1363        return true;
1364    }
1365
1366    private int maybeUpdateTransitToWallpaper(int transit, boolean openingAppHasWallpaper,
1367            boolean closingAppHasWallpaper, WindowState lowerWallpaperTarget,
1368            WindowState upperWallpaperTarget) {
1369        // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
1370        final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
1371        final WindowState oldWallpaper =
1372                mWallpaperControllerLocked.isWallpaperTargetAnimating()
1373                        ? null : wallpaperTarget;
1374        final ArraySet<AppWindowToken> openingApps = mService.mOpeningApps;
1375        final ArraySet<AppWindowToken> closingApps = mService.mClosingApps;
1376        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
1377                "New wallpaper target=" + wallpaperTarget
1378                        + ", oldWallpaper=" + oldWallpaper
1379                        + ", lower target=" + lowerWallpaperTarget
1380                        + ", upper target=" + upperWallpaperTarget
1381                        + ", openingApps=" + openingApps
1382                        + ", closingApps=" + closingApps);
1383        mService.mAnimateWallpaperWithTarget = false;
1384        if (closingAppHasWallpaper && openingAppHasWallpaper) {
1385            if (DEBUG_APP_TRANSITIONS)
1386                Slog.v(TAG, "Wallpaper animation!");
1387            switch (transit) {
1388                case AppTransition.TRANSIT_ACTIVITY_OPEN:
1389                case AppTransition.TRANSIT_TASK_OPEN:
1390                case AppTransition.TRANSIT_TASK_TO_FRONT:
1391                    transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
1392                    break;
1393                case AppTransition.TRANSIT_ACTIVITY_CLOSE:
1394                case AppTransition.TRANSIT_TASK_CLOSE:
1395                case AppTransition.TRANSIT_TASK_TO_BACK:
1396                    transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
1397                    break;
1398            }
1399            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
1400                    "New transit: " + AppTransition.appTransitionToString(transit));
1401        } else if (oldWallpaper != null && !mService.mOpeningApps.isEmpty()
1402                && !openingApps.contains(oldWallpaper.mAppToken)
1403                && closingApps.contains(oldWallpaper.mAppToken)) {
1404            // We are transitioning from an activity with a wallpaper to one without.
1405            transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
1406            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
1407                    "New transit away from wallpaper: "
1408                    + AppTransition.appTransitionToString(transit));
1409        } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw() &&
1410                openingApps.contains(wallpaperTarget.mAppToken)) {
1411            // We are transitioning from an activity without
1412            // a wallpaper to now showing the wallpaper
1413            transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
1414            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
1415                    "New transit into wallpaper: "
1416                    + AppTransition.appTransitionToString(transit));
1417        } else {
1418            mService.mAnimateWallpaperWithTarget = true;
1419        }
1420        return transit;
1421    }
1422
1423    /**
1424     * @param w WindowState this method is applied to.
1425     * @param dispInfo info of the display that the window's obscuring state is checked against.
1426     */
1427    private void handleNotObscuredLocked(final WindowState w, final DisplayInfo dispInfo) {
1428        final LayoutParams attrs = w.mAttrs;
1429        final int attrFlags = attrs.flags;
1430        final boolean canBeSeen = w.isDisplayedLw();
1431        final int privateflags = attrs.privateFlags;
1432
1433        if (canBeSeen && w.isObscuringFullscreen(dispInfo)) {
1434            // This window completely covers everything behind it,
1435            // so we want to leave all of them as undimmed (for
1436            // performance reasons).
1437            if (!mObscured) {
1438                mObsuringWindow = w;
1439            }
1440
1441            mObscured = true;
1442        }
1443
1444        if (w.mHasSurface) {
1445            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
1446                mHoldScreen = w.mSession;
1447                mHoldScreenWindow = w;
1448            } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) {
1449                Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding "
1450                        + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by"
1451                        + Debug.getCallers(10));
1452            }
1453            if (!mSyswin && w.mAttrs.screenBrightness >= 0
1454                    && mScreenBrightness < 0) {
1455                mScreenBrightness = w.mAttrs.screenBrightness;
1456            }
1457            if (!mSyswin && w.mAttrs.buttonBrightness >= 0
1458                    && mButtonBrightness < 0) {
1459                mButtonBrightness = w.mAttrs.buttonBrightness;
1460            }
1461            if (!mSyswin && w.mAttrs.userActivityTimeout >= 0
1462                    && mUserActivityTimeout < 0) {
1463                mUserActivityTimeout = w.mAttrs.userActivityTimeout;
1464            }
1465
1466            final int type = attrs.type;
1467            if (canBeSeen
1468                    && (type == TYPE_SYSTEM_DIALOG
1469                     || type == TYPE_SYSTEM_ERROR
1470                     || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
1471                mSyswin = true;
1472            }
1473
1474            if (canBeSeen) {
1475                // This function assumes that the contents of the default display are
1476                // processed first before secondary displays.
1477                final DisplayContent displayContent = w.getDisplayContent();
1478                if (displayContent != null && displayContent.isDefaultDisplay) {
1479                    // While a dream or keyguard is showing, obscure ordinary application
1480                    // content on secondary displays (by forcibly enabling mirroring unless
1481                    // there is other content we want to show) but still allow opaque
1482                    // keyguard dialogs to be shown.
1483                    if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
1484                        mObscureApplicationContentOnSecondaryDisplays = true;
1485                    }
1486                    mDisplayHasContent = true;
1487                } else if (displayContent != null &&
1488                        (!mObscureApplicationContentOnSecondaryDisplays
1489                        || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
1490                    // Allow full screen keyguard presentation dialogs to be seen.
1491                    mDisplayHasContent = true;
1492                }
1493                if (mPreferredRefreshRate == 0
1494                        && w.mAttrs.preferredRefreshRate != 0) {
1495                    mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
1496                }
1497                if (mPreferredModeId == 0
1498                        && w.mAttrs.preferredDisplayModeId != 0) {
1499                    mPreferredModeId = w.mAttrs.preferredDisplayModeId;
1500                }
1501                if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
1502                    mSustainedPerformanceModeCurrent = true;
1503                }
1504            }
1505        }
1506    }
1507
1508    private void updateAllDrawnLocked(DisplayContent displayContent) {
1509        // See if any windows have been drawn, so they (and others
1510        // associated with them) can now be shown.
1511        ArrayList<TaskStack> stacks = displayContent.getStacks();
1512        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
1513            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
1514            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
1515                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1516                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
1517                    final AppWindowToken wtoken = tokens.get(tokenNdx);
1518                    if (!wtoken.allDrawn) {
1519                        int numInteresting = wtoken.numInterestingWindows;
1520                        if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
1521                            if (DEBUG_VISIBILITY)
1522                                Slog.v(TAG, "allDrawn: " + wtoken
1523                                    + " interesting=" + numInteresting
1524                                    + " drawn=" + wtoken.numDrawnWindows);
1525                            wtoken.allDrawn = true;
1526                            // Force an additional layout pass where WindowStateAnimator#
1527                            // commitFinishDrawingLocked() will call performShowLocked().
1528                            displayContent.layoutNeeded = true;
1529                            mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN,
1530                                    wtoken.token).sendToTarget();
1531                        }
1532                    }
1533                }
1534            }
1535        }
1536    }
1537
1538    private static int toBrightnessOverride(float value) {
1539        return (int)(value * PowerManager.BRIGHTNESS_ON);
1540    }
1541
1542    private void processApplicationsAnimatingInPlace(int transit) {
1543        if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
1544            // Find the focused window
1545            final WindowState win = mService.findFocusedWindowLocked(
1546                    mService.getDefaultDisplayContentLocked());
1547            if (win != null) {
1548                final AppWindowToken wtoken = win.mAppToken;
1549                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
1550                if (DEBUG_APP_TRANSITIONS)
1551                    Slog.v(TAG, "Now animating app in place " + wtoken);
1552                appAnimator.clearThumbnail();
1553                appAnimator.setNullAnimation();
1554                mService.updateTokenInPlaceLocked(wtoken, transit);
1555                wtoken.updateReportedVisibilityLocked();
1556
1557                appAnimator.mAllAppWinAnimators.clear();
1558                final int N = wtoken.allAppWindows.size();
1559                for (int j = 0; j < N; j++) {
1560                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
1561                }
1562                mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
1563                mService.mAnimator.orAnimating(appAnimator.showAllWindowsLocked());
1564            }
1565        }
1566    }
1567
1568    private void createThumbnailAppAnimator(int transit, AppWindowToken appToken,
1569            int openingLayer, int closingLayer) {
1570        AppWindowAnimator openingAppAnimator = (appToken == null) ? null : appToken.mAppAnimator;
1571        if (openingAppAnimator == null || openingAppAnimator.animation == null) {
1572            return;
1573        }
1574        final int taskId = appToken.mTask.mTaskId;
1575        Bitmap thumbnailHeader = mService.mAppTransition.getAppTransitionThumbnailHeader(taskId);
1576        if (thumbnailHeader == null || thumbnailHeader.getConfig() == Bitmap.Config.ALPHA_8) {
1577            if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
1578            return;
1579        }
1580        // This thumbnail animation is very special, we need to have
1581        // an extra surface with the thumbnail included with the animation.
1582        Rect dirty = new Rect(0, 0, thumbnailHeader.getWidth(), thumbnailHeader.getHeight());
1583        try {
1584            // TODO(multi-display): support other displays
1585            final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
1586            final Display display = displayContent.getDisplay();
1587            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
1588
1589            // Create a new surface for the thumbnail
1590            SurfaceControl surfaceControl = new SurfaceControl(mService.mFxSession,
1591                    "thumbnail anim", dirty.width(), dirty.height(),
1592                    PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
1593            surfaceControl.setLayerStack(display.getLayerStack());
1594            if (SHOW_TRANSACTIONS) {
1595                Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
1596            }
1597
1598            // Draw the thumbnail onto the surface
1599            Surface drawSurface = new Surface();
1600            drawSurface.copyFrom(surfaceControl);
1601            Canvas c = drawSurface.lockCanvas(dirty);
1602            c.drawBitmap(thumbnailHeader, 0, 0, null);
1603            drawSurface.unlockCanvasAndPost(c);
1604            drawSurface.release();
1605
1606            // Get the thumbnail animation
1607            Animation anim;
1608            if (mService.mAppTransition.isNextThumbnailTransitionAspectScaled()) {
1609                // If this is a multi-window scenario, we use the windows frame as
1610                // destination of the thumbnail header animation. If this is a full screen
1611                // window scenario, we use the whole display as the target.
1612                WindowState win = appToken.findMainWindow();
1613                Rect appRect = win != null ? win.getContentFrameLw() :
1614                        new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
1615                Rect insets = win != null ? win.mContentInsets : null;
1616                // For the new aspect-scaled transition, we want it to always show
1617                // above the animating opening/closing window, and we want to
1618                // synchronize its thumbnail surface with the surface for the
1619                // open/close animation (only on the way down)
1620                anim = mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect,
1621                        insets, thumbnailHeader, taskId, mService.mCurConfiguration.uiMode,
1622                        mService.mCurConfiguration.orientation);
1623                openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer);
1624                openingAppAnimator.deferThumbnailDestruction =
1625                        !mService.mAppTransition.isNextThumbnailTransitionScaleUp();
1626            } else {
1627                anim = mService.mAppTransition.createThumbnailScaleAnimationLocked(
1628                        displayInfo.appWidth, displayInfo.appHeight, transit, thumbnailHeader);
1629            }
1630            anim.restrictDuration(MAX_ANIMATION_DURATION);
1631            anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked());
1632
1633            openingAppAnimator.thumbnail = surfaceControl;
1634            openingAppAnimator.thumbnailLayer = openingLayer;
1635            openingAppAnimator.thumbnailAnimation = anim;
1636            mService.mAppTransition.getNextAppTransitionStartRect(taskId, mTmpStartRect);
1637        } catch (Surface.OutOfResourcesException e) {
1638            Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w="
1639                    + dirty.width() + " h=" + dirty.height(), e);
1640            openingAppAnimator.clearThumbnail();
1641        }
1642    }
1643
1644    boolean copyAnimToLayoutParamsLocked() {
1645        boolean doRequest = false;
1646
1647        final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams;
1648        if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
1649            mUpdateRotation = true;
1650            doRequest = true;
1651        }
1652        if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) {
1653            mWallpaperMayChange = true;
1654            doRequest = true;
1655        }
1656        if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
1657            mWallpaperForceHidingChanged = true;
1658            doRequest = true;
1659        }
1660        if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
1661            mOrientationChangeComplete = false;
1662        } else {
1663            mOrientationChangeComplete = true;
1664            mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource;
1665            if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
1666                doRequest = true;
1667            }
1668        }
1669        if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) {
1670            mService.mTurnOnScreen = true;
1671        }
1672        if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) {
1673            mWallpaperActionPending = true;
1674        }
1675
1676        return doRequest;
1677    }
1678
1679    void requestTraversal() {
1680        if (!mTraversalScheduled) {
1681            mTraversalScheduled = true;
1682            mService.mH.sendEmptyMessage(DO_TRAVERSAL);
1683        }
1684    }
1685
1686    /**
1687     * Puts the {@param surface} into a pending list to be destroyed after the current transaction
1688     * has been committed.
1689     */
1690    void destroyAfterTransaction(SurfaceControl surface) {
1691        mPendingDestroyingSurfaces.add(surface);
1692    }
1693
1694    /**
1695     * Destroys any surfaces that have been put into the pending list with
1696     * {@link #destroyAfterTransaction}.
1697     */
1698    void destroyPendingSurfaces() {
1699        for (int i = mPendingDestroyingSurfaces.size() - 1; i >= 0; i--) {
1700            mPendingDestroyingSurfaces.get(i).destroy();
1701        }
1702        mPendingDestroyingSurfaces.clear();
1703    }
1704
1705    public void dump(PrintWriter pw, String prefix) {
1706        pw.print(prefix); pw.print("mTraversalScheduled="); pw.println(mTraversalScheduled);
1707        pw.print(prefix); pw.print("mHoldScreenWindow="); pw.println(mHoldScreenWindow);
1708        pw.print(prefix); pw.print("mObsuringWindow="); pw.println(mObsuringWindow);
1709    }
1710}
1711