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