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