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