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.ActivityTaskManager.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.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
30 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
31 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
32 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
33 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
34 import static android.view.Display.DEFAULT_DISPLAY;
35 import static android.view.Display.FLAG_PRIVATE;
36 import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
37 import static android.view.Display.INVALID_DISPLAY;
38 import static android.view.InsetsState.TYPE_IME;
39 import static android.view.InsetsState.TYPE_LEFT_GESTURES;
40 import static android.view.InsetsState.TYPE_RIGHT_GESTURES;
41 import static android.view.Surface.ROTATION_0;
42 import static android.view.Surface.ROTATION_180;
43 import static android.view.Surface.ROTATION_270;
44 import static android.view.Surface.ROTATION_90;
45 import static android.view.View.GONE;
46 import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
47 import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
48 import static android.view.WindowManager.DOCKED_BOTTOM;
49 import static android.view.WindowManager.DOCKED_INVALID;
50 import static android.view.WindowManager.DOCKED_TOP;
51 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
52 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
53 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
54 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
55 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
56 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
57 import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
58 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
59 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
60 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
61 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
62 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
63 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
64 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
65 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
66 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
67 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
68 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
69 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
70 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
71 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
72 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
73 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
74 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
75 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
76 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
77 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
78 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
79 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
80 
81 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
82 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
83 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
84 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
85 import static com.android.server.wm.DisplayContentProto.ABOVE_APP_WINDOWS;
86 import static com.android.server.wm.DisplayContentProto.APP_TRANSITION;
87 import static com.android.server.wm.DisplayContentProto.BELOW_APP_WINDOWS;
88 import static com.android.server.wm.DisplayContentProto.CHANGING_APPS;
89 import static com.android.server.wm.DisplayContentProto.CLOSING_APPS;
90 import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES;
91 import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO;
92 import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER;
93 import static com.android.server.wm.DisplayContentProto.DPI;
94 import static com.android.server.wm.DisplayContentProto.FOCUSED_APP;
95 import static com.android.server.wm.DisplayContentProto.ID;
96 import static com.android.server.wm.DisplayContentProto.IME_WINDOWS;
97 import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
98 import static com.android.server.wm.DisplayContentProto.PINNED_STACK_CONTROLLER;
99 import static com.android.server.wm.DisplayContentProto.ROTATION;
100 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
101 import static com.android.server.wm.DisplayContentProto.STACKS;
102 import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
103 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
104 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
105 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
106 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
107 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
108 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
109 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
110 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
111 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
112 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
113 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
114 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
115 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
116 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
117 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
118 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
119 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
120 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
121 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
122 import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION;
123 import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE;
124 import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE;
125 import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
126 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
127 import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
128 import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
129 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
130 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
131 import static com.android.server.wm.WindowManagerService.SEAMLESS_ROTATION_TIMEOUT_DURATION;
132 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
133 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS;
134 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS;
135 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
136 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE;
137 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
138 import static com.android.server.wm.WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION;
139 import static com.android.server.wm.WindowManagerService.dipToPixel;
140 import static com.android.server.wm.WindowManagerService.logSurface;
141 import static com.android.server.wm.WindowState.EXCLUSION_LEFT;
142 import static com.android.server.wm.WindowState.EXCLUSION_RIGHT;
143 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
144 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
145 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
146 import static com.android.server.wm.utils.RegionUtils.forEachRectReverse;
147 import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
148 
149 import android.animation.AnimationHandler;
150 import android.annotation.CallSuper;
151 import android.annotation.IntDef;
152 import android.annotation.NonNull;
153 import android.annotation.Nullable;
154 import android.content.pm.PackageManager;
155 import android.content.res.CompatibilityInfo;
156 import android.content.res.Configuration;
157 import android.graphics.Bitmap;
158 import android.graphics.Insets;
159 import android.graphics.Matrix;
160 import android.graphics.Point;
161 import android.graphics.Rect;
162 import android.graphics.RectF;
163 import android.graphics.Region;
164 import android.graphics.Region.Op;
165 import android.hardware.display.DisplayManagerInternal;
166 import android.metrics.LogMaker;
167 import android.os.Binder;
168 import android.os.Debug;
169 import android.os.Handler;
170 import android.os.IBinder;
171 import android.os.Process;
172 import android.os.RemoteCallbackList;
173 import android.os.RemoteException;
174 import android.os.SystemClock;
175 import android.os.Trace;
176 import android.os.UserHandle;
177 import android.util.ArraySet;
178 import android.util.DisplayMetrics;
179 import android.util.Slog;
180 import android.util.proto.ProtoOutputStream;
181 import android.view.Display;
182 import android.view.DisplayCutout;
183 import android.view.DisplayInfo;
184 import android.view.Gravity;
185 import android.view.ISystemGestureExclusionListener;
186 import android.view.InputChannel;
187 import android.view.InputDevice;
188 import android.view.InputWindowHandle;
189 import android.view.InsetsState.InternalInsetType;
190 import android.view.MagnificationSpec;
191 import android.view.RemoteAnimationDefinition;
192 import android.view.Surface;
193 import android.view.SurfaceControl;
194 import android.view.SurfaceControl.Transaction;
195 import android.view.SurfaceSession;
196 import android.view.View;
197 import android.view.WindowManager;
198 import android.view.WindowManagerPolicyConstants.PointerEventListener;
199 
200 import com.android.internal.annotations.VisibleForTesting;
201 import com.android.internal.logging.MetricsLogger;
202 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
203 import com.android.internal.util.ToBooleanFunction;
204 import com.android.internal.util.function.TriConsumer;
205 import com.android.internal.util.function.pooled.PooledConsumer;
206 import com.android.internal.util.function.pooled.PooledLambda;
207 import com.android.server.AnimationThread;
208 import com.android.server.policy.WindowManagerPolicy;
209 import com.android.server.wm.utils.DisplayRotationUtil;
210 import com.android.server.wm.utils.RotationCache;
211 import com.android.server.wm.utils.WmDisplayCutout;
212 
213 import java.io.PrintWriter;
214 import java.lang.annotation.Retention;
215 import java.lang.annotation.RetentionPolicy;
216 import java.util.ArrayList;
217 import java.util.Comparator;
218 import java.util.HashMap;
219 import java.util.Iterator;
220 import java.util.LinkedList;
221 import java.util.List;
222 import java.util.Objects;
223 import java.util.function.Consumer;
224 import java.util.function.Predicate;
225 
226 /**
227  * Utility class for keeping track of the WindowStates and other pertinent contents of a
228  * particular Display.
229  */
230 class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer>
231         implements WindowManagerPolicy.DisplayContentInfo {
232     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
233 
234     /** The default scaling mode that scales content automatically. */
235     static final int FORCE_SCALING_MODE_AUTO = 0;
236     /** For {@link #setForcedScalingMode} to apply flag {@link Display#FLAG_SCALING_DISABLED}. */
237     static final int FORCE_SCALING_MODE_DISABLED = 1;
238 
239     @IntDef(prefix = { "FORCE_SCALING_MODE_" }, value = {
240             FORCE_SCALING_MODE_AUTO,
241             FORCE_SCALING_MODE_DISABLED
242     })
243     @Retention(RetentionPolicy.SOURCE)
244     @interface ForceScalingMode {}
245 
246     /** Unique identifier of this stack. */
247     private final int mDisplayId;
248 
249     // TODO: Remove once unification is complete.
250     ActivityDisplay mAcitvityDisplay;
251 
252     /** The containers below are the only child containers the display can have. */
253     // Contains all window containers that are related to apps (Activities)
254     private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(mWmService);
255     // Contains all non-app window containers that should be displayed above the app containers
256     // (e.g. Status bar)
257     private final AboveAppWindowContainers mAboveAppWindowsContainers =
258             new AboveAppWindowContainers("mAboveAppWindowsContainers", mWmService);
259     // Contains all non-app window containers that should be displayed below the app containers
260     // (e.g. Wallpaper).
261     private final NonAppWindowContainers mBelowAppWindowsContainers =
262             new NonAppWindowContainers("mBelowAppWindowsContainers", mWmService);
263     // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
264     // on the IME target. We mainly have this container grouping so we can keep track of all the IME
265     // window containers together and move them in-sync if/when needed. We use a subclass of
266     // WindowContainer which is omitted from screen magnification, as the IME is never magnified.
267     private final NonAppWindowContainers mImeWindowsContainers =
268             new NonAppWindowContainers("mImeWindowsContainers", mWmService);
269 
270     private WindowState mTmpWindow;
271     private WindowState mTmpWindow2;
272     private boolean mTmpRecoveringMemory;
273     private boolean mUpdateImeTarget;
274     private boolean mTmpInitial;
275     private int mMaxUiWidth;
276 
277     final AppTransition mAppTransition;
278     final AppTransitionController mAppTransitionController;
279     boolean mSkipAppTransitionAnimation = false;
280 
281     final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
282     final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
283     final ArraySet<AppWindowToken> mChangingApps = new ArraySet<>();
284     final UnknownAppVisibilityController mUnknownAppVisibilityController;
285     BoundsAnimationController mBoundsAnimationController;
286 
287     private MetricsLogger mMetricsLogger;
288 
289     /**
290      * List of clients without a transtiton animation that we notify once we are done
291      * transitioning since they won't be notified through the app window animator.
292      */
293     final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
294 
295     // Mapping from a token IBinder to a WindowToken object on this display.
296     private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
297 
298     // Initial display metrics.
299     int mInitialDisplayWidth = 0;
300     int mInitialDisplayHeight = 0;
301     int mInitialDisplayDensity = 0;
302 
303     DisplayCutout mInitialDisplayCutout;
304     private final RotationCache<DisplayCutout, WmDisplayCutout> mDisplayCutoutCache
305             = new RotationCache<>(this::calculateDisplayCutoutForRotationUncached);
306 
307     /**
308      * Overridden display size. Initialized with {@link #mInitialDisplayWidth}
309      * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size".
310      * @see WindowManagerService#setForcedDisplaySize(int, int, int)
311      */
312     int mBaseDisplayWidth = 0;
313     int mBaseDisplayHeight = 0;
314     /**
315      * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity}
316      * but can be set from Settings or via shell command "adb shell wm density".
317      * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
318      */
319     int mBaseDisplayDensity = 0;
320 
321     /**
322      * Whether to disable display scaling. This can be set via shell command "adb shell wm scaling".
323      * @see WindowManagerService#setForcedDisplayScalingMode(int, int)
324      */
325     boolean mDisplayScalingDisabled;
326     private final DisplayInfo mDisplayInfo = new DisplayInfo();
327     private final Display mDisplay;
328     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
329     private final DisplayPolicy mDisplayPolicy;
330     private DisplayRotation mDisplayRotation;
331     DisplayFrames mDisplayFrames;
332 
333     private final RemoteCallbackList<ISystemGestureExclusionListener>
334             mSystemGestureExclusionListeners = new RemoteCallbackList<>();
335     private final Region mSystemGestureExclusion = new Region();
336     private boolean mSystemGestureExclusionWasRestricted = false;
337     private final Region mSystemGestureExclusionUnrestricted = new Region();
338     private int mSystemGestureExclusionLimit;
339 
340     /**
341      * For default display it contains real metrics, empty for others.
342      * @see WindowManagerService#createWatermarkInTransaction()
343      */
344     final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
345 
346     /** @see #computeCompatSmallestWidth(boolean, int, int, int) */
347     private final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
348 
349     /**
350      * Compat metrics computed based on {@link #mDisplayMetrics}.
351      * @see #updateDisplayAndOrientation(int)
352      */
353     private final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
354 
355     /** The desired scaling factor for compatible apps. */
356     float mCompatibleScreenScale;
357 
358     /**
359      * Current rotation of the display.
360      * Constants as per {@link android.view.Surface.Rotation}.
361      *
362      * @see #updateRotationUnchecked()
363      */
364     private int mRotation = 0;
365 
366     /**
367      * Last applied orientation of the display.
368      * Constants as per {@link android.content.pm.ActivityInfo.ScreenOrientation}.
369      *
370      * @see #updateOrientationFromAppTokens()
371      */
372     private int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
373 
374     /**
375      * Orientation forced by some window. If there is no visible window that specifies orientation
376      * it is set to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}.
377      *
378      * @see NonAppWindowContainers#getOrientation()
379      */
380     private int mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
381 
382     /**
383      * Last orientation forced by the keyguard. It is applied when keyguard is shown and is not
384      * occluded.
385      *
386      * @see NonAppWindowContainers#getOrientation()
387      */
388     private int mLastKeyguardForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
389 
390     /**
391      * The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. The
392      * orientation requests from apps would be ignored if the display is close-to-square.
393      */
394     @VisibleForTesting
395     final float mCloseToSquareMaxAspectRatio;
396 
397     /**
398      * If this is true, we would not rotate the display for apps. The rotation would be either the
399      * sensor rotation or the user rotation, controlled by
400      * {@link WindowManagerPolicy.UserRotationMode}.
401      */
402     private boolean mIgnoreRotationForApps;
403 
404     /**
405      * Keep track of wallpaper visibility to notify changes.
406      */
407     private boolean mLastWallpaperVisible = false;
408 
409     private Rect mBaseDisplayRect = new Rect();
410 
411     // Accessed directly by all users.
412     private boolean mLayoutNeeded;
413     int pendingLayoutChanges;
414     int mDeferredRotationPauseCount;
415 
416     /**
417      * Used to gate application window layout until we have sent the complete configuration.
418      * TODO: There are still scenarios where we may be out of sync with the client. Ideally
419      *       we want to replace this flag with a mechanism that will confirm the configuration
420      *       applied by the client is the one expected by the system server.
421      */
422     boolean mWaitingForConfig;
423 
424     // TODO(multi-display): remove some of the usages.
425     @VisibleForTesting
426     boolean isDefaultDisplay;
427 
428     /**
429      * Flag indicating whether WindowManager should override info for this display in
430      * DisplayManager.
431      */
432     boolean mShouldOverrideDisplayConfiguration = true;
433 
434     /** Window tokens that are in the process of exiting, but still on screen for animations. */
435     final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
436 
437     /** Detect user tapping outside of current focused task bounds .*/
438     @VisibleForTesting
439     final TaskTapPointerEventListener mTapDetector;
440 
441     /** Detect user tapping outside of current focused stack bounds .*/
442     private Region mTouchExcludeRegion = new Region();
443 
444     /** Save allocating when calculating rects */
445     private final Rect mTmpRect = new Rect();
446     private final Rect mTmpRect2 = new Rect();
447     private final RectF mTmpRectF = new RectF();
448     private final Matrix mTmpMatrix = new Matrix();
449     private final Region mTmpRegion = new Region();
450 
451     /** Used for handing back size of display */
452     private final Rect mTmpBounds = new Rect();
453 
454     private final Configuration mTmpConfiguration = new Configuration();
455 
456     /** Remove this display when animation on it has completed. */
457     private boolean mDeferredRemoval;
458 
459     final DockedStackDividerController mDividerControllerLocked;
460     final PinnedStackController mPinnedStackControllerLocked;
461 
462     final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
463     /** A collection of windows that provide tap exclude regions inside of them. */
464     final ArraySet<WindowState> mTapExcludeProvidingWindows = new ArraySet<>();
465 
466     private boolean mHaveBootMsg = false;
467     private boolean mHaveApp = false;
468     private boolean mHaveWallpaper = false;
469     private boolean mHaveKeyguard = true;
470 
471     private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
472 
473     private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
474             new TaskForResizePointSearchResult();
475     private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState =
476             new ApplySurfaceChangesTransactionState();
477 
478     // True if this display is in the process of being removed. Used to determine if the removal of
479     // the display's direct children should be allowed.
480     private boolean mRemovingDisplay = false;
481 
482     // {@code false} if this display is in the processing of being created.
483     private boolean mDisplayReady = false;
484 
485     WallpaperController mWallpaperController;
486 
487     boolean mWallpaperMayChange = false;
488 
489     private final SurfaceSession mSession = new SurfaceSession();
490 
491     /**
492      * Window that is currently interacting with the user. This window is responsible for receiving
493      * key events and pointer events from the user.
494      */
495     WindowState mCurrentFocus = null;
496 
497     /**
498      * The last focused window that we've notified the client that the focus is changed.
499      */
500     WindowState mLastFocus = null;
501 
502     /**
503      * Windows that have lost input focus and are waiting for the new focus window to be displayed
504      * before they are told about this.
505      */
506     ArrayList<WindowState> mLosingFocus = new ArrayList<>();
507 
508     /**
509      * The foreground app of this display. Windows below this app cannot be the focused window. If
510      * the user taps on the area outside of the task of the focused app, we will notify AM about the
511      * new task the user wants to interact with.
512      */
513     AppWindowToken mFocusedApp = null;
514 
515     /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
516     final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
517 
518     /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
519     final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
520 
521     /**
522      * We organize all top-level Surfaces in to the following layers.
523      * mOverlayLayer contains a few Surfaces which are always on top of others
524      * and omitted from Screen-Magnification, for example the strict mode flash or
525      * the magnification overlay itself.
526      * {@link #mWindowingLayer} contains everything else.
527      */
528     private SurfaceControl mOverlayLayer;
529 
530     /**
531      * See {@link #mOverlayLayer}
532      */
533     private SurfaceControl mWindowingLayer;
534 
535     /**
536      * Sequence number for the current layout pass.
537      */
538     int mLayoutSeq = 0;
539 
540     /**
541      * Specifies the count to determine whether to defer updating the IME target until ready.
542      */
543     private int mDeferUpdateImeTargetCount;
544 
545     /** Temporary float array to retrieve 3x3 matrix values. */
546     private final float[] mTmpFloats = new float[9];
547 
548     private MagnificationSpec mMagnificationSpec;
549 
550     private InputMonitor mInputMonitor;
551 
552     /** Caches the value whether told display manager that we have content. */
553     private boolean mLastHasContent;
554 
555     private DisplayRotationUtil mRotationUtil = new DisplayRotationUtil();
556 
557     /**
558      * The input method window for this display.
559      */
560     WindowState mInputMethodWindow;
561 
562     /**
563      * This just indicates the window the input method is on top of, not
564      * necessarily the window its input is going to.
565      */
566     WindowState mInputMethodTarget;
567 
568     /** If true hold off on modifying the animation layer of mInputMethodTarget */
569     boolean mInputMethodTargetWaitingAnim;
570 
571     private final PointerEventDispatcher mPointerEventDispatcher;
572 
573     private final InsetsStateController mInsetsStateController;
574 
575     /** @see #getParentWindow() */
576     private WindowState mParentWindow;
577 
578     private Point mLocationInParentWindow = new Point();
579     private SurfaceControl mParentSurfaceControl;
580     private InputWindowHandle mPortalWindowHandle;
581 
582     // Last systemUiVisibility we received from status bar.
583     private int mLastStatusBarVisibility = 0;
584     // Last systemUiVisibility we dispatched to windows.
585     private int mLastDispatchedSystemUiVisibility = 0;
586 
587     /** Corner radius that windows should have in order to match the display. */
588     private final float mWindowCornerRadius;
589 
590     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
591         WindowStateAnimator winAnimator = w.mWinAnimator;
592         final AppWindowToken atoken = w.mAppToken;
593         if (winAnimator.mDrawState == READY_TO_SHOW) {
594             if (atoken == null || atoken.canShowWindows()) {
595                 if (w.performShowLocked()) {
596                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
597                     if (DEBUG_LAYOUT_REPEATS) {
598                         mWmService.mWindowPlacerLocked.debugLayoutRepeats(
599                                 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
600                     }
601                 }
602             }
603         }
604     };
605 
606     private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> {
607         final WindowStateAnimator winAnimator = w.mWinAnimator;
608         if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
609             return;
610         }
611 
612         // If this window is animating, ensure the animation background is set.
613         final AnimationAdapter anim = w.mAppToken != null
614                 ? w.mAppToken.getAnimation()
615                 : w.getAnimation();
616         if (anim != null) {
617             final int color = anim.getBackgroundColor();
618             if (color != 0) {
619                 final TaskStack stack = w.getStack();
620                 if (stack != null) {
621                     stack.setAnimationBackground(winAnimator, color);
622                 }
623             }
624         }
625     };
626 
627     private final Consumer<WindowState> mScheduleToastTimeout = w -> {
628         final int lostFocusUid = mTmpWindow.mOwnerUid;
629         final Handler handler = mWmService.mH;
630         if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) {
631             if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) {
632                 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w),
633                         w.mAttrs.hideTimeoutMilliseconds);
634             }
635         }
636     };
637 
638     private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
639         final AppWindowToken focusedApp = mFocusedApp;
640         if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w
641                 + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys());
642 
643         if (!w.canReceiveKeys()) {
644             return false;
645         }
646 
647         final AppWindowToken wtoken = w.mAppToken;
648 
649         // If this window's application has been removed, just skip it.
650         if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
651             if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
652                     + (wtoken.removed ? "removed" : "sendingToBottom"));
653             return false;
654         }
655 
656         if (focusedApp == null) {
657             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
658                     + " using new focus @ " + w);
659             mTmpWindow = w;
660             return true;
661         }
662 
663         if (!focusedApp.windowsAreFocusable()) {
664             // Current focused app windows aren't focusable...
665             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
666                     + " focusable using new focus @ " + w);
667             mTmpWindow = w;
668             return true;
669         }
670 
671         // Descend through all of the app tokens and find the first that either matches
672         // win.mAppToken (return win) or mFocusedApp (return null).
673         if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
674             if (focusedApp.compareTo(wtoken) > 0) {
675                 // App stack below focused app stack. No focus for you!!!
676                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
677                         "findFocusedWindow: Reached focused app=" + focusedApp);
678                 mTmpWindow = null;
679                 return true;
680             }
681         }
682 
683         if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w);
684         mTmpWindow = w;
685         return true;
686     };
687 
688     private final Consumer<WindowState> mPerformLayout = w -> {
689         // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
690         // wasting time and funky changes while a window is animating away.
691         final boolean gone = (mTmpWindow != null && mWmService.mPolicy.canBeHiddenByKeyguardLw(w))
692                 || w.isGoneForLayoutLw();
693 
694         if (DEBUG_LAYOUT && !w.mLayoutAttached) {
695             Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
696                     + " mLayoutAttached=" + w.mLayoutAttached
697                     + " config reported=" + w.isLastConfigReportedToClient());
698             final AppWindowToken atoken = w.mAppToken;
699             if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
700                     + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
701                     + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
702                     + " parentHidden=" + w.isParentWindowHidden());
703             else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
704                     + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
705                     + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
706                     + " parentHidden=" + w.isParentWindowHidden());
707         }
708 
709         // If this view is GONE, then skip it -- keep the current frame, and let the caller know
710         // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
711         // since that means "perform layout as normal, just don't display").
712         if ((!gone || !w.mHaveFrame || w.mLayoutNeeded) && !w.mLayoutAttached) {
713             if (mTmpInitial) {
714                 w.resetContentChanged();
715             }
716             if (w.mAttrs.type == TYPE_DREAM) {
717                 // Don't layout windows behind a dream, so that if it does stuff like hide
718                 // the status bar we won't get a bad transition when it goes away.
719                 mTmpWindow = w;
720             }
721             w.mLayoutNeeded = false;
722             w.prelayout();
723             final boolean firstLayout = !w.isLaidOut();
724             getDisplayPolicy().layoutWindowLw(w, null, mDisplayFrames);
725             w.mLayoutSeq = mLayoutSeq;
726 
727             // If this is the first layout, we need to initialize the last inset values as
728             // otherwise we'd immediately cause an unnecessary resize.
729             if (firstLayout) {
730                 w.updateLastInsetValues();
731             }
732 
733             if (w.mAppToken != null) {
734                 w.mAppToken.layoutLetterbox(w);
735             }
736 
737             if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.getFrameLw()
738                     + " mContainingFrame=" + w.getContainingFrame()
739                     + " mDisplayFrame=" + w.getDisplayFrameLw());
740         }
741     };
742 
743     private final Consumer<WindowState> mPerformLayoutAttached = w -> {
744         if (w.mLayoutAttached) {
745             if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
746                     + " mViewVisibility=" + w.mViewVisibility
747                     + " mRelayoutCalled=" + w.mRelayoutCalled);
748             // If this view is GONE, then skip it -- keep the current frame, and let the caller
749             // know so they can ignore it if they want.  (We do the normal layout for INVISIBLE
750             // windows, since that means "perform layout as normal, just don't display").
751             if (mTmpWindow != null && mWmService.mPolicy.canBeHiddenByKeyguardLw(w)) {
752                 return;
753             }
754             if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
755                     || w.mLayoutNeeded) {
756                 if (mTmpInitial) {
757                     //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
758                     w.resetContentChanged();
759                 }
760                 w.mLayoutNeeded = false;
761                 w.prelayout();
762                 getDisplayPolicy().layoutWindowLw(w, w.getParentWindow(), mDisplayFrames);
763                 w.mLayoutSeq = mLayoutSeq;
764                 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrameLw()
765                         + " mContainingFrame=" + w.getContainingFrame()
766                         + " mDisplayFrame=" + w.getDisplayFrameLw());
767             }
768         } else if (w.mAttrs.type == TYPE_DREAM) {
769             // Don't layout windows behind a dream, so that if it does stuff like hide the
770             // status bar we won't get a bad transition when it goes away.
771             mTmpWindow = mTmpWindow2;
772         }
773     };
774 
775     private final Predicate<WindowState> mComputeImeTargetPredicate = w -> {
776         if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w
777                 + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
778         return w.canBeImeTarget();
779     };
780 
781     private final Consumer<WindowState> mApplyPostLayoutPolicy =
782             w -> getDisplayPolicy().applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
783                     mInputMethodTarget);
784 
785     private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
786         final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
787         final boolean obscuredChanged = w.mObscured !=
788                 mTmpApplySurfaceChangesTransactionState.obscured;
789         final RootWindowContainer root = mWmService.mRoot;
790 
791         // Update effect.
792         w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
793         if (!mTmpApplySurfaceChangesTransactionState.obscured) {
794             final boolean isDisplayed = w.isDisplayedLw();
795 
796             if (isDisplayed && w.isObscuringDisplay()) {
797                 // This window completely covers everything behind it, so we want to leave all
798                 // of them as undimmed (for performance reasons).
799                 root.mObscuringWindow = w;
800                 mTmpApplySurfaceChangesTransactionState.obscured = true;
801             }
802 
803             mTmpApplySurfaceChangesTransactionState.displayHasContent |=
804                     root.handleNotObscuredLocked(w,
805                             mTmpApplySurfaceChangesTransactionState.obscured,
806                             mTmpApplySurfaceChangesTransactionState.syswin);
807 
808             if (w.mHasSurface && isDisplayed) {
809                 final int type = w.mAttrs.type;
810                 if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
811                         || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
812                     mTmpApplySurfaceChangesTransactionState.syswin = true;
813                 }
814                 if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
815                         && w.mAttrs.preferredRefreshRate != 0) {
816                     mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
817                             = w.mAttrs.preferredRefreshRate;
818                 }
819                 final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy()
820                         .getPreferredModeId(w);
821                 if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
822                         && preferredModeId != 0) {
823                     mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId;
824                 }
825             }
826         }
827 
828         if (obscuredChanged && w.isVisibleLw() && mWallpaperController.isWallpaperTarget(w)) {
829             // This is the wallpaper target and its obscured state changed... make sure the
830             // current wallpaper's visibility has been updated accordingly.
831             mWallpaperController.updateWallpaperVisibility();
832         }
833 
834         w.handleWindowMovedIfNeeded();
835 
836         final WindowStateAnimator winAnimator = w.mWinAnimator;
837 
838         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
839         w.resetContentChanged();
840 
841         // Moved from updateWindowsAndWallpaperLocked().
842         if (w.mHasSurface) {
843             // Take care of the window being ready to display.
844             final boolean committed = winAnimator.commitFinishDrawingLocked();
845             if (isDefaultDisplay && committed) {
846                 if (w.mAttrs.type == TYPE_DREAM) {
847                     // HACK: When a dream is shown, it may at that point hide the lock screen.
848                     // So we need to redo the layout to let the phone window manager make this
849                     // happen.
850                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
851                     if (DEBUG_LAYOUT_REPEATS) {
852                         surfacePlacer.debugLayoutRepeats(
853                                 "dream and commitFinishDrawingLocked true",
854                                 pendingLayoutChanges);
855                     }
856                 }
857                 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
858                     if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
859                             "First draw done in potential wallpaper target " + w);
860                     mWallpaperMayChange = true;
861                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
862                     if (DEBUG_LAYOUT_REPEATS) {
863                         surfacePlacer.debugLayoutRepeats(
864                                 "wallpaper and commitFinishDrawingLocked true",
865                                 pendingLayoutChanges);
866                     }
867                 }
868             }
869         }
870 
871         final AppWindowToken atoken = w.mAppToken;
872         if (atoken != null) {
873             atoken.updateLetterboxSurface(w);
874             final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
875             if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
876                 mTmpUpdateAllDrawn.add(atoken);
877             }
878         }
879 
880         if (!mLosingFocus.isEmpty() && w.isFocused() && w.isDisplayedLw()) {
881             mWmService.mH.obtainMessage(REPORT_LOSING_FOCUS, this).sendToTarget();
882         }
883 
884         w.updateResizingWindowIfNeeded();
885     };
886 
887     /**
888      * Create new {@link DisplayContent} instance, add itself to the root window container and
889      * initialize direct children.
890      * @param display May not be null.
891      * @param service You know.
892      * @param activityDisplay The ActivityDisplay for the display container.
893      */
DisplayContent(Display display, WindowManagerService service, ActivityDisplay activityDisplay)894     DisplayContent(Display display, WindowManagerService service,
895             ActivityDisplay activityDisplay) {
896         super(service);
897         mAcitvityDisplay = activityDisplay;
898         if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) {
899             throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
900                     + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId())
901                     + " new=" + display);
902         }
903 
904         mDisplay = display;
905         mDisplayId = display.getDisplayId();
906         mWallpaperController = new WallpaperController(mWmService, this);
907         display.getDisplayInfo(mDisplayInfo);
908         display.getMetrics(mDisplayMetrics);
909         mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
910                 * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
911         isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
912         mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
913                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
914         initializeDisplayBaseInfo();
915 
916         mAppTransition = new AppTransition(service.mContext, service, this);
917         mAppTransition.registerListenerLocked(service.mActivityManagerAppTransitionNotifier);
918         mAppTransitionController = new AppTransitionController(service, this);
919         mUnknownAppVisibilityController = new UnknownAppVisibilityController(service, this);
920 
921         AnimationHandler animationHandler = new AnimationHandler();
922         mBoundsAnimationController = new BoundsAnimationController(service.mContext,
923                 mAppTransition, AnimationThread.getHandler(), animationHandler);
924 
925         final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
926                 "PointerEventDispatcher" + mDisplayId, mDisplayId);
927         mPointerEventDispatcher = new PointerEventDispatcher(inputChannel);
928 
929         // Tap Listeners are supported for:
930         // 1. All physical displays (multi-display).
931         // 2. VirtualDisplays on VR, AA (and everything else).
932         mTapDetector = new TaskTapPointerEventListener(mWmService, this);
933         registerPointerEventListener(mTapDetector);
934         registerPointerEventListener(mWmService.mMousePositionTracker);
935         if (mWmService.mAtmService.getRecentTasks() != null) {
936             registerPointerEventListener(
937                     mWmService.mAtmService.getRecentTasks().getInputListener());
938         }
939 
940         mDisplayPolicy = new DisplayPolicy(service, this);
941         mDisplayRotation = new DisplayRotation(service, this);
942         mCloseToSquareMaxAspectRatio = service.mContext.getResources().getFloat(
943                 com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio);
944         if (isDefaultDisplay) {
945             // The policy may be invoked right after here, so it requires the necessary default
946             // fields of this display content.
947             mWmService.mPolicy.setDefaultDisplay(this);
948         }
949         if (mWmService.mDisplayReady) {
950             mDisplayPolicy.onConfigurationChanged();
951         }
952         if (mWmService.mSystemReady) {
953             mDisplayPolicy.systemReady();
954         }
955         mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius();
956         mDividerControllerLocked = new DockedStackDividerController(service, this);
957         mPinnedStackControllerLocked = new PinnedStackController(service, this);
958 
959         final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession)
960                 .setOpaque(true)
961                 .setContainerLayer();
962         mWindowingLayer = b.setName("Display Root").build();
963         mOverlayLayer = b.setName("Display Overlays").build();
964 
965         getPendingTransaction().setLayer(mWindowingLayer, 0)
966                 .setLayerStack(mWindowingLayer, mDisplayId)
967                 .show(mWindowingLayer)
968                 .setLayer(mOverlayLayer, 1)
969                 .setLayerStack(mOverlayLayer, mDisplayId)
970                 .show(mOverlayLayer);
971         getPendingTransaction().apply();
972 
973         // These are the only direct children we should ever have and they are permanent.
974         super.addChild(mBelowAppWindowsContainers, null);
975         super.addChild(mTaskStackContainers, null);
976         super.addChild(mAboveAppWindowsContainers, null);
977         super.addChild(mImeWindowsContainers, null);
978 
979         // Add itself as a child to the root container.
980         mWmService.mRoot.addChild(this, null);
981 
982         // TODO(b/62541591): evaluate whether this is the best spot to declare the
983         // {@link DisplayContent} ready for use.
984         mDisplayReady = true;
985 
986         mWmService.mAnimator.addDisplayLocked(mDisplayId);
987         mInputMonitor = new InputMonitor(service, mDisplayId);
988         mInsetsStateController = new InsetsStateController(this);
989     }
990 
isReady()991     boolean isReady() {
992         // The display is ready when the system and the individual display are both ready.
993         return mWmService.mDisplayReady && mDisplayReady;
994     }
995 
getDisplayId()996     int getDisplayId() {
997         return mDisplayId;
998     }
999 
getWindowCornerRadius()1000     float getWindowCornerRadius() {
1001         return mWindowCornerRadius;
1002     }
1003 
getWindowToken(IBinder binder)1004     WindowToken getWindowToken(IBinder binder) {
1005         return mTokenMap.get(binder);
1006     }
1007 
getAppWindowToken(IBinder binder)1008     AppWindowToken getAppWindowToken(IBinder binder) {
1009         final WindowToken token = getWindowToken(binder);
1010         if (token == null) {
1011             return null;
1012         }
1013         return token.asAppWindowToken();
1014     }
1015 
addWindowToken(IBinder binder, WindowToken token)1016     private void addWindowToken(IBinder binder, WindowToken token) {
1017         final DisplayContent dc = mWmService.mRoot.getWindowTokenDisplay(token);
1018         if (dc != null) {
1019             // We currently don't support adding a window token to the display if the display
1020             // already has the binder mapped to another token. If there is a use case for supporting
1021             // this moving forward we will either need to merge the WindowTokens some how or have
1022             // the binder map to a list of window tokens.
1023             throw new IllegalArgumentException("Can't map token=" + token + " to display="
1024                     + getName() + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
1025         }
1026         if (binder == null) {
1027             throw new IllegalArgumentException("Can't map token=" + token + " to display="
1028                     + getName() + " binder is null");
1029         }
1030         if (token == null) {
1031             throw new IllegalArgumentException("Can't map null token to display="
1032                     + getName() + " binder=" + binder);
1033         }
1034 
1035         mTokenMap.put(binder, token);
1036 
1037         if (token.asAppWindowToken() == null) {
1038             // Add non-app token to container hierarchy on the display. App tokens are added through
1039             // the parent container managing them (e.g. Tasks).
1040             switch (token.windowType) {
1041                 case TYPE_WALLPAPER:
1042                     mBelowAppWindowsContainers.addChild(token);
1043                     break;
1044                 case TYPE_INPUT_METHOD:
1045                 case TYPE_INPUT_METHOD_DIALOG:
1046                     mImeWindowsContainers.addChild(token);
1047                     break;
1048                 default:
1049                     mAboveAppWindowsContainers.addChild(token);
1050                     break;
1051             }
1052         }
1053     }
1054 
removeWindowToken(IBinder binder)1055     WindowToken removeWindowToken(IBinder binder) {
1056         final WindowToken token = mTokenMap.remove(binder);
1057         if (token != null && token.asAppWindowToken() == null) {
1058             token.setExiting();
1059         }
1060         return token;
1061     }
1062 
1063     /** Changes the display the input window token is housed on to this one. */
reParentWindowToken(WindowToken token)1064     void reParentWindowToken(WindowToken token) {
1065         final DisplayContent prevDc = token.getDisplayContent();
1066         if (prevDc == this) {
1067             return;
1068         }
1069         if (prevDc != null) {
1070             if (prevDc.mTokenMap.remove(token.token) != null && token.asAppWindowToken() == null) {
1071                 // Removed the token from the map, but made sure it's not an app token before
1072                 // removing from parent.
1073                 token.getParent().removeChild(token);
1074             }
1075             if (token.hasChild(prevDc.mLastFocus)) {
1076                 // If the reparent window token contains previous display's last focus window, means
1077                 // it will end up to gain window focus on the target display, so it should not be
1078                 // notified that it lost focus from the previous display.
1079                 prevDc.mLastFocus = null;
1080             }
1081         }
1082 
1083         addWindowToken(token.token, token);
1084     }
1085 
removeAppToken(IBinder binder)1086     void removeAppToken(IBinder binder) {
1087         final WindowToken token = removeWindowToken(binder);
1088         if (token == null) {
1089             Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
1090             return;
1091         }
1092 
1093         final AppWindowToken appToken = token.asAppWindowToken();
1094 
1095         if (appToken == null) {
1096             Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
1097             return;
1098         }
1099 
1100         appToken.onRemovedFromDisplay();
1101     }
1102 
1103     @Override
getDisplay()1104     public Display getDisplay() {
1105         return mDisplay;
1106     }
1107 
getDisplayInfo()1108     DisplayInfo getDisplayInfo() {
1109         return mDisplayInfo;
1110     }
1111 
getDisplayMetrics()1112     DisplayMetrics getDisplayMetrics() {
1113         return mDisplayMetrics;
1114     }
1115 
getDisplayPolicy()1116     DisplayPolicy getDisplayPolicy() {
1117         return mDisplayPolicy;
1118     }
1119 
1120     @Override
getDisplayRotation()1121     public DisplayRotation getDisplayRotation() {
1122         return mDisplayRotation;
1123     }
1124 
1125     /**
1126      * Marks a window as providing insets for the rest of the windows in the system.
1127      *
1128      * @param type The type of inset this window provides.
1129      * @param win The window.
1130      * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of
1131      *                      the window should be taken.
1132      */
setInsetProvider(@nternalInsetType int type, WindowState win, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider)1133     void setInsetProvider(@InternalInsetType int type, WindowState win,
1134             @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
1135         mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider);
1136     }
1137 
getInsetsStateController()1138     InsetsStateController getInsetsStateController() {
1139         return mInsetsStateController;
1140     }
1141 
1142     @VisibleForTesting
setDisplayRotation(DisplayRotation displayRotation)1143     void setDisplayRotation(DisplayRotation displayRotation) {
1144         mDisplayRotation = displayRotation;
1145     }
1146 
getRotation()1147     int getRotation() {
1148         return mRotation;
1149     }
1150 
1151     @VisibleForTesting
setRotation(int newRotation)1152     void setRotation(int newRotation) {
1153         mRotation = newRotation;
1154         mDisplayRotation.setRotation(newRotation);
1155     }
1156 
getLastOrientation()1157     int getLastOrientation() {
1158         return mLastOrientation;
1159     }
1160 
getLastWindowForcedOrientation()1161     int getLastWindowForcedOrientation() {
1162         return mLastWindowForcedOrientation;
1163     }
1164 
registerRemoteAnimations(RemoteAnimationDefinition definition)1165     void registerRemoteAnimations(RemoteAnimationDefinition definition) {
1166         mAppTransitionController.registerRemoteAnimations(definition);
1167     }
1168 
1169     /**
1170      * Temporarily pauses rotation changes until resumed.
1171      *
1172      * This can be used to prevent rotation changes from occurring while the user is
1173      * performing certain operations, such as drag and drop.
1174      *
1175      * This call nests and must be matched by an equal number of calls to
1176      * {@link #resumeRotationLocked}.
1177      */
pauseRotationLocked()1178     void pauseRotationLocked() {
1179         mDeferredRotationPauseCount++;
1180     }
1181 
1182     /**
1183      * Resumes normal rotation changes after being paused.
1184      */
resumeRotationLocked()1185     void resumeRotationLocked() {
1186         if (mDeferredRotationPauseCount <= 0) {
1187             return;
1188         }
1189 
1190         mDeferredRotationPauseCount--;
1191         if (mDeferredRotationPauseCount == 0) {
1192             updateRotationAndSendNewConfigIfNeeded();
1193         }
1194     }
1195 
1196     /**
1197      * If this is true we have updated our desired orientation, but not yet changed the real
1198      * orientation our applied our screen rotation animation. For example, because a previous
1199      * screen rotation was in progress.
1200      *
1201      * @return {@code true} if the there is an ongoing rotation change.
1202      */
rotationNeedsUpdate()1203     boolean rotationNeedsUpdate() {
1204         final int lastOrientation = getLastOrientation();
1205         final int oldRotation = getRotation();
1206 
1207         final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
1208         return oldRotation != rotation;
1209     }
1210 
1211     /**
1212      * The display content may have configuration set from {@link #DisplayWindowSettings}. This
1213      * callback let the owner of container know there is existing configuration to prevent the
1214      * values from being replaced by the initializing {@link #ActivityDisplay}.
1215      */
initializeDisplayOverrideConfiguration()1216     void initializeDisplayOverrideConfiguration() {
1217         if (mAcitvityDisplay != null) {
1218             mAcitvityDisplay.onInitializeOverrideConfiguration(getRequestedOverrideConfiguration());
1219         }
1220     }
1221 
1222     /** Notify the configuration change of this display. */
sendNewConfiguration()1223     void sendNewConfiguration() {
1224         mWmService.mH.obtainMessage(SEND_NEW_CONFIGURATION, this).sendToTarget();
1225     }
1226 
1227     @Override
onDescendantOrientationChanged(IBinder freezeDisplayToken, ConfigurationContainer requestingContainer)1228     boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
1229             ConfigurationContainer requestingContainer) {
1230         final Configuration config = updateOrientationFromAppTokens(
1231                 getRequestedOverrideConfiguration(), freezeDisplayToken, false);
1232         // If display rotation class tells us that it doesn't consider app requested orientation,
1233         // this display won't rotate just because of an app changes its requested orientation. Thus
1234         // it indicates that this display chooses not to handle this request.
1235         final boolean handled = getDisplayRotation().respectAppRequestedOrientation();
1236         if (config == null) {
1237             return handled;
1238         }
1239 
1240         if (handled && requestingContainer instanceof ActivityRecord) {
1241             final ActivityRecord activityRecord = (ActivityRecord) requestingContainer;
1242             final boolean kept = mWmService.mAtmService.updateDisplayOverrideConfigurationLocked(
1243                     config, activityRecord, false /* deferResume */, getDisplayId());
1244             activityRecord.frozenBeforeDestroy = true;
1245             if (!kept) {
1246                 mWmService.mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
1247             }
1248         } else {
1249             // We have a new configuration to push so we need to update ATMS for now.
1250             // TODO: Clean up display configuration push between ATMS and WMS after unification.
1251             mWmService.mAtmService.updateDisplayOverrideConfigurationLocked(
1252                     config, null /* starting */, false /* deferResume */, getDisplayId());
1253         }
1254         return handled;
1255     }
1256 
1257     @Override
handlesOrientationChangeFromDescendant()1258     boolean handlesOrientationChangeFromDescendant() {
1259         return getDisplayRotation().respectAppRequestedOrientation();
1260     }
1261 
1262     /**
1263      * Determine the new desired orientation of this display.
1264      *
1265      * The orientation is computed from non-application windows first. If none of the
1266      * non-application windows specify orientation, the orientation is computed from application
1267      * tokens.
1268      *
1269      * @return {@code true} if the orientation is changed.
1270      */
updateOrientationFromAppTokens()1271     boolean updateOrientationFromAppTokens() {
1272         return updateOrientationFromAppTokens(false /* forceUpdate */);
1273     }
1274 
1275     /**
1276      * Update orientation of the target display, returning a non-null new Configuration if it has
1277      * changed from the current orientation. If a non-null configuration is returned, someone must
1278      * call {@link WindowManagerService#setNewDisplayOverrideConfiguration(Configuration,
1279      * DisplayContent)} to tell the window manager it can unfreeze the screen. This will typically
1280      * be done by calling {@link WindowManagerService#sendNewConfiguration(int)}.
1281      */
updateOrientationFromAppTokens(Configuration currentConfig, IBinder freezeDisplayToken, boolean forceUpdate)1282     Configuration updateOrientationFromAppTokens(Configuration currentConfig,
1283             IBinder freezeDisplayToken, boolean forceUpdate) {
1284         if (!mDisplayReady) {
1285             return null;
1286         }
1287 
1288         Configuration config = null;
1289         if (updateOrientationFromAppTokens(forceUpdate)) {
1290             // If we changed the orientation but mOrientationChangeComplete is already true,
1291             // we used seamless rotation, and we don't need to freeze the screen.
1292             if (freezeDisplayToken != null && !mWmService.mRoot.mOrientationChangeComplete) {
1293                 final AppWindowToken atoken = getAppWindowToken(freezeDisplayToken);
1294                 if (atoken != null) {
1295                     atoken.startFreezingScreen();
1296                 }
1297             }
1298             config = new Configuration();
1299             computeScreenConfiguration(config);
1300         } else if (currentConfig != null) {
1301             // No obvious action we need to take, but if our current state mismatches the
1302             // activity manager's, update it, disregarding font scale, which should remain set
1303             // to the value of the previous configuration.
1304             // Here we're calling Configuration#unset() instead of setToDefaults() because we
1305             // need to keep override configs clear of non-empty values (e.g. fontSize).
1306             mTmpConfiguration.unset();
1307             mTmpConfiguration.updateFrom(currentConfig);
1308             computeScreenConfiguration(mTmpConfiguration);
1309             if (currentConfig.diff(mTmpConfiguration) != 0) {
1310                 mWaitingForConfig = true;
1311                 setLayoutNeeded();
1312                 int[] anim = new int[2];
1313                 getDisplayPolicy().selectRotationAnimationLw(anim);
1314 
1315                 mWmService.startFreezingDisplayLocked(anim[0], anim[1], this);
1316                 config = new Configuration(mTmpConfiguration);
1317             }
1318         }
1319 
1320         return config;
1321     }
1322 
1323 
updateOrientationFromAppTokens(boolean forceUpdate)1324     private boolean updateOrientationFromAppTokens(boolean forceUpdate) {
1325         final int req = getOrientation();
1326         if (req != mLastOrientation || forceUpdate) {
1327             mLastOrientation = req;
1328             mDisplayRotation.setCurrentOrientation(req);
1329             return updateRotationUnchecked(forceUpdate);
1330         }
1331         return false;
1332     }
1333 
1334     /**
1335      * Update rotation of the display and send configuration if the rotation is changed.
1336      *
1337      * @return {@code true} if the rotation has been changed and the new config is sent.
1338      */
updateRotationAndSendNewConfigIfNeeded()1339     boolean updateRotationAndSendNewConfigIfNeeded() {
1340         final boolean changed = updateRotationUnchecked(false /* forceUpdate */);
1341         if (changed) {
1342             sendNewConfiguration();
1343         }
1344         return changed;
1345     }
1346 
1347     /**
1348      * Update rotation of the display.
1349      *
1350      * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
1351      *         {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
1352      */
updateRotationUnchecked()1353     boolean updateRotationUnchecked() {
1354         return updateRotationUnchecked(false /* forceUpdate */);
1355     }
1356 
1357     /**
1358      * Update rotation of the DisplayContent with an option to force the update. This updates
1359      * the container's perception of rotation and, depending on the top activities, will freeze
1360      * the screen or start seamless rotation. The display itself gets rotated in
1361      * {@link #applyRotationLocked} during {@link WindowManagerService#sendNewConfiguration}.
1362      *
1363      * @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating
1364      *                    orientation because we're waiting for some rotation to finish or display
1365      *                    to unfreeze, which results in configuration of the previously visible
1366      *                    activity being applied to a newly visible one. Forcing the rotation
1367      *                    update allows to workaround this issue.
1368      * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
1369      *         {@link WindowManagerService#sendNewConfiguration(int)} TO COMPLETE THE ROTATION AND
1370      *         UNFREEZE THE SCREEN.
1371      */
updateRotationUnchecked(boolean forceUpdate)1372     boolean updateRotationUnchecked(boolean forceUpdate) {
1373         ScreenRotationAnimation screenRotationAnimation;
1374         if (!forceUpdate) {
1375             if (mDeferredRotationPauseCount > 0) {
1376                 // Rotation updates have been paused temporarily.  Defer the update until
1377                 // updates have been resumed.
1378                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
1379                 return false;
1380             }
1381 
1382             screenRotationAnimation =
1383                     mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
1384             if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
1385                 // Rotation updates cannot be performed while the previous rotation change
1386                 // animation is still in progress.  Skip this update.  We will try updating
1387                 // again after the animation is finished and the display is unfrozen.
1388                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
1389                 return false;
1390             }
1391             if (mWmService.mDisplayFrozen) {
1392                 // Even if the screen rotation animation has finished (e.g. isAnimating
1393                 // returns false), there is still some time where we haven't yet unfrozen
1394                 // the display. We also need to abort rotation here.
1395                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
1396                         "Deferring rotation, still finishing previous rotation");
1397                 return false;
1398             }
1399         }
1400 
1401         if (!mWmService.mDisplayEnabled) {
1402             // No point choosing a rotation if the display is not enabled.
1403             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
1404             return false;
1405         }
1406 
1407         final int oldRotation = mRotation;
1408         final int lastOrientation = mLastOrientation;
1409         final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
1410         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id="
1411                 + mDisplayId + " based on lastOrientation=" + lastOrientation
1412                 + " and oldRotation=" + oldRotation);
1413         boolean mayRotateSeamlessly = mDisplayPolicy.shouldRotateSeamlessly(mDisplayRotation,
1414                 oldRotation, rotation);
1415 
1416         if (mayRotateSeamlessly) {
1417             final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated);
1418             if (seamlessRotated != null && !forceUpdate) {
1419                 // We can't rotate (seamlessly or not) while waiting for the last seamless rotation
1420                 // to complete (that is, waiting for windows to redraw). It's tempting to check
1421                 // w.mSeamlessRotationCount but that could be incorrect in the case of
1422                 // window-removal.
1423                 return false;
1424             }
1425 
1426             // In the presence of the PINNED stack or System Alert
1427             // windows we unfortunately can not seamlessly rotate.
1428             if (hasPinnedStack()) {
1429                 mayRotateSeamlessly = false;
1430             }
1431             for (int i = 0; i < mWmService.mSessions.size(); i++) {
1432                 if (mWmService.mSessions.valueAt(i).hasAlertWindowSurfaces()) {
1433                     mayRotateSeamlessly = false;
1434                     break;
1435                 }
1436             }
1437         }
1438         final boolean rotateSeamlessly = mayRotateSeamlessly;
1439 
1440         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
1441                 + " selected orientation " + lastOrientation
1442                 + ", got rotation " + rotation);
1443 
1444         if (oldRotation == rotation) {
1445             // No change.
1446             return false;
1447         }
1448 
1449         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
1450                 + " rotation changed to " + rotation
1451                 + " from " + oldRotation
1452                 + ", lastOrientation=" + lastOrientation);
1453 
1454         if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) {
1455             mWaitingForConfig = true;
1456         }
1457 
1458         mRotation = rotation;
1459 
1460         mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
1461         mWmService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
1462                 this, WINDOW_FREEZE_TIMEOUT_DURATION);
1463 
1464         setLayoutNeeded();
1465         final int[] anim = new int[2];
1466         mDisplayPolicy.selectRotationAnimationLw(anim);
1467 
1468         if (!rotateSeamlessly) {
1469             mWmService.startFreezingDisplayLocked(anim[0], anim[1], this);
1470             // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
1471         } else {
1472             // The screen rotation animation uses a screenshot to freeze the screen
1473             // while windows resize underneath.
1474             // When we are rotating seamlessly, we allow the elements to transition
1475             // to their rotated state independently and without a freeze required.
1476             mWmService.startSeamlessRotation();
1477         }
1478 
1479         return true;
1480     }
1481 
1482     /**
1483      * Applies the rotation transaction. This must be called after {@link #updateRotationUnchecked}
1484      * (if it returned {@code true}) to actually finish the rotation.
1485      *
1486      * @param oldRotation the rotation we are coming from.
1487      * @param rotation the rotation to apply.
1488      */
applyRotationLocked(final int oldRotation, final int rotation)1489     void applyRotationLocked(final int oldRotation, final int rotation) {
1490         mDisplayRotation.setRotation(rotation);
1491         final boolean rotateSeamlessly = mWmService.isRotatingSeamlessly();
1492         ScreenRotationAnimation screenRotationAnimation = rotateSeamlessly
1493                 ? null : mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
1494         // We need to update our screen size information to match the new rotation. If the rotation
1495         // has actually changed then this method will return true and, according to the comment at
1496         // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
1497         // By updating the Display info here it will be available to
1498         // #computeScreenConfiguration() later.
1499         updateDisplayAndOrientation(getConfiguration().uiMode, null /* outConfig */);
1500 
1501         // NOTE: We disable the rotation in the emulator because
1502         //       it doesn't support hardware OpenGL emulation yet.
1503         if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
1504                 && screenRotationAnimation.hasScreenshot()) {
1505             if (screenRotationAnimation.setRotation(getPendingTransaction(), rotation,
1506                     MAX_ANIMATION_DURATION, mWmService.getTransitionAnimationScaleLocked(),
1507                     mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
1508                 mWmService.scheduleAnimationLocked();
1509             }
1510         }
1511 
1512         forAllWindows(w -> {
1513             w.seamlesslyRotateIfAllowed(getPendingTransaction(), oldRotation, rotation,
1514                     rotateSeamlessly);
1515         }, true /* traverseTopToBottom */);
1516 
1517         mWmService.mDisplayManagerInternal.performTraversal(getPendingTransaction());
1518         scheduleAnimation();
1519 
1520         forAllWindows(w -> {
1521             if (w.mHasSurface && !rotateSeamlessly) {
1522                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
1523                 w.setOrientationChanging(true);
1524                 mWmService.mRoot.mOrientationChangeComplete = false;
1525                 w.mLastFreezeDuration = 0;
1526             }
1527             w.mReportOrientationChanged = true;
1528         }, true /* traverseTopToBottom */);
1529 
1530         if (rotateSeamlessly) {
1531             mWmService.mH.sendNewMessageDelayed(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT,
1532                     this, SEAMLESS_ROTATION_TIMEOUT_DURATION);
1533         }
1534 
1535         for (int i = mWmService.mRotationWatchers.size() - 1; i >= 0; i--) {
1536             final WindowManagerService.RotationWatcher rotationWatcher
1537                     = mWmService.mRotationWatchers.get(i);
1538             if (rotationWatcher.mDisplayId == mDisplayId) {
1539                 try {
1540                     rotationWatcher.mWatcher.onRotationChanged(rotation);
1541                 } catch (RemoteException e) {
1542                     // Ignore
1543                 }
1544             }
1545         }
1546 
1547         // Announce rotation only if we will not animate as we already have the
1548         // windows in final state. Otherwise, we make this call at the rotation end.
1549         if (screenRotationAnimation == null && mWmService.mAccessibilityController != null) {
1550             mWmService.mAccessibilityController.onRotationChangedLocked(this);
1551         }
1552     }
1553 
configureDisplayPolicy()1554     void configureDisplayPolicy() {
1555         final int width = mBaseDisplayWidth;
1556         final int height = mBaseDisplayHeight;
1557         final int shortSize;
1558         final int longSize;
1559         if (width > height) {
1560             shortSize = height;
1561             longSize = width;
1562         } else {
1563             shortSize = width;
1564             longSize = height;
1565         }
1566 
1567         final int shortSizeDp = shortSize * DENSITY_DEFAULT / mBaseDisplayDensity;
1568         final int longSizeDp = longSize * DENSITY_DEFAULT / mBaseDisplayDensity;
1569 
1570         mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
1571         mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
1572 
1573         mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
1574                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
1575 
1576         // Not much of use to rotate the display for apps since it's close to square.
1577         mIgnoreRotationForApps = isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height);
1578     }
1579 
isNonDecorDisplayCloseToSquare(int rotation, int width, int height)1580     private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) {
1581         final DisplayCutout displayCutout =
1582                 calculateDisplayCutoutForRotation(rotation).getDisplayCutout();
1583         final int uiMode = mWmService.mPolicy.getUiMode();
1584         final int w = mDisplayPolicy.getNonDecorDisplayWidth(
1585                 width, height, rotation, uiMode, displayCutout);
1586         final int h = mDisplayPolicy.getNonDecorDisplayHeight(
1587                 width, height, rotation, uiMode, displayCutout);
1588         final float aspectRatio = Math.max(w, h) / (float) Math.min(w, h);
1589         return aspectRatio <= mCloseToSquareMaxAspectRatio;
1590     }
1591 
1592     /**
1593      * Update {@link #mDisplayInfo} and other internal variables when display is rotated or config
1594      * changed.
1595      * Do not call if {@link WindowManagerService#mDisplayReady} == false.
1596      */
updateDisplayAndOrientation(int uiMode, Configuration outConfig)1597     private DisplayInfo updateDisplayAndOrientation(int uiMode, Configuration outConfig) {
1598         // Use the effective "visual" dimensions based on current rotation
1599         final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270);
1600         final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
1601         final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
1602 
1603         // Update application display metrics.
1604         final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(mRotation);
1605         final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout();
1606 
1607         final int appWidth = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode,
1608                 displayCutout);
1609         final int appHeight = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode,
1610                 displayCutout);
1611         mDisplayInfo.rotation = mRotation;
1612         mDisplayInfo.logicalWidth = dw;
1613         mDisplayInfo.logicalHeight = dh;
1614         mDisplayInfo.logicalDensityDpi = mBaseDisplayDensity;
1615         mDisplayInfo.appWidth = appWidth;
1616         mDisplayInfo.appHeight = appHeight;
1617         if (isDefaultDisplay) {
1618             mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics,
1619                     CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
1620         }
1621         mDisplayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout;
1622         mDisplayInfo.getAppMetrics(mDisplayMetrics);
1623         if (mDisplayScalingDisabled) {
1624             mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED;
1625         } else {
1626             mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
1627         }
1628 
1629         computeSizeRangesAndScreenLayout(mDisplayInfo, rotated, uiMode, dw, dh,
1630                 mDisplayMetrics.density, outConfig);
1631 
1632         // We usually set the override info in DisplayManager so that we get consistent display
1633         // metrics values when displays are changing and don't send out new values until WM is aware
1634         // of them. However, we don't do this for displays that serve as containers for ActivityView
1635         // because we don't want letter-/pillar-boxing during resize.
1636         final DisplayInfo overrideDisplayInfo = mShouldOverrideDisplayConfiguration
1637                 ? mDisplayInfo : null;
1638         mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
1639                 overrideDisplayInfo);
1640 
1641         mBaseDisplayRect.set(0, 0, dw, dh);
1642 
1643         if (isDefaultDisplay) {
1644             mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
1645                     mCompatDisplayMetrics);
1646         }
1647 
1648         return mDisplayInfo;
1649     }
1650 
calculateDisplayCutoutForRotation(int rotation)1651     WmDisplayCutout calculateDisplayCutoutForRotation(int rotation) {
1652         return mDisplayCutoutCache.getOrCompute(mInitialDisplayCutout, rotation);
1653     }
1654 
calculateDisplayCutoutForRotationUncached( DisplayCutout cutout, int rotation)1655     private WmDisplayCutout calculateDisplayCutoutForRotationUncached(
1656             DisplayCutout cutout, int rotation) {
1657         if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) {
1658             return WmDisplayCutout.NO_CUTOUT;
1659         }
1660         if (rotation == ROTATION_0) {
1661             return WmDisplayCutout.computeSafeInsets(
1662                     cutout, mInitialDisplayWidth, mInitialDisplayHeight);
1663         }
1664         final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
1665         final Rect[] newBounds = mRotationUtil.getRotatedBounds(
1666                 WmDisplayCutout.computeSafeInsets(
1667                         cutout, mInitialDisplayWidth, mInitialDisplayHeight)
1668                         .getDisplayCutout().getBoundingRectsAll(),
1669                 rotation, mInitialDisplayWidth, mInitialDisplayHeight);
1670         return WmDisplayCutout.computeSafeInsets(DisplayCutout.fromBounds(newBounds),
1671                 rotated ? mInitialDisplayHeight : mInitialDisplayWidth,
1672                 rotated ? mInitialDisplayWidth : mInitialDisplayHeight);
1673     }
1674 
1675     /**
1676      * Compute display configuration based on display properties and policy settings.
1677      * Do not call if mDisplayReady == false.
1678      */
computeScreenConfiguration(Configuration config)1679     void computeScreenConfiguration(Configuration config) {
1680         final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config);
1681         calculateBounds(displayInfo, mTmpBounds);
1682         config.windowConfiguration.setBounds(mTmpBounds);
1683 
1684         final int dw = displayInfo.logicalWidth;
1685         final int dh = displayInfo.logicalHeight;
1686         config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
1687         config.windowConfiguration.setWindowingMode(getWindowingMode());
1688         config.windowConfiguration.setDisplayWindowingMode(getWindowingMode());
1689         config.windowConfiguration.setRotation(displayInfo.rotation);
1690 
1691         final float density = mDisplayMetrics.density;
1692         config.screenWidthDp =
1693                 (int)(mDisplayPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation,
1694                         config.uiMode, displayInfo.displayCutout) / density);
1695         config.screenHeightDp =
1696                 (int)(mDisplayPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation,
1697                         config.uiMode, displayInfo.displayCutout) / density);
1698 
1699         mDisplayPolicy.getNonDecorInsetsLw(displayInfo.rotation, dw, dh,
1700                 displayInfo.displayCutout, mTmpRect);
1701         final int leftInset = mTmpRect.left;
1702         final int topInset = mTmpRect.top;
1703         // appBounds at the root level should mirror the app screen size.
1704         config.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */,
1705                 leftInset + displayInfo.appWidth /* right */,
1706                 topInset + displayInfo.appHeight /* bottom */);
1707         final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90
1708                 || displayInfo.rotation == Surface.ROTATION_270);
1709 
1710         config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
1711                 | ((displayInfo.flags & Display.FLAG_ROUND) != 0
1712                 ? Configuration.SCREENLAYOUT_ROUND_YES
1713                 : Configuration.SCREENLAYOUT_ROUND_NO);
1714 
1715         config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
1716         config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
1717         config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, dw,
1718                 dh);
1719         config.densityDpi = displayInfo.logicalDensityDpi;
1720 
1721         config.colorMode =
1722                 ((displayInfo.isHdr() && mWmService.hasHdrSupport())
1723                         ? Configuration.COLOR_MODE_HDR_YES
1724                         : Configuration.COLOR_MODE_HDR_NO)
1725                         | (displayInfo.isWideColorGamut() && mWmService.hasWideColorGamutSupport()
1726                         ? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES
1727                         : Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO);
1728 
1729         // Update the configuration based on available input devices, lid switch,
1730         // and platform configuration.
1731         config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
1732         config.keyboard = Configuration.KEYBOARD_NOKEYS;
1733         config.navigation = Configuration.NAVIGATION_NONAV;
1734 
1735         int keyboardPresence = 0;
1736         int navigationPresence = 0;
1737         final InputDevice[] devices = mWmService.mInputManager.getInputDevices();
1738         final int len = devices != null ? devices.length : 0;
1739         for (int i = 0; i < len; i++) {
1740             InputDevice device = devices[i];
1741             // Ignore virtual input device.
1742             if (device.isVirtual()) {
1743                 continue;
1744             }
1745 
1746             // Check if input device can dispatch events to current display.
1747             // If display type is virtual, will follow the default display.
1748             if (!mWmService.mInputManager.canDispatchToDisplay(device.getId(),
1749                     displayInfo.type == Display.TYPE_VIRTUAL ? DEFAULT_DISPLAY : mDisplayId)) {
1750                 continue;
1751             }
1752 
1753             final int sources = device.getSources();
1754             final int presenceFlag = device.isExternal()
1755                     ? WindowManagerPolicy.PRESENCE_EXTERNAL : WindowManagerPolicy.PRESENCE_INTERNAL;
1756 
1757             if (mWmService.mIsTouchDevice) {
1758                 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) {
1759                     config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
1760                 }
1761             } else {
1762                 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
1763             }
1764 
1765             if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
1766                 config.navigation = Configuration.NAVIGATION_TRACKBALL;
1767                 navigationPresence |= presenceFlag;
1768             } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
1769                     && config.navigation == Configuration.NAVIGATION_NONAV) {
1770                 config.navigation = Configuration.NAVIGATION_DPAD;
1771                 navigationPresence |= presenceFlag;
1772             }
1773 
1774             if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
1775                 config.keyboard = Configuration.KEYBOARD_QWERTY;
1776                 keyboardPresence |= presenceFlag;
1777             }
1778         }
1779 
1780         if (config.navigation == Configuration.NAVIGATION_NONAV && mWmService.mHasPermanentDpad) {
1781             config.navigation = Configuration.NAVIGATION_DPAD;
1782             navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
1783         }
1784 
1785         // Determine whether a hard keyboard is available and enabled.
1786         // TODO(multi-display): Should the hardware keyboard be tied to a display or to a device?
1787         boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
1788         if (hardKeyboardAvailable != mWmService.mHardKeyboardAvailable) {
1789             mWmService.mHardKeyboardAvailable = hardKeyboardAvailable;
1790             mWmService.mH.removeMessages(REPORT_HARD_KEYBOARD_STATUS_CHANGE);
1791             mWmService.mH.sendEmptyMessage(REPORT_HARD_KEYBOARD_STATUS_CHANGE);
1792         }
1793 
1794         mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
1795 
1796         // Let the policy update hidden states.
1797         config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
1798         config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
1799         config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
1800         mWmService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
1801     }
1802 
computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh)1803     private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh) {
1804         mTmpDisplayMetrics.setTo(mDisplayMetrics);
1805         final DisplayMetrics tmpDm = mTmpDisplayMetrics;
1806         final int unrotDw, unrotDh;
1807         if (rotated) {
1808             unrotDw = dh;
1809             unrotDh = dw;
1810         } else {
1811             unrotDw = dw;
1812             unrotDh = dh;
1813         }
1814         int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw,
1815                 unrotDh);
1816         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh,
1817                 unrotDw);
1818         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw,
1819                 unrotDh);
1820         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh,
1821                 unrotDw);
1822         return sw;
1823     }
1824 
reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, DisplayMetrics dm, int dw, int dh)1825     private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
1826             DisplayMetrics dm, int dw, int dh) {
1827         final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
1828                 rotation).getDisplayCutout();
1829         dm.noncompatWidthPixels = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
1830                 displayCutout);
1831         dm.noncompatHeightPixels = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode,
1832                 displayCutout);
1833         float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
1834         int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
1835         if (curSize == 0 || size < curSize) {
1836             curSize = size;
1837         }
1838         return curSize;
1839     }
1840 
computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig)1841     private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
1842             int uiMode, int dw, int dh, float density, Configuration outConfig) {
1843 
1844         // We need to determine the smallest width that will occur under normal
1845         // operation.  To this, start with the base screen size and compute the
1846         // width under the different possible rotations.  We need to un-rotate
1847         // the current screen dimensions before doing this.
1848         int unrotDw, unrotDh;
1849         if (rotated) {
1850             unrotDw = dh;
1851             unrotDh = dw;
1852         } else {
1853             unrotDw = dw;
1854             unrotDh = dh;
1855         }
1856         displayInfo.smallestNominalAppWidth = 1<<30;
1857         displayInfo.smallestNominalAppHeight = 1<<30;
1858         displayInfo.largestNominalAppWidth = 0;
1859         displayInfo.largestNominalAppHeight = 0;
1860         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh);
1861         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw);
1862         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh);
1863         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw);
1864 
1865         if (outConfig == null) {
1866             return;
1867         }
1868         int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
1869         sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode);
1870         sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode);
1871         sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode);
1872         sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode);
1873         outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
1874         outConfig.screenLayout = sl;
1875     }
1876 
reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, int uiMode)1877     private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh,
1878             int uiMode) {
1879         // Get the display cutout at this rotation.
1880         final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
1881                 rotation).getDisplayCutout();
1882 
1883         // Get the app screen size at this rotation.
1884         int w = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayCutout);
1885         int h = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayCutout);
1886 
1887         // Compute the screen layout size class for this rotation.
1888         int longSize = w;
1889         int shortSize = h;
1890         if (longSize < shortSize) {
1891             int tmp = longSize;
1892             longSize = shortSize;
1893             shortSize = tmp;
1894         }
1895         longSize = (int)(longSize/density);
1896         shortSize = (int)(shortSize/density);
1897         return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
1898     }
1899 
adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode, int dw, int dh)1900     private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation,
1901             int uiMode, int dw, int dh) {
1902         final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
1903                 rotation).getDisplayCutout();
1904         final int width = mDisplayPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode,
1905                 displayCutout);
1906         if (width < displayInfo.smallestNominalAppWidth) {
1907             displayInfo.smallestNominalAppWidth = width;
1908         }
1909         if (width > displayInfo.largestNominalAppWidth) {
1910             displayInfo.largestNominalAppWidth = width;
1911         }
1912         final int height = mDisplayPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode,
1913                 displayCutout);
1914         if (height < displayInfo.smallestNominalAppHeight) {
1915             displayInfo.smallestNominalAppHeight = height;
1916         }
1917         if (height > displayInfo.largestNominalAppHeight) {
1918             displayInfo.largestNominalAppHeight = height;
1919         }
1920     }
1921 
1922     /**
1923      * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
1924      * theme attribute) on devices that feature a physical options menu key attempt to position
1925      * their menu panel window along the edge of the screen nearest the physical menu key.
1926      * This lowers the travel distance between invoking the menu panel and selecting
1927      * a menu option.
1928      *
1929      * This method helps control where that menu is placed. Its current implementation makes
1930      * assumptions about the menu key and its relationship to the screen based on whether
1931      * the device's natural orientation is portrait (width < height) or landscape.
1932      *
1933      * The menu key is assumed to be located along the bottom edge of natural-portrait
1934      * devices and along the right edge of natural-landscape devices. If these assumptions
1935      * do not hold for the target device, this method should be changed to reflect that.
1936      *
1937      * @return A {@link Gravity} value for placing the options menu window.
1938      */
getPreferredOptionsPanelGravity()1939     int getPreferredOptionsPanelGravity() {
1940         final int rotation = getRotation();
1941         if (mInitialDisplayWidth < mInitialDisplayHeight) {
1942             // On devices with a natural orientation of portrait.
1943             switch (rotation) {
1944                 default:
1945                 case Surface.ROTATION_0:
1946                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
1947                 case Surface.ROTATION_90:
1948                     return Gravity.RIGHT | Gravity.BOTTOM;
1949                 case Surface.ROTATION_180:
1950                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
1951                 case Surface.ROTATION_270:
1952                     return Gravity.START | Gravity.BOTTOM;
1953             }
1954         }
1955 
1956         // On devices with a natural orientation of landscape.
1957         switch (rotation) {
1958             default:
1959             case Surface.ROTATION_0:
1960                 return Gravity.RIGHT | Gravity.BOTTOM;
1961             case Surface.ROTATION_90:
1962                 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
1963             case Surface.ROTATION_180:
1964                 return Gravity.START | Gravity.BOTTOM;
1965             case Surface.ROTATION_270:
1966                 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
1967         }
1968     }
1969 
getDockedDividerController()1970     DockedStackDividerController getDockedDividerController() {
1971         return mDividerControllerLocked;
1972     }
1973 
getPinnedStackController()1974     PinnedStackController getPinnedStackController() {
1975         return mPinnedStackControllerLocked;
1976     }
1977 
1978     /**
1979      * Returns true if the specified UID has access to this display.
1980      */
hasAccess(int uid)1981     boolean hasAccess(int uid) {
1982         return mDisplay.hasAccess(uid);
1983     }
1984 
isPrivate()1985     boolean isPrivate() {
1986         return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
1987     }
1988 
getHomeStack()1989     TaskStack getHomeStack() {
1990         return mTaskStackContainers.getHomeStack();
1991     }
1992 
1993     /**
1994      * @return The primary split-screen stack, but only if it is visible, and {@code null} otherwise.
1995      */
getSplitScreenPrimaryStack()1996     TaskStack getSplitScreenPrimaryStack() {
1997         TaskStack stack = mTaskStackContainers.getSplitScreenPrimaryStack();
1998         return (stack != null && stack.isVisible()) ? stack : null;
1999     }
2000 
hasSplitScreenPrimaryStack()2001     boolean hasSplitScreenPrimaryStack() {
2002         return getSplitScreenPrimaryStack() != null;
2003     }
2004 
2005     /**
2006      * Like {@link #getSplitScreenPrimaryStack}, but also returns the stack if it's currently
2007      * not visible.
2008      */
getSplitScreenPrimaryStackIgnoringVisibility()2009     TaskStack getSplitScreenPrimaryStackIgnoringVisibility() {
2010         return mTaskStackContainers.getSplitScreenPrimaryStack();
2011     }
2012 
getPinnedStack()2013     TaskStack getPinnedStack() {
2014         return mTaskStackContainers.getPinnedStack();
2015     }
2016 
hasPinnedStack()2017     private boolean hasPinnedStack() {
2018         return mTaskStackContainers.getPinnedStack() != null;
2019     }
2020 
2021     /**
2022      * Returns the topmost stack on the display that is compatible with the input windowing mode.
2023      * Null is no compatible stack on the display.
2024      */
getTopStackInWindowingMode(int windowingMode)2025     TaskStack getTopStackInWindowingMode(int windowingMode) {
2026         return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED);
2027     }
2028 
2029     /**
2030      * Returns the topmost stack on the display that is compatible with the input windowing mode and
2031      * activity type. Null is no compatible stack on the display.
2032      */
getStack(int windowingMode, int activityType)2033     TaskStack getStack(int windowingMode, int activityType) {
2034         return mTaskStackContainers.getStack(windowingMode, activityType);
2035     }
2036 
2037     @VisibleForTesting
getStacks()2038     WindowList<TaskStack> getStacks() {
2039         return mTaskStackContainers.mChildren;
2040     }
2041 
2042     @VisibleForTesting
getTopStack()2043     TaskStack getTopStack() {
2044         return mTaskStackContainers.getTopStack();
2045     }
2046 
getVisibleTasks()2047     ArrayList<Task> getVisibleTasks() {
2048         return mTaskStackContainers.getVisibleTasks();
2049     }
2050 
onStackWindowingModeChanged(TaskStack stack)2051     void onStackWindowingModeChanged(TaskStack stack) {
2052         mTaskStackContainers.onStackWindowingModeChanged(stack);
2053     }
2054 
2055     @Override
onConfigurationChanged(Configuration newParentConfig)2056     public void onConfigurationChanged(Configuration newParentConfig) {
2057         final int lastOrientation = getConfiguration().orientation;
2058         super.onConfigurationChanged(newParentConfig);
2059         if (mDisplayPolicy != null) {
2060             mDisplayPolicy.onConfigurationChanged();
2061         }
2062 
2063         if (lastOrientation != getConfiguration().orientation) {
2064             getMetricsLogger().write(
2065                     new LogMaker(MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED)
2066                     .setSubtype(getConfiguration().orientation)
2067                     .addTaggedData(MetricsEvent.FIELD_DISPLAY_ID, getDisplayId()));
2068         }
2069 
2070         // If there was no pinned stack, we still need to notify the controller of the display info
2071         // update as a result of the config change.
2072         if (mPinnedStackControllerLocked != null && !hasPinnedStack()) {
2073             mPinnedStackControllerLocked.onDisplayInfoChanged(getDisplayInfo());
2074         }
2075     }
2076 
2077     /**
2078      * Updates the resources used by docked/pinned controllers. This needs to be called at the
2079      * beginning of a configuration update cascade since the metrics from these resources are used
2080      * for bounds calculations. Since ActivityDisplay initiates the configuration update, this
2081      * should be called from there instead of DisplayContent's onConfigurationChanged.
2082      */
preOnConfigurationChanged()2083     void preOnConfigurationChanged() {
2084         final DockedStackDividerController dividerController = getDockedDividerController();
2085 
2086         if (dividerController != null) {
2087             getDockedDividerController().onConfigurationChanged();
2088         }
2089 
2090         final PinnedStackController pinnedStackController = getPinnedStackController();
2091 
2092         if (pinnedStackController != null) {
2093             getPinnedStackController().onConfigurationChanged();
2094         }
2095     }
2096 
2097     @Override
fillsParent()2098     boolean fillsParent() {
2099         return true;
2100     }
2101 
2102     @Override
isVisible()2103     boolean isVisible() {
2104         return true;
2105     }
2106 
2107     @Override
onAppTransitionDone()2108     void onAppTransitionDone() {
2109         super.onAppTransitionDone();
2110         mWmService.mWindowsChanged = true;
2111     }
2112 
2113     @Override
setWindowingMode(int windowingMode)2114     public void setWindowingMode(int windowingMode) {
2115         super.setWindowingMode(windowingMode);
2116         super.setDisplayWindowingMode(windowingMode);
2117     }
2118 
2119     @Override
setDisplayWindowingMode(int windowingMode)2120     void setDisplayWindowingMode(int windowingMode) {
2121         setWindowingMode(windowingMode);
2122     }
2123 
2124     /**
2125      * In split-screen mode we process the IME containers above the docked divider
2126      * rather than directly above their target.
2127      */
skipTraverseChild(WindowContainer child)2128     private boolean skipTraverseChild(WindowContainer child) {
2129         if (child == mImeWindowsContainers && mInputMethodTarget != null
2130                 && !hasSplitScreenPrimaryStack()) {
2131             return true;
2132         }
2133         return false;
2134     }
2135 
2136     @Override
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)2137     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
2138         // Special handling so we can process IME windows with #forAllImeWindows above their IME
2139         // target, or here in order if there isn't an IME target.
2140         if (traverseTopToBottom) {
2141             for (int i = mChildren.size() - 1; i >= 0; --i) {
2142                 final DisplayChildWindowContainer child = mChildren.get(i);
2143                 if (skipTraverseChild(child)) {
2144                     continue;
2145                 }
2146 
2147                 if (child.forAllWindows(callback, traverseTopToBottom)) {
2148                     return true;
2149                 }
2150             }
2151         } else {
2152             final int count = mChildren.size();
2153             for (int i = 0; i < count; i++) {
2154                 final DisplayChildWindowContainer child = mChildren.get(i);
2155                 if (skipTraverseChild(child)) {
2156                     continue;
2157                 }
2158 
2159                 if (child.forAllWindows(callback, traverseTopToBottom)) {
2160                     return true;
2161                 }
2162             }
2163         }
2164         return false;
2165     }
2166 
forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)2167     boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
2168         return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
2169     }
2170 
2171     @Override
getOrientation()2172     int getOrientation() {
2173         final WindowManagerPolicy policy = mWmService.mPolicy;
2174 
2175         if (mIgnoreRotationForApps) {
2176             return SCREEN_ORIENTATION_USER;
2177         }
2178 
2179         if (mWmService.mDisplayFrozen) {
2180             if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
2181                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
2182                         + " is frozen, return " + mLastWindowForcedOrientation);
2183                 // If the display is frozen, some activities may be in the middle of restarting, and
2184                 // thus have removed their old window. If the window has the flag to hide the lock
2185                 // screen, then the lock screen can re-appear and inflict its own orientation on us.
2186                 // Keep the orientation stable until this all settles down.
2187                 return mLastWindowForcedOrientation;
2188             } else if (policy.isKeyguardLocked()) {
2189                 // Use the last orientation the while the display is frozen with the keyguard
2190                 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED
2191                 // window. We don't want to check the show when locked window directly though as
2192                 // things aren't stable while the display is frozen, for example the window could be
2193                 // momentarily unavailable due to activity relaunch.
2194                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
2195                         + " is frozen while keyguard locked, return " + mLastOrientation);
2196                 return mLastOrientation;
2197             }
2198         } else {
2199             final int orientation = mAboveAppWindowsContainers.getOrientation();
2200             if (orientation != SCREEN_ORIENTATION_UNSET) {
2201                 return orientation;
2202             }
2203         }
2204 
2205         // Top system windows are not requesting an orientation. Start searching from apps.
2206         return mTaskStackContainers.getOrientation();
2207     }
2208 
updateDisplayInfo()2209     void updateDisplayInfo() {
2210         // Check if display metrics changed and update base values if needed.
2211         updateBaseDisplayMetricsIfNeeded();
2212 
2213         mDisplay.getDisplayInfo(mDisplayInfo);
2214         mDisplay.getMetrics(mDisplayMetrics);
2215 
2216         onDisplayChanged(this);
2217     }
2218 
2219     @Override
onDisplayChanged(DisplayContent dc)2220     void onDisplayChanged(DisplayContent dc) {
2221         super.onDisplayChanged(dc);
2222         updateSystemGestureExclusionLimit();
2223     }
2224 
updateSystemGestureExclusionLimit()2225     void updateSystemGestureExclusionLimit() {
2226         mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
2227                 * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
2228         updateSystemGestureExclusion();
2229     }
2230 
initializeDisplayBaseInfo()2231     void initializeDisplayBaseInfo() {
2232         final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal;
2233         if (displayManagerInternal != null) {
2234             // Bootstrap the default logical display from the display manager.
2235             final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
2236             if (newDisplayInfo != null) {
2237                 mDisplayInfo.copyFrom(newDisplayInfo);
2238             }
2239         }
2240 
2241         updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
2242                 mDisplayInfo.logicalDensityDpi);
2243         mInitialDisplayWidth = mDisplayInfo.logicalWidth;
2244         mInitialDisplayHeight = mDisplayInfo.logicalHeight;
2245         mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
2246         mInitialDisplayCutout = mDisplayInfo.displayCutout;
2247     }
2248 
2249     /**
2250      * If display metrics changed, overrides are not set and it's not just a rotation - update base
2251      * values.
2252      */
updateBaseDisplayMetricsIfNeeded()2253     private void updateBaseDisplayMetricsIfNeeded() {
2254         // Get real display metrics without overrides from WM.
2255         mWmService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo);
2256         final int orientation = mDisplayInfo.rotation;
2257         final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
2258         final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
2259         final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
2260         final int newDensity = mDisplayInfo.logicalDensityDpi;
2261         final DisplayCutout newCutout = mDisplayInfo.displayCutout;
2262 
2263         final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth
2264                 || mInitialDisplayHeight != newHeight
2265                 || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi
2266                 || !Objects.equals(mInitialDisplayCutout, newCutout);
2267 
2268         if (displayMetricsChanged) {
2269             // Check if display size or density is forced.
2270             final boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth
2271                     || mBaseDisplayHeight != mInitialDisplayHeight;
2272             final boolean isDisplayDensityForced = mBaseDisplayDensity != mInitialDisplayDensity;
2273 
2274             // If there is an override set for base values - use it, otherwise use new values.
2275             updateBaseDisplayMetrics(isDisplaySizeForced ? mBaseDisplayWidth : newWidth,
2276                     isDisplaySizeForced ? mBaseDisplayHeight : newHeight,
2277                     isDisplayDensityForced ? mBaseDisplayDensity : newDensity);
2278 
2279             // Real display metrics changed, so we should also update initial values.
2280             mInitialDisplayWidth = newWidth;
2281             mInitialDisplayHeight = newHeight;
2282             mInitialDisplayDensity = newDensity;
2283             mInitialDisplayCutout = newCutout;
2284             mWmService.reconfigureDisplayLocked(this);
2285         }
2286     }
2287 
2288     /** Sets the maximum width the screen resolution can be */
setMaxUiWidth(int width)2289     void setMaxUiWidth(int width) {
2290         if (DEBUG_DISPLAY) {
2291             Slog.v(TAG_WM, "Setting max ui width:" + width + " on display:" + getDisplayId());
2292         }
2293 
2294         mMaxUiWidth = width;
2295 
2296         // Update existing metrics.
2297         updateBaseDisplayMetrics(mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity);
2298     }
2299 
2300     /** Update base (override) display metrics. */
updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity)2301     void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) {
2302         mBaseDisplayWidth = baseWidth;
2303         mBaseDisplayHeight = baseHeight;
2304         mBaseDisplayDensity = baseDensity;
2305 
2306         if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) {
2307             mBaseDisplayHeight = (mMaxUiWidth * mBaseDisplayHeight) / mBaseDisplayWidth;
2308             mBaseDisplayDensity = (mMaxUiWidth * mBaseDisplayDensity) / mBaseDisplayWidth;
2309             mBaseDisplayWidth = mMaxUiWidth;
2310 
2311             if (DEBUG_DISPLAY) {
2312                 Slog.v(TAG_WM, "Applying config restraints:" + mBaseDisplayWidth + "x"
2313                         + mBaseDisplayHeight + " at density:" + mBaseDisplayDensity
2314                         + " on display:" + getDisplayId());
2315             }
2316         }
2317 
2318         mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
2319 
2320         updateBounds();
2321     }
2322 
2323     /**
2324      * Forces this display to use the specified density.
2325      *
2326      * @param density The density in DPI to use. If the value equals to initial density, the setting
2327      *                will be cleared.
2328      * @param userId The target user to apply. Only meaningful when this is default display. If the
2329      *               user id is {@link UserHandle#USER_CURRENT}, it means to apply current settings
2330      *               so only need to configure display.
2331      */
setForcedDensity(int density, int userId)2332     void setForcedDensity(int density, int userId) {
2333         final boolean clear = density == mInitialDisplayDensity;
2334         final boolean updateCurrent = userId == UserHandle.USER_CURRENT;
2335         if (mWmService.mCurrentUserId == userId || updateCurrent) {
2336             mBaseDisplayDensity = density;
2337             mWmService.reconfigureDisplayLocked(this);
2338         }
2339         if (updateCurrent) {
2340             // We are applying existing settings so no need to save it again.
2341             return;
2342         }
2343 
2344         if (density == mInitialDisplayDensity) {
2345             density = 0;
2346         }
2347         mWmService.mDisplayWindowSettings.setForcedDensity(this, density, userId);
2348     }
2349 
2350     /** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */
setForcedScalingMode(@orceScalingMode int mode)2351     void setForcedScalingMode(@ForceScalingMode int mode) {
2352         if (mode != FORCE_SCALING_MODE_DISABLED) {
2353             mode = FORCE_SCALING_MODE_AUTO;
2354         }
2355 
2356         mDisplayScalingDisabled = (mode != FORCE_SCALING_MODE_AUTO);
2357         Slog.i(TAG_WM, "Using display scaling mode: " + (mDisplayScalingDisabled ? "off" : "auto"));
2358         mWmService.reconfigureDisplayLocked(this);
2359 
2360         mWmService.mDisplayWindowSettings.setForcedScalingMode(this, mode);
2361     }
2362 
2363     /** If the given width and height equal to initial size, the setting will be cleared. */
setForcedSize(int width, int height)2364     void setForcedSize(int width, int height) {
2365         final boolean clear = mInitialDisplayWidth == width && mInitialDisplayHeight == height;
2366         if (!clear) {
2367             // Set some sort of reasonable bounds on the size of the display that we will try
2368             // to emulate.
2369             final int minSize = 200;
2370             final int maxScale = 2;
2371             width = Math.min(Math.max(width, minSize), mInitialDisplayWidth * maxScale);
2372             height = Math.min(Math.max(height, minSize), mInitialDisplayHeight * maxScale);
2373         }
2374 
2375         Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
2376         updateBaseDisplayMetrics(width, height, mBaseDisplayDensity);
2377         mWmService.reconfigureDisplayLocked(this);
2378 
2379         if (clear) {
2380             width = height = 0;
2381         }
2382         mWmService.mDisplayWindowSettings.setForcedSize(this, width, height);
2383     }
2384 
getStableRect(Rect out)2385     void getStableRect(Rect out) {
2386         out.set(mDisplayFrames.mStable);
2387     }
2388 
setStackOnDisplay(int stackId, boolean onTop, TaskStack stack)2389     void setStackOnDisplay(int stackId, boolean onTop, TaskStack stack) {
2390         if (DEBUG_STACK) {
2391             Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" + mDisplayId);
2392         }
2393 
2394         mTaskStackContainers.addStackToDisplay(stack, onTop);
2395     }
2396 
moveStackToDisplay(TaskStack stack, boolean onTop)2397     void moveStackToDisplay(TaskStack stack, boolean onTop) {
2398         final DisplayContent prevDc = stack.getDisplayContent();
2399         if (prevDc == null) {
2400             throw new IllegalStateException("Trying to move stackId=" + stack.mStackId
2401                     + " which is not currently attached to any display");
2402         }
2403         if (prevDc.getDisplayId() == mDisplayId) {
2404             throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId
2405                     + " to its current displayId=" + mDisplayId);
2406         }
2407 
2408         prevDc.mTaskStackContainers.removeChild(stack);
2409         mTaskStackContainers.addStackToDisplay(stack, onTop);
2410     }
2411 
2412     @Override
addChild(DisplayChildWindowContainer child, Comparator<DisplayChildWindowContainer> comparator)2413     protected void addChild(DisplayChildWindowContainer child,
2414             Comparator<DisplayChildWindowContainer> comparator) {
2415         throw new UnsupportedOperationException("See DisplayChildWindowContainer");
2416     }
2417 
2418     @Override
addChild(DisplayChildWindowContainer child, int index)2419     protected void addChild(DisplayChildWindowContainer child, int index) {
2420         throw new UnsupportedOperationException("See DisplayChildWindowContainer");
2421     }
2422 
2423     @Override
removeChild(DisplayChildWindowContainer child)2424     protected void removeChild(DisplayChildWindowContainer child) {
2425         // Only allow removal of direct children from this display if the display is in the process
2426         // of been removed.
2427         if (mRemovingDisplay) {
2428             super.removeChild(child);
2429             return;
2430         }
2431         throw new UnsupportedOperationException("See DisplayChildWindowContainer");
2432     }
2433 
2434     @Override
positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents)2435     void positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents) {
2436         // Children of the display are statically ordered, so the real intention here is to perform
2437         // the operation on the display and not the static direct children.
2438         getParent().positionChildAt(position, this, includingParents);
2439     }
2440 
positionStackAt(int position, TaskStack child, boolean includingParents)2441     void positionStackAt(int position, TaskStack child, boolean includingParents) {
2442         mTaskStackContainers.positionChildAt(position, child, includingParents);
2443         layoutAndAssignWindowLayersIfNeeded();
2444     }
2445 
2446     /**
2447      * Returns true if the input point is within an app window.
2448      */
pointWithinAppWindow(int x, int y)2449     boolean pointWithinAppWindow(int x, int y) {
2450         final int[] targetWindowType = {-1};
2451         final Consumer fn = PooledLambda.obtainConsumer((w, nonArg) -> {
2452             if (targetWindowType[0] != -1) {
2453                 return;
2454             }
2455 
2456             if (w.isOnScreen() && w.isVisibleLw() && w.getFrameLw().contains(x, y)) {
2457                 targetWindowType[0] = w.mAttrs.type;
2458                 return;
2459             }
2460         }, PooledLambda.__(WindowState.class), mTmpRect);
2461         forAllWindows(fn, true /* traverseTopToBottom */);
2462         ((PooledConsumer) fn).recycle();
2463         return FIRST_APPLICATION_WINDOW <= targetWindowType[0]
2464                         && targetWindowType[0] <= LAST_APPLICATION_WINDOW;
2465     }
2466 
2467     /**
2468      * Find the task whose outside touch area (for resizing) (x, y) falls within.
2469      * Returns null if the touch doesn't fall into a resizing area.
2470      */
findTaskForResizePoint(int x, int y)2471     Task findTaskForResizePoint(int x, int y) {
2472         final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
2473         mTmpTaskForResizePointSearchResult.reset();
2474         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2475             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
2476             if (!stack.getWindowConfiguration().canResizeTask()) {
2477                 return null;
2478             }
2479 
2480             stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult);
2481             if (mTmpTaskForResizePointSearchResult.searchDone) {
2482                 return mTmpTaskForResizePointSearchResult.taskForResize;
2483             }
2484         }
2485         return null;
2486     }
2487 
updateTouchExcludeRegion()2488     void updateTouchExcludeRegion() {
2489         final Task focusedTask = (mFocusedApp != null ? mFocusedApp.getTask() : null);
2490         if (focusedTask == null) {
2491             mTouchExcludeRegion.setEmpty();
2492         } else {
2493             mTouchExcludeRegion.set(mBaseDisplayRect);
2494             final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
2495             mTmpRect2.setEmpty();
2496             for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0;
2497                     --stackNdx) {
2498                 final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
2499                 stack.setTouchExcludeRegion(focusedTask, delta, mTouchExcludeRegion,
2500                         mDisplayFrames.mContent, mTmpRect2);
2501             }
2502             // If we removed the focused task above, add it back and only leave its
2503             // outside touch area in the exclusion. TapDetector is not interested in
2504             // any touch inside the focused task itself.
2505             if (!mTmpRect2.isEmpty()) {
2506                 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
2507             }
2508         }
2509         if (mInputMethodWindow != null && mInputMethodWindow.isVisibleLw()) {
2510             // If the input method is visible and the user is typing, we don't want these touch
2511             // events to be intercepted and used to change focus. This would likely cause a
2512             // disappearance of the input method.
2513             mInputMethodWindow.getTouchableRegion(mTmpRegion);
2514             mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
2515         }
2516         for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
2517             final WindowState win = mTapExcludedWindows.get(i);
2518             win.getTouchableRegion(mTmpRegion);
2519             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
2520         }
2521         amendWindowTapExcludeRegion(mTouchExcludeRegion);
2522         // TODO(multi-display): Support docked stacks on secondary displays.
2523         if (mDisplayId == DEFAULT_DISPLAY && getSplitScreenPrimaryStack() != null) {
2524             mDividerControllerLocked.getTouchRegion(mTmpRect);
2525             mTmpRegion.set(mTmpRect);
2526             mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
2527         }
2528         mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
2529     }
2530 
2531     /**
2532      * Union the region with all the tap exclude region provided by windows on this display.
2533      *
2534      * @param inOutRegion The region to be amended.
2535      */
amendWindowTapExcludeRegion(Region inOutRegion)2536     void amendWindowTapExcludeRegion(Region inOutRegion) {
2537         for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
2538             final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
2539             win.amendTapExcludeRegion(inOutRegion);
2540         }
2541     }
2542 
2543     @Override
switchUser()2544     void switchUser() {
2545         super.switchUser();
2546         mWmService.mWindowsChanged = true;
2547         mDisplayPolicy.switchUser();
2548     }
2549 
resetAnimationBackgroundAnimator()2550     private void resetAnimationBackgroundAnimator() {
2551         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2552             mTaskStackContainers.getChildAt(stackNdx).resetAnimationBackgroundAnimator();
2553         }
2554     }
2555 
2556     @Override
removeIfPossible()2557     void removeIfPossible() {
2558         if (isAnimating()) {
2559             mDeferredRemoval = true;
2560             return;
2561         }
2562         removeImmediately();
2563     }
2564 
2565     @Override
removeImmediately()2566     void removeImmediately() {
2567         mRemovingDisplay = true;
2568         try {
2569             if (mParentWindow != null) {
2570                 mParentWindow.removeEmbeddedDisplayContent(this);
2571             }
2572             // Clear all transitions & screen frozen states when removing display.
2573             mOpeningApps.clear();
2574             mClosingApps.clear();
2575             mChangingApps.clear();
2576             mUnknownAppVisibilityController.clear();
2577             mAppTransition.removeAppTransitionTimeoutCallbacks();
2578             handleAnimatingStoppedAndTransition();
2579             mWmService.stopFreezingDisplayLocked();
2580             super.removeImmediately();
2581             if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
2582             mPointerEventDispatcher.dispose();
2583             mWmService.mAnimator.removeDisplayLocked(mDisplayId);
2584             mWindowingLayer.release();
2585             mOverlayLayer.release();
2586             mInputMonitor.onDisplayRemoved();
2587         } finally {
2588             mDisplayReady = false;
2589             mRemovingDisplay = false;
2590         }
2591 
2592         mWmService.mWindowPlacerLocked.requestTraversal();
2593     }
2594 
2595     /** Returns true if a removal action is still being deferred. */
2596     @Override
checkCompleteDeferredRemoval()2597     boolean checkCompleteDeferredRemoval() {
2598         final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
2599 
2600         if (!stillDeferringRemoval && mDeferredRemoval) {
2601             removeImmediately();
2602             return false;
2603         }
2604         return true;
2605     }
2606 
2607     /** @return 'true' if removal of this display content is deferred due to active animation. */
isRemovalDeferred()2608     boolean isRemovalDeferred() {
2609         return mDeferredRemoval;
2610     }
2611 
animateForIme(float interpolatedValue, float animationTarget, float dividerAnimationTarget)2612     boolean animateForIme(float interpolatedValue, float animationTarget,
2613             float dividerAnimationTarget) {
2614         boolean updated = false;
2615 
2616         for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
2617             final TaskStack stack = mTaskStackContainers.getChildAt(i);
2618             if (stack == null || !stack.isAdjustedForIme()) {
2619                 continue;
2620             }
2621 
2622             if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) {
2623                 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
2624                 updated = true;
2625             } else {
2626                 mDividerControllerLocked.mLastAnimationProgress =
2627                         mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue);
2628                 mDividerControllerLocked.mLastDividerProgress =
2629                         mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue);
2630                 updated |= stack.updateAdjustForIme(
2631                         mDividerControllerLocked.mLastAnimationProgress,
2632                         mDividerControllerLocked.mLastDividerProgress,
2633                         false /* force */);
2634             }
2635             if (interpolatedValue >= 1f) {
2636                 stack.endImeAdjustAnimation();
2637             }
2638         }
2639 
2640         return updated;
2641     }
2642 
clearImeAdjustAnimation()2643     boolean clearImeAdjustAnimation() {
2644         boolean changed = false;
2645         for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
2646             final TaskStack stack = mTaskStackContainers.getChildAt(i);
2647             if (stack != null && stack.isAdjustedForIme()) {
2648                 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
2649                 changed  = true;
2650             }
2651         }
2652         return changed;
2653     }
2654 
beginImeAdjustAnimation()2655     void beginImeAdjustAnimation() {
2656         for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
2657             final TaskStack stack = mTaskStackContainers.getChildAt(i);
2658             if (stack.isVisible() && stack.isAdjustedForIme()) {
2659                 stack.beginImeAdjustAnimation();
2660             }
2661         }
2662     }
2663 
adjustForImeIfNeeded()2664     void adjustForImeIfNeeded() {
2665         final WindowState imeWin = mInputMethodWindow;
2666         final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
2667                 && !mDividerControllerLocked.isImeHideRequested();
2668         final TaskStack dockedStack = getSplitScreenPrimaryStack();
2669         final boolean dockVisible = dockedStack != null;
2670         final Task topDockedTask = dockVisible ? dockedStack.getTopChild() : null;
2671         final TaskStack imeTargetStack = mWmService.getImeFocusStackLocked();
2672         final int imeDockSide = (dockVisible && imeTargetStack != null) ?
2673                 imeTargetStack.getDockSide() : DOCKED_INVALID;
2674         final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
2675         final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
2676         final int imeHeight = mDisplayFrames.getInputMethodWindowVisibleHeight();
2677         final boolean imeHeightChanged = imeVisible &&
2678                 imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
2679 
2680         // This includes a case where the docked stack is unminimizing and IME is visible for the
2681         // bottom side stack. The condition prevents adjusting the override task bounds for IME to
2682         // the minimized docked stack bounds.
2683         final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock()
2684                 || (topDockedTask != null && imeOnBottom && !dockedStack.isAdjustedForIme()
2685                         && dockedStack.getBounds().height() < topDockedTask.getBounds().height());
2686 
2687         // The divider could be adjusted for IME position, or be thinner than usual,
2688         // or both. There are three possible cases:
2689         // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
2690         // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
2691         // - If IME is not visible, divider is not moved and is normal width.
2692 
2693         if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
2694             for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
2695                 final TaskStack stack = mTaskStackContainers.getChildAt(i);
2696                 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
2697                 if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)
2698                         && stack.inSplitScreenWindowingMode()) {
2699                     stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
2700                 } else {
2701                     stack.resetAdjustedForIme(false);
2702                 }
2703             }
2704             mDividerControllerLocked.setAdjustedForIme(
2705                     imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
2706         } else {
2707             for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
2708                 final TaskStack stack = mTaskStackContainers.getChildAt(i);
2709                 stack.resetAdjustedForIme(!dockVisible);
2710             }
2711             mDividerControllerLocked.setAdjustedForIme(
2712                     false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
2713         }
2714         mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
2715     }
2716 
prepareFreezingTaskBounds()2717     void prepareFreezingTaskBounds() {
2718         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2719             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
2720             stack.prepareFreezingTaskBounds();
2721         }
2722     }
2723 
rotateBounds(int oldRotation, int newRotation, Rect bounds)2724     void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
2725         getBounds(mTmpRect, newRotation);
2726         rotateBounds(mTmpRect, oldRotation, newRotation, bounds);
2727     }
2728 
rotateBounds(Rect parentBounds, int oldRotation, int newRotation, Rect bounds)2729     void rotateBounds(Rect parentBounds, int oldRotation, int newRotation, Rect bounds) {
2730         // Compute a transform matrix to undo the coordinate space transformation,
2731         // and present the window at the same physical position it previously occupied.
2732         final int deltaRotation = deltaRotation(newRotation, oldRotation);
2733         createRotationMatrix(
2734                 deltaRotation, parentBounds.width(), parentBounds.height(), mTmpMatrix);
2735 
2736         mTmpRectF.set(bounds);
2737         mTmpMatrix.mapRect(mTmpRectF);
2738         mTmpRectF.round(bounds);
2739     }
2740 
deltaRotation(int oldRotation, int newRotation)2741     static int deltaRotation(int oldRotation, int newRotation) {
2742         int delta = newRotation - oldRotation;
2743         if (delta < 0) delta += 4;
2744         return delta;
2745     }
2746 
createRotationMatrix(int rotation, float displayWidth, float displayHeight, Matrix outMatrix)2747     private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
2748             Matrix outMatrix) {
2749         // For rotations without Z-ordering we don't need the target rectangle's position.
2750         createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
2751                 displayHeight, outMatrix);
2752     }
2753 
createRotationMatrix(int rotation, float rectLeft, float rectTop, float displayWidth, float displayHeight, Matrix outMatrix)2754     static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
2755             float displayWidth, float displayHeight, Matrix outMatrix) {
2756         switch (rotation) {
2757             case ROTATION_0:
2758                 outMatrix.reset();
2759                 break;
2760             case ROTATION_270:
2761                 outMatrix.setRotate(270, 0, 0);
2762                 outMatrix.postTranslate(0, displayHeight);
2763                 outMatrix.postTranslate(rectTop, 0);
2764                 break;
2765             case ROTATION_180:
2766                 outMatrix.reset();
2767                 break;
2768             case ROTATION_90:
2769                 outMatrix.setRotate(90, 0, 0);
2770                 outMatrix.postTranslate(displayWidth, 0);
2771                 outMatrix.postTranslate(-rectTop, rectLeft);
2772                 break;
2773         }
2774     }
2775 
2776     @CallSuper
2777     @Override
writeToProto(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)2778     public void writeToProto(ProtoOutputStream proto, long fieldId,
2779             @WindowTraceLogLevel int logLevel) {
2780         // Critical log level logs only visible elements to mitigate performance overheard
2781         if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
2782             return;
2783         }
2784 
2785         final long token = proto.start(fieldId);
2786         super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
2787         proto.write(ID, mDisplayId);
2788         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2789             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
2790             stack.writeToProto(proto, STACKS, logLevel);
2791         }
2792         mDividerControllerLocked.writeToProto(proto, DOCKED_STACK_DIVIDER_CONTROLLER);
2793         mPinnedStackControllerLocked.writeToProto(proto, PINNED_STACK_CONTROLLER);
2794         for (int i = mAboveAppWindowsContainers.getChildCount() - 1; i >= 0; --i) {
2795             final WindowToken windowToken = mAboveAppWindowsContainers.getChildAt(i);
2796             windowToken.writeToProto(proto, ABOVE_APP_WINDOWS, logLevel);
2797         }
2798         for (int i = mBelowAppWindowsContainers.getChildCount() - 1; i >= 0; --i) {
2799             final WindowToken windowToken = mBelowAppWindowsContainers.getChildAt(i);
2800             windowToken.writeToProto(proto, BELOW_APP_WINDOWS, logLevel);
2801         }
2802         for (int i = mImeWindowsContainers.getChildCount() - 1; i >= 0; --i) {
2803             final WindowToken windowToken = mImeWindowsContainers.getChildAt(i);
2804             windowToken.writeToProto(proto, IME_WINDOWS, logLevel);
2805         }
2806         proto.write(DPI, mBaseDisplayDensity);
2807         mDisplayInfo.writeToProto(proto, DISPLAY_INFO);
2808         proto.write(ROTATION, mRotation);
2809         final ScreenRotationAnimation screenRotationAnimation =
2810                 mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
2811         if (screenRotationAnimation != null) {
2812             screenRotationAnimation.writeToProto(proto, SCREEN_ROTATION_ANIMATION);
2813         }
2814         mDisplayFrames.writeToProto(proto, DISPLAY_FRAMES);
2815         mAppTransition.writeToProto(proto, APP_TRANSITION);
2816         if (mFocusedApp != null) {
2817             mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
2818         }
2819         for (int i = mOpeningApps.size() - 1; i >= 0; i--) {
2820             mOpeningApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, OPENING_APPS);
2821         }
2822         for (int i = mClosingApps.size() - 1; i >= 0; i--) {
2823             mClosingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CLOSING_APPS);
2824         }
2825         for (int i = mChangingApps.size() - 1; i >= 0; i--) {
2826             mChangingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CHANGING_APPS);
2827         }
2828         proto.end(token);
2829     }
2830 
2831     @Override
dump(PrintWriter pw, String prefix, boolean dumpAll)2832     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2833         super.dump(pw, prefix, dumpAll);
2834         pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
2835         final String subPrefix = "  " + prefix;
2836         pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
2837             pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
2838             pw.print("dpi");
2839             if (mInitialDisplayWidth != mBaseDisplayWidth
2840                     || mInitialDisplayHeight != mBaseDisplayHeight
2841                     || mInitialDisplayDensity != mBaseDisplayDensity) {
2842                 pw.print(" base=");
2843                 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
2844                 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
2845             }
2846             if (mDisplayScalingDisabled) {
2847                 pw.println(" noscale");
2848             }
2849             pw.print(" cur=");
2850             pw.print(mDisplayInfo.logicalWidth);
2851             pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
2852             pw.print(" app=");
2853             pw.print(mDisplayInfo.appWidth);
2854             pw.print("x"); pw.print(mDisplayInfo.appHeight);
2855             pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
2856             pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
2857             pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
2858             pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
2859             pw.print(subPrefix + "deferred=" + mDeferredRemoval
2860                     + " mLayoutNeeded=" + mLayoutNeeded);
2861             pw.println(" mTouchExcludeRegion=" + mTouchExcludeRegion);
2862 
2863         pw.println();
2864         pw.print(prefix); pw.print("mLayoutSeq="); pw.println(mLayoutSeq);
2865         pw.print(prefix);
2866         pw.print("mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
2867 
2868         pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
2869         if (mLastFocus != mCurrentFocus) {
2870             pw.print("  mLastFocus="); pw.println(mLastFocus);
2871         }
2872         if (mLosingFocus.size() > 0) {
2873             pw.println();
2874             pw.println("  Windows losing focus:");
2875             for (int i = mLosingFocus.size() - 1; i >= 0; i--) {
2876                 final WindowState w = mLosingFocus.get(i);
2877                 pw.print("  Losing #"); pw.print(i); pw.print(' ');
2878                 pw.print(w);
2879                 if (dumpAll) {
2880                     pw.println(":");
2881                     w.dump(pw, "    ", true);
2882                 } else {
2883                     pw.println();
2884                 }
2885             }
2886         }
2887         pw.print("  mFocusedApp="); pw.println(mFocusedApp);
2888         if (mLastStatusBarVisibility != 0) {
2889             pw.print("  mLastStatusBarVisibility=0x");
2890             pw.println(Integer.toHexString(mLastStatusBarVisibility));
2891         }
2892 
2893         pw.println();
2894         mWallpaperController.dump(pw, "  ");
2895 
2896         pw.println();
2897         pw.print("mSystemGestureExclusion=");
2898         if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() > 0) {
2899             pw.println(mSystemGestureExclusion);
2900         } else {
2901             pw.println("<no lstnrs>");
2902         }
2903 
2904         pw.println();
2905         pw.println(prefix + "Application tokens in top down Z order:");
2906         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2907             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
2908             stack.dump(pw, prefix + "  ", dumpAll);
2909         }
2910 
2911         pw.println();
2912         if (!mExitingTokens.isEmpty()) {
2913             pw.println();
2914             pw.println("  Exiting tokens:");
2915             for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
2916                 final WindowToken token = mExitingTokens.get(i);
2917                 pw.print("  Exiting #"); pw.print(i);
2918                 pw.print(' '); pw.print(token);
2919                 pw.println(':');
2920                 token.dump(pw, "    ", dumpAll);
2921             }
2922         }
2923 
2924         pw.println();
2925 
2926         // Dump stack references
2927         final TaskStack homeStack = getHomeStack();
2928         if (homeStack != null) {
2929             pw.println(prefix + "homeStack=" + homeStack.getName());
2930         }
2931         final TaskStack pinnedStack = getPinnedStack();
2932         if (pinnedStack != null) {
2933             pw.println(prefix + "pinnedStack=" + pinnedStack.getName());
2934         }
2935         final TaskStack splitScreenPrimaryStack = getSplitScreenPrimaryStack();
2936         if (splitScreenPrimaryStack != null) {
2937             pw.println(prefix + "splitScreenPrimaryStack=" + splitScreenPrimaryStack.getName());
2938         }
2939 
2940         pw.println();
2941         mDividerControllerLocked.dump(prefix, pw);
2942         pw.println();
2943         mPinnedStackControllerLocked.dump(prefix, pw);
2944 
2945         pw.println();
2946         mDisplayFrames.dump(prefix, pw);
2947         pw.println();
2948         mDisplayPolicy.dump(prefix, pw);
2949         pw.println();
2950         mDisplayRotation.dump(prefix, pw);
2951         pw.println();
2952         mInputMonitor.dump(pw, "  ");
2953         pw.println();
2954         mInsetsStateController.dump(prefix, pw);
2955     }
2956 
2957     @Override
toString()2958     public String toString() {
2959         return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren;
2960     }
2961 
getName()2962     String getName() {
2963         return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
2964     }
2965 
2966     /** Returns true if the stack in the windowing mode is visible. */
isStackVisible(int windowingMode)2967     boolean isStackVisible(int windowingMode) {
2968         final TaskStack stack = getTopStackInWindowingMode(windowingMode);
2969         return stack != null && stack.isVisible();
2970     }
2971 
2972     /** Find the visible, touch-deliverable window under the given point */
getTouchableWinAtPointLocked(float xf, float yf)2973     WindowState getTouchableWinAtPointLocked(float xf, float yf) {
2974         final int x = (int) xf;
2975         final int y = (int) yf;
2976         final WindowState touchedWin = getWindow(w -> {
2977             final int flags = w.mAttrs.flags;
2978             if (!w.isVisibleLw()) {
2979                 return false;
2980             }
2981             if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
2982                 return false;
2983             }
2984 
2985             w.getVisibleBounds(mTmpRect);
2986             if (!mTmpRect.contains(x, y)) {
2987                 return false;
2988             }
2989 
2990             w.getTouchableRegion(mTmpRegion);
2991 
2992             final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
2993             return mTmpRegion.contains(x, y) || touchFlags == 0;
2994         });
2995 
2996         return touchedWin;
2997     }
2998 
canAddToastWindowForUid(int uid)2999     boolean canAddToastWindowForUid(int uid) {
3000         // We allow one toast window per UID being shown at a time.
3001         // Also if the app is focused adding more than one toast at
3002         // a time for better backwards compatibility.
3003         final WindowState focusedWindowForUid = getWindow(w ->
3004                 w.mOwnerUid == uid && w.isFocused());
3005         if (focusedWindowForUid != null) {
3006             return true;
3007         }
3008         final WindowState win = getWindow(w ->
3009                 w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden
3010                 && !w.mWindowRemovalAllowed);
3011         return win == null;
3012     }
3013 
scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus)3014     void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
3015         if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
3016             return;
3017         }
3018 
3019         // Used to communicate the old focus to the callback method.
3020         mTmpWindow = oldFocus;
3021 
3022         forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */);
3023     }
3024 
3025     /**
3026      * Looking for the focused window on this display if the top focused display hasn't been
3027      * found yet (topFocusedDisplayId is INVALID_DISPLAY) or per-display focused was allowed.
3028      *
3029      * @param topFocusedDisplayId Id of the top focused display.
3030      * @return The focused window or null if there isn't any or no need to seek.
3031      */
findFocusedWindowIfNeeded(int topFocusedDisplayId)3032     WindowState findFocusedWindowIfNeeded(int topFocusedDisplayId) {
3033         return (mWmService.mPerDisplayFocusEnabled || topFocusedDisplayId == INVALID_DISPLAY)
3034                 ? findFocusedWindow() : null;
3035     }
3036 
findFocusedWindow()3037     WindowState findFocusedWindow() {
3038         mTmpWindow = null;
3039 
3040         forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */);
3041 
3042         if (mTmpWindow == null) {
3043             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
3044             return null;
3045         }
3046         return mTmpWindow;
3047     }
3048 
3049     /**
3050      * Update the focused window and make some adjustments if the focus has changed.
3051      *
3052      * @param mode Indicates the situation we are in. Possible modes are:
3053      *             {@link WindowManagerService#UPDATE_FOCUS_NORMAL},
3054      *             {@link WindowManagerService#UPDATE_FOCUS_PLACING_SURFACES},
3055      *             {@link WindowManagerService#UPDATE_FOCUS_WILL_PLACE_SURFACES},
3056      *             {@link WindowManagerService#UPDATE_FOCUS_REMOVING_FOCUS}
3057      * @param updateInputWindows Whether to sync the window information to the input module.
3058      * @param topFocusedDisplayId Display id of current top focused display.
3059      * @return {@code true} if the focused window has changed.
3060      */
updateFocusedWindowLocked(int mode, boolean updateInputWindows, int topFocusedDisplayId)3061     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows,
3062             int topFocusedDisplayId) {
3063         WindowState newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
3064         if (mCurrentFocus == newFocus) {
3065             return false;
3066         }
3067         boolean imWindowChanged = false;
3068         final WindowState imWindow = mInputMethodWindow;
3069         if (imWindow != null) {
3070             final WindowState prevTarget = mInputMethodTarget;
3071             final WindowState newTarget = computeImeTarget(true /* updateImeTarget*/);
3072             imWindowChanged = prevTarget != newTarget;
3073 
3074             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
3075                     && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
3076                 assignWindowLayers(false /* setLayoutNeeded */);
3077             }
3078         }
3079 
3080         if (imWindowChanged) {
3081             mWmService.mWindowsChanged = true;
3082             setLayoutNeeded();
3083             newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
3084         }
3085         if (mCurrentFocus != newFocus) {
3086             mWmService.mH.obtainMessage(REPORT_FOCUS_CHANGE, this).sendToTarget();
3087         }
3088 
3089         if (DEBUG_FOCUS_LIGHT || mWmService.localLOGV) Slog.v(TAG_WM, "Changing focus from "
3090                 + mCurrentFocus + " to " + newFocus + " displayId=" + getDisplayId()
3091                 + " Callers=" + Debug.getCallers(4));
3092         final WindowState oldFocus = mCurrentFocus;
3093         mCurrentFocus = newFocus;
3094         mLosingFocus.remove(newFocus);
3095 
3096         if (newFocus != null) {
3097             mWinAddedSinceNullFocus.clear();
3098             mWinRemovedSinceNullFocus.clear();
3099 
3100             if (newFocus.canReceiveKeys()) {
3101                 // Displaying a window implicitly causes dispatching to be unpaused.
3102                 // This is to protect against bugs if someone pauses dispatching but
3103                 // forgets to resume.
3104                 newFocus.mToken.paused = false;
3105             }
3106         }
3107 
3108         int focusChanged = getDisplayPolicy().focusChangedLw(oldFocus, newFocus);
3109 
3110         if (imWindowChanged && oldFocus != mInputMethodWindow) {
3111             // Focus of the input method window changed. Perform layout if needed.
3112             if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
3113                 performLayout(true /*initial*/,  updateInputWindows);
3114                 focusChanged &= ~FINISH_LAYOUT_REDO_LAYOUT;
3115             } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
3116                 // Client will do the layout, but we need to assign layers
3117                 // for handleNewWindowLocked() below.
3118                 assignWindowLayers(false /* setLayoutNeeded */);
3119             }
3120         }
3121 
3122         if ((focusChanged & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
3123             // The change in focus caused us to need to do a layout.  Okay.
3124             setLayoutNeeded();
3125             if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
3126                 performLayout(true /*initial*/, updateInputWindows);
3127             } else if (mode == UPDATE_FOCUS_REMOVING_FOCUS) {
3128                 mWmService.mRoot.performSurfacePlacement(false);
3129             }
3130         }
3131 
3132         if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
3133             // If we defer assigning layers, then the caller is responsible for doing this part.
3134             getInputMonitor().setInputFocusLw(newFocus, updateInputWindows);
3135         }
3136 
3137         adjustForImeIfNeeded();
3138 
3139         // We may need to schedule some toast windows to be removed. The toasts for an app that
3140         // does not have input focus are removed within a timeout to prevent apps to redress
3141         // other apps' UI.
3142         scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus);
3143 
3144         if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
3145             pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
3146         }
3147         return true;
3148     }
3149 
3150     /**
3151      * Set the new focused app to this display.
3152      *
3153      * @param newFocus the new focused AppWindowToken.
3154      * @return true if the focused app is changed.
3155      */
setFocusedApp(AppWindowToken newFocus)3156     boolean setFocusedApp(AppWindowToken newFocus) {
3157         if (newFocus != null) {
3158             final DisplayContent appDisplay = newFocus.getDisplayContent();
3159             if (appDisplay != this) {
3160                 throw new IllegalStateException(newFocus + " is not on " + getName()
3161                         + " but " + ((appDisplay != null) ? appDisplay.getName() : "none"));
3162             }
3163         }
3164         if (mFocusedApp == newFocus) {
3165             return false;
3166         }
3167         mFocusedApp = newFocus;
3168         getInputMonitor().setFocusedAppLw(newFocus);
3169         updateTouchExcludeRegion();
3170         return true;
3171     }
3172 
3173     /** Updates the layer assignment of windows on this display. */
assignWindowLayers(boolean setLayoutNeeded)3174     void assignWindowLayers(boolean setLayoutNeeded) {
3175         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "assignWindowLayers");
3176         assignChildLayers(getPendingTransaction());
3177         if (setLayoutNeeded) {
3178             setLayoutNeeded();
3179         }
3180 
3181         // We accumlate the layer changes in-to "getPendingTransaction()" but we defer
3182         // the application of this transaction until the animation pass triggers
3183         // prepareSurfaces. This allows us to synchronize Z-ordering changes with
3184         // the hiding and showing of surfaces.
3185         scheduleAnimation();
3186         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3187     }
3188 
3189     // TODO: This should probably be called any time a visual change is made to the hierarchy like
3190     // moving containers or resizing them. Need to investigate the best way to have it automatically
3191     // happen so we don't run into issues with programmers forgetting to do it.
layoutAndAssignWindowLayersIfNeeded()3192     void layoutAndAssignWindowLayersIfNeeded() {
3193         mWmService.mWindowsChanged = true;
3194         setLayoutNeeded();
3195 
3196         if (!mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
3197                 false /*updateInputWindows*/)) {
3198             assignWindowLayers(false /* setLayoutNeeded */);
3199         }
3200 
3201         mInputMonitor.setUpdateInputWindowsNeededLw();
3202         mWmService.mWindowPlacerLocked.performSurfacePlacement();
3203         mInputMonitor.updateInputWindowsLw(false /*force*/);
3204     }
3205 
3206     /** Returns true if a leaked surface was destroyed */
destroyLeakedSurfaces()3207     boolean destroyLeakedSurfaces() {
3208         // Used to indicate that a surface was leaked.
3209         mTmpWindow = null;
3210         forAllWindows(w -> {
3211             final WindowStateAnimator wsa = w.mWinAnimator;
3212             if (wsa.mSurfaceController == null) {
3213                 return;
3214             }
3215             if (!mWmService.mSessions.contains(wsa.mSession)) {
3216                 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
3217                         + w + " surface=" + wsa.mSurfaceController
3218                         + " token=" + w.mToken
3219                         + " pid=" + w.mSession.mPid
3220                         + " uid=" + w.mSession.mUid);
3221                 wsa.destroySurface();
3222                 mWmService.mForceRemoves.add(w);
3223                 mTmpWindow = w;
3224             } else if (w.mAppToken != null && w.mAppToken.isClientHidden()) {
3225                 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
3226                         + w + " surface=" + wsa.mSurfaceController
3227                         + " token=" + w.mAppToken);
3228                 if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false);
3229                 wsa.destroySurface();
3230                 mTmpWindow = w;
3231             }
3232         }, false /* traverseTopToBottom */);
3233 
3234         return mTmpWindow != null;
3235     }
3236 
3237     /**
3238      * Set input method window for the display.
3239      * @param win Set when window added or Null when destroyed.
3240      */
setInputMethodWindowLocked(WindowState win)3241     void setInputMethodWindowLocked(WindowState win) {
3242         mInputMethodWindow = win;
3243         // Update display configuration for IME process.
3244         if (mInputMethodWindow != null) {
3245             final int imePid = mInputMethodWindow.mSession.mPid;
3246             mWmService.mAtmInternal.onImeWindowSetOnDisplay(imePid,
3247                     mInputMethodWindow.getDisplayId());
3248         }
3249         computeImeTarget(true /* updateImeTarget */);
3250         mInsetsStateController.getSourceProvider(TYPE_IME).setWindow(win,
3251                 null /* frameProvider */);
3252     }
3253 
3254     /**
3255      * Determine and return the window that should be the IME target.
3256      * @param updateImeTarget If true the system IME target will be updated to match what we found.
3257      * @return The window that should be used as the IME target or null if there isn't any.
3258      */
computeImeTarget(boolean updateImeTarget)3259     WindowState computeImeTarget(boolean updateImeTarget) {
3260         if (mInputMethodWindow == null) {
3261             // There isn't an IME so there shouldn't be a target...That was easy!
3262             if (updateImeTarget) {
3263                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
3264                         + mInputMethodTarget + " to null since mInputMethodWindow is null");
3265                 setInputMethodTarget(null, mInputMethodTargetWaitingAnim);
3266             }
3267             return null;
3268         }
3269 
3270         final WindowState curTarget = mInputMethodTarget;
3271         if (!canUpdateImeTarget()) {
3272             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
3273             return curTarget;
3274         }
3275 
3276         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
3277         // same display. Or even when the current IME/target are not on the same screen as the next
3278         // IME/target. For now only look for input windows on the main screen.
3279         mUpdateImeTarget = updateImeTarget;
3280         WindowState target = getWindow(mComputeImeTargetPredicate);
3281 
3282 
3283         // Yet more tricksyness!  If this window is a "starting" window, we do actually want
3284         // to be on top of it, but it is not -really- where input will go. So look down below
3285         // for a real window to target...
3286         if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) {
3287             final AppWindowToken token = target.mAppToken;
3288             if (token != null) {
3289                 final WindowState betterTarget = token.getImeTargetBelowWindow(target);
3290                 if (betterTarget != null) {
3291                     target = betterTarget;
3292                 }
3293             }
3294         }
3295 
3296         if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
3297                 "Proposed new IME target: " + target + " for display: " + getDisplayId());
3298 
3299         // Now, a special case -- if the last target's window is in the process of exiting, but
3300         // not removed, keep on the last target to avoid IME flicker.
3301         if (curTarget != null && !curTarget.mRemoved && curTarget.isDisplayedLw()
3302                 && curTarget.isClosing()) {
3303             if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Not changing target till current window is"
3304                     + " closing and not removed");
3305             return curTarget;
3306         }
3307 
3308         if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target
3309                 + " updateImeTarget=" + updateImeTarget);
3310 
3311         if (target == null) {
3312             if (updateImeTarget) {
3313                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
3314                         + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
3315                         + Debug.getCallers(4) : ""));
3316                 setInputMethodTarget(null, mInputMethodTargetWaitingAnim);
3317             }
3318 
3319             return null;
3320         }
3321 
3322         if (updateImeTarget) {
3323             AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
3324             if (token != null) {
3325 
3326                 // Now some fun for dealing with window animations that modify the Z order. We need
3327                 // to look at all windows below the current target that are in this app, finding the
3328                 // highest visible one in layering.
3329                 WindowState highestTarget = null;
3330                 if (token.isSelfAnimating()) {
3331                     highestTarget = token.getHighestAnimLayerWindow(curTarget);
3332                 }
3333 
3334                 if (highestTarget != null) {
3335                     if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, mAppTransition + " " + highestTarget
3336                             + " animating=" + highestTarget.isAnimating());
3337 
3338                     if (mAppTransition.isTransitionSet()) {
3339                         // If we are currently setting up for an animation, hold everything until we
3340                         // can find out what will happen.
3341                         setInputMethodTarget(highestTarget, true);
3342                         return highestTarget;
3343                     }
3344                 }
3345             }
3346 
3347             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
3348                     + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
3349             setInputMethodTarget(target, false);
3350         }
3351 
3352         return target;
3353     }
3354 
3355     /**
3356      * Calling {@link #computeImeTarget(boolean)} to update the input method target window in
3357      * the candidate app window token if needed.
3358      */
computeImeTargetIfNeeded(AppWindowToken candidate)3359     void computeImeTargetIfNeeded(AppWindowToken candidate) {
3360         if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == candidate) {
3361             computeImeTarget(true /* updateImeTarget */);
3362         }
3363     }
3364 
setInputMethodTarget(WindowState target, boolean targetWaitingAnim)3365     private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) {
3366         if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) {
3367             return;
3368         }
3369 
3370         mInputMethodTarget = target;
3371         mInputMethodTargetWaitingAnim = targetWaitingAnim;
3372         assignWindowLayers(false /* setLayoutNeeded */);
3373         mInsetsStateController.onImeTargetChanged(target);
3374         updateImeParent();
3375     }
3376 
updateImeParent()3377     private void updateImeParent() {
3378         // Force attaching IME to the display when magnifying, or it would be magnified with
3379         // target app together.
3380         final boolean shouldAttachToDisplay = (mMagnificationSpec != null);
3381         final SurfaceControl newParent =
3382                 shouldAttachToDisplay ? mWindowingLayer : computeImeParent();
3383         if (newParent != null) {
3384             getPendingTransaction().reparent(mImeWindowsContainers.mSurfaceControl, newParent);
3385             scheduleAnimation();
3386         }
3387     }
3388 
3389     /**
3390      * Computes the window the IME should be attached to.
3391      */
3392     @VisibleForTesting
computeImeParent()3393     SurfaceControl computeImeParent() {
3394 
3395         // Attach it to app if the target is part of an app and such app is covering the entire
3396         // screen. If it's not covering the entire screen the IME might extend beyond the apps
3397         // bounds.
3398         if (mInputMethodTarget != null && mInputMethodTarget.mAppToken != null
3399                 && mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
3400                 // An activity with override bounds should be letterboxed inside its parent bounds,
3401                 // so it doesn't fill the screen.
3402                 && mInputMethodTarget.mAppToken.matchParentBounds()) {
3403             return mInputMethodTarget.mAppToken.getSurfaceControl();
3404         }
3405 
3406         // Otherwise, we just attach it to the display.
3407         return mWindowingLayer;
3408     }
3409 
getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom)3410     boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
3411         if (top.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
3412             return top.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
3413         }
3414 
3415         // Used to indicate we have reached the first window in the range we are interested in.
3416         mTmpWindow = null;
3417 
3418         // TODO: Figure-out a more efficient way to do this.
3419         final WindowState candidate = getWindow(w -> {
3420             if (w == top) {
3421                 // Reached the first window in the range we are interested in.
3422                 mTmpWindow = w;
3423             }
3424             if (mTmpWindow == null) {
3425                 return false;
3426             }
3427 
3428             if (w.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
3429                 return true;
3430             }
3431             // If we reached the bottom of the range of windows we are considering,
3432             // assume no menu is needed.
3433             if (w == bottom) {
3434                 return true;
3435             }
3436             return false;
3437         });
3438 
3439         return candidate != null && candidate.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
3440     }
3441 
setLayoutNeeded()3442     void setLayoutNeeded() {
3443         if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
3444         mLayoutNeeded = true;
3445     }
3446 
clearLayoutNeeded()3447     private void clearLayoutNeeded() {
3448         if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3));
3449         mLayoutNeeded = false;
3450     }
3451 
isLayoutNeeded()3452     boolean isLayoutNeeded() {
3453         return mLayoutNeeded;
3454     }
3455 
dumpTokens(PrintWriter pw, boolean dumpAll)3456     void dumpTokens(PrintWriter pw, boolean dumpAll) {
3457         if (mTokenMap.isEmpty()) {
3458             return;
3459         }
3460         pw.println("  Display #" + mDisplayId);
3461         final Iterator<WindowToken> it = mTokenMap.values().iterator();
3462         while (it.hasNext()) {
3463             final WindowToken token = it.next();
3464             pw.print("  ");
3465             pw.print(token);
3466             if (dumpAll) {
3467                 pw.println(':');
3468                 token.dump(pw, "    ", dumpAll);
3469             } else {
3470                 pw.println();
3471             }
3472         }
3473 
3474         if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty() || !mChangingApps.isEmpty()) {
3475             pw.println();
3476             if (mOpeningApps.size() > 0) {
3477                 pw.print("  mOpeningApps="); pw.println(mOpeningApps);
3478             }
3479             if (mClosingApps.size() > 0) {
3480                 pw.print("  mClosingApps="); pw.println(mClosingApps);
3481             }
3482             if (mChangingApps.size() > 0) {
3483                 pw.print("  mChangingApps="); pw.println(mChangingApps);
3484             }
3485         }
3486 
3487         mUnknownAppVisibilityController.dump(pw, "  ");
3488     }
3489 
dumpWindowAnimators(PrintWriter pw, String subPrefix)3490     void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
3491         final int[] index = new int[1];
3492         forAllWindows(w -> {
3493             final WindowStateAnimator wAnim = w.mWinAnimator;
3494             pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim);
3495             index[0] = index[0] + 1;
3496         }, false /* traverseTopToBottom */);
3497     }
3498 
3499     /**
3500      * Starts the Keyguard exit animation on all windows that don't belong to an app token.
3501      */
startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade, boolean subtle)3502     void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade,
3503             boolean subtle) {
3504         final WindowManagerPolicy policy = mWmService.mPolicy;
3505         forAllWindows(w -> {
3506             if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)
3507                     && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
3508                 w.startAnimation(policy.createHiddenByKeyguardExit(
3509                         onWallpaper, goingToShade, subtle));
3510             }
3511         }, true /* traverseTopToBottom */);
3512     }
3513 
checkWaitingForWindows()3514     boolean checkWaitingForWindows() {
3515 
3516         mHaveBootMsg = false;
3517         mHaveApp = false;
3518         mHaveWallpaper = false;
3519         mHaveKeyguard = true;
3520 
3521         final WindowState visibleWindow = getWindow(w -> {
3522             if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
3523                 return true;
3524             }
3525             if (w.isDrawnLw()) {
3526                 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
3527                     mHaveBootMsg = true;
3528                 } else if (w.mAttrs.type == TYPE_APPLICATION
3529                         || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
3530                     mHaveApp = true;
3531                 } else if (w.mAttrs.type == TYPE_WALLPAPER) {
3532                     mHaveWallpaper = true;
3533                 } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
3534                     mHaveKeyguard = mWmService.mPolicy.isKeyguardDrawnLw();
3535                 }
3536             }
3537             return false;
3538         });
3539 
3540         if (visibleWindow != null) {
3541             // We have a visible window.
3542             return true;
3543         }
3544 
3545         // if the wallpaper service is disabled on the device, we're never going to have
3546         // wallpaper, don't bother waiting for it
3547         boolean wallpaperEnabled = mWmService.mContext.getResources().getBoolean(
3548                 com.android.internal.R.bool.config_enableWallpaperService)
3549                 && mWmService.mContext.getResources().getBoolean(
3550                         com.android.internal.R.bool.config_checkWallpaperAtBoot)
3551                 && !mWmService.mOnlyCore;
3552 
3553         if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
3554                 "******** booted=" + mWmService.mSystemBooted
3555                 + " msg=" + mWmService.mShowingBootMessages
3556                 + " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp
3557                 + " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled
3558                 + " haveKeyguard=" + mHaveKeyguard);
3559 
3560         // If we are turning on the screen to show the boot message, don't do it until the boot
3561         // message is actually displayed.
3562         if (!mWmService.mSystemBooted && !mHaveBootMsg) {
3563             return true;
3564         }
3565 
3566         // If we are turning on the screen after the boot is completed normally, don't do so until
3567         // we have the application and wallpaper.
3568         if (mWmService.mSystemBooted
3569                 && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) {
3570             return true;
3571         }
3572 
3573         return false;
3574     }
3575 
updateWindowsForAnimator()3576     void updateWindowsForAnimator() {
3577         forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
3578     }
3579 
3580     /**
3581      * Updates the {@link TaskStack#setAnimationBackground} for all windows.
3582      */
updateBackgroundForAnimator()3583     void updateBackgroundForAnimator() {
3584         resetAnimationBackgroundAnimator();
3585         forAllWindows(mUpdateWallpaperForAnimator, true /* traverseTopToBottom */);
3586     }
3587 
isInputMethodClientFocus(int uid, int pid)3588     boolean isInputMethodClientFocus(int uid, int pid) {
3589         final WindowState imFocus = computeImeTarget(false /* updateImeTarget */);
3590         if (imFocus == null) {
3591             return false;
3592         }
3593 
3594         if (DEBUG_INPUT_METHOD) {
3595             Slog.i(TAG_WM, "Desired input method target: " + imFocus);
3596             Slog.i(TAG_WM, "Current focus: " + mCurrentFocus + " displayId=" + mDisplayId);
3597             Slog.i(TAG_WM, "Last focus: " + mLastFocus + " displayId=" + mDisplayId);
3598         }
3599 
3600         if (DEBUG_INPUT_METHOD) {
3601             Slog.i(TAG_WM, "IM target uid/pid: " + imFocus.mSession.mUid
3602                     + "/" + imFocus.mSession.mPid);
3603             Slog.i(TAG_WM, "Requesting client uid/pid: " + uid + "/" + pid);
3604         }
3605 
3606         return imFocus.mSession.mUid == uid && imFocus.mSession.mPid == pid;
3607     }
3608 
hasSecureWindowOnScreen()3609     boolean hasSecureWindowOnScreen() {
3610         final WindowState win = getWindow(
3611                 w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0);
3612         return win != null;
3613     }
3614 
statusBarVisibilityChanged(int visibility)3615     void statusBarVisibilityChanged(int visibility) {
3616         mLastStatusBarVisibility = visibility;
3617         visibility = getDisplayPolicy().adjustSystemUiVisibilityLw(visibility);
3618         updateStatusBarVisibilityLocked(visibility);
3619     }
3620 
updateStatusBarVisibilityLocked(int visibility)3621     private boolean updateStatusBarVisibilityLocked(int visibility) {
3622         if (mLastDispatchedSystemUiVisibility == visibility) {
3623             return false;
3624         }
3625         final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility)
3626                 // We are only interested in differences of one of the
3627                 // clearable flags...
3628                 & View.SYSTEM_UI_CLEARABLE_FLAGS
3629                 // ...if it has actually been cleared.
3630                 & ~visibility;
3631 
3632         mLastDispatchedSystemUiVisibility = visibility;
3633         if (isDefaultDisplay) {
3634             mWmService.mInputManager.setSystemUiVisibility(visibility);
3635         }
3636         updateSystemUiVisibility(visibility, globalDiff);
3637         return true;
3638     }
3639 
updateSystemUiVisibility(int visibility, int globalDiff)3640     void updateSystemUiVisibility(int visibility, int globalDiff) {
3641         forAllWindows(w -> {
3642             try {
3643                 final int curValue = w.mSystemUiVisibility;
3644                 final int diff = (curValue ^ visibility) & globalDiff;
3645                 final int newValue = (curValue & ~diff) | (visibility & diff);
3646                 if (newValue != curValue) {
3647                     w.mSeq++;
3648                     w.mSystemUiVisibility = newValue;
3649                 }
3650                 if (newValue != curValue || w.mAttrs.hasSystemUiListeners) {
3651                     w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq,
3652                             visibility, newValue, diff);
3653                 }
3654             } catch (RemoteException e) {
3655                 // so sorry
3656             }
3657         }, true /* traverseTopToBottom */);
3658     }
3659 
reevaluateStatusBarVisibility()3660     void reevaluateStatusBarVisibility() {
3661         int visibility = getDisplayPolicy().adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
3662         if (updateStatusBarVisibilityLocked(visibility)) {
3663             mWmService.mWindowPlacerLocked.requestTraversal();
3664         }
3665     }
3666 
onWindowFreezeTimeout()3667     void onWindowFreezeTimeout() {
3668         Slog.w(TAG_WM, "Window freeze timeout expired.");
3669         mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
3670 
3671         forAllWindows(w -> {
3672             if (!w.getOrientationChanging()) {
3673                 return;
3674             }
3675             w.orientationChangeTimedOut();
3676             w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
3677                     - mWmService.mDisplayFreezeTime);
3678             Slog.w(TAG_WM, "Force clearing orientation change: " + w);
3679         }, true /* traverseTopToBottom */);
3680         mWmService.mWindowPlacerLocked.performSurfacePlacement();
3681     }
3682 
waitForAllWindowsDrawn()3683     void waitForAllWindowsDrawn() {
3684         final WindowManagerPolicy policy = mWmService.mPolicy;
3685         forAllWindows(w -> {
3686             final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
3687             if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
3688                 w.mWinAnimator.mDrawState = DRAW_PENDING;
3689                 // Force add to mResizingWindows.
3690                 w.resetLastContentInsets();
3691                 mWmService.mWaitingForDrawn.add(w);
3692             }
3693         }, true /* traverseTopToBottom */);
3694     }
3695 
3696     // TODO: Super crazy long method that should be broken down...
applySurfaceChangesTransaction(boolean recoveringMemory)3697     void applySurfaceChangesTransaction(boolean recoveringMemory) {
3698         final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
3699 
3700         mTmpUpdateAllDrawn.clear();
3701 
3702         int repeats = 0;
3703         do {
3704             repeats++;
3705             if (repeats > 6) {
3706                 Slog.w(TAG, "Animation repeat aborted after too many iterations");
3707                 clearLayoutNeeded();
3708                 break;
3709             }
3710 
3711             if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
3712                     pendingLayoutChanges);
3713 
3714             if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
3715                 mWallpaperController.adjustWallpaperWindows();
3716             }
3717 
3718             if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
3719                 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
3720                 if (updateOrientationFromAppTokens()) {
3721                     setLayoutNeeded();
3722                     sendNewConfiguration();
3723                 }
3724             }
3725 
3726             if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
3727                 setLayoutNeeded();
3728             }
3729 
3730             // FIRST LOOP: Perform a layout, if needed.
3731             if (repeats < LAYOUT_REPEAT_THRESHOLD) {
3732                 performLayout(repeats == 1, false /* updateInputWindows */);
3733             } else {
3734                 Slog.w(TAG, "Layout repeat skipped after too many iterations");
3735             }
3736 
3737             // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
3738             pendingLayoutChanges = 0;
3739 
3740             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
3741             try {
3742                 mDisplayPolicy.beginPostLayoutPolicyLw();
3743                 forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
3744                 pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw();
3745             } finally {
3746                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3747             }
3748             if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
3749                     "after finishPostLayoutPolicyLw", pendingLayoutChanges);
3750                 mInsetsStateController.onPostLayout();
3751         } while (pendingLayoutChanges != 0);
3752 
3753         mTmpApplySurfaceChangesTransactionState.reset();
3754 
3755         mTmpRecoveringMemory = recoveringMemory;
3756 
3757         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
3758         try {
3759             forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
3760         } finally {
3761             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3762         }
3763         prepareSurfaces();
3764 
3765         mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent;
3766         mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
3767                 mLastHasContent,
3768                 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
3769                 mTmpApplySurfaceChangesTransactionState.preferredModeId,
3770                 true /* inTraversal, must call performTraversalInTrans... below */);
3771 
3772         final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
3773         if (wallpaperVisible != mLastWallpaperVisible) {
3774             mLastWallpaperVisible = wallpaperVisible;
3775             mWmService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this);
3776         }
3777 
3778         while (!mTmpUpdateAllDrawn.isEmpty()) {
3779             final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
3780             // See if any windows have been drawn, so they (and others associated with them)
3781             // can now be shown.
3782             atoken.updateAllDrawn();
3783         }
3784     }
3785 
updateBounds()3786     private void updateBounds() {
3787         calculateBounds(mDisplayInfo, mTmpBounds);
3788         setBounds(mTmpBounds);
3789         if (mPortalWindowHandle != null && mParentSurfaceControl != null) {
3790             mPortalWindowHandle.touchableRegion.getBounds(mTmpRect);
3791             if (!mTmpBounds.equals(mTmpRect)) {
3792                 mPortalWindowHandle.touchableRegion.set(mTmpBounds);
3793                 getPendingTransaction().setInputWindowInfo(
3794                         mParentSurfaceControl, mPortalWindowHandle);
3795             }
3796         }
3797     }
3798 
3799     // Determines the current display bounds based on the current state
calculateBounds(DisplayInfo displayInfo, Rect out)3800     private void calculateBounds(DisplayInfo displayInfo, Rect out) {
3801         // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
3802         final int rotation = displayInfo.rotation;
3803         boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
3804         final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
3805         final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
3806         int width = displayInfo.logicalWidth;
3807         int left = (physWidth - width) / 2;
3808         int height = displayInfo.logicalHeight;
3809         int top = (physHeight - height) / 2;
3810         out.set(left, top, left + width, top + height);
3811     }
3812 
getBounds(Rect out, int orientation)3813     private void getBounds(Rect out, int orientation) {
3814         getBounds(out);
3815 
3816         // Rotate the Rect if needed.
3817         final int currentRotation = mDisplayInfo.rotation;
3818         final int rotationDelta = deltaRotation(currentRotation, orientation);
3819         if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
3820             createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
3821             mTmpRectF.set(out);
3822             mTmpMatrix.mapRect(mTmpRectF);
3823             mTmpRectF.round(out);
3824         }
3825     }
3826 
3827     /** @returns the orientation of the display when it's rotation is ROTATION_0. */
getNaturalOrientation()3828     int getNaturalOrientation() {
3829         return mBaseDisplayWidth < mBaseDisplayHeight
3830                 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
3831     }
3832 
performLayout(boolean initial, boolean updateInputWindows)3833     void performLayout(boolean initial, boolean updateInputWindows) {
3834         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performLayout");
3835         try {
3836             performLayoutNoTrace(initial, updateInputWindows);
3837         } finally {
3838             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3839         }
3840     }
3841 
performLayoutNoTrace(boolean initial, boolean updateInputWindows)3842     private void performLayoutNoTrace(boolean initial, boolean updateInputWindows) {
3843         if (!isLayoutNeeded()) {
3844             return;
3845         }
3846         clearLayoutNeeded();
3847 
3848         final int dw = mDisplayInfo.logicalWidth;
3849         final int dh = mDisplayInfo.logicalHeight;
3850         if (DEBUG_LAYOUT) {
3851             Slog.v(TAG, "-------------------------------------");
3852             Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw
3853                     + " dh=" + dh);
3854         }
3855 
3856         mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
3857                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
3858         // TODO: Not sure if we really need to set the rotation here since we are updating from
3859         // the display info above...
3860         mDisplayFrames.mRotation = mRotation;
3861         mDisplayPolicy.beginLayoutLw(mDisplayFrames, getConfiguration().uiMode);
3862 
3863         int seq = mLayoutSeq + 1;
3864         if (seq < 0) seq = 0;
3865         mLayoutSeq = seq;
3866 
3867         // Used to indicate that we have processed the dream window and all additional windows are
3868         // behind it.
3869         mTmpWindow = null;
3870         mTmpInitial = initial;
3871 
3872         // First perform layout of any root windows (not attached to another window).
3873         forAllWindows(mPerformLayout, true /* traverseTopToBottom */);
3874 
3875         // Used to indicate that we have processed the dream window and all additional attached
3876         // windows are behind it.
3877         mTmpWindow2 = mTmpWindow;
3878         mTmpWindow = null;
3879 
3880         // Now perform layout of attached windows, which usually depend on the position of the
3881         // window they are attached to. XXX does not deal with windows that are attached to windows
3882         // that are themselves attached.
3883         forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);
3884 
3885         // Window frames may have changed. Tell the input dispatcher about it.
3886         mInputMonitor.layoutInputConsumers(dw, dh);
3887         mInputMonitor.setUpdateInputWindowsNeededLw();
3888         if (updateInputWindows) {
3889             mInputMonitor.updateInputWindowsLw(false /*force*/);
3890         }
3891 
3892         mWmService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
3893     }
3894 
3895     /**
3896      * Takes a snapshot of the display.  In landscape mode this grabs the whole screen.
3897      * In portrait mode, it grabs the full screenshot.
3898      *
3899      * @param config of the output bitmap
3900      */
screenshotDisplayLocked(Bitmap.Config config)3901     Bitmap screenshotDisplayLocked(Bitmap.Config config) {
3902         if (!mWmService.mPolicy.isScreenOn()) {
3903             if (DEBUG_SCREENSHOT) {
3904                 Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
3905             }
3906             return null;
3907         }
3908 
3909         int dw = mDisplayInfo.logicalWidth;
3910         int dh = mDisplayInfo.logicalHeight;
3911 
3912         if (dw <= 0 || dh <= 0) {
3913             return null;
3914         }
3915 
3916         final Rect frame = new Rect(0, 0, dw, dh);
3917 
3918         // The screenshot API does not apply the current screen rotation.
3919         int rot = mDisplay.getRotation();
3920 
3921         if (rot == ROTATION_90 || rot == ROTATION_270) {
3922             rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90;
3923         }
3924 
3925         // SurfaceFlinger is not aware of orientation, so convert our logical
3926         // crop to SurfaceFlinger's portrait orientation.
3927         convertCropForSurfaceFlinger(frame, rot, dw, dh);
3928 
3929         final ScreenRotationAnimation screenRotationAnimation =
3930                 mWmService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
3931         final boolean inRotation = screenRotationAnimation != null &&
3932                 screenRotationAnimation.isAnimating();
3933         if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, "Taking screenshot while rotating");
3934 
3935         // TODO(b/68392460): We should screenshot Task controls directly
3936         // but it's difficult at the moment as the Task doesn't have the
3937         // correct size set.
3938         final Bitmap bitmap = SurfaceControl.screenshot(frame, dw, dh, inRotation, rot);
3939         if (bitmap == null) {
3940             Slog.w(TAG_WM, "Failed to take screenshot");
3941             return null;
3942         }
3943 
3944         // Create a copy of the screenshot that is immutable and backed in ashmem.
3945         // This greatly reduces the overhead of passing the bitmap between processes.
3946         final Bitmap ret = bitmap.createAshmemBitmap(config);
3947         bitmap.recycle();
3948         return ret;
3949     }
3950 
3951     // TODO: Can this use createRotationMatrix()?
convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh)3952     private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
3953         if (rot == Surface.ROTATION_90) {
3954             final int tmp = crop.top;
3955             crop.top = dw - crop.right;
3956             crop.right = crop.bottom;
3957             crop.bottom = dw - crop.left;
3958             crop.left = tmp;
3959         } else if (rot == Surface.ROTATION_180) {
3960             int tmp = crop.top;
3961             crop.top = dh - crop.bottom;
3962             crop.bottom = dh - tmp;
3963             tmp = crop.right;
3964             crop.right = dw - crop.left;
3965             crop.left = dw - tmp;
3966         } else if (rot == Surface.ROTATION_270) {
3967             final int tmp = crop.top;
3968             crop.top = crop.left;
3969             crop.left = dh - crop.bottom;
3970             crop.bottom = crop.right;
3971             crop.right = dh - tmp;
3972         }
3973     }
3974 
onSeamlessRotationTimeout()3975     void onSeamlessRotationTimeout() {
3976         // Used to indicate the layout is needed.
3977         mTmpWindow = null;
3978 
3979         forAllWindows(w -> {
3980             if (!w.mSeamlesslyRotated) {
3981                 return;
3982             }
3983             mTmpWindow = w;
3984             w.setDisplayLayoutNeeded();
3985             w.finishSeamlessRotation(true /* timeout */);
3986             mWmService.markForSeamlessRotation(w, false);
3987         }, true /* traverseTopToBottom */);
3988 
3989         if (mTmpWindow != null) {
3990             mWmService.mWindowPlacerLocked.performSurfacePlacement();
3991         }
3992     }
3993 
setExitingTokensHasVisible(boolean hasVisible)3994     void setExitingTokensHasVisible(boolean hasVisible) {
3995         for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
3996             mExitingTokens.get(i).hasVisible = hasVisible;
3997         }
3998 
3999         // Initialize state of exiting applications.
4000         mTaskStackContainers.setExitingTokensHasVisible(hasVisible);
4001     }
4002 
removeExistingTokensIfPossible()4003     void removeExistingTokensIfPossible() {
4004         for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
4005             final WindowToken token = mExitingTokens.get(i);
4006             if (!token.hasVisible) {
4007                 mExitingTokens.remove(i);
4008             }
4009         }
4010 
4011         // Time to remove any exiting applications?
4012         mTaskStackContainers.removeExistingAppTokensIfPossible();
4013     }
4014 
4015     @Override
onDescendantOverrideConfigurationChanged()4016     void onDescendantOverrideConfigurationChanged() {
4017         setLayoutNeeded();
4018         mWmService.requestTraversal();
4019     }
4020 
okToDisplay()4021     boolean okToDisplay() {
4022         if (mDisplayId == DEFAULT_DISPLAY) {
4023             return !mWmService.mDisplayFrozen
4024                     && mWmService.mDisplayEnabled && mWmService.mPolicy.isScreenOn();
4025         }
4026         return mDisplayInfo.state == Display.STATE_ON;
4027     }
4028 
okToAnimate()4029     boolean okToAnimate() {
4030         return okToDisplay() &&
4031                 (mDisplayId != DEFAULT_DISPLAY || mWmService.mPolicy.okToAnimate());
4032     }
4033 
4034     static final class TaskForResizePointSearchResult {
4035         boolean searchDone;
4036         Task taskForResize;
4037 
reset()4038         void reset() {
4039             searchDone = false;
4040             taskForResize = null;
4041         }
4042     }
4043 
4044     private static final class ApplySurfaceChangesTransactionState {
4045         boolean displayHasContent;
4046         boolean obscured;
4047         boolean syswin;
4048         float preferredRefreshRate;
4049         int preferredModeId;
4050 
reset()4051         void reset() {
4052             displayHasContent = false;
4053             obscured = false;
4054             syswin = false;
4055             preferredRefreshRate = 0;
4056             preferredModeId = 0;
4057         }
4058     }
4059 
4060     private static final class ScreenshotApplicationState {
4061         WindowState appWin;
4062         int maxLayer;
4063         int minLayer;
4064         boolean screenshotReady;
4065 
reset(boolean screenshotReady)4066         void reset(boolean screenshotReady) {
4067             appWin = null;
4068             maxLayer = 0;
4069             minLayer = 0;
4070             this.screenshotReady = screenshotReady;
4071             minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE;
4072         }
4073     }
4074 
4075     /**
4076      * Base class for any direct child window container of {@link #DisplayContent} need to inherit
4077      * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
4078      * homogeneous children type which is currently required by sub-classes of
4079      * {@link WindowContainer} class.
4080      */
4081     static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
4082 
DisplayChildWindowContainer(WindowManagerService service)4083         DisplayChildWindowContainer(WindowManagerService service) {
4084             super(service);
4085         }
4086 
4087         @Override
fillsParent()4088         boolean fillsParent() {
4089             return true;
4090         }
4091 
4092         @Override
isVisible()4093         boolean isVisible() {
4094             return true;
4095         }
4096     }
4097 
4098     /**
4099      * Window container class that contains all containers on this display relating to Apps.
4100      * I.e Activities.
4101      */
4102     private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
4103         /**
4104          * A control placed at the appropriate level for transitions to occur.
4105          */
4106         SurfaceControl mAppAnimationLayer = null;
4107         SurfaceControl mBoostedAppAnimationLayer = null;
4108         SurfaceControl mHomeAppAnimationLayer = null;
4109 
4110         /**
4111          * Given that the split-screen divider does not have an AppWindowToken, it
4112          * will have to live inside of a "NonAppWindowContainer", in particular
4113          * {@link DisplayContent#mAboveAppWindowsContainers}. However, in visual Z order
4114          * it will need to be interleaved with some of our children, appearing on top of
4115          * both docked stacks but underneath any assistant stacks.
4116          *
4117          * To solve this problem we have this anchor control, which will always exist so
4118          * we can always assign it the correct value in our {@link #assignChildLayers}.
4119          * Likewise since it always exists, {@link AboveAppWindowContainers} can always
4120          * assign the divider a layer relative to it. This way we prevent linking lifecycle
4121          * events between the two containers.
4122          */
4123         SurfaceControl mSplitScreenDividerAnchor = null;
4124 
4125         // Cached reference to some special stacks we tend to get a lot so we don't need to loop
4126         // through the list to find them.
4127         private TaskStack mHomeStack = null;
4128         private TaskStack mPinnedStack = null;
4129         private TaskStack mSplitScreenPrimaryStack = null;
4130 
TaskStackContainers(WindowManagerService service)4131         TaskStackContainers(WindowManagerService service) {
4132             super(service);
4133         }
4134 
4135         /**
4136          * Returns the topmost stack on the display that is compatible with the input windowing mode
4137          * and activity type. Null is no compatible stack on the display.
4138          */
getStack(int windowingMode, int activityType)4139         TaskStack getStack(int windowingMode, int activityType) {
4140             if (activityType == ACTIVITY_TYPE_HOME) {
4141                 return mHomeStack;
4142             }
4143             if (windowingMode == WINDOWING_MODE_PINNED) {
4144                 return mPinnedStack;
4145             } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
4146                 return mSplitScreenPrimaryStack;
4147             }
4148             for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
4149                 final TaskStack stack = mTaskStackContainers.getChildAt(i);
4150                 if (activityType == ACTIVITY_TYPE_UNDEFINED
4151                         && windowingMode == stack.getWindowingMode()) {
4152                     // Passing in undefined type means we want to match the topmost stack with the
4153                     // windowing mode.
4154                     return stack;
4155                 }
4156                 if (stack.isCompatible(windowingMode, activityType)) {
4157                     return stack;
4158                 }
4159             }
4160             return null;
4161         }
4162 
4163         @VisibleForTesting
getTopStack()4164         TaskStack getTopStack() {
4165             return mTaskStackContainers.getChildCount() > 0
4166                     ? mTaskStackContainers.getChildAt(mTaskStackContainers.getChildCount() - 1) : null;
4167         }
4168 
getHomeStack()4169         TaskStack getHomeStack() {
4170             if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
4171                 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
4172             }
4173             return mHomeStack;
4174         }
4175 
getPinnedStack()4176         TaskStack getPinnedStack() {
4177             return mPinnedStack;
4178         }
4179 
getSplitScreenPrimaryStack()4180         TaskStack getSplitScreenPrimaryStack() {
4181             return mSplitScreenPrimaryStack;
4182         }
4183 
getVisibleTasks()4184         ArrayList<Task> getVisibleTasks() {
4185             final ArrayList<Task> visibleTasks = new ArrayList<>();
4186             forAllTasks(task -> {
4187                 if (task.isVisible()) {
4188                     visibleTasks.add(task);
4189                 }
4190             });
4191             return visibleTasks;
4192         }
4193 
4194         /**
4195          * Adds the stack to this container.
4196          */
addStackToDisplay(TaskStack stack, boolean onTop)4197         void addStackToDisplay(TaskStack stack, boolean onTop) {
4198             addStackReferenceIfNeeded(stack);
4199             addChild(stack, onTop);
4200             stack.onDisplayChanged(DisplayContent.this);
4201         }
4202 
onStackWindowingModeChanged(TaskStack stack)4203         void onStackWindowingModeChanged(TaskStack stack) {
4204             removeStackReferenceIfNeeded(stack);
4205             addStackReferenceIfNeeded(stack);
4206             if (stack == mPinnedStack && getTopStack() != stack) {
4207                 // Looks like this stack changed windowing mode to pinned. Move it to the top.
4208                 positionChildAt(POSITION_TOP, stack, false /* includingParents */);
4209             }
4210         }
4211 
addStackReferenceIfNeeded(TaskStack stack)4212         private void addStackReferenceIfNeeded(TaskStack stack) {
4213             if (stack.isActivityTypeHome()) {
4214                 if (mHomeStack != null) {
4215                     throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
4216                             + mHomeStack + " already exist on display=" + this + " stack=" + stack);
4217 
4218                 }
4219                 mHomeStack = stack;
4220             }
4221             final int windowingMode = stack.getWindowingMode();
4222             if (windowingMode == WINDOWING_MODE_PINNED) {
4223                 if (mPinnedStack != null) {
4224                     throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
4225                             + mPinnedStack + " already exist on display=" + this
4226                             + " stack=" + stack);
4227                 }
4228                 mPinnedStack = stack;
4229             } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
4230                 if (mSplitScreenPrimaryStack != null) {
4231                     throw new IllegalArgumentException("addStackReferenceIfNeeded:"
4232                             + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
4233                             + " already exist on display=" + this + " stack=" + stack);
4234                 }
4235                 mSplitScreenPrimaryStack = stack;
4236                 mDividerControllerLocked.notifyDockedStackExistsChanged(true);
4237             }
4238         }
4239 
removeStackReferenceIfNeeded(TaskStack stack)4240         private void removeStackReferenceIfNeeded(TaskStack stack) {
4241             if (stack == mHomeStack) {
4242                 mHomeStack = null;
4243             } else if (stack == mPinnedStack) {
4244                 mPinnedStack = null;
4245             } else if (stack == mSplitScreenPrimaryStack) {
4246                 mSplitScreenPrimaryStack = null;
4247                 // Re-set the split-screen create mode whenever the split-screen stack is removed.
4248                 mWmService.setDockedStackCreateStateLocked(
4249                         SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
4250                 mDividerControllerLocked.notifyDockedStackExistsChanged(false);
4251             }
4252         }
4253 
addChild(TaskStack stack, boolean toTop)4254         private void addChild(TaskStack stack, boolean toTop) {
4255             final int addIndex = findPositionForStack(toTop ? mChildren.size() : 0, stack,
4256                     true /* adding */);
4257             addChild(stack, addIndex);
4258             setLayoutNeeded();
4259         }
4260 
4261         @Override
removeChild(TaskStack stack)4262         protected void removeChild(TaskStack stack) {
4263             super.removeChild(stack);
4264             removeStackReferenceIfNeeded(stack);
4265         }
4266 
4267         @Override
isOnTop()4268         boolean isOnTop() {
4269             // Considered always on top
4270             return true;
4271         }
4272 
4273         @Override
positionChildAt(int position, TaskStack child, boolean includingParents)4274         void positionChildAt(int position, TaskStack child, boolean includingParents) {
4275             if (child.getWindowConfiguration().isAlwaysOnTop()
4276                     && position != POSITION_TOP) {
4277                 // This stack is always-on-top, override the default behavior.
4278                 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
4279 
4280                 // Moving to its current position, as we must call super but we don't want to
4281                 // perform any meaningful action.
4282                 final int currentPosition = mChildren.indexOf(child);
4283                 super.positionChildAt(currentPosition, child, false /* includingParents */);
4284                 return;
4285             }
4286 
4287             final int targetPosition = findPositionForStack(position, child, false /* adding */);
4288             super.positionChildAt(targetPosition, child, includingParents);
4289 
4290             if (includingParents) {
4291                 // We still want to move the display of this stack container to top because even the
4292                 // target position is adjusted to non-top, the intention of the condition is to have
4293                 // higher z-order to gain focus (e.g. moving a task of a fullscreen stack to front
4294                 // in a non-top display which is using picture-in-picture mode).
4295                 final int topChildPosition = getChildCount() - 1;
4296                 if (targetPosition < topChildPosition && position >= topChildPosition) {
4297                     getParent().positionChildAt(POSITION_TOP, this /* child */,
4298                             true /* includingParents */);
4299                 }
4300             }
4301 
4302             setLayoutNeeded();
4303         }
4304 
4305         /**
4306          * When stack is added or repositioned, find a proper position for it.
4307          * This will make sure that pinned stack always stays on top.
4308          * @param requestedPosition Position requested by caller.
4309          * @param stack Stack to be added or positioned.
4310          * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
4311          * @return The proper position for the stack.
4312          */
findPositionForStack(int requestedPosition, TaskStack stack, boolean adding)4313         private int findPositionForStack(int requestedPosition, TaskStack stack, boolean adding) {
4314             if (stack.inPinnedWindowingMode()) {
4315                 return POSITION_TOP;
4316             }
4317 
4318             final int topChildPosition = mChildren.size() - 1;
4319             int belowAlwaysOnTopPosition = POSITION_BOTTOM;
4320             for (int i = topChildPosition; i >= 0; --i) {
4321                 if (getStacks().get(i) != stack && !getStacks().get(i).isAlwaysOnTop()) {
4322                     belowAlwaysOnTopPosition = i;
4323                     break;
4324                 }
4325             }
4326 
4327             // The max possible position we can insert the stack at.
4328             int maxPosition = POSITION_TOP;
4329             // The min possible position we can insert the stack at.
4330             int minPosition = POSITION_BOTTOM;
4331 
4332             if (stack.isAlwaysOnTop()) {
4333                 if (hasPinnedStack()) {
4334                     // Always-on-top stacks go below the pinned stack.
4335                     maxPosition = getStacks().indexOf(mPinnedStack) - 1;
4336                 }
4337                 // Always-on-top stacks need to be above all other stacks.
4338                 minPosition = belowAlwaysOnTopPosition !=
4339                         POSITION_BOTTOM ? belowAlwaysOnTopPosition : topChildPosition;
4340             } else {
4341                 // Other stacks need to be below the always-on-top stacks.
4342                 maxPosition = belowAlwaysOnTopPosition !=
4343                         POSITION_BOTTOM ? belowAlwaysOnTopPosition : 0;
4344             }
4345 
4346             int targetPosition = requestedPosition;
4347             targetPosition = Math.min(targetPosition, maxPosition);
4348             targetPosition = Math.max(targetPosition, minPosition);
4349 
4350             int prevPosition = getStacks().indexOf(stack);
4351             // The positions we calculated above (maxPosition, minPosition) do not take into
4352             // consideration the following edge cases.
4353             // 1) We need to adjust the position depending on the value "adding".
4354             // 2) When we are moving a stack to another position, we also need to adjust the
4355             //    position depending on whether the stack is moving to a higher or lower position.
4356             if ((targetPosition != requestedPosition) &&
4357                     (adding || targetPosition < prevPosition)) {
4358                 targetPosition++;
4359             }
4360 
4361             return targetPosition;
4362         }
4363 
4364         @Override
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4365         boolean forAllWindows(ToBooleanFunction<WindowState> callback,
4366                 boolean traverseTopToBottom) {
4367             if (traverseTopToBottom) {
4368                 if (super.forAllWindows(callback, traverseTopToBottom)) {
4369                     return true;
4370                 }
4371                 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
4372                     return true;
4373                 }
4374             } else {
4375                 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
4376                     return true;
4377                 }
4378                 if (super.forAllWindows(callback, traverseTopToBottom)) {
4379                     return true;
4380                 }
4381             }
4382             return false;
4383         }
4384 
forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4385         private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
4386                 boolean traverseTopToBottom) {
4387             // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the
4388             // app tokens.
4389             // TODO: Investigate if we need to continue to do this or if we can just process them
4390             // in-order.
4391             if (traverseTopToBottom) {
4392                 for (int i = mChildren.size() - 1; i >= 0; --i) {
4393                     final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
4394                     for (int j = appTokens.size() - 1; j >= 0; --j) {
4395                         if (appTokens.get(j).forAllWindowsUnchecked(callback,
4396                                 traverseTopToBottom)) {
4397                             return true;
4398                         }
4399                     }
4400                 }
4401             } else {
4402                 final int count = mChildren.size();
4403                 for (int i = 0; i < count; ++i) {
4404                     final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
4405                     final int appTokensCount = appTokens.size();
4406                     for (int j = 0; j < appTokensCount; j++) {
4407                         if (appTokens.get(j).forAllWindowsUnchecked(callback,
4408                                 traverseTopToBottom)) {
4409                             return true;
4410                         }
4411                     }
4412                 }
4413             }
4414             return false;
4415         }
4416 
setExitingTokensHasVisible(boolean hasVisible)4417         void setExitingTokensHasVisible(boolean hasVisible) {
4418             for (int i = mChildren.size() - 1; i >= 0; --i) {
4419                 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
4420                 for (int j = appTokens.size() - 1; j >= 0; --j) {
4421                     appTokens.get(j).hasVisible = hasVisible;
4422                 }
4423             }
4424         }
4425 
removeExistingAppTokensIfPossible()4426         void removeExistingAppTokensIfPossible() {
4427             for (int i = mChildren.size() - 1; i >= 0; --i) {
4428                 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
4429                 for (int j = appTokens.size() - 1; j >= 0; --j) {
4430                     final AppWindowToken token = appTokens.get(j);
4431                     if (!token.hasVisible && !mClosingApps.contains(token)
4432                             && (!token.mIsExiting || token.isEmpty())) {
4433                         // Make sure there is no animation running on this token, so any windows
4434                         // associated with it will be removed as soon as their animations are
4435                         // complete.
4436                         cancelAnimation();
4437                         if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4438                                 "performLayout: App token exiting now removed" + token);
4439                         token.removeIfPossible();
4440                     }
4441                 }
4442             }
4443         }
4444 
4445         @Override
getOrientation()4446         int getOrientation() {
4447             if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
4448                     || isStackVisible(WINDOWING_MODE_FREEFORM)) {
4449                 // Apps and their containers are not allowed to specify an orientation while the
4450                 // docked or freeform stack is visible...except for the home stack if the docked
4451                 // stack is minimized and it actually set something and the bounds is different from
4452                 // the display.
4453                 if (mHomeStack != null && mHomeStack.isVisible()
4454                         && mDividerControllerLocked.isMinimizedDock()
4455                         && !(mDividerControllerLocked.isHomeStackResizable()
4456                             && mHomeStack.matchParentBounds())) {
4457                     final int orientation = mHomeStack.getOrientation();
4458                     if (orientation != SCREEN_ORIENTATION_UNSET) {
4459                         return orientation;
4460                     }
4461                 }
4462                 return SCREEN_ORIENTATION_UNSPECIFIED;
4463             }
4464 
4465             final int orientation = super.getOrientation();
4466             boolean isCar = mWmService.mContext.getPackageManager().hasSystemFeature(
4467                     PackageManager.FEATURE_AUTOMOTIVE);
4468             if (isCar) {
4469                 // In a car, you cannot physically rotate the screen, so it doesn't make sense to
4470                 // allow anything but the default orientation.
4471                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
4472                         "Forcing UNSPECIFIED orientation in car for display id=" + mDisplayId
4473                                 + ". Ignoring " + orientation);
4474                 return SCREEN_ORIENTATION_UNSPECIFIED;
4475             }
4476 
4477             if (orientation != SCREEN_ORIENTATION_UNSET
4478                     && orientation != SCREEN_ORIENTATION_BEHIND) {
4479                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
4480                         "App is requesting an orientation, return " + orientation
4481                                 + " for display id=" + mDisplayId);
4482                 return orientation;
4483             }
4484 
4485             if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
4486                     "No app is requesting an orientation, return " + mLastOrientation
4487                             + " for display id=" + mDisplayId);
4488             // The next app has not been requested to be visible, so we keep the current orientation
4489             // to prevent freezing/unfreezing the display too early.
4490             return mLastOrientation;
4491         }
4492 
4493         @Override
assignChildLayers(SurfaceControl.Transaction t)4494         void assignChildLayers(SurfaceControl.Transaction t) {
4495             assignStackOrdering(t);
4496 
4497             for (int i = 0; i < mChildren.size(); i++) {
4498                 final TaskStack s = mChildren.get(i);
4499                 s.assignChildLayers(t);
4500             }
4501         }
4502 
assignStackOrdering(SurfaceControl.Transaction t)4503         void assignStackOrdering(SurfaceControl.Transaction t) {
4504 
4505             final int HOME_STACK_STATE = 0;
4506             final int NORMAL_STACK_STATE = 1;
4507             final int ALWAYS_ON_TOP_STATE = 2;
4508 
4509             int layer = 0;
4510             int layerForAnimationLayer = 0;
4511             int layerForBoostedAnimationLayer = 0;
4512             int layerForHomeAnimationLayer = 0;
4513 
4514             for (int state = 0; state <= ALWAYS_ON_TOP_STATE; state++) {
4515                 for (int i = 0; i < mChildren.size(); i++) {
4516                     final TaskStack s = mChildren.get(i);
4517                     if (state == HOME_STACK_STATE && !s.isActivityTypeHome()) {
4518                         continue;
4519                     } else if (state == NORMAL_STACK_STATE && (s.isActivityTypeHome()
4520                             || s.isAlwaysOnTop())) {
4521                         continue;
4522                     } else if (state == ALWAYS_ON_TOP_STATE && !s.isAlwaysOnTop()) {
4523                         continue;
4524                     }
4525                     s.assignLayer(t, layer++);
4526                     if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) {
4527                         t.setLayer(mSplitScreenDividerAnchor, layer++);
4528                     }
4529                     if ((s.isTaskAnimating() || s.isAppAnimating())
4530                             && state != ALWAYS_ON_TOP_STATE) {
4531                         // Ensure the animation layer ends up above the
4532                         // highest animating stack and no higher.
4533                         layerForAnimationLayer = layer++;
4534                     }
4535                     if (state != ALWAYS_ON_TOP_STATE) {
4536                         layerForBoostedAnimationLayer = layer++;
4537                     }
4538                 }
4539                 if (state == HOME_STACK_STATE) {
4540                     layerForHomeAnimationLayer = layer++;
4541                 }
4542             }
4543             if (mAppAnimationLayer != null) {
4544                 t.setLayer(mAppAnimationLayer, layerForAnimationLayer);
4545             }
4546             if (mBoostedAppAnimationLayer != null) {
4547                 t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
4548             }
4549             if (mHomeAppAnimationLayer != null) {
4550                 t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer);
4551             }
4552         }
4553 
4554         @Override
getAppAnimationLayer(@nimationLayer int animationLayer)4555         SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
4556             switch (animationLayer) {
4557                 case ANIMATION_LAYER_BOOSTED:
4558                     return mBoostedAppAnimationLayer;
4559                 case ANIMATION_LAYER_HOME:
4560                     return mHomeAppAnimationLayer;
4561                 case ANIMATION_LAYER_STANDARD:
4562                 default:
4563                     return mAppAnimationLayer;
4564             }
4565         }
4566 
getSplitScreenDividerAnchor()4567         SurfaceControl getSplitScreenDividerAnchor() {
4568             return mSplitScreenDividerAnchor;
4569         }
4570 
4571         @Override
onParentChanged()4572         void onParentChanged() {
4573             super.onParentChanged();
4574             if (getParent() != null) {
4575                 mAppAnimationLayer = makeChildSurface(null)
4576                         .setName("animationLayer")
4577                         .build();
4578                 mBoostedAppAnimationLayer = makeChildSurface(null)
4579                         .setName("boostedAnimationLayer")
4580                         .build();
4581                 mHomeAppAnimationLayer = makeChildSurface(null)
4582                         .setName("homeAnimationLayer")
4583                         .build();
4584                 mSplitScreenDividerAnchor = makeChildSurface(null)
4585                         .setName("splitScreenDividerAnchor")
4586                         .build();
4587                 getPendingTransaction()
4588                         .show(mAppAnimationLayer)
4589                         .show(mBoostedAppAnimationLayer)
4590                         .show(mHomeAppAnimationLayer)
4591                         .show(mSplitScreenDividerAnchor);
4592                 scheduleAnimation();
4593             } else {
4594                 mWmService.mTransactionFactory.make()
4595                         .remove(mAppAnimationLayer)
4596                         .remove(mBoostedAppAnimationLayer)
4597                         .remove(mHomeAppAnimationLayer)
4598                         .remove(mSplitScreenDividerAnchor)
4599                         .apply();
4600                 mAppAnimationLayer = null;
4601                 mBoostedAppAnimationLayer = null;
4602                 mHomeAppAnimationLayer = null;
4603                 mSplitScreenDividerAnchor = null;
4604             }
4605         }
4606     }
4607 
4608     private final class AboveAppWindowContainers extends NonAppWindowContainers {
AboveAppWindowContainers(String name, WindowManagerService service)4609         AboveAppWindowContainers(String name, WindowManagerService service) {
4610             super(name, service);
4611         }
4612 
4613         @Override
makeChildSurface(WindowContainer child)4614         SurfaceControl.Builder makeChildSurface(WindowContainer child) {
4615             final SurfaceControl.Builder builder = super.makeChildSurface(child);
4616             if (child instanceof WindowToken && ((WindowToken) child).mRoundedCornerOverlay) {
4617                 // To draw above the ColorFade layer during the screen off transition, the
4618                 // rounded corner overlays need to be at the root of the surface hierarchy.
4619                 // TODO: move the ColorLayer into the display overlay layer such that this is not
4620                 // necessary anymore.
4621                 builder.setParent(null);
4622             }
4623             return builder;
4624         }
4625 
4626         @Override
assignChildLayers(SurfaceControl.Transaction t)4627         void assignChildLayers(SurfaceControl.Transaction t) {
4628             assignChildLayers(t, null /* imeContainer */);
4629         }
4630 
assignChildLayers(SurfaceControl.Transaction t, WindowContainer imeContainer)4631         void assignChildLayers(SurfaceControl.Transaction t, WindowContainer imeContainer) {
4632             boolean needAssignIme = imeContainer != null
4633                     && imeContainer.getSurfaceControl() != null;
4634             for (int j = 0; j < mChildren.size(); ++j) {
4635                 final WindowToken wt = mChildren.get(j);
4636 
4637                 // See {@link mSplitScreenDividerAnchor}
4638                 if (wt.windowType == TYPE_DOCK_DIVIDER) {
4639                     wt.assignRelativeLayer(t, mTaskStackContainers.getSplitScreenDividerAnchor(), 1);
4640                     continue;
4641                 }
4642                 if (wt.mRoundedCornerOverlay) {
4643                     wt.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1);
4644                     continue;
4645                 }
4646                 wt.assignLayer(t, j);
4647                 wt.assignChildLayers(t);
4648 
4649                 int layer = mWmService.mPolicy.getWindowLayerFromTypeLw(
4650                         wt.windowType, wt.mOwnerCanManageAppTokens);
4651 
4652                 if (needAssignIme && layer >= mWmService.mPolicy.getWindowLayerFromTypeLw(
4653                                 TYPE_INPUT_METHOD_DIALOG, true)) {
4654                     imeContainer.assignRelativeLayer(t, wt.getSurfaceControl(), -1);
4655                     needAssignIme = false;
4656                 }
4657             }
4658             if (needAssignIme) {
4659                 imeContainer.assignRelativeLayer(t, getSurfaceControl(), Integer.MAX_VALUE);
4660             }
4661         }
4662     }
4663 
4664     /**
4665      * Window container class that contains all containers on this display that are not related to
4666      * Apps. E.g. status bar.
4667      */
4668     private class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
4669         /**
4670          * Compares two child window tokens returns -1 if the first is lesser than the second in
4671          * terms of z-order and 1 otherwise.
4672          */
4673         private final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
4674                 // Tokens with higher base layer are z-ordered on-top.
4675                 mWmService.mPolicy.getWindowLayerFromTypeLw(token1.windowType,
4676                         token1.mOwnerCanManageAppTokens)
4677                 < mWmService.mPolicy.getWindowLayerFromTypeLw(token2.windowType,
4678                         token2.mOwnerCanManageAppTokens) ? -1 : 1;
4679 
4680         private final Predicate<WindowState> mGetOrientingWindow = w -> {
4681             if (!w.isVisibleLw() || !w.mLegacyPolicyVisibilityAfterAnim) {
4682                 return false;
4683             }
4684             final int req = w.mAttrs.screenOrientation;
4685             if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND
4686                     || req == SCREEN_ORIENTATION_UNSET) {
4687                 return false;
4688             }
4689             return true;
4690         };
4691 
4692         private final String mName;
4693         private final Dimmer mDimmer = new Dimmer(this);
4694         private final Rect mTmpDimBoundsRect = new Rect();
4695 
NonAppWindowContainers(String name, WindowManagerService service)4696         NonAppWindowContainers(String name, WindowManagerService service) {
4697             super(service);
4698             mName = name;
4699         }
4700 
addChild(WindowToken token)4701         void addChild(WindowToken token) {
4702             addChild(token, mWindowComparator);
4703         }
4704 
4705         @Override
getOrientation()4706         int getOrientation() {
4707             final WindowManagerPolicy policy = mWmService.mPolicy;
4708             // Find a window requesting orientation.
4709             final WindowState win = getWindow(mGetOrientingWindow);
4710 
4711             if (win != null) {
4712                 final int req = win.mAttrs.screenOrientation;
4713                 if (policy.isKeyguardHostWindow(win.mAttrs)) {
4714                     mLastKeyguardForcedOrientation = req;
4715                     if (mWmService.mKeyguardGoingAway) {
4716                         // Keyguard can't affect the orientation if it is going away...
4717                         mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
4718                         return SCREEN_ORIENTATION_UNSET;
4719                     }
4720                 }
4721                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req
4722                         + " for display id=" + mDisplayId);
4723                 return (mLastWindowForcedOrientation = req);
4724             }
4725 
4726             mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
4727 
4728             // Only allow force setting the orientation when all unknown visibilities have been
4729             // resolved, as otherwise we just may be starting another occluding activity.
4730             final boolean isUnoccluding =
4731                     mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
4732                             && mUnknownAppVisibilityController.allResolved();
4733             if (policy.isKeyguardShowingAndNotOccluded() || isUnoccluding) {
4734                 return mLastKeyguardForcedOrientation;
4735             }
4736 
4737             return SCREEN_ORIENTATION_UNSET;
4738         }
4739 
4740         @Override
getName()4741         String getName() {
4742             return mName;
4743         }
4744 
4745         @Override
getDimmer()4746         Dimmer getDimmer() {
4747             return mDimmer;
4748         }
4749 
4750         @Override
prepareSurfaces()4751         void prepareSurfaces() {
4752             mDimmer.resetDimStates();
4753             super.prepareSurfaces();
4754             getBounds(mTmpDimBoundsRect);
4755 
4756             if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
4757                 scheduleAnimation();
4758             }
4759         }
4760     }
4761 
makeSurface(SurfaceSession s)4762     SurfaceControl.Builder makeSurface(SurfaceSession s) {
4763         return mWmService.makeSurfaceBuilder(s)
4764                 .setParent(mWindowingLayer);
4765     }
4766 
4767     @Override
getSession()4768     SurfaceSession getSession() {
4769         return mSession;
4770     }
4771 
4772     @Override
makeChildSurface(WindowContainer child)4773     SurfaceControl.Builder makeChildSurface(WindowContainer child) {
4774         SurfaceSession s = child != null ? child.getSession() : getSession();
4775         final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer();
4776         if (child == null) {
4777             return b;
4778         }
4779 
4780         return b.setName(child.getName())
4781                 .setParent(mWindowingLayer);
4782     }
4783 
4784     /**
4785      * The makeSurface variants are for use by the window-container
4786      * hierarchy. makeOverlay here is a function for various non windowing
4787      * overlays like the ScreenRotation screenshot, the Strict Mode Flash
4788      * and other potpourii.
4789      */
makeOverlay()4790     SurfaceControl.Builder makeOverlay() {
4791         return mWmService.makeSurfaceBuilder(mSession)
4792             .setParent(mOverlayLayer);
4793     }
4794 
4795     /**
4796      * Reparents the given surface to mOverlayLayer.
4797      */
reparentToOverlay(Transaction transaction, SurfaceControl surface)4798     void reparentToOverlay(Transaction transaction, SurfaceControl surface) {
4799         transaction.reparent(surface, mOverlayLayer);
4800     }
4801 
applyMagnificationSpec(MagnificationSpec spec)4802     void applyMagnificationSpec(MagnificationSpec spec) {
4803         if (spec.scale != 1.0) {
4804             mMagnificationSpec = spec;
4805         } else {
4806             mMagnificationSpec = null;
4807         }
4808         // Re-parent IME's SurfaceControl when MagnificationSpec changed.
4809         updateImeParent();
4810 
4811         if (spec.scale != 1.0) {
4812             applyMagnificationSpec(getPendingTransaction(), spec);
4813         } else {
4814             clearMagnificationSpec(getPendingTransaction());
4815         }
4816         getPendingTransaction().apply();
4817     }
4818 
reapplyMagnificationSpec()4819     void reapplyMagnificationSpec() {
4820         if (mMagnificationSpec != null) {
4821             applyMagnificationSpec(getPendingTransaction(), mMagnificationSpec);
4822         }
4823     }
4824 
4825     @Override
onParentChanged()4826     void onParentChanged() {
4827         // Since we are the top of the SurfaceControl hierarchy here
4828         // we create the root surfaces explicitly rather than chaining
4829         // up as the default implementation in onParentChanged does. So we
4830         // explicitly do NOT call super here.
4831     }
4832 
4833     @Override
assignChildLayers(SurfaceControl.Transaction t)4834     void assignChildLayers(SurfaceControl.Transaction t) {
4835 
4836         // These are layers as children of "mWindowingLayer"
4837         mBelowAppWindowsContainers.assignLayer(t, 0);
4838         mTaskStackContainers.assignLayer(t, 1);
4839         mAboveAppWindowsContainers.assignLayer(t, 2);
4840 
4841         final WindowState imeTarget = mInputMethodTarget;
4842         boolean needAssignIme = true;
4843 
4844         // In the case where we have an IME target that is not in split-screen
4845         // mode IME assignment is easy. We just need the IME to go directly above
4846         // the target. This way children of the target will naturally go above the IME
4847         // and everyone is happy.
4848         //
4849         // In the case of split-screen windowing mode, we need to elevate the IME above the
4850         // docked divider while keeping the app itself below the docked divider, so instead
4851         // we use relative layering of the IME targets child windows, and place the
4852         // IME in the non-app layer (see {@link AboveAppWindowContainers#assignChildLayers}).
4853         //
4854         // In the case the IME target is animating, the animation Z order may be different
4855         // than the WindowContainer Z order, so it's difficult to be sure we have the correct
4856         // IME target. In this case we just layer the IME over all transitions by placing it in the
4857         // above applications layer.
4858         //
4859         // In the case where we have no IME target we assign it where it's base layer would
4860         // place it in the AboveAppWindowContainers.
4861         //
4862         // Keep IME window in mAboveAppWindowsContainers as long as app's starting window exists
4863         // so it get's layered above the starting window.
4864         if (imeTarget != null
4865                 && !(imeTarget.mAppToken != null && imeTarget.mAppToken.hasStartingWindow())
4866                 && (!(imeTarget.inSplitScreenWindowingMode() || imeTarget.mToken.isAppAnimating())
4867                 && (imeTarget.getSurfaceControl() != null))) {
4868             mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
4869                     // TODO: We need to use an extra level on the app surface to ensure
4870                     // this is always above SurfaceView but always below attached window.
4871                     1);
4872             needAssignIme = false;
4873         }
4874 
4875         // Above we have assigned layers to our children, now we ask them to assign
4876         // layers to their children.
4877         mBelowAppWindowsContainers.assignChildLayers(t);
4878         mTaskStackContainers.assignChildLayers(t);
4879         mAboveAppWindowsContainers.assignChildLayers(t,
4880                 needAssignIme == true ? mImeWindowsContainers : null);
4881         mImeWindowsContainers.assignChildLayers(t);
4882     }
4883 
4884     /**
4885      * Here we satisfy an unfortunate special case of the IME in split-screen mode. Imagine
4886      * that the IME target is one of the docked applications. We'd like the docked divider to be
4887      * above both of the applications, and we'd like the IME to be above the docked divider.
4888      * However we need child windows of the applications to be above the IME (Text drag handles).
4889      * This is a non-strictly hierarcical layering and we need to break out of the Z ordering
4890      * somehow. We do this by relatively ordering children of the target to the IME in cooperation
4891      * with {@link WindowState#assignLayer}
4892      */
assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child)4893     void assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child) {
4894         child.assignRelativeLayer(t, mImeWindowsContainers.getSurfaceControl(), 1);
4895     }
4896 
4897     @Override
prepareSurfaces()4898     void prepareSurfaces() {
4899         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareSurfaces");
4900         try {
4901             final ScreenRotationAnimation screenRotationAnimation =
4902                     mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
4903             final Transaction transaction = getPendingTransaction();
4904             if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
4905                 screenRotationAnimation.getEnterTransformation().getMatrix().getValues(mTmpFloats);
4906                 transaction.setMatrix(mWindowingLayer,
4907                         mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
4908                         mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
4909                 transaction.setPosition(mWindowingLayer,
4910                         mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]);
4911                 transaction.setAlpha(mWindowingLayer,
4912                         screenRotationAnimation.getEnterTransformation().getAlpha());
4913             }
4914 
4915             super.prepareSurfaces();
4916 
4917             // TODO: Once we totally eliminate global transaction we will pass transaction in here
4918             //       rather than merging to global.
4919             SurfaceControl.mergeToGlobalTransaction(transaction);
4920         } finally {
4921             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4922         }
4923     }
4924 
assignStackOrdering()4925     void assignStackOrdering() {
4926         mTaskStackContainers.assignStackOrdering(getPendingTransaction());
4927     }
4928 
4929     /**
4930      * Increment the deferral count to determine whether to update the IME target.
4931      */
deferUpdateImeTarget()4932     void deferUpdateImeTarget() {
4933         mDeferUpdateImeTargetCount++;
4934     }
4935 
4936     /**
4937      * Decrement the deferral count to determine whether to update the IME target. If the count
4938      * reaches 0, a new ime target will get computed.
4939      */
continueUpdateImeTarget()4940     void continueUpdateImeTarget() {
4941         if (mDeferUpdateImeTargetCount == 0) {
4942             return;
4943         }
4944 
4945         mDeferUpdateImeTargetCount--;
4946         if (mDeferUpdateImeTargetCount == 0) {
4947             computeImeTarget(true /* updateImeTarget */);
4948         }
4949     }
4950 
4951     /**
4952      * @return Whether a new IME target should be computed.
4953      */
canUpdateImeTarget()4954     private boolean canUpdateImeTarget() {
4955         return mDeferUpdateImeTargetCount == 0;
4956     }
4957 
getInputMonitor()4958     InputMonitor getInputMonitor() {
4959         return mInputMonitor;
4960     }
4961 
4962     /**
4963      * @return Cached value whether we told display manager that we have content.
4964      */
getLastHasContent()4965     boolean getLastHasContent() {
4966         return mLastHasContent;
4967     }
4968 
registerPointerEventListener(@onNull PointerEventListener listener)4969     void registerPointerEventListener(@NonNull PointerEventListener listener) {
4970         mPointerEventDispatcher.registerInputEventListener(listener);
4971     }
4972 
unregisterPointerEventListener(@onNull PointerEventListener listener)4973     void unregisterPointerEventListener(@NonNull PointerEventListener listener) {
4974         mPointerEventDispatcher.unregisterInputEventListener(listener);
4975     }
4976 
prepareAppTransition(@indowManager.TransitionType int transit, boolean alwaysKeepCurrent)4977     void prepareAppTransition(@WindowManager.TransitionType int transit,
4978             boolean alwaysKeepCurrent) {
4979         prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
4980     }
4981 
prepareAppTransition(@indowManager.TransitionType int transit, boolean alwaysKeepCurrent, @WindowManager.TransitionFlags int flags, boolean forceOverride)4982     void prepareAppTransition(@WindowManager.TransitionType int transit,
4983             boolean alwaysKeepCurrent, @WindowManager.TransitionFlags int flags,
4984             boolean forceOverride) {
4985         final boolean prepared = mAppTransition.prepareAppTransitionLocked(
4986                 transit, alwaysKeepCurrent, flags, forceOverride);
4987         if (prepared && okToAnimate()) {
4988             mSkipAppTransitionAnimation = false;
4989         }
4990     }
4991 
executeAppTransition()4992     void executeAppTransition() {
4993         if (mAppTransition.isTransitionSet()) {
4994             if (DEBUG_APP_TRANSITIONS) {
4995                 Slog.w(TAG_WM, "Execute app transition: " + mAppTransition + ", displayId: "
4996                         + mDisplayId + " Callers=" + Debug.getCallers(5));
4997             }
4998             mAppTransition.setReady();
4999             mWmService.mWindowPlacerLocked.requestTraversal();
5000         }
5001     }
5002 
5003     /**
5004      * Update pendingLayoutChanges after app transition has finished.
5005      */
handleAnimatingStoppedAndTransition()5006     void handleAnimatingStoppedAndTransition() {
5007         int changes = 0;
5008 
5009         mAppTransition.setIdle();
5010 
5011         for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
5012             final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
5013             mAppTransition.notifyAppTransitionFinishedLocked(token);
5014         }
5015         mNoAnimationNotifyOnTransitionFinished.clear();
5016 
5017         mWallpaperController.hideDeferredWallpapersIfNeeded();
5018 
5019         onAppTransitionDone();
5020 
5021         changes |= FINISH_LAYOUT_REDO_LAYOUT;
5022         if (DEBUG_WALLPAPER_LIGHT) {
5023             Slog.v(TAG_WM, "Wallpaper layer changed: assigning layers + relayout");
5024         }
5025         computeImeTarget(true /* updateImeTarget */);
5026         mWallpaperMayChange = true;
5027         // Since the window list has been rebuilt, focus might have to be recomputed since the
5028         // actual order of windows might have changed again.
5029         mWmService.mFocusMayChange = true;
5030 
5031         pendingLayoutChanges |= changes;
5032     }
5033 
5034     /** Check if pending app transition is for activity / task launch. */
isNextTransitionForward()5035     boolean isNextTransitionForward() {
5036         final int transit = mAppTransition.getAppTransition();
5037         return transit == TRANSIT_ACTIVITY_OPEN
5038                 || transit == TRANSIT_TASK_OPEN
5039                 || transit == TRANSIT_TASK_TO_FRONT;
5040     }
5041 
5042     /**
5043      * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
5044      */
supportsSystemDecorations()5045     boolean supportsSystemDecorations() {
5046         return (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this)
5047                 || (mDisplay.getFlags() & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0
5048                 || (mWmService.mForceDesktopModeOnExternalDisplays && !isUntrustedVirtualDisplay()))
5049                 // VR virtual display will be used to run and render 2D app within a VR experience.
5050                 && mDisplayId != mWmService.mVr2dDisplayId;
5051     }
5052 
5053     /**
5054      * @return {@code true} if the display is non-system created virtual display.
5055      */
isUntrustedVirtualDisplay()5056     boolean isUntrustedVirtualDisplay() {
5057         return mDisplay.getType() == Display.TYPE_VIRTUAL
5058                 && mDisplay.getOwnerUid() != Process.SYSTEM_UID;
5059     }
5060 
5061     /**
5062      * Re-parent the DisplayContent's top surfaces, {@link #mWindowingLayer} and
5063      * {@link #mOverlayLayer} to the specified SurfaceControl.
5064      *
5065      * @param win The window which owns the SurfaceControl. This indicates the z-order of the
5066      *            windows of this display against the windows on the parent display.
5067      * @param sc The new SurfaceControl, where the DisplayContent's surfaces will be re-parented to.
5068      */
reparentDisplayContent(WindowState win, SurfaceControl sc)5069     void reparentDisplayContent(WindowState win, SurfaceControl sc) {
5070         mParentWindow = win;
5071         mParentWindow.addEmbeddedDisplayContent(this);
5072         mParentSurfaceControl = sc;
5073         if (mPortalWindowHandle == null) {
5074             mPortalWindowHandle = createPortalWindowHandle(sc.toString());
5075         }
5076         getPendingTransaction().setInputWindowInfo(sc, mPortalWindowHandle)
5077                 .reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc);
5078     }
5079 
5080     /**
5081      * Get the window which owns the surface that this DisplayContent is re-parented to.
5082      *
5083      * @return the parent window.
5084      */
getParentWindow()5085     WindowState getParentWindow() {
5086         return mParentWindow;
5087     }
5088 
5089     /**
5090      * Update the location of this display in the parent window. This enables windows in this
5091      * display to compute the global transformation matrix.
5092      *
5093      * @param win The parent window of this display.
5094      * @param x The x coordinate in the parent window.
5095      * @param y The y coordinate in the parent window.
5096      */
updateLocation(WindowState win, int x, int y)5097     void updateLocation(WindowState win, int x, int y) {
5098         if (mParentWindow != win) {
5099             throw new IllegalArgumentException(
5100                     "The given window is not the parent window of this display.");
5101         }
5102         if (!mLocationInParentWindow.equals(x, y)) {
5103             mLocationInParentWindow.set(x, y);
5104             if (mWmService.mAccessibilityController != null) {
5105                 mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
5106             }
5107             notifyLocationInParentDisplayChanged();
5108         }
5109     }
5110 
getLocationInParentWindow()5111     Point getLocationInParentWindow() {
5112         return mLocationInParentWindow;
5113     }
5114 
getLocationInParentDisplay()5115     Point getLocationInParentDisplay() {
5116         final Point location = new Point();
5117         if (mParentWindow != null) {
5118             // LocationInParentWindow indicates the offset to (0,0) of window, but what we need is
5119             // the offset to (0,0) of display.
5120             DisplayContent dc = this;
5121             do {
5122                 final WindowState displayParent = dc.getParentWindow();
5123                 location.x += displayParent.getFrameLw().left
5124                         + (dc.getLocationInParentWindow().x * displayParent.mGlobalScale + 0.5f);
5125                 location.y += displayParent.getFrameLw().top
5126                         + (dc.getLocationInParentWindow().y * displayParent.mGlobalScale + 0.5f);
5127                 dc = displayParent.getDisplayContent();
5128             } while (dc != null && dc.getParentWindow() != null);
5129         }
5130         return location;
5131     }
5132 
notifyLocationInParentDisplayChanged()5133     void notifyLocationInParentDisplayChanged() {
5134         forAllWindows(w -> {
5135             w.updateLocationInParentDisplayIfNeeded();
5136         }, false /* traverseTopToBottom */);
5137     }
5138 
5139     @VisibleForTesting
getWindowingLayer()5140     SurfaceControl getWindowingLayer() {
5141         return mWindowingLayer;
5142     }
5143 
5144     /**
5145      * Updates the display's system gesture exclusion.
5146      *
5147      * @return true, if the exclusion changed.
5148      */
updateSystemGestureExclusion()5149     boolean updateSystemGestureExclusion() {
5150         if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 0) {
5151             // No one's interested anyways.
5152             return false;
5153         }
5154 
5155         final Region systemGestureExclusion = Region.obtain();
5156         mSystemGestureExclusionWasRestricted = calculateSystemGestureExclusion(
5157                 systemGestureExclusion, mSystemGestureExclusionUnrestricted);
5158         try {
5159             if (mSystemGestureExclusion.equals(systemGestureExclusion)) {
5160                 return false;
5161             }
5162             mSystemGestureExclusion.set(systemGestureExclusion);
5163             final Region unrestrictedOrNull = mSystemGestureExclusionWasRestricted
5164                     ? mSystemGestureExclusionUnrestricted : null;
5165             for (int i = mSystemGestureExclusionListeners.beginBroadcast() - 1; i >= 0; --i) {
5166                 try {
5167                     mSystemGestureExclusionListeners.getBroadcastItem(i)
5168                             .onSystemGestureExclusionChanged(mDisplayId, systemGestureExclusion,
5169                                     unrestrictedOrNull);
5170                 } catch (RemoteException e) {
5171                     Slog.e(TAG, "Failed to notify SystemGestureExclusionListener", e);
5172                 }
5173             }
5174             mSystemGestureExclusionListeners.finishBroadcast();
5175             return true;
5176         } finally {
5177             systemGestureExclusion.recycle();
5178         }
5179     }
5180 
5181     /**
5182      * Calculates the system gesture exclusion.
5183      *
5184      * @param outExclusion will be set to the gesture exclusion region
5185      * @param outExclusionUnrestricted will be set to the gesture exclusion region without
5186      *                                 any restrictions applied.
5187      * @return whether any restrictions were applied, i.e. outExclusion and outExclusionUnrestricted
5188      *         differ.
5189      */
5190     @VisibleForTesting
calculateSystemGestureExclusion(Region outExclusion, @Nullable Region outExclusionUnrestricted)5191     boolean calculateSystemGestureExclusion(Region outExclusion, @Nullable
5192             Region outExclusionUnrestricted) {
5193         outExclusion.setEmpty();
5194         if (outExclusionUnrestricted != null) {
5195             outExclusionUnrestricted.setEmpty();
5196         }
5197         final Region unhandled = Region.obtain();
5198         unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight);
5199 
5200         final Rect leftEdge = mInsetsStateController.getSourceProvider(TYPE_LEFT_GESTURES)
5201                 .getSource().getFrame();
5202         final Rect rightEdge = mInsetsStateController.getSourceProvider(TYPE_RIGHT_GESTURES)
5203                 .getSource().getFrame();
5204 
5205         final Region touchableRegion = Region.obtain();
5206         final Region local = Region.obtain();
5207         final int[] remainingLeftRight =
5208                 {mSystemGestureExclusionLimit, mSystemGestureExclusionLimit};
5209 
5210         // Traverse all windows top down to assemble the gesture exclusion rects.
5211         // For each window, we only take the rects that fall within its touchable region.
5212         forAllWindows(w -> {
5213             if (w.cantReceiveTouchInput() || !w.isVisible()
5214                     || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
5215                     || unhandled.isEmpty()) {
5216                 return;
5217             }
5218 
5219             // Get the touchable region of the window, and intersect with where the screen is still
5220             // touchable, i.e. touchable regions on top are not covering it yet.
5221             w.getEffectiveTouchableRegion(touchableRegion);
5222             touchableRegion.op(unhandled, Op.INTERSECT);
5223 
5224             if (w.isImplicitlyExcludingAllSystemGestures()) {
5225                 local.set(touchableRegion);
5226             } else {
5227                 rectListToRegion(w.getSystemGestureExclusion(), local);
5228 
5229                 // Transform to display coordinates
5230                 local.scale(w.mGlobalScale);
5231                 final Rect frame = w.getWindowFrames().mFrame;
5232                 local.translate(frame.left, frame.top);
5233 
5234                 // A window can only exclude system gestures where it is actually touchable
5235                 local.op(touchableRegion, Op.INTERSECT);
5236             }
5237 
5238             // Apply restriction if necessary.
5239             if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) {
5240 
5241                 // Processes the region along the left edge.
5242                 remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
5243                         remainingLeftRight[0], w, EXCLUSION_LEFT);
5244 
5245                 // Processes the region along the right edge.
5246                 remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
5247                         remainingLeftRight[1], w, EXCLUSION_RIGHT);
5248 
5249                 // Adds the middle (unrestricted area)
5250                 final Region middle = Region.obtain(local);
5251                 middle.op(leftEdge, Op.DIFFERENCE);
5252                 middle.op(rightEdge, Op.DIFFERENCE);
5253                 outExclusion.op(middle, Op.UNION);
5254                 middle.recycle();
5255             } else {
5256                 boolean loggable = needsGestureExclusionRestrictions(w, 0 /* lastSysUiVis */);
5257                 if (loggable) {
5258                     addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
5259                             Integer.MAX_VALUE, w, EXCLUSION_LEFT);
5260                     addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
5261                             Integer.MAX_VALUE, w, EXCLUSION_RIGHT);
5262                 }
5263                 outExclusion.op(local, Op.UNION);
5264             }
5265             if (outExclusionUnrestricted != null) {
5266                 outExclusionUnrestricted.op(local, Op.UNION);
5267             }
5268             unhandled.op(touchableRegion, Op.DIFFERENCE);
5269         }, true /* topToBottom */);
5270         local.recycle();
5271         touchableRegion.recycle();
5272         unhandled.recycle();
5273         return remainingLeftRight[0] < mSystemGestureExclusionLimit
5274                 || remainingLeftRight[1] < mSystemGestureExclusionLimit;
5275     }
5276 
5277     /**
5278      * @return Whether gesture exclusion area should be restricted from the window depending on the
5279      *         current SystemUI visibility flags.
5280      */
needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility)5281     private static boolean needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility) {
5282         final int type = win.mAttrs.type;
5283         final int stickyHideNavFlags =
5284                 SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
5285         final boolean stickyHideNav =
5286                 (sysUiVisibility & stickyHideNavFlags) == stickyHideNavFlags;
5287         return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_STATUS_BAR
5288                 && win.getActivityType() != ACTIVITY_TYPE_HOME;
5289     }
5290 
5291     /**
5292      * @return Whether gesture exclusion area should be logged for the given window
5293      */
logsGestureExclusionRestrictions(WindowState win)5294     static boolean logsGestureExclusionRestrictions(WindowState win) {
5295         if (win.mWmService.mSystemGestureExclusionLogDebounceTimeoutMillis <= 0) {
5296             return false;
5297         }
5298         final WindowManager.LayoutParams attrs = win.getAttrs();
5299         final int type = attrs.type;
5300         return type != TYPE_WALLPAPER
5301                 && type != TYPE_APPLICATION_STARTING
5302                 && type != TYPE_NAVIGATION_BAR
5303                 && (attrs.flags & FLAG_NOT_TOUCHABLE) == 0
5304                 && needsGestureExclusionRestrictions(win, 0 /* sysUiVisibility */)
5305                 && win.getDisplayContent().mDisplayPolicy.hasSideGestures();
5306     }
5307 
5308     /**
5309      * Adds a local gesture exclusion area to the global area while applying a limit per edge.
5310      *
5311      * @param local The gesture exclusion area to add.
5312      * @param global The destination.
5313      * @param edge Only processes the part in that region.
5314      * @param limit How much limit in pixels we have.
5315      * @param win The WindowState that is being processed
5316      * @param side The side that is being processed, either {@link WindowState#EXCLUSION_LEFT} or
5317      *             {@link WindowState#EXCLUSION_RIGHT}
5318      * @return How much of the limit is remaining.
5319      */
addToGlobalAndConsumeLimit(Region local, Region global, Rect edge, int limit, WindowState win, int side)5320     private static int addToGlobalAndConsumeLimit(Region local, Region global, Rect edge,
5321             int limit, WindowState win, int side) {
5322         final Region r = Region.obtain(local);
5323         r.op(edge, Op.INTERSECT);
5324 
5325         final int[] remaining = {limit};
5326         final int[] requestedExclusion = {0};
5327         forEachRectReverse(r, rect -> {
5328             if (remaining[0] <= 0) {
5329                 return;
5330             }
5331             final int height = rect.height();
5332             requestedExclusion[0] += height;
5333             if (height > remaining[0]) {
5334                 rect.top = rect.bottom - remaining[0];
5335             }
5336             remaining[0] -= height;
5337             global.op(rect, Op.UNION);
5338         });
5339 
5340         final int grantedExclusion = limit - remaining[0];
5341         win.setLastExclusionHeights(side, requestedExclusion[0], grantedExclusion);
5342 
5343         r.recycle();
5344         return remaining[0];
5345     }
5346 
registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener)5347     void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
5348         mSystemGestureExclusionListeners.register(listener);
5349         final boolean changed;
5350         if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 1) {
5351             changed = updateSystemGestureExclusion();
5352         } else {
5353             changed = false;
5354         }
5355 
5356         if (!changed) {
5357             final Region unrestrictedOrNull = mSystemGestureExclusionWasRestricted
5358                     ? mSystemGestureExclusionUnrestricted : null;
5359             // If updateSystemGestureExclusion changed the exclusion, it will already have
5360             // notified the listener. Otherwise, we'll do it here.
5361             try {
5362                 listener.onSystemGestureExclusionChanged(mDisplayId, mSystemGestureExclusion,
5363                         unrestrictedOrNull);
5364             } catch (RemoteException e) {
5365                 Slog.e(TAG, "Failed to notify SystemGestureExclusionListener during register", e);
5366             }
5367         }
5368     }
5369 
unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener)5370     void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
5371         mSystemGestureExclusionListeners.unregister(listener);
5372     }
5373 
5374     /**
5375      * Create a portal window handle for input. This window transports any touch to the display
5376      * indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window.
5377      *
5378      * @param name The name of the portal window handle.
5379      * @return the new portal window handle.
5380      */
createPortalWindowHandle(String name)5381     private InputWindowHandle createPortalWindowHandle(String name) {
5382         // Let surface flinger to set the display ID of this input window handle because we don't
5383         // know which display the parent surface control is on.
5384         final InputWindowHandle portalWindowHandle = new InputWindowHandle(
5385                 null /* inputApplicationHandle */, null /* clientWindow */, INVALID_DISPLAY);
5386         portalWindowHandle.name = name;
5387         portalWindowHandle.token = new Binder();
5388         portalWindowHandle.layoutParamsFlags =
5389                 FLAG_SPLIT_TOUCH | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL;
5390         getBounds(mTmpBounds);
5391         portalWindowHandle.touchableRegion.set(mTmpBounds);
5392         portalWindowHandle.scaleFactor = 1f;
5393         portalWindowHandle.ownerPid = Process.myPid();
5394         portalWindowHandle.ownerUid = Process.myUid();
5395         portalWindowHandle.portalToDisplayId = mDisplayId;
5396         return portalWindowHandle;
5397     }
5398 
5399     /**
5400      * @see IWindowManager#setForwardedInsets
5401      */
setForwardedInsets(Insets insets)5402     public void setForwardedInsets(Insets insets) {
5403         if (insets == null) {
5404             insets = Insets.NONE;
5405         }
5406         if (mDisplayPolicy.getForwardedInsets().equals(insets)) {
5407             return;
5408         }
5409         mDisplayPolicy.setForwardedInsets(insets);
5410         setLayoutNeeded();
5411         mWmService.mWindowPlacerLocked.requestTraversal();
5412     }
5413 
getMetricsLogger()5414     protected MetricsLogger getMetricsLogger() {
5415         if (mMetricsLogger == null) {
5416             mMetricsLogger = new MetricsLogger();
5417         }
5418         return mMetricsLogger;
5419     }
5420 }
5421