OSDN Git Service

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