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