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