• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.INVALID_TASK_ID;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
24 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
25 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
26 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
27 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
28 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
29 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
30 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
31 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
32 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
33 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
34 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
35 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
36 import static android.os.Build.VERSION_CODES.N;
37 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
38 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
39 import static android.util.RotationUtils.deltaRotation;
40 import static android.view.Display.DEFAULT_DISPLAY;
41 import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
42 import static android.view.Display.FLAG_PRIVATE;
43 import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
44 import static android.view.Display.INVALID_DISPLAY;
45 import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
46 import static android.view.InsetsState.ITYPE_IME;
47 import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
48 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
49 import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
50 import static android.view.Surface.ROTATION_0;
51 import static android.view.Surface.ROTATION_270;
52 import static android.view.Surface.ROTATION_90;
53 import static android.view.View.GONE;
54 import static android.view.WindowInsets.Type.displayCutout;
55 import static android.view.WindowInsets.Type.ime;
56 import static android.view.WindowInsets.Type.systemBars;
57 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
58 import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
59 import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
60 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
61 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
62 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
63 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
64 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
65 import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
66 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
67 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
68 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
69 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
70 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
71 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
72 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
73 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
74 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
75 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
76 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
77 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
78 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
79 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
80 import static android.view.WindowManager.TRANSIT_OPEN;
81 import static android.view.WindowManager.TRANSIT_TO_FRONT;
82 import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
83 import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
84 
85 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
86 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
87 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
88 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
89 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
90 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
91 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
92 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
93 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
94 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
95 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
96 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
97 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
98 import static com.android.server.wm.DisplayContentProto.APP_TRANSITION;
99 import static com.android.server.wm.DisplayContentProto.CLOSING_APPS;
100 import static com.android.server.wm.DisplayContentProto.CURRENT_FOCUS;
101 import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES;
102 import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO;
103 import static com.android.server.wm.DisplayContentProto.DISPLAY_READY;
104 import static com.android.server.wm.DisplayContentProto.DISPLAY_ROTATION;
105 import static com.android.server.wm.DisplayContentProto.DPI;
106 import static com.android.server.wm.DisplayContentProto.FOCUSED_APP;
107 import static com.android.server.wm.DisplayContentProto.FOCUSED_ROOT_TASK_ID;
108 import static com.android.server.wm.DisplayContentProto.ID;
109 import static com.android.server.wm.DisplayContentProto.IME_INSETS_SOURCE_PROVIDER;
110 import static com.android.server.wm.DisplayContentProto.IME_POLICY;
111 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_CONTROL_TARGET;
112 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_INPUT_TARGET;
113 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_TARGET;
114 import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
115 import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
116 import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
117 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
118 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
119 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
120 import static com.android.server.wm.Task.ActivityState.RESUMED;
121 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
122 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
123 import static com.android.server.wm.WindowContainerChildProto.DISPLAY_CONTENT;
124 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
125 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
126 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
127 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
128 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
129 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
130 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
131 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
132 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
133 import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE;
134 import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
135 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
136 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
137 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS;
138 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS;
139 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
140 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
141 import static com.android.server.wm.WindowManagerService.dipToPixel;
142 import static com.android.server.wm.WindowState.EXCLUSION_LEFT;
143 import static com.android.server.wm.WindowState.EXCLUSION_RIGHT;
144 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
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.annotation.IntDef;
150 import android.annotation.NonNull;
151 import android.annotation.Nullable;
152 import android.app.ActivityManager;
153 import android.app.ActivityManagerInternal;
154 import android.content.Context;
155 import android.content.pm.ActivityInfo;
156 import android.content.pm.ActivityInfo.ScreenOrientation;
157 import android.content.res.CompatibilityInfo;
158 import android.content.res.Configuration;
159 import android.graphics.Bitmap;
160 import android.graphics.ColorSpace;
161 import android.graphics.GraphicBuffer;
162 import android.graphics.Insets;
163 import android.graphics.Point;
164 import android.graphics.Rect;
165 import android.graphics.Region;
166 import android.graphics.Region.Op;
167 import android.hardware.HardwareBuffer;
168 import android.hardware.display.DisplayManagerInternal;
169 import android.metrics.LogMaker;
170 import android.os.Binder;
171 import android.os.Bundle;
172 import android.os.Debug;
173 import android.os.Handler;
174 import android.os.IBinder;
175 import android.os.Message;
176 import android.os.Process;
177 import android.os.RemoteCallbackList;
178 import android.os.RemoteException;
179 import android.os.SystemClock;
180 import android.os.Trace;
181 import android.os.UserHandle;
182 import android.provider.Settings;
183 import android.util.ArraySet;
184 import android.util.DisplayMetrics;
185 import android.util.IntArray;
186 import android.util.RotationUtils;
187 import android.util.Slog;
188 import android.util.SparseArray;
189 import android.util.SparseBooleanArray;
190 import android.util.proto.ProtoOutputStream;
191 import android.view.Display;
192 import android.view.DisplayCutout;
193 import android.view.DisplayCutout.CutoutPathParserInfo;
194 import android.view.DisplayInfo;
195 import android.view.Gravity;
196 import android.view.IDisplayWindowInsetsController;
197 import android.view.ISystemGestureExclusionListener;
198 import android.view.IWindow;
199 import android.view.InputChannel;
200 import android.view.InputDevice;
201 import android.view.InputWindowHandle;
202 import android.view.InsetsSource;
203 import android.view.InsetsState;
204 import android.view.InsetsState.InternalInsetsType;
205 import android.view.MagnificationSpec;
206 import android.view.PrivacyIndicatorBounds;
207 import android.view.RemoteAnimationDefinition;
208 import android.view.RoundedCorners;
209 import android.view.Surface;
210 import android.view.Surface.Rotation;
211 import android.view.SurfaceControl;
212 import android.view.SurfaceControl.Transaction;
213 import android.view.SurfaceSession;
214 import android.view.View;
215 import android.view.WindowInsets;
216 import android.view.WindowManager;
217 import android.view.WindowManager.DisplayImePolicy;
218 import android.view.WindowManagerPolicyConstants.PointerEventListener;
219 import android.window.IDisplayAreaOrganizer;
220 
221 import com.android.internal.annotations.VisibleForTesting;
222 import com.android.internal.logging.MetricsLogger;
223 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
224 import com.android.internal.protolog.common.ProtoLog;
225 import com.android.internal.util.ToBooleanFunction;
226 import com.android.internal.util.function.TriConsumer;
227 import com.android.internal.util.function.pooled.PooledConsumer;
228 import com.android.internal.util.function.pooled.PooledFunction;
229 import com.android.internal.util.function.pooled.PooledLambda;
230 import com.android.internal.util.function.pooled.PooledPredicate;
231 import com.android.server.inputmethod.InputMethodManagerInternal;
232 import com.android.server.policy.WindowManagerPolicy;
233 import com.android.server.wm.utils.DisplayRotationUtil;
234 import com.android.server.wm.utils.RotationCache;
235 import com.android.server.wm.utils.WmDisplayCutout;
236 
237 import java.io.PrintWriter;
238 import java.lang.annotation.Retention;
239 import java.lang.annotation.RetentionPolicy;
240 import java.util.ArrayList;
241 import java.util.HashMap;
242 import java.util.Iterator;
243 import java.util.LinkedList;
244 import java.util.List;
245 import java.util.Objects;
246 import java.util.Set;
247 import java.util.function.Consumer;
248 import java.util.function.Predicate;
249 
250 /**
251  * Utility class for keeping track of the WindowStates and other pertinent contents of a
252  * particular Display.
253  */
254 class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.DisplayContentInfo {
255     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
256 
257     /** The default scaling mode that scales content automatically. */
258     static final int FORCE_SCALING_MODE_AUTO = 0;
259     /** For {@link #setForcedScalingMode} to apply flag {@link Display#FLAG_SCALING_DISABLED}. */
260     static final int FORCE_SCALING_MODE_DISABLED = 1;
261 
262     @IntDef(prefix = { "FORCE_SCALING_MODE_" }, value = {
263             FORCE_SCALING_MODE_AUTO,
264             FORCE_SCALING_MODE_DISABLED
265     })
266     @Retention(RetentionPolicy.SOURCE)
267     @interface ForceScalingMode {}
268 
269     final ActivityTaskManagerService mAtmService;
270 
271     /**
272      * Unique logical identifier of this display.
273      *
274      * @see DisplayInfo#displayId
275      */
276     final int mDisplayId;
277 
278     /**
279      * Unique physical identifier of this display. Unlike {@link #mDisplayId} this value can change
280      * at runtime if the underlying physical display changes.
281      *
282      * @see DisplayInfo#uniqueId
283      */
284     @Nullable
285     String mCurrentUniqueDisplayId;
286 
287     /**
288      * We organize all top-level Surfaces into the following layer.
289      * It contains a few Surfaces which are always on top of others, and omitted from
290      * Screen-Magnification, for example the strict mode flash or the fullscreen magnification
291      * overlay.
292      */
293     private SurfaceControl mOverlayLayer;
294 
295     /**
296      * The direct child layer of the display to put all non-overlay windows. This is also used for
297      * screen rotation animation so that there is a parent layer to put the animation leash.
298      */
299     private final SurfaceControl mWindowingLayer;
300 
301     // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
302     // on the IME target. We mainly have this container grouping so we can keep track of all the IME
303     // window containers together and move them in-sync if/when needed. We use a subclass of
304     // WindowContainer which is omitted from screen magnification, as the IME is never magnified.
305     // TODO(display-area): is "no magnification" in the comment still true?
306     private final ImeContainer mImeWindowsContainer = new ImeContainer(mWmService);
307 
308     @VisibleForTesting
309     final DisplayAreaPolicy mDisplayAreaPolicy;
310 
311     private WindowState mTmpWindow;
312     private boolean mUpdateImeTarget;
313     private boolean mTmpInitial;
314     private int mMaxUiWidth;
315 
316     final AppTransition mAppTransition;
317     final AppTransitionController mAppTransitionController;
318     boolean mSkipAppTransitionAnimation = false;
319 
320     final ArraySet<ActivityRecord> mOpeningApps = new ArraySet<>();
321     final ArraySet<ActivityRecord> mClosingApps = new ArraySet<>();
322     final ArraySet<WindowContainer> mChangingContainers = new ArraySet<>();
323     final UnknownAppVisibilityController mUnknownAppVisibilityController;
324 
325     private MetricsLogger mMetricsLogger;
326 
327     /**
328      * List of clients without a transtiton animation that we notify once we are done
329      * transitioning since they won't be notified through the app window animator.
330      */
331     final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
332 
333     // Mapping from a token IBinder to a WindowToken object on this display.
334     private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
335 
336     // Initial display metrics.
337     int mInitialDisplayWidth = 0;
338     int mInitialDisplayHeight = 0;
339     int mInitialDisplayDensity = 0;
340 
341     DisplayCutout mInitialDisplayCutout;
342     private final RotationCache<DisplayCutout, WmDisplayCutout> mDisplayCutoutCache
343             = new RotationCache<>(this::calculateDisplayCutoutForRotationUncached);
344     boolean mIgnoreDisplayCutout;
345 
346     RoundedCorners mInitialRoundedCorners;
347     private final RotationCache<RoundedCorners, RoundedCorners> mRoundedCornerCache =
348             new RotationCache<>(this::calculateRoundedCornersForRotationUncached);
349 
350     PrivacyIndicatorBounds mCurrentPrivacyIndicatorBounds = new PrivacyIndicatorBounds();
351     private final RotationCache<PrivacyIndicatorBounds, PrivacyIndicatorBounds>
352             mPrivacyIndicatorBoundsCache = new
353             RotationCache<>(this::calculatePrivacyIndicatorBoundsForRotationUncached);
354 
355     /**
356      * Overridden display size. Initialized with {@link #mInitialDisplayWidth}
357      * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size".
358      * @see WindowManagerService#setForcedDisplaySize(int, int, int)
359      */
360     int mBaseDisplayWidth = 0;
361     int mBaseDisplayHeight = 0;
362     boolean mIsSizeForced = false;
363 
364     /**
365      * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity}
366      * but can be set from Settings or via shell command "adb shell wm density".
367      * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
368      */
369     int mBaseDisplayDensity = 0;
370     boolean mIsDensityForced = false;
371 
372     /**
373      * Whether to disable display scaling. This can be set via shell command "adb shell wm scaling".
374      * @see WindowManagerService#setForcedDisplayScalingMode(int, int)
375      */
376     boolean mDisplayScalingDisabled;
377     final Display mDisplay;
378     private final DisplayInfo mDisplayInfo = new DisplayInfo();
379     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
380     private final DisplayPolicy mDisplayPolicy;
381     private final DisplayRotation mDisplayRotation;
382     DisplayFrames mDisplayFrames;
383 
384     private final RemoteCallbackList<ISystemGestureExclusionListener>
385             mSystemGestureExclusionListeners = new RemoteCallbackList<>();
386     private final Region mSystemGestureExclusion = new Region();
387     private boolean mSystemGestureExclusionWasRestricted = false;
388     private final Region mSystemGestureExclusionUnrestricted = new Region();
389     private int mSystemGestureExclusionLimit;
390 
391     /**
392      * For default display it contains real metrics, empty for others.
393      * @see WindowManagerService#createWatermark()
394      */
395     final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
396 
397     /** @see #computeCompatSmallestWidth(boolean, int, int, int) */
398     private final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
399 
400     /**
401      * Compat metrics computed based on {@link #mDisplayMetrics}.
402      * @see #updateDisplayAndOrientation(int)
403      */
404     private final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
405 
406     /** The desired scaling factor for compatible apps. */
407     float mCompatibleScreenScale;
408 
409     /** @see #getCurrentOverrideConfigurationChanges */
410     private int mCurrentOverrideConfigurationChanges;
411 
412     /**
413      * The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. The
414      * orientation requests from apps would be ignored if the display is close-to-square.
415      */
416     @VisibleForTesting
417     final float mCloseToSquareMaxAspectRatio;
418 
419     /**
420      * Keep track of wallpaper visibility to notify changes.
421      */
422     private boolean mLastWallpaperVisible = false;
423 
424     private Rect mBaseDisplayRect = new Rect();
425 
426     // Accessed directly by all users.
427     private boolean mLayoutNeeded;
428     int pendingLayoutChanges;
429 
430     /**
431      * Used to gate application window layout until we have sent the complete configuration.
432      * TODO: There are still scenarios where we may be out of sync with the client. Ideally
433      *       we want to replace this flag with a mechanism that will confirm the configuration
434      *       applied by the client is the one expected by the system server.
435      */
436     boolean mWaitingForConfig;
437 
438     // TODO(multi-display): remove some of the usages.
439     @VisibleForTesting
440     boolean isDefaultDisplay;
441 
442     /**
443      * Flag indicating whether WindowManager should override info for this display in
444      * DisplayManager.
445      */
446     boolean mShouldOverrideDisplayConfiguration = true;
447 
448     /** Window tokens that are in the process of exiting, but still on screen for animations. */
449     final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
450 
451     /** Detect user tapping outside of current focused task bounds .*/
452     @VisibleForTesting
453     final TaskTapPointerEventListener mTapDetector;
454 
455     /** Detect user tapping outside of current focused root task bounds .*/
456     private Region mTouchExcludeRegion = new Region();
457 
458     /** Save allocating when calculating rects */
459     private final Rect mTmpRect = new Rect();
460     private final Rect mTmpRect2 = new Rect();
461     private final Region mTmpRegion = new Region();
462 
463     /** Used for handing back size of display */
464     private final Rect mTmpBounds = new Rect();
465 
466     private final Configuration mTmpConfiguration = new Configuration();
467 
468     /** Remove this display when animation on it has completed. */
469     private boolean mDeferredRemoval;
470 
471     final DockedTaskDividerController mDividerControllerLocked;
472     final PinnedTaskController mPinnedTaskController;
473 
474     final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
475     /** A collection of windows that provide tap exclude regions inside of them. */
476     final ArraySet<WindowState> mTapExcludeProvidingWindows = new ArraySet<>();
477 
478     private final LinkedList<ActivityRecord> mTmpUpdateAllDrawn = new LinkedList();
479 
480     private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
481             new TaskForResizePointSearchResult();
482     private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState =
483             new ApplySurfaceChangesTransactionState();
484 
485     // {@code false} if this display is in the processing of being created.
486     private boolean mDisplayReady = false;
487 
488     WallpaperController mWallpaperController;
489 
490     boolean mWallpaperMayChange = false;
491 
492     private final SurfaceSession mSession = new SurfaceSession();
493 
494     /**
495      * Window that is currently interacting with the user. This window is responsible for receiving
496      * key events and pointer events from the user.
497      */
498     WindowState mCurrentFocus = null;
499 
500     /**
501      * The last focused window that we've notified the client that the focus is changed.
502      */
503     WindowState mLastFocus = null;
504 
505     /**
506      * The foreground app of this display. Windows below this app cannot be the focused window. If
507      * the user taps on the area outside of the task of the focused app, we will notify AM about the
508      * new task the user wants to interact with.
509      */
510     ActivityRecord mFocusedApp = null;
511 
512     /**
513      * We only respect the orientation request from apps below this {@link TaskDisplayArea}.
514      * It is the last focused {@link TaskDisplayArea} on this display that handles orientation
515      * request.
516      */
517     @Nullable
518     private TaskDisplayArea mOrientationRequestingTaskDisplayArea = null;
519 
520     /**
521      * The launching activity which is using fixed rotation transformation.
522      *
523      * @see #handleTopActivityLaunchingInDifferentOrientation
524      * @see #setFixedRotationLaunchingApp(ActivityRecord, int)
525      * @see DisplayRotation#shouldRotateSeamlessly
526      */
527     private ActivityRecord mFixedRotationLaunchingApp;
528 
529     /** The delay to avoid toggling the animation quickly. */
530     private static final long FIXED_ROTATION_HIDE_ANIMATION_DEBOUNCE_DELAY_MS = 250;
531     private FadeRotationAnimationController mFadeRotationAnimationController;
532 
533     final FixedRotationTransitionListener mFixedRotationTransitionListener =
534             new FixedRotationTransitionListener();
535 
536     /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
537     final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
538 
539     /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
540     final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
541 
542     /** Windows whose client's insets states are not up-to-date. */
543     final ArrayList<WindowState> mWinInsetsChanged = new ArrayList<>();
544 
545     private ScreenRotationAnimation mScreenRotationAnimation;
546 
547     /**
548      * Sequence number for the current layout pass.
549      */
550     int mLayoutSeq = 0;
551 
552     /**
553      * Specifies the count to determine whether to defer updating the IME target until ready.
554      */
555     private int mDeferUpdateImeTargetCount;
556 
557     private MagnificationSpec mMagnificationSpec;
558 
559     private InputMonitor mInputMonitor;
560 
561     /** Caches the value whether told display manager that we have content. */
562     private boolean mLastHasContent;
563 
564     private DisplayRotationUtil mRotationUtil = new DisplayRotationUtil();
565 
566     /**
567      * The input method window for this display.
568      */
569     WindowState mInputMethodWindow;
570 
571     /**
572      * This just indicates the window the input method is on top of, not
573      * necessarily the window its input is going to.
574      */
575     private WindowState mImeLayeringTarget;
576 
577     /**
578      * The window which receives input from the input method. This is also a candidate of the
579      * input method control target.
580      */
581     private WindowState mImeInputTarget;
582 
583     /**
584      * This controls the visibility and animation of the input method window.
585      */
586     private InsetsControlTarget mImeControlTarget;
587 
588     /**
589      * Used by {@link #getImeTarget} to return the IME target which the input method window on
590      * top of for adjusting input method window surface layer Z-Ordering.
591      *
592      * @see #mImeLayeringTarget
593      */
594     static final int IME_TARGET_LAYERING = 0;
595 
596     /**
597      * Used by {@link #getImeTarget} to return the IME target which received the input connection
598      * from IME.
599      *
600      * @see #mImeInputTarget
601      */
602     static final int IME_TARGET_INPUT = 1;
603 
604     /**
605      * Used by {@link #getImeTarget} to return the IME target which controls the IME insets
606      * visibility and animation.
607      *
608      * @see #mImeControlTarget
609      */
610     static final int IME_TARGET_CONTROL = 2;
611 
612     @IntDef(flag = false, prefix = { "IME_TARGET_" }, value = {
613             IME_TARGET_LAYERING,
614             IME_TARGET_INPUT,
615             IME_TARGET_CONTROL,
616     })
617     @Retention(RetentionPolicy.SOURCE)
618     @interface InputMethodTarget {}
619 
620     /** The surface parent of the IME container. */
621     private SurfaceControl mInputMethodSurfaceParent;
622 
623     /** If {@code true} hold off on modifying the animation layer of {@link #mImeLayeringTarget} */
624     boolean mImeLayeringTargetWaitingAnim;
625 
626     /** The screenshot IME surface to place on the task while transitioning to the next task. */
627     SurfaceControl mImeScreenshot;
628 
629     private final PointerEventDispatcher mPointerEventDispatcher;
630 
631     private final InsetsStateController mInsetsStateController;
632     private final InsetsPolicy mInsetsPolicy;
633 
634     /** @see #getParentWindow() */
635     private WindowState mParentWindow;
636 
637     private Point mLocationInParentWindow = new Point();
638     private SurfaceControl mParentSurfaceControl;
639     private InputWindowHandle mPortalWindowHandle;
640 
641     /** Corner radius that windows should have in order to match the display. */
642     private final float mWindowCornerRadius;
643 
644     final SparseArray<ShellRoot> mShellRoots = new SparseArray<>();
645     RemoteInsetsControlTarget mRemoteInsetsControlTarget = null;
646     private final IBinder.DeathRecipient mRemoteInsetsDeath =
647             () -> {
648                 synchronized (mWmService.mGlobalLock) {
649                     mRemoteInsetsControlTarget = null;
650                 }
651             };
652 
653     private RootWindowContainer mRootWindowContainer;
654 
655     /** Array of all UIDs that are present on the display. */
656     private IntArray mDisplayAccessUIDs = new IntArray();
657 
658     /** All tokens used to put activities on this root task to sleep (including mOffToken) */
659     final ArrayList<RootWindowContainer.SleepToken> mAllSleepTokens = new ArrayList<>();
660     /** The token acquirer to put root tasks on the display to sleep */
661     private final ActivityTaskManagerInternal.SleepTokenAcquirer mOffTokenAcquirer;
662 
663     private boolean mSleeping;
664 
665     /** We started the process of removing the display from the system. */
666     private boolean mRemoving;
667 
668     /**
669      * The display is removed from the system and we are just waiting for all activities on it to be
670      * finished before removing this object.
671      */
672     private boolean mRemoved;
673 
674     /** Set of activities in foreground size compat mode. */
675     private Set<ActivityRecord> mActiveSizeCompatActivities = new ArraySet<>();
676 
677     // Used in updating the display size
678     private Point mTmpDisplaySize = new Point();
679 
680     // Used in updating override configurations
681     private final Configuration mTempConfig = new Configuration();
682 
683     /**
684      * Used to prevent recursions when calling
685      * {@link #ensureActivitiesVisible(ActivityRecord, int, boolean, boolean)}
686      */
687     private boolean mInEnsureActivitiesVisible = false;
688 
689     // Used to indicate that the movement of child tasks to top will not move the display to top as
690     // well and thus won't change the top resumed / focused record
691     boolean mDontMoveToTop;
692 
693     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
694         WindowStateAnimator winAnimator = w.mWinAnimator;
695         final ActivityRecord activity = w.mActivityRecord;
696         if (winAnimator.mDrawState == READY_TO_SHOW) {
697             if (activity == null || activity.canShowWindows()) {
698                 if (w.performShowLocked()) {
699                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
700                     if (DEBUG_LAYOUT_REPEATS) {
701                         mWmService.mWindowPlacerLocked.debugLayoutRepeats(
702                                 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
703                     }
704                 }
705             }
706         }
707     };
708 
709     private final Consumer<WindowState> mScheduleToastTimeout = w -> {
710         final int lostFocusUid = mTmpWindow.mOwnerUid;
711         final Handler handler = mWmService.mH;
712         if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) {
713             if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) {
714                 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w),
715                         w.mAttrs.hideTimeoutMilliseconds);
716             }
717         }
718     };
719 
720     private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
721         final ActivityRecord focusedApp = mFocusedApp;
722         ProtoLog.v(WM_DEBUG_FOCUS, "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s",
723                 w, w.mAttrs.flags, w.canReceiveKeys(),
724                 w.canReceiveKeysReason(false /* fromUserTouch */));
725 
726         if (!w.canReceiveKeys()) {
727             return false;
728         }
729 
730         // When switching the app task, we keep the IME window visibility for better
731         // transitioning experiences.
732         // However, in case IME created a child window or the IME selection dialog without
733         // dismissing during the task switching to keep the window focus because IME window has
734         // higher window hierarchy, we don't give it focus if the next IME layering target
735         // doesn't request IME visible.
736         if (w.mIsImWindow && w.isChildWindow() && (mImeLayeringTarget == null
737                 || !mImeLayeringTarget.getRequestedVisibility(ITYPE_IME))) {
738             return false;
739         }
740         if (w.mAttrs.type == TYPE_INPUT_METHOD_DIALOG && mImeLayeringTarget != null
741                 && !mImeLayeringTarget.getRequestedVisibility(ITYPE_IME)
742                 && mImeLayeringTarget.isAnimating(PARENTS | TRANSITION,
743                 ANIMATION_TYPE_APP_TRANSITION)) {
744             return false;
745         }
746 
747         final ActivityRecord activity = w.mActivityRecord;
748 
749         if (focusedApp == null) {
750             ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
751                     "findFocusedWindow: focusedApp=null using new focus @ %s", w);
752             mTmpWindow = w;
753             return true;
754         }
755 
756         if (!focusedApp.windowsAreFocusable()) {
757             // Current focused app windows aren't focusable...
758             ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: focusedApp windows not"
759                     + " focusable using new focus @ %s", w);
760             mTmpWindow = w;
761             return true;
762         }
763 
764         // Descend through all of the app tokens and find the first that either matches
765         // win.mActivityRecord (return win) or mFocusedApp (return null).
766         if (activity != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
767             if (focusedApp.compareTo(activity) > 0) {
768                 // App root task below focused app root task. No focus for you!!!
769                 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
770                         "findFocusedWindow: Reached focused app=%s", focusedApp);
771                 mTmpWindow = null;
772                 return true;
773             }
774         }
775 
776         ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: Found new focus @ %s", w);
777         mTmpWindow = w;
778         return true;
779     };
780 
781     private final Consumer<WindowState> mPerformLayout = w -> {
782         // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
783         // wasting time and funky changes while a window is animating away.
784         final boolean gone = w.isGoneForLayout();
785 
786         if (DEBUG_LAYOUT && !w.mLayoutAttached) {
787             Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
788                     + " mLayoutAttached=" + w.mLayoutAttached
789                     + " config reported=" + w.isLastConfigReportedToClient());
790             final ActivityRecord activity = w.mActivityRecord;
791             if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
792                     + " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()
793                     + " visibleRequested=" + (activity != null && activity.mVisibleRequested)
794                     + " parentHidden=" + w.isParentWindowHidden());
795             else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
796                     + " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()
797                     + " visibleRequested=" + (activity != null && activity.mVisibleRequested)
798                     + " parentHidden=" + w.isParentWindowHidden());
799         }
800 
801         // If this view is GONE, then skip it -- keep the current frame, and let the caller know
802         // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
803         // since that means "perform layout as normal, just don't display").
804         if ((!gone || !w.mHaveFrame || w.mLayoutNeeded) && !w.mLayoutAttached) {
805             if (mTmpInitial) {
806                 w.resetContentChanged();
807             }
808             w.mSurfacePlacementNeeded = true;
809             w.mLayoutNeeded = false;
810             w.prelayout();
811             final boolean firstLayout = !w.isLaidOut();
812             getDisplayPolicy().layoutWindowLw(w, null, mDisplayFrames);
813             w.mLayoutSeq = mLayoutSeq;
814 
815             // If this is the first layout, we need to initialize the last frames and inset values,
816             // as otherwise we'd immediately cause an unnecessary resize.
817             if (firstLayout) {
818                 // The client may compute its actual requested size according to the first layout,
819                 // so we still request the window to resize if the current frame is empty.
820                 if (!w.getFrame().isEmpty()) {
821                     w.updateLastFrames();
822                 }
823                 w.onResizeHandled();
824                 w.updateLocationInParentDisplayIfNeeded();
825             }
826 
827             if (w.mActivityRecord != null) {
828                 w.mActivityRecord.layoutLetterbox(w);
829             }
830 
831             if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.getFrame()
832                     + " mContainingFrame=" + w.getContainingFrame()
833                     + " mDisplayFrame=" + w.getDisplayFrame());
834         }
835     };
836 
837     private final Consumer<WindowState> mPerformLayoutAttached = w -> {
838         if (w.mLayoutAttached) {
839             if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
840                     + " mViewVisibility=" + w.mViewVisibility
841                     + " mRelayoutCalled=" + w.mRelayoutCalled);
842             // If this view is GONE, then skip it -- keep the current frame, and let the caller
843             // know so they can ignore it if they want.  (We do the normal layout for INVISIBLE
844             // windows, since that means "perform layout as normal, just don't display").
845             if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
846                     || w.mLayoutNeeded) {
847                 if (mTmpInitial) {
848                     //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
849                     w.resetContentChanged();
850                 }
851                 w.mSurfacePlacementNeeded = true;
852                 w.mLayoutNeeded = false;
853                 w.prelayout();
854                 getDisplayPolicy().layoutWindowLw(w, w.getParentWindow(), mDisplayFrames);
855                 w.mLayoutSeq = mLayoutSeq;
856                 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrame()
857                         + " mContainingFrame=" + w.getContainingFrame()
858                         + " mDisplayFrame=" + w.getDisplayFrame());
859             }
860         }
861     };
862 
863     private final Predicate<WindowState> mComputeImeTargetPredicate = w -> {
864         if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w
865                 + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
866         return w.canBeImeTarget();
867     };
868 
869     private final Consumer<WindowState> mApplyPostLayoutPolicy =
870             w -> getDisplayPolicy().applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
871                     mImeLayeringTarget);
872 
873     private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
874         final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
875         final boolean obscuredChanged = w.mObscured !=
876                 mTmpApplySurfaceChangesTransactionState.obscured;
877         final RootWindowContainer root = mWmService.mRoot;
878 
879         // Update effect.
880         w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
881 
882         if (!mTmpApplySurfaceChangesTransactionState.obscured) {
883             final boolean isDisplayed = w.isDisplayed();
884 
885             if (isDisplayed && w.isObscuringDisplay()) {
886                 // This window completely covers everything behind it, so we want to leave all
887                 // of them as undimmed (for performance reasons).
888                 root.mObscuringWindow = w;
889                 mTmpApplySurfaceChangesTransactionState.obscured = true;
890             }
891 
892             final boolean displayHasContent = root.handleNotObscuredLocked(w,
893                     mTmpApplySurfaceChangesTransactionState.obscured,
894                     mTmpApplySurfaceChangesTransactionState.syswin);
895 
896             if (!mTmpApplySurfaceChangesTransactionState.displayHasContent
897                     && !getDisplayPolicy().isWindowExcludedFromContent(w)) {
898                 mTmpApplySurfaceChangesTransactionState.displayHasContent |= displayHasContent;
899             }
900 
901             if (w.mHasSurface && isDisplayed) {
902                 final int type = w.mAttrs.type;
903                 if (type == TYPE_SYSTEM_DIALOG
904                         || type == TYPE_SYSTEM_ERROR
905                         || (type == TYPE_NOTIFICATION_SHADE
906                             &&  mWmService.mPolicy.isKeyguardShowing())) {
907                     mTmpApplySurfaceChangesTransactionState.syswin = true;
908                 }
909                 if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
910                         && w.mAttrs.preferredRefreshRate != 0) {
911                     mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
912                             = w.mAttrs.preferredRefreshRate;
913                 }
914 
915                 mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing
916                         |= w.mAttrs.preferMinimalPostProcessing;
917 
918                 final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy()
919                         .getPreferredModeId(w);
920                 if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
921                         && preferredModeId != 0) {
922                     mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId;
923                 }
924 
925                 final float preferredMinRefreshRate = getDisplayPolicy().getRefreshRatePolicy()
926                         .getPreferredMinRefreshRate(w);
927                 if (mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate == 0
928                         && preferredMinRefreshRate != 0) {
929                     mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate =
930                             preferredMinRefreshRate;
931                 }
932 
933                 final float preferredMaxRefreshRate = getDisplayPolicy().getRefreshRatePolicy()
934                         .getPreferredMaxRefreshRate(w);
935                 if (mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate == 0
936                         && preferredMaxRefreshRate != 0) {
937                     mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate =
938                             preferredMaxRefreshRate;
939                 }
940             }
941         }
942 
943         if (obscuredChanged && w.isVisible() && mWallpaperController.isWallpaperTarget(w)) {
944             // This is the wallpaper target and its obscured state changed... make sure the
945             // current wallpaper's visibility has been updated accordingly.
946             mWallpaperController.updateWallpaperVisibility();
947         }
948 
949         w.handleWindowMovedIfNeeded();
950 
951         final WindowStateAnimator winAnimator = w.mWinAnimator;
952 
953         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
954         w.resetContentChanged();
955 
956         // Moved from updateWindowsAndWallpaperLocked().
957         if (w.mHasSurface) {
958             // Take care of the window being ready to display.
959             final boolean committed = winAnimator.commitFinishDrawingLocked();
960             if (isDefaultDisplay && committed) {
961                 if (w.hasWallpaper()) {
962                     if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
963                             "First draw done in potential wallpaper target " + w);
964                     mWallpaperMayChange = true;
965                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
966                     if (DEBUG_LAYOUT_REPEATS) {
967                         surfacePlacer.debugLayoutRepeats(
968                                 "wallpaper and commitFinishDrawingLocked true",
969                                 pendingLayoutChanges);
970                     }
971                 }
972             }
973         }
974 
975         final ActivityRecord activity = w.mActivityRecord;
976         if (activity != null && activity.isVisibleRequested()) {
977             activity.updateLetterboxSurface(w);
978             final boolean updateAllDrawn = activity.updateDrawnWindowStates(w);
979             if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(activity)) {
980                 mTmpUpdateAllDrawn.add(activity);
981             }
982         }
983 
984         w.updateResizingWindowIfNeeded();
985     };
986 
987     /**
988      * Create new {@link DisplayContent} instance, add itself to the root window container and
989      * initialize direct children.
990      * @param display May not be null.
991      * @param root {@link RootWindowContainer}
992      */
DisplayContent(Display display, RootWindowContainer root)993     DisplayContent(Display display, RootWindowContainer root) {
994         super(root.mWindowManager, "DisplayContent", FEATURE_ROOT);
995         if (mWmService.mRoot.getDisplayContent(display.getDisplayId()) != null) {
996             throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
997                     + " already exists="
998                     + mWmService.mRoot.getDisplayContent(display.getDisplayId())
999                     + " new=" + display);
1000         }
1001 
1002         mRootWindowContainer = root;
1003         mAtmService = mWmService.mAtmService;
1004         mDisplay = display;
1005         mDisplayId = display.getDisplayId();
1006         mCurrentUniqueDisplayId = display.getUniqueId();
1007         mOffTokenAcquirer = mRootWindowContainer.mDisplayOffTokenAcquirer;
1008         mWallpaperController = new WallpaperController(mWmService, this);
1009         display.getDisplayInfo(mDisplayInfo);
1010         display.getMetrics(mDisplayMetrics);
1011         mSystemGestureExclusionLimit = mWmService.mConstants.mSystemGestureExclusionLimitDp
1012                 * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
1013         isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
1014         mInsetsStateController = new InsetsStateController(this);
1015         mDisplayFrames = new DisplayFrames(mDisplayId, mInsetsStateController.getRawInsetsState(),
1016                 mDisplayInfo, calculateDisplayCutoutForRotation(mDisplayInfo.rotation),
1017                 calculateRoundedCornersForRotation(mDisplayInfo.rotation),
1018                 calculatePrivacyIndicatorBoundsForRotation(mDisplayInfo.rotation));
1019         initializeDisplayBaseInfo();
1020 
1021         mAppTransition = new AppTransition(mWmService.mContext, mWmService, this);
1022         mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier);
1023         mAppTransition.registerListenerLocked(mFixedRotationTransitionListener);
1024         mAppTransitionController = new AppTransitionController(mWmService, this);
1025         mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this);
1026 
1027         final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
1028                 "PointerEventDispatcher" + mDisplayId, mDisplayId);
1029         mPointerEventDispatcher = new PointerEventDispatcher(inputChannel, this);
1030 
1031         // Tap Listeners are supported for:
1032         // 1. All physical displays (multi-display).
1033         // 2. VirtualDisplays on VR, AA (and everything else).
1034         mTapDetector = new TaskTapPointerEventListener(mWmService, this);
1035         registerPointerEventListener(mTapDetector);
1036         registerPointerEventListener(mWmService.mMousePositionTracker);
1037         if (mWmService.mAtmService.getRecentTasks() != null) {
1038             registerPointerEventListener(
1039                     mWmService.mAtmService.getRecentTasks().getInputListener());
1040         }
1041 
1042         mDisplayPolicy = new DisplayPolicy(mWmService, this);
1043         mDisplayRotation = new DisplayRotation(mWmService, this);
1044         mCloseToSquareMaxAspectRatio = mWmService.mContext.getResources().getFloat(
1045                 com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio);
1046         if (isDefaultDisplay) {
1047             // The policy may be invoked right after here, so it requires the necessary default
1048             // fields of this display content.
1049             mWmService.mPolicy.setDefaultDisplay(this);
1050         }
1051         if (mWmService.mDisplayReady) {
1052             mDisplayPolicy.onConfigurationChanged();
1053         }
1054         if (mWmService.mSystemReady) {
1055             mDisplayPolicy.systemReady();
1056         }
1057         mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius();
1058         mDividerControllerLocked = new DockedTaskDividerController(this);
1059         mPinnedTaskController = new PinnedTaskController(mWmService, this);
1060 
1061         final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession)
1062                 .setOpaque(true)
1063                 .setContainerLayer()
1064                 .setCallsite("DisplayContent");
1065         mSurfaceControl = b.setName("Root").setContainerLayer().build();
1066 
1067         // Setup the policy and build the display area hierarchy.
1068         mDisplayAreaPolicy = mWmService.getDisplayAreaPolicyProvider().instantiate(
1069                 mWmService, this /* content */, this /* root */, mImeWindowsContainer);
1070 
1071         final List<DisplayArea<? extends WindowContainer>> areas =
1072                 mDisplayAreaPolicy.getDisplayAreas(FEATURE_WINDOWED_MAGNIFICATION);
1073         final DisplayArea<?> area = areas.size() == 1 ? areas.get(0) : null;
1074         if (area != null && area.getParent() == this) {
1075             // The windowed magnification area should contain all non-overlay windows, so just use
1076             // it as the windowing layer.
1077             mWindowingLayer = area.mSurfaceControl;
1078         } else {
1079             // Need an additional layer for screen level animation, so move the layer containing
1080             // the windows to the new root.
1081             mWindowingLayer = mSurfaceControl;
1082             mSurfaceControl = b.setName("RootWrapper").build();
1083             getPendingTransaction().reparent(mWindowingLayer, mSurfaceControl)
1084                     .show(mWindowingLayer);
1085         }
1086 
1087         mOverlayLayer = b.setName("Display Overlays").setParent(mSurfaceControl).build();
1088 
1089         getPendingTransaction()
1090                 .setLayer(mSurfaceControl, 0)
1091                 .setLayerStack(mSurfaceControl, mDisplayId)
1092                 .show(mSurfaceControl)
1093                 .setLayer(mOverlayLayer, Integer.MAX_VALUE)
1094                 .show(mOverlayLayer);
1095         getPendingTransaction().apply();
1096 
1097         // Sets the display content for the children.
1098         onDisplayChanged(this);
1099         updateDisplayAreaOrganizers();
1100 
1101         mInputMonitor = new InputMonitor(mWmService, this);
1102         mInsetsPolicy = new InsetsPolicy(mInsetsStateController, this);
1103 
1104         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Creating display=" + display);
1105 
1106         mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this);
1107     }
1108 
isReady()1109     boolean isReady() {
1110         // The display is ready when the system and the individual display are both ready.
1111         return mWmService.mDisplayReady && mDisplayReady;
1112     }
1113 
getDisplayId()1114     int getDisplayId() {
1115         return mDisplayId;
1116     }
1117 
getWindowCornerRadius()1118     float getWindowCornerRadius() {
1119         return mWindowCornerRadius;
1120     }
1121 
getWindowToken(IBinder binder)1122     WindowToken getWindowToken(IBinder binder) {
1123         return mTokenMap.get(binder);
1124     }
1125 
getActivityRecord(IBinder binder)1126     ActivityRecord getActivityRecord(IBinder binder) {
1127         final WindowToken token = getWindowToken(binder);
1128         if (token == null) {
1129             return null;
1130         }
1131         return token.asActivityRecord();
1132     }
1133 
addWindowToken(IBinder binder, WindowToken token)1134     void addWindowToken(IBinder binder, WindowToken token) {
1135         final DisplayContent dc = mWmService.mRoot.getWindowTokenDisplay(token);
1136         if (dc != null) {
1137             // We currently don't support adding a window token to the display if the display
1138             // already has the binder mapped to another token. If there is a use case for supporting
1139             // this moving forward we will either need to merge the WindowTokens some how or have
1140             // the binder map to a list of window tokens.
1141             throw new IllegalArgumentException("Can't map token=" + token + " to display="
1142                     + getName() + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
1143         }
1144         if (binder == null) {
1145             throw new IllegalArgumentException("Can't map token=" + token + " to display="
1146                     + getName() + " binder is null");
1147         }
1148         if (token == null) {
1149             throw new IllegalArgumentException("Can't map null token to display="
1150                     + getName() + " binder=" + binder);
1151         }
1152 
1153         mTokenMap.put(binder, token);
1154 
1155         if (token.asActivityRecord() == null) {
1156             // Set displayContent for non-app token to prevent same token will add twice after
1157             // onDisplayChanged.
1158             // TODO: Check if it's fine that super.onDisplayChanged of WindowToken
1159             //  (WindowsContainer#onDisplayChanged) may skipped when token.mDisplayContent assigned.
1160             token.mDisplayContent = this;
1161             // Add non-app token to container hierarchy on the display. App tokens are added through
1162             // the parent container managing them (e.g. Tasks).
1163             final DisplayArea.Tokens da = findAreaForToken(token).asTokens();
1164             da.addChild(token);
1165         }
1166     }
1167 
removeWindowToken(IBinder binder)1168     WindowToken removeWindowToken(IBinder binder) {
1169         final WindowToken token = mTokenMap.remove(binder);
1170         if (token != null && token.asActivityRecord() == null) {
1171             token.setExiting();
1172         }
1173         return token;
1174     }
1175 
addShellRoot(@onNull IWindow client, @WindowManager.ShellRootLayer int shellRootLayer)1176     SurfaceControl addShellRoot(@NonNull IWindow client,
1177             @WindowManager.ShellRootLayer int shellRootLayer) {
1178         ShellRoot root = mShellRoots.get(shellRootLayer);
1179         if (root != null) {
1180             if (root.getClient() == client) {
1181                 return root.getSurfaceControl();
1182             }
1183             root.clear();
1184             mShellRoots.remove(shellRootLayer);
1185         }
1186         root = new ShellRoot(client, this, shellRootLayer);
1187         SurfaceControl rootLeash = root.getSurfaceControl();
1188         if (rootLeash == null) {
1189             // Root didn't finish initializing, so don't add it.
1190             root.clear();
1191             return null;
1192         }
1193         mShellRoots.put(shellRootLayer, root);
1194         SurfaceControl out = new SurfaceControl(rootLeash, "DisplayContent.addShellRoot");
1195         return out;
1196     }
1197 
removeShellRoot(int windowType)1198     void removeShellRoot(int windowType) {
1199         synchronized(mWmService.mGlobalLock) {
1200             ShellRoot root = mShellRoots.get(windowType);
1201             if (root == null) {
1202                 return;
1203             }
1204             root.clear();
1205             mShellRoots.remove(windowType);
1206         }
1207     }
1208 
setRemoteInsetsController(IDisplayWindowInsetsController controller)1209     void setRemoteInsetsController(IDisplayWindowInsetsController controller) {
1210         if (mRemoteInsetsControlTarget != null) {
1211             mRemoteInsetsControlTarget.mRemoteInsetsController.asBinder().unlinkToDeath(
1212                     mRemoteInsetsDeath, 0);
1213             mRemoteInsetsControlTarget = null;
1214         }
1215         if (controller != null) {
1216             try {
1217                 controller.asBinder().linkToDeath(mRemoteInsetsDeath, 0);
1218                 mRemoteInsetsControlTarget = new RemoteInsetsControlTarget(controller);
1219             } catch (RemoteException e) {
1220                 return;
1221             }
1222         }
1223     }
1224 
1225     /** Changes the display the input window token is housed on to this one. */
reParentWindowToken(WindowToken token)1226     void reParentWindowToken(WindowToken token) {
1227         final DisplayContent prevDc = token.getDisplayContent();
1228         if (prevDc == this) {
1229             return;
1230         }
1231         if (prevDc != null) {
1232             if (prevDc.mTokenMap.remove(token.token) != null && token.asActivityRecord() == null) {
1233                 // Removed the token from the map, but made sure it's not an app token before
1234                 // removing from parent.
1235                 token.getParent().removeChild(token);
1236             }
1237             if (token.hasChild(prevDc.mLastFocus)) {
1238                 // If the reparent window token contains previous display's last focus window, means
1239                 // it will end up to gain window focus on the target display, so it should not be
1240                 // notified that it lost focus from the previous display.
1241                 prevDc.mLastFocus = null;
1242             }
1243         }
1244 
1245         addWindowToken(token.token, token);
1246 
1247         if (mWmService.mAccessibilityController != null) {
1248             final int prevDisplayId = prevDc != null ? prevDc.getDisplayId() : INVALID_DISPLAY;
1249             mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(prevDisplayId,
1250                     getDisplayId());
1251         }
1252     }
1253 
removeAppToken(IBinder binder)1254     void removeAppToken(IBinder binder) {
1255         final WindowToken token = removeWindowToken(binder);
1256         if (token == null) {
1257             Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
1258             return;
1259         }
1260 
1261         final ActivityRecord activity = token.asActivityRecord();
1262 
1263         if (activity == null) {
1264             Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
1265             return;
1266         }
1267 
1268         activity.onRemovedFromDisplay();
1269         if (activity == mFixedRotationLaunchingApp) {
1270             // Make sure the states of associated tokens are also cleared.
1271             activity.finishFixedRotationTransform();
1272             setFixedRotationLaunchingAppUnchecked(null);
1273         }
1274     }
1275 
1276     @Override
getDisplay()1277     public Display getDisplay() {
1278         return mDisplay;
1279     }
1280 
getDisplayInfo()1281     DisplayInfo getDisplayInfo() {
1282         return mDisplayInfo;
1283     }
1284 
getDisplayMetrics()1285     DisplayMetrics getDisplayMetrics() {
1286         return mDisplayMetrics;
1287     }
1288 
getDisplayPolicy()1289     DisplayPolicy getDisplayPolicy() {
1290         return mDisplayPolicy;
1291     }
1292 
1293     @Override
getDisplayRotation()1294     public DisplayRotation getDisplayRotation() {
1295         return mDisplayRotation;
1296     }
1297 
setInsetProvider(@nternalInsetsType int type, WindowState win, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider)1298     void setInsetProvider(@InternalInsetsType int type, WindowState win,
1299             @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider){
1300         setInsetProvider(type, win, frameProvider, null /* imeFrameProvider */);
1301     }
1302 
1303     /**
1304      * Marks a window as providing insets for the rest of the windows in the system.
1305      *
1306      * @param type The type of inset this window provides.
1307      * @param win The window.
1308      * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of
1309      *                      the window should be taken.
1310      * @param imeFrameProvider Function to compute the frame when dispatching insets to the IME, or
1311      *                         {@code null} if the normal frame should be taken.
1312      */
setInsetProvider(@nternalInsetsType int type, WindowState win, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> imeFrameProvider)1313     void setInsetProvider(@InternalInsetsType int type, WindowState win,
1314             @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider,
1315             @Nullable TriConsumer<DisplayFrames, WindowState, Rect> imeFrameProvider) {
1316         mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider,
1317                 imeFrameProvider);
1318     }
1319 
getInsetsStateController()1320     InsetsStateController getInsetsStateController() {
1321         return mInsetsStateController;
1322     }
1323 
getInsetsPolicy()1324     InsetsPolicy getInsetsPolicy() {
1325         return mInsetsPolicy;
1326     }
1327 
1328     @Rotation
getRotation()1329     int getRotation() {
1330         return mDisplayRotation.getRotation();
1331     }
1332 
1333     @ScreenOrientation
getLastOrientation()1334     int getLastOrientation() {
1335         return mDisplayRotation.getLastOrientation();
1336     }
1337 
registerRemoteAnimations(RemoteAnimationDefinition definition)1338     void registerRemoteAnimations(RemoteAnimationDefinition definition) {
1339         mAppTransitionController.registerRemoteAnimations(definition);
1340     }
1341 
reconfigureDisplayLocked()1342     void reconfigureDisplayLocked() {
1343         if (!isReady()) {
1344             return;
1345         }
1346         configureDisplayPolicy();
1347         setLayoutNeeded();
1348 
1349         boolean configChanged = updateOrientation();
1350         final Configuration currentDisplayConfig = getConfiguration();
1351         mTmpConfiguration.setTo(currentDisplayConfig);
1352         computeScreenConfiguration(mTmpConfiguration);
1353         configChanged |= currentDisplayConfig.diff(mTmpConfiguration) != 0;
1354 
1355         if (configChanged) {
1356             mWaitingForConfig = true;
1357             mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */, this);
1358             sendNewConfiguration();
1359         }
1360 
1361         mWmService.mWindowPlacerLocked.performSurfacePlacement();
1362     }
1363 
sendNewConfiguration()1364     void sendNewConfiguration() {
1365         if (!isReady()) {
1366             return;
1367         }
1368         if (mDisplayRotation.isWaitingForRemoteRotation()) {
1369             return;
1370         }
1371 
1372         final boolean configUpdated = updateDisplayOverrideConfigurationLocked();
1373         if (configUpdated) {
1374             return;
1375         }
1376 
1377         // The display configuration doesn't change. If there is a launching transformed app, that
1378         // means its request to change display configuration has been discarded, then it should
1379         // respect to the current configuration of display.
1380         clearFixedRotationLaunchingApp();
1381 
1382         // Something changed (E.g. device rotation), but no configuration update is needed.
1383         // E.g. changing device rotation by 180 degrees. Go ahead and perform surface placement to
1384         // unfreeze the display since we froze it when the rotation was updated in
1385         // DisplayContent#updateRotationUnchecked.
1386         if (mWaitingForConfig) {
1387             mWaitingForConfig = false;
1388             mWmService.mLastFinishedFreezeSource = "config-unchanged";
1389             setLayoutNeeded();
1390             mWmService.mWindowPlacerLocked.performSurfacePlacement();
1391         }
1392     }
1393 
1394     @Override
onDescendantOrientationChanged(WindowContainer requestingContainer)1395     boolean onDescendantOrientationChanged(WindowContainer requestingContainer) {
1396         final Configuration config = updateOrientation(
1397                 getRequestedOverrideConfiguration(), requestingContainer, false /* forceUpdate */);
1398         // If display rotation class tells us that it doesn't consider app requested orientation,
1399         // this display won't rotate just because of an app changes its requested orientation. Thus
1400         // it indicates that this display chooses not to handle this request.
1401         final boolean handled = handlesOrientationChangeFromDescendant();
1402         if (config == null) {
1403             return handled;
1404         }
1405 
1406         if (handled && requestingContainer instanceof ActivityRecord) {
1407             final ActivityRecord activityRecord = (ActivityRecord) requestingContainer;
1408             final boolean kept = updateDisplayOverrideConfigurationLocked(config, activityRecord,
1409                     false /* deferResume */, null /* result */);
1410             activityRecord.frozenBeforeDestroy = true;
1411             if (!kept) {
1412                 mRootWindowContainer.resumeFocusedTasksTopActivities();
1413             }
1414         } else {
1415             // We have a new configuration to push so we need to update ATMS for now.
1416             // TODO: Clean up display configuration push between ATMS and WMS after unification.
1417             updateDisplayOverrideConfigurationLocked(config, null /* starting */,
1418                     false /* deferResume */, null);
1419         }
1420         return handled;
1421     }
1422 
1423     @Override
handlesOrientationChangeFromDescendant()1424     boolean handlesOrientationChangeFromDescendant() {
1425         return !mIgnoreOrientationRequest && !getDisplayRotation().isFixedToUserRotation();
1426     }
1427 
1428     /**
1429      * Determine the new desired orientation of this display.
1430      *
1431      * @see #getOrientation()
1432      * @return {@code true} if the orientation is changed and the caller should call
1433      *         {@link #sendNewConfiguration} if the method returns {@code true}.
1434      */
updateOrientation()1435     boolean updateOrientation() {
1436         return updateOrientation(false /* forceUpdate */);
1437     }
1438 
1439     /**
1440      * Update orientation of the display, returning a non-null new Configuration if it has
1441      * changed from the current orientation. If a non-null configuration is returned, someone must
1442      * call {@link WindowManagerService#setNewDisplayOverrideConfiguration(Configuration,
1443      * DisplayContent)} to tell the window manager it can unfreeze the screen. This will typically
1444      * be done by calling {@link #sendNewConfiguration}.
1445      *
1446      * @param currentConfig The current requested override configuration (it is usually set from
1447      *                      the last {@link #sendNewConfiguration}) of the display. It is used to
1448      *                      check if the configuration container has the latest state.
1449      * @param freezeDisplayWindow Freeze the app window if the orientation is changed.
1450      * @param forceUpdate See {@link DisplayRotation#updateRotationUnchecked(boolean)}
1451      */
updateOrientation(Configuration currentConfig, WindowContainer freezeDisplayWindow, boolean forceUpdate)1452     Configuration updateOrientation(Configuration currentConfig,
1453             WindowContainer freezeDisplayWindow, boolean forceUpdate) {
1454         if (!mDisplayReady) {
1455             return null;
1456         }
1457 
1458         Configuration config = null;
1459         if (updateOrientation(forceUpdate)) {
1460             // If we changed the orientation but mOrientationChangeComplete is already true,
1461             // we used seamless rotation, and we don't need to freeze the screen.
1462             if (freezeDisplayWindow != null && !mWmService.mRoot.mOrientationChangeComplete) {
1463                 final ActivityRecord activity = freezeDisplayWindow.asActivityRecord();
1464                 if (activity != null && activity.mayFreezeScreenLocked()) {
1465                     activity.startFreezingScreen();
1466                 }
1467             }
1468             config = new Configuration();
1469             computeScreenConfiguration(config);
1470         } else if (currentConfig != null
1471                 // If waiting for a remote rotation, don't prematurely update configuration.
1472                 && !(mDisplayRotation.isWaitingForRemoteRotation()
1473                         || mAtmService.getTransitionController().isCollecting(this))) {
1474             // No obvious action we need to take, but if our current state mismatches the
1475             // activity manager's, update it, disregarding font scale, which should remain set
1476             // to the value of the previous configuration.
1477             // Here we're calling Configuration#unset() instead of setToDefaults() because we
1478             // need to keep override configs clear of non-empty values (e.g. fontSize).
1479             mTmpConfiguration.unset();
1480             mTmpConfiguration.updateFrom(currentConfig);
1481             computeScreenConfiguration(mTmpConfiguration);
1482             if (currentConfig.diff(mTmpConfiguration) != 0) {
1483                 mWaitingForConfig = true;
1484                 setLayoutNeeded();
1485                 mDisplayRotation.prepareNormalRotationAnimation();
1486                 config = new Configuration(mTmpConfiguration);
1487             }
1488         }
1489 
1490         return config;
1491     }
1492 
updateOrientation(boolean forceUpdate)1493     private boolean updateOrientation(boolean forceUpdate) {
1494         final int orientation = getOrientation();
1495         // The last orientation source is valid only after getOrientation.
1496         final WindowContainer orientationSource = getLastOrientationSource();
1497         final ActivityRecord r =
1498                 orientationSource != null ? orientationSource.asActivityRecord() : null;
1499         if (r != null) {
1500             final Task task = r.getTask();
1501             if (task != null && orientation != task.mLastReportedRequestedOrientation) {
1502                 task.mLastReportedRequestedOrientation = orientation;
1503                 mAtmService.getTaskChangeNotificationController()
1504                         .notifyTaskRequestedOrientationChanged(task.mTaskId, orientation);
1505             }
1506             // Currently there is no use case from non-activity.
1507             if (handleTopActivityLaunchingInDifferentOrientation(r, true /* checkOpening */)) {
1508                 // Display orientation should be deferred until the top fixed rotation is finished.
1509                 return false;
1510             }
1511         }
1512         return mDisplayRotation.updateOrientation(orientation, forceUpdate);
1513     }
1514 
1515     @Override
isSyncFinished()1516     boolean isSyncFinished() {
1517         if (mDisplayRotation.isWaitingForRemoteRotation()) return false;
1518         return super.isSyncFinished();
1519     }
1520 
1521     /**
1522      * Returns a valid rotation if the activity can use different orientation than the display.
1523      * Otherwise {@link #ROTATION_UNDEFINED}.
1524      */
1525     @Rotation
rotationForActivityInDifferentOrientation(@onNull ActivityRecord r)1526     int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) {
1527         if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) {
1528             return ROTATION_UNDEFINED;
1529         }
1530         if (r.inMultiWindowMode() || r.getRequestedConfigurationOrientation(true /* forDisplay */)
1531                 == getConfiguration().orientation) {
1532             return ROTATION_UNDEFINED;
1533         }
1534         final int currentRotation = getRotation();
1535         final int rotation = mDisplayRotation.rotationForOrientation(r.getRequestedOrientation(),
1536                 currentRotation);
1537         if (rotation == currentRotation) {
1538             return ROTATION_UNDEFINED;
1539         }
1540         return rotation;
1541     }
1542 
1543     /**
1544      * We need to keep display rotation fixed for a while when the activity in different orientation
1545      * is launching until the launch animation is done to avoid showing the previous activity
1546      * inadvertently in a wrong orientation.
1547      *
1548      * @param r The launching activity which may change display orientation.
1549      * @param checkOpening Whether to check if the activity is animating by transition. Set to
1550      *                     {@code true} if the caller is not sure whether the activity is launching.
1551      * @return {@code true} if the fixed rotation is started.
1552      */
handleTopActivityLaunchingInDifferentOrientation(@onNull ActivityRecord r, boolean checkOpening)1553     boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r,
1554             boolean checkOpening) {
1555         if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) {
1556             return false;
1557         }
1558         if (r.isFinishingFixedRotationTransform()) {
1559             return false;
1560         }
1561         if (r.hasFixedRotationTransform()) {
1562             // It has been set and not yet finished.
1563             return true;
1564         }
1565         if (!r.occludesParent() || r.isVisible()) {
1566             // While entering or leaving a translucent or floating activity (e.g. dialog style),
1567             // there is a visible activity in the background. Then it still needs rotation animation
1568             // to cover the activity configuration change.
1569             return false;
1570         }
1571         if (r.attachedToProcess() && mayImeShowOnLaunchingActivity(r)) {
1572             // Currently it is unknown that when will IME window be ready. Reject the case to
1573             // avoid flickering by showing IME in inconsistent orientation.
1574             return false;
1575         }
1576         if (checkOpening) {
1577             if (!mAppTransition.isTransitionSet() || !mOpeningApps.contains(r)) {
1578                 // Apply normal rotation animation in case of the activity set different requested
1579                 // orientation without activity switch, or the transition is unset due to starting
1580                 // window was transferred ({@link #mSkipAppTransitionAnimation}).
1581                 return false;
1582             }
1583             if (r.isState(RESUMED) && !r.getRootTask().mInResumeTopActivity) {
1584                 // If the activity is executing or has done the lifecycle callback, use normal
1585                 // rotation animation so the display info can be updated immediately (see
1586                 // updateDisplayAndOrientation). This prevents a compatibility issue such as
1587                 // calling setRequestedOrientation in Activity#onCreate and then get display info.
1588                 // If fixed rotation is applied, the display rotation will still be the old one,
1589                 // unless the client side gets the rotation again after the adjustments arrive.
1590                 return false;
1591             }
1592         } else if (r != topRunningActivity()) {
1593             // If the transition has not started yet, the activity must be the top.
1594             return false;
1595         }
1596         if (mLastWallpaperVisible && r.windowsCanBeWallpaperTarget()
1597                 && mFixedRotationTransitionListener.mAnimatingRecents == null) {
1598             // Use normal rotation animation for orientation change of visible wallpaper if recents
1599             // animation is not running (it may be swiping to home).
1600             return false;
1601         }
1602         final int rotation = rotationForActivityInDifferentOrientation(r);
1603         if (rotation == ROTATION_UNDEFINED) {
1604             // The display rotation won't be changed by current top activity. The client side
1605             // adjustments of previous rotated activity should be cleared earlier. Otherwise if
1606             // the current top is in the same process, it may get the rotated state. The transform
1607             // will be cleared later with transition callback to ensure smooth animation.
1608             if (hasTopFixedRotationLaunchingApp()) {
1609                 mFixedRotationLaunchingApp.notifyFixedRotationTransform(false /* enabled */);
1610             }
1611             return false;
1612         }
1613         if (!r.getDisplayArea().matchParentBounds()) {
1614             // Because the fixed rotated configuration applies to activity directly, if its parent
1615             // has it own policy for bounds, the activity bounds based on parent is unknown.
1616             return false;
1617         }
1618 
1619         setFixedRotationLaunchingApp(r, rotation);
1620         return true;
1621     }
1622 
1623     /** Returns {@code true} if the IME is possible to show on the launching activity. */
mayImeShowOnLaunchingActivity(@onNull ActivityRecord r)1624     private boolean mayImeShowOnLaunchingActivity(@NonNull ActivityRecord r) {
1625         final WindowState win = r.findMainWindow();
1626         if (win == null) {
1627             return false;
1628         }
1629         // See InputMethodManagerService#shouldRestoreImeVisibility that we expecting the IME
1630         // should be hidden when the window set the hidden softInputMode.
1631         final int softInputMode = win.mAttrs.softInputMode;
1632         switch (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
1633             case SOFT_INPUT_STATE_ALWAYS_HIDDEN:
1634             case SOFT_INPUT_STATE_HIDDEN:
1635                 return false;
1636         }
1637         return r.mLastImeShown && mInputMethodWindow != null && mInputMethodWindow.mHasSurface
1638                 && mInputMethodWindow.mViewVisibility == View.VISIBLE;
1639     }
1640 
1641     /** Returns {@code true} if the top activity is transformed with the new rotation of display. */
hasTopFixedRotationLaunchingApp()1642     boolean hasTopFixedRotationLaunchingApp() {
1643         return mFixedRotationLaunchingApp != null
1644                 // Ignore animating recents because it hasn't really become the top.
1645                 && mFixedRotationLaunchingApp != mFixedRotationTransitionListener.mAnimatingRecents;
1646     }
1647 
isFixedRotationLaunchingApp(ActivityRecord r)1648     boolean isFixedRotationLaunchingApp(ActivityRecord r) {
1649         return mFixedRotationLaunchingApp == r;
1650     }
1651 
1652     @VisibleForTesting
getFadeRotationAnimationController()1653     @Nullable FadeRotationAnimationController getFadeRotationAnimationController() {
1654         return mFadeRotationAnimationController;
1655     }
1656 
setFixedRotationLaunchingAppUnchecked(@ullable ActivityRecord r)1657     void setFixedRotationLaunchingAppUnchecked(@Nullable ActivityRecord r) {
1658         setFixedRotationLaunchingAppUnchecked(r, ROTATION_UNDEFINED);
1659     }
1660 
setFixedRotationLaunchingAppUnchecked(@ullable ActivityRecord r, int rotation)1661     void setFixedRotationLaunchingAppUnchecked(@Nullable ActivityRecord r, int rotation) {
1662         if (mFixedRotationLaunchingApp == null && r != null) {
1663             mWmService.mDisplayNotificationController.dispatchFixedRotationStarted(this, rotation);
1664             startFadeRotationAnimation(
1665                     // Delay the hide animation to avoid blinking by clicking navigation bar that
1666                     // may toggle fixed rotation in a short time.
1667                     r == mFixedRotationTransitionListener.mAnimatingRecents /* shouldDebounce */);
1668         } else if (mFixedRotationLaunchingApp != null && r == null) {
1669             mWmService.mDisplayNotificationController.dispatchFixedRotationFinished(this);
1670             finishFadeRotationAnimationIfPossible();
1671         }
1672         mFixedRotationLaunchingApp = r;
1673     }
1674 
1675     /**
1676      * Sets the provided record to {@link #mFixedRotationLaunchingApp} if possible to apply fixed
1677      * rotation transform to it and indicate that the display may be rotated after it is launched.
1678      */
setFixedRotationLaunchingApp(@onNull ActivityRecord r, @Rotation int rotation)1679     void setFixedRotationLaunchingApp(@NonNull ActivityRecord r, @Rotation int rotation) {
1680         final WindowToken prevRotatedLaunchingApp = mFixedRotationLaunchingApp;
1681         if (prevRotatedLaunchingApp == r
1682                 && r.getWindowConfiguration().getRotation() == rotation) {
1683             // The given launching app and target rotation are the same as the existing ones.
1684             return;
1685         }
1686         if (prevRotatedLaunchingApp != null
1687                 && prevRotatedLaunchingApp.getWindowConfiguration().getRotation() == rotation
1688                 // It is animating so we can expect there will have a transition callback.
1689                 && prevRotatedLaunchingApp.isAnimating(TRANSITION | PARENTS)) {
1690             // It may be the case that multiple activities launch consecutively. Because their
1691             // rotation are the same, the transformed state can be shared to avoid duplicating
1692             // the heavy operations. This also benefits that the states of multiple activities
1693             // are handled together.
1694             r.linkFixedRotationTransform(prevRotatedLaunchingApp);
1695             if (r != mFixedRotationTransitionListener.mAnimatingRecents) {
1696                 // Only update the record for normal activity so the display orientation can be
1697                 // updated when the transition is done if it becomes the top. And the case of
1698                 // recents can be handled when the recents animation is finished.
1699                 setFixedRotationLaunchingAppUnchecked(r, rotation);
1700             }
1701             return;
1702         }
1703 
1704         if (!r.hasFixedRotationTransform()) {
1705             startFixedRotationTransform(r, rotation);
1706         }
1707         setFixedRotationLaunchingAppUnchecked(r, rotation);
1708         if (prevRotatedLaunchingApp != null) {
1709             prevRotatedLaunchingApp.finishFixedRotationTransform();
1710         }
1711     }
1712 
1713     /**
1714      * Continue updating the orientation change of display if it was deferred by a top activity
1715      * launched in a different orientation.
1716      */
continueUpdateOrientationForDiffOrienLaunchingApp()1717     void continueUpdateOrientationForDiffOrienLaunchingApp() {
1718         if (mFixedRotationLaunchingApp == null) {
1719             return;
1720         }
1721         if (mPinnedTaskController.shouldDeferOrientationChange()) {
1722             // Wait for the PiP animation to finish.
1723             return;
1724         }
1725         // Update directly because the app which will change the orientation of display is ready.
1726         if (mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */)) {
1727             sendNewConfiguration();
1728             return;
1729         }
1730         if (mDisplayRotation.isWaitingForRemoteRotation()) {
1731             // There is pending rotation change to apply.
1732             return;
1733         }
1734         // The orientation of display is not changed.
1735         clearFixedRotationLaunchingApp();
1736     }
1737 
1738     /**
1739      * Clears the {@link #mFixedRotationLaunchingApp} without applying rotation to display. It is
1740      * used when the display won't rotate (e.g. the orientation from sensor has updated again before
1741      * applying rotation to display) but the launching app has been transformed. So the record need
1742      * to be cleared and restored to stop using seamless rotation and rotated configuration.
1743      */
clearFixedRotationLaunchingApp()1744     private void clearFixedRotationLaunchingApp() {
1745         if (mFixedRotationLaunchingApp == null) {
1746             return;
1747         }
1748         mFixedRotationLaunchingApp.finishFixedRotationTransform();
1749         setFixedRotationLaunchingAppUnchecked(null);
1750     }
1751 
startFixedRotationTransform(WindowToken token, int rotation)1752     private void startFixedRotationTransform(WindowToken token, int rotation) {
1753         mTmpConfiguration.unset();
1754         final DisplayInfo info = computeScreenConfiguration(mTmpConfiguration, rotation);
1755         final WmDisplayCutout cutout = calculateDisplayCutoutForRotation(rotation);
1756         final RoundedCorners roundedCorners = calculateRoundedCornersForRotation(rotation);
1757         final PrivacyIndicatorBounds indicatorBounds =
1758                 calculatePrivacyIndicatorBoundsForRotation(rotation);
1759         final DisplayFrames displayFrames = new DisplayFrames(mDisplayId, new InsetsState(), info,
1760                 cutout, roundedCorners, indicatorBounds);
1761         token.applyFixedRotationTransform(info, displayFrames, mTmpConfiguration);
1762     }
1763 
1764     /**
1765      * If the provided {@link ActivityRecord} can be displayed in an orientation different from the
1766      * display's, it will be rotated to match its requested orientation.
1767      *
1768      * @see #rotationForActivityInDifferentOrientation(ActivityRecord).
1769      * @see WindowToken#applyFixedRotationTransform(DisplayInfo, DisplayFrames, Configuration)
1770      */
rotateInDifferentOrientationIfNeeded(ActivityRecord activityRecord)1771     void rotateInDifferentOrientationIfNeeded(ActivityRecord activityRecord) {
1772         int rotation = rotationForActivityInDifferentOrientation(activityRecord);
1773         if (rotation != ROTATION_UNDEFINED) {
1774             startFixedRotationTransform(activityRecord, rotation);
1775         }
1776     }
1777 
1778     /**
1779      * Starts the hide animation for the windows which will be rotated seamlessly.
1780      *
1781      * @return {@code true} if the animation is executed right now.
1782      */
startFadeRotationAnimation(boolean shouldDebounce)1783     private boolean startFadeRotationAnimation(boolean shouldDebounce) {
1784         if (shouldDebounce) {
1785             mWmService.mH.postDelayed(() -> {
1786                 synchronized (mWmService.mGlobalLock) {
1787                     if (mFixedRotationLaunchingApp != null
1788                             && startFadeRotationAnimation(false /* shouldDebounce */)) {
1789                         // Apply the transaction so the animation leash can take effect immediately.
1790                         getPendingTransaction().apply();
1791                     }
1792                 }
1793             }, FIXED_ROTATION_HIDE_ANIMATION_DEBOUNCE_DELAY_MS);
1794             return false;
1795         }
1796         if (mFadeRotationAnimationController == null) {
1797             mFadeRotationAnimationController = new FadeRotationAnimationController(this);
1798             mFadeRotationAnimationController.hide();
1799             return true;
1800         }
1801         return false;
1802     }
1803 
1804     /** Re-show the previously hidden windows if all seamless rotated windows are done. */
finishFadeRotationAnimationIfPossible()1805     void finishFadeRotationAnimationIfPossible() {
1806         final FadeRotationAnimationController controller = mFadeRotationAnimationController;
1807         if (controller != null && !mDisplayRotation.hasSeamlessRotatingWindow()) {
1808             controller.show();
1809             mFadeRotationAnimationController = null;
1810         }
1811     }
1812 
1813     /** Shows the given window which may be hidden for screen frozen. */
finishFadeRotationAnimation(WindowState w)1814     void finishFadeRotationAnimation(WindowState w) {
1815         final FadeRotationAnimationController controller = mFadeRotationAnimationController;
1816         if (controller != null && controller.show(w.mToken)) {
1817             mFadeRotationAnimationController = null;
1818         }
1819     }
1820 
1821     /** Returns {@code true} if the display should wait for the given window to stop freezing. */
waitForUnfreeze(WindowState w)1822     boolean waitForUnfreeze(WindowState w) {
1823         if (w.mForceSeamlesslyRotate) {
1824             // The window should look no different before and after rotation.
1825             return false;
1826         }
1827         final FadeRotationAnimationController controller = mFadeRotationAnimationController;
1828         return controller == null || !controller.isHandledToken(w.mToken);
1829     }
1830 
notifyInsetsChanged(Consumer<WindowState> dispatchInsetsChanged)1831     void notifyInsetsChanged(Consumer<WindowState> dispatchInsetsChanged) {
1832         if (mFixedRotationLaunchingApp != null) {
1833             // The insets state of fixed rotation app is a rotated copy. Make sure the visibilities
1834             // of insets sources are consistent with the latest state.
1835             final InsetsState rotatedState =
1836                     mFixedRotationLaunchingApp.getFixedRotationTransformInsetsState();
1837             if (rotatedState != null) {
1838                 final InsetsState state = mInsetsStateController.getRawInsetsState();
1839                 for (int i = 0; i < InsetsState.SIZE; i++) {
1840                     final InsetsSource source = state.peekSource(i);
1841                     if (source != null) {
1842                         rotatedState.setSourceVisible(i, source.isVisible());
1843                     }
1844                 }
1845             }
1846         }
1847         forAllWindows(dispatchInsetsChanged, true /* traverseTopToBottom */);
1848         if (mRemoteInsetsControlTarget != null) {
1849             mRemoteInsetsControlTarget.notifyInsetsChanged();
1850         }
1851     }
1852 
1853     /**
1854      * Update rotation of the display.
1855      *
1856      * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
1857      *         {@link #sendNewConfiguration} TO UNFREEZE THE SCREEN unless using Shell transitions.
1858      */
updateRotationUnchecked()1859     boolean updateRotationUnchecked() {
1860         return mDisplayRotation.updateRotationUnchecked(false /* forceUpdate */);
1861     }
1862 
1863     /**
1864      * Applies the rotation transaction. This must be called after {@link #updateRotationUnchecked}
1865      * (if it returned {@code true}) to actually finish the rotation.
1866      *
1867      * @param oldRotation the rotation we are coming from.
1868      * @param rotation the rotation to apply.
1869      */
applyRotation(final int oldRotation, final int rotation)1870     private void applyRotation(final int oldRotation, final int rotation) {
1871         mDisplayRotation.applyCurrentRotation(rotation);
1872         final boolean shellTransitions =
1873                 mWmService.mAtmService.getTransitionController().getTransitionPlayer() != null;
1874         final boolean rotateSeamlessly =
1875                 mDisplayRotation.isRotatingSeamlessly() && !shellTransitions;
1876         final Transaction transaction =
1877                 shellTransitions ? getSyncTransaction() : getPendingTransaction();
1878         ScreenRotationAnimation screenRotationAnimation = rotateSeamlessly
1879                 ? null : getRotationAnimation();
1880         // We need to update our screen size information to match the new rotation. If the rotation
1881         // has actually changed then this method will return true and, according to the comment at
1882         // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
1883         // By updating the Display info here it will be available to
1884         // #computeScreenConfiguration() later.
1885         updateDisplayAndOrientation(getConfiguration().uiMode, null /* outConfig */);
1886 
1887         // NOTE: We disable the rotation in the emulator because
1888         //       it doesn't support hardware OpenGL emulation yet.
1889         if (screenRotationAnimation != null && screenRotationAnimation.hasScreenshot()) {
1890             screenRotationAnimation.setRotation(transaction, rotation);
1891         }
1892 
1893         if (!shellTransitions) {
1894             forAllWindows(w -> {
1895                 w.seamlesslyRotateIfAllowed(transaction, oldRotation, rotation, rotateSeamlessly);
1896             }, true /* traverseTopToBottom */);
1897             mPinnedTaskController.startSeamlessRotationIfNeeded(transaction, oldRotation, rotation);
1898         }
1899 
1900         mWmService.mDisplayManagerInternal.performTraversal(transaction);
1901         scheduleAnimation();
1902 
1903         forAllWindows(w -> {
1904             if (w.mHasSurface && !rotateSeamlessly) {
1905                 ProtoLog.v(WM_DEBUG_ORIENTATION, "Set mOrientationChanging of %s", w);
1906                 w.setOrientationChanging(true);
1907             }
1908             w.mReportOrientationChanged = true;
1909         }, true /* traverseTopToBottom */);
1910 
1911         for (int i = mWmService.mRotationWatchers.size() - 1; i >= 0; i--) {
1912             final WindowManagerService.RotationWatcher rotationWatcher
1913                     = mWmService.mRotationWatchers.get(i);
1914             if (rotationWatcher.mDisplayId == mDisplayId) {
1915                 try {
1916                     rotationWatcher.mWatcher.onRotationChanged(rotation);
1917                 } catch (RemoteException e) {
1918                     // Ignore
1919                 }
1920             }
1921         }
1922 
1923         if (mWmService.mAccessibilityController != null) {
1924             mWmService.mAccessibilityController.onRotationChanged(this);
1925         }
1926     }
1927 
configureDisplayPolicy()1928     void configureDisplayPolicy() {
1929         final int width = mBaseDisplayWidth;
1930         final int height = mBaseDisplayHeight;
1931         final int shortSize;
1932         final int longSize;
1933         if (width > height) {
1934             shortSize = height;
1935             longSize = width;
1936         } else {
1937             shortSize = width;
1938             longSize = height;
1939         }
1940 
1941         final int shortSizeDp = shortSize * DENSITY_DEFAULT / mBaseDisplayDensity;
1942         final int longSizeDp = longSize * DENSITY_DEFAULT / mBaseDisplayDensity;
1943 
1944         mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
1945         mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
1946     }
1947 
1948     /**
1949      * Update {@link #mDisplayInfo} and other internal variables when display is rotated or config
1950      * changed.
1951      * Do not call if {@link WindowManagerService#mDisplayReady} == false.
1952      */
updateDisplayAndOrientation(int uiMode, Configuration outConfig)1953     private DisplayInfo updateDisplayAndOrientation(int uiMode, Configuration outConfig) {
1954         // Use the effective "visual" dimensions based on current rotation
1955         final int rotation = getRotation();
1956         final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
1957         final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
1958         final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
1959 
1960         // Update application display metrics.
1961         final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation);
1962         final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout();
1963         final RoundedCorners roundedCorners = calculateRoundedCornersForRotation(rotation);
1964 
1965         final int appWidth = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
1966                 displayCutout);
1967         final int appHeight = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode,
1968                 displayCutout);
1969         mDisplayInfo.rotation = rotation;
1970         mDisplayInfo.logicalWidth = dw;
1971         mDisplayInfo.logicalHeight = dh;
1972         mDisplayInfo.logicalDensityDpi = mBaseDisplayDensity;
1973         mDisplayInfo.appWidth = appWidth;
1974         mDisplayInfo.appHeight = appHeight;
1975         if (isDefaultDisplay) {
1976             mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics,
1977                     CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
1978         }
1979         mDisplayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout;
1980         mDisplayInfo.roundedCorners = roundedCorners;
1981         mDisplayInfo.getAppMetrics(mDisplayMetrics);
1982         if (mDisplayScalingDisabled) {
1983             mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED;
1984         } else {
1985             mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
1986         }
1987 
1988         computeSizeRangesAndScreenLayout(mDisplayInfo, rotated, uiMode, dw, dh,
1989                 mDisplayMetrics.density, outConfig);
1990 
1991         // We usually set the override info in DisplayManager so that we get consistent display
1992         // metrics values when displays are changing and don't send out new values until WM is aware
1993         // of them. However, we don't do this for displays that serve as containers for ActivityView
1994         // because we don't want letter-/pillar-boxing during resize.
1995         final DisplayInfo overrideDisplayInfo = mShouldOverrideDisplayConfiguration
1996                 ? mDisplayInfo : null;
1997         mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
1998                 overrideDisplayInfo);
1999 
2000         mBaseDisplayRect.set(0, 0, dw, dh);
2001 
2002         if (isDefaultDisplay) {
2003             mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
2004                     mCompatDisplayMetrics);
2005         }
2006 
2007         onDisplayInfoChanged();
2008 
2009         return mDisplayInfo;
2010     }
2011 
calculateDisplayCutoutForRotation(int rotation)2012     WmDisplayCutout calculateDisplayCutoutForRotation(int rotation) {
2013         return mDisplayCutoutCache.getOrCompute(mInitialDisplayCutout, rotation);
2014     }
2015 
calculateDisplayCutoutForRotationUncached( DisplayCutout cutout, int rotation)2016     private WmDisplayCutout calculateDisplayCutoutForRotationUncached(
2017             DisplayCutout cutout, int rotation) {
2018         if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) {
2019             return WmDisplayCutout.NO_CUTOUT;
2020         }
2021         if (rotation == ROTATION_0) {
2022             return WmDisplayCutout.computeSafeInsets(
2023                     cutout, mInitialDisplayWidth, mInitialDisplayHeight);
2024         }
2025         final Insets waterfallInsets =
2026                 RotationUtils.rotateInsets(cutout.getWaterfallInsets(), rotation);
2027         final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
2028         final Rect[] newBounds = mRotationUtil.getRotatedBounds(
2029                 cutout.getBoundingRectsAll(),
2030                 rotation, mInitialDisplayWidth, mInitialDisplayHeight);
2031         final CutoutPathParserInfo info = cutout.getCutoutPathParserInfo();
2032         final CutoutPathParserInfo newInfo = new CutoutPathParserInfo(
2033                 info.getDisplayWidth(), info.getDisplayHeight(), info.getDensity(),
2034                 info.getCutoutSpec(), rotation, info.getScale());
2035         return WmDisplayCutout.computeSafeInsets(
2036                 DisplayCutout.constructDisplayCutout(newBounds, waterfallInsets, newInfo),
2037                 rotated ? mInitialDisplayHeight : mInitialDisplayWidth,
2038                 rotated ? mInitialDisplayWidth : mInitialDisplayHeight);
2039     }
2040 
calculateRoundedCornersForRotation(int rotation)2041     RoundedCorners calculateRoundedCornersForRotation(int rotation) {
2042         return mRoundedCornerCache.getOrCompute(mInitialRoundedCorners, rotation);
2043     }
2044 
calculateRoundedCornersForRotationUncached( RoundedCorners roundedCorners, int rotation)2045     private RoundedCorners calculateRoundedCornersForRotationUncached(
2046             RoundedCorners roundedCorners, int rotation) {
2047         if (roundedCorners == null || roundedCorners == RoundedCorners.NO_ROUNDED_CORNERS) {
2048             return RoundedCorners.NO_ROUNDED_CORNERS;
2049         }
2050 
2051         if (rotation == ROTATION_0) {
2052             return roundedCorners;
2053         }
2054 
2055         return roundedCorners.rotate(rotation, mInitialDisplayWidth, mInitialDisplayHeight);
2056     }
2057 
calculatePrivacyIndicatorBoundsForRotation(int rotation)2058     PrivacyIndicatorBounds calculatePrivacyIndicatorBoundsForRotation(int rotation) {
2059         return mPrivacyIndicatorBoundsCache.getOrCompute(mCurrentPrivacyIndicatorBounds, rotation);
2060     }
2061 
calculatePrivacyIndicatorBoundsForRotationUncached( PrivacyIndicatorBounds bounds, int rotation)2062     private PrivacyIndicatorBounds calculatePrivacyIndicatorBoundsForRotationUncached(
2063             PrivacyIndicatorBounds bounds, int rotation) {
2064         if (bounds == null) {
2065             return new PrivacyIndicatorBounds(new Rect[4], rotation);
2066         }
2067 
2068         return bounds.rotate(rotation);
2069     }
2070 
2071     /**
2072      * Compute display info and configuration according to the given rotation without changing
2073      * current display.
2074      */
computeScreenConfiguration(Configuration outConfig, int rotation)2075     DisplayInfo computeScreenConfiguration(Configuration outConfig, int rotation) {
2076         final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
2077         final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
2078         final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
2079         outConfig.windowConfiguration.setMaxBounds(0, 0, dw, dh);
2080         outConfig.windowConfiguration.setBounds(outConfig.windowConfiguration.getMaxBounds());
2081 
2082         final int uiMode = getConfiguration().uiMode;
2083         final DisplayCutout displayCutout =
2084                 calculateDisplayCutoutForRotation(rotation).getDisplayCutout();
2085         computeScreenAppConfiguration(outConfig, dw, dh, rotation, uiMode, displayCutout);
2086 
2087         final DisplayInfo displayInfo = new DisplayInfo(mDisplayInfo);
2088         displayInfo.rotation = rotation;
2089         displayInfo.logicalWidth = dw;
2090         displayInfo.logicalHeight = dh;
2091         final Rect appBounds = outConfig.windowConfiguration.getAppBounds();
2092         displayInfo.appWidth = appBounds.width();
2093         displayInfo.appHeight = appBounds.height();
2094         displayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout;
2095         computeSizeRangesAndScreenLayout(displayInfo, rotated, uiMode, dw, dh,
2096                 mDisplayMetrics.density, outConfig);
2097         return displayInfo;
2098     }
2099 
2100     /** Compute configuration related to application without changing current display. */
computeScreenAppConfiguration(Configuration outConfig, int dw, int dh, int rotation, int uiMode, DisplayCutout displayCutout)2101     private void computeScreenAppConfiguration(Configuration outConfig, int dw, int dh,
2102             int rotation, int uiMode, DisplayCutout displayCutout) {
2103         final int appWidth = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
2104                 displayCutout);
2105         final int appHeight = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode,
2106                 displayCutout);
2107         mDisplayPolicy.getNonDecorInsetsLw(rotation, dw, dh, displayCutout, mTmpRect);
2108         final int leftInset = mTmpRect.left;
2109         final int topInset = mTmpRect.top;
2110         // AppBounds at the root level should mirror the app screen size.
2111         outConfig.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */,
2112                 leftInset + appWidth /* right */, topInset + appHeight /* bottom */);
2113         outConfig.windowConfiguration.setRotation(rotation);
2114         outConfig.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
2115 
2116         final float density = mDisplayMetrics.density;
2117         outConfig.screenWidthDp = (int) (mDisplayPolicy.getConfigDisplayWidth(dw, dh, rotation,
2118                 uiMode, displayCutout) / density);
2119         outConfig.screenHeightDp = (int) (mDisplayPolicy.getConfigDisplayHeight(dw, dh, rotation,
2120                 uiMode, displayCutout) / density);
2121         outConfig.compatScreenWidthDp = (int) (outConfig.screenWidthDp / mCompatibleScreenScale);
2122         outConfig.compatScreenHeightDp = (int) (outConfig.screenHeightDp / mCompatibleScreenScale);
2123 
2124         final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
2125         outConfig.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, uiMode, dw,
2126                 dh);
2127     }
2128 
2129     /**
2130      * Compute display configuration based on display properties and policy settings.
2131      * Do not call if mDisplayReady == false.
2132      */
computeScreenConfiguration(Configuration config)2133     void computeScreenConfiguration(Configuration config) {
2134         final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config);
2135         calculateBounds(displayInfo, mTmpBounds);
2136         config.windowConfiguration.setBounds(mTmpBounds);
2137         config.windowConfiguration.setMaxBounds(mTmpBounds);
2138         config.windowConfiguration.setWindowingMode(getWindowingMode());
2139         config.windowConfiguration.setDisplayWindowingMode(getWindowingMode());
2140 
2141         final int dw = displayInfo.logicalWidth;
2142         final int dh = displayInfo.logicalHeight;
2143         computeScreenAppConfiguration(config, dw, dh, displayInfo.rotation, config.uiMode,
2144                 displayInfo.displayCutout);
2145 
2146         config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
2147                 | ((displayInfo.flags & Display.FLAG_ROUND) != 0
2148                 ? Configuration.SCREENLAYOUT_ROUND_YES
2149                 : Configuration.SCREENLAYOUT_ROUND_NO);
2150 
2151         config.densityDpi = displayInfo.logicalDensityDpi;
2152 
2153         config.colorMode =
2154                 ((displayInfo.isHdr() && mWmService.hasHdrSupport())
2155                         ? Configuration.COLOR_MODE_HDR_YES
2156                         : Configuration.COLOR_MODE_HDR_NO)
2157                         | (displayInfo.isWideColorGamut() && mWmService.hasWideColorGamutSupport()
2158                         ? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES
2159                         : Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO);
2160 
2161         // Update the configuration based on available input devices, lid switch,
2162         // and platform configuration.
2163         config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
2164         config.keyboard = Configuration.KEYBOARD_NOKEYS;
2165         config.navigation = Configuration.NAVIGATION_NONAV;
2166 
2167         int keyboardPresence = 0;
2168         int navigationPresence = 0;
2169         final InputDevice[] devices = mWmService.mInputManager.getInputDevices();
2170         final int len = devices != null ? devices.length : 0;
2171         for (int i = 0; i < len; i++) {
2172             InputDevice device = devices[i];
2173             // Ignore virtual input device.
2174             if (device.isVirtual()) {
2175                 continue;
2176             }
2177 
2178             // Check if input device can dispatch events to current display.
2179             if (!mWmService.mInputManager.canDispatchToDisplay(device.getId(), mDisplayId)) {
2180                 continue;
2181             }
2182 
2183             final int sources = device.getSources();
2184             final int presenceFlag = device.isExternal()
2185                     ? WindowManagerPolicy.PRESENCE_EXTERNAL : WindowManagerPolicy.PRESENCE_INTERNAL;
2186 
2187             if (mWmService.mIsTouchDevice) {
2188                 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) {
2189                     config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
2190                 }
2191             } else {
2192                 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
2193             }
2194 
2195             if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
2196                 config.navigation = Configuration.NAVIGATION_TRACKBALL;
2197                 navigationPresence |= presenceFlag;
2198             } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
2199                     && config.navigation == Configuration.NAVIGATION_NONAV) {
2200                 config.navigation = Configuration.NAVIGATION_DPAD;
2201                 navigationPresence |= presenceFlag;
2202             }
2203 
2204             if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
2205                 config.keyboard = Configuration.KEYBOARD_QWERTY;
2206                 keyboardPresence |= presenceFlag;
2207             }
2208         }
2209 
2210         if (config.navigation == Configuration.NAVIGATION_NONAV && mWmService.mHasPermanentDpad) {
2211             config.navigation = Configuration.NAVIGATION_DPAD;
2212             navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
2213         }
2214 
2215         // Determine whether a hard keyboard is available and enabled.
2216         // TODO(multi-display): Should the hardware keyboard be tied to a display or to a device?
2217         boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
2218         if (hardKeyboardAvailable != mWmService.mHardKeyboardAvailable) {
2219             mWmService.mHardKeyboardAvailable = hardKeyboardAvailable;
2220             mWmService.mH.removeMessages(REPORT_HARD_KEYBOARD_STATUS_CHANGE);
2221             mWmService.mH.sendEmptyMessage(REPORT_HARD_KEYBOARD_STATUS_CHANGE);
2222         }
2223 
2224         mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
2225 
2226         // Let the policy update hidden states.
2227         config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
2228         config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
2229         config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
2230         mWmService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
2231     }
2232 
computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh)2233     private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh) {
2234         mTmpDisplayMetrics.setTo(mDisplayMetrics);
2235         final DisplayMetrics tmpDm = mTmpDisplayMetrics;
2236         final int unrotDw, unrotDh;
2237         if (rotated) {
2238             unrotDw = dh;
2239             unrotDh = dw;
2240         } else {
2241             unrotDw = dw;
2242             unrotDh = dh;
2243         }
2244         int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw,
2245                 unrotDh);
2246         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh,
2247                 unrotDw);
2248         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw,
2249                 unrotDh);
2250         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh,
2251                 unrotDw);
2252         return sw;
2253     }
2254 
reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, DisplayMetrics dm, int dw, int dh)2255     private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
2256             DisplayMetrics dm, int dw, int dh) {
2257         final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
2258                 rotation).getDisplayCutout();
2259         dm.noncompatWidthPixels = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
2260                 displayCutout);
2261         dm.noncompatHeightPixels = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode,
2262                 displayCutout);
2263         float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
2264         int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
2265         if (curSize == 0 || size < curSize) {
2266             curSize = size;
2267         }
2268         return curSize;
2269     }
2270 
computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig)2271     private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
2272             int uiMode, int dw, int dh, float density, Configuration outConfig) {
2273 
2274         // We need to determine the smallest width that will occur under normal
2275         // operation.  To this, start with the base screen size and compute the
2276         // width under the different possible rotations.  We need to un-rotate
2277         // the current screen dimensions before doing this.
2278         int unrotDw, unrotDh;
2279         if (rotated) {
2280             unrotDw = dh;
2281             unrotDh = dw;
2282         } else {
2283             unrotDw = dw;
2284             unrotDh = dh;
2285         }
2286         displayInfo.smallestNominalAppWidth = 1<<30;
2287         displayInfo.smallestNominalAppHeight = 1<<30;
2288         displayInfo.largestNominalAppWidth = 0;
2289         displayInfo.largestNominalAppHeight = 0;
2290         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh);
2291         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw);
2292         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh);
2293         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw);
2294 
2295         if (outConfig == null) {
2296             return;
2297         }
2298         int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
2299         sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode);
2300         sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode);
2301         sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode);
2302         sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode);
2303         outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
2304         outConfig.screenLayout = sl;
2305     }
2306 
reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, int uiMode)2307     private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh,
2308             int uiMode) {
2309         // Get the display cutout at this rotation.
2310         final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
2311                 rotation).getDisplayCutout();
2312 
2313         // Get the app screen size at this rotation.
2314         int w = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayCutout);
2315         int h = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayCutout);
2316 
2317         // Compute the screen layout size class for this rotation.
2318         int longSize = w;
2319         int shortSize = h;
2320         if (longSize < shortSize) {
2321             int tmp = longSize;
2322             longSize = shortSize;
2323             shortSize = tmp;
2324         }
2325         longSize = (int)(longSize/density);
2326         shortSize = (int)(shortSize/density);
2327         return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
2328     }
2329 
adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode, int dw, int dh)2330     private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation,
2331             int uiMode, int dw, int dh) {
2332         final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
2333                 rotation).getDisplayCutout();
2334         final int width = mDisplayPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode,
2335                 displayCutout);
2336         if (width < displayInfo.smallestNominalAppWidth) {
2337             displayInfo.smallestNominalAppWidth = width;
2338         }
2339         if (width > displayInfo.largestNominalAppWidth) {
2340             displayInfo.largestNominalAppWidth = width;
2341         }
2342         final int height = mDisplayPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode,
2343                 displayCutout);
2344         if (height < displayInfo.smallestNominalAppHeight) {
2345             displayInfo.smallestNominalAppHeight = height;
2346         }
2347         if (height > displayInfo.largestNominalAppHeight) {
2348             displayInfo.largestNominalAppHeight = height;
2349         }
2350     }
2351 
2352     /**
2353      * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
2354      * theme attribute) on devices that feature a physical options menu key attempt to position
2355      * their menu panel window along the edge of the screen nearest the physical menu key.
2356      * This lowers the travel distance between invoking the menu panel and selecting
2357      * a menu option.
2358      *
2359      * This method helps control where that menu is placed. Its current implementation makes
2360      * assumptions about the menu key and its relationship to the screen based on whether
2361      * the device's natural orientation is portrait (width < height) or landscape.
2362      *
2363      * The menu key is assumed to be located along the bottom edge of natural-portrait
2364      * devices and along the right edge of natural-landscape devices. If these assumptions
2365      * do not hold for the target device, this method should be changed to reflect that.
2366      *
2367      * @return A {@link Gravity} value for placing the options menu window.
2368      */
getPreferredOptionsPanelGravity()2369     int getPreferredOptionsPanelGravity() {
2370         final int rotation = getRotation();
2371         if (mInitialDisplayWidth < mInitialDisplayHeight) {
2372             // On devices with a natural orientation of portrait.
2373             switch (rotation) {
2374                 default:
2375                 case Surface.ROTATION_0:
2376                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
2377                 case Surface.ROTATION_90:
2378                     return Gravity.RIGHT | Gravity.BOTTOM;
2379                 case Surface.ROTATION_180:
2380                     return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
2381                 case Surface.ROTATION_270:
2382                     return Gravity.START | Gravity.BOTTOM;
2383             }
2384         }
2385 
2386         // On devices with a natural orientation of landscape.
2387         switch (rotation) {
2388             default:
2389             case Surface.ROTATION_0:
2390                 return Gravity.RIGHT | Gravity.BOTTOM;
2391             case Surface.ROTATION_90:
2392                 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
2393             case Surface.ROTATION_180:
2394                 return Gravity.START | Gravity.BOTTOM;
2395             case Surface.ROTATION_270:
2396                 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
2397         }
2398     }
2399 
getDockedDividerController()2400     DockedTaskDividerController getDockedDividerController() {
2401         return mDividerControllerLocked;
2402     }
2403 
getPinnedTaskController()2404     PinnedTaskController getPinnedTaskController() {
2405         return mPinnedTaskController;
2406     }
2407 
2408     /**
2409      * Returns true if the specified UID has access to this display.
2410      */
hasAccess(int uid)2411     boolean hasAccess(int uid) {
2412         return mDisplay.hasAccess(uid);
2413     }
2414 
isPrivate()2415     boolean isPrivate() {
2416         return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
2417     }
2418 
isTrusted()2419     boolean isTrusted() {
2420         return mDisplay.isTrusted();
2421     }
2422 
2423     /**
2424      * Returns the topmost root task on the display that is compatible with the input windowing
2425      * mode and activity type. Null is no compatible root task on the display.
2426      */
2427     @Nullable
getRootTask(int windowingMode, int activityType)2428     Task getRootTask(int windowingMode, int activityType) {
2429         return getItemFromTaskDisplayAreas(taskDisplayArea ->
2430                 taskDisplayArea.getRootTask(windowingMode, activityType));
2431     }
2432 
2433     @Nullable
getRootTask(int rootTaskId)2434     Task getRootTask(int rootTaskId) {
2435         return getRootTask(rootTask -> rootTask.getRootTaskId() == rootTaskId);
2436     }
2437 
getRootTaskCount()2438     int getRootTaskCount() {
2439         final int[] count = new int[1];
2440         forAllRootTasks(task -> {
2441             count[0]++;
2442         });
2443         return count[0];
2444     }
2445 
2446     @Nullable
getTopRootTask()2447     Task getTopRootTask() {
2448         return getRootTask(t -> true);
2449     }
2450 
2451     /**
2452      * The value is only valid in the scope {@link #onRequestedOverrideConfigurationChanged} of the
2453      * changing hierarchy and the {@link #onConfigurationChanged} of its children.
2454      *
2455      * @return The current changes ({@link android.content.pm.ActivityInfo.Config}) of requested
2456      *         override configuration.
2457      */
getCurrentOverrideConfigurationChanges()2458     int getCurrentOverrideConfigurationChanges() {
2459         return mCurrentOverrideConfigurationChanges;
2460     }
2461 
2462     @Override
onConfigurationChanged(Configuration newParentConfig)2463     public void onConfigurationChanged(Configuration newParentConfig) {
2464         final int lastOrientation = getConfiguration().orientation;
2465         super.onConfigurationChanged(newParentConfig);
2466         if (mDisplayPolicy != null) {
2467             mDisplayPolicy.onConfigurationChanged();
2468             mPinnedTaskController.onPostDisplayConfigurationChanged();
2469         }
2470         // Update IME parent if needed.
2471         updateImeParent();
2472 
2473         if (lastOrientation != getConfiguration().orientation) {
2474             getMetricsLogger().write(
2475                     new LogMaker(MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED)
2476                             .setSubtype(getConfiguration().orientation)
2477                             .addTaggedData(MetricsEvent.FIELD_DISPLAY_ID, getDisplayId()));
2478         }
2479     }
2480 
2481     @Override
fillsParent()2482     boolean fillsParent() {
2483         return true;
2484     }
2485 
2486     @Override
isVisible()2487     boolean isVisible() {
2488         return true;
2489     }
2490 
2491     @Override
isVisibleRequested()2492     boolean isVisibleRequested() {
2493         return isVisible();
2494     }
2495 
2496     @Override
onAppTransitionDone()2497     void onAppTransitionDone() {
2498         super.onAppTransitionDone();
2499         mWmService.mWindowsChanged = true;
2500         // If the transition finished callback cannot match the token for some reason, make sure the
2501         // rotated state is cleared if it is already invisible.
2502         if (mFixedRotationLaunchingApp != null && !mFixedRotationLaunchingApp.mVisibleRequested
2503                 && !mFixedRotationLaunchingApp.isVisible()
2504                 && !mDisplayRotation.isRotatingSeamlessly()) {
2505             clearFixedRotationLaunchingApp();
2506         }
2507     }
2508 
2509     @Override
setWindowingMode(int windowingMode)2510     public void setWindowingMode(int windowingMode) {
2511         // Intentionally call onRequestedOverrideConfigurationChanged() directly to change windowing
2512         // mode and display windowing mode atomically.
2513         mTmpConfiguration.setTo(getRequestedOverrideConfiguration());
2514         mTmpConfiguration.windowConfiguration.setWindowingMode(windowingMode);
2515         mTmpConfiguration.windowConfiguration.setDisplayWindowingMode(windowingMode);
2516         onRequestedOverrideConfigurationChanged(mTmpConfiguration);
2517     }
2518 
2519     @Override
setDisplayWindowingMode(int windowingMode)2520     void setDisplayWindowingMode(int windowingMode) {
2521         setWindowingMode(windowingMode);
2522     }
2523 
2524     /**
2525      * See {@code WindowState#applyImeWindowsIfNeeded} for the details that we won't traverse the
2526      * IME window in some cases.
2527      */
forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)2528     boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
2529         return mImeWindowsContainer.forAllWindowForce(callback, traverseTopToBottom);
2530     }
2531 
2532     /**
2533      * In the general case, the orientation is computed from the above app windows first. If none of
2534      * the above app windows specify orientation, the orientation is computed from the child window
2535      * container, e.g. {@link ActivityRecord#getOrientation(int)}.
2536      */
2537     @ScreenOrientation
2538     @Override
getOrientation()2539     int getOrientation() {
2540         mLastOrientationSource = null;
2541         if (!handlesOrientationChangeFromDescendant()) {
2542             // Return SCREEN_ORIENTATION_UNSPECIFIED so that Display respect sensor rotation
2543             ProtoLog.v(WM_DEBUG_ORIENTATION,
2544                     "Display id=%d is ignoring all orientation requests, return %d",
2545                     mDisplayId, SCREEN_ORIENTATION_UNSPECIFIED);
2546             return SCREEN_ORIENTATION_UNSPECIFIED;
2547         }
2548 
2549         if (mWmService.mDisplayFrozen) {
2550             if (mWmService.mPolicy.isKeyguardLocked()) {
2551                 // Use the last orientation the while the display is frozen with the keyguard
2552                 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED
2553                 // window. We don't want to check the show when locked window directly though as
2554                 // things aren't stable while the display is frozen, for example the window could be
2555                 // momentarily unavailable due to activity relaunch.
2556                 ProtoLog.v(WM_DEBUG_ORIENTATION,
2557                         "Display id=%d is frozen while keyguard locked, return %d",
2558                         mDisplayId, getLastOrientation());
2559                 return getLastOrientation();
2560             }
2561         }
2562 
2563         final int orientation = super.getOrientation();
2564         if (orientation == SCREEN_ORIENTATION_UNSET) {
2565             // Return SCREEN_ORIENTATION_UNSPECIFIED so that Display respect sensor rotation
2566             ProtoLog.v(WM_DEBUG_ORIENTATION,
2567                     "No app or window is requesting an orientation, return %d for display id=%d",
2568                     SCREEN_ORIENTATION_UNSPECIFIED, mDisplayId);
2569             return SCREEN_ORIENTATION_UNSPECIFIED;
2570         }
2571 
2572         return orientation;
2573     }
2574 
updateDisplayInfo()2575     void updateDisplayInfo() {
2576         // Check if display metrics changed and update base values if needed.
2577         updateBaseDisplayMetricsIfNeeded();
2578 
2579         mDisplay.getDisplayInfo(mDisplayInfo);
2580         mDisplay.getMetrics(mDisplayMetrics);
2581 
2582         onDisplayInfoChanged();
2583         onDisplayChanged(this);
2584     }
2585 
updatePrivacyIndicatorBounds(Rect[] staticBounds)2586     void updatePrivacyIndicatorBounds(Rect[] staticBounds) {
2587         PrivacyIndicatorBounds oldBounds = mCurrentPrivacyIndicatorBounds;
2588         mCurrentPrivacyIndicatorBounds =
2589                 mCurrentPrivacyIndicatorBounds.updateStaticBounds(staticBounds);
2590         if (!Objects.equals(oldBounds, mCurrentPrivacyIndicatorBounds)) {
2591             final DisplayInfo info = mDisplayInfo;
2592             if (mDisplayFrames.onDisplayInfoUpdated(info,
2593                     calculateDisplayCutoutForRotation(info.rotation),
2594                     calculateRoundedCornersForRotation(info.rotation),
2595                     calculatePrivacyIndicatorBoundsForRotation(info.rotation))) {
2596                 mInsetsStateController.onDisplayInfoUpdated(true);
2597             }
2598         }
2599     }
2600 
onDisplayInfoChanged()2601     void onDisplayInfoChanged() {
2602         final DisplayInfo info = mDisplayInfo;
2603         if (mDisplayFrames.onDisplayInfoUpdated(info,
2604                 calculateDisplayCutoutForRotation(info.rotation),
2605                 calculateRoundedCornersForRotation(info.rotation),
2606                 calculatePrivacyIndicatorBoundsForRotation(info.rotation))) {
2607             // TODO(b/161810301): Set notifyInsetsChange to true while the server no longer performs
2608             //                    layout.
2609             mInsetsStateController.onDisplayInfoUpdated(false /* notifyInsetsChanged */);
2610         }
2611         mInputMonitor.layoutInputConsumers(info.logicalWidth, info.logicalHeight);
2612         mDisplayPolicy.onDisplayInfoChanged(info);
2613     }
2614 
2615     @Override
onDisplayChanged(DisplayContent dc)2616     void onDisplayChanged(DisplayContent dc) {
2617         super.onDisplayChanged(dc);
2618         updateSystemGestureExclusionLimit();
2619     }
2620 
updateSystemGestureExclusionLimit()2621     void updateSystemGestureExclusionLimit() {
2622         mSystemGestureExclusionLimit = mWmService.mConstants.mSystemGestureExclusionLimitDp
2623                 * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
2624         updateSystemGestureExclusion();
2625     }
2626 
initializeDisplayBaseInfo()2627     void initializeDisplayBaseInfo() {
2628         final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal;
2629         if (displayManagerInternal != null) {
2630             // Bootstrap the default logical display from the display manager.
2631             final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
2632             if (newDisplayInfo != null) {
2633                 mDisplayInfo.copyFrom(newDisplayInfo);
2634             }
2635         }
2636 
2637         updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
2638                 mDisplayInfo.logicalDensityDpi);
2639         mInitialDisplayWidth = mDisplayInfo.logicalWidth;
2640         mInitialDisplayHeight = mDisplayInfo.logicalHeight;
2641         mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
2642         mInitialDisplayCutout = mDisplayInfo.displayCutout;
2643         mInitialRoundedCorners = mDisplayInfo.roundedCorners;
2644         mCurrentPrivacyIndicatorBounds = new PrivacyIndicatorBounds(new Rect[4],
2645                 mDisplayInfo.rotation);
2646     }
2647 
2648     /**
2649      * If display metrics changed, overrides are not set and it's not just a rotation - update base
2650      * values.
2651      */
updateBaseDisplayMetricsIfNeeded()2652     private void updateBaseDisplayMetricsIfNeeded() {
2653         // Get real display metrics without overrides from WM.
2654         mWmService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo);
2655         final int orientation = mDisplayInfo.rotation;
2656         final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
2657         final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
2658         final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
2659         final int newDensity = mDisplayInfo.logicalDensityDpi;
2660         final DisplayCutout newCutout = mIgnoreDisplayCutout
2661                 ? DisplayCutout.NO_CUTOUT : mDisplayInfo.displayCutout;
2662         final String newUniqueId = mDisplayInfo.uniqueId;
2663         final RoundedCorners newRoundedCorners = mDisplayInfo.roundedCorners;
2664 
2665         final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth
2666                 || mInitialDisplayHeight != newHeight
2667                 || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi
2668                 || !Objects.equals(mInitialDisplayCutout, newCutout)
2669                 || !Objects.equals(mInitialRoundedCorners, newRoundedCorners);
2670         final boolean physicalDisplayChanged = !newUniqueId.equals(mCurrentUniqueDisplayId);
2671 
2672         if (displayMetricsChanged || physicalDisplayChanged) {
2673             if (physicalDisplayChanged) {
2674                 // Reapply the window settings as the underlying physical display has changed.
2675                 mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this);
2676             }
2677 
2678             // If there is an override set for base values - use it, otherwise use new values.
2679             updateBaseDisplayMetrics(mIsSizeForced ? mBaseDisplayWidth : newWidth,
2680                     mIsSizeForced ? mBaseDisplayHeight : newHeight,
2681                     mIsDensityForced ? mBaseDisplayDensity : newDensity);
2682 
2683             // Real display metrics changed, so we should also update initial values.
2684             mInitialDisplayWidth = newWidth;
2685             mInitialDisplayHeight = newHeight;
2686             mInitialDisplayDensity = newDensity;
2687             mInitialDisplayCutout = newCutout;
2688             mInitialRoundedCorners = newRoundedCorners;
2689             mCurrentUniqueDisplayId = newUniqueId;
2690             reconfigureDisplayLocked();
2691         }
2692     }
2693 
2694     /** Sets the maximum width the screen resolution can be */
setMaxUiWidth(int width)2695     void setMaxUiWidth(int width) {
2696         if (DEBUG_DISPLAY) {
2697             Slog.v(TAG_WM, "Setting max ui width:" + width + " on display:" + getDisplayId());
2698         }
2699 
2700         mMaxUiWidth = width;
2701 
2702         // Update existing metrics.
2703         updateBaseDisplayMetrics(mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity);
2704     }
2705 
2706     /** Update base (override) display metrics. */
updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity)2707     void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) {
2708         final int originalWidth = mBaseDisplayWidth;
2709         final int originalHeight = mBaseDisplayHeight;
2710         final int originalDensity = mBaseDisplayDensity;
2711 
2712         mBaseDisplayWidth = baseWidth;
2713         mBaseDisplayHeight = baseHeight;
2714         mBaseDisplayDensity = baseDensity;
2715 
2716         if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) {
2717             mBaseDisplayHeight = (mMaxUiWidth * mBaseDisplayHeight) / mBaseDisplayWidth;
2718             mBaseDisplayWidth = mMaxUiWidth;
2719 
2720             if (DEBUG_DISPLAY) {
2721                 Slog.v(TAG_WM, "Applying config restraints:" + mBaseDisplayWidth + "x"
2722                         + mBaseDisplayHeight + " on display:" + getDisplayId());
2723             }
2724         }
2725 
2726         if (mBaseDisplayWidth != originalWidth || mBaseDisplayHeight != originalHeight
2727                 || mBaseDisplayDensity != originalDensity) {
2728             mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
2729             updateBounds();
2730         }
2731     }
2732 
2733     /**
2734      * Forces this display to use the specified density.
2735      *
2736      * @param density The density in DPI to use. If the value equals to initial density, the setting
2737      *                will be cleared.
2738      * @param userId The target user to apply. Only meaningful when this is default display. If the
2739      *               user id is {@link UserHandle#USER_CURRENT}, it means to apply current settings
2740      *               so only need to configure display.
2741      */
setForcedDensity(int density, int userId)2742     void setForcedDensity(int density, int userId) {
2743         mIsDensityForced = density != mInitialDisplayDensity;
2744         final boolean updateCurrent = userId == UserHandle.USER_CURRENT;
2745         if (mWmService.mCurrentUserId == userId || updateCurrent) {
2746             mBaseDisplayDensity = density;
2747             reconfigureDisplayLocked();
2748         }
2749         if (updateCurrent) {
2750             // We are applying existing settings so no need to save it again.
2751             return;
2752         }
2753 
2754         if (density == mInitialDisplayDensity) {
2755             density = 0;
2756         }
2757         mWmService.mDisplayWindowSettings.setForcedDensity(this, density, userId);
2758     }
2759 
2760     /** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */
setForcedScalingMode(@orceScalingMode int mode)2761     void setForcedScalingMode(@ForceScalingMode int mode) {
2762         if (mode != FORCE_SCALING_MODE_DISABLED) {
2763             mode = FORCE_SCALING_MODE_AUTO;
2764         }
2765 
2766         mDisplayScalingDisabled = (mode != FORCE_SCALING_MODE_AUTO);
2767         Slog.i(TAG_WM, "Using display scaling mode: " + (mDisplayScalingDisabled ? "off" : "auto"));
2768         reconfigureDisplayLocked();
2769 
2770         mWmService.mDisplayWindowSettings.setForcedScalingMode(this, mode);
2771     }
2772 
2773     /** If the given width and height equal to initial size, the setting will be cleared. */
setForcedSize(int width, int height)2774     void setForcedSize(int width, int height) {
2775         mIsSizeForced = mInitialDisplayWidth != width || mInitialDisplayHeight != height;
2776         if (mIsSizeForced) {
2777             // Set some sort of reasonable bounds on the size of the display that we will try
2778             // to emulate.
2779             final int minSize = 200;
2780             final int maxScale = 2;
2781             width = Math.min(Math.max(width, minSize), mInitialDisplayWidth * maxScale);
2782             height = Math.min(Math.max(height, minSize), mInitialDisplayHeight * maxScale);
2783         }
2784 
2785         Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
2786         updateBaseDisplayMetrics(width, height, mBaseDisplayDensity);
2787         reconfigureDisplayLocked();
2788 
2789         if (!mIsSizeForced) {
2790             width = height = 0;
2791         }
2792         mWmService.mDisplayWindowSettings.setForcedSize(this, width, height);
2793     }
2794 
2795     @Override
getStableRect(Rect out)2796     void getStableRect(Rect out) {
2797         final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
2798         out.set(state.getDisplayFrame());
2799         out.inset(state.calculateInsets(out, systemBars(), true /* ignoreVisibility */));
2800     }
2801 
2802     /**
2803      * Get the default display area on the display dedicated to app windows. This one should be used
2804      * only as a fallback location for activity launches when no target display area is specified,
2805      * or for cases when multi-instance is not supported yet (like Split-screen, PiP or Recents).
2806      */
getDefaultTaskDisplayArea()2807     TaskDisplayArea getDefaultTaskDisplayArea() {
2808         return mDisplayAreaPolicy.getDefaultTaskDisplayArea();
2809     }
2810 
2811     /**
2812      * Checks for all non-organized {@link DisplayArea}s for if there is any existing organizer for
2813      * their features. If so, registers them with the matched organizer.
2814      */
2815     @VisibleForTesting
updateDisplayAreaOrganizers()2816     void updateDisplayAreaOrganizers() {
2817         if (!isTrusted()) {
2818             // No need to update for untrusted display.
2819             return;
2820         }
2821         forAllDisplayAreas(displayArea -> {
2822             if (displayArea.isOrganized()) {
2823                 return;
2824             }
2825             // Check if we have a registered organizer for the DA feature.
2826             final IDisplayAreaOrganizer organizer =
2827                     mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController
2828                             .getOrganizerByFeature(displayArea.mFeatureId);
2829             if (organizer != null) {
2830                 displayArea.setOrganizer(organizer);
2831             }
2832         });
2833     }
2834 
2835     /**
2836      * Returns true if the input point is within an app window.
2837      */
pointWithinAppWindow(int x, int y)2838     boolean pointWithinAppWindow(int x, int y) {
2839         final int[] targetWindowType = {-1};
2840         final PooledConsumer fn = PooledLambda.obtainConsumer((w, nonArg) -> {
2841             if (targetWindowType[0] != -1) {
2842                 return;
2843             }
2844 
2845             if (w.isOnScreen() && w.isVisible() && w.getFrame().contains(x, y)) {
2846                 targetWindowType[0] = w.mAttrs.type;
2847                 return;
2848             }
2849         }, PooledLambda.__(WindowState.class), mTmpRect);
2850         forAllWindows(fn, true /* traverseTopToBottom */);
2851         fn.recycle();
2852         return FIRST_APPLICATION_WINDOW <= targetWindowType[0]
2853                 && targetWindowType[0] <= LAST_APPLICATION_WINDOW;
2854     }
2855 
2856     /**
2857      * Find the task whose outside touch area (for resizing) (x, y) falls within.
2858      * Returns null if the touch doesn't fall into a resizing area.
2859      */
2860     @Nullable
findTaskForResizePoint(int x, int y)2861     Task findTaskForResizePoint(int x, int y) {
2862         final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
2863         return getItemFromTaskDisplayAreas(taskDisplayArea ->
2864                 mTmpTaskForResizePointSearchResult.process(taskDisplayArea, x, y, delta));
2865     }
2866 
updateTouchExcludeRegion()2867     void updateTouchExcludeRegion() {
2868         final Task focusedTask = (mFocusedApp != null ? mFocusedApp.getTask() : null);
2869         if (focusedTask == null) {
2870             mTouchExcludeRegion.setEmpty();
2871         } else {
2872             mTouchExcludeRegion.set(mBaseDisplayRect);
2873             final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
2874             mTmpRect.setEmpty();
2875             mTmpRect2.setEmpty();
2876 
2877             final PooledConsumer c = PooledLambda.obtainConsumer(
2878                     DisplayContent::processTaskForTouchExcludeRegion, this,
2879                     PooledLambda.__(Task.class), focusedTask, delta);
2880             forAllTasks(c);
2881             c.recycle();
2882 
2883             // If we removed the focused task above, add it back and only leave its
2884             // outside touch area in the exclusion. TapDetector is not interested in
2885             // any touch inside the focused task itself.
2886             if (!mTmpRect2.isEmpty()) {
2887                 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
2888             }
2889         }
2890         if (mInputMethodWindow != null && mInputMethodWindow.isVisible()) {
2891             // If the input method is visible and the user is typing, we don't want these touch
2892             // events to be intercepted and used to change focus. This would likely cause a
2893             // disappearance of the input method.
2894             mInputMethodWindow.getTouchableRegion(mTmpRegion);
2895             mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
2896         }
2897         for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
2898             final WindowState win = mTapExcludedWindows.get(i);
2899             if (!win.isVisible()) {
2900                 continue;
2901             }
2902             win.getTouchableRegion(mTmpRegion);
2903             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
2904         }
2905         amendWindowTapExcludeRegion(mTouchExcludeRegion);
2906         // TODO(multi-display): Support docked root tasks on secondary displays & task containers.
2907         if (mDisplayId == DEFAULT_DISPLAY
2908                 && getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
2909             mDividerControllerLocked.getTouchRegion(mTmpRect);
2910             mTmpRegion.set(mTmpRect);
2911             mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
2912         }
2913         mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
2914     }
2915 
processTaskForTouchExcludeRegion(Task task, Task focusedTask, int delta)2916     private void processTaskForTouchExcludeRegion(Task task, Task focusedTask, int delta) {
2917         final ActivityRecord topVisibleActivity = task.getTopVisibleActivity();
2918 
2919         if (topVisibleActivity == null || !topVisibleActivity.hasContentToDisplay()) {
2920             return;
2921         }
2922 
2923         // Exclusion region is the region that TapDetector doesn't care about.
2924         // Here we want to remove all non-focused tasks from the exclusion region.
2925         // We also remove the outside touch area for resizing for all freeform
2926         // tasks (including the focused).
2927         // We save the focused task region once we find it, and add it back at the end.
2928         // If the task is root home task and it is resizable and visible (top of its root task),
2929         // we want to exclude the root docked task from touch so we need the entire screen area
2930         // and not just a small portion which the root home task currently is resized to.
2931         if (task.isActivityTypeHome() && task.isVisible() && task.isResizeable()) {
2932             task.getDisplayArea().getBounds(mTmpRect);
2933         } else {
2934             task.getDimBounds(mTmpRect);
2935         }
2936 
2937         if (task == focusedTask) {
2938             // Add the focused task rect back into the exclude region once we are done
2939             // processing root tasks.
2940             // NOTE: this *looks* like a no-op, but this usage of mTmpRect2 is expected by
2941             //       updateTouchExcludeRegion.
2942             mTmpRect2.set(mTmpRect);
2943         }
2944 
2945         final boolean isFreeformed = task.inFreeformWindowingMode();
2946         if (task != focusedTask || isFreeformed) {
2947             if (isFreeformed) {
2948                 // If the task is freeformed, enlarge the area to account for outside
2949                 // touch area for resize.
2950                 mTmpRect.inset(-delta, -delta);
2951                 // Intersect with display content frame. If we have system decor (status bar/
2952                 // navigation bar), we want to exclude that from the tap detection.
2953                 // Otherwise, if the app is partially placed under some system button (eg.
2954                 // Recents, Home), pressing that button would cause a full series of
2955                 // unwanted transfer focus/resume/pause, before we could go home.
2956                 mTmpRect.inset(getInsetsStateController().getRawInsetsState().calculateInsets(
2957                         mTmpRect, systemBars() | ime(), false /* ignoreVisibility */));
2958             }
2959             mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
2960         }
2961     }
2962 
2963     /**
2964      * Union the region with all the tap exclude region provided by windows on this display.
2965      *
2966      * @param inOutRegion The region to be amended.
2967      */
amendWindowTapExcludeRegion(Region inOutRegion)2968     private void amendWindowTapExcludeRegion(Region inOutRegion) {
2969         final Region region = Region.obtain();
2970         for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
2971             final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
2972             win.getTapExcludeRegion(region);
2973             inOutRegion.op(region, Op.UNION);
2974         }
2975         region.recycle();
2976     }
2977 
2978     @Override
switchUser(int userId)2979     void switchUser(int userId) {
2980         super.switchUser(userId);
2981         mWmService.mWindowsChanged = true;
2982         mDisplayPolicy.switchUser();
2983     }
2984 
2985     @Override
removeIfPossible()2986     void removeIfPossible() {
2987         if (isAnimating(TRANSITION | PARENTS)) {
2988             mDeferredRemoval = true;
2989             return;
2990         }
2991         removeImmediately();
2992     }
2993 
2994     @Override
removeImmediately()2995     void removeImmediately() {
2996         mDeferredRemoval = false;
2997         try {
2998             if (mParentWindow != null) {
2999                 mParentWindow.removeEmbeddedDisplayContent(this);
3000             }
3001             // Clear all transitions & screen frozen states when removing display.
3002             mOpeningApps.clear();
3003             mClosingApps.clear();
3004             mChangingContainers.clear();
3005             mUnknownAppVisibilityController.clear();
3006             mAppTransition.removeAppTransitionTimeoutCallbacks();
3007             handleAnimatingStoppedAndTransition();
3008             mWmService.stopFreezingDisplayLocked();
3009             super.removeImmediately();
3010             if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
3011             mPointerEventDispatcher.dispose();
3012             setRotationAnimation(null);
3013             mWmService.mAnimator.removeDisplayLocked(mDisplayId);
3014             mOverlayLayer.release();
3015             mInputMonitor.onDisplayRemoved();
3016             mWmService.mDisplayNotificationController.dispatchDisplayRemoved(this);
3017         } finally {
3018             mDisplayReady = false;
3019         }
3020 
3021         // Apply the pending transaction here since we may not be able to reach the DisplayContent
3022         // on the next traversal if it's removed from RootWindowContainer child list.
3023         getPendingTransaction().apply();
3024         mWmService.mWindowPlacerLocked.requestTraversal();
3025     }
3026 
3027     /** Returns true if a removal action is still being deferred. */
3028     @Override
handleCompleteDeferredRemoval()3029     boolean handleCompleteDeferredRemoval() {
3030         final boolean stillDeferringRemoval = super.handleCompleteDeferredRemoval();
3031 
3032         if (!stillDeferringRemoval && mDeferredRemoval) {
3033             removeImmediately();
3034             return false;
3035         }
3036         return stillDeferringRemoval;
3037     }
3038 
adjustForImeIfNeeded()3039     void adjustForImeIfNeeded() {
3040         final WindowState imeWin = mInputMethodWindow;
3041         final boolean imeVisible = imeWin != null && imeWin.isVisible()
3042                 && imeWin.isDisplayed();
3043         final int imeHeight = getInputMethodWindowVisibleHeight();
3044         mPinnedTaskController.setAdjustedForIme(imeVisible, imeHeight);
3045     }
3046 
getInputMethodWindowVisibleHeight()3047     int getInputMethodWindowVisibleHeight() {
3048         final InsetsState state = getInsetsStateController().getRawInsetsState();
3049         final InsetsSource imeSource = state.peekSource(ITYPE_IME);
3050         if (imeSource == null || !imeSource.isVisible()) {
3051             return 0;
3052         }
3053         final Rect imeFrame = imeSource.getVisibleFrame() != null
3054                 ? imeSource.getVisibleFrame() : imeSource.getFrame();
3055         final Rect dockFrame = mTmpRect;
3056         dockFrame.set(state.getDisplayFrame());
3057         dockFrame.inset(state.calculateInsets(dockFrame, systemBars() | displayCutout(),
3058                 false /* ignoreVisibility */));
3059         return dockFrame.bottom - imeFrame.top;
3060     }
3061 
rotateBounds(@otation int oldRotation, @Rotation int newRotation, Rect inOutBounds)3062     void rotateBounds(@Rotation int oldRotation, @Rotation int newRotation, Rect inOutBounds) {
3063         // Get display bounds on oldRotation as parent bounds for the rotation.
3064         getBounds(mTmpRect, oldRotation);
3065         RotationUtils.rotateBounds(inOutBounds, mTmpRect, oldRotation, newRotation);
3066     }
3067 
setRotationAnimation(ScreenRotationAnimation screenRotationAnimation)3068     public void setRotationAnimation(ScreenRotationAnimation screenRotationAnimation) {
3069         if (mScreenRotationAnimation != null) {
3070             mScreenRotationAnimation.kill();
3071         }
3072         mScreenRotationAnimation = screenRotationAnimation;
3073 
3074         // Hide the windows which are not significant in rotation animation. So that the windows
3075         // don't need to block the unfreeze time.
3076         if (screenRotationAnimation != null && screenRotationAnimation.hasScreenshot()
3077                 // Do not fade for freezing without rotation change.
3078                 && mDisplayRotation.getRotation() != getWindowConfiguration().getRotation()
3079                 && mFadeRotationAnimationController == null) {
3080             startFadeRotationAnimation(false /* shouldDebounce */);
3081         }
3082     }
3083 
getRotationAnimation()3084     public ScreenRotationAnimation getRotationAnimation() {
3085         return mScreenRotationAnimation;
3086     }
3087 
3088     @Override
dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)3089     public void dumpDebug(ProtoOutputStream proto, long fieldId,
3090             @WindowTraceLogLevel int logLevel) {
3091         // Critical log level logs only visible elements to mitigate performance overheard
3092         if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3093             return;
3094         }
3095 
3096         final long token = proto.start(fieldId);
3097         super.dumpDebug(proto, ROOT_DISPLAY_AREA, logLevel);
3098 
3099         proto.write(ID, mDisplayId);
3100         proto.write(DPI, mBaseDisplayDensity);
3101         mDisplayInfo.dumpDebug(proto, DISPLAY_INFO);
3102         mDisplayRotation.dumpDebug(proto, DISPLAY_ROTATION);
3103         final ScreenRotationAnimation screenRotationAnimation = getRotationAnimation();
3104         if (screenRotationAnimation != null) {
3105             screenRotationAnimation.dumpDebug(proto, SCREEN_ROTATION_ANIMATION);
3106         }
3107         mDisplayFrames.dumpDebug(proto, DISPLAY_FRAMES);
3108         mAppTransition.dumpDebug(proto, APP_TRANSITION);
3109         if (mFocusedApp != null) {
3110             mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
3111         }
3112         for (int i = mOpeningApps.size() - 1; i >= 0; i--) {
3113             mOpeningApps.valueAt(i).writeIdentifierToProto(proto, OPENING_APPS);
3114         }
3115         for (int i = mClosingApps.size() - 1; i >= 0; i--) {
3116             mClosingApps.valueAt(i).writeIdentifierToProto(proto, CLOSING_APPS);
3117         }
3118 
3119         final Task focusedRootTask = getFocusedRootTask();
3120         if (focusedRootTask != null) {
3121             proto.write(FOCUSED_ROOT_TASK_ID, focusedRootTask.getRootTaskId());
3122             final ActivityRecord focusedActivity = focusedRootTask.getDisplayArea()
3123                     .getFocusedActivity();
3124             if (focusedActivity != null) {
3125                 focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
3126             }
3127         } else {
3128             proto.write(FOCUSED_ROOT_TASK_ID, INVALID_TASK_ID);
3129         }
3130         proto.write(DISPLAY_READY, isReady());
3131         if (mImeLayeringTarget != null) {
3132             mImeLayeringTarget.dumpDebug(proto, INPUT_METHOD_TARGET, logLevel);
3133         }
3134         if (mImeInputTarget != null) {
3135             mImeInputTarget.dumpDebug(proto, INPUT_METHOD_INPUT_TARGET, logLevel);
3136         }
3137         if (mImeControlTarget != null
3138                 && mImeControlTarget.getWindow() != null) {
3139             mImeControlTarget.getWindow().dumpDebug(proto, INPUT_METHOD_CONTROL_TARGET,
3140                     logLevel);
3141         }
3142         if (mCurrentFocus != null) {
3143             mCurrentFocus.dumpDebug(proto, CURRENT_FOCUS, logLevel);
3144         }
3145         if (mInsetsStateController != null
3146                 && mInsetsStateController.getImeSourceProvider() != null) {
3147             mInsetsStateController.getImeSourceProvider().dumpDebug(proto,
3148                     IME_INSETS_SOURCE_PROVIDER, logLevel);
3149         }
3150         proto.write(IME_POLICY, getImePolicy());
3151         proto.end(token);
3152     }
3153 
3154     @Override
getProtoFieldId()3155     long getProtoFieldId() {
3156         return DISPLAY_CONTENT;
3157     }
3158 
3159     @Override
dump(PrintWriter pw, String prefix, boolean dumpAll)3160     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3161         super.dump(pw, prefix, dumpAll);
3162         pw.print(prefix);
3163         pw.println("Display: mDisplayId=" + mDisplayId + " rootTasks=" + getRootTaskCount());
3164         final String subPrefix = "  " + prefix;
3165         pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
3166         pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
3167         pw.print("dpi");
3168         if (mInitialDisplayWidth != mBaseDisplayWidth
3169                 || mInitialDisplayHeight != mBaseDisplayHeight
3170                 || mInitialDisplayDensity != mBaseDisplayDensity) {
3171             pw.print(" base=");
3172             pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
3173             pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
3174         }
3175         if (mDisplayScalingDisabled) {
3176             pw.println(" noscale");
3177         }
3178         pw.print(" cur=");
3179         pw.print(mDisplayInfo.logicalWidth);
3180         pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
3181         pw.print(" app=");
3182         pw.print(mDisplayInfo.appWidth);
3183         pw.print("x"); pw.print(mDisplayInfo.appHeight);
3184         pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
3185         pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
3186         pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
3187         pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
3188         pw.print(subPrefix + "deferred=" + mDeferredRemoval
3189                 + " mLayoutNeeded=" + mLayoutNeeded);
3190         pw.println(" mTouchExcludeRegion=" + mTouchExcludeRegion);
3191 
3192         pw.println();
3193         pw.print(prefix); pw.print("mLayoutSeq="); pw.println(mLayoutSeq);
3194 
3195         pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
3196         if (mLastFocus != mCurrentFocus) {
3197             pw.print("  mLastFocus="); pw.println(mLastFocus);
3198         }
3199         pw.print("  mFocusedApp="); pw.println(mFocusedApp);
3200         if (mFixedRotationLaunchingApp != null) {
3201             pw.println("  mFixedRotationLaunchingApp=" + mFixedRotationLaunchingApp);
3202         }
3203 
3204         pw.println();
3205         mWallpaperController.dump(pw, "  ");
3206 
3207         if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() > 0) {
3208             pw.println();
3209             pw.print("  mSystemGestureExclusion=");
3210             pw.println(mSystemGestureExclusion);
3211         }
3212 
3213         pw.println();
3214         pw.println(prefix + "Display areas in top down Z order:");
3215         dumpChildDisplayArea(pw, subPrefix, dumpAll);
3216 
3217         pw.println();
3218         pw.println(prefix + "Task display areas in top down Z order:");
3219         forAllTaskDisplayAreas(taskDisplayArea -> {
3220             taskDisplayArea.dump(pw, prefix + "  ", dumpAll);
3221         });
3222 
3223         pw.println();
3224         if (!mExitingTokens.isEmpty()) {
3225             pw.println();
3226             pw.println("  Exiting tokens:");
3227             for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
3228                 final WindowToken token = mExitingTokens.get(i);
3229                 pw.print("  Exiting #"); pw.print(i);
3230                 pw.print(' '); pw.print(token);
3231                 pw.println(':');
3232                 token.dump(pw, "    ", dumpAll);
3233             }
3234         }
3235 
3236         final ScreenRotationAnimation rotationAnimation = getRotationAnimation();
3237         if (rotationAnimation != null) {
3238             pw.println("  mScreenRotationAnimation:");
3239             rotationAnimation.printTo(subPrefix, pw);
3240         } else if (dumpAll) {
3241             pw.println("  no ScreenRotationAnimation ");
3242         }
3243 
3244         pw.println();
3245 
3246         // Dump root task references
3247         final Task rootHomeTask = getDefaultTaskDisplayArea().getRootHomeTask();
3248         if (rootHomeTask != null) {
3249             pw.println(prefix + "rootHomeTask=" + rootHomeTask.getName());
3250         }
3251         final Task rootPinnedTask = getDefaultTaskDisplayArea().getRootPinnedTask();
3252         if (rootPinnedTask != null) {
3253             pw.println(prefix + "rootPinnedTask=" + rootPinnedTask.getName());
3254         }
3255         final Task rootSplitScreenPrimaryTask = getDefaultTaskDisplayArea()
3256                 .getRootSplitScreenPrimaryTask();
3257         if (rootSplitScreenPrimaryTask != null) {
3258             pw.println(
3259                     prefix + "rootSplitScreenPrimaryTask=" + rootSplitScreenPrimaryTask.getName());
3260         }
3261         // TODO: Support recents on non-default task containers
3262         final Task rootRecentsTask = getDefaultTaskDisplayArea().getRootTask(
3263                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
3264         if (rootRecentsTask != null) {
3265             pw.println(prefix + "rootRecentsTask=" + rootRecentsTask.getName());
3266         }
3267         final Task rootDreamTask =
3268                 getRootTask(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_DREAM);
3269         if (rootDreamTask != null) {
3270             pw.println(prefix + "rootDreamTask=" + rootDreamTask.getName());
3271         }
3272 
3273         pw.println();
3274         mPinnedTaskController.dump(prefix, pw);
3275 
3276         pw.println();
3277         mDisplayFrames.dump(prefix, pw);
3278         pw.println();
3279         mDisplayPolicy.dump(prefix, pw);
3280         pw.println();
3281         mDisplayRotation.dump(prefix, pw);
3282         pw.println();
3283         mInputMonitor.dump(pw, "  ");
3284         pw.println();
3285         mInsetsStateController.dump(prefix, pw);
3286     }
3287 
3288     @Override
toString()3289     public String toString() {
3290         return "Display " + mDisplayId + " info=" + mDisplayInfo + " rootTasks=" + mChildren;
3291     }
3292 
getName()3293     String getName() {
3294         return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
3295     }
3296 
3297     /** Find the visible, touch-deliverable window under the given point */
getTouchableWinAtPointLocked(float xf, float yf)3298     WindowState getTouchableWinAtPointLocked(float xf, float yf) {
3299         final int x = (int) xf;
3300         final int y = (int) yf;
3301         final WindowState touchedWin = getWindow(w -> {
3302             final int flags = w.mAttrs.flags;
3303             if (!w.isVisible()) {
3304                 return false;
3305             }
3306             if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
3307                 return false;
3308             }
3309 
3310             w.getVisibleBounds(mTmpRect);
3311             if (!mTmpRect.contains(x, y)) {
3312                 return false;
3313             }
3314 
3315             w.getTouchableRegion(mTmpRegion);
3316 
3317             final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
3318             return mTmpRegion.contains(x, y) || touchFlags == 0;
3319         });
3320 
3321         return touchedWin;
3322     }
3323 
canAddToastWindowForUid(int uid)3324     boolean canAddToastWindowForUid(int uid) {
3325         // We allow one toast window per UID being shown at a time.
3326         // Also if the app is focused adding more than one toast at
3327         // a time for better backwards compatibility.
3328         final WindowState focusedWindowForUid = getWindow(w ->
3329                 w.mOwnerUid == uid && w.isFocused());
3330         if (focusedWindowForUid != null) {
3331             return true;
3332         }
3333         final WindowState win = getWindow(w ->
3334                 w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden
3335                         && !w.mWindowRemovalAllowed);
3336         return win == null;
3337     }
3338 
scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus)3339     void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
3340         if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
3341             return;
3342         }
3343 
3344         // Used to communicate the old focus to the callback method.
3345         mTmpWindow = oldFocus;
3346 
3347         forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */);
3348     }
3349 
3350     /**
3351      * Looking for the focused window on this display if the top focused display hasn't been
3352      * found yet (topFocusedDisplayId is INVALID_DISPLAY) or per-display focused was allowed.
3353      *
3354      * @param topFocusedDisplayId Id of the top focused display.
3355      * @return The focused window or null if there isn't any or no need to seek.
3356      */
findFocusedWindowIfNeeded(int topFocusedDisplayId)3357     WindowState findFocusedWindowIfNeeded(int topFocusedDisplayId) {
3358         return (mWmService.mPerDisplayFocusEnabled || topFocusedDisplayId == INVALID_DISPLAY)
3359                     ? findFocusedWindow() : null;
3360     }
3361 
findFocusedWindow()3362     WindowState findFocusedWindow() {
3363         mTmpWindow = null;
3364 
3365         forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */);
3366 
3367         if (mTmpWindow == null) {
3368             ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: No focusable windows, display=%d",
3369                     getDisplayId());
3370             return null;
3371         }
3372         return mTmpWindow;
3373     }
3374 
3375     /**
3376      * Update the focused window and make some adjustments if the focus has changed.
3377      *
3378      * @param mode Indicates the situation we are in. Possible modes are:
3379      *             {@link WindowManagerService#UPDATE_FOCUS_NORMAL},
3380      *             {@link WindowManagerService#UPDATE_FOCUS_PLACING_SURFACES},
3381      *             {@link WindowManagerService#UPDATE_FOCUS_WILL_PLACE_SURFACES},
3382      *             {@link WindowManagerService#UPDATE_FOCUS_REMOVING_FOCUS}
3383      * @param updateInputWindows Whether to sync the window information to the input module.
3384      * @param topFocusedDisplayId Display id of current top focused display.
3385      * @return {@code true} if the focused window has changed.
3386      */
updateFocusedWindowLocked(int mode, boolean updateInputWindows, int topFocusedDisplayId)3387     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows,
3388             int topFocusedDisplayId) {
3389         WindowState newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
3390         if (mCurrentFocus == newFocus) {
3391             return false;
3392         }
3393         boolean imWindowChanged = false;
3394         final WindowState imWindow = mInputMethodWindow;
3395         if (imWindow != null) {
3396             final WindowState prevTarget = mImeLayeringTarget;
3397             final WindowState newTarget = computeImeTarget(true /* updateImeTarget*/);
3398             imWindowChanged = prevTarget != newTarget;
3399 
3400             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
3401                     && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
3402                 assignWindowLayers(false /* setLayoutNeeded */);
3403             }
3404 
3405             if (imWindowChanged) {
3406                 mWmService.mWindowsChanged = true;
3407                 setLayoutNeeded();
3408                 newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
3409             }
3410         }
3411 
3412         ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "Changing focus from %s to %s displayId=%d Callers=%s",
3413                 mCurrentFocus, newFocus, getDisplayId(), Debug.getCallers(4));
3414         final WindowState oldFocus = mCurrentFocus;
3415         mCurrentFocus = newFocus;
3416 
3417         if (newFocus != null) {
3418             mWinAddedSinceNullFocus.clear();
3419             mWinRemovedSinceNullFocus.clear();
3420 
3421             if (newFocus.canReceiveKeys()) {
3422                 // Displaying a window implicitly causes dispatching to be unpaused.
3423                 // This is to protect against bugs if someone pauses dispatching but
3424                 // forgets to resume.
3425                 newFocus.mToken.paused = false;
3426             }
3427         }
3428 
3429         onWindowFocusChanged(oldFocus, newFocus);
3430 
3431         int focusChanged = getDisplayPolicy().focusChangedLw(oldFocus, newFocus);
3432 
3433         if (imWindowChanged && oldFocus != mInputMethodWindow) {
3434             // Focus of the input method window changed. Perform layout if needed.
3435             if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
3436                 performLayout(true /*initial*/,  updateInputWindows);
3437                 focusChanged &= ~FINISH_LAYOUT_REDO_LAYOUT;
3438             } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
3439                 // Client will do the layout, but we need to assign layers
3440                 // for handleNewWindowLocked() below.
3441                 assignWindowLayers(false /* setLayoutNeeded */);
3442             }
3443         }
3444 
3445         if ((focusChanged & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
3446             // The change in focus caused us to need to do a layout.  Okay.
3447             setLayoutNeeded();
3448             if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
3449                 performLayout(true /*initial*/, updateInputWindows);
3450             } else if (mode == UPDATE_FOCUS_REMOVING_FOCUS) {
3451                 mWmService.mRoot.performSurfacePlacement();
3452             }
3453         }
3454 
3455         if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
3456             // If we defer assigning layers, then the caller is responsible for doing this part.
3457             getInputMonitor().setInputFocusLw(newFocus, updateInputWindows);
3458         }
3459 
3460         adjustForImeIfNeeded();
3461 
3462         // We may need to schedule some toast windows to be removed. The toasts for an app that
3463         // does not have input focus are removed within a timeout to prevent apps to redress
3464         // other apps' UI.
3465         scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus);
3466 
3467         if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
3468             pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
3469         }
3470 
3471         // Notify the accessibility manager for the change so it has the windows before the newly
3472         // focused one starts firing events.
3473         // TODO(b/151179149) investigate what info accessibility service needs before input can
3474         // dispatch focus to clients.
3475         if (mWmService.mAccessibilityController != null) {
3476             mWmService.mH.sendMessage(PooledLambda.obtainMessage(
3477                     this::updateAccessibilityOnWindowFocusChanged,
3478                     mWmService.mAccessibilityController));
3479         }
3480 
3481         mLastFocus = mCurrentFocus;
3482         return true;
3483     }
3484 
updateAccessibilityOnWindowFocusChanged(AccessibilityController accessibilityController)3485     void updateAccessibilityOnWindowFocusChanged(AccessibilityController accessibilityController) {
3486         accessibilityController.onWindowFocusChangedNot(getDisplayId());
3487     }
3488 
onWindowFocusChanged(WindowState oldFocus, WindowState newFocus)3489     private static void onWindowFocusChanged(WindowState oldFocus, WindowState newFocus) {
3490         final Task focusedTask = newFocus != null ? newFocus.getTask() : null;
3491         final Task unfocusedTask = oldFocus != null ? oldFocus.getTask() : null;
3492         if (focusedTask == unfocusedTask) {
3493             return;
3494         }
3495         if (focusedTask != null) {
3496             focusedTask.onWindowFocusChanged(true /* hasFocus */);
3497         }
3498         if (unfocusedTask != null) {
3499             unfocusedTask.onWindowFocusChanged(false /* hasFocus */);
3500         }
3501     }
3502 
3503     /**
3504      * Set the new focused app to this display.
3505      *
3506      * @param newFocus the new focused {@link ActivityRecord}.
3507      * @return true if the focused app is changed.
3508      */
setFocusedApp(ActivityRecord newFocus)3509     boolean setFocusedApp(ActivityRecord newFocus) {
3510         if (newFocus != null) {
3511             final DisplayContent appDisplay = newFocus.getDisplayContent();
3512             if (appDisplay != this) {
3513                 throw new IllegalStateException(newFocus + " is not on " + getName()
3514                         + " but " + ((appDisplay != null) ? appDisplay.getName() : "none"));
3515             }
3516 
3517             // Called even if the focused app is not changed in case the app is moved to a different
3518             // TaskDisplayArea.
3519             onLastFocusedTaskDisplayAreaChanged(newFocus.getDisplayArea());
3520         }
3521         if (mFocusedApp == newFocus) {
3522             return false;
3523         }
3524         ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "setFocusedApp %s displayId=%d Callers=%s",
3525                 newFocus, getDisplayId(), Debug.getCallers(4));
3526         mFocusedApp = newFocus;
3527         getInputMonitor().setFocusedAppLw(newFocus);
3528         updateTouchExcludeRegion();
3529         return true;
3530     }
3531 
3532     /** Called when the focused {@link TaskDisplayArea} on this display may have changed. */
onLastFocusedTaskDisplayAreaChanged(@ullable TaskDisplayArea taskDisplayArea)3533     void onLastFocusedTaskDisplayAreaChanged(@Nullable TaskDisplayArea taskDisplayArea) {
3534         // Only record the TaskDisplayArea that handles orientation request.
3535         if (taskDisplayArea != null && taskDisplayArea.handlesOrientationChangeFromDescendant()) {
3536             mOrientationRequestingTaskDisplayArea = taskDisplayArea;
3537             return;
3538         }
3539 
3540         // If the previous TDA no longer handles orientation request, clear it.
3541         if (mOrientationRequestingTaskDisplayArea != null
3542                 && !mOrientationRequestingTaskDisplayArea
3543                 .handlesOrientationChangeFromDescendant()) {
3544             mOrientationRequestingTaskDisplayArea = null;
3545         }
3546     }
3547 
3548     /**
3549      * Gets the {@link TaskDisplayArea} that we respect orientation requests from apps below it.
3550      */
3551     @Nullable
getOrientationRequestingTaskDisplayArea()3552     TaskDisplayArea getOrientationRequestingTaskDisplayArea() {
3553         return mOrientationRequestingTaskDisplayArea;
3554     }
3555 
3556     /** Updates the layer assignment of windows on this display. */
assignWindowLayers(boolean setLayoutNeeded)3557     void assignWindowLayers(boolean setLayoutNeeded) {
3558         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "assignWindowLayers");
3559         assignChildLayers(getSyncTransaction());
3560         if (setLayoutNeeded) {
3561             setLayoutNeeded();
3562         }
3563 
3564         // We accumlate the layer changes in-to "getPendingTransaction()" but we defer
3565         // the application of this transaction until the animation pass triggers
3566         // prepareSurfaces. This allows us to synchronize Z-ordering changes with
3567         // the hiding and showing of surfaces.
3568         scheduleAnimation();
3569         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3570     }
3571 
3572     // TODO: This should probably be called any time a visual change is made to the hierarchy like
3573     // moving containers or resizing them. Need to investigate the best way to have it automatically
3574     // happen so we don't run into issues with programmers forgetting to do it.
layoutAndAssignWindowLayersIfNeeded()3575     void layoutAndAssignWindowLayersIfNeeded() {
3576         mWmService.mWindowsChanged = true;
3577         setLayoutNeeded();
3578 
3579         if (!mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
3580                 false /*updateInputWindows*/)) {
3581             assignWindowLayers(false /* setLayoutNeeded */);
3582         }
3583 
3584         mInputMonitor.setUpdateInputWindowsNeededLw();
3585         mWmService.mWindowPlacerLocked.performSurfacePlacement();
3586         mInputMonitor.updateInputWindowsLw(false /*force*/);
3587     }
3588 
3589     /** Returns true if a leaked surface was destroyed */
destroyLeakedSurfaces()3590     boolean destroyLeakedSurfaces() {
3591         // Used to indicate that a surface was leaked.
3592         mTmpWindow = null;
3593         final Transaction t = mWmService.mTransactionFactory.get();
3594         forAllWindows(w -> {
3595             final WindowStateAnimator wsa = w.mWinAnimator;
3596             if (wsa.mSurfaceController == null) {
3597                 return;
3598             }
3599             if (!mWmService.mSessions.contains(wsa.mSession)) {
3600                 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
3601                         + w + " surface=" + wsa.mSurfaceController
3602                         + " token=" + w.mToken
3603                         + " pid=" + w.mSession.mPid
3604                         + " uid=" + w.mSession.mUid);
3605                 wsa.destroySurface(t);
3606                 mWmService.mForceRemoves.add(w);
3607                 mTmpWindow = w;
3608             } else if (w.mActivityRecord != null && !w.mActivityRecord.isClientVisible()) {
3609                 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
3610                         + w + " surface=" + wsa.mSurfaceController
3611                         + " token=" + w.mActivityRecord);
3612                 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE LEAK DESTROY: %s", w);
3613                 wsa.destroySurface(t);
3614                 mTmpWindow = w;
3615             }
3616         }, false /* traverseTopToBottom */);
3617         t.apply();
3618 
3619         return mTmpWindow != null;
3620     }
3621 
hasAlertWindowSurfaces()3622     boolean hasAlertWindowSurfaces() {
3623         for (int i = mWmService.mSessions.size() - 1; i >= 0; --i) {
3624             if (mWmService.mSessions.valueAt(i).hasAlertWindowSurfaces(this)) {
3625                 return true;
3626             }
3627         }
3628         return false;
3629     }
3630 
3631     /**
3632      * Set input method window for the display.
3633      * @param win Set when window added or Null when destroyed.
3634      */
setInputMethodWindowLocked(WindowState win)3635     void setInputMethodWindowLocked(WindowState win) {
3636         mInputMethodWindow = win;
3637         // Update display configuration for IME process.
3638         if (mInputMethodWindow != null) {
3639             final int imePid = mInputMethodWindow.mSession.mPid;
3640             mAtmService.onImeWindowSetOnDisplayArea(imePid, mImeWindowsContainer);
3641         }
3642         mInsetsStateController.getSourceProvider(ITYPE_IME).setWindow(win,
3643                 mDisplayPolicy.getImeSourceFrameProvider(), null /* imeFrameProvider */);
3644         computeImeTarget(true /* updateImeTarget */);
3645         updateImeControlTarget();
3646     }
3647 
3648     /**
3649      * Determine and return the window that should be the IME target for layering the IME window.
3650      * @param updateImeTarget If true the system IME target will be updated to match what we found.
3651      * @return The window that should be used as the IME target or null if there isn't any.
3652      */
computeImeTarget(boolean updateImeTarget)3653     WindowState computeImeTarget(boolean updateImeTarget) {
3654         if (mInputMethodWindow == null) {
3655             // There isn't an IME so there shouldn't be a target...That was easy!
3656             if (updateImeTarget) {
3657                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
3658                         + mImeLayeringTarget + " to null since mInputMethodWindow is null");
3659                 setImeLayeringTargetInner(null);
3660             }
3661             return null;
3662         }
3663 
3664         final WindowState curTarget = mImeLayeringTarget;
3665         if (!canUpdateImeTarget()) {
3666             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
3667             return curTarget;
3668         }
3669 
3670         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
3671         // same display. Or even when the current IME/target are not on the same screen as the next
3672         // IME/target. For now only look for input windows on the main screen.
3673         mUpdateImeTarget = updateImeTarget;
3674         WindowState target = getWindow(mComputeImeTargetPredicate);
3675 
3676         if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
3677                 "Proposed new IME target: " + target + " for display: " + getDisplayId());
3678 
3679         if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target
3680                 + " updateImeTarget=" + updateImeTarget);
3681 
3682         if (target == null) {
3683             if (updateImeTarget) {
3684                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
3685                         + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
3686                         + Debug.getCallers(4) : ""));
3687                 setImeLayeringTargetInner(null);
3688             }
3689 
3690             return null;
3691         }
3692 
3693         if (updateImeTarget) {
3694             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
3695                     + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
3696             setImeLayeringTargetInner(target);
3697         }
3698 
3699         return target;
3700     }
3701 
3702     /**
3703      * Calling {@link #computeImeTarget(boolean)} to update the input method target window in
3704      * the candidate app window token if needed.
3705      */
computeImeTargetIfNeeded(ActivityRecord candidate)3706     void computeImeTargetIfNeeded(ActivityRecord candidate) {
3707         if (mImeLayeringTarget != null && mImeLayeringTarget.mActivityRecord == candidate) {
3708             computeImeTarget(true /* updateImeTarget */);
3709         }
3710     }
3711 
isImeControlledByApp()3712     private boolean isImeControlledByApp() {
3713         return mImeInputTarget != null && !mImeInputTarget.inMultiWindowMode();
3714     }
3715 
shouldImeAttachedToApp()3716     boolean shouldImeAttachedToApp() {
3717         return isImeControlledByApp()
3718                 && mImeLayeringTarget != null
3719                 && mImeLayeringTarget.mActivityRecord != null
3720                 && mImeLayeringTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
3721                 // IME is attached to app windows that fill display area. This excludes
3722                 // letterboxed windows.
3723                 && mImeLayeringTarget.matchesDisplayAreaBounds();
3724     }
3725 
3726     /**
3727      * Unlike {@link #shouldImeAttachedToApp()}, this method returns {@code @true} only when both
3728      * the IME layering target is valid to attach the IME surface to the app, and the
3729      * {@link #mInputMethodSurfaceParent} of the {@link ImeContainer} has actually attached to
3730      * the app. (i.e. Even if {@link #shouldImeAttachedToApp()} returns {@code true}, calling this
3731      * method will return {@code false} if the IME surface doesn't actually attach to the app.)
3732      */
isImeAttachedToApp()3733     boolean isImeAttachedToApp() {
3734         return shouldImeAttachedToApp()
3735                 && mInputMethodSurfaceParent != null
3736                 && mInputMethodSurfaceParent.isSameSurface(
3737                         mImeLayeringTarget.mActivityRecord.getSurfaceControl());
3738     }
3739 
3740     /**
3741      * Finds the window which can host IME if IME target cannot host it.
3742      * e.g. IME target cannot host IME when it's display has a parent display OR when display
3743      * doesn't support IME/system decorations.
3744      *
3745      * @param target current IME target.
3746      * @return {@link InsetsControlTarget} that can host IME.
3747      */
getImeHostOrFallback(WindowState target)3748     InsetsControlTarget getImeHostOrFallback(WindowState target) {
3749         if (target != null
3750                 && target.getDisplayContent().getImePolicy() == DISPLAY_IME_POLICY_LOCAL) {
3751             return target;
3752         }
3753         return getImeFallback();
3754     }
3755 
getImeFallback()3756     InsetsControlTarget getImeFallback() {
3757         // host is in non-default display that doesn't support system decor, default to
3758         // default display's StatusBar to control IME (when available), else let system control it.
3759         final DisplayContent defaultDc = mWmService.getDefaultDisplayContentLocked();
3760         WindowState statusBar = defaultDc.getDisplayPolicy().getStatusBar();
3761         return statusBar != null ? statusBar : defaultDc.mRemoteInsetsControlTarget;
3762     }
3763 
3764     /**
3765      * Returns the corresponding IME insets control target according the IME target type.
3766      *
3767      * @param type The type of the IME target.
3768      * @see #IME_TARGET_LAYERING
3769      * @see #IME_TARGET_INPUT
3770      * @see #IME_TARGET_CONTROL
3771      */
getImeTarget(@nputMethodTarget int type)3772     InsetsControlTarget getImeTarget(@InputMethodTarget int type) {
3773         switch (type) {
3774             case IME_TARGET_LAYERING: return mImeLayeringTarget;
3775             case IME_TARGET_INPUT: return mImeInputTarget;
3776             case IME_TARGET_CONTROL: return mImeControlTarget;
3777             default:
3778                 return null;
3779         }
3780     }
3781 
getImePolicy()3782     @DisplayImePolicy int getImePolicy() {
3783         if (!isTrusted()) {
3784             return DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
3785         }
3786         final int imePolicy = mWmService.mDisplayWindowSettings.getImePolicyLocked(this);
3787         if (imePolicy == DISPLAY_IME_POLICY_FALLBACK_DISPLAY && forceDesktopMode()) {
3788             // If the display has not explicitly requested for the IME to be hidden then it shall
3789             // show the IME locally.
3790             return DISPLAY_IME_POLICY_LOCAL;
3791         }
3792         return imePolicy;
3793     }
3794 
forceDesktopMode()3795     boolean forceDesktopMode() {
3796         return mWmService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay && !isPrivate();
3797     }
3798 
3799     @VisibleForTesting
setImeLayeringTarget(WindowState target)3800     void setImeLayeringTarget(WindowState target) {
3801         mImeLayeringTarget = target;
3802     }
3803 
3804     /**
3805      * Sets the window the IME is on top of.
3806      * @param target window to place the IME surface on top of. If {@code null}, the IME will be
3807      *               placed at its parent's surface.
3808      */
setImeLayeringTargetInner(@ullable WindowState target)3809     private void setImeLayeringTargetInner(@Nullable WindowState target) {
3810         if (target == mImeLayeringTarget) {
3811             return;
3812         }
3813         // Prepare the IME screenshot for the last IME target when its task is applying app
3814         // transition. This is for the better IME transition to keep IME visibility when
3815         // transitioning to the next task.
3816         if (mImeLayeringTarget != null && mImeLayeringTarget.isAnimating(PARENTS | TRANSITION,
3817                 ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)) {
3818             attachAndShowImeScreenshotOnTarget();
3819         }
3820 
3821         ProtoLog.i(WM_DEBUG_IME, "setInputMethodTarget %s", target);
3822         mImeLayeringTarget = target;
3823 
3824         // 1. Reparent the IME container window to the target root DA to get the correct bounds and
3825         // config. (Only happens when the target window is in a different root DA)
3826         if (target != null) {
3827             RootDisplayArea targetRoot = target.getRootDisplayArea();
3828             if (targetRoot != null && targetRoot != mImeWindowsContainer.getRootDisplayArea()) {
3829                 // Reposition the IME container to the target root to get the correct bounds and
3830                 // config.
3831                 targetRoot.placeImeContainer(mImeWindowsContainer);
3832                 // Directly hide the IME window so it doesn't flash immediately after reparenting.
3833                 // InsetsController will make IME visible again before animating it.
3834                 if (mInputMethodWindow != null) {
3835                     mInputMethodWindow.hide(false /* doAnimation */, false /* requestAnim */);
3836                 }
3837             }
3838         }
3839         // 2. Assign window layers based on the IME surface parent to make sure it is on top of the
3840         // app.
3841         assignWindowLayers(true /* setLayoutNeeded */);
3842         // 3. The z-order of IME might have been changed. Update the above insets state.
3843         mInsetsStateController.updateAboveInsetsState(mInputMethodWindow,
3844                 mInsetsStateController.getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
3845         // 4. Update the IME control target to apply any inset change and animation.
3846         // 5. Reparent the IME container surface to either the input target app, or the IME window
3847         // parent.
3848         updateImeControlTarget(true /* forceUpdateImeParent */);
3849     }
3850 
3851     @VisibleForTesting
setImeInputTarget(WindowState target)3852     void setImeInputTarget(WindowState target) {
3853         mImeInputTarget = target;
3854         boolean canScreenshot = mImeInputTarget == null || !mImeInputTarget.isSecureLocked();
3855         if (mImeWindowsContainer.setCanScreenshot(canScreenshot)) {
3856             mWmService.requestTraversal();
3857         }
3858     }
3859 
3860     @VisibleForTesting
setImeControlTarget(InsetsControlTarget target)3861     void setImeControlTarget(InsetsControlTarget target) {
3862         mImeControlTarget = target;
3863     }
3864 
3865     @VisibleForTesting
attachAndShowImeScreenshotOnTarget()3866     void attachAndShowImeScreenshotOnTarget() {
3867         // No need to attach screenshot if the IME target not exists or screen is off.
3868         if (!shouldImeAttachedToApp() || !mWmService.mPolicy.isScreenOn()) {
3869             return;
3870         }
3871 
3872         final SurfaceControl.Transaction t = getPendingTransaction();
3873         // Prepare IME screenshot for the target if it allows to attach into.
3874         if (mInputMethodWindow != null && mInputMethodWindow.isVisible()) {
3875             final Task task = mImeLayeringTarget.getTask();
3876             // Re-new the IME screenshot when it does not exist or the size changed.
3877             final boolean renewImeSurface = mImeScreenshot == null
3878                     || mImeScreenshot.getWidth() != mInputMethodWindow.getFrame().width()
3879                     || mImeScreenshot.getHeight() != mInputMethodWindow.getFrame().height();
3880             if (task != null && !task.isHomeOrRecentsRootTask()) {
3881                 SurfaceControl.ScreenshotHardwareBuffer imeBuffer = renewImeSurface
3882                         ? mWmService.mTaskSnapshotController.snapshotImeFromAttachedTask(task)
3883                         : null;
3884                 if (imeBuffer != null) {
3885                     // Remove the last IME surface when the surface needs to renew.
3886                     removeImeSurfaceImmediately();
3887                     mImeScreenshot = createImeSurface(imeBuffer, t);
3888                 }
3889             }
3890         }
3891 
3892         final boolean isValidSnapshot = mImeScreenshot != null && mImeScreenshot.isValid();
3893         // Showing the IME screenshot if the target has already in app transition stage.
3894         // Note that if the current IME insets is not showing, no need to show IME screenshot
3895         // to reflect the true IME insets visibility and the app task layout as possible.
3896         if (isValidSnapshot && getInsetsStateController().getImeSourceProvider().isImeShowing()) {
3897             if (DEBUG_INPUT_METHOD) {
3898                 Slog.d(TAG, "show IME snapshot, ime target=" + mImeLayeringTarget);
3899             }
3900             t.show(mImeScreenshot);
3901         } else if (!isValidSnapshot) {
3902             removeImeSurfaceImmediately();
3903         }
3904     }
3905 
3906     @VisibleForTesting
createImeSurface(SurfaceControl.ScreenshotHardwareBuffer imeBuffer, Transaction t)3907     SurfaceControl createImeSurface(SurfaceControl.ScreenshotHardwareBuffer imeBuffer,
3908             Transaction t) {
3909         final HardwareBuffer buffer = imeBuffer.getHardwareBuffer();
3910         if (DEBUG_INPUT_METHOD) Slog.d(TAG, "create IME snapshot for "
3911                 + mImeLayeringTarget + ", buff width=" + buffer.getWidth()
3912                 + ", height=" + buffer.getHeight());
3913         final ActivityRecord activity = mImeLayeringTarget.mActivityRecord;
3914         final SurfaceControl imeSurface = mWmService.mSurfaceControlFactory.apply(null)
3915                 .setName("IME-snapshot-surface")
3916                 .setBLASTLayer()
3917                 .setFormat(buffer.getFormat())
3918                 .setParent(activity.getSurfaceControl())
3919                 .setCallsite("DisplayContent.attachAndShowImeScreenshotOnTarget")
3920                 .build();
3921         // Make IME snapshot as trusted overlay
3922         InputMonitor.setTrustedOverlayInputInfo(imeSurface, t, getDisplayId(),
3923                 "IME-snapshot-surface");
3924         GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(buffer);
3925         t.setBuffer(imeSurface, graphicBuffer);
3926         t.setColorSpace(mSurfaceControl, ColorSpace.get(ColorSpace.Named.SRGB));
3927         t.setRelativeLayer(imeSurface, activity.getSurfaceControl(), 1);
3928         t.setPosition(imeSurface, mInputMethodWindow.getDisplayFrame().left,
3929                 mInputMethodWindow.getDisplayFrame().top);
3930         return imeSurface;
3931     }
3932 
3933     /**
3934      * Shows the IME screenshot and attach to the IME target window.
3935      *
3936      * Used when the IME target window with IME visible is transitioning to the next target.
3937      * e.g. App transitioning or swiping this the task of the IME target window to recents app.
3938      */
showImeScreenshot()3939     void showImeScreenshot() {
3940         attachAndShowImeScreenshotOnTarget();
3941     }
3942 
3943     /**
3944      * Removes the IME screenshot when necessary.
3945      *
3946      * Used when app transition animation finished or obsoleted screenshot surface like size
3947      * changed by rotation.
3948      */
removeImeScreenshotIfPossible()3949     void removeImeScreenshotIfPossible() {
3950         if (mImeLayeringTarget == null
3951                 || mImeLayeringTarget.mAttrs.type != TYPE_APPLICATION_STARTING
3952                 && !mImeLayeringTarget.isAnimating(PARENTS | TRANSITION,
3953                 ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)) {
3954             removeImeSurfaceImmediately();
3955         }
3956     }
3957 
3958     /** Removes the IME screenshot immediately. */
removeImeSurfaceImmediately()3959     void removeImeSurfaceImmediately() {
3960         if (mImeScreenshot != null) {
3961             if (DEBUG_INPUT_METHOD) Slog.d(TAG, "remove IME snapshot");
3962             getSyncTransaction().remove(mImeScreenshot);
3963             mImeScreenshot = null;
3964         }
3965     }
3966 
3967     /**
3968      * The IME input target is the window which receives input from IME. It is also a candidate
3969      * which controls the visibility and animation of the input method window.
3970      */
updateImeInputAndControlTarget(WindowState target)3971     void updateImeInputAndControlTarget(WindowState target) {
3972         if (mImeInputTarget != target) {
3973             ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
3974             setImeInputTarget(target);
3975             updateImeControlTarget();
3976         }
3977     }
3978 
updateImeControlTarget()3979     void updateImeControlTarget() {
3980         updateImeControlTarget(false /* forceUpdateImeParent */);
3981     }
3982 
updateImeControlTarget(boolean forceUpdateImeParent)3983     void updateImeControlTarget(boolean forceUpdateImeParent) {
3984         InsetsControlTarget prevImeControlTarget = mImeControlTarget;
3985         mImeControlTarget = computeImeControlTarget();
3986         mInsetsStateController.onImeControlTargetChanged(mImeControlTarget);
3987         // Update Ime parent when IME insets leash created or the new IME layering target might
3988         // updated from setImeLayeringTarget, which is the best time that default IME visibility
3989         // has been settled down after IME control target changed.
3990         final boolean imeParentChanged =
3991                 prevImeControlTarget != mImeControlTarget || forceUpdateImeParent;
3992         if (imeParentChanged) {
3993             updateImeParent();
3994         }
3995 
3996         final WindowState win = InsetsControlTarget.asWindowOrNull(mImeControlTarget);
3997         final IBinder token = win != null ? win.mClient.asBinder() : null;
3998         // Note: not allowed to call into IMMS with the WM lock held, hence the post.
3999         mWmService.mH.post(() ->
4000                 InputMethodManagerInternal.get().reportImeControl(token, imeParentChanged)
4001         );
4002     }
4003 
updateImeParent()4004     void updateImeParent() {
4005         final SurfaceControl newParent = computeImeParent();
4006         if (newParent != null && newParent != mInputMethodSurfaceParent) {
4007             mInputMethodSurfaceParent = newParent;
4008             getPendingTransaction().reparent(mImeWindowsContainer.mSurfaceControl, newParent);
4009             // When surface parent is removed, the relative layer will also be removed. We need to
4010             // do a force update to make sure there is a layer set for the new parent.
4011             assignRelativeLayerForIme(getPendingTransaction(), true /* forceUpdate */);
4012             scheduleAnimation();
4013         }
4014     }
4015 
4016     /**
4017      * Computes the window where we hand IME control to.
4018      */
4019     @VisibleForTesting
computeImeControlTarget()4020     InsetsControlTarget computeImeControlTarget() {
4021         if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null
4022                 || (mImeInputTarget != null
4023                         && getImeHostOrFallback(mImeInputTarget.getWindow())
4024                                 == mRemoteInsetsControlTarget)) {
4025             return mRemoteInsetsControlTarget;
4026         } else {
4027             return mImeInputTarget;
4028         }
4029     }
4030 
4031     /**
4032      * Computes the window the IME should be attached to.
4033      */
4034     @VisibleForTesting
computeImeParent()4035     SurfaceControl computeImeParent() {
4036         // Force attaching IME to the display when magnifying, or it would be magnified with
4037         // target app together.
4038         final boolean allowAttachToApp = (mMagnificationSpec == null);
4039 
4040         // Attach it to app if the target is part of an app and such app is covering the entire
4041         // screen. If it's not covering the entire screen the IME might extend beyond the apps
4042         // bounds.
4043         if (allowAttachToApp && shouldImeAttachedToApp()) {
4044             if (mImeLayeringTarget.mActivityRecord != mImeInputTarget.mActivityRecord) {
4045                 // Do not change parent if the window hasn't requested IME.
4046                 return null;
4047             }
4048             return mImeLayeringTarget.mActivityRecord.getSurfaceControl();
4049         }
4050 
4051         // Otherwise, we just attach it to where the display area policy put it.
4052         return mImeWindowsContainer.getParent() != null
4053                 ? mImeWindowsContainer.getParent().getSurfaceControl() : null;
4054     }
4055 
setLayoutNeeded()4056     void setLayoutNeeded() {
4057         if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
4058         mLayoutNeeded = true;
4059     }
4060 
clearLayoutNeeded()4061     private void clearLayoutNeeded() {
4062         if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3));
4063         mLayoutNeeded = false;
4064     }
4065 
isLayoutNeeded()4066     boolean isLayoutNeeded() {
4067         return mLayoutNeeded;
4068     }
4069 
dumpTokens(PrintWriter pw, boolean dumpAll)4070     void dumpTokens(PrintWriter pw, boolean dumpAll) {
4071         if (mTokenMap.isEmpty()) {
4072             return;
4073         }
4074         pw.println("  Display #" + mDisplayId);
4075         final Iterator<WindowToken> it = mTokenMap.values().iterator();
4076         while (it.hasNext()) {
4077             final WindowToken token = it.next();
4078             pw.print("  ");
4079             pw.print(token);
4080             if (dumpAll) {
4081                 pw.println(':');
4082                 token.dump(pw, "    ", dumpAll);
4083             } else {
4084                 pw.println();
4085             }
4086         }
4087 
4088         if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty() || !mChangingContainers.isEmpty()) {
4089             pw.println();
4090             if (mOpeningApps.size() > 0) {
4091                 pw.print("  mOpeningApps="); pw.println(mOpeningApps);
4092             }
4093             if (mClosingApps.size() > 0) {
4094                 pw.print("  mClosingApps="); pw.println(mClosingApps);
4095             }
4096             if (mChangingContainers.size() > 0) {
4097                 pw.print("  mChangingApps="); pw.println(mChangingContainers);
4098             }
4099         }
4100 
4101         mUnknownAppVisibilityController.dump(pw, "  ");
4102     }
4103 
dumpWindowAnimators(PrintWriter pw, String subPrefix)4104     void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
4105         final int[] index = new int[1];
4106         forAllWindows(w -> {
4107             final WindowStateAnimator wAnim = w.mWinAnimator;
4108             pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim);
4109             index[0] = index[0] + 1;
4110         }, false /* traverseTopToBottom */);
4111     }
4112 
4113     /**
4114      * Starts the Keyguard exit animation on all windows that don't belong to an app token.
4115      */
startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade, boolean subtle)4116     void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade,
4117             boolean subtle) {
4118         final WindowManagerPolicy policy = mWmService.mPolicy;
4119         forAllWindows(w -> {
4120             if (w.mActivityRecord == null && policy.canBeHiddenByKeyguardLw(w)
4121                     && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
4122                 w.startAnimation(policy.createHiddenByKeyguardExit(
4123                         onWallpaper, goingToShade, subtle));
4124             }
4125         }, true /* traverseTopToBottom */);
4126         for (int i = mShellRoots.size() - 1; i >= 0; --i) {
4127             mShellRoots.valueAt(i).startAnimation(policy.createHiddenByKeyguardExit(
4128                     onWallpaper, goingToShade, subtle));
4129         }
4130     }
4131 
4132     /** @return {@code true} if there is window to wait before enabling the screen. */
shouldWaitForSystemDecorWindowsOnBoot()4133     boolean shouldWaitForSystemDecorWindowsOnBoot() {
4134         if (!isDefaultDisplay && !supportsSystemDecorations()) {
4135             // Nothing to wait because the secondary display doesn't support system decorations,
4136             // there is no wallpaper, keyguard (status bar) or application (home) window to show
4137             // during booting.
4138             return false;
4139         }
4140 
4141         final SparseBooleanArray drawnWindowTypes = new SparseBooleanArray();
4142         // Presuppose keyguard is drawn because if its window isn't attached, we don't know if it
4143         // wants to be shown or hidden, then it should not delay enabling the screen.
4144         drawnWindowTypes.put(TYPE_NOTIFICATION_SHADE, true);
4145 
4146         final WindowState visibleNotDrawnWindow = getWindow(w -> {
4147             final boolean isVisible = w.isVisible() && !w.mObscured;
4148             final boolean isDrawn = w.isDrawn();
4149             if (isVisible && !isDrawn) {
4150                 ProtoLog.d(WM_DEBUG_BOOT,
4151                         "DisplayContent: boot is waiting for window of type %d to be drawn",
4152                         w.mAttrs.type);
4153                 return true;
4154             }
4155             if (isDrawn) {
4156                 switch (w.mAttrs.type) {
4157                     case TYPE_BOOT_PROGRESS:
4158                     case TYPE_BASE_APPLICATION:
4159                     case TYPE_WALLPAPER:
4160                         drawnWindowTypes.put(w.mAttrs.type, true);
4161                         break;
4162                     case TYPE_NOTIFICATION_SHADE:
4163                         drawnWindowTypes.put(TYPE_NOTIFICATION_SHADE,
4164                                 mWmService.mPolicy.isKeyguardDrawnLw());
4165                         break;
4166                 }
4167             }
4168             return false;
4169         });
4170 
4171         if (visibleNotDrawnWindow != null) {
4172             // Wait for the visible window to be drawn.
4173             return true;
4174         }
4175 
4176         // if the wallpaper service is disabled on the device, we're never going to have
4177         // wallpaper, don't bother waiting for it
4178         boolean wallpaperEnabled = mWmService.mContext.getResources().getBoolean(
4179                 com.android.internal.R.bool.config_enableWallpaperService)
4180                 && mWmService.mContext.getResources().getBoolean(
4181                 com.android.internal.R.bool.config_checkWallpaperAtBoot)
4182                 && !mWmService.mOnlyCore;
4183 
4184         final boolean haveBootMsg = drawnWindowTypes.get(TYPE_BOOT_PROGRESS);
4185         final boolean haveApp = drawnWindowTypes.get(TYPE_BASE_APPLICATION);
4186         final boolean haveWallpaper = drawnWindowTypes.get(TYPE_WALLPAPER);
4187         final boolean haveKeyguard = drawnWindowTypes.get(TYPE_NOTIFICATION_SHADE);
4188 
4189         ProtoLog.i(WM_DEBUG_SCREEN_ON,
4190                 "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b "
4191                         + "wallEnabled=%b haveKeyguard=%b",
4192                 mWmService.mSystemBooted, mWmService.mShowingBootMessages, haveBootMsg,
4193                 haveApp, haveWallpaper, wallpaperEnabled, haveKeyguard);
4194 
4195         // If we are turning on the screen to show the boot message, don't do it until the boot
4196         // message is actually displayed.
4197         if (!mWmService.mSystemBooted && !haveBootMsg) {
4198             return true;
4199         }
4200 
4201         // If we are turning on the screen after the boot is completed normally, don't do so until
4202         // we have the application and wallpaper.
4203         if (mWmService.mSystemBooted
4204                 && ((!haveApp && !haveKeyguard) || (wallpaperEnabled && !haveWallpaper))) {
4205             return true;
4206         }
4207 
4208         return false;
4209     }
4210 
updateWindowsForAnimator()4211     void updateWindowsForAnimator() {
4212         forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
4213     }
4214 
isInputMethodClientFocus(int uid, int pid)4215     boolean isInputMethodClientFocus(int uid, int pid) {
4216         final WindowState imFocus = computeImeTarget(false /* updateImeTarget */);
4217         if (imFocus == null) {
4218             return false;
4219         }
4220 
4221         if (DEBUG_INPUT_METHOD) {
4222             Slog.i(TAG_WM, "Desired input method target: " + imFocus);
4223             Slog.i(TAG_WM, "Current focus: " + mCurrentFocus + " displayId=" + mDisplayId);
4224             Slog.i(TAG_WM, "Last focus: " + mLastFocus + " displayId=" + mDisplayId);
4225         }
4226 
4227         if (DEBUG_INPUT_METHOD) {
4228             Slog.i(TAG_WM, "IM target uid/pid: " + imFocus.mSession.mUid
4229                     + "/" + imFocus.mSession.mPid);
4230             Slog.i(TAG_WM, "Requesting client uid/pid: " + uid + "/" + pid);
4231         }
4232 
4233         return imFocus.mSession.mUid == uid && imFocus.mSession.mPid == pid;
4234     }
4235 
hasSecureWindowOnScreen()4236     boolean hasSecureWindowOnScreen() {
4237         final WindowState win = getWindow(w -> w.isOnScreen() && w.isSecureLocked());
4238         return win != null;
4239     }
4240 
onWindowFreezeTimeout()4241     void onWindowFreezeTimeout() {
4242         Slog.w(TAG_WM, "Window freeze timeout expired.");
4243         mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
4244 
4245         forAllWindows(w -> {
4246             if (!w.getOrientationChanging()) {
4247                 return;
4248             }
4249             w.orientationChangeTimedOut();
4250             w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
4251                     - mWmService.mDisplayFreezeTime);
4252             Slog.w(TAG_WM, "Force clearing orientation change: " + w);
4253         }, true /* traverseTopToBottom */);
4254         mWmService.mWindowPlacerLocked.performSurfacePlacement();
4255     }
4256 
4257     /**
4258      * Callbacks when the given type of {@link WindowContainer} animation finished running in the
4259      * hierarchy.
4260      */
onWindowAnimationFinished(@onNull WindowContainer wc, int type)4261     void onWindowAnimationFinished(@NonNull WindowContainer wc, int type) {
4262         if (type == ANIMATION_TYPE_APP_TRANSITION || type == ANIMATION_TYPE_RECENTS) {
4263             removeImeSurfaceImmediately();
4264         }
4265     }
4266 
4267     // TODO: Super unexpected long method that should be broken down...
applySurfaceChangesTransaction()4268     void applySurfaceChangesTransaction() {
4269         final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
4270 
4271         mTmpUpdateAllDrawn.clear();
4272 
4273         int repeats = 0;
4274         do {
4275             repeats++;
4276             if (repeats > 6) {
4277                 Slog.w(TAG, "Animation repeat aborted after too many iterations");
4278                 clearLayoutNeeded();
4279                 break;
4280             }
4281 
4282             if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
4283                     pendingLayoutChanges);
4284 
4285             if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
4286                 mWallpaperController.adjustWallpaperWindows();
4287             }
4288 
4289             if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
4290                 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
4291                 if (updateOrientation()) {
4292                     setLayoutNeeded();
4293                     sendNewConfiguration();
4294                 }
4295             }
4296 
4297             if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
4298                 setLayoutNeeded();
4299             }
4300 
4301             // FIRST LOOP: Perform a layout, if needed.
4302             if (repeats < LAYOUT_REPEAT_THRESHOLD) {
4303                 performLayout(repeats == 1, false /* updateInputWindows */);
4304             } else {
4305                 Slog.w(TAG, "Layout repeat skipped after too many iterations");
4306             }
4307 
4308             // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
4309             pendingLayoutChanges = 0;
4310 
4311             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
4312             try {
4313                 mDisplayPolicy.beginPostLayoutPolicyLw();
4314                 forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
4315                 pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw();
4316             } finally {
4317                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4318             }
4319             if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
4320                     "after finishPostLayoutPolicyLw", pendingLayoutChanges);
4321             mInsetsStateController.onPostLayout();
4322         } while (pendingLayoutChanges != 0);
4323 
4324         mTmpApplySurfaceChangesTransactionState.reset();
4325 
4326         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
4327         try {
4328             forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
4329         } finally {
4330             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4331         }
4332         prepareSurfaces();
4333 
4334         // This should be called after the insets have been dispatched to clients and we have
4335         // committed finish drawing windows.
4336         mInsetsStateController.getImeSourceProvider().checkShowImePostLayout();
4337 
4338         mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent;
4339         if (!mWmService.mDisplayFrozen) {
4340             mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
4341                     mLastHasContent,
4342                     mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
4343                     mTmpApplySurfaceChangesTransactionState.preferredModeId,
4344                     mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate,
4345                     mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate,
4346                     mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
4347                     true /* inTraversal, must call performTraversalInTrans... below */);
4348         }
4349 
4350         final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
4351         if (wallpaperVisible != mLastWallpaperVisible) {
4352             mLastWallpaperVisible = wallpaperVisible;
4353             mWmService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this);
4354         }
4355 
4356         while (!mTmpUpdateAllDrawn.isEmpty()) {
4357             final ActivityRecord activity = mTmpUpdateAllDrawn.removeLast();
4358             // See if any windows have been drawn, so they (and others associated with them)
4359             // can now be shown.
4360             activity.updateAllDrawn();
4361         }
4362     }
4363 
updateBounds()4364     private void updateBounds() {
4365         calculateBounds(mDisplayInfo, mTmpBounds);
4366         setBounds(mTmpBounds);
4367         if (mPortalWindowHandle != null && mParentSurfaceControl != null) {
4368             mPortalWindowHandle.touchableRegion.getBounds(mTmpRect);
4369             if (!mTmpBounds.equals(mTmpRect)) {
4370                 mPortalWindowHandle.touchableRegion.set(mTmpBounds);
4371                 getPendingTransaction().setInputWindowInfo(
4372                         mParentSurfaceControl, mPortalWindowHandle);
4373             }
4374         }
4375     }
4376 
4377     // Determines the current display bounds based on the current state
calculateBounds(DisplayInfo displayInfo, Rect out)4378     private void calculateBounds(DisplayInfo displayInfo, Rect out) {
4379         // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
4380         final int rotation = displayInfo.rotation;
4381         boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
4382         final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
4383         final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
4384         int width = displayInfo.logicalWidth;
4385         int left = (physWidth - width) / 2;
4386         int height = displayInfo.logicalHeight;
4387         int top = (physHeight - height) / 2;
4388         out.set(left, top, left + width, top + height);
4389     }
4390 
getBounds(Rect out, @Rotation int rotation)4391     private void getBounds(Rect out, @Rotation int rotation) {
4392         getBounds(out);
4393 
4394         // Rotate the Rect if needed.
4395         final int currentRotation = mDisplayInfo.rotation;
4396         final int rotationDelta = deltaRotation(currentRotation, rotation);
4397         if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
4398             out.set(0, 0, out.height(), out.width());
4399         }
4400     }
4401 
4402     /** @return the orientation of the display when it's rotation is ROTATION_0. */
getNaturalOrientation()4403     int getNaturalOrientation() {
4404         return mBaseDisplayWidth < mBaseDisplayHeight
4405                 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
4406     }
4407 
performLayout(boolean initial, boolean updateInputWindows)4408     void performLayout(boolean initial, boolean updateInputWindows) {
4409         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performLayout");
4410         try {
4411             performLayoutNoTrace(initial, updateInputWindows);
4412         } finally {
4413             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4414         }
4415     }
4416 
performLayoutNoTrace(boolean initial, boolean updateInputWindows)4417     private void performLayoutNoTrace(boolean initial, boolean updateInputWindows) {
4418         if (!isLayoutNeeded()) {
4419             return;
4420         }
4421         clearLayoutNeeded();
4422 
4423         if (DEBUG_LAYOUT) {
4424             Slog.v(TAG, "-------------------------------------");
4425             Slog.v(TAG, "performLayout: dw=" + mDisplayInfo.logicalWidth
4426                     + " dh=" + mDisplayInfo.logicalHeight);
4427         }
4428 
4429         int seq = mLayoutSeq + 1;
4430         if (seq < 0) seq = 0;
4431         mLayoutSeq = seq;
4432 
4433         mTmpInitial = initial;
4434 
4435 
4436         // First perform layout of any root windows (not attached to another window).
4437         forAllWindows(mPerformLayout, true /* traverseTopToBottom */);
4438 
4439         // Now perform layout of attached windows, which usually depend on the position of the
4440         // window they are attached to. XXX does not deal with windows that are attached to windows
4441         // that are themselves attached.
4442         forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);
4443 
4444         // Window frames may have changed. Tell the input dispatcher about it.
4445         mInputMonitor.setUpdateInputWindowsNeededLw();
4446         if (updateInputWindows) {
4447             mInputMonitor.updateInputWindowsLw(false /*force*/);
4448         }
4449     }
4450 
4451     /**
4452      * Takes a snapshot of the display.  In landscape mode this grabs the whole screen.
4453      * In portrait mode, it grabs the full screenshot.
4454      */
screenshotDisplayLocked()4455     Bitmap screenshotDisplayLocked() {
4456         if (!mWmService.mPolicy.isScreenOn()) {
4457             if (DEBUG_SCREENSHOT) {
4458                 Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
4459             }
4460             return null;
4461         }
4462 
4463         final ScreenRotationAnimation screenRotationAnimation =
4464                 mWmService.mRoot.getDisplayContent(DEFAULT_DISPLAY).getRotationAnimation();
4465         final boolean inRotation = screenRotationAnimation != null &&
4466                 screenRotationAnimation.isAnimating();
4467         if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, "Taking screenshot while rotating");
4468 
4469         // Send invalid rect and no width and height since it will screenshot the entire display.
4470         final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
4471         final SurfaceControl.DisplayCaptureArgs captureArgs =
4472                 new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
4473                         .setUseIdentityTransform(inRotation)
4474                         .build();
4475         final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
4476                 SurfaceControl.captureDisplay(captureArgs);
4477         final Bitmap bitmap = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
4478         if (bitmap == null) {
4479             Slog.w(TAG_WM, "Failed to take screenshot");
4480             return null;
4481         }
4482 
4483         // Create a copy of the screenshot that is immutable and backed in ashmem.
4484         // This greatly reduces the overhead of passing the bitmap between processes.
4485         final Bitmap ret = bitmap.asShared();
4486         if (ret != bitmap) {
4487             bitmap.recycle();
4488         }
4489         return ret;
4490     }
4491 
setExitingTokensHasVisible(boolean hasVisible)4492     void setExitingTokensHasVisible(boolean hasVisible) {
4493         for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
4494             mExitingTokens.get(i).hasVisible = hasVisible;
4495         }
4496 
4497         // Initialize state of exiting applications.
4498         forAllRootTasks(task -> {
4499             final ArrayList<ActivityRecord> activities = task.mExitingActivities;
4500             for (int j = activities.size() - 1; j >= 0; --j) {
4501                 activities.get(j).hasVisible = hasVisible;
4502             }
4503         });
4504     }
4505 
removeExistingTokensIfPossible()4506     void removeExistingTokensIfPossible() {
4507         for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
4508             final WindowToken token = mExitingTokens.get(i);
4509             if (!token.hasVisible) {
4510                 mExitingTokens.remove(i);
4511             }
4512         }
4513 
4514         // Time to remove any exiting applications?
4515         forAllRootTasks(task -> {
4516             final ArrayList<ActivityRecord> activities = task.mExitingActivities;
4517             for (int j = activities.size() - 1; j >= 0; --j) {
4518                 final ActivityRecord activity = activities.get(j);
4519                 if (!activity.hasVisible && !mDisplayContent.mClosingApps.contains(activity)
4520                         && (!activity.mIsExiting || activity.isEmpty())) {
4521                     // Make sure there is no animation running on this activity, so any windows
4522                     // associated with it will be removed as soon as their animations are
4523                     // complete.
4524                     cancelAnimation();
4525                     ProtoLog.v(WM_DEBUG_ADD_REMOVE,
4526                             "performLayout: Activity exiting now removed %s", activity);
4527                     activity.removeIfPossible();
4528                 }
4529             }
4530         });
4531     }
4532 
4533     @Override
onDescendantOverrideConfigurationChanged()4534     void onDescendantOverrideConfigurationChanged() {
4535         setLayoutNeeded();
4536         mWmService.requestTraversal();
4537     }
4538 
okToDisplay()4539     boolean okToDisplay() {
4540         return okToDisplay(false);
4541     }
4542 
okToDisplay(boolean ignoreFrozen)4543     boolean okToDisplay(boolean ignoreFrozen) {
4544         return okToDisplay(ignoreFrozen, false /* ignoreScreenOn */);
4545     }
4546 
okToDisplay(boolean ignoreFrozen, boolean ignoreScreenOn)4547     boolean okToDisplay(boolean ignoreFrozen, boolean ignoreScreenOn) {
4548         if (mDisplayId == DEFAULT_DISPLAY) {
4549             return (!mWmService.mDisplayFrozen || ignoreFrozen)
4550                     && mWmService.mDisplayEnabled
4551                     && (ignoreScreenOn || mWmService.mPolicy.isScreenOn());
4552         }
4553         return mDisplayInfo.state == Display.STATE_ON;
4554     }
4555 
okToAnimate()4556     boolean okToAnimate() {
4557         return okToAnimate(false);
4558     }
4559 
okToAnimate(boolean ignoreFrozen)4560     boolean okToAnimate(boolean ignoreFrozen) {
4561         return okToAnimate(ignoreFrozen, false /* ignoreScreenOn */);
4562     }
4563 
okToAnimate(boolean ignoreFrozen, boolean ignoreScreenOn)4564     boolean okToAnimate(boolean ignoreFrozen, boolean ignoreScreenOn) {
4565         return okToDisplay(ignoreFrozen, ignoreScreenOn)
4566                 && (mDisplayId != DEFAULT_DISPLAY
4567                 || mWmService.mPolicy.okToAnimate(ignoreScreenOn));
4568     }
4569 
4570     static final class TaskForResizePointSearchResult {
4571         private Task taskForResize;
4572         private int x;
4573         private int y;
4574         private int delta;
4575         private Rect mTmpRect = new Rect();
4576 
process(WindowContainer root, int x, int y, int delta)4577         Task process(WindowContainer root, int x, int y, int delta) {
4578             taskForResize = null;
4579             this.x = x;
4580             this.y = y;
4581             this.delta = delta;
4582             mTmpRect.setEmpty();
4583 
4584             final PooledFunction f = PooledLambda.obtainFunction(
4585                     TaskForResizePointSearchResult::processTask, this, PooledLambda.__(Task.class));
4586             root.forAllTasks(f);
4587             f.recycle();
4588 
4589             return taskForResize;
4590         }
4591 
processTask(Task task)4592         private boolean processTask(Task task) {
4593             if (!task.getRootTask().getWindowConfiguration().canResizeTask()) {
4594                 return true;
4595             }
4596 
4597             if (task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
4598                 return true;
4599             }
4600 
4601             if (task.isOrganized()) {
4602                 return true;
4603             }
4604 
4605             // We need to use the task's dim bounds (which is derived from the visible bounds of
4606             // its apps windows) for any touch-related tests. Can't use the task's original
4607             // bounds because it might be adjusted to fit the content frame. One example is when
4608             // the task is put to top-left quadrant, the actual visible area would not start at
4609             // (0,0) after it's adjusted for the status bar.
4610             task.getDimBounds(mTmpRect);
4611             mTmpRect.inset(-delta, -delta);
4612             if (mTmpRect.contains(x, y)) {
4613                 mTmpRect.inset(delta, delta);
4614 
4615                 if (!mTmpRect.contains(x, y)) {
4616                     taskForResize = task;
4617                     return true;
4618                 }
4619                 // User touched inside the task. No need to look further,
4620                 // focus transfer will be handled in ACTION_UP.
4621                 return true;
4622             }
4623 
4624             return false;
4625         }
4626     }
4627 
4628     private static final class ApplySurfaceChangesTransactionState {
4629         public boolean displayHasContent;
4630         public boolean obscured;
4631         public boolean syswin;
4632         public boolean preferMinimalPostProcessing;
4633         public float preferredRefreshRate;
4634         public int preferredModeId;
4635         public float preferredMinRefreshRate;
4636         public float preferredMaxRefreshRate;
4637 
reset()4638         void reset() {
4639             displayHasContent = false;
4640             obscured = false;
4641             syswin = false;
4642             preferMinimalPostProcessing = false;
4643             preferredRefreshRate = 0;
4644             preferredModeId = 0;
4645             preferredMinRefreshRate = 0;
4646             preferredMaxRefreshRate = 0;
4647         }
4648     }
4649 
4650     /**
4651      * Container for IME windows.
4652      *
4653      * This has some special behaviors:
4654      * - layers assignment is ignored except if setNeedsLayer() has been called before (and no
4655      *   layer has been assigned since), to facilitate assigning the layer from the IME target, or
4656      *   fall back if there is no target.
4657      * - the container doesn't always participate in window traversal, according to
4658      *   {@link #skipImeWindowsDuringTraversal()}
4659      */
4660     private static class ImeContainer extends DisplayArea.Tokens {
4661         boolean mNeedsLayer = false;
4662 
ImeContainer(WindowManagerService wms)4663         ImeContainer(WindowManagerService wms) {
4664             super(wms, Type.ABOVE_TASKS, "ImeContainer");
4665         }
4666 
setNeedsLayer()4667         public void setNeedsLayer() {
4668             mNeedsLayer = true;
4669         }
4670 
4671         @Override
getOrientation(int candidate)4672         int getOrientation(int candidate) {
4673             if (mIgnoreOrientationRequest) {
4674                 return SCREEN_ORIENTATION_UNSET;
4675             }
4676 
4677             // IME does not participate in orientation.
4678             return candidate;
4679         }
4680 
4681         @Override
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4682         boolean forAllWindows(ToBooleanFunction<WindowState> callback,
4683                 boolean traverseTopToBottom) {
4684             final DisplayContent dc = mDisplayContent;
4685             if (skipImeWindowsDuringTraversal(dc)) {
4686                 return false;
4687             }
4688             return super.forAllWindows(callback, traverseTopToBottom);
4689         }
4690 
skipImeWindowsDuringTraversal(DisplayContent dc)4691         private static boolean skipImeWindowsDuringTraversal(DisplayContent dc) {
4692             // We skip IME windows so they're processed just above their target, except
4693             // in split-screen mode where we process the IME containers above the docked divider.
4694             // Note that this method check should align with {@link
4695             // WindowState#applyImeWindowsIfNeeded} in case of any state mismatch.
4696             return dc.mImeLayeringTarget != null
4697                     && (!dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
4698                              || dc.mImeLayeringTarget.getTask() == null);
4699         }
4700 
4701         /** Like {@link #forAllWindows}, but ignores {@link #skipImeWindowsDuringTraversal} */
forAllWindowForce(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4702         boolean forAllWindowForce(ToBooleanFunction<WindowState> callback,
4703                 boolean traverseTopToBottom) {
4704             return super.forAllWindows(callback, traverseTopToBottom);
4705         }
4706 
4707         @Override
assignLayer(Transaction t, int layer)4708         void assignLayer(Transaction t, int layer) {
4709             if (!mNeedsLayer) {
4710                 return;
4711             }
4712             super.assignLayer(t, layer);
4713             mNeedsLayer = false;
4714         }
4715 
4716         @Override
assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer, boolean forceUpdate)4717         void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer,
4718                 boolean forceUpdate) {
4719             if (!mNeedsLayer) {
4720                 return;
4721             }
4722             super.assignRelativeLayer(t, relativeTo, layer, forceUpdate);
4723             mNeedsLayer = false;
4724         }
4725     }
4726 
4727     @Override
getSession()4728     SurfaceSession getSession() {
4729         return mSession;
4730     }
4731 
4732     @Override
makeChildSurface(WindowContainer child)4733     SurfaceControl.Builder makeChildSurface(WindowContainer child) {
4734         SurfaceSession s = child != null ? child.getSession() : getSession();
4735         final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer();
4736         if (child == null) {
4737             return b;
4738         }
4739 
4740         return b.setName(child.getName())
4741                 .setParent(mSurfaceControl);
4742     }
4743 
4744     /**
4745      * The makeSurface variants are for use by the window-container
4746      * hierarchy. makeOverlay here is a function for various non windowing
4747      * overlays like the ScreenRotation screenshot, the Strict Mode Flash
4748      * and other potpourii.
4749      */
makeOverlay()4750     SurfaceControl.Builder makeOverlay() {
4751         return mWmService.makeSurfaceBuilder(mSession).setParent(getOverlayLayer());
4752     }
4753 
4754     @Override
makeAnimationLeash()4755     public SurfaceControl.Builder makeAnimationLeash() {
4756         return mWmService.makeSurfaceBuilder(mSession).setParent(mSurfaceControl)
4757                 .setContainerLayer();
4758     }
4759 
4760     /**
4761      * Reparents the given surface to {@link #mOverlayLayer} SurfaceControl.
4762      */
reparentToOverlay(Transaction transaction, SurfaceControl surface)4763     void reparentToOverlay(Transaction transaction, SurfaceControl surface) {
4764         transaction.reparent(surface, getOverlayLayer());
4765     }
4766 
applyMagnificationSpec(MagnificationSpec spec)4767     void applyMagnificationSpec(MagnificationSpec spec) {
4768         if (spec.scale != 1.0) {
4769             mMagnificationSpec = spec;
4770         } else {
4771             mMagnificationSpec = null;
4772         }
4773         // Re-parent IME's SurfaceControl when MagnificationSpec changed.
4774         updateImeParent();
4775 
4776         if (spec.scale != 1.0) {
4777             applyMagnificationSpec(getPendingTransaction(), spec);
4778         } else {
4779             clearMagnificationSpec(getPendingTransaction());
4780         }
4781         getPendingTransaction().apply();
4782     }
4783 
reapplyMagnificationSpec()4784     void reapplyMagnificationSpec() {
4785         if (mMagnificationSpec != null) {
4786             applyMagnificationSpec(getPendingTransaction(), mMagnificationSpec);
4787         }
4788     }
4789 
4790     @Override
onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent)4791     void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
4792         // Since we are the top of the SurfaceControl hierarchy here
4793         // we create the root surfaces explicitly rather than chaining
4794         // up as the default implementation in onParentChanged does. So we
4795         // explicitly do NOT call super here.
4796 
4797         if (!isReady()) {
4798             // TODO(b/62541591): evaluate whether this is the best spot to declare the
4799             // {@link DisplayContent} ready for use.
4800             mDisplayReady = true;
4801 
4802             mWmService.mAnimator.addDisplayLocked(mDisplayId);
4803 
4804             if (mWmService.mDisplayManagerInternal != null) {
4805                 mWmService.mDisplayManagerInternal
4806                         .setDisplayInfoOverrideFromWindowManager(mDisplayId, getDisplayInfo());
4807                 configureDisplayPolicy();
4808             }
4809 
4810             reconfigureDisplayLocked();
4811             onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
4812             mWmService.mDisplayNotificationController.dispatchDisplayAdded(this);
4813         }
4814     }
4815 
4816     @Override
assignChildLayers(SurfaceControl.Transaction t)4817     void assignChildLayers(SurfaceControl.Transaction t) {
4818         assignRelativeLayerForIme(t, false /* forceUpdate */);
4819         super.assignChildLayers(t);
4820     }
4821 
assignRelativeLayerForIme(SurfaceControl.Transaction t, boolean forceUpdate)4822     private void assignRelativeLayerForIme(SurfaceControl.Transaction t, boolean forceUpdate) {
4823         mImeWindowsContainer.setNeedsLayer();
4824         final WindowState imeTarget = mImeLayeringTarget;
4825         // In the case where we have an IME target that is not in split-screen mode IME
4826         // assignment is easy. We just need the IME to go directly above the target. This way
4827         // children of the target will naturally go above the IME and everyone is happy.
4828         //
4829         // In the case of split-screen windowing mode, we need to elevate the IME above the
4830         // docked divider while keeping the app itself below the docked divider, so instead
4831         // we will put the docked divider below the IME. @see #assignRelativeLayerForImeTargetChild
4832         //
4833         // In the case the IME target is animating, the animation Z order may be different
4834         // than the WindowContainer Z order, so it's difficult to be sure we have the correct
4835         // IME target. In this case we just layer the IME over its parent surface.
4836         //
4837         // In the case where we have no IME target we let its window parent to place it.
4838         //
4839         // Keep IME window in surface parent as long as app's starting window
4840         // exists so it get's layered above the starting window.
4841         if (imeTarget != null && !(imeTarget.mActivityRecord != null
4842                 && imeTarget.mActivityRecord.hasStartingWindow()) && (
4843                 !(imeTarget.inMultiWindowMode()
4844                         || imeTarget.mToken.isAppTransitioning()) && (
4845                         imeTarget.getSurfaceControl() != null))) {
4846             mImeWindowsContainer.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
4847                     // TODO: We need to use an extra level on the app surface to ensure
4848                     // this is always above SurfaceView but always below attached window.
4849                     1, forceUpdate);
4850         } else if (mInputMethodSurfaceParent != null) {
4851             // The IME surface parent may not be its window parent's surface
4852             // (@see #computeImeParent), so set relative layer here instead of letting the window
4853             // parent to assign layer.
4854             mImeWindowsContainer.assignRelativeLayer(t, mInputMethodSurfaceParent, 1, forceUpdate);
4855         }
4856     }
4857 
4858     /**
4859      * Here we satisfy an unfortunate special case of the IME in split-screen mode. Imagine
4860      * that the IME target is one of the docked applications. We'd like the docked divider to be
4861      * above both of the applications, and we'd like the IME to be above the docked divider.
4862      * However we need child windows of the applications to be above the IME (Text drag handles).
4863      * This is a non-strictly hierarcical layering and we need to break out of the Z ordering
4864      * somehow. We do this by relatively ordering children of the target to the IME in cooperation
4865      * with {@link WindowState#assignLayer}
4866      */
assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child)4867     void assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child) {
4868         child.assignRelativeLayer(t, mImeWindowsContainer.getSurfaceControl(), 1);
4869     }
4870 
4871     @Override
prepareSurfaces()4872     void prepareSurfaces() {
4873         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareSurfaces");
4874         try {
4875             final Transaction transaction = getPendingTransaction();
4876             super.prepareSurfaces();
4877 
4878             // TODO: Once we totally eliminate global transaction we will pass transaction in here
4879             //       rather than merging to global.
4880             SurfaceControl.mergeToGlobalTransaction(transaction);
4881         } finally {
4882             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4883         }
4884     }
4885 
assignRootTaskOrdering()4886     void assignRootTaskOrdering() {
4887         forAllTaskDisplayAreas(taskDisplayArea -> {
4888             taskDisplayArea.assignRootTaskOrdering(getPendingTransaction());
4889         });
4890     }
4891 
4892     /**
4893      * Increment the deferral count to determine whether to update the IME target.
4894      */
deferUpdateImeTarget()4895     void deferUpdateImeTarget() {
4896         mDeferUpdateImeTargetCount++;
4897     }
4898 
4899     /**
4900      * Decrement the deferral count to determine whether to update the IME target. If the count
4901      * reaches 0, a new ime target will get computed.
4902      */
continueUpdateImeTarget()4903     void continueUpdateImeTarget() {
4904         if (mDeferUpdateImeTargetCount == 0) {
4905             return;
4906         }
4907 
4908         mDeferUpdateImeTargetCount--;
4909         if (mDeferUpdateImeTargetCount == 0) {
4910             computeImeTarget(true /* updateImeTarget */);
4911         }
4912     }
4913 
4914     /**
4915      * @return Whether a new IME target should be computed.
4916      */
canUpdateImeTarget()4917     private boolean canUpdateImeTarget() {
4918         return mDeferUpdateImeTargetCount == 0;
4919     }
4920 
getInputMonitor()4921     InputMonitor getInputMonitor() {
4922         return mInputMonitor;
4923     }
4924 
4925     /**
4926      * @return Cached value whether we told display manager that we have content.
4927      */
getLastHasContent()4928     boolean getLastHasContent() {
4929         return mLastHasContent;
4930     }
4931 
registerPointerEventListener(@onNull PointerEventListener listener)4932     void registerPointerEventListener(@NonNull PointerEventListener listener) {
4933         mPointerEventDispatcher.registerInputEventListener(listener);
4934     }
4935 
unregisterPointerEventListener(@onNull PointerEventListener listener)4936     void unregisterPointerEventListener(@NonNull PointerEventListener listener) {
4937         mPointerEventDispatcher.unregisterInputEventListener(listener);
4938     }
4939 
4940     /**
4941      * Transfer app transition from other display to this display.
4942      *
4943      * @param from Display from where the app transition is transferred.
4944      *
4945      * TODO(new-app-transition): Remove this once the shell handles app transition.
4946      */
transferAppTransitionFrom(DisplayContent from)4947     void transferAppTransitionFrom(DisplayContent from) {
4948         final boolean prepared = mAppTransition.transferFrom(from.mAppTransition);
4949         if (prepared && okToAnimate()) {
4950             mSkipAppTransitionAnimation = false;
4951         }
4952     }
4953 
prepareAppTransition(@indowManager.TransitionType int transit)4954     void prepareAppTransition(@WindowManager.TransitionType int transit) {
4955         prepareAppTransition(transit, 0 /* flags */);
4956     }
4957 
prepareAppTransition(@indowManager.TransitionType int transit, @WindowManager.TransitionFlags int flags)4958     void prepareAppTransition(@WindowManager.TransitionType int transit,
4959             @WindowManager.TransitionFlags int flags) {
4960         final boolean prepared = mAppTransition.prepareAppTransition(transit, flags);
4961         if (prepared && okToAnimate()) {
4962             mSkipAppTransitionAnimation = false;
4963         }
4964     }
4965 
4966     /**
4967      * Helper that both requests a transition (using the new transition system) and prepares
4968      * the legacy transition system. Use this when both systems have the same start-point.
4969      *
4970      * @see TransitionController#requestTransitionIfNeeded(int, int, WindowContainer)
4971      * @see AppTransition#prepareAppTransition
4972      */
requestTransitionAndLegacyPrepare(@indowManager.TransitionType int transit, @WindowManager.TransitionFlags int flags)4973     void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit,
4974             @WindowManager.TransitionFlags int flags) {
4975         prepareAppTransition(transit, flags);
4976         mAtmService.getTransitionController().requestTransitionIfNeeded(transit, flags,
4977                 null /* trigger */);
4978     }
4979 
4980     /** @see #requestTransitionAndLegacyPrepare(int, int) */
requestTransitionAndLegacyPrepare(@indowManager.TransitionType int transit, @Nullable WindowContainer trigger)4981     void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit,
4982             @Nullable WindowContainer trigger) {
4983         prepareAppTransition(transit);
4984         mAtmService.getTransitionController().requestTransitionIfNeeded(transit, 0 /* flags */,
4985                 trigger);
4986     }
4987 
executeAppTransition()4988     void executeAppTransition() {
4989         mAtmService.getTransitionController().setReady();
4990         if (mAppTransition.isTransitionSet()) {
4991             ProtoLog.w(WM_DEBUG_APP_TRANSITIONS,
4992                     "Execute app transition: %s, displayId: %d Callers=%s",
4993                     mAppTransition, mDisplayId, Debug.getCallers(5));
4994             mAppTransition.setReady();
4995             mWmService.mWindowPlacerLocked.requestTraversal();
4996         }
4997     }
4998 
4999     /**
5000      * Update pendingLayoutChanges after app transition has finished.
5001      */
handleAnimatingStoppedAndTransition()5002     void handleAnimatingStoppedAndTransition() {
5003         int changes = 0;
5004 
5005         mAppTransition.setIdle();
5006 
5007         for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) {
5008             final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i);
5009             mAppTransition.notifyAppTransitionFinishedLocked(token);
5010         }
5011         mNoAnimationNotifyOnTransitionFinished.clear();
5012 
5013         mWallpaperController.hideDeferredWallpapersIfNeededLegacy();
5014 
5015         onAppTransitionDone();
5016 
5017         changes |= FINISH_LAYOUT_REDO_LAYOUT;
5018         if (DEBUG_WALLPAPER_LIGHT) {
5019             Slog.v(TAG_WM, "Wallpaper layer changed: assigning layers + relayout");
5020         }
5021         computeImeTarget(true /* updateImeTarget */);
5022         mWallpaperMayChange = true;
5023         // Since the window list has been rebuilt, focus might have to be recomputed since the
5024         // actual order of windows might have changed again.
5025         mWmService.mFocusMayChange = true;
5026 
5027         pendingLayoutChanges |= changes;
5028     }
5029 
5030     /** Check if pending app transition is for activity / task launch. */
isNextTransitionForward()5031     boolean isNextTransitionForward() {
5032         return mAppTransition.containsTransitRequest(TRANSIT_OPEN)
5033                 || mAppTransition.containsTransitRequest(TRANSIT_TO_FRONT);
5034     }
5035 
5036     /**
5037      * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
5038      */
supportsSystemDecorations()5039     boolean supportsSystemDecorations() {
5040         return (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this)
5041                 || (mDisplay.getFlags() & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0
5042                 || forceDesktopMode())
5043                 // VR virtual display will be used to run and render 2D app within a VR experience.
5044                 && mDisplayId != mWmService.mVr2dDisplayId
5045                 // Do not show system decorations on untrusted virtual display.
5046                 && isTrusted();
5047     }
5048 
5049     /**
5050      * Get the window which owns the surface that this DisplayContent is re-parented to.
5051      *
5052      * @return the parent window.
5053      */
getParentWindow()5054     WindowState getParentWindow() {
5055         return mParentWindow;
5056     }
5057 
5058     /**
5059      * Update the location of this display in the parent window. This enables windows in this
5060      * display to compute the global transformation matrix.
5061      *
5062      * @param win The parent window of this display.
5063      * @param x The x coordinate in the parent window.
5064      * @param y The y coordinate in the parent window.
5065      */
updateLocation(WindowState win, int x, int y)5066     void updateLocation(WindowState win, int x, int y) {
5067         if (mParentWindow != win) {
5068             throw new IllegalArgumentException(
5069                     "The given window is not the parent window of this display.");
5070         }
5071         if (!mLocationInParentWindow.equals(x, y)) {
5072             mLocationInParentWindow.set(x, y);
5073             if (mWmService.mAccessibilityController != null) {
5074                 mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(mDisplayId);
5075             }
5076             notifyLocationInParentDisplayChanged();
5077         }
5078     }
5079 
getLocationInParentWindow()5080     Point getLocationInParentWindow() {
5081         return mLocationInParentWindow;
5082     }
5083 
getLocationInParentDisplay()5084     Point getLocationInParentDisplay() {
5085         final Point location = new Point();
5086         if (mParentWindow != null) {
5087             // LocationInParentWindow indicates the offset to (0,0) of window, but what we need is
5088             // the offset to (0,0) of display.
5089             DisplayContent dc = this;
5090             do {
5091                 final WindowState displayParent = dc.getParentWindow();
5092                 location.x += displayParent.getFrame().left
5093                         + (dc.getLocationInParentWindow().x * displayParent.mGlobalScale + 0.5f);
5094                 location.y += displayParent.getFrame().top
5095                         + (dc.getLocationInParentWindow().y * displayParent.mGlobalScale + 0.5f);
5096                 dc = displayParent.getDisplayContent();
5097             } while (dc != null && dc.getParentWindow() != null);
5098         }
5099         return location;
5100     }
5101 
notifyLocationInParentDisplayChanged()5102     void notifyLocationInParentDisplayChanged() {
5103         forAllWindows(w -> {
5104             w.updateLocationInParentDisplayIfNeeded();
5105         }, false /* traverseTopToBottom */);
5106     }
5107 
getWindowingLayer()5108     SurfaceControl getWindowingLayer() {
5109         return mWindowingLayer;
5110     }
5111 
getImeContainer()5112     DisplayArea.Tokens getImeContainer() {
5113         return mImeWindowsContainer;
5114     }
5115 
getOverlayLayer()5116     SurfaceControl getOverlayLayer() {
5117         return mOverlayLayer;
5118     }
5119 
5120     /**
5121      * Updates the display's system gesture exclusion.
5122      *
5123      * @return true, if the exclusion changed.
5124      */
updateSystemGestureExclusion()5125     boolean updateSystemGestureExclusion() {
5126         if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 0) {
5127             // No one's interested anyways.
5128             return false;
5129         }
5130 
5131         final Region systemGestureExclusion = Region.obtain();
5132         mSystemGestureExclusionWasRestricted = calculateSystemGestureExclusion(
5133                 systemGestureExclusion, mSystemGestureExclusionUnrestricted);
5134         try {
5135             if (mSystemGestureExclusion.equals(systemGestureExclusion)) {
5136                 return false;
5137             }
5138             mSystemGestureExclusion.set(systemGestureExclusion);
5139             final Region unrestrictedOrNull = mSystemGestureExclusionWasRestricted
5140                     ? mSystemGestureExclusionUnrestricted : null;
5141             for (int i = mSystemGestureExclusionListeners.beginBroadcast() - 1; i >= 0; --i) {
5142                 try {
5143                     mSystemGestureExclusionListeners.getBroadcastItem(i)
5144                             .onSystemGestureExclusionChanged(mDisplayId, systemGestureExclusion,
5145                                     unrestrictedOrNull);
5146                 } catch (RemoteException e) {
5147                     Slog.e(TAG, "Failed to notify SystemGestureExclusionListener", e);
5148                 }
5149             }
5150             mSystemGestureExclusionListeners.finishBroadcast();
5151             return true;
5152         } finally {
5153             systemGestureExclusion.recycle();
5154         }
5155     }
5156 
5157     /**
5158      * Calculates the system gesture exclusion.
5159      *
5160      * @param outExclusion will be set to the gesture exclusion region
5161      * @param outExclusionUnrestricted will be set to the gesture exclusion region without
5162      *                                 any restrictions applied.
5163      * @return whether any restrictions were applied, i.e. outExclusion and outExclusionUnrestricted
5164      *         differ.
5165      */
5166     @VisibleForTesting
calculateSystemGestureExclusion(Region outExclusion, @Nullable Region outExclusionUnrestricted)5167     boolean calculateSystemGestureExclusion(Region outExclusion, @Nullable
5168             Region outExclusionUnrestricted) {
5169         outExclusion.setEmpty();
5170         if (outExclusionUnrestricted != null) {
5171             outExclusionUnrestricted.setEmpty();
5172         }
5173         final Region unhandled = Region.obtain();
5174         unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight);
5175 
5176         final Rect leftEdge = mInsetsStateController.getSourceProvider(ITYPE_LEFT_GESTURES)
5177                 .getSource().getFrame();
5178         final Rect rightEdge = mInsetsStateController.getSourceProvider(ITYPE_RIGHT_GESTURES)
5179                 .getSource().getFrame();
5180 
5181         final Region touchableRegion = Region.obtain();
5182         final Region local = Region.obtain();
5183         final int[] remainingLeftRight =
5184                 {mSystemGestureExclusionLimit, mSystemGestureExclusionLimit};
5185 
5186         // Traverse all windows top down to assemble the gesture exclusion rects.
5187         // For each window, we only take the rects that fall within its touchable region.
5188         forAllWindows(w -> {
5189             if (!w.canReceiveTouchInput() || !w.isVisible()
5190                     || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
5191                     || unhandled.isEmpty()) {
5192                 return;
5193             }
5194 
5195             // Get the touchable region of the window, and intersect with where the screen is still
5196             // touchable, i.e. touchable regions on top are not covering it yet.
5197             w.getEffectiveTouchableRegion(touchableRegion);
5198             touchableRegion.op(unhandled, Op.INTERSECT);
5199 
5200             if (w.isImplicitlyExcludingAllSystemGestures()) {
5201                 local.set(touchableRegion);
5202             } else {
5203                 rectListToRegion(w.getSystemGestureExclusion(), local);
5204 
5205                 // Transform to display coordinates
5206                 local.scale(w.mGlobalScale);
5207                 final Rect frame = w.getWindowFrames().mFrame;
5208                 local.translate(frame.left, frame.top);
5209 
5210                 // A window can only exclude system gestures where it is actually touchable
5211                 local.op(touchableRegion, Op.INTERSECT);
5212             }
5213 
5214             // Apply restriction if necessary.
5215             if (needsGestureExclusionRestrictions(w, false /* ignoreRequest */)) {
5216 
5217                 // Processes the region along the left edge.
5218                 remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
5219                         remainingLeftRight[0], w, EXCLUSION_LEFT);
5220 
5221                 // Processes the region along the right edge.
5222                 remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
5223                         remainingLeftRight[1], w, EXCLUSION_RIGHT);
5224 
5225                 // Adds the middle (unrestricted area)
5226                 final Region middle = Region.obtain(local);
5227                 middle.op(leftEdge, Op.DIFFERENCE);
5228                 middle.op(rightEdge, Op.DIFFERENCE);
5229                 outExclusion.op(middle, Op.UNION);
5230                 middle.recycle();
5231             } else {
5232                 boolean loggable = needsGestureExclusionRestrictions(w, true /* ignoreRequest */);
5233                 if (loggable) {
5234                     addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
5235                             Integer.MAX_VALUE, w, EXCLUSION_LEFT);
5236                     addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
5237                             Integer.MAX_VALUE, w, EXCLUSION_RIGHT);
5238                 }
5239                 outExclusion.op(local, Op.UNION);
5240             }
5241             if (outExclusionUnrestricted != null) {
5242                 outExclusionUnrestricted.op(local, Op.UNION);
5243             }
5244             unhandled.op(touchableRegion, Op.DIFFERENCE);
5245         }, true /* topToBottom */);
5246         local.recycle();
5247         touchableRegion.recycle();
5248         unhandled.recycle();
5249         return remainingLeftRight[0] < mSystemGestureExclusionLimit
5250                 || remainingLeftRight[1] < mSystemGestureExclusionLimit;
5251     }
5252 
5253     /**
5254      * Returns whether gesture exclusion area should be restricted from the window depending on the
5255      * window/activity types and the requested navigation bar visibility and the behavior.
5256      *
5257      * @param win The target window.
5258      * @param ignoreRequest If this is {@code true}, only the window/activity types are considered.
5259      * @return {@code true} if the gesture exclusion restrictions are needed.
5260      */
needsGestureExclusionRestrictions(WindowState win, boolean ignoreRequest)5261     private static boolean needsGestureExclusionRestrictions(WindowState win,
5262             boolean ignoreRequest) {
5263         final int type = win.mAttrs.type;
5264         final boolean stickyHideNav =
5265                 !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
5266                         && win.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
5267         return (!stickyHideNav || ignoreRequest) && type != TYPE_INPUT_METHOD
5268                 && type != TYPE_NOTIFICATION_SHADE && win.getActivityType() != ACTIVITY_TYPE_HOME;
5269     }
5270 
5271     /**
5272      * @return Whether gesture exclusion area should be logged for the given window
5273      */
logsGestureExclusionRestrictions(WindowState win)5274     static boolean logsGestureExclusionRestrictions(WindowState win) {
5275         if (win.mWmService.mConstants.mSystemGestureExclusionLogDebounceTimeoutMillis <= 0) {
5276             return false;
5277         }
5278         final WindowManager.LayoutParams attrs = win.getAttrs();
5279         final int type = attrs.type;
5280         return type != TYPE_WALLPAPER
5281                 && type != TYPE_APPLICATION_STARTING
5282                 && type != TYPE_NAVIGATION_BAR
5283                 && (attrs.flags & FLAG_NOT_TOUCHABLE) == 0
5284                 && needsGestureExclusionRestrictions(win, true /* ignoreRequest */)
5285                 && win.getDisplayContent().mDisplayPolicy.hasSideGestures();
5286     }
5287 
5288     /**
5289      * Adds a local gesture exclusion area to the global area while applying a limit per edge.
5290      *
5291      * @param local The gesture exclusion area to add.
5292      * @param global The destination.
5293      * @param edge Only processes the part in that region.
5294      * @param limit How much limit in pixels we have.
5295      * @param win The WindowState that is being processed
5296      * @param side The side that is being processed, either {@link WindowState#EXCLUSION_LEFT} or
5297      *             {@link WindowState#EXCLUSION_RIGHT}
5298      * @return How much of the limit is remaining.
5299      */
addToGlobalAndConsumeLimit(Region local, Region global, Rect edge, int limit, WindowState win, int side)5300     private static int addToGlobalAndConsumeLimit(Region local, Region global, Rect edge,
5301             int limit, WindowState win, int side) {
5302         final Region r = Region.obtain(local);
5303         r.op(edge, Op.INTERSECT);
5304 
5305         final int[] remaining = {limit};
5306         final int[] requestedExclusion = {0};
5307         forEachRectReverse(r, rect -> {
5308             if (remaining[0] <= 0) {
5309                 return;
5310             }
5311             final int height = rect.height();
5312             requestedExclusion[0] += height;
5313             if (height > remaining[0]) {
5314                 rect.top = rect.bottom - remaining[0];
5315             }
5316             remaining[0] -= height;
5317             global.op(rect, Op.UNION);
5318         });
5319 
5320         final int grantedExclusion = limit - remaining[0];
5321         win.setLastExclusionHeights(side, requestedExclusion[0], grantedExclusion);
5322 
5323         r.recycle();
5324         return remaining[0];
5325     }
5326 
registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener)5327     void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
5328         mSystemGestureExclusionListeners.register(listener);
5329         final boolean changed;
5330         if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 1) {
5331             changed = updateSystemGestureExclusion();
5332         } else {
5333             changed = false;
5334         }
5335 
5336         if (!changed) {
5337             final Region unrestrictedOrNull = mSystemGestureExclusionWasRestricted
5338                     ? mSystemGestureExclusionUnrestricted : null;
5339             // If updateSystemGestureExclusion changed the exclusion, it will already have
5340             // notified the listener. Otherwise, we'll do it here.
5341             try {
5342                 listener.onSystemGestureExclusionChanged(mDisplayId, mSystemGestureExclusion,
5343                         unrestrictedOrNull);
5344             } catch (RemoteException e) {
5345                 Slog.e(TAG, "Failed to notify SystemGestureExclusionListener during register", e);
5346             }
5347         }
5348     }
5349 
unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener)5350     void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
5351         mSystemGestureExclusionListeners.unregister(listener);
5352     }
5353 
5354     /**
5355      * Create a portal window handle for input. This window transports any touch to the display
5356      * indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window.
5357      *
5358      * @param name The name of the portal window handle.
5359      * @return the new portal window handle.
5360      */
createPortalWindowHandle(String name)5361     private InputWindowHandle createPortalWindowHandle(String name) {
5362         // Let surface flinger to set the display ID of this input window handle because we don't
5363         // know which display the parent surface control is on.
5364         final InputWindowHandle portalWindowHandle = new InputWindowHandle(
5365                 null /* inputApplicationHandle */, INVALID_DISPLAY);
5366         portalWindowHandle.name = name;
5367         portalWindowHandle.token = new Binder();
5368         portalWindowHandle.layoutParamsFlags =
5369                 FLAG_SPLIT_TOUCH | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL;
5370         getBounds(mTmpBounds);
5371         portalWindowHandle.touchableRegion.set(mTmpBounds);
5372         portalWindowHandle.scaleFactor = 1f;
5373         portalWindowHandle.ownerPid = Process.myPid();
5374         portalWindowHandle.ownerUid = Process.myUid();
5375         portalWindowHandle.portalToDisplayId = mDisplayId;
5376         return portalWindowHandle;
5377     }
5378 
5379     /**
5380      * @see IWindowManager#setForwardedInsets
5381      */
setForwardedInsets(Insets insets)5382     public void setForwardedInsets(Insets insets) {
5383         if (insets == null) {
5384             insets = Insets.NONE;
5385         }
5386         if (mDisplayPolicy.getForwardedInsets().equals(insets)) {
5387             return;
5388         }
5389         mDisplayPolicy.setForwardedInsets(insets);
5390         setLayoutNeeded();
5391         mWmService.mWindowPlacerLocked.requestTraversal();
5392     }
5393 
getMetricsLogger()5394     protected MetricsLogger getMetricsLogger() {
5395         if (mMetricsLogger == null) {
5396             mMetricsLogger = new MetricsLogger();
5397         }
5398         return mMetricsLogger;
5399     }
5400 
onDisplayChanged()5401     void onDisplayChanged() {
5402         mDisplay.getRealSize(mTmpDisplaySize);
5403         setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
5404         updateDisplayInfo();
5405 
5406         // The window policy is responsible for stopping activities on the default display.
5407         final int displayId = mDisplay.getDisplayId();
5408         if (displayId != DEFAULT_DISPLAY) {
5409             final int displayState = mDisplay.getState();
5410             if (displayState == Display.STATE_OFF) {
5411                 mOffTokenAcquirer.acquire(mDisplayId);
5412             } else if (displayState == Display.STATE_ON) {
5413                 mOffTokenAcquirer.release(mDisplayId);
5414             }
5415         }
5416         mWmService.requestTraversal();
5417     }
5418 
alwaysCreateRootTask(int windowingMode, int activityType)5419     static boolean alwaysCreateRootTask(int windowingMode, int activityType) {
5420         // Always create a root task for fullscreen, freeform, and split-screen-secondary windowing
5421         // modes so that we can manage visual ordering and return types correctly.
5422         return activityType == ACTIVITY_TYPE_STANDARD
5423                 && (windowingMode == WINDOWING_MODE_FULLSCREEN
5424                 || windowingMode == WINDOWING_MODE_FREEFORM
5425                 || windowingMode == WINDOWING_MODE_PINNED
5426                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
5427                 || windowingMode == WINDOWING_MODE_MULTI_WINDOW);
5428     }
5429 
5430     @Nullable
getFocusedRootTask()5431     Task getFocusedRootTask() {
5432         return getItemFromTaskDisplayAreas(TaskDisplayArea::getFocusedRootTask);
5433     }
5434 
5435     /**
5436      * Removes root tasks in the input windowing modes from the system if they are of activity type
5437      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
5438      */
removeRootTasksInWindowingModes(int... windowingModes)5439     void removeRootTasksInWindowingModes(int... windowingModes) {
5440         if (windowingModes == null || windowingModes.length == 0) {
5441             return;
5442         }
5443 
5444         // Collect the root tasks that are necessary to be removed instead of performing the removal
5445         // by looping the children, so that we don't miss any root tasks after the children size
5446         // changed or reordered.
5447         final ArrayList<Task> rootTasks = new ArrayList<>();
5448         forAllRootTasks(rootTask -> {
5449             for (int windowingMode : windowingModes) {
5450                 if (rootTask.mCreatedByOrganizer
5451                         || rootTask.getWindowingMode() != windowingMode
5452                         || !rootTask.isActivityTypeStandardOrUndefined()) {
5453                     continue;
5454                 }
5455                 rootTasks.add(rootTask);
5456             }
5457         });
5458         for (int i = rootTasks.size() - 1; i >= 0; --i) {
5459             mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i));
5460         }
5461     }
5462 
removeRootTasksWithActivityTypes(int... activityTypes)5463     void removeRootTasksWithActivityTypes(int... activityTypes) {
5464         if (activityTypes == null || activityTypes.length == 0) {
5465             return;
5466         }
5467 
5468         // Collect the root tasks that are necessary to be removed instead of performing the removal
5469         // by looping the children, so that we don't miss any root tasks after the children size
5470         // changed or reordered.
5471         final ArrayList<Task> rootTasks = new ArrayList<>();
5472         forAllRootTasks(rootTask -> {
5473             for (int activityType : activityTypes) {
5474                 // Collect the root tasks that are currently being organized.
5475                 if (rootTask.mCreatedByOrganizer) {
5476                     for (int k = rootTask.getChildCount() - 1; k >= 0; --k) {
5477                         final Task task = (Task) rootTask.getChildAt(k);
5478                         if (task.getActivityType() == activityType) {
5479                             rootTasks.add(task);
5480                         }
5481                     }
5482                 } else if (rootTask.getActivityType() == activityType) {
5483                     rootTasks.add(rootTask);
5484                 }
5485             }
5486         });
5487         for (int i = rootTasks.size() - 1; i >= 0; --i) {
5488             mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i));
5489         }
5490     }
5491 
topRunningActivity()5492     ActivityRecord topRunningActivity() {
5493         return topRunningActivity(false /* considerKeyguardState */);
5494     }
5495 
5496     /**
5497      * Returns the top running activity in the focused root task. In the case the focused root
5498      * task has no such activity, the next focusable root task on this display is returned.
5499      *
5500      * @param considerKeyguardState Indicates whether the locked state should be considered. if
5501      *                              {@code true} and the keyguard is locked, only activities that
5502      *                              can be shown on top of the keyguard will be considered.
5503      * @return The top running activity. {@code null} if none is available.
5504      */
5505     @Nullable
topRunningActivity(boolean considerKeyguardState)5506     ActivityRecord topRunningActivity(boolean considerKeyguardState) {
5507         return getItemFromTaskDisplayAreas(taskDisplayArea ->
5508                 taskDisplayArea.topRunningActivity(considerKeyguardState));
5509     }
5510 
updateDisplayOverrideConfigurationLocked()5511     boolean updateDisplayOverrideConfigurationLocked() {
5512         // Preemptively cancel the running recents animation -- SysUI can't currently handle this
5513         // case properly since the signals it receives all happen post-change
5514         final RecentsAnimationController recentsAnimationController =
5515                 mWmService.getRecentsAnimationController();
5516         if (recentsAnimationController != null) {
5517             recentsAnimationController.cancelAnimationForDisplayChange();
5518         }
5519 
5520         Configuration values = new Configuration();
5521         computeScreenConfiguration(values);
5522 
5523         mAtmService.mH.sendMessage(PooledLambda.obtainMessage(
5524                 ActivityManagerInternal::updateOomLevelsForDisplay, mAtmService.mAmInternal,
5525                 mDisplayId));
5526 
5527         Settings.System.clearConfiguration(values);
5528         updateDisplayOverrideConfigurationLocked(values, null /* starting */,
5529                 false /* deferResume */, mAtmService.mTmpUpdateConfigurationResult);
5530         return mAtmService.mTmpUpdateConfigurationResult.changes != 0;
5531     }
5532 
5533     /**
5534      * Updates override configuration specific for the selected display. If no config is provided,
5535      * new one will be computed in WM based on current display info.
5536      */
updateDisplayOverrideConfigurationLocked(Configuration values, ActivityRecord starting, boolean deferResume, ActivityTaskManagerService.UpdateConfigurationResult result)5537     boolean updateDisplayOverrideConfigurationLocked(Configuration values,
5538             ActivityRecord starting, boolean deferResume,
5539             ActivityTaskManagerService.UpdateConfigurationResult result) {
5540 
5541         int changes = 0;
5542         boolean kept = true;
5543 
5544         mAtmService.deferWindowLayout();
5545         try {
5546             if (values != null) {
5547                 if (mDisplayId == DEFAULT_DISPLAY) {
5548                     // Override configuration of the default display duplicates global config, so
5549                     // we're calling global config update instead for default display. It will also
5550                     // apply the correct override config.
5551                     changes = mAtmService.updateGlobalConfigurationLocked(values,
5552                             false /* initLocale */, false /* persistent */,
5553                             UserHandle.USER_NULL /* userId */);
5554                 } else {
5555                     changes = performDisplayOverrideConfigUpdate(values);
5556                 }
5557             }
5558 
5559             if (!deferResume) {
5560                 kept = mAtmService.ensureConfigAndVisibilityAfterUpdate(starting, changes);
5561             }
5562         } finally {
5563             mAtmService.continueWindowLayout();
5564         }
5565 
5566         if (result != null) {
5567             result.changes = changes;
5568             result.activityRelaunched = !kept;
5569         }
5570         return kept;
5571     }
5572 
performDisplayOverrideConfigUpdate(Configuration values)5573     int performDisplayOverrideConfigUpdate(Configuration values) {
5574         mTempConfig.setTo(getRequestedOverrideConfiguration());
5575         final int changes = mTempConfig.updateFrom(values);
5576         if (changes != 0) {
5577             Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
5578                     + mTempConfig + " for displayId=" + mDisplayId);
5579             onRequestedOverrideConfigurationChanged(mTempConfig);
5580 
5581             final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
5582             if (isDensityChange && mDisplayId == DEFAULT_DISPLAY) {
5583                 mAtmService.mAppWarnings.onDensityChanged();
5584 
5585                 // Post message to start process to avoid possible deadlock of calling into AMS with
5586                 // the ATMS lock held.
5587                 final Message msg = PooledLambda.obtainMessage(
5588                         ActivityManagerInternal::killAllBackgroundProcessesExcept,
5589                         mAtmService.mAmInternal, N,
5590                         ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
5591                 mAtmService.mH.sendMessage(msg);
5592             }
5593             mWmService.mDisplayNotificationController.dispatchDisplayChanged(
5594                     this, getConfiguration());
5595         }
5596         return changes;
5597     }
5598 
5599     @Override
onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration)5600     public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
5601         final Configuration currOverrideConfig = getRequestedOverrideConfiguration();
5602         final int currRotation = currOverrideConfig.windowConfiguration.getRotation();
5603         final int overrideRotation = overrideConfiguration.windowConfiguration.getRotation();
5604         if (currRotation != ROTATION_UNDEFINED && currRotation != overrideRotation) {
5605             applyRotationAndFinishFixedRotation(currRotation, overrideRotation);
5606         }
5607         mCurrentOverrideConfigurationChanges = currOverrideConfig.diff(overrideConfiguration);
5608         super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
5609         mCurrentOverrideConfigurationChanges = 0;
5610         mWmService.setNewDisplayOverrideConfiguration(currOverrideConfig, this);
5611         mAtmService.addWindowLayoutReasons(
5612                 ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED);
5613     }
5614 
5615     /**
5616      * If the launching rotated activity ({@link #mFixedRotationLaunchingApp}) is null, it simply
5617      * applies the rotation to display. Otherwise because the activity has shown as rotated, the
5618      * fixed rotation transform also needs to be cleared to make sure the rotated activity fits
5619      * the display naturally.
5620      */
applyRotationAndFinishFixedRotation(int oldRotation, int newRotation)5621     private void applyRotationAndFinishFixedRotation(int oldRotation, int newRotation) {
5622         final WindowToken rotatedLaunchingApp = mFixedRotationLaunchingApp;
5623         if (rotatedLaunchingApp == null) {
5624             applyRotation(oldRotation, newRotation);
5625             return;
5626         }
5627 
5628         rotatedLaunchingApp.finishFixedRotationTransform(
5629                 () -> applyRotation(oldRotation, newRotation));
5630         setFixedRotationLaunchingAppUnchecked(null);
5631     }
5632 
5633     /** Checks whether the given activity is in size compatibility mode and notifies the change. */
handleActivitySizeCompatModeIfNeeded(ActivityRecord r)5634     void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) {
5635         final Task organizedTask = r.getOrganizedTask();
5636         if (organizedTask == null) {
5637             mActiveSizeCompatActivities.remove(r);
5638             return;
5639         }
5640 
5641         if (r.isState(RESUMED) && r.inSizeCompatMode()) {
5642             if (mActiveSizeCompatActivities.add(r)) {
5643                 // Trigger task event for new size compat activity.
5644                 organizedTask.onSizeCompatActivityChanged();
5645             }
5646             return;
5647         }
5648 
5649         if (mActiveSizeCompatActivities.remove(r)) {
5650             // Trigger task event for activity no longer in foreground size compat.
5651             organizedTask.onSizeCompatActivityChanged();
5652         }
5653     }
5654 
isUidPresent(int uid)5655     boolean isUidPresent(int uid) {
5656         final PooledPredicate p = PooledLambda.obtainPredicate(
5657                 ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid);
5658         final boolean isUidPresent = mDisplayContent.getActivity(p) != null;
5659         p.recycle();
5660         return isUidPresent;
5661     }
5662 
5663     /**
5664      * @see #mRemoved
5665      */
isRemoved()5666     boolean isRemoved() {
5667         return mRemoved;
5668     }
5669 
5670     /**
5671      * @see #mRemoving
5672      */
isRemoving()5673     boolean isRemoving() {
5674         return mRemoving;
5675     }
5676 
remove()5677     void remove() {
5678         mRemoving = true;
5679         Task lastReparentedRootTask;
5680 
5681         mRootWindowContainer.mTaskSupervisor.beginDeferResume();
5682         try {
5683             lastReparentedRootTask = reduceOnAllTaskDisplayAreas((taskDisplayArea, rootTask) -> {
5684                 final Task lastReparentedRootTaskFromArea = taskDisplayArea.remove();
5685                 if (lastReparentedRootTaskFromArea != null) {
5686                     return lastReparentedRootTaskFromArea;
5687                 }
5688                 return rootTask;
5689             }, null /* initValue */, false /* traverseTopToBottom */);
5690         } finally {
5691             mRootWindowContainer.mTaskSupervisor.endDeferResume();
5692         }
5693         mRemoved = true;
5694 
5695         // Only update focus/visibility for the last one because there may be many root tasks are
5696         // reparented and the intermediate states are unnecessary.
5697         if (lastReparentedRootTask != null) {
5698             lastReparentedRootTask.resumeNextFocusAfterReparent();
5699         }
5700         releaseSelfIfNeeded();
5701         mDisplayPolicy.release();
5702 
5703         if (!mAllSleepTokens.isEmpty()) {
5704             mAllSleepTokens.forEach(token ->
5705                     mRootWindowContainer.mSleepTokens.remove(token.mHashKey));
5706             mAllSleepTokens.clear();
5707             mAtmService.updateSleepIfNeededLocked();
5708         }
5709     }
5710 
releaseSelfIfNeeded()5711     void releaseSelfIfNeeded() {
5712         if (!mRemoved) {
5713             return;
5714         }
5715 
5716         // Check if all task display areas have only the empty home root tasks left.
5717         boolean hasNonEmptyHomeRootTask = forAllRootTasks(rootTask ->
5718                 !rootTask.isActivityTypeHome() || rootTask.hasChild());
5719         if (!hasNonEmptyHomeRootTask && getRootTaskCount() > 0) {
5720             // Release this display if only empty home root task(s) are left. This display will be
5721             // released along with the root task(s) removal.
5722             forAllRootTasks(t -> {t.removeIfPossible("releaseSelfIfNeeded");});
5723         } else if (getTopRootTask() == null) {
5724             removeIfPossible();
5725             mRootWindowContainer.mTaskSupervisor
5726                     .getKeyguardController().onDisplayRemoved(mDisplayId);
5727         }
5728     }
5729 
5730     /** Update and get all UIDs that are present on the display and have access to it. */
getPresentUIDs()5731     IntArray getPresentUIDs() {
5732         mDisplayAccessUIDs.clear();
5733         final PooledConsumer c = PooledLambda.obtainConsumer(DisplayContent::addActivityUid,
5734                 PooledLambda.__(ActivityRecord.class), mDisplayAccessUIDs);
5735         mDisplayContent.forAllActivities(c);
5736         c.recycle();
5737         return mDisplayAccessUIDs;
5738     }
5739 
addActivityUid(ActivityRecord r, IntArray uids)5740     private static void addActivityUid(ActivityRecord r, IntArray uids) {
5741         uids.add(r.getUid());
5742     }
5743 
5744     @VisibleForTesting
shouldDestroyContentOnRemove()5745     boolean shouldDestroyContentOnRemove() {
5746         return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
5747     }
5748 
shouldSleep()5749     boolean shouldSleep() {
5750         return (getRootTaskCount() == 0 || !mAllSleepTokens.isEmpty())
5751                 && (mAtmService.mRunningVoice == null);
5752     }
5753 
5754 
ensureActivitiesVisible(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients)5755     void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
5756             boolean preserveWindows, boolean notifyClients) {
5757         if (mInEnsureActivitiesVisible) {
5758             // Don't do recursive work.
5759             return;
5760         }
5761         mInEnsureActivitiesVisible = true;
5762         mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate();
5763         try {
5764             forAllRootTasks(rootTask -> {
5765                 rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
5766                         notifyClients);
5767             });
5768         } finally {
5769             mAtmService.mTaskSupervisor.endActivityVisibilityUpdate();
5770             mInEnsureActivitiesVisible = false;
5771         }
5772     }
5773 
isSleeping()5774     boolean isSleeping() {
5775         return mSleeping;
5776     }
5777 
setIsSleeping(boolean asleep)5778     void setIsSleeping(boolean asleep) {
5779         mSleeping = asleep;
5780     }
5781 
5782     /**
5783      * Check if the display has {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied.
5784      */
canShowWithInsecureKeyguard()5785     boolean canShowWithInsecureKeyguard() {
5786         final int flags = mDisplay.getFlags();
5787         return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
5788     }
5789 
5790     @VisibleForTesting
removeAllTasks()5791     void removeAllTasks() {
5792         forAllTasks((t) -> { t.getRootTask().removeChild(t, "removeAllTasks"); });
5793     }
5794 
getDisplayUiContext()5795     Context getDisplayUiContext() {
5796         return mDisplayPolicy.getSystemUiContext();
5797     }
5798 
5799     @Override
setIgnoreOrientationRequest(boolean ignoreOrientationRequest)5800     boolean setIgnoreOrientationRequest(boolean ignoreOrientationRequest) {
5801         if (mIgnoreOrientationRequest == ignoreOrientationRequest) return false;
5802         final boolean rotationChanged = super.setIgnoreOrientationRequest(ignoreOrientationRequest);
5803         mWmService.mDisplayWindowSettings.setIgnoreOrientationRequest(
5804                 this, mIgnoreOrientationRequest);
5805         return rotationChanged;
5806     }
5807 
5808     /**
5809      * Locates the appropriate target window for scroll capture. The search progresses top to
5810      * bottom.
5811      * If {@code searchBehind} is non-null, the search will only consider windows behind this one.
5812      * If a valid taskId is specified, the target window must belong to the given task.
5813      *
5814      * @param searchBehind a window used to filter the search to windows behind it, or null to begin
5815      *                     the search at the top window of the display
5816      * @param taskId       specifies the id of a task the result must belong to or
5817      *                     {@link android.app.ActivityTaskManager#INVALID_TASK_ID INVALID_TASK_ID}
5818      *                     to match any window
5819      * @return the located window or null if none could be found matching criteria
5820      */
5821     @Nullable
findScrollCaptureTargetWindow(@ullable WindowState searchBehind, int taskId)5822     WindowState findScrollCaptureTargetWindow(@Nullable WindowState searchBehind, int taskId) {
5823         return getWindow(new Predicate<WindowState>() {
5824             boolean behindTopWindow = (searchBehind == null); // optional filter
5825             @Override
5826             public boolean test(WindowState nextWindow) {
5827                 // Skip through all windows until we pass topWindow (if specified)
5828                 if (!behindTopWindow) {
5829                     if (nextWindow == searchBehind) {
5830                         behindTopWindow = true;
5831                     }
5832                     return false; /* continue */
5833                 }
5834                 if (taskId == INVALID_TASK_ID) {
5835                     if (!nextWindow.canReceiveKeys()) {
5836                         return false; /* continue */
5837                     }
5838                 } else {
5839                     Task task = nextWindow.getTask();
5840                     if (task == null || !task.isTaskId(taskId)) {
5841                         return false; /* continue */
5842                     }
5843                 }
5844                 if (nextWindow.isSecureLocked()) {
5845                     return false; /* continue */
5846                 }
5847                 return true; /* stop, match found */
5848             }
5849         });
5850     }
5851 
5852     @Override
providesMaxBounds()5853     public boolean providesMaxBounds() {
5854         return true;
5855     }
5856 
5857     /** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */
5858     class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener {
5859 
5860         /**
5861          * The animating activity which shows the recents task list. It is set between
5862          * {@link RecentsAnimationController#initialize} and
5863          * {@link RecentsAnimationController#cleanupAnimation}.
5864          */
5865         private ActivityRecord mAnimatingRecents;
5866 
5867         /** Whether {@link #mAnimatingRecents} is going to be the top activity. */
5868         private boolean mRecentsWillBeTop;
5869 
5870         /**
5871          * If the recents activity has a fixed orientation which is different from the current top
5872          * activity, it will be rotated before being shown so we avoid a screen rotation animation
5873          * when showing the Recents view.
5874          */
onStartRecentsAnimation(@onNull ActivityRecord r)5875         void onStartRecentsAnimation(@NonNull ActivityRecord r) {
5876             mAnimatingRecents = r;
5877             if (r.isVisible() && mFocusedApp != null && !mFocusedApp.occludesParent()) {
5878                 // The recents activity has shown with the orientation determined by the top
5879                 // activity, keep its current orientation to avoid flicking by the configuration
5880                 // change of visible activity.
5881                 return;
5882             }
5883             rotateInDifferentOrientationIfNeeded(r);
5884             if (r.hasFixedRotationTransform()) {
5885                 // Set the record so we can recognize it to continue to update display orientation
5886                 // if the recents activity becomes the top later.
5887                 setFixedRotationLaunchingApp(r, r.getWindowConfiguration().getRotation());
5888             }
5889         }
5890 
5891         /**
5892          * If {@link #mAnimatingRecents} still has fixed rotation, it should be moved to top so we
5893          * don't clear {@link #mFixedRotationLaunchingApp} that will be handled by transition.
5894          */
onFinishRecentsAnimation()5895         void onFinishRecentsAnimation() {
5896             final ActivityRecord animatingRecents = mAnimatingRecents;
5897             final boolean recentsWillBeTop = mRecentsWillBeTop;
5898             mAnimatingRecents = null;
5899             mRecentsWillBeTop = false;
5900             if (recentsWillBeTop) {
5901                 // The recents activity will be the top, such as staying at recents list or
5902                 // returning to home (if home and recents are the same activity).
5903                 return;
5904             }
5905 
5906             if (animatingRecents != null && animatingRecents == mFixedRotationLaunchingApp
5907                     && animatingRecents.isVisible() && animatingRecents != topRunningActivity()) {
5908                 // The recents activity should be going to be invisible (switch to another app or
5909                 // return to original top). Only clear the top launching record without finishing
5910                 // the transform immediately because it won't affect display orientation. And before
5911                 // the visibility is committed, the recents activity may perform relayout which may
5912                 // cause unexpected configuration change if the rotated configuration is restored.
5913                 // The transform will be finished when the transition is done.
5914                 setFixedRotationLaunchingAppUnchecked(null);
5915             } else {
5916                 // If there is already a launching activity that is not the recents, before its
5917                 // transition is completed, the recents animation may be started. So if the recents
5918                 // activity won't be the top, the display orientation should be updated according
5919                 // to the current top activity.
5920                 continueUpdateOrientationForDiffOrienLaunchingApp();
5921             }
5922         }
5923 
notifyRecentsWillBeTop()5924         void notifyRecentsWillBeTop() {
5925             mRecentsWillBeTop = true;
5926         }
5927 
5928         /**
5929          * Return {@code true} if there is an ongoing animation to the "Recents" activity and this
5930          * activity as a fixed orientation so shouldn't be rotated.
5931          */
isTopFixedOrientationRecentsAnimating()5932         boolean isTopFixedOrientationRecentsAnimating() {
5933             return mAnimatingRecents != null
5934                     && mAnimatingRecents.getRequestedConfigurationOrientation(true /* forDisplay */)
5935                     != ORIENTATION_UNDEFINED && !hasTopFixedRotationLaunchingApp();
5936         }
5937 
5938         @Override
onAppTransitionFinishedLocked(IBinder token)5939         public void onAppTransitionFinishedLocked(IBinder token) {
5940             final ActivityRecord r = getActivityRecord(token);
5941             // Ignore the animating recents so the fixed rotation transform won't be switched twice
5942             // by finishing the recents animation and moving it to top. That also avoids flickering
5943             // due to wait for previous activity to be paused if it supports PiP that ignores the
5944             // effect of resume-while-pausing.
5945             if (r == null || r == mAnimatingRecents) {
5946                 return;
5947             }
5948             if (mAnimatingRecents != null && mRecentsWillBeTop) {
5949                 // The activity is not the recents and it should be moved to back later, so it is
5950                 // better to keep its current appearance for the next transition. Otherwise the
5951                 // display orientation may be updated too early and the layout procedures at the
5952                 // end of finishing recents animation is skipped. That causes flickering because
5953                 // the surface of closing app hasn't updated to invisible.
5954                 return;
5955             }
5956             if (mFixedRotationLaunchingApp == null) {
5957                 // In most cases this is a no-op if the activity doesn't have fixed rotation.
5958                 // Otherwise it could be from finishing recents animation while the display has
5959                 // different orientation.
5960                 r.finishFixedRotationTransform();
5961                 return;
5962             }
5963             if (mFixedRotationLaunchingApp.hasFixedRotationTransform(r)) {
5964                 if (mFixedRotationLaunchingApp.hasAnimatingFixedRotationTransition()) {
5965                     // Waiting until all of the associated activities have done animation, or the
5966                     // orientation would be updated too early and cause flickering.
5967                     return;
5968                 }
5969             } else {
5970                 // Handle a corner case that the task of {@link #mFixedRotationLaunchingApp} is no
5971                 // longer animating but the corresponding transition finished event won't notify.
5972                 // E.g. activity A transferred starting window to B, only A will receive transition
5973                 // finished event. A doesn't have fixed rotation but B is the rotated launching app.
5974                 final Task task = r.getTask();
5975                 if (task == null || task != mFixedRotationLaunchingApp.getTask()) {
5976                     // Different tasks won't be in one activity transition animation.
5977                     return;
5978                 }
5979                 if (task.isAppTransitioning()) {
5980                     return;
5981                     // Continue to update orientation because the transition of the top rotated
5982                     // launching activity is done.
5983                 }
5984             }
5985             continueUpdateOrientationForDiffOrienLaunchingApp();
5986         }
5987 
5988         @Override
onAppTransitionCancelledLocked(boolean keyguardGoingAway)5989         public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {
5990             continueUpdateOrientationForDiffOrienLaunchingApp();
5991         }
5992 
5993         @Override
onAppTransitionTimeoutLocked()5994         public void onAppTransitionTimeoutLocked() {
5995             continueUpdateOrientationForDiffOrienLaunchingApp();
5996         }
5997     }
5998 
5999     class RemoteInsetsControlTarget implements InsetsControlTarget {
6000         private final IDisplayWindowInsetsController mRemoteInsetsController;
6001         private final InsetsState mRequestedInsetsState = new InsetsState();
6002 
RemoteInsetsControlTarget(IDisplayWindowInsetsController controller)6003         RemoteInsetsControlTarget(IDisplayWindowInsetsController controller) {
6004             mRemoteInsetsController = controller;
6005         }
6006 
6007         /**
6008          * Notifies the remote insets controller that the top focused window has changed.
6009          *
6010          * @param packageName The name of the package that is open in the top focused window.
6011          */
topFocusedWindowChanged(String packageName)6012         void topFocusedWindowChanged(String packageName) {
6013             try {
6014                 mRemoteInsetsController.topFocusedWindowChanged(packageName);
6015             } catch (RemoteException e) {
6016                 Slog.w(TAG, "Failed to deliver package in top focused window change", e);
6017             }
6018         }
6019 
notifyInsetsChanged()6020         void notifyInsetsChanged() {
6021             try {
6022                 mRemoteInsetsController.insetsChanged(
6023                         getInsetsStateController().getRawInsetsState());
6024             } catch (RemoteException e) {
6025                 Slog.w(TAG, "Failed to deliver inset state change", e);
6026             }
6027         }
6028 
6029         @Override
notifyInsetsControlChanged()6030         public void notifyInsetsControlChanged() {
6031             final InsetsStateController stateController = getInsetsStateController();
6032             try {
6033                 mRemoteInsetsController.insetsControlChanged(stateController.getRawInsetsState(),
6034                         stateController.getControlsForDispatch(this));
6035             } catch (RemoteException e) {
6036                 Slog.w(TAG, "Failed to deliver inset state change", e);
6037             }
6038         }
6039 
6040         @Override
showInsets(@indowInsets.Type.InsetsType int types, boolean fromIme)6041         public void showInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) {
6042             try {
6043                 mRemoteInsetsController.showInsets(types, fromIme);
6044             } catch (RemoteException e) {
6045                 Slog.w(TAG, "Failed to deliver showInsets", e);
6046             }
6047         }
6048 
6049         @Override
hideInsets(@indowInsets.Type.InsetsType int types, boolean fromIme)6050         public void hideInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) {
6051             try {
6052                 mRemoteInsetsController.hideInsets(types, fromIme);
6053             } catch (RemoteException e) {
6054                 Slog.w(TAG, "Failed to deliver showInsets", e);
6055             }
6056         }
6057 
6058         @Override
getRequestedVisibility(@nternalInsetsType int type)6059         public boolean getRequestedVisibility(@InternalInsetsType int type) {
6060             if (type == ITYPE_IME) {
6061                 return getInsetsStateController().getImeSourceProvider().isImeShowing();
6062             }
6063             return mRequestedInsetsState.getSourceOrDefaultVisibility(type);
6064         }
6065 
updateRequestedVisibility(InsetsState state)6066         void updateRequestedVisibility(InsetsState state) {
6067             for (int i = 0; i < InsetsState.SIZE; i++) {
6068                 final InsetsSource source = state.peekSource(i);
6069                 if (source == null) continue;
6070                 mRequestedInsetsState.addSource(source);
6071             }
6072         }
6073     }
6074 
getMagnificationSpec()6075     MagnificationSpec getMagnificationSpec() {
6076         return mMagnificationSpec;
6077     }
6078 
findAreaForWindowType(int windowType, Bundle options, boolean ownerCanManageAppToken, boolean roundedCornerOverlay)6079     DisplayArea findAreaForWindowType(int windowType, Bundle options,
6080             boolean ownerCanManageAppToken, boolean roundedCornerOverlay) {
6081         // TODO(b/159767464): figure out how to find an appropriate TDA.
6082         if (windowType >= FIRST_APPLICATION_WINDOW && windowType <= LAST_APPLICATION_WINDOW) {
6083             return getDefaultTaskDisplayArea();
6084         }
6085         // Return IME container here because it could be in one of sub RootDisplayAreas depending on
6086         // the focused edit text. Also, the RootDisplayArea choosing strategy is implemented by
6087         // the server side, but not mSelectRootForWindowFunc customized by OEM.
6088         if (windowType == TYPE_INPUT_METHOD || windowType == TYPE_INPUT_METHOD_DIALOG) {
6089             return getImeContainer();
6090         }
6091         return mDisplayAreaPolicy.findAreaForWindowType(windowType, options,
6092                 ownerCanManageAppToken, roundedCornerOverlay);
6093     }
6094 
6095     /**
6096      * Finds the {@link DisplayArea} for the {@link WindowToken} to attach to.
6097      * <p>
6098      * Note that the differences between this API and
6099      * {@link RootDisplayArea#findAreaForTokenInLayer(WindowToken)} is that this API finds a
6100      * {@link DisplayArea} in {@link DisplayContent} level, which may find a {@link DisplayArea}
6101      * from multiple {@link RootDisplayArea RootDisplayAreas} under this {@link DisplayContent}'s
6102      * hierarchy, while {@link RootDisplayArea#findAreaForTokenInLayer(WindowToken)} finds a
6103      * {@link DisplayArea.Tokens} from a {@link DisplayArea.Tokens} list mapped to window layers.
6104      * </p>
6105      *
6106      * @see DisplayContent#findAreaForTokenInLayer(WindowToken)
6107      */
findAreaForToken(WindowToken windowToken)6108     DisplayArea findAreaForToken(WindowToken windowToken) {
6109         return findAreaForWindowType(windowToken.getWindowType(), windowToken.mOptions,
6110                 windowToken.mOwnerCanManageAppTokens, windowToken.mRoundedCornerOverlay);
6111     }
6112 
6113     @Override
asDisplayContent()6114     DisplayContent asDisplayContent() {
6115         return this;
6116     }
6117 }
6118