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