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