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