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