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