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