DisplayContent.java revision aea6b74e17a0f7b105999adad50dd20eac17df35
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
19import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
20import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
21import static android.app.ActivityManager.StackId.HOME_STACK_ID;
22import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
23import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
24import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
25import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
26import static android.view.Display.DEFAULT_DISPLAY;
27import static android.view.Display.FLAG_PRIVATE;
28import static android.view.Surface.ROTATION_0;
29import static android.view.Surface.ROTATION_180;
30import static android.view.Surface.ROTATION_270;
31import static android.view.Surface.ROTATION_90;
32import static android.view.View.GONE;
33import static android.view.WindowManager.DOCKED_BOTTOM;
34import static android.view.WindowManager.DOCKED_INVALID;
35import static android.view.WindowManager.DOCKED_TOP;
36import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
37import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
38import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
39import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
40import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
41import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
42import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
43import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
44import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
45import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
46import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
47import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
48import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
49import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
50import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
51import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
52import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
53import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
54import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
55import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
56import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
57import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
58import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
59import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
60import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
61import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
62import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
63import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
64import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
76import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
77import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
78import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
79import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
80import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
81import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION;
82import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
83import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
84import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
85import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
86import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
87import static com.android.server.wm.WindowManagerService.SEAMLESS_ROTATION_TIMEOUT_DURATION;
88import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
89import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
90import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
91import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE;
92import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
93import static com.android.server.wm.WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION;
94import static com.android.server.wm.WindowManagerService.dipToPixel;
95import static com.android.server.wm.WindowManagerService.logSurface;
96import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
97import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
98import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
99import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
100
101import android.annotation.NonNull;
102import android.app.ActivityManager.StackId;
103import android.content.res.CompatibilityInfo;
104import android.content.res.Configuration;
105import android.graphics.Bitmap;
106import android.graphics.GraphicBuffer;
107import android.graphics.Matrix;
108import android.graphics.Rect;
109import android.graphics.RectF;
110import android.graphics.Region;
111import android.graphics.Region.Op;
112import android.hardware.display.DisplayManagerInternal;
113import android.os.Debug;
114import android.os.Handler;
115import android.os.IBinder;
116import android.os.RemoteException;
117import android.os.SystemClock;
118import android.util.DisplayMetrics;
119import android.util.MutableBoolean;
120import android.util.Slog;
121import android.view.Display;
122import android.view.DisplayInfo;
123import android.view.InputDevice;
124import android.view.Surface;
125import android.view.SurfaceControl;
126import android.view.WindowManagerPolicy;
127
128import com.android.internal.util.ToBooleanFunction;
129import com.android.internal.view.IInputMethodClient;
130
131import java.io.FileDescriptor;
132import java.io.PrintWriter;
133import java.util.ArrayList;
134import java.util.Comparator;
135import java.util.HashMap;
136import java.util.Iterator;
137import java.util.LinkedList;
138import java.util.List;
139import java.util.function.Consumer;
140import java.util.function.Predicate;
141
142/**
143 * Utility class for keeping track of the WindowStates and other pertinent contents of a
144 * particular Display.
145 *
146 * IMPORTANT: No method from this class should ever be used without holding
147 * WindowManagerService.mWindowMap.
148 */
149class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
150    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
151
152    /** Unique identifier of this stack. */
153    private final int mDisplayId;
154
155    /** The containers below are the only child containers the display can have. */
156    // Contains all window containers that are related to apps (Activities)
157    private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
158    // Contains all non-app window containers that should be displayed above the app containers
159    // (e.g. Status bar)
160    private final NonAppWindowContainers mAboveAppWindowsContainers =
161            new NonAppWindowContainers("mAboveAppWindowsContainers");
162    // Contains all non-app window containers that should be displayed below the app containers
163    // (e.g. Wallpaper).
164    private final NonAppWindowContainers mBelowAppWindowsContainers =
165            new NonAppWindowContainers("mBelowAppWindowsContainers");
166    // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
167    // on the IME target. We mainly have this container grouping so we can keep track of all the IME
168    // window containers together and move them in-sync if/when needed.
169    private final NonAppWindowContainers mImeWindowsContainers =
170            new NonAppWindowContainers("mImeWindowsContainers");
171
172    private WindowState mTmpWindow;
173    private WindowState mTmpWindow2;
174    private WindowAnimator mTmpWindowAnimator;
175    private boolean mTmpRecoveringMemory;
176    private boolean mUpdateImeTarget;
177    private boolean mTmpInitial;
178    private int mMaxUiWidth;
179
180    // Mapping from a token IBinder to a WindowToken object on this display.
181    private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
182
183    int mInitialDisplayWidth = 0;
184    int mInitialDisplayHeight = 0;
185    int mInitialDisplayDensity = 0;
186    int mBaseDisplayWidth = 0;
187    int mBaseDisplayHeight = 0;
188    int mBaseDisplayDensity = 0;
189    boolean mDisplayScalingDisabled;
190    private final DisplayInfo mDisplayInfo = new DisplayInfo();
191    private final Display mDisplay;
192    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
193    /**
194     * For default display it contains real metrics, empty for others.
195     * @see WindowManagerService#createWatermarkInTransaction()
196     */
197    final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
198    /** @see #computeCompatSmallestWidth(boolean, int, int, int, int) */
199    private final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
200    /**
201     * Compat metrics computed based on {@link #mDisplayMetrics}.
202     * @see #updateDisplayAndOrientation(int)
203     */
204    private final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
205
206    /** The desired scaling factor for compatible apps. */
207    float mCompatibleScreenScale;
208
209    /**
210     * Current rotation of the display.
211     * Constants as per {@link android.view.Surface.Rotation}.
212     *
213     * @see #updateRotationUnchecked(boolean)
214     */
215    private int mRotation = 0;
216    /**
217     * Last applied orientation of the display.
218     * Constants as per {@link android.content.pm.ActivityInfo.ScreenOrientation}.
219     *
220     * @see WindowManagerService#updateOrientationFromAppTokensLocked(boolean, int)
221     */
222    private int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
223    /**
224     * Flag indicating that the application is receiving an orientation that has different metrics
225     * than it expected. E.g. Portrait instead of Landscape.
226     *
227     * @see #updateRotationUnchecked(boolean)
228     */
229    private boolean mAltOrientation = false;
230    /**
231     * Orientation forced by some window. If there is no visible window that specifies orientation
232     * it is set to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}.
233     *
234     * @see NonAppWindowContainers#getOrientation()
235     */
236    private int mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
237    /**
238     * Last orientation forced by the keyguard. It is applied when keyguard is shown and is not
239     * occluded.
240     *
241     * @see NonAppWindowContainers#getOrientation()
242     */
243    private int mLastKeyguardForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
244
245    private Rect mBaseDisplayRect = new Rect();
246    private Rect mContentRect = new Rect();
247
248    // Accessed directly by all users.
249    private boolean mLayoutNeeded;
250    int pendingLayoutChanges;
251    // TODO(multi-display): remove some of the usages.
252    boolean isDefaultDisplay;
253
254    /** Window tokens that are in the process of exiting, but still on screen for animations. */
255    final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
256
257    /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
258     * (except a future lockscreen TaskStack) moves to the top. */
259    private TaskStack mHomeStack = null;
260
261    /** Detect user tapping outside of current focused task bounds .*/
262    TaskTapPointerEventListener mTapDetector;
263
264    /** Detect user tapping outside of current focused stack bounds .*/
265    private Region mTouchExcludeRegion = new Region();
266
267    /** Save allocating when calculating rects */
268    private final Rect mTmpRect = new Rect();
269    private final Rect mTmpRect2 = new Rect();
270    private final RectF mTmpRectF = new RectF();
271    private final Matrix mTmpMatrix = new Matrix();
272    private final Region mTmpRegion = new Region();
273
274    WindowManagerService mService;
275
276    /** Remove this display when animation on it has completed. */
277    private boolean mDeferredRemoval;
278
279    final DockedStackDividerController mDividerControllerLocked;
280    final PinnedStackController mPinnedStackControllerLocked;
281
282    DimLayerController mDimLayerController;
283
284    final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
285
286    private boolean mHaveBootMsg = false;
287    private boolean mHaveApp = false;
288    private boolean mHaveWallpaper = false;
289    private boolean mHaveKeyguard = true;
290
291    private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
292
293    private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
294            new TaskForResizePointSearchResult();
295    private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState =
296            new ApplySurfaceChangesTransactionState();
297    private final ScreenshotApplicationState mScreenshotApplicationState =
298            new ScreenshotApplicationState();
299
300    // True if this display is in the process of being removed. Used to determine if the removal of
301    // the display's direct children should be allowed.
302    private boolean mRemovingDisplay = false;
303
304    private final WindowLayersController mLayersController;
305    WallpaperController mWallpaperController;
306    int mInputMethodAnimLayerAdjustment;
307
308    private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
309        WindowStateAnimator winAnimator = w.mWinAnimator;
310        if (winAnimator.hasSurface()) {
311            final boolean wasAnimating = winAnimator.mWasAnimating;
312            final boolean nowAnimating = winAnimator.stepAnimationLocked(
313                    mTmpWindowAnimator.mCurrentTime);
314            winAnimator.mWasAnimating = nowAnimating;
315            mTmpWindowAnimator.orAnimating(nowAnimating);
316
317            if (DEBUG_WALLPAPER) Slog.v(TAG,
318                    w + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
319
320            if (wasAnimating && !winAnimator.mAnimating
321                    && mWallpaperController.isWallpaperTarget(w)) {
322                mTmpWindowAnimator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
323                pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
324                if (DEBUG_LAYOUT_REPEATS) {
325                    mService.mWindowPlacerLocked.debugLayoutRepeats(
326                            "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
327                }
328            }
329        }
330
331        final AppWindowToken atoken = w.mAppToken;
332        if (winAnimator.mDrawState == READY_TO_SHOW) {
333            if (atoken == null || atoken.allDrawn) {
334                if (w.performShowLocked()) {
335                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
336                    if (DEBUG_LAYOUT_REPEATS) {
337                        mService.mWindowPlacerLocked.debugLayoutRepeats(
338                                "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
339                    }
340                }
341            }
342        }
343        final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
344        if (appAnimator != null && appAnimator.thumbnail != null) {
345            if (appAnimator.thumbnailTransactionSeq
346                    != mTmpWindowAnimator.mAnimTransactionSequence) {
347                appAnimator.thumbnailTransactionSeq =
348                        mTmpWindowAnimator.mAnimTransactionSequence;
349                appAnimator.thumbnailLayer = 0;
350            }
351            if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
352                appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
353            }
354        }
355    };
356
357    private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> {
358        final WindowStateAnimator winAnimator = w.mWinAnimator;
359        if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
360            return;
361        }
362
363        final int flags = w.mAttrs.flags;
364
365        // If this window is animating, make a note that we have an animating window and take
366        // care of a request to run a detached wallpaper animation.
367        if (winAnimator.mAnimating) {
368            if (winAnimator.mAnimation != null) {
369                if ((flags & FLAG_SHOW_WALLPAPER) != 0
370                        && winAnimator.mAnimation.getDetachWallpaper()) {
371                    mTmpWindow = w;
372                }
373                final int color = winAnimator.mAnimation.getBackgroundColor();
374                if (color != 0) {
375                    final TaskStack stack = w.getStack();
376                    if (stack != null) {
377                        stack.setAnimationBackground(winAnimator, color);
378                    }
379                }
380            }
381            mTmpWindowAnimator.setAnimating(true);
382        }
383
384        // If this window's app token is running a detached wallpaper animation, make a note so
385        // we can ensure the wallpaper is displayed behind it.
386        final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
387        if (appAnimator != null && appAnimator.animation != null
388                && appAnimator.animating) {
389            if ((flags & FLAG_SHOW_WALLPAPER) != 0
390                    && appAnimator.animation.getDetachWallpaper()) {
391                mTmpWindow = w;
392            }
393
394            final int color = appAnimator.animation.getBackgroundColor();
395            if (color != 0) {
396                final TaskStack stack = w.getStack();
397                if (stack != null) {
398                    stack.setAnimationBackground(winAnimator, color);
399                }
400            }
401        }
402    };
403
404    private final Consumer<WindowState> mScheduleToastTimeout = w -> {
405        final int lostFocusUid = mTmpWindow.mOwnerUid;
406        final Handler handler = mService.mH;
407        if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) {
408            if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) {
409                handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w),
410                        w.mAttrs.hideTimeoutMilliseconds);
411            }
412        }
413    };
414
415    private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
416        final AppWindowToken focusedApp = mService.mFocusedApp;
417        if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w
418                + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys());
419
420        if (!w.canReceiveKeys()) {
421            return false;
422        }
423
424        final AppWindowToken wtoken = w.mAppToken;
425
426        // If this window's application has been removed, just skip it.
427        if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
428            if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
429                    + (wtoken.removed ? "removed" : "sendingToBottom"));
430            return false;
431        }
432
433        if (focusedApp == null) {
434            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
435                    + " using new focus @ " + w);
436            mTmpWindow = w;
437            return true;
438        }
439
440        if (!focusedApp.windowsAreFocusable()) {
441            // Current focused app windows aren't focusable...
442            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
443                    + " focusable using new focus @ " + w);
444            mTmpWindow = w;
445            return true;
446        }
447
448        // Descend through all of the app tokens and find the first that either matches
449        // win.mAppToken (return win) or mFocusedApp (return null).
450        if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
451            if (focusedApp.compareTo(wtoken) > 0) {
452                // App stack below focused app stack. No focus for you!!!
453                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
454                        "findFocusedWindow: Reached focused app=" + focusedApp);
455                mTmpWindow = null;
456                return true;
457            }
458        }
459
460        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w);
461        mTmpWindow = w;
462        return true;
463    };
464
465    private final Consumer<WindowState> mPrepareWindowSurfaces =
466            w -> w.mWinAnimator.prepareSurfaceLocked(true);
467
468    private final Consumer<WindowState> mPerformLayout = w -> {
469        // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
470        // wasting time and funky changes while a window is animating away.
471        final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w))
472                || w.isGoneForLayoutLw();
473
474        if (DEBUG_LAYOUT && !w.mLayoutAttached) {
475            Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
476                    + " mLayoutAttached=" + w.mLayoutAttached
477                    + " screen changed=" + w.isConfigChanged());
478            final AppWindowToken atoken = w.mAppToken;
479            if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
480                    + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
481                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
482                    + " parentHidden=" + w.isParentWindowHidden());
483            else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
484                    + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
485                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
486                    + " parentHidden=" + w.isParentWindowHidden());
487        }
488
489        // If this view is GONE, then skip it -- keep the current frame, and let the caller know
490        // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
491        // since that means "perform layout as normal, just don't display").
492        if (!gone || !w.mHaveFrame || w.mLayoutNeeded
493                || ((w.isConfigChanged() || w.setReportResizeHints())
494                && !w.isGoneForLayoutLw() &&
495                ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
496                        (w.mHasSurface && w.mAppToken != null &&
497                                w.mAppToken.layoutConfigChanges)))) {
498            if (!w.mLayoutAttached) {
499                if (mTmpInitial) {
500                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
501                    w.mContentChanged = false;
502                }
503                if (w.mAttrs.type == TYPE_DREAM) {
504                    // Don't layout windows behind a dream, so that if it does stuff like hide
505                    // the status bar we won't get a bad transition when it goes away.
506                    mTmpWindow = w;
507                }
508                w.mLayoutNeeded = false;
509                w.prelayout();
510                mService.mPolicy.layoutWindowLw(w, null);
511                w.mLayoutSeq = mService.mLayoutSeq;
512
513                // Window frames may have changed. Update dim layer with the new bounds.
514                final Task task = w.getTask();
515                if (task != null) {
516                    mDimLayerController.updateDimLayer(task);
517                }
518
519                if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.mFrame
520                        + " mContainingFrame=" + w.mContainingFrame
521                        + " mDisplayFrame=" + w.mDisplayFrame);
522            }
523        }
524    };
525
526    private final Consumer<WindowState> mPerformLayoutAttached = w -> {
527        if (w.mLayoutAttached) {
528            if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
529                    + " mViewVisibility=" + w.mViewVisibility
530                    + " mRelayoutCalled=" + w.mRelayoutCalled);
531            // If this view is GONE, then skip it -- keep the current frame, and let the caller
532            // know so they can ignore it if they want.  (We do the normal layout for INVISIBLE
533            // windows, since that means "perform layout as normal, just don't display").
534            if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) {
535                return;
536            }
537            if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
538                    || w.mLayoutNeeded) {
539                if (mTmpInitial) {
540                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
541                    w.mContentChanged = false;
542                }
543                w.mLayoutNeeded = false;
544                w.prelayout();
545                mService.mPolicy.layoutWindowLw(w, w.getParentWindow());
546                w.mLayoutSeq = mService.mLayoutSeq;
547                if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame
548                        + " mContainingFrame=" + w.mContainingFrame
549                        + " mDisplayFrame=" + w.mDisplayFrame);
550            }
551        } else if (w.mAttrs.type == TYPE_DREAM) {
552            // Don't layout windows behind a dream, so that if it does stuff like hide the
553            // status bar we won't get a bad transition when it goes away.
554            mTmpWindow = mTmpWindow2;
555        }
556    };
557
558    private final Predicate<WindowState> mComputeImeTargetPredicate = w -> {
559        if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w
560                + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
561        return w.canBeImeTarget();
562    };
563
564    private final Consumer<WindowState> mApplyPostLayoutPolicy =
565            w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
566                    mService.mInputMethodTarget);
567
568    private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
569        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
570        final boolean obscuredChanged = w.mObscured !=
571                mTmpApplySurfaceChangesTransactionState.obscured;
572        final RootWindowContainer root = mService.mRoot;
573        // Only used if default window
574        final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
575
576        // Update effect.
577        w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
578        if (!mTmpApplySurfaceChangesTransactionState.obscured) {
579            final boolean isDisplayed = w.isDisplayedLw();
580
581            if (isDisplayed && w.isObscuringDisplay()) {
582                // This window completely covers everything behind it, so we want to leave all
583                // of them as undimmed (for performance reasons).
584                root.mObscuringWindow = w;
585                mTmpApplySurfaceChangesTransactionState.obscured = true;
586            }
587
588            mTmpApplySurfaceChangesTransactionState.displayHasContent |=
589                    root.handleNotObscuredLocked(w,
590                            mTmpApplySurfaceChangesTransactionState.obscured,
591                            mTmpApplySurfaceChangesTransactionState.syswin);
592
593            if (w.mHasSurface && isDisplayed) {
594                final int type = w.mAttrs.type;
595                if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
596                        || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
597                    mTmpApplySurfaceChangesTransactionState.syswin = true;
598                }
599                if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
600                        && w.mAttrs.preferredRefreshRate != 0) {
601                    mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
602                            = w.mAttrs.preferredRefreshRate;
603                }
604                if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
605                        && w.mAttrs.preferredDisplayModeId != 0) {
606                    mTmpApplySurfaceChangesTransactionState.preferredModeId
607                            = w.mAttrs.preferredDisplayModeId;
608                }
609            }
610        }
611
612        w.applyDimLayerIfNeeded();
613
614        if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
615                && mWallpaperController.isWallpaperTarget(w)) {
616            // This is the wallpaper target and its obscured state changed... make sure the
617            // current wallpaper's visibility has been updated accordingly.
618            mWallpaperController.updateWallpaperVisibility();
619        }
620
621        w.handleWindowMovedIfNeeded();
622
623        final WindowStateAnimator winAnimator = w.mWinAnimator;
624
625        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
626        w.mContentChanged = false;
627
628        // Moved from updateWindowsAndWallpaperLocked().
629        if (w.mHasSurface) {
630            // Take care of the window being ready to display.
631            final boolean committed = winAnimator.commitFinishDrawingLocked();
632            if (isDefaultDisplay && committed) {
633                if (w.mAttrs.type == TYPE_DREAM) {
634                    // HACK: When a dream is shown, it may at that point hide the lock screen.
635                    // So we need to redo the layout to let the phone window manager make this
636                    // happen.
637                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
638                    if (DEBUG_LAYOUT_REPEATS) {
639                        surfacePlacer.debugLayoutRepeats(
640                                "dream and commitFinishDrawingLocked true",
641                                pendingLayoutChanges);
642                    }
643                }
644                if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
645                    if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
646                            "First draw done in potential wallpaper target " + w);
647                    root.mWallpaperMayChange = true;
648                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
649                    if (DEBUG_LAYOUT_REPEATS) {
650                        surfacePlacer.debugLayoutRepeats(
651                                "wallpaper and commitFinishDrawingLocked true",
652                                pendingLayoutChanges);
653                    }
654                }
655            }
656            if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
657                // Updates the shown frame before we set up the surface. This is needed
658                // because the resizing could change the top-left position (in addition to
659                // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
660                // position the surface.
661                //
662                // If an animation is being started, we can't call this method because the
663                // animation hasn't processed its initial transformation yet, but in general
664                // we do want to update the position if the window is animating.
665                winAnimator.computeShownFrameLocked();
666            }
667            winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */);
668        }
669
670        final AppWindowToken atoken = w.mAppToken;
671        if (atoken != null) {
672            final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
673            if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
674                mTmpUpdateAllDrawn.add(atoken);
675            }
676        }
677
678        if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
679                && w.isDisplayedLw()) {
680            mTmpApplySurfaceChangesTransactionState.focusDisplayed = true;
681        }
682
683        w.updateResizingWindowIfNeeded();
684    };
685
686    /**
687     * Create new {@link DisplayContent} instance, add itself to the root window container and
688     * initialize direct children.
689     * @param display May not be null.
690     * @param service You know.
691     * @param layersController window layer controller used to assign layer to the windows on this
692     *                         display.
693     * @param wallpaperController wallpaper windows controller used to adjust the positioning of the
694     *                            wallpaper windows in the window list.
695     */
696    DisplayContent(Display display, WindowManagerService service,
697            WindowLayersController layersController, WallpaperController wallpaperController) {
698
699        if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) {
700            throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
701                    + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId())
702                    + " new=" + display);
703        }
704
705        mDisplay = display;
706        mDisplayId = display.getDisplayId();
707        mLayersController = layersController;
708        mWallpaperController = wallpaperController;
709        display.getDisplayInfo(mDisplayInfo);
710        display.getMetrics(mDisplayMetrics);
711        isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
712        mService = service;
713        initializeDisplayBaseInfo();
714        mDividerControllerLocked = new DockedStackDividerController(service, this);
715        mPinnedStackControllerLocked = new PinnedStackController(service, this);
716        mDimLayerController = new DimLayerController(this);
717
718        // These are the only direct children we should ever have and they are permanent.
719        super.addChild(mBelowAppWindowsContainers, null);
720        super.addChild(mTaskStackContainers, null);
721        super.addChild(mAboveAppWindowsContainers, null);
722        super.addChild(mImeWindowsContainers, null);
723
724        // Add itself as a child to the root container.
725        mService.mRoot.addChild(this, null);
726    }
727
728    int getDisplayId() {
729        return mDisplayId;
730    }
731
732    WindowToken getWindowToken(IBinder binder) {
733        return mTokenMap.get(binder);
734    }
735
736    AppWindowToken getAppWindowToken(IBinder binder) {
737        final WindowToken token = getWindowToken(binder);
738        if (token == null) {
739            return null;
740        }
741        return token.asAppWindowToken();
742    }
743
744    void addWindowToken(IBinder binder, WindowToken token) {
745        final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
746        if (dc != null) {
747            // We currently don't support adding a window token to the display if the display
748            // already has the binder mapped to another token. If there is a use case for supporting
749            // this moving forward we will either need to merge the WindowTokens some how or have
750            // the binder map to a list of window tokens.
751            throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this
752                    + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
753        }
754        mTokenMap.put(binder, token);
755
756        if (token.asAppWindowToken() == null) {
757            // Add non-app token to container hierarchy on the display. App tokens are added through
758            // the parent container managing them (e.g. Tasks).
759            switch (token.windowType) {
760                case TYPE_WALLPAPER:
761                    mBelowAppWindowsContainers.addChild(token);
762                    break;
763                case TYPE_INPUT_METHOD:
764                case TYPE_INPUT_METHOD_DIALOG:
765                    mImeWindowsContainers.addChild(token);
766                    break;
767                default:
768                    mAboveAppWindowsContainers.addChild(token);
769                    break;
770            }
771        }
772    }
773
774    WindowToken removeWindowToken(IBinder binder) {
775        final WindowToken token = mTokenMap.remove(binder);
776        if (token != null && token.asAppWindowToken() == null) {
777            token.setExiting();
778        }
779        return token;
780    }
781
782    /** Changes the display the input window token is housed on to this one. */
783    void reParentWindowToken(WindowToken token) {
784        final DisplayContent prevDc = token.getDisplayContent();
785        if (prevDc == this) {
786            return;
787        }
788        if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null
789                && token.asAppWindowToken() == null) {
790            // Removed the token from the map, but made sure it's not an app token before removing
791            // from parent.
792            token.getParent().removeChild(token);
793        }
794
795        addWindowToken(token.token, token);
796    }
797
798    void removeAppToken(IBinder binder) {
799        final WindowToken token = removeWindowToken(binder);
800        if (token == null) {
801            Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
802            return;
803        }
804
805        final AppWindowToken appToken = token.asAppWindowToken();
806
807        if (appToken == null) {
808            Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
809            return;
810        }
811
812        appToken.onRemovedFromDisplay();
813    }
814
815    Display getDisplay() {
816        return mDisplay;
817    }
818
819    DisplayInfo getDisplayInfo() {
820        return mDisplayInfo;
821    }
822
823    DisplayMetrics getDisplayMetrics() {
824        return mDisplayMetrics;
825    }
826
827    int getRotation() {
828        return mRotation;
829    }
830
831    void setRotation(int newRotation) {
832        mRotation = newRotation;
833    }
834
835    int getLastOrientation() {
836        return mLastOrientation;
837    }
838
839    void setLastOrientation(int orientation) {
840        mLastOrientation = orientation;
841    }
842
843    boolean getAltOrientation() {
844        return mAltOrientation;
845    }
846
847    void setAltOrientation(boolean altOrientation) {
848        mAltOrientation = altOrientation;
849    }
850
851    int getLastWindowForcedOrientation() {
852        return mLastWindowForcedOrientation;
853    }
854
855    /**
856     * Update rotation of the display.
857     *
858     * Returns true if the rotation has been changed.  In this case YOU MUST CALL
859     * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
860     */
861    boolean updateRotationUnchecked(boolean inTransaction) {
862        if (mService.mDeferredRotationPauseCount > 0) {
863            // Rotation updates have been paused temporarily.  Defer the update until
864            // updates have been resumed.
865            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
866            return false;
867        }
868
869        ScreenRotationAnimation screenRotationAnimation =
870                mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
871        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
872            // Rotation updates cannot be performed while the previous rotation change
873            // animation is still in progress.  Skip this update.  We will try updating
874            // again after the animation is finished and the display is unfrozen.
875            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
876            return false;
877        }
878        if (mService.mDisplayFrozen) {
879            // Even if the screen rotation animation has finished (e.g. isAnimating
880            // returns false), there is still some time where we haven't yet unfrozen
881            // the display. We also need to abort rotation here.
882            if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
883                    "Deferring rotation, still finishing previous rotation");
884            return false;
885        }
886
887        if (!mService.mDisplayEnabled) {
888            // No point choosing a rotation if the display is not enabled.
889            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
890            return false;
891        }
892
893        final int oldRotation = mRotation;
894        final int lastOrientation = mLastOrientation;
895        final boolean oldAltOrientation = mAltOrientation;
896        int rotation = mService.mPolicy.rotationForOrientationLw(lastOrientation, oldRotation);
897        final boolean rotateSeamlessly = mService.mPolicy.shouldRotateSeamlessly(oldRotation,
898                rotation);
899
900        if (rotateSeamlessly) {
901            final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated);
902            if (seamlessRotated != null) {
903                // We can't rotate (seamlessly or not) while waiting for the last seamless rotation
904                // to complete (that is, waiting for windows to redraw). It's tempting to check
905                // w.mSeamlessRotationCount but that could be incorrect in the case of
906                // window-removal.
907                return false;
908            }
909        }
910
911        // TODO: Implement forced rotation changes.
912        //       Set mAltOrientation to indicate that the application is receiving
913        //       an orientation that has different metrics than it expected.
914        //       eg. Portrait instead of Landscape.
915
916        final boolean altOrientation = !mService.mPolicy.rotationHasCompatibleMetricsLw(
917                lastOrientation, rotation);
918
919        if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Selected orientation " + lastOrientation
920                + ", got rotation " + rotation + " which has "
921                + (altOrientation ? "incompatible" : "compatible") + " metrics");
922
923        if (oldRotation == rotation && oldAltOrientation == altOrientation) {
924            // No change.
925            return false;
926        }
927
928        if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Rotation changed to " + rotation
929                + (altOrientation ? " (alt)" : "") + " from " + oldRotation
930                + (oldAltOrientation ? " (alt)" : "") + ", lastOrientation=" + lastOrientation);
931
932        if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) {
933            mService.mWaitingForConfig = true;
934        }
935
936        mRotation = rotation;
937        mAltOrientation = altOrientation;
938        if (isDefaultDisplay) {
939            mService.mPolicy.setRotationLw(rotation);
940        }
941
942        mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
943        mService.mH.removeMessages(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT);
944        mService.mH.sendEmptyMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
945                WINDOW_FREEZE_TIMEOUT_DURATION);
946
947        setLayoutNeeded();
948        final int[] anim = new int[2];
949        if (isDimming()) {
950            anim[0] = anim[1] = 0;
951        } else {
952            mService.mPolicy.selectRotationAnimationLw(anim);
953        }
954
955        if (!rotateSeamlessly) {
956            mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
957            // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
958            screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
959                    mDisplayId);
960        } else {
961            // The screen rotation animation uses a screenshot to freeze the screen
962            // while windows resize underneath.
963            // When we are rotating seamlessly, we allow the elements to transition
964            // to their rotated state independently and without a freeze required.
965            screenRotationAnimation = null;
966
967            // We have to reset this in case a window was removed before it
968            // finished seamless rotation.
969            mService.mSeamlessRotationCount = 0;
970        }
971
972        // We need to update our screen size information to match the new rotation. If the rotation
973        // has actually changed then this method will return true and, according to the comment at
974        // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
975        // By updating the Display info here it will be available to
976        // #computeScreenConfiguration() later.
977        updateDisplayAndOrientation(getConfiguration().uiMode);
978
979        if (!inTransaction) {
980            if (SHOW_TRANSACTIONS) {
981                Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked");
982            }
983            mService.openSurfaceTransaction();
984        }
985        try {
986            // NOTE: We disable the rotation in the emulator because
987            //       it doesn't support hardware OpenGL emulation yet.
988            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
989                    && screenRotationAnimation.hasScreenshot()) {
990                if (screenRotationAnimation.setRotationInTransaction(
991                        rotation, mService.mFxSession,
992                        MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(),
993                        mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
994                    mService.scheduleAnimationLocked();
995                }
996            }
997
998            if (rotateSeamlessly) {
999                forAllWindows(w -> {
1000                    w.mWinAnimator.seamlesslyRotateWindow(oldRotation, rotation);
1001                }, true /* traverseTopToBottom */);
1002            }
1003
1004            mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
1005        } finally {
1006            if (!inTransaction) {
1007                mService.closeSurfaceTransaction();
1008                if (SHOW_LIGHT_TRANSACTIONS) {
1009                    Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked");
1010                }
1011            }
1012        }
1013
1014        forAllWindows(w -> {
1015            // Discard surface after orientation change, these can't be reused.
1016            if (w.mAppToken != null) {
1017                w.mAppToken.destroySavedSurfaces();
1018            }
1019            if (w.mHasSurface && !rotateSeamlessly) {
1020                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
1021                w.mOrientationChanging = true;
1022                mService.mRoot.mOrientationChangeComplete = false;
1023                w.mLastFreezeDuration = 0;
1024            }
1025            w.mReportOrientationChanged = true;
1026        }, true /* traverseTopToBottom */);
1027
1028        if (rotateSeamlessly) {
1029            mService.mH.removeMessages(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT);
1030            mService.mH.sendEmptyMessageDelayed(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT,
1031                    SEAMLESS_ROTATION_TIMEOUT_DURATION);
1032        }
1033
1034        for (int i = mService.mRotationWatchers.size() - 1; i >= 0; i--) {
1035            final WindowManagerService.RotationWatcher rotationWatcher
1036                    = mService.mRotationWatchers.get(i);
1037            if (rotationWatcher.mDisplayId == mDisplayId) {
1038                try {
1039                    rotationWatcher.mWatcher.onRotationChanged(rotation);
1040                } catch (RemoteException e) {
1041                    // Ignore
1042                }
1043            }
1044        }
1045
1046        // TODO (multi-display): Magnification is supported only for the default display.
1047        // Announce rotation only if we will not animate as we already have the
1048        // windows in final state. Otherwise, we make this call at the rotation end.
1049        if (screenRotationAnimation == null && mService.mAccessibilityController != null
1050                && isDefaultDisplay) {
1051            mService.mAccessibilityController.onRotationChangedLocked(this);
1052        }
1053
1054        return true;
1055    }
1056
1057    /**
1058     * Update {@link #mDisplayInfo} and other internal variables when display is rotated or config
1059     * changed.
1060     * Do not call if {@link WindowManagerService#mDisplayReady} == false.
1061     */
1062    private DisplayInfo updateDisplayAndOrientation(int uiMode) {
1063        // Use the effective "visual" dimensions based on current rotation
1064        final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270);
1065        final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
1066        final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
1067        int dw = realdw;
1068        int dh = realdh;
1069
1070        if (mAltOrientation) {
1071            if (realdw > realdh) {
1072                // Turn landscape into portrait.
1073                int maxw = (int)(realdh/1.3f);
1074                if (maxw < realdw) {
1075                    dw = maxw;
1076                }
1077            } else {
1078                // Turn portrait into landscape.
1079                int maxh = (int)(realdw/1.3f);
1080                if (maxh < realdh) {
1081                    dh = maxh;
1082                }
1083            }
1084        }
1085
1086        // Update application display metrics.
1087        final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode,
1088                mDisplayId);
1089        final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode,
1090                mDisplayId);
1091        mDisplayInfo.rotation = mRotation;
1092        mDisplayInfo.logicalWidth = dw;
1093        mDisplayInfo.logicalHeight = dh;
1094        mDisplayInfo.logicalDensityDpi = mBaseDisplayDensity;
1095        mDisplayInfo.appWidth = appWidth;
1096        mDisplayInfo.appHeight = appHeight;
1097        if (isDefaultDisplay) {
1098            mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics,
1099                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
1100        }
1101        mDisplayInfo.getAppMetrics(mDisplayMetrics);
1102        if (mDisplayScalingDisabled) {
1103            mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED;
1104        } else {
1105            mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
1106        }
1107
1108        mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
1109                mDisplayInfo);
1110
1111        mBaseDisplayRect.set(0, 0, dw, dh);
1112
1113        if (isDefaultDisplay) {
1114            mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
1115                    mCompatDisplayMetrics);
1116        }
1117        return mDisplayInfo;
1118    }
1119
1120    /**
1121     * Compute display configuration based on display properties and policy settings.
1122     * Do not call if mDisplayReady == false.
1123     */
1124    void computeScreenConfiguration(Configuration config) {
1125        final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode);
1126
1127        final int dw = displayInfo.logicalWidth;
1128        final int dh = displayInfo.logicalHeight;
1129        config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
1130                Configuration.ORIENTATION_LANDSCAPE;
1131        config.screenWidthDp =
1132                (int)(mService.mPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation,
1133                        config.uiMode, mDisplayId) / mDisplayMetrics.density);
1134        config.screenHeightDp =
1135                (int)(mService.mPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation,
1136                        config.uiMode, mDisplayId) / mDisplayMetrics.density);
1137        final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90
1138                || displayInfo.rotation == Surface.ROTATION_270);
1139
1140        computeSizeRangesAndScreenLayout(displayInfo, mDisplayId, rotated, config.uiMode, dw, dh,
1141                mDisplayMetrics.density, config);
1142
1143        config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
1144                | ((displayInfo.flags & Display.FLAG_ROUND) != 0
1145                ? Configuration.SCREENLAYOUT_ROUND_YES
1146                : Configuration.SCREENLAYOUT_ROUND_NO);
1147
1148        config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
1149        config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
1150        config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, dw,
1151                dh, mDisplayId);
1152        config.densityDpi = displayInfo.logicalDensityDpi;
1153
1154        config.colorMode =
1155                (displayInfo.isHdr()
1156                        ? Configuration.COLOR_MODE_HDR_YES
1157                        : Configuration.COLOR_MODE_HDR_NO)
1158                        | (displayInfo.isWideColorGamut()
1159                        ? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES
1160                        : Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO);
1161
1162        // Update the configuration based on available input devices, lid switch,
1163        // and platform configuration.
1164        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
1165        config.keyboard = Configuration.KEYBOARD_NOKEYS;
1166        config.navigation = Configuration.NAVIGATION_NONAV;
1167
1168        int keyboardPresence = 0;
1169        int navigationPresence = 0;
1170        final InputDevice[] devices = mService.mInputManager.getInputDevices();
1171        final int len = devices != null ? devices.length : 0;
1172        for (int i = 0; i < len; i++) {
1173            InputDevice device = devices[i];
1174            if (!device.isVirtual()) {
1175                final int sources = device.getSources();
1176                final int presenceFlag = device.isExternal() ?
1177                        WindowManagerPolicy.PRESENCE_EXTERNAL :
1178                        WindowManagerPolicy.PRESENCE_INTERNAL;
1179
1180                // TODO(multi-display): Configure on per-display basis.
1181                if (mService.mIsTouchDevice) {
1182                    if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
1183                            InputDevice.SOURCE_TOUCHSCREEN) {
1184                        config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
1185                    }
1186                } else {
1187                    config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
1188                }
1189
1190                if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
1191                    config.navigation = Configuration.NAVIGATION_TRACKBALL;
1192                    navigationPresence |= presenceFlag;
1193                } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
1194                        && config.navigation == Configuration.NAVIGATION_NONAV) {
1195                    config.navigation = Configuration.NAVIGATION_DPAD;
1196                    navigationPresence |= presenceFlag;
1197                }
1198
1199                if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
1200                    config.keyboard = Configuration.KEYBOARD_QWERTY;
1201                    keyboardPresence |= presenceFlag;
1202                }
1203            }
1204        }
1205
1206        if (config.navigation == Configuration.NAVIGATION_NONAV && mService.mHasPermanentDpad) {
1207            config.navigation = Configuration.NAVIGATION_DPAD;
1208            navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
1209        }
1210
1211        // Determine whether a hard keyboard is available and enabled.
1212        // TODO(multi-display): Should the hardware keyboard be tied to a display or to a device?
1213        boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
1214        if (hardKeyboardAvailable != mService.mHardKeyboardAvailable) {
1215            mService.mHardKeyboardAvailable = hardKeyboardAvailable;
1216            mService.mH.removeMessages(WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
1217            mService.mH.sendEmptyMessage(WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
1218        }
1219
1220        // Let the policy update hidden states.
1221        config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
1222        config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
1223        config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
1224        mService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
1225    }
1226
1227    private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh,
1228            int displayId) {
1229        mTmpDisplayMetrics.setTo(mDisplayMetrics);
1230        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
1231        final int unrotDw, unrotDh;
1232        if (rotated) {
1233            unrotDw = dh;
1234            unrotDh = dw;
1235        } else {
1236            unrotDw = dw;
1237            unrotDh = dh;
1238        }
1239        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh,
1240                displayId);
1241        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw,
1242                displayId);
1243        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh,
1244                displayId);
1245        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw,
1246                displayId);
1247        return sw;
1248    }
1249
1250    private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
1251            DisplayMetrics dm, int dw, int dh, int displayId) {
1252        dm.noncompatWidthPixels = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
1253                displayId);
1254        dm.noncompatHeightPixels = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
1255                uiMode, displayId);
1256        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
1257        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
1258        if (curSize == 0 || size < curSize) {
1259            curSize = size;
1260        }
1261        return curSize;
1262    }
1263
1264    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, int displayId,
1265            boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig) {
1266
1267        // We need to determine the smallest width that will occur under normal
1268        // operation.  To this, start with the base screen size and compute the
1269        // width under the different possible rotations.  We need to un-rotate
1270        // the current screen dimensions before doing this.
1271        int unrotDw, unrotDh;
1272        if (rotated) {
1273            unrotDw = dh;
1274            unrotDh = dw;
1275        } else {
1276            unrotDw = dw;
1277            unrotDh = dh;
1278        }
1279        displayInfo.smallestNominalAppWidth = 1<<30;
1280        displayInfo.smallestNominalAppHeight = 1<<30;
1281        displayInfo.largestNominalAppWidth = 0;
1282        displayInfo.largestNominalAppHeight = 0;
1283        adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_0, uiMode, unrotDw,
1284                unrotDh);
1285        adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_90, uiMode, unrotDh,
1286                unrotDw);
1287        adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_180, uiMode, unrotDw,
1288                unrotDh);
1289        adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_270, uiMode, unrotDh,
1290                unrotDw);
1291        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
1292        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode,
1293                displayId);
1294        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode,
1295                displayId);
1296        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode,
1297                displayId);
1298        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode,
1299                displayId);
1300        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
1301        outConfig.screenLayout = sl;
1302    }
1303
1304    private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh,
1305            int uiMode, int displayId) {
1306        // Get the app screen size at this rotation.
1307        int w = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayId);
1308        int h = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayId);
1309
1310        // Compute the screen layout size class for this rotation.
1311        int longSize = w;
1312        int shortSize = h;
1313        if (longSize < shortSize) {
1314            int tmp = longSize;
1315            longSize = shortSize;
1316            shortSize = tmp;
1317        }
1318        longSize = (int)(longSize/density);
1319        shortSize = (int)(shortSize/density);
1320        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
1321    }
1322
1323    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int displayId, int rotation,
1324            int uiMode, int dw, int dh) {
1325        final int width = mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode,
1326                displayId);
1327        if (width < displayInfo.smallestNominalAppWidth) {
1328            displayInfo.smallestNominalAppWidth = width;
1329        }
1330        if (width > displayInfo.largestNominalAppWidth) {
1331            displayInfo.largestNominalAppWidth = width;
1332        }
1333        final int height = mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode,
1334                displayId);
1335        if (height < displayInfo.smallestNominalAppHeight) {
1336            displayInfo.smallestNominalAppHeight = height;
1337        }
1338        if (height > displayInfo.largestNominalAppHeight) {
1339            displayInfo.largestNominalAppHeight = height;
1340        }
1341    }
1342
1343    DockedStackDividerController getDockedDividerController() {
1344        return mDividerControllerLocked;
1345    }
1346
1347    PinnedStackController getPinnedStackController() {
1348        return mPinnedStackControllerLocked;
1349    }
1350
1351    /**
1352     * Returns true if the specified UID has access to this display.
1353     */
1354    boolean hasAccess(int uid) {
1355        return mDisplay.hasAccess(uid);
1356    }
1357
1358    boolean isPrivate() {
1359        return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
1360    }
1361
1362    TaskStack getHomeStack() {
1363        if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
1364            Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
1365        }
1366        return mHomeStack;
1367    }
1368
1369    TaskStack getStackById(int stackId) {
1370        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1371            final TaskStack stack = mTaskStackContainers.get(i);
1372            if (stack.mStackId == stackId) {
1373                return stack;
1374            }
1375        }
1376        return null;
1377    }
1378
1379    @Override
1380    void onConfigurationChanged(Configuration newParentConfig) {
1381        super.onConfigurationChanged(newParentConfig);
1382
1383        // The display size information is heavily dependent on the resources in the current
1384        // configuration, so we need to reconfigure it every time the configuration changes.
1385        // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
1386        mService.reconfigureDisplayLocked(this);
1387
1388        getDockedDividerController().onConfigurationChanged();
1389        getPinnedStackController().onConfigurationChanged();
1390    }
1391
1392    /**
1393     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
1394     * bounds were updated.
1395     */
1396    void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
1397        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1398            final TaskStack stack = mTaskStackContainers.get(i);
1399            if (stack.updateBoundsAfterConfigChange()) {
1400                changedStackList.add(stack.mStackId);
1401            }
1402        }
1403    }
1404
1405    @Override
1406    boolean fillsParent() {
1407        return true;
1408    }
1409
1410    @Override
1411    boolean isVisible() {
1412        return true;
1413    }
1414
1415    @Override
1416    void onAppTransitionDone() {
1417        super.onAppTransitionDone();
1418        mService.mWindowsChanged = true;
1419    }
1420
1421    @Override
1422    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
1423        // Special handling so we can process IME windows with #forAllImeWindows above their IME
1424        // target, or here in order if there isn't an IME target.
1425        if (traverseTopToBottom) {
1426            for (int i = mChildren.size() - 1; i >= 0; --i) {
1427                final DisplayChildWindowContainer child = mChildren.get(i);
1428                if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
1429                    // In this case the Ime windows will be processed above their target so we skip
1430                    // here.
1431                    continue;
1432                }
1433                if (child.forAllWindows(callback, traverseTopToBottom)) {
1434                    return true;
1435                }
1436            }
1437        } else {
1438            final int count = mChildren.size();
1439            for (int i = 0; i < count; i++) {
1440                final DisplayChildWindowContainer child = mChildren.get(i);
1441                if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
1442                    // In this case the Ime windows will be processed above their target so we skip
1443                    // here.
1444                    continue;
1445                }
1446                if (child.forAllWindows(callback, traverseTopToBottom)) {
1447                    return true;
1448                }
1449            }
1450        }
1451        return false;
1452    }
1453
1454    boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
1455        return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
1456    }
1457
1458    @Override
1459    int getOrientation() {
1460        final WindowManagerPolicy policy = mService.mPolicy;
1461
1462        if (mService.mDisplayFrozen) {
1463            if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
1464                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
1465                        "Display is frozen, return " + mLastWindowForcedOrientation);
1466                // If the display is frozen, some activities may be in the middle of restarting, and
1467                // thus have removed their old window. If the window has the flag to hide the lock
1468                // screen, then the lock screen can re-appear and inflict its own orientation on us.
1469                // Keep the orientation stable until this all settles down.
1470                return mLastWindowForcedOrientation;
1471            } else if (policy.isKeyguardLocked()) {
1472                // Use the last orientation the while the display is frozen with the keyguard
1473                // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED
1474                // window. We don't want to check the show when locked window directly though as
1475                // things aren't stable while the display is frozen, for example the window could be
1476                // momentarily unavailable due to activity relaunch.
1477                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
1478                        + "return " + mLastOrientation);
1479                return mLastOrientation;
1480            }
1481        } else {
1482            final int orientation = mAboveAppWindowsContainers.getOrientation();
1483            if (orientation != SCREEN_ORIENTATION_UNSET) {
1484                return orientation;
1485            }
1486        }
1487
1488        // Top system windows are not requesting an orientation. Start searching from apps.
1489        return mTaskStackContainers.getOrientation();
1490    }
1491
1492    void updateDisplayInfo() {
1493        mDisplay.getDisplayInfo(mDisplayInfo);
1494        mDisplay.getMetrics(mDisplayMetrics);
1495        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1496            mTaskStackContainers.get(i).updateDisplayInfo(null);
1497        }
1498    }
1499
1500    void initializeDisplayBaseInfo() {
1501        final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal;
1502        if (displayManagerInternal != null) {
1503            // Bootstrap the default logical display from the display manager.
1504            final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
1505            if (newDisplayInfo != null) {
1506                mDisplayInfo.copyFrom(newDisplayInfo);
1507            }
1508        }
1509
1510        mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
1511        mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
1512        mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
1513        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
1514    }
1515
1516    void getLogicalDisplayRect(Rect out) {
1517        // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
1518        final int orientation = mDisplayInfo.rotation;
1519        boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
1520        final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
1521        final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
1522        int width = mDisplayInfo.logicalWidth;
1523        int left = (physWidth - width) / 2;
1524        int height = mDisplayInfo.logicalHeight;
1525        int top = (physHeight - height) / 2;
1526        out.set(left, top, left + width, top + height);
1527    }
1528
1529    private void getLogicalDisplayRect(Rect out, int orientation) {
1530        getLogicalDisplayRect(out);
1531
1532        // Rotate the Rect if needed.
1533        final int currentRotation = mDisplayInfo.rotation;
1534        final int rotationDelta = deltaRotation(currentRotation, orientation);
1535        if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
1536            createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
1537            mTmpRectF.set(out);
1538            mTmpMatrix.mapRect(mTmpRectF);
1539            mTmpRectF.round(out);
1540        }
1541    }
1542
1543    /** Sets the maximum width the screen resolution can be */
1544    void setMaxUiWidth(int width) {
1545        if (DEBUG_DISPLAY) {
1546            Slog.v(TAG_WM, "Setting max ui width:" + width + " on display:" + getDisplayId());
1547        }
1548
1549        mMaxUiWidth = width;
1550
1551        // Update existing metrics.
1552        updateBaseDisplayMetrics(mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity);
1553    }
1554
1555    /** Update base (override) display metrics. */
1556    void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) {
1557        mBaseDisplayWidth = baseWidth;
1558        mBaseDisplayHeight = baseHeight;
1559        mBaseDisplayDensity = baseDensity;
1560
1561        if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) {
1562            mBaseDisplayHeight = (mMaxUiWidth * mBaseDisplayHeight) / mBaseDisplayWidth;
1563            mBaseDisplayDensity = (mMaxUiWidth * mBaseDisplayDensity) / mBaseDisplayWidth;
1564            mBaseDisplayWidth = mMaxUiWidth;
1565
1566            if (DEBUG_DISPLAY) {
1567                Slog.v(TAG_WM, "Applying config restraints:" + mBaseDisplayWidth + "x"
1568                        + mBaseDisplayHeight + " at density:" + mBaseDisplayDensity
1569                        + " on display:" + getDisplayId());
1570            }
1571        }
1572
1573        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
1574    }
1575
1576    void getContentRect(Rect out) {
1577        out.set(mContentRect);
1578    }
1579
1580    TaskStack addStackToDisplay(int stackId, boolean onTop) {
1581        if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
1582                + mDisplayId);
1583
1584        TaskStack stack = getStackById(stackId);
1585        if (stack != null) {
1586            // It's already attached to the display...clear mDeferRemoval and move stack to
1587            // appropriate z-order on display as needed.
1588            stack.mDeferRemoval = false;
1589            // We're not moving the display to front when we're adding stacks, only when
1590            // requested to change the position of stack explicitly.
1591            mTaskStackContainers.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, stack,
1592                    false /* includingParents */);
1593        } else {
1594            stack = new TaskStack(mService, stackId);
1595            mTaskStackContainers.addStackToDisplay(stack, onTop);
1596        }
1597
1598        if (stackId == DOCKED_STACK_ID) {
1599            mDividerControllerLocked.notifyDockedStackExistsChanged(true);
1600        }
1601        return stack;
1602    }
1603
1604    void moveStackToDisplay(TaskStack stack) {
1605        final DisplayContent prevDc = stack.getDisplayContent();
1606        if (prevDc == null) {
1607            throw new IllegalStateException("Trying to move stackId=" + stack.mStackId
1608                    + " which is not currently attached to any display");
1609        }
1610        if (prevDc.getDisplayId() == mDisplayId) {
1611            throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId
1612                    + " to its current displayId=" + mDisplayId);
1613        }
1614
1615        prevDc.mTaskStackContainers.removeStackFromDisplay(stack);
1616        mTaskStackContainers.addStackToDisplay(stack, true /* onTop */);
1617    }
1618
1619    @Override
1620    protected void addChild(DisplayChildWindowContainer child,
1621            Comparator<DisplayChildWindowContainer> comparator) {
1622        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1623    }
1624
1625    @Override
1626    protected void addChild(DisplayChildWindowContainer child, int index) {
1627        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1628    }
1629
1630    @Override
1631    protected void removeChild(DisplayChildWindowContainer child) {
1632        // Only allow removal of direct children from this display if the display is in the process
1633        // of been removed.
1634        if (mRemovingDisplay) {
1635            super.removeChild(child);
1636            return;
1637        }
1638        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1639    }
1640
1641    @Override
1642    void positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents) {
1643        // Children of the display are statically ordered, so the real intention here is to perform
1644        // the operation on the display and not the static direct children.
1645        getParent().positionChildAt(position, this, includingParents);
1646    }
1647
1648    int taskIdFromPoint(int x, int y) {
1649        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1650            final TaskStack stack = mTaskStackContainers.get(stackNdx);
1651            final int taskId = stack.taskIdFromPoint(x, y);
1652            if (taskId != -1) {
1653                return taskId;
1654            }
1655        }
1656        return -1;
1657    }
1658
1659    /**
1660     * Find the task whose outside touch area (for resizing) (x, y) falls within.
1661     * Returns null if the touch doesn't fall into a resizing area.
1662     */
1663    Task findTaskForResizePoint(int x, int y) {
1664        final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
1665        mTmpTaskForResizePointSearchResult.reset();
1666        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1667            final TaskStack stack = mTaskStackContainers.get(stackNdx);
1668            if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
1669                return null;
1670            }
1671
1672            stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult);
1673            if (mTmpTaskForResizePointSearchResult.searchDone) {
1674                return mTmpTaskForResizePointSearchResult.taskForResize;
1675            }
1676        }
1677        return null;
1678    }
1679
1680    void setTouchExcludeRegion(Task focusedTask) {
1681        // The provided task is the task on this display with focus, so if WindowManagerService's
1682        // focused app is not on this display, focusedTask will be null.
1683        if (focusedTask == null) {
1684            mTouchExcludeRegion.setEmpty();
1685        } else {
1686            mTouchExcludeRegion.set(mBaseDisplayRect);
1687            final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
1688            mTmpRect2.setEmpty();
1689            for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1690                final TaskStack stack = mTaskStackContainers.get(stackNdx);
1691                stack.setTouchExcludeRegion(
1692                        focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
1693            }
1694            // If we removed the focused task above, add it back and only leave its
1695            // outside touch area in the exclusion. TapDectector is not interested in
1696            // any touch inside the focused task itself.
1697            if (!mTmpRect2.isEmpty()) {
1698                mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
1699            }
1700        }
1701        final WindowState inputMethod = mService.mInputMethodWindow;
1702        if (inputMethod != null && inputMethod.isVisibleLw()) {
1703            // If the input method is visible and the user is typing, we don't want these touch
1704            // events to be intercepted and used to change focus. This would likely cause a
1705            // disappearance of the input method.
1706            inputMethod.getTouchableRegion(mTmpRegion);
1707            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
1708        }
1709        for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
1710            WindowState win = mTapExcludedWindows.get(i);
1711            win.getTouchableRegion(mTmpRegion);
1712            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
1713        }
1714        // TODO(multi-display): Support docked stacks on secondary displays.
1715        if (mDisplayId == DEFAULT_DISPLAY && getDockedStackLocked() != null) {
1716            mDividerControllerLocked.getTouchRegion(mTmpRect);
1717            mTmpRegion.set(mTmpRect);
1718            mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
1719        }
1720        if (mTapDetector != null) {
1721            mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
1722        }
1723    }
1724
1725    @Override
1726    void switchUser() {
1727        super.switchUser();
1728        mService.mWindowsChanged = true;
1729    }
1730
1731    private void resetAnimationBackgroundAnimator() {
1732        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1733            mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator();
1734        }
1735    }
1736
1737    boolean animateDimLayers() {
1738        return mDimLayerController.animateDimLayers();
1739    }
1740
1741    private void resetDimming() {
1742        mDimLayerController.resetDimming();
1743    }
1744
1745    boolean isDimming() {
1746        return mDimLayerController.isDimming();
1747    }
1748
1749    private void stopDimmingIfNeeded() {
1750        mDimLayerController.stopDimmingIfNeeded();
1751    }
1752
1753    @Override
1754    void removeIfPossible() {
1755        if (isAnimating()) {
1756            mDeferredRemoval = true;
1757            return;
1758        }
1759        removeImmediately();
1760    }
1761
1762    @Override
1763    void removeImmediately() {
1764        mRemovingDisplay = true;
1765        try {
1766            super.removeImmediately();
1767            if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
1768            mDimLayerController.close();
1769            if (mDisplayId == DEFAULT_DISPLAY && mService.canDispatchPointerEvents()) {
1770                mService.unregisterPointerEventListener(mTapDetector);
1771                mService.unregisterPointerEventListener(mService.mMousePositionTracker);
1772            }
1773        } finally {
1774            mRemovingDisplay = false;
1775        }
1776    }
1777
1778    /** Returns true if a removal action is still being deferred. */
1779    @Override
1780    boolean checkCompleteDeferredRemoval() {
1781        final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
1782
1783        if (!stillDeferringRemoval && mDeferredRemoval) {
1784            removeImmediately();
1785            mService.onDisplayRemoved(mDisplayId);
1786            return false;
1787        }
1788        return true;
1789    }
1790
1791    boolean animateForIme(float interpolatedValue, float animationTarget,
1792            float dividerAnimationTarget) {
1793        boolean updated = false;
1794
1795        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1796            final TaskStack stack = mTaskStackContainers.get(i);
1797            if (stack == null || !stack.isAdjustedForIme()) {
1798                continue;
1799            }
1800
1801            if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) {
1802                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
1803                updated = true;
1804            } else {
1805                mDividerControllerLocked.mLastAnimationProgress =
1806                        mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue);
1807                mDividerControllerLocked.mLastDividerProgress =
1808                        mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue);
1809                updated |= stack.updateAdjustForIme(
1810                        mDividerControllerLocked.mLastAnimationProgress,
1811                        mDividerControllerLocked.mLastDividerProgress,
1812                        false /* force */);
1813            }
1814            if (interpolatedValue >= 1f) {
1815                stack.endImeAdjustAnimation();
1816            }
1817        }
1818
1819        return updated;
1820    }
1821
1822    boolean clearImeAdjustAnimation() {
1823        boolean changed = false;
1824        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1825            final TaskStack stack = mTaskStackContainers.get(i);
1826            if (stack != null && stack.isAdjustedForIme()) {
1827                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
1828                changed  = true;
1829            }
1830        }
1831        return changed;
1832    }
1833
1834    void beginImeAdjustAnimation() {
1835        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1836            final TaskStack stack = mTaskStackContainers.get(i);
1837            if (stack.isVisible() && stack.isAdjustedForIme()) {
1838                stack.beginImeAdjustAnimation();
1839            }
1840        }
1841    }
1842
1843    void adjustForImeIfNeeded() {
1844        final WindowState imeWin = mService.mInputMethodWindow;
1845        final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
1846                && !mDividerControllerLocked.isImeHideRequested();
1847        final boolean dockVisible = isStackVisible(DOCKED_STACK_ID);
1848        final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
1849        final int imeDockSide = (dockVisible && imeTargetStack != null) ?
1850                imeTargetStack.getDockSide() : DOCKED_INVALID;
1851        final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
1852        final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
1853        final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock();
1854        final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw();
1855        final boolean imeHeightChanged = imeVisible &&
1856                imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
1857
1858        // The divider could be adjusted for IME position, or be thinner than usual,
1859        // or both. There are three possible cases:
1860        // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
1861        // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
1862        // - If IME is not visible, divider is not moved and is normal width.
1863
1864        if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
1865            for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1866                final TaskStack stack = mTaskStackContainers.get(i);
1867                final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
1868                if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
1869                    stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
1870                } else {
1871                    stack.resetAdjustedForIme(false);
1872                }
1873            }
1874            mDividerControllerLocked.setAdjustedForIme(
1875                    imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
1876        } else {
1877            for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1878                final TaskStack stack = mTaskStackContainers.get(i);
1879                stack.resetAdjustedForIme(!dockVisible);
1880            }
1881            mDividerControllerLocked.setAdjustedForIme(
1882                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
1883        }
1884        mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
1885    }
1886
1887    void setInputMethodAnimLayerAdjustment(int adj) {
1888        if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
1889        mInputMethodAnimLayerAdjustment = adj;
1890        assignWindowLayers(false /* relayoutNeeded */);
1891    }
1892
1893    /**
1894     * If a window that has an animation specifying a colored background and the current wallpaper
1895     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
1896     * suddenly disappear.
1897     */
1898    int getLayerForAnimationBackground(WindowStateAnimator winAnimator) {
1899        final WindowState visibleWallpaper = mBelowAppWindowsContainers.getWindow(
1900                w -> w.mIsWallpaper && w.isVisibleNow());
1901
1902        if (visibleWallpaper != null) {
1903            return visibleWallpaper.mWinAnimator.mAnimLayer;
1904        }
1905        return winAnimator.mAnimLayer;
1906    }
1907
1908    void prepareFreezingTaskBounds() {
1909        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1910            final TaskStack stack = mTaskStackContainers.get(stackNdx);
1911            stack.prepareFreezingTaskBounds();
1912        }
1913    }
1914
1915    void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
1916        getLogicalDisplayRect(mTmpRect, newRotation);
1917
1918        // Compute a transform matrix to undo the coordinate space transformation,
1919        // and present the window at the same physical position it previously occupied.
1920        final int deltaRotation = deltaRotation(newRotation, oldRotation);
1921        createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
1922
1923        mTmpRectF.set(bounds);
1924        mTmpMatrix.mapRect(mTmpRectF);
1925        mTmpRectF.round(bounds);
1926    }
1927
1928    static int deltaRotation(int oldRotation, int newRotation) {
1929        int delta = newRotation - oldRotation;
1930        if (delta < 0) delta += 4;
1931        return delta;
1932    }
1933
1934    private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
1935            Matrix outMatrix) {
1936        // For rotations without Z-ordering we don't need the target rectangle's position.
1937        createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
1938                displayHeight, outMatrix);
1939    }
1940
1941    static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
1942            float displayWidth, float displayHeight, Matrix outMatrix) {
1943        switch (rotation) {
1944            case ROTATION_0:
1945                outMatrix.reset();
1946                break;
1947            case ROTATION_270:
1948                outMatrix.setRotate(270, 0, 0);
1949                outMatrix.postTranslate(0, displayHeight);
1950                outMatrix.postTranslate(rectTop, 0);
1951                break;
1952            case ROTATION_180:
1953                outMatrix.reset();
1954                break;
1955            case ROTATION_90:
1956                outMatrix.setRotate(90, 0, 0);
1957                outMatrix.postTranslate(displayWidth, 0);
1958                outMatrix.postTranslate(-rectTop, rectLeft);
1959                break;
1960        }
1961    }
1962
1963    public void dump(String prefix, PrintWriter pw) {
1964        pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
1965        final String subPrefix = "  " + prefix;
1966        pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
1967            pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
1968            pw.print("dpi");
1969            if (mInitialDisplayWidth != mBaseDisplayWidth
1970                    || mInitialDisplayHeight != mBaseDisplayHeight
1971                    || mInitialDisplayDensity != mBaseDisplayDensity) {
1972                pw.print(" base=");
1973                pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
1974                pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
1975            }
1976            if (mDisplayScalingDisabled) {
1977                pw.println(" noscale");
1978            }
1979            pw.print(" cur=");
1980            pw.print(mDisplayInfo.logicalWidth);
1981            pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
1982            pw.print(" app=");
1983            pw.print(mDisplayInfo.appWidth);
1984            pw.print("x"); pw.print(mDisplayInfo.appHeight);
1985            pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
1986            pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
1987            pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
1988            pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
1989            pw.println(subPrefix + "deferred=" + mDeferredRemoval
1990                    + " mLayoutNeeded=" + mLayoutNeeded);
1991
1992        pw.println();
1993        pw.println(prefix + "Application tokens in top down Z order:");
1994        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1995            final TaskStack stack = mTaskStackContainers.get(stackNdx);
1996            stack.dump(prefix + "  ", pw);
1997        }
1998
1999        pw.println();
2000        if (!mExitingTokens.isEmpty()) {
2001            pw.println();
2002            pw.println("  Exiting tokens:");
2003            for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
2004                final WindowToken token = mExitingTokens.get(i);
2005                pw.print("  Exiting #"); pw.print(i);
2006                pw.print(' '); pw.print(token);
2007                pw.println(':');
2008                token.dump(pw, "    ");
2009            }
2010        }
2011        pw.println();
2012        mDimLayerController.dump(prefix, pw);
2013        pw.println();
2014        mDividerControllerLocked.dump(prefix, pw);
2015        pw.println();
2016        mPinnedStackControllerLocked.dump(prefix, pw);
2017
2018        if (mInputMethodAnimLayerAdjustment != 0) {
2019            pw.println(subPrefix
2020                    + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment);
2021        }
2022    }
2023
2024    @Override
2025    public String toString() {
2026        return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren;
2027    }
2028
2029    String getName() {
2030        return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
2031    }
2032
2033    /** Checks if stack with provided id is visible on this display. */
2034    boolean isStackVisible(int stackId) {
2035        final TaskStack stack = getStackById(stackId);
2036        return (stack != null && stack.isVisible());
2037    }
2038
2039    /**
2040     * @return The docked stack, but only if it is visible, and {@code null} otherwise.
2041     */
2042    TaskStack getDockedStackLocked() {
2043        final TaskStack stack = getStackById(DOCKED_STACK_ID);
2044        return (stack != null && stack.isVisible()) ? stack : null;
2045    }
2046
2047    /**
2048     * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
2049     * visible.
2050     */
2051    TaskStack getDockedStackIgnoringVisibility() {
2052        return getStackById(DOCKED_STACK_ID);
2053    }
2054
2055    /** Find the visible, touch-deliverable window under the given point */
2056    WindowState getTouchableWinAtPointLocked(float xf, float yf) {
2057        final int x = (int) xf;
2058        final int y = (int) yf;
2059        final WindowState touchedWin = getWindow(w -> {
2060            final int flags = w.mAttrs.flags;
2061            if (!w.isVisibleLw()) {
2062                return false;
2063            }
2064            if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
2065                return false;
2066            }
2067
2068            w.getVisibleBounds(mTmpRect);
2069            if (!mTmpRect.contains(x, y)) {
2070                return false;
2071            }
2072
2073            w.getTouchableRegion(mTmpRegion);
2074
2075            final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
2076            return mTmpRegion.contains(x, y) || touchFlags == 0;
2077        });
2078
2079        return touchedWin;
2080    }
2081
2082    boolean canAddToastWindowForUid(int uid) {
2083        // We allow one toast window per UID being shown at a time.
2084        // Also if the app is focused adding more than one toast at
2085        // a time for better backwards compatibility.
2086        final WindowState focusedWindowForUid = getWindow(w ->
2087                w.mOwnerUid == uid && w.isFocused());
2088        if (focusedWindowForUid != null) {
2089            return true;
2090        }
2091        final WindowState win = getWindow(w ->
2092                w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden
2093                && !w.mWindowRemovalAllowed);
2094        return win == null;
2095    }
2096
2097    void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
2098        if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
2099            return;
2100        }
2101
2102        // Used to communicate the old focus to the callback method.
2103        mTmpWindow = oldFocus;
2104
2105        forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */);
2106    }
2107
2108    WindowState findFocusedWindow() {
2109        mTmpWindow = null;
2110
2111        forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */);
2112
2113        if (mTmpWindow == null) {
2114            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
2115            return null;
2116        }
2117        return mTmpWindow;
2118    }
2119
2120    /** Updates the layer assignment of windows on this display. */
2121    void assignWindowLayers(boolean setLayoutNeeded) {
2122        mLayersController.assignWindowLayers(this);
2123        if (setLayoutNeeded) {
2124            setLayoutNeeded();
2125        }
2126    }
2127
2128    // TODO: This should probably be called any time a visual change is made to the hierarchy like
2129    // moving containers or resizing them. Need to investigate the best way to have it automatically
2130    // happen so we don't run into issues with programmers forgetting to do it.
2131    void layoutAndAssignWindowLayersIfNeeded() {
2132        mService.mWindowsChanged = true;
2133        setLayoutNeeded();
2134
2135        if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2136                false /*updateInputWindows*/)) {
2137            assignWindowLayers(false /* setLayoutNeeded */);
2138        }
2139
2140        mService.mInputMonitor.setUpdateInputWindowsNeededLw();
2141        mService.mWindowPlacerLocked.performSurfacePlacement();
2142        mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
2143    }
2144
2145    /** Returns true if a leaked surface was destroyed */
2146    boolean destroyLeakedSurfaces() {
2147        // Used to indicate that a surface was leaked.
2148        mTmpWindow = null;
2149        forAllWindows(w -> {
2150            final WindowStateAnimator wsa = w.mWinAnimator;
2151            if (wsa.mSurfaceController == null) {
2152                return;
2153            }
2154            if (!mService.mSessions.contains(wsa.mSession)) {
2155                Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
2156                        + w + " surface=" + wsa.mSurfaceController
2157                        + " token=" + w.mToken
2158                        + " pid=" + w.mSession.mPid
2159                        + " uid=" + w.mSession.mUid);
2160                wsa.destroySurface();
2161                mService.mForceRemoves.add(w);
2162                mTmpWindow = w;
2163            } else if (w.mAppToken != null && w.mAppToken.clientHidden) {
2164                Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
2165                        + w + " surface=" + wsa.mSurfaceController
2166                        + " token=" + w.mAppToken
2167                        + " saved=" + w.hasSavedSurface());
2168                if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false);
2169                wsa.destroySurface();
2170                mTmpWindow = w;
2171            }
2172        }, false /* traverseTopToBottom */);
2173
2174        return mTmpWindow != null;
2175    }
2176
2177    /**
2178     * Determine and return the window that should be the IME target.
2179     * @param updateImeTarget If true the system IME target will be updated to match what we found.
2180     * @return The window that should be used as the IME target or null if there isn't any.
2181     */
2182    WindowState computeImeTarget(boolean updateImeTarget) {
2183        if (mService.mInputMethodWindow == null) {
2184            // There isn't an IME so there shouldn't be a target...That was easy!
2185            if (updateImeTarget) {
2186                if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
2187                        + mService.mInputMethodTarget + " to null since mInputMethodWindow is null");
2188                setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0);
2189            }
2190            return null;
2191        }
2192
2193        // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
2194        // same display. Or even when the current IME/target are not on the same screen as the next
2195        // IME/target. For now only look for input windows on the main screen.
2196        mUpdateImeTarget = updateImeTarget;
2197        WindowState target = getWindow(mComputeImeTargetPredicate);
2198
2199
2200        // Yet more tricksyness!  If this window is a "starting" window, we do actually want
2201        // to be on top of it, but it is not -really- where input will go. So look down below
2202        // for a real window to target...
2203        if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) {
2204            final AppWindowToken token = target.mAppToken;
2205            if (token != null) {
2206                final WindowState betterTarget = token.getImeTargetBelowWindow(target);
2207                if (betterTarget != null) {
2208                    target = betterTarget;
2209                }
2210            }
2211        }
2212
2213        if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
2214                "Proposed new IME target: " + target);
2215
2216        // Now, a special case -- if the last target's window is in the process of exiting, and is
2217        // above the new target, keep on the last target to avoid flicker. Consider for example a
2218        // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it
2219        // until it is completely gone so it doesn't drop behind the dialog or its full-screen
2220        // scrim.
2221        final WindowState curTarget = mService.mInputMethodTarget;
2222        if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing()
2223                && (target == null
2224                    || curTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer)) {
2225            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
2226            return curTarget;
2227        }
2228
2229        if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target
2230                + " updateImeTarget=" + updateImeTarget);
2231
2232        if (target == null) {
2233            if (updateImeTarget) {
2234                if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
2235                        + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
2236                        + Debug.getCallers(4) : ""));
2237                setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0);
2238            }
2239
2240            return null;
2241        }
2242
2243        if (updateImeTarget) {
2244            AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
2245            if (token != null) {
2246
2247                // Now some fun for dealing with window animations that modify the Z order. We need
2248                // to look at all windows below the current target that are in this app, finding the
2249                // highest visible one in layering.
2250                WindowState highestTarget = null;
2251                if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
2252                    highestTarget = token.getHighestAnimLayerWindow(curTarget);
2253                }
2254
2255                if (highestTarget != null) {
2256                    final AppTransition appTransition = mService.mAppTransition;
2257                    if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget
2258                            + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
2259                            + " layer=" + highestTarget.mWinAnimator.mAnimLayer
2260                            + " new layer=" + target.mWinAnimator.mAnimLayer);
2261
2262                    if (appTransition.isTransitionSet()) {
2263                        // If we are currently setting up for an animation, hold everything until we
2264                        // can find out what will happen.
2265                        setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment);
2266                        return highestTarget;
2267                    } else if (highestTarget.mWinAnimator.isAnimationSet() &&
2268                            highestTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer) {
2269                        // If the window we are currently targeting is involved with an animation,
2270                        // and it is on top of the next target we will be over, then hold off on
2271                        // moving until that is done.
2272                        setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment);
2273                        return highestTarget;
2274                    }
2275                }
2276            }
2277
2278            if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
2279                    + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
2280            setInputMethodTarget(target, false, target.mAppToken != null
2281                    ? target.mAppToken.getAnimLayerAdjustment() : 0);
2282        }
2283
2284        return target;
2285    }
2286
2287    private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim, int layerAdj) {
2288        if (target == mService.mInputMethodTarget
2289                && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim
2290                && mInputMethodAnimLayerAdjustment == layerAdj) {
2291            return;
2292        }
2293
2294        mService.mInputMethodTarget = target;
2295        mService.mInputMethodTargetWaitingAnim = targetWaitingAnim;
2296        setInputMethodAnimLayerAdjustment(layerAdj);
2297        assignWindowLayers(false /* setLayoutNeeded */);
2298    }
2299
2300    boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
2301        if (top.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
2302            return top.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
2303        }
2304
2305        // Used to indicate we have reached the first window in the range we are interested in.
2306        mTmpWindow = null;
2307
2308        // TODO: Figure-out a more efficient way to do this.
2309        final WindowState candidate = getWindow(w -> {
2310            if (w == top) {
2311                // Reached the first window in the range we are interested in.
2312                mTmpWindow = w;
2313            }
2314            if (mTmpWindow == null) {
2315                return false;
2316            }
2317
2318            if (w.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
2319                return true;
2320            }
2321            // If we reached the bottom of the range of windows we are considering,
2322            // assume no menu is needed.
2323            if (w == bottom) {
2324                return true;
2325            }
2326            return false;
2327        });
2328
2329        return candidate != null && candidate.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
2330    }
2331
2332    void setLayoutNeeded() {
2333        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
2334        mLayoutNeeded = true;
2335    }
2336
2337    private void clearLayoutNeeded() {
2338        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3));
2339        mLayoutNeeded = false;
2340    }
2341
2342    boolean isLayoutNeeded() {
2343        return mLayoutNeeded;
2344    }
2345
2346    void dumpTokens(PrintWriter pw, boolean dumpAll) {
2347        if (mTokenMap.isEmpty()) {
2348            return;
2349        }
2350        pw.println("  Display #" + mDisplayId);
2351        final Iterator<WindowToken> it = mTokenMap.values().iterator();
2352        while (it.hasNext()) {
2353            final WindowToken token = it.next();
2354            pw.print("  ");
2355            pw.print(token);
2356            if (dumpAll) {
2357                pw.println(':');
2358                token.dump(pw, "    ");
2359            } else {
2360                pw.println();
2361            }
2362        }
2363    }
2364
2365    void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
2366        final int[] index = new int[1];
2367        forAllWindows(w -> {
2368            final WindowStateAnimator wAnim = w.mWinAnimator;
2369            pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim);
2370            index[0] = index[0] + 1;
2371        }, false /* traverseTopToBottom */);
2372    }
2373
2374    void enableSurfaceTrace(FileDescriptor fd) {
2375        forAllWindows(w -> {
2376            w.mWinAnimator.enableSurfaceTrace(fd);
2377        }, true /* traverseTopToBottom */);
2378    }
2379
2380    void disableSurfaceTrace() {
2381        forAllWindows(w -> {
2382            w.mWinAnimator.disableSurfaceTrace();
2383        }, true /* traverseTopToBottom */);
2384    }
2385
2386    /**
2387     * Starts the Keyguard exit animation on all windows that don't belong to an app token.
2388     */
2389    void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) {
2390        final WindowManagerPolicy policy = mService.mPolicy;
2391        forAllWindows(w -> {
2392            if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)) {
2393                w.mWinAnimator.setAnimation(
2394                        policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
2395            }
2396        }, true /* traverseTopToBottom */);
2397    }
2398
2399    boolean checkWaitingForWindows() {
2400
2401        mHaveBootMsg = false;
2402        mHaveApp = false;
2403        mHaveWallpaper = false;
2404        mHaveKeyguard = true;
2405
2406        final WindowState visibleWindow = getWindow(w -> {
2407            if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
2408                return true;
2409            }
2410            if (w.isDrawnLw()) {
2411                if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
2412                    mHaveBootMsg = true;
2413                } else if (w.mAttrs.type == TYPE_APPLICATION
2414                        || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
2415                    mHaveApp = true;
2416                } else if (w.mAttrs.type == TYPE_WALLPAPER) {
2417                    mHaveWallpaper = true;
2418                } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
2419                    mHaveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
2420                }
2421            }
2422            return false;
2423        });
2424
2425        if (visibleWindow != null) {
2426            // We have a visible window.
2427            return true;
2428        }
2429
2430        // if the wallpaper service is disabled on the device, we're never going to have
2431        // wallpaper, don't bother waiting for it
2432        boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
2433                com.android.internal.R.bool.config_enableWallpaperService)
2434                && !mService.mOnlyCore;
2435
2436        if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
2437                "******** booted=" + mService.mSystemBooted
2438                + " msg=" + mService.mShowingBootMessages
2439                + " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp
2440                + " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled
2441                + " haveKeyguard=" + mHaveKeyguard);
2442
2443        // If we are turning on the screen to show the boot message, don't do it until the boot
2444        // message is actually displayed.
2445        if (!mService.mSystemBooted && !mHaveBootMsg) {
2446            return true;
2447        }
2448
2449        // If we are turning on the screen after the boot is completed normally, don't do so until
2450        // we have the application and wallpaper.
2451        if (mService.mSystemBooted
2452                && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) {
2453            return true;
2454        }
2455
2456        return false;
2457    }
2458
2459    void updateWindowsForAnimator(WindowAnimator animator) {
2460        mTmpWindowAnimator = animator;
2461        forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
2462    }
2463
2464    void updateWallpaperForAnimator(WindowAnimator animator) {
2465        resetAnimationBackgroundAnimator();
2466
2467        // Used to indicate a detached wallpaper.
2468        mTmpWindow = null;
2469        mTmpWindowAnimator = animator;
2470
2471        forAllWindows(mUpdateWallpaperForAnimator, true /* traverseTopToBottom */);
2472
2473        if (animator.mWindowDetachedWallpaper != mTmpWindow) {
2474            if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from "
2475                    + animator.mWindowDetachedWallpaper + " to " + mTmpWindow);
2476            animator.mWindowDetachedWallpaper = mTmpWindow;
2477            animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
2478        }
2479    }
2480
2481    void prepareWindowSurfaces() {
2482        forAllWindows(mPrepareWindowSurfaces, false /* traverseTopToBottom */);
2483    }
2484
2485    boolean inputMethodClientHasFocus(IInputMethodClient client) {
2486        final WindowState imFocus = computeImeTarget(false /* updateImeTarget */);
2487        if (imFocus == null) {
2488            return false;
2489        }
2490
2491        if (DEBUG_INPUT_METHOD) {
2492            Slog.i(TAG_WM, "Desired input method target: " + imFocus);
2493            Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
2494            Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
2495        }
2496
2497        final IInputMethodClient imeClient = imFocus.mSession.mClient;
2498
2499        if (DEBUG_INPUT_METHOD) {
2500            Slog.i(TAG_WM, "IM target client: " + imeClient);
2501            if (imeClient != null) {
2502                Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder());
2503                Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
2504            }
2505        }
2506
2507        return imeClient != null && imeClient.asBinder() == client.asBinder();
2508    }
2509
2510    boolean hasSecureWindowOnScreen() {
2511        final WindowState win = getWindow(
2512                w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0);
2513        return win != null;
2514    }
2515
2516    void updateSystemUiVisibility(int visibility, int globalDiff) {
2517        forAllWindows(w -> {
2518            try {
2519                final int curValue = w.mSystemUiVisibility;
2520                final int diff = (curValue ^ visibility) & globalDiff;
2521                final int newValue = (curValue & ~diff) | (visibility & diff);
2522                if (newValue != curValue) {
2523                    w.mSeq++;
2524                    w.mSystemUiVisibility = newValue;
2525                }
2526                if (newValue != curValue || w.mAttrs.hasSystemUiListeners) {
2527                    w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq,
2528                            visibility, newValue, diff);
2529                }
2530            } catch (RemoteException e) {
2531                // so sorry
2532            }
2533        }, true /* traverseTopToBottom */);
2534    }
2535
2536    void onWindowFreezeTimeout() {
2537        Slog.w(TAG_WM, "Window freeze timeout expired.");
2538        mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
2539
2540        forAllWindows(w -> {
2541            if (!w.mOrientationChanging) {
2542                return;
2543            }
2544            w.mOrientationChanging = false;
2545            w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
2546                    - mService.mDisplayFreezeTime);
2547            Slog.w(TAG_WM, "Force clearing orientation change: " + w);
2548        }, true /* traverseTopToBottom */);
2549        mService.mWindowPlacerLocked.performSurfacePlacement();
2550    }
2551
2552    void waitForAllWindowsDrawn() {
2553        final WindowManagerPolicy policy = mService.mPolicy;
2554        forAllWindows(w -> {
2555            final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
2556            if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
2557                w.mWinAnimator.mDrawState = DRAW_PENDING;
2558                // Force add to mResizingWindows.
2559                w.mLastContentInsets.set(-1, -1, -1, -1);
2560                mService.mWaitingForDrawn.add(w);
2561            }
2562        }, true /* traverseTopToBottom */);
2563    }
2564
2565    // TODO: Super crazy long method that should be broken down...
2566    boolean applySurfaceChangesTransaction(boolean recoveringMemory) {
2567
2568        final int dw = mDisplayInfo.logicalWidth;
2569        final int dh = mDisplayInfo.logicalHeight;
2570        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
2571
2572        mTmpUpdateAllDrawn.clear();
2573
2574        int repeats = 0;
2575        do {
2576            repeats++;
2577            if (repeats > 6) {
2578                Slog.w(TAG, "Animation repeat aborted after too many iterations");
2579                clearLayoutNeeded();
2580                break;
2581            }
2582
2583            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
2584                    pendingLayoutChanges);
2585
2586            // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid
2587            // the wallpaper window jumping across displays.
2588            // Remove check for default display when there will be support for multiple wallpaper
2589            // targets (on different displays).
2590            if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
2591                mWallpaperController.adjustWallpaperWindows(this);
2592            }
2593
2594            if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
2595                if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
2596                if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) {
2597                    setLayoutNeeded();
2598                    mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
2599                }
2600            }
2601
2602            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
2603                setLayoutNeeded();
2604            }
2605
2606            // FIRST LOOP: Perform a layout, if needed.
2607            if (repeats < LAYOUT_REPEAT_THRESHOLD) {
2608                performLayout(repeats == 1, false /* updateInputWindows */);
2609            } else {
2610                Slog.w(TAG, "Layout repeat skipped after too many iterations");
2611            }
2612
2613            // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
2614            pendingLayoutChanges = 0;
2615
2616            if (isDefaultDisplay) {
2617                mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
2618                forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
2619                pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
2620                if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
2621                        "after finishPostLayoutPolicyLw", pendingLayoutChanges);
2622            }
2623        } while (pendingLayoutChanges != 0);
2624
2625        mTmpApplySurfaceChangesTransactionState.reset();
2626        resetDimming();
2627
2628        mTmpRecoveringMemory = recoveringMemory;
2629        forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
2630
2631        mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
2632                mTmpApplySurfaceChangesTransactionState.displayHasContent,
2633                mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
2634                mTmpApplySurfaceChangesTransactionState.preferredModeId,
2635                true /* inTraversal, must call performTraversalInTrans... below */);
2636
2637        stopDimmingIfNeeded();
2638
2639        while (!mTmpUpdateAllDrawn.isEmpty()) {
2640            final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
2641            // See if any windows have been drawn, so they (and others associated with them)
2642            // can now be shown.
2643            atoken.updateAllDrawn(this);
2644        }
2645
2646        return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
2647    }
2648
2649    void performLayout(boolean initial, boolean updateInputWindows) {
2650        if (!isLayoutNeeded()) {
2651            return;
2652        }
2653        clearLayoutNeeded();
2654
2655        final int dw = mDisplayInfo.logicalWidth;
2656        final int dh = mDisplayInfo.logicalHeight;
2657
2658        if (DEBUG_LAYOUT) {
2659            Slog.v(TAG, "-------------------------------------");
2660            Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh);
2661        }
2662
2663        mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation,
2664                getConfiguration().uiMode);
2665        if (isDefaultDisplay) {
2666            // Not needed on non-default displays.
2667            mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
2668            mService.mScreenRect.set(0, 0, dw, dh);
2669        }
2670
2671        mService.mPolicy.getContentRectLw(mContentRect);
2672
2673        int seq = mService.mLayoutSeq + 1;
2674        if (seq < 0) seq = 0;
2675        mService.mLayoutSeq = seq;
2676
2677        // Used to indicate that we have processed the dream window and all additional windows are
2678        // behind it.
2679        mTmpWindow = null;
2680        mTmpInitial = initial;
2681
2682        // First perform layout of any root windows (not attached to another window).
2683        forAllWindows(mPerformLayout, true /* traverseTopToBottom */);
2684
2685        // Used to indicate that we have processed the dream window and all additional attached
2686        // windows are behind it.
2687        mTmpWindow2 = mTmpWindow;
2688        mTmpWindow = null;
2689
2690        // Now perform layout of attached windows, which usually depend on the position of the
2691        // window they are attached to. XXX does not deal with windows that are attached to windows
2692        // that are themselves attached.
2693        forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);
2694
2695        // Window frames may have changed. Tell the input dispatcher about it.
2696        mService.mInputMonitor.layoutInputConsumers(dw, dh);
2697        mService.mInputMonitor.setUpdateInputWindowsNeededLw();
2698        if (updateInputWindows) {
2699            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
2700        }
2701
2702        mService.mPolicy.finishLayoutLw();
2703        mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
2704    }
2705
2706    /**
2707     * Takes a snapshot of the display.  In landscape mode this grabs the whole screen.
2708     * In portrait mode, it grabs the full screenshot.
2709     *
2710     * @param width the width of the target bitmap
2711     * @param height the height of the target bitmap
2712     * @param includeFullDisplay true if the screen should not be cropped before capture
2713     * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
2714     * @param config of the output bitmap
2715     * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
2716     * @param includeDecor whether to include window decors, like the status or navigation bar
2717     *                     background of the window
2718     */
2719    Bitmap screenshotApplications(IBinder appToken, int width, int height,
2720            boolean includeFullDisplay, float frameScale, Bitmap.Config config,
2721            boolean wallpaperOnly, boolean includeDecor) {
2722        Bitmap bitmap = screenshotApplications(appToken, width, height, includeFullDisplay,
2723                frameScale, wallpaperOnly, includeDecor, SurfaceControl::screenshot);
2724        if (bitmap == null) {
2725            return null;
2726        }
2727
2728        if (DEBUG_SCREENSHOT) {
2729            // TEST IF IT's ALL BLACK
2730            int[] buffer = new int[bitmap.getWidth() * bitmap.getHeight()];
2731            bitmap.getPixels(buffer, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(),
2732                    bitmap.getHeight());
2733            boolean allBlack = true;
2734            final int firstColor = buffer[0];
2735            for (int i = 0; i < buffer.length; i++) {
2736                if (buffer[i] != firstColor) {
2737                    allBlack = false;
2738                    break;
2739                }
2740            }
2741            if (allBlack) {
2742                final WindowState appWin = mScreenshotApplicationState.appWin;
2743                final int maxLayer = mScreenshotApplicationState.maxLayer;
2744                final int minLayer = mScreenshotApplicationState.minLayer;
2745                Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
2746                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
2747                        (appWin != null ?
2748                                appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
2749                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
2750            }
2751        }
2752
2753        // Create a copy of the screenshot that is immutable and backed in ashmem.
2754        // This greatly reduces the overhead of passing the bitmap between processes.
2755        Bitmap ret = bitmap.createAshmemBitmap(config);
2756        bitmap.recycle();
2757        return ret;
2758    }
2759
2760    GraphicBuffer screenshotApplicationsToBuffer(IBinder appToken, int width, int height,
2761            boolean includeFullDisplay, float frameScale, boolean wallpaperOnly,
2762            boolean includeDecor) {
2763        return screenshotApplications(appToken, width, height, includeFullDisplay, frameScale,
2764                wallpaperOnly, includeDecor, SurfaceControl::screenshotToBuffer);
2765    }
2766
2767    private <E> E screenshotApplications(IBinder appToken, int width, int height,
2768            boolean includeFullDisplay, float frameScale, boolean wallpaperOnly,
2769            boolean includeDecor, Screenshoter<E> screenshoter) {
2770        int dw = mDisplayInfo.logicalWidth;
2771        int dh = mDisplayInfo.logicalHeight;
2772        if (dw == 0 || dh == 0) {
2773            if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
2774                    + ": returning null. logical widthxheight=" + dw + "x" + dh);
2775            return null;
2776        }
2777
2778        E bitmap;
2779
2780        mScreenshotApplicationState.reset(appToken == null && !wallpaperOnly);
2781        final Rect frame = new Rect();
2782        final Rect stackBounds = new Rect();
2783
2784        boolean includeImeInScreenshot;
2785        synchronized(mService.mWindowMap) {
2786            final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null
2787                    ? mService.mInputMethodTarget.mAppToken : null;
2788            // We only include the Ime in the screenshot if the app we are screenshoting is the IME
2789            // target and isn't in multi-window mode. We don't screenshot the IME in multi-window
2790            // mode because the frame of the IME might not overlap with that of the app.
2791            // E.g. IME target app at the top in split-screen mode and the IME at the bottom
2792            // overlapping with the bottom app.
2793            includeImeInScreenshot = imeTargetAppToken != null
2794                    && imeTargetAppToken.appToken != null
2795                    && imeTargetAppToken.appToken.asBinder() == appToken
2796                    && !mService.mInputMethodTarget.isInMultiWindowMode();
2797        }
2798
2799        final int aboveAppLayer = (mService.mPolicy.getWindowLayerFromTypeLw(TYPE_APPLICATION) + 1)
2800                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
2801        final MutableBoolean mutableIncludeFullDisplay = new MutableBoolean(includeFullDisplay);
2802        synchronized(mService.mWindowMap) {
2803            // Figure out the part of the screen that is actually the app.
2804            mScreenshotApplicationState.appWin = null;
2805            forAllWindows(w -> {
2806                if (!w.mHasSurface) {
2807                    return false;
2808                }
2809                if (w.mLayer >= aboveAppLayer) {
2810                    return false;
2811                }
2812                if (wallpaperOnly && !w.mIsWallpaper) {
2813                    return false;
2814                }
2815                if (w.mIsImWindow) {
2816                    if (!includeImeInScreenshot) {
2817                        return false;
2818                    }
2819                } else if (w.mIsWallpaper) {
2820                    // If this is the wallpaper layer and we're only looking for the wallpaper layer
2821                    // then the target window state is this one.
2822                    if (wallpaperOnly) {
2823                        mScreenshotApplicationState.appWin = w;
2824                    }
2825
2826                    if (mScreenshotApplicationState.appWin == null) {
2827                        // We have not ran across the target window yet, so it is probably behind
2828                        // the wallpaper. This can happen when the keyguard is up and all windows
2829                        // are moved behind the wallpaper. We don't want to include the wallpaper
2830                        // layer in the screenshot as it will cover-up the layer of the target
2831                        // window.
2832                        return false;
2833                    }
2834                    // Fall through. The target window is in front of the wallpaper. For this
2835                    // case we want to include the wallpaper layer in the screenshot because
2836                    // the target window might have some transparent areas.
2837                } else if (appToken != null) {
2838                    if (w.mAppToken == null || w.mAppToken.token != appToken) {
2839                        // This app window is of no interest if it is not associated with the
2840                        // screenshot app.
2841                        return false;
2842                    }
2843                    mScreenshotApplicationState.appWin = w;
2844                }
2845
2846                // Include this window.
2847
2848                final WindowStateAnimator winAnim = w.mWinAnimator;
2849                int layer = winAnim.mSurfaceController.getLayer();
2850                if (mScreenshotApplicationState.maxLayer < layer) {
2851                    mScreenshotApplicationState.maxLayer = layer;
2852                }
2853                if (mScreenshotApplicationState.minLayer > layer) {
2854                    mScreenshotApplicationState.minLayer = layer;
2855                }
2856
2857                // Don't include wallpaper in bounds calculation
2858                if (!mutableIncludeFullDisplay.value && includeDecor) {
2859                    final TaskStack stack = w.getStack();
2860                    if (stack != null) {
2861                        stack.getBounds(frame);
2862                    }
2863
2864                    // We want to screenshot with the exact bounds of the surface of the app. Thus,
2865                    // intersect it with the frame.
2866                    frame.intersect(w.mFrame);
2867                }else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) {
2868                    final Rect wf = w.mFrame;
2869                    final Rect cr = w.mContentInsets;
2870                    int left = wf.left + cr.left;
2871                    int top = wf.top + cr.top;
2872                    int right = wf.right - cr.right;
2873                    int bottom = wf.bottom - cr.bottom;
2874                    frame.union(left, top, right, bottom);
2875                    w.getVisibleBounds(stackBounds);
2876                    if (!Rect.intersects(frame, stackBounds)) {
2877                        // Set frame empty if there's no intersection.
2878                        frame.setEmpty();
2879                    }
2880                }
2881
2882                final boolean foundTargetWs =
2883                        (w.mAppToken != null && w.mAppToken.token == appToken)
2884                                || (mScreenshotApplicationState.appWin != null && wallpaperOnly);
2885                if (foundTargetWs && winAnim.getShown()) {
2886                    mScreenshotApplicationState.screenshotReady = true;
2887                }
2888
2889                if (w.isObscuringDisplay()){
2890                    return true;
2891                }
2892                return false;
2893            }, true /* traverseTopToBottom */);
2894
2895            final WindowState appWin = mScreenshotApplicationState.appWin;
2896            final boolean screenshotReady = mScreenshotApplicationState.screenshotReady;
2897            final int maxLayer = mScreenshotApplicationState.maxLayer;
2898            final int minLayer = mScreenshotApplicationState.minLayer;
2899
2900            if (appToken != null && appWin == null) {
2901                // Can't find a window to snapshot.
2902                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
2903                        "Screenshot: Couldn't find a surface matching " + appToken);
2904                return null;
2905            }
2906
2907            if (!screenshotReady) {
2908                Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken +
2909                        " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
2910                        appWin.mWinAnimator.mDrawState)));
2911                return null;
2912            }
2913
2914            // Screenshot is ready to be taken. Everything from here below will continue
2915            // through the bottom of the loop and return a value. We only stay in the loop
2916            // because we don't want to release the mWindowMap lock until the screenshot is
2917            // taken.
2918
2919            if (maxLayer == 0) {
2920                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
2921                        + ": returning null maxLayer=" + maxLayer);
2922                return null;
2923            }
2924
2925            if (!mutableIncludeFullDisplay.value) {
2926                // Constrain frame to the screen size.
2927                if (!frame.intersect(0, 0, dw, dh)) {
2928                    frame.setEmpty();
2929                }
2930            } else {
2931                // Caller just wants entire display.
2932                frame.set(0, 0, dw, dh);
2933            }
2934            if (frame.isEmpty()) {
2935                return null;
2936            }
2937
2938            if (width < 0) {
2939                width = (int) (frame.width() * frameScale);
2940            }
2941            if (height < 0) {
2942                height = (int) (frame.height() * frameScale);
2943            }
2944
2945            // Tell surface flinger what part of the image to crop. Take the top
2946            // right part of the application, and crop the larger dimension to fit.
2947            Rect crop = new Rect(frame);
2948            if (width / (float) frame.width() < height / (float) frame.height()) {
2949                int cropWidth = (int)((float)width / (float)height * frame.height());
2950                crop.right = crop.left + cropWidth;
2951            } else {
2952                int cropHeight = (int)((float)height / (float)width * frame.width());
2953                crop.bottom = crop.top + cropHeight;
2954            }
2955
2956            // The screenshot API does not apply the current screen rotation.
2957            int rot = mDisplay.getRotation();
2958
2959            if (rot == ROTATION_90 || rot == ROTATION_270) {
2960                rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90;
2961            }
2962
2963            // Surfaceflinger is not aware of orientation, so convert our logical
2964            // crop to surfaceflinger's portrait orientation.
2965            convertCropForSurfaceFlinger(crop, rot, dw, dh);
2966
2967            if (DEBUG_SCREENSHOT) {
2968                Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
2969                        + maxLayer + " appToken=" + appToken);
2970                forAllWindows(w -> {
2971                    final WindowSurfaceController controller = w.mWinAnimator.mSurfaceController;
2972                    Slog.i(TAG_WM, w + ": " + w.mLayer
2973                            + " animLayer=" + w.mWinAnimator.mAnimLayer
2974                            + " surfaceLayer=" + ((controller == null)
2975                            ? "null" : controller.getLayer()));
2976                }, false /* traverseTopToBottom */);
2977            }
2978
2979            final ScreenRotationAnimation screenRotationAnimation =
2980                    mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
2981            final boolean inRotation = screenRotationAnimation != null &&
2982                    screenRotationAnimation.isAnimating();
2983            if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
2984                    "Taking screenshot while rotating");
2985
2986            // We force pending transactions to flush before taking
2987            // the screenshot by pushing an empty synchronous transaction.
2988            SurfaceControl.openTransaction();
2989            SurfaceControl.closeTransactionSync();
2990
2991            bitmap = screenshoter.screenshot(crop, width, height, minLayer, maxLayer,
2992                    inRotation, rot);
2993            if (bitmap == null) {
2994                Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
2995                        + ") to layer " + maxLayer);
2996                return null;
2997            }
2998        }
2999        return bitmap;
3000    }
3001
3002    // TODO: Can this use createRotationMatrix()?
3003    private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
3004        if (rot == Surface.ROTATION_90) {
3005            final int tmp = crop.top;
3006            crop.top = dw - crop.right;
3007            crop.right = crop.bottom;
3008            crop.bottom = dw - crop.left;
3009            crop.left = tmp;
3010        } else if (rot == Surface.ROTATION_180) {
3011            int tmp = crop.top;
3012            crop.top = dh - crop.bottom;
3013            crop.bottom = dh - tmp;
3014            tmp = crop.right;
3015            crop.right = dw - crop.left;
3016            crop.left = dw - tmp;
3017        } else if (rot == Surface.ROTATION_270) {
3018            final int tmp = crop.top;
3019            crop.top = crop.left;
3020            crop.left = dh - crop.bottom;
3021            crop.bottom = crop.right;
3022            crop.right = dh - tmp;
3023        }
3024    }
3025
3026    void onSeamlessRotationTimeout() {
3027        // Used to indicate the layout is needed.
3028        mTmpWindow = null;
3029
3030        forAllWindows(w -> {
3031            if (!w.mSeamlesslyRotated) {
3032                return;
3033            }
3034            mTmpWindow = w;
3035            w.setDisplayLayoutNeeded();
3036            mService.markForSeamlessRotation(w, false);
3037        }, true /* traverseTopToBottom */);
3038
3039        if (mTmpWindow != null) {
3040            mService.mWindowPlacerLocked.performSurfacePlacement();
3041        }
3042    }
3043
3044    void setExitingTokensHasVisible(boolean hasVisible) {
3045        for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
3046            mExitingTokens.get(i).hasVisible = hasVisible;
3047        }
3048
3049        // Initialize state of exiting applications.
3050        mTaskStackContainers.setExitingTokensHasVisible(hasVisible);
3051    }
3052
3053    void removeExistingTokensIfPossible() {
3054        for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
3055            final WindowToken token = mExitingTokens.get(i);
3056            if (!token.hasVisible) {
3057                mExitingTokens.remove(i);
3058            }
3059        }
3060
3061        // Time to remove any exiting applications?
3062        mTaskStackContainers.removeExistingAppTokensIfPossible();
3063    }
3064
3065    @Override
3066    void onDescendantOverrideConfigurationChanged() {
3067        setLayoutNeeded();
3068        mService.requestTraversal();
3069    }
3070
3071    static final class TaskForResizePointSearchResult {
3072        boolean searchDone;
3073        Task taskForResize;
3074
3075        void reset() {
3076            searchDone = false;
3077            taskForResize = null;
3078        }
3079    }
3080
3081    private static final class ApplySurfaceChangesTransactionState {
3082        boolean displayHasContent;
3083        boolean obscured;
3084        boolean syswin;
3085        boolean focusDisplayed;
3086        float preferredRefreshRate;
3087        int preferredModeId;
3088
3089        void reset() {
3090            displayHasContent = false;
3091            obscured = false;
3092            syswin = false;
3093            focusDisplayed = false;
3094            preferredRefreshRate = 0;
3095            preferredModeId = 0;
3096        }
3097    }
3098
3099    private static final class ScreenshotApplicationState {
3100        WindowState appWin;
3101        int maxLayer;
3102        int minLayer;
3103        boolean screenshotReady;
3104
3105        void reset(boolean screenshotReady) {
3106            appWin = null;
3107            maxLayer = 0;
3108            minLayer = 0;
3109            this.screenshotReady = screenshotReady;
3110            minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE;
3111        }
3112    }
3113
3114    /**
3115     * Base class for any direct child window container of {@link #DisplayContent} need to inherit
3116     * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
3117     * homogeneous children type which is currently required by sub-classes of
3118     * {@link WindowContainer} class.
3119     */
3120    static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
3121
3122        int size() {
3123            return mChildren.size();
3124        }
3125
3126        E get(int index) {
3127            return mChildren.get(index);
3128        }
3129
3130        @Override
3131        boolean fillsParent() {
3132            return true;
3133        }
3134
3135        @Override
3136        boolean isVisible() {
3137            return true;
3138        }
3139    }
3140
3141    /**
3142     * Window container class that contains all containers on this display relating to Apps.
3143     * I.e Activities.
3144     */
3145    private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
3146
3147        /**
3148         * Adds the stack to this container.
3149         * @see WindowManagerService#addStackToDisplay(int, int, boolean)
3150         */
3151        void addStackToDisplay(TaskStack stack, boolean onTop) {
3152            if (stack.mStackId == HOME_STACK_ID) {
3153                if (mHomeStack != null) {
3154                    throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
3155                }
3156                mHomeStack = stack;
3157            }
3158            addChild(stack, onTop);
3159            stack.onDisplayChanged(DisplayContent.this);
3160        }
3161
3162        /** Removes the stack from its container and prepare for changing the parent. */
3163        void removeStackFromDisplay(TaskStack stack) {
3164            removeChild(stack);
3165            stack.onRemovedFromDisplay();
3166        }
3167
3168        private void addChild(TaskStack stack, boolean toTop) {
3169            final int addIndex = findPositionForStack(toTop ? mChildren.size() : 0, stack,
3170                    true /* adding */);
3171            addChild(stack, addIndex);
3172            setLayoutNeeded();
3173        }
3174
3175        @Override
3176        void positionChildAt(int position, TaskStack child, boolean includingParents) {
3177            if (StackId.isAlwaysOnTop(child.mStackId) && position != POSITION_TOP) {
3178                // This stack is always-on-top, override the default behavior.
3179                Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
3180
3181                // Moving to its current position, as we must call super but we don't want to
3182                // perform any meaningful action.
3183                final int currentPosition = mChildren.indexOf(child);
3184                super.positionChildAt(currentPosition, child, false /* includingParents */);
3185                return;
3186            }
3187
3188            final int targetPosition = findPositionForStack(position, child, false /* adding */);
3189            super.positionChildAt(targetPosition, child, includingParents);
3190
3191            setLayoutNeeded();
3192        }
3193
3194        /**
3195         * When stack is added or repositioned, find a proper position for it.
3196         * This will make sure that pinned stack always stays on top.
3197         * @param requestedPosition Position requested by caller.
3198         * @param stack Stack to be added or positioned.
3199         * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
3200         * @return The proper position for the stack.
3201         */
3202        private int findPositionForStack(int requestedPosition, TaskStack stack, boolean adding) {
3203            final int topChildPosition = mChildren.size() - 1;
3204            boolean toTop = requestedPosition == POSITION_TOP;
3205            toTop |= adding ? requestedPosition >= topChildPosition + 1
3206                    : requestedPosition >= topChildPosition;
3207            int targetPosition = requestedPosition;
3208
3209            if (toTop && isStackVisible(PINNED_STACK_ID) && stack.mStackId != PINNED_STACK_ID) {
3210                // The pinned stack is always the top most stack (always-on-top) when it is visible.
3211                TaskStack topStack = mChildren.get(topChildPosition);
3212                if (topStack.mStackId != PINNED_STACK_ID) {
3213                    throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
3214                }
3215
3216                // So, stack is moved just below the pinned stack.
3217                // When we're adding a new stack the target is the current pinned stack position.
3218                // When we're positioning an existing stack the target is the position below pinned
3219                // stack, because WindowContainer#positionAt() first removes element and then adds
3220                // it to specified place.
3221                targetPosition = adding ? topChildPosition : topChildPosition - 1;
3222            }
3223
3224            return targetPosition;
3225        }
3226
3227        @Override
3228        boolean forAllWindows(ToBooleanFunction<WindowState> callback,
3229                boolean traverseTopToBottom) {
3230            if (traverseTopToBottom) {
3231                if (super.forAllWindows(callback, traverseTopToBottom)) {
3232                    return true;
3233                }
3234                if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
3235                    return true;
3236                }
3237            } else {
3238                if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
3239                    return true;
3240                }
3241                if (super.forAllWindows(callback, traverseTopToBottom)) {
3242                    return true;
3243                }
3244            }
3245            return false;
3246        }
3247
3248        private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
3249                boolean traverseTopToBottom) {
3250            // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the
3251            // app tokens.
3252            // TODO: Investigate if we need to continue to do this or if we can just process them
3253            // in-order.
3254            if (traverseTopToBottom) {
3255                for (int i = mChildren.size() - 1; i >= 0; --i) {
3256                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
3257                    for (int j = appTokens.size() - 1; j >= 0; --j) {
3258                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
3259                                traverseTopToBottom)) {
3260                            return true;
3261                        }
3262                    }
3263                }
3264            } else {
3265                final int count = mChildren.size();
3266                for (int i = 0; i < count; ++i) {
3267                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
3268                    final int appTokensCount = appTokens.size();
3269                    for (int j = 0; j < appTokensCount; j++) {
3270                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
3271                                traverseTopToBottom)) {
3272                            return true;
3273                        }
3274                    }
3275                }
3276            }
3277            return false;
3278        }
3279
3280        void setExitingTokensHasVisible(boolean hasVisible) {
3281            for (int i = mChildren.size() - 1; i >= 0; --i) {
3282                final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
3283                for (int j = appTokens.size() - 1; j >= 0; --j) {
3284                    appTokens.get(j).hasVisible = hasVisible;
3285                }
3286            }
3287        }
3288
3289        void removeExistingAppTokensIfPossible() {
3290            for (int i = mChildren.size() - 1; i >= 0; --i) {
3291                final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
3292                for (int j = appTokens.size() - 1; j >= 0; --j) {
3293                    final AppWindowToken token = appTokens.get(j);
3294                    if (!token.hasVisible && !mService.mClosingApps.contains(token)
3295                            && (!token.mIsExiting || token.isEmpty())) {
3296                        // Make sure there is no animation running on this token, so any windows
3297                        // associated with it will be removed as soon as their animations are
3298                        // complete.
3299                        token.mAppAnimator.clearAnimation();
3300                        token.mAppAnimator.animating = false;
3301                        if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
3302                                "performLayout: App token exiting now removed" + token);
3303                        token.removeIfPossible();
3304                    }
3305                }
3306            }
3307        }
3308
3309        @Override
3310        int getOrientation() {
3311            if (isStackVisible(DOCKED_STACK_ID) || isStackVisible(FREEFORM_WORKSPACE_STACK_ID)) {
3312                // Apps and their containers are not allowed to specify an orientation while the
3313                // docked or freeform stack is visible...except for the home stack/task if the
3314                // docked stack is minimized and it actually set something.
3315                if (mHomeStack != null && mHomeStack.isVisible()
3316                        && mDividerControllerLocked.isMinimizedDock()) {
3317                    final int orientation = mHomeStack.getOrientation();
3318                    if (orientation != SCREEN_ORIENTATION_UNSET) {
3319                        return orientation;
3320                    }
3321                }
3322                return SCREEN_ORIENTATION_UNSPECIFIED;
3323            }
3324
3325            final int orientation = super.getOrientation();
3326            if (orientation != SCREEN_ORIENTATION_UNSET
3327                    && orientation != SCREEN_ORIENTATION_BEHIND) {
3328                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3329                        "App is requesting an orientation, return " + orientation);
3330                return orientation;
3331            }
3332
3333            if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3334                    "No app is requesting an orientation, return " + mLastOrientation);
3335            // The next app has not been requested to be visible, so we keep the current orientation
3336            // to prevent freezing/unfreezing the display too early.
3337            return mLastOrientation;
3338        }
3339    }
3340
3341    /**
3342     * Window container class that contains all containers on this display that are not related to
3343     * Apps. E.g. status bar.
3344     */
3345    private final class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
3346        /**
3347         * Compares two child window tokens returns -1 if the first is lesser than the second in
3348         * terms of z-order and 1 otherwise.
3349         */
3350        private final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
3351                // Tokens with higher base layer are z-ordered on-top.
3352                mService.mPolicy.getWindowLayerFromTypeLw(token1.windowType,
3353                        token1.mOwnerCanManageAppTokens)
3354                < mService.mPolicy.getWindowLayerFromTypeLw(token2.windowType,
3355                        token2.mOwnerCanManageAppTokens) ? -1 : 1;
3356
3357        private final Predicate<WindowState> mGetOrientingWindow = w -> {
3358            if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) {
3359                return false;
3360            }
3361            final int req = w.mAttrs.screenOrientation;
3362            if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND
3363                    || req == SCREEN_ORIENTATION_UNSET) {
3364                return false;
3365            }
3366            return true;
3367        };
3368
3369        private final String mName;
3370        NonAppWindowContainers(String name) {
3371            mName = name;
3372        }
3373
3374        void addChild(WindowToken token) {
3375            addChild(token, mWindowComparator);
3376        }
3377
3378        @Override
3379        int getOrientation() {
3380            final WindowManagerPolicy policy = mService.mPolicy;
3381            // Find a window requesting orientation.
3382            final WindowState win = getWindow(mGetOrientingWindow);
3383
3384            if (win != null) {
3385                final int req = win.mAttrs.screenOrientation;
3386                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
3387                if (policy.isKeyguardHostWindow(win.mAttrs)) {
3388                    mLastKeyguardForcedOrientation = req;
3389                }
3390                return (mLastWindowForcedOrientation = req);
3391            }
3392
3393            mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
3394
3395            if (policy.isKeyguardShowingAndNotOccluded()) {
3396                return mLastKeyguardForcedOrientation;
3397            }
3398
3399            return SCREEN_ORIENTATION_UNSET;
3400        }
3401
3402        @Override
3403        String getName() {
3404            return mName;
3405        }
3406    }
3407
3408    /**
3409     * Interface to screenshot into various types, i.e. {@link Bitmap} and {@link GraphicBuffer}.
3410     */
3411    @FunctionalInterface
3412    private interface Screenshoter<E> {
3413        E screenshot(Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
3414                boolean useIdentityTransform, int rotation);
3415    }
3416}
3417