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.ActivityManager.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.res.Configuration.ORIENTATION_LANDSCAPE;
30 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
31 import static android.view.Display.DEFAULT_DISPLAY;
32 import static android.view.Display.FLAG_PRIVATE;
33 import static android.view.Surface.ROTATION_0;
34 import static android.view.Surface.ROTATION_180;
35 import static android.view.Surface.ROTATION_270;
36 import static android.view.Surface.ROTATION_90;
37 import static android.view.View.GONE;
38 import static android.view.WindowManager.DOCKED_BOTTOM;
39 import static android.view.WindowManager.DOCKED_INVALID;
40 import static android.view.WindowManager.DOCKED_TOP;
41 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
42 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
43 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
44 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
45 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
46 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
47 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
48 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
49 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
50 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
51 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
52 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
53 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
54 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
55 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
56 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
57 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
58 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
59 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
60 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
61 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
62 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
63 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
64 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
65 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
66 import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
67 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
68 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
69 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
70 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
71 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
72 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
73 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
74 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
75 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
76 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
77 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
78 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
79 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
80 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
81 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
82 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
83 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
84 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
85 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
86 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
87 import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION;
88 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
89 import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
90 import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
91 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
92 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
93 import static com.android.server.wm.WindowManagerService.SEAMLESS_ROTATION_TIMEOUT_DURATION;
94 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
95 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE;
96 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
97 import static com.android.server.wm.WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION;
98 import static com.android.server.wm.WindowManagerService.dipToPixel;
99 import static com.android.server.wm.WindowManagerService.logSurface;
100 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
101 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
102 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
103 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
104 import static com.android.server.wm.DisplayProto.ABOVE_APP_WINDOWS;
105 import static com.android.server.wm.DisplayProto.BELOW_APP_WINDOWS;
106 import static com.android.server.wm.DisplayProto.DISPLAY_FRAMES;
107 import static com.android.server.wm.DisplayProto.DISPLAY_INFO;
108 import static com.android.server.wm.DisplayProto.DOCKED_STACK_DIVIDER_CONTROLLER;
109 import static com.android.server.wm.DisplayProto.DPI;
110 import static com.android.server.wm.DisplayProto.ID;
111 import static com.android.server.wm.DisplayProto.IME_WINDOWS;
112 import static com.android.server.wm.DisplayProto.PINNED_STACK_CONTROLLER;
113 import static com.android.server.wm.DisplayProto.ROTATION;
114 import static com.android.server.wm.DisplayProto.SCREEN_ROTATION_ANIMATION;
115 import static com.android.server.wm.DisplayProto.STACKS;
116 import static com.android.server.wm.DisplayProto.WINDOW_CONTAINER;
117 
118 import android.annotation.CallSuper;
119 import android.annotation.NonNull;
120 import android.content.pm.PackageManager;
121 import android.content.res.CompatibilityInfo;
122 import android.content.res.Configuration;
123 import android.graphics.Bitmap;
124 import android.graphics.Matrix;
125 import android.graphics.Path;
126 import android.graphics.Rect;
127 import android.graphics.RectF;
128 import android.graphics.Region;
129 import android.graphics.Region.Op;
130 import android.hardware.display.DisplayManagerInternal;
131 import android.os.Debug;
132 import android.os.Handler;
133 import android.os.IBinder;
134 import android.os.RemoteException;
135 import android.os.SystemClock;
136 import android.os.Trace;
137 import android.util.ArraySet;
138 import android.util.DisplayMetrics;
139 import android.util.Slog;
140 import android.util.proto.ProtoOutputStream;
141 import android.view.Display;
142 import android.view.DisplayCutout;
143 import android.view.DisplayInfo;
144 import android.view.InputDevice;
145 import android.view.MagnificationSpec;
146 import android.view.Surface;
147 import android.view.SurfaceControl;
148 import android.view.SurfaceControl.Transaction;
149 import android.view.SurfaceSession;
150 
151 import com.android.internal.annotations.VisibleForTesting;
152 import com.android.internal.util.ToBooleanFunction;
153 import com.android.internal.view.IInputMethodClient;
154 import com.android.server.policy.WindowManagerPolicy;
155 import com.android.server.wm.utils.RotationCache;
156 import com.android.server.wm.utils.WmDisplayCutout;
157 
158 import java.io.PrintWriter;
159 import java.util.ArrayList;
160 import java.util.Comparator;
161 import java.util.HashMap;
162 import java.util.Iterator;
163 import java.util.LinkedList;
164 import java.util.List;
165 import java.util.Objects;
166 import java.util.function.Consumer;
167 import java.util.function.Predicate;
168 
169 /**
170  * Utility class for keeping track of the WindowStates and other pertinent contents of a
171  * particular Display.
172  *
173  * IMPORTANT: No method from this class should ever be used without holding
174  * WindowManagerService.mWindowMap.
175  */
176 class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
177     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
178 
179     /** Unique identifier of this stack. */
180     private final int mDisplayId;
181 
182     /** The containers below are the only child containers the display can have. */
183     // Contains all window containers that are related to apps (Activities)
184     private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(mService);
185     // Contains all non-app window containers that should be displayed above the app containers
186     // (e.g. Status bar)
187     private final AboveAppWindowContainers mAboveAppWindowsContainers =
188             new AboveAppWindowContainers("mAboveAppWindowsContainers", mService);
189     // Contains all non-app window containers that should be displayed below the app containers
190     // (e.g. Wallpaper).
191     private final NonAppWindowContainers mBelowAppWindowsContainers =
192             new NonAppWindowContainers("mBelowAppWindowsContainers", mService);
193     // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
194     // on the IME target. We mainly have this container grouping so we can keep track of all the IME
195     // window containers together and move them in-sync if/when needed. We use a subclass of
196     // WindowContainer which is omitted from screen magnification, as the IME is never magnified.
197     private final NonMagnifiableWindowContainers mImeWindowsContainers =
198             new NonMagnifiableWindowContainers("mImeWindowsContainers", mService);
199 
200     private WindowState mTmpWindow;
201     private WindowState mTmpWindow2;
202     private WindowAnimator mTmpWindowAnimator;
203     private boolean mTmpRecoveringMemory;
204     private boolean mUpdateImeTarget;
205     private boolean mTmpInitial;
206     private int mMaxUiWidth;
207 
208     // Mapping from a token IBinder to a WindowToken object on this display.
209     private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
210 
211     // Initial display metrics.
212     int mInitialDisplayWidth = 0;
213     int mInitialDisplayHeight = 0;
214     int mInitialDisplayDensity = 0;
215 
216     DisplayCutout mInitialDisplayCutout;
217     private final RotationCache<DisplayCutout, WmDisplayCutout> mDisplayCutoutCache
218             = new RotationCache<>(this::calculateDisplayCutoutForRotationUncached);
219 
220     /**
221      * Overridden display size. Initialized with {@link #mInitialDisplayWidth}
222      * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size".
223      * @see WindowManagerService#setForcedDisplaySize(int, int, int)
224      */
225     int mBaseDisplayWidth = 0;
226     int mBaseDisplayHeight = 0;
227     /**
228      * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity}
229      * but can be set from Settings or via shell command "adb shell wm density".
230      * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
231      */
232     int mBaseDisplayDensity = 0;
233     boolean mDisplayScalingDisabled;
234     private final DisplayInfo mDisplayInfo = new DisplayInfo();
235     private final Display mDisplay;
236     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
237     DisplayFrames mDisplayFrames;
238 
239     /**
240      * For default display it contains real metrics, empty for others.
241      * @see WindowManagerService#createWatermarkInTransaction()
242      */
243     final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
244     /** @see #computeCompatSmallestWidth(boolean, int, int, int, int) */
245     private final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
246 
247     /**
248      * Compat metrics computed based on {@link #mDisplayMetrics}.
249      * @see #updateDisplayAndOrientation(int)
250      */
251     private final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
252 
253     /** The desired scaling factor for compatible apps. */
254     float mCompatibleScreenScale;
255 
256     /**
257      * Current rotation of the display.
258      * Constants as per {@link android.view.Surface.Rotation}.
259      *
260      * @see #updateRotationUnchecked()
261      */
262     private int mRotation = 0;
263 
264     /**
265      * Last applied orientation of the display.
266      * Constants as per {@link android.content.pm.ActivityInfo.ScreenOrientation}.
267      *
268      * @see WindowManagerService#updateOrientationFromAppTokensLocked(boolean, int)
269      */
270     private int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
271 
272     /**
273      * Flag indicating that the application is receiving an orientation that has different metrics
274      * than it expected. E.g. Portrait instead of Landscape.
275      *
276      * @see #updateRotationUnchecked()
277      */
278     private boolean mAltOrientation = false;
279 
280     /**
281      * Orientation forced by some window. If there is no visible window that specifies orientation
282      * it is set to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}.
283      *
284      * @see NonAppWindowContainers#getOrientation()
285      */
286     private int mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
287 
288     /**
289      * Last orientation forced by the keyguard. It is applied when keyguard is shown and is not
290      * occluded.
291      *
292      * @see NonAppWindowContainers#getOrientation()
293      */
294     private int mLastKeyguardForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
295 
296     /**
297      * Keep track of wallpaper visibility to notify changes.
298      */
299     private boolean mLastWallpaperVisible = false;
300 
301     private Rect mBaseDisplayRect = new Rect();
302 
303     // Accessed directly by all users.
304     private boolean mLayoutNeeded;
305     int pendingLayoutChanges;
306     // TODO(multi-display): remove some of the usages.
307     boolean isDefaultDisplay;
308     /**
309      * Flag indicating whether WindowManager should override info for this display in
310      * DisplayManager.
311      */
312     boolean mShouldOverrideDisplayConfiguration = true;
313 
314     /** Window tokens that are in the process of exiting, but still on screen for animations. */
315     final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
316 
317     /** Detect user tapping outside of current focused task bounds .*/
318     TaskTapPointerEventListener mTapDetector;
319 
320     /** Detect user tapping outside of current focused stack bounds .*/
321     private Region mTouchExcludeRegion = new Region();
322 
323     /** Save allocating when calculating rects */
324     private final Rect mTmpRect = new Rect();
325     private final Rect mTmpRect2 = new Rect();
326     private final RectF mTmpRectF = new RectF();
327     private final Matrix mTmpMatrix = new Matrix();
328     private final Region mTmpRegion = new Region();
329 
330     /** Used for handing back size of display */
331     private final Rect mTmpBounds = new Rect();
332 
333     /** Remove this display when animation on it has completed. */
334     private boolean mDeferredRemoval;
335 
336     final DockedStackDividerController mDividerControllerLocked;
337     final PinnedStackController mPinnedStackControllerLocked;
338 
339     final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
340     /** A collection of windows that provide tap exclude regions inside of them. */
341     final ArraySet<WindowState> mTapExcludeProvidingWindows = new ArraySet<>();
342 
343     private boolean mHaveBootMsg = false;
344     private boolean mHaveApp = false;
345     private boolean mHaveWallpaper = false;
346     private boolean mHaveKeyguard = true;
347 
348     private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
349 
350     private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
351             new TaskForResizePointSearchResult();
352     private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState =
353             new ApplySurfaceChangesTransactionState();
354 
355     // True if this display is in the process of being removed. Used to determine if the removal of
356     // the display's direct children should be allowed.
357     private boolean mRemovingDisplay = false;
358 
359     // {@code false} if this display is in the processing of being created.
360     private boolean mDisplayReady = false;
361 
362     WallpaperController mWallpaperController;
363 
364     private final SurfaceSession mSession = new SurfaceSession();
365 
366     /**
367      * We organize all top-level Surfaces in to the following layers.
368      * mOverlayLayer contains a few Surfaces which are always on top of others
369      * and omitted from Screen-Magnification, for example the strict mode flash or
370      * the magnification overlay itself.
371      * {@link #mWindowingLayer} contains everything else.
372      */
373     private SurfaceControl mOverlayLayer;
374 
375     /**
376      * See {@link #mOverlayLayer}
377      */
378     private SurfaceControl mWindowingLayer;
379 
380     /**
381      * Specifies the size of the surfaces in {@link #mOverlayLayer} and {@link #mWindowingLayer}.
382      * <p>
383      * For these surfaces currently we use a surface based on the larger of width or height so we
384      * don't have to resize when rotating the display.
385      */
386     private int mSurfaceSize;
387 
388     /**
389      * Sequence number for the current layout pass.
390      */
391     int mLayoutSeq = 0;
392 
393     /**
394      * Specifies the count to determine whether to defer updating the IME target until ready.
395      */
396     private int mDeferUpdateImeTargetCount;
397 
398     /** Temporary float array to retrieve 3x3 matrix values. */
399     private final float[] mTmpFloats = new float[9];
400 
401     private MagnificationSpec mMagnificationSpec;
402 
403     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
404         WindowStateAnimator winAnimator = w.mWinAnimator;
405         final AppWindowToken atoken = w.mAppToken;
406         if (winAnimator.mDrawState == READY_TO_SHOW) {
407             if (atoken == null || atoken.allDrawn) {
408                 if (w.performShowLocked()) {
409                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
410                     if (DEBUG_LAYOUT_REPEATS) {
411                         mService.mWindowPlacerLocked.debugLayoutRepeats(
412                                 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
413                     }
414                 }
415             }
416         }
417     };
418 
419     private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> {
420         final WindowStateAnimator winAnimator = w.mWinAnimator;
421         if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
422             return;
423         }
424 
425         final int flags = w.mAttrs.flags;
426 
427         // If this window is animating, make a note that we have an animating window and take
428         // care of a request to run a detached wallpaper animation.
429         if (winAnimator.isAnimationSet()) {
430             final AnimationAdapter anim = w.getAnimation();
431             if (anim != null) {
432                 if ((flags & FLAG_SHOW_WALLPAPER) != 0 && anim.getDetachWallpaper()) {
433                     mTmpWindow = w;
434                 }
435                 final int color = anim.getBackgroundColor();
436                 if (color != 0) {
437                     final TaskStack stack = w.getStack();
438                     if (stack != null) {
439                         stack.setAnimationBackground(winAnimator, color);
440                     }
441                 }
442             }
443         }
444 
445         // If this window's app token is running a detached wallpaper animation, make a note so
446         // we can ensure the wallpaper is displayed behind it.
447         final AppWindowToken atoken = winAnimator.mWin.mAppToken;
448         final AnimationAdapter animation = atoken != null ? atoken.getAnimation() : null;
449         if (animation != null) {
450             if ((flags & FLAG_SHOW_WALLPAPER) != 0 && animation.getDetachWallpaper()) {
451                 mTmpWindow = w;
452             }
453 
454             final int color = animation.getBackgroundColor();
455             if (color != 0) {
456                 final TaskStack stack = w.getStack();
457                 if (stack != null) {
458                     stack.setAnimationBackground(winAnimator, color);
459                 }
460             }
461         }
462     };
463 
464     private final Consumer<WindowState> mScheduleToastTimeout = w -> {
465         final int lostFocusUid = mTmpWindow.mOwnerUid;
466         final Handler handler = mService.mH;
467         if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) {
468             if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) {
469                 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w),
470                         w.mAttrs.hideTimeoutMilliseconds);
471             }
472         }
473     };
474 
475     private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
476         final AppWindowToken focusedApp = mService.mFocusedApp;
477         if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w
478                 + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys());
479 
480         if (!w.canReceiveKeys()) {
481             return false;
482         }
483 
484         final AppWindowToken wtoken = w.mAppToken;
485 
486         // If this window's application has been removed, just skip it.
487         if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
488             if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
489                     + (wtoken.removed ? "removed" : "sendingToBottom"));
490             return false;
491         }
492 
493         if (focusedApp == null) {
494             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
495                     + " using new focus @ " + w);
496             mTmpWindow = w;
497             return true;
498         }
499 
500         if (!focusedApp.windowsAreFocusable()) {
501             // Current focused app windows aren't focusable...
502             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
503                     + " focusable using new focus @ " + w);
504             mTmpWindow = w;
505             return true;
506         }
507 
508         // Descend through all of the app tokens and find the first that either matches
509         // win.mAppToken (return win) or mFocusedApp (return null).
510         if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
511             if (focusedApp.compareTo(wtoken) > 0) {
512                 // App stack below focused app stack. No focus for you!!!
513                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
514                         "findFocusedWindow: Reached focused app=" + focusedApp);
515                 mTmpWindow = null;
516                 return true;
517             }
518         }
519 
520         if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w);
521         mTmpWindow = w;
522         return true;
523     };
524 
525     private final Consumer<WindowState> mPerformLayout = w -> {
526         // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
527         // wasting time and funky changes while a window is animating away.
528         final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w))
529                 || w.isGoneForLayoutLw();
530 
531         if (DEBUG_LAYOUT && !w.mLayoutAttached) {
532             Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
533                     + " mLayoutAttached=" + w.mLayoutAttached
534                     + " screen changed=" + w.isConfigChanged());
535             final AppWindowToken atoken = w.mAppToken;
536             if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
537                     + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
538                     + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
539                     + " parentHidden=" + w.isParentWindowHidden());
540             else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
541                     + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
542                     + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
543                     + " parentHidden=" + w.isParentWindowHidden());
544         }
545 
546         // If this view is GONE, then skip it -- keep the current frame, and let the caller know
547         // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
548         // since that means "perform layout as normal, just don't display").
549         if (!gone || !w.mHaveFrame || w.mLayoutNeeded
550                 || ((w.isConfigChanged() || w.setReportResizeHints())
551                 && !w.isGoneForLayoutLw() &&
552                 ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
553                         (w.mHasSurface && w.mAppToken != null &&
554                                 w.mAppToken.layoutConfigChanges)))) {
555             if (!w.mLayoutAttached) {
556                 if (mTmpInitial) {
557                     //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
558                     w.mContentChanged = false;
559                 }
560                 if (w.mAttrs.type == TYPE_DREAM) {
561                     // Don't layout windows behind a dream, so that if it does stuff like hide
562                     // the status bar we won't get a bad transition when it goes away.
563                     mTmpWindow = w;
564                 }
565                 w.mLayoutNeeded = false;
566                 w.prelayout();
567                 final boolean firstLayout = !w.isLaidOut();
568                 mService.mPolicy.layoutWindowLw(w, null, mDisplayFrames);
569                 w.mLayoutSeq = mLayoutSeq;
570 
571                 // If this is the first layout, we need to initialize the last inset values as
572                 // otherwise we'd immediately cause an unnecessary resize.
573                 if (firstLayout) {
574                     w.updateLastInsetValues();
575                 }
576 
577                 if (w.mAppToken != null) {
578                     w.mAppToken.layoutLetterbox(w);
579                 }
580 
581                 if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.mFrame
582                         + " mContainingFrame=" + w.mContainingFrame
583                         + " mDisplayFrame=" + w.mDisplayFrame);
584             }
585         }
586     };
587 
588     private final Consumer<WindowState> mPerformLayoutAttached = w -> {
589         if (w.mLayoutAttached) {
590             if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
591                     + " mViewVisibility=" + w.mViewVisibility
592                     + " mRelayoutCalled=" + w.mRelayoutCalled);
593             // If this view is GONE, then skip it -- keep the current frame, and let the caller
594             // know so they can ignore it if they want.  (We do the normal layout for INVISIBLE
595             // windows, since that means "perform layout as normal, just don't display").
596             if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) {
597                 return;
598             }
599             if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
600                     || w.mLayoutNeeded) {
601                 if (mTmpInitial) {
602                     //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
603                     w.mContentChanged = false;
604                 }
605                 w.mLayoutNeeded = false;
606                 w.prelayout();
607                 mService.mPolicy.layoutWindowLw(w, w.getParentWindow(), mDisplayFrames);
608                 w.mLayoutSeq = mLayoutSeq;
609                 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame
610                         + " mContainingFrame=" + w.mContainingFrame
611                         + " mDisplayFrame=" + w.mDisplayFrame);
612             }
613         } else if (w.mAttrs.type == TYPE_DREAM) {
614             // Don't layout windows behind a dream, so that if it does stuff like hide the
615             // status bar we won't get a bad transition when it goes away.
616             mTmpWindow = mTmpWindow2;
617         }
618     };
619 
620     private final Predicate<WindowState> mComputeImeTargetPredicate = w -> {
621         if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w
622                 + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
623         return w.canBeImeTarget();
624     };
625 
626     private final Consumer<WindowState> mApplyPostLayoutPolicy =
627             w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
628                     mService.mInputMethodTarget);
629 
630     private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
631         final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
632         final boolean obscuredChanged = w.mObscured !=
633                 mTmpApplySurfaceChangesTransactionState.obscured;
634         final RootWindowContainer root = mService.mRoot;
635         // Only used if default window
636         final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
637 
638         // Update effect.
639         w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
640         if (!mTmpApplySurfaceChangesTransactionState.obscured) {
641             final boolean isDisplayed = w.isDisplayedLw();
642 
643             if (isDisplayed && w.isObscuringDisplay()) {
644                 // This window completely covers everything behind it, so we want to leave all
645                 // of them as undimmed (for performance reasons).
646                 root.mObscuringWindow = w;
647                 mTmpApplySurfaceChangesTransactionState.obscured = true;
648             }
649 
650             mTmpApplySurfaceChangesTransactionState.displayHasContent |=
651                     root.handleNotObscuredLocked(w,
652                             mTmpApplySurfaceChangesTransactionState.obscured,
653                             mTmpApplySurfaceChangesTransactionState.syswin);
654 
655             if (w.mHasSurface && isDisplayed) {
656                 final int type = w.mAttrs.type;
657                 if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
658                         || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
659                     mTmpApplySurfaceChangesTransactionState.syswin = true;
660                 }
661                 if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
662                         && w.mAttrs.preferredRefreshRate != 0) {
663                     mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
664                             = w.mAttrs.preferredRefreshRate;
665                 }
666                 if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
667                         && w.mAttrs.preferredDisplayModeId != 0) {
668                     mTmpApplySurfaceChangesTransactionState.preferredModeId
669                             = w.mAttrs.preferredDisplayModeId;
670                 }
671             }
672         }
673 
674         if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
675                 && mWallpaperController.isWallpaperTarget(w)) {
676             // This is the wallpaper target and its obscured state changed... make sure the
677             // current wallpaper's visibility has been updated accordingly.
678             mWallpaperController.updateWallpaperVisibility();
679         }
680 
681         w.handleWindowMovedIfNeeded();
682 
683         final WindowStateAnimator winAnimator = w.mWinAnimator;
684 
685         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
686         w.mContentChanged = false;
687 
688         // Moved from updateWindowsAndWallpaperLocked().
689         if (w.mHasSurface) {
690             // Take care of the window being ready to display.
691             final boolean committed = winAnimator.commitFinishDrawingLocked();
692             if (isDefaultDisplay && committed) {
693                 if (w.mAttrs.type == TYPE_DREAM) {
694                     // HACK: When a dream is shown, it may at that point hide the lock screen.
695                     // So we need to redo the layout to let the phone window manager make this
696                     // happen.
697                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
698                     if (DEBUG_LAYOUT_REPEATS) {
699                         surfacePlacer.debugLayoutRepeats(
700                                 "dream and commitFinishDrawingLocked true",
701                                 pendingLayoutChanges);
702                     }
703                 }
704                 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
705                     if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
706                             "First draw done in potential wallpaper target " + w);
707                     root.mWallpaperMayChange = true;
708                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
709                     if (DEBUG_LAYOUT_REPEATS) {
710                         surfacePlacer.debugLayoutRepeats(
711                                 "wallpaper and commitFinishDrawingLocked true",
712                                 pendingLayoutChanges);
713                     }
714                 }
715             }
716         }
717 
718         final AppWindowToken atoken = w.mAppToken;
719         if (atoken != null) {
720             atoken.updateLetterboxSurface(w);
721             final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
722             if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
723                 mTmpUpdateAllDrawn.add(atoken);
724             }
725         }
726 
727         if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
728                 && w.isDisplayedLw()) {
729             mTmpApplySurfaceChangesTransactionState.focusDisplayed = true;
730         }
731 
732         w.updateResizingWindowIfNeeded();
733     };
734 
735     /**
736      * Create new {@link DisplayContent} instance, add itself to the root window container and
737      * initialize direct children.
738      * @param display May not be null.
739      * @param service You know.
740      * @param wallpaperController wallpaper windows controller used to adjust the positioning of the
741      *                            wallpaper windows in the window list.
742      */
DisplayContent(Display display, WindowManagerService service, WallpaperController wallpaperController, DisplayWindowController controller)743     DisplayContent(Display display, WindowManagerService service,
744             WallpaperController wallpaperController, DisplayWindowController controller) {
745         super(service);
746         setController(controller);
747         if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) {
748             throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
749                     + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId())
750                     + " new=" + display);
751         }
752 
753         mDisplay = display;
754         mDisplayId = display.getDisplayId();
755         mWallpaperController = wallpaperController;
756         display.getDisplayInfo(mDisplayInfo);
757         display.getMetrics(mDisplayMetrics);
758         isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
759         mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
760                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
761         initializeDisplayBaseInfo();
762         mDividerControllerLocked = new DockedStackDividerController(service, this);
763         mPinnedStackControllerLocked = new PinnedStackController(service, this);
764 
765         // We use this as our arbitrary surface size for buffer-less parents
766         // that don't impose cropping on their children. It may need to be larger
767         // than the display size because fullscreen windows can be shifted offscreen
768         // due to surfaceInsets. 2 times the largest display dimension feels like an
769         // appropriately arbitrary number. Eventually we would like to give SurfaceFlinger
770         // layers the ability to match their parent sizes and be able to skip
771         // such arbitrary size settings.
772         mSurfaceSize = Math.max(mBaseDisplayHeight, mBaseDisplayWidth) * 2;
773 
774         final SurfaceControl.Builder b = mService.makeSurfaceBuilder(mSession)
775                 .setSize(mSurfaceSize, mSurfaceSize)
776                 .setOpaque(true);
777         mWindowingLayer = b.setName("Display Root").build();
778         mOverlayLayer = b.setName("Display Overlays").build();
779 
780         getPendingTransaction().setLayer(mWindowingLayer, 0)
781                 .setLayerStack(mWindowingLayer, mDisplayId)
782                 .show(mWindowingLayer)
783                 .setLayer(mOverlayLayer, 1)
784                 .setLayerStack(mOverlayLayer, mDisplayId)
785                 .show(mOverlayLayer);
786         getPendingTransaction().apply();
787 
788         // These are the only direct children we should ever have and they are permanent.
789         super.addChild(mBelowAppWindowsContainers, null);
790         super.addChild(mTaskStackContainers, null);
791         super.addChild(mAboveAppWindowsContainers, null);
792         super.addChild(mImeWindowsContainers, null);
793 
794         // Add itself as a child to the root container.
795         mService.mRoot.addChild(this, null);
796 
797         // TODO(b/62541591): evaluate whether this is the best spot to declare the
798         // {@link DisplayContent} ready for use.
799         mDisplayReady = true;
800     }
801 
isReady()802     boolean isReady() {
803         // The display is ready when the system and the individual display are both ready.
804         return mService.mDisplayReady && mDisplayReady;
805     }
806 
getDisplayId()807     int getDisplayId() {
808         return mDisplayId;
809     }
810 
getWindowToken(IBinder binder)811     WindowToken getWindowToken(IBinder binder) {
812         return mTokenMap.get(binder);
813     }
814 
getAppWindowToken(IBinder binder)815     AppWindowToken getAppWindowToken(IBinder binder) {
816         final WindowToken token = getWindowToken(binder);
817         if (token == null) {
818             return null;
819         }
820         return token.asAppWindowToken();
821     }
822 
addWindowToken(IBinder binder, WindowToken token)823     private void addWindowToken(IBinder binder, WindowToken token) {
824         final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
825         if (dc != null) {
826             // We currently don't support adding a window token to the display if the display
827             // already has the binder mapped to another token. If there is a use case for supporting
828             // this moving forward we will either need to merge the WindowTokens some how or have
829             // the binder map to a list of window tokens.
830             throw new IllegalArgumentException("Can't map token=" + token + " to display="
831                     + getName() + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
832         }
833         if (binder == null) {
834             throw new IllegalArgumentException("Can't map token=" + token + " to display="
835                     + getName() + " binder is null");
836         }
837         if (token == null) {
838             throw new IllegalArgumentException("Can't map null token to display="
839                     + getName() + " binder=" + binder);
840         }
841 
842         mTokenMap.put(binder, token);
843 
844         if (token.asAppWindowToken() == null) {
845             // Add non-app token to container hierarchy on the display. App tokens are added through
846             // the parent container managing them (e.g. Tasks).
847             switch (token.windowType) {
848                 case TYPE_WALLPAPER:
849                     mBelowAppWindowsContainers.addChild(token);
850                     break;
851                 case TYPE_INPUT_METHOD:
852                 case TYPE_INPUT_METHOD_DIALOG:
853                     mImeWindowsContainers.addChild(token);
854                     break;
855                 default:
856                     mAboveAppWindowsContainers.addChild(token);
857                     break;
858             }
859         }
860     }
861 
removeWindowToken(IBinder binder)862     WindowToken removeWindowToken(IBinder binder) {
863         final WindowToken token = mTokenMap.remove(binder);
864         if (token != null && token.asAppWindowToken() == null) {
865             token.setExiting();
866         }
867         return token;
868     }
869 
870     /** Changes the display the input window token is housed on to this one. */
reParentWindowToken(WindowToken token)871     void reParentWindowToken(WindowToken token) {
872         final DisplayContent prevDc = token.getDisplayContent();
873         if (prevDc == this) {
874             return;
875         }
876         if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null
877                 && token.asAppWindowToken() == null) {
878             // Removed the token from the map, but made sure it's not an app token before removing
879             // from parent.
880             token.getParent().removeChild(token);
881         }
882 
883         addWindowToken(token.token, token);
884     }
885 
removeAppToken(IBinder binder)886     void removeAppToken(IBinder binder) {
887         final WindowToken token = removeWindowToken(binder);
888         if (token == null) {
889             Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
890             return;
891         }
892 
893         final AppWindowToken appToken = token.asAppWindowToken();
894 
895         if (appToken == null) {
896             Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
897             return;
898         }
899 
900         appToken.onRemovedFromDisplay();
901     }
902 
getDisplay()903     Display getDisplay() {
904         return mDisplay;
905     }
906 
getDisplayInfo()907     DisplayInfo getDisplayInfo() {
908         return mDisplayInfo;
909     }
910 
getDisplayMetrics()911     DisplayMetrics getDisplayMetrics() {
912         return mDisplayMetrics;
913     }
914 
getRotation()915     int getRotation() {
916         return mRotation;
917     }
918 
919     @VisibleForTesting
setRotation(int newRotation)920     void setRotation(int newRotation) {
921         mRotation = newRotation;
922     }
923 
getLastOrientation()924     int getLastOrientation() {
925         return mLastOrientation;
926     }
927 
setLastOrientation(int orientation)928     void setLastOrientation(int orientation) {
929         mLastOrientation = orientation;
930     }
931 
getAltOrientation()932     boolean getAltOrientation() {
933         return mAltOrientation;
934     }
935 
setAltOrientation(boolean altOrientation)936     void setAltOrientation(boolean altOrientation) {
937         mAltOrientation = altOrientation;
938     }
939 
getLastWindowForcedOrientation()940     int getLastWindowForcedOrientation() {
941         return mLastWindowForcedOrientation;
942     }
943 
944     /**
945      * Update rotation of the display.
946      *
947      * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
948      *         {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
949      */
updateRotationUnchecked()950     boolean updateRotationUnchecked() {
951         return updateRotationUnchecked(false /* forceUpdate */);
952     }
953 
954     /**
955      * Update rotation of the display with an option to force the update.
956      * @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating
957      *                    orientation because we're waiting for some rotation to finish or display
958      *                    to unfreeze, which results in configuration of the previously visible
959      *                    activity being applied to a newly visible one. Forcing the rotation
960      *                    update allows to workaround this issue.
961      * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
962      *         {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
963      */
updateRotationUnchecked(boolean forceUpdate)964     boolean updateRotationUnchecked(boolean forceUpdate) {
965         ScreenRotationAnimation screenRotationAnimation;
966         if (!forceUpdate) {
967             if (mService.mDeferredRotationPauseCount > 0) {
968                 // Rotation updates have been paused temporarily.  Defer the update until
969                 // updates have been resumed.
970                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
971                 return false;
972             }
973 
974             screenRotationAnimation =
975                     mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
976             if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
977                 // Rotation updates cannot be performed while the previous rotation change
978                 // animation is still in progress.  Skip this update.  We will try updating
979                 // again after the animation is finished and the display is unfrozen.
980                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
981                 return false;
982             }
983             if (mService.mDisplayFrozen) {
984                 // Even if the screen rotation animation has finished (e.g. isAnimating
985                 // returns false), there is still some time where we haven't yet unfrozen
986                 // the display. We also need to abort rotation here.
987                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
988                         "Deferring rotation, still finishing previous rotation");
989                 return false;
990             }
991         }
992 
993         if (!mService.mDisplayEnabled) {
994             // No point choosing a rotation if the display is not enabled.
995             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
996             return false;
997         }
998 
999         final int oldRotation = mRotation;
1000         final int lastOrientation = mLastOrientation;
1001         final boolean oldAltOrientation = mAltOrientation;
1002         final int rotation = mService.mPolicy.rotationForOrientationLw(lastOrientation, oldRotation,
1003                 isDefaultDisplay);
1004         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id="
1005                 + mDisplayId + " based on lastOrientation=" + lastOrientation
1006                 + " and oldRotation=" + oldRotation);
1007         boolean mayRotateSeamlessly = mService.mPolicy.shouldRotateSeamlessly(oldRotation,
1008                 rotation);
1009 
1010         if (mayRotateSeamlessly) {
1011             final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated);
1012             if (seamlessRotated != null && !forceUpdate) {
1013                 // We can't rotate (seamlessly or not) while waiting for the last seamless rotation
1014                 // to complete (that is, waiting for windows to redraw). It's tempting to check
1015                 // w.mSeamlessRotationCount but that could be incorrect in the case of
1016                 // window-removal.
1017                 return false;
1018             }
1019 
1020             // In the presence of the PINNED stack or System Alert
1021             // windows we unfortunately can not seamlessly rotate.
1022             if (hasPinnedStack()) {
1023                 mayRotateSeamlessly = false;
1024             }
1025             for (int i = 0; i < mService.mSessions.size(); i++) {
1026                 if (mService.mSessions.valueAt(i).hasAlertWindowSurfaces()) {
1027                     mayRotateSeamlessly = false;
1028                     break;
1029                 }
1030             }
1031         }
1032         final boolean rotateSeamlessly = mayRotateSeamlessly;
1033 
1034         // TODO: Implement forced rotation changes.
1035         //       Set mAltOrientation to indicate that the application is receiving
1036         //       an orientation that has different metrics than it expected.
1037         //       eg. Portrait instead of Landscape.
1038 
1039         final boolean altOrientation = !mService.mPolicy.rotationHasCompatibleMetricsLw(
1040                 lastOrientation, rotation);
1041 
1042         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
1043                 + " selected orientation " + lastOrientation
1044                 + ", got rotation " + rotation + " which has "
1045                 + (altOrientation ? "incompatible" : "compatible") + " metrics");
1046 
1047         if (oldRotation == rotation && oldAltOrientation == altOrientation) {
1048             // No change.
1049             return false;
1050         }
1051 
1052         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
1053                 + " rotation changed to " + rotation
1054                 + (altOrientation ? " (alt)" : "") + " from " + oldRotation
1055                 + (oldAltOrientation ? " (alt)" : "") + ", lastOrientation=" + lastOrientation);
1056 
1057         if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) {
1058             mService.mWaitingForConfig = true;
1059         }
1060 
1061         mRotation = rotation;
1062         mAltOrientation = altOrientation;
1063         if (isDefaultDisplay) {
1064             mService.mPolicy.setRotationLw(rotation);
1065         }
1066 
1067         mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
1068         mService.mH.removeMessages(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT);
1069         mService.mH.sendEmptyMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
1070                 WINDOW_FREEZE_TIMEOUT_DURATION);
1071 
1072         setLayoutNeeded();
1073         final int[] anim = new int[2];
1074         mService.mPolicy.selectRotationAnimationLw(anim);
1075 
1076         if (!rotateSeamlessly) {
1077             mService.startFreezingDisplayLocked(anim[0], anim[1], this);
1078             // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
1079             screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
1080                     mDisplayId);
1081         } else {
1082             // The screen rotation animation uses a screenshot to freeze the screen
1083             // while windows resize underneath.
1084             // When we are rotating seamlessly, we allow the elements to transition
1085             // to their rotated state independently and without a freeze required.
1086             screenRotationAnimation = null;
1087 
1088             mService.startSeamlessRotation();
1089         }
1090 
1091         // We need to update our screen size information to match the new rotation. If the rotation
1092         // has actually changed then this method will return true and, according to the comment at
1093         // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
1094         // By updating the Display info here it will be available to
1095         // #computeScreenConfiguration() later.
1096         updateDisplayAndOrientation(getConfiguration().uiMode);
1097 
1098         // NOTE: We disable the rotation in the emulator because
1099         //       it doesn't support hardware OpenGL emulation yet.
1100         if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
1101                 && screenRotationAnimation.hasScreenshot()) {
1102             if (screenRotationAnimation.setRotation(getPendingTransaction(), rotation,
1103                     MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(),
1104                     mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
1105                 mService.scheduleAnimationLocked();
1106             }
1107         }
1108 
1109         if (rotateSeamlessly) {
1110             forAllWindows(w -> {
1111                     w.mWinAnimator.seamlesslyRotateWindow(getPendingTransaction(),
1112                             oldRotation, rotation);
1113             }, true /* traverseTopToBottom */);
1114         }
1115 
1116         mService.mDisplayManagerInternal.performTraversal(getPendingTransaction());
1117         scheduleAnimation();
1118 
1119         forAllWindows(w -> {
1120             if (w.mHasSurface && !rotateSeamlessly) {
1121                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
1122                 w.setOrientationChanging(true);
1123                 mService.mRoot.mOrientationChangeComplete = false;
1124                 w.mLastFreezeDuration = 0;
1125             }
1126             w.mReportOrientationChanged = true;
1127         }, true /* traverseTopToBottom */);
1128 
1129         if (rotateSeamlessly) {
1130             mService.mH.removeMessages(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT);
1131             mService.mH.sendEmptyMessageDelayed(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT,
1132                     SEAMLESS_ROTATION_TIMEOUT_DURATION);
1133         }
1134 
1135         for (int i = mService.mRotationWatchers.size() - 1; i >= 0; i--) {
1136             final WindowManagerService.RotationWatcher rotationWatcher
1137                     = mService.mRotationWatchers.get(i);
1138             if (rotationWatcher.mDisplayId == mDisplayId) {
1139                 try {
1140                     rotationWatcher.mWatcher.onRotationChanged(rotation);
1141                 } catch (RemoteException e) {
1142                     // Ignore
1143                 }
1144             }
1145         }
1146 
1147         // TODO (multi-display): Magnification is supported only for the default display.
1148         // Announce rotation only if we will not animate as we already have the
1149         // windows in final state. Otherwise, we make this call at the rotation end.
1150         if (screenRotationAnimation == null && mService.mAccessibilityController != null
1151                 && isDefaultDisplay) {
1152             mService.mAccessibilityController.onRotationChangedLocked(this);
1153         }
1154 
1155         return true;
1156     }
1157 
configureDisplayPolicy()1158     void configureDisplayPolicy() {
1159         mService.mPolicy.setInitialDisplaySize(getDisplay(),
1160                 mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity);
1161 
1162         mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
1163                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
1164     }
1165 
1166     /**
1167      * Update {@link #mDisplayInfo} and other internal variables when display is rotated or config
1168      * changed.
1169      * Do not call if {@link WindowManagerService#mDisplayReady} == false.
1170      */
updateDisplayAndOrientation(int uiMode)1171     private DisplayInfo updateDisplayAndOrientation(int uiMode) {
1172         // Use the effective "visual" dimensions based on current rotation
1173         final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270);
1174         final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
1175         final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
1176         int dw = realdw;
1177         int dh = realdh;
1178 
1179         if (mAltOrientation) {
1180             if (realdw > realdh) {
1181                 // Turn landscape into portrait.
1182                 int maxw = (int)(realdh/1.3f);
1183                 if (maxw < realdw) {
1184                     dw = maxw;
1185                 }
1186             } else {
1187                 // Turn portrait into landscape.
1188                 int maxh = (int)(realdw/1.3f);
1189                 if (maxh < realdh) {
1190                     dh = maxh;
1191                 }
1192             }
1193         }
1194 
1195         // Update application display metrics.
1196         final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(mRotation);
1197         final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout();
1198 
1199         final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode,
1200                 mDisplayId, displayCutout);
1201         final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode,
1202                 mDisplayId, displayCutout);
1203         mDisplayInfo.rotation = mRotation;
1204         mDisplayInfo.logicalWidth = dw;
1205         mDisplayInfo.logicalHeight = dh;
1206         mDisplayInfo.logicalDensityDpi = mBaseDisplayDensity;
1207         mDisplayInfo.appWidth = appWidth;
1208         mDisplayInfo.appHeight = appHeight;
1209         if (isDefaultDisplay) {
1210             mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics,
1211                     CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
1212         }
1213         mDisplayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout;
1214         mDisplayInfo.getAppMetrics(mDisplayMetrics);
1215         if (mDisplayScalingDisabled) {
1216             mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED;
1217         } else {
1218             mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
1219         }
1220 
1221         // We usually set the override info in DisplayManager so that we get consistent display
1222         // metrics values when displays are changing and don't send out new values until WM is aware
1223         // of them. However, we don't do this for displays that serve as containers for ActivityView
1224         // because we don't want letter-/pillar-boxing during resize.
1225         final DisplayInfo overrideDisplayInfo = mShouldOverrideDisplayConfiguration
1226                 ? mDisplayInfo : null;
1227         mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
1228                 overrideDisplayInfo);
1229 
1230         mBaseDisplayRect.set(0, 0, dw, dh);
1231 
1232         if (isDefaultDisplay) {
1233             mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
1234                     mCompatDisplayMetrics);
1235         }
1236 
1237         updateBounds();
1238         return mDisplayInfo;
1239     }
1240 
calculateDisplayCutoutForRotation(int rotation)1241     WmDisplayCutout calculateDisplayCutoutForRotation(int rotation) {
1242         return mDisplayCutoutCache.getOrCompute(mInitialDisplayCutout, rotation);
1243     }
1244 
calculateDisplayCutoutForRotationUncached( DisplayCutout cutout, int rotation)1245     private WmDisplayCutout calculateDisplayCutoutForRotationUncached(
1246             DisplayCutout cutout, int rotation) {
1247         if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) {
1248             return WmDisplayCutout.NO_CUTOUT;
1249         }
1250         if (rotation == ROTATION_0) {
1251             return WmDisplayCutout.computeSafeInsets(
1252                     cutout, mInitialDisplayWidth, mInitialDisplayHeight);
1253         }
1254         final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
1255         final Path bounds = cutout.getBounds().getBoundaryPath();
1256         transformPhysicalToLogicalCoordinates(rotation, mInitialDisplayWidth, mInitialDisplayHeight,
1257                 mTmpMatrix);
1258         bounds.transform(mTmpMatrix);
1259         return WmDisplayCutout.computeSafeInsets(DisplayCutout.fromBounds(bounds),
1260                 rotated ? mInitialDisplayHeight : mInitialDisplayWidth,
1261                 rotated ? mInitialDisplayWidth : mInitialDisplayHeight);
1262     }
1263 
1264     /**
1265      * Compute display configuration based on display properties and policy settings.
1266      * Do not call if mDisplayReady == false.
1267      */
computeScreenConfiguration(Configuration config)1268     void computeScreenConfiguration(Configuration config) {
1269         final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode);
1270 
1271         final int dw = displayInfo.logicalWidth;
1272         final int dh = displayInfo.logicalHeight;
1273         config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
1274         // TODO: Probably best to set this based on some setting in the display content object,
1275         // so the display can be configured for things like fullscreen.
1276         config.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
1277 
1278         final float density = mDisplayMetrics.density;
1279         config.screenWidthDp =
1280                 (int)(mService.mPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation,
1281                         config.uiMode, mDisplayId, displayInfo.displayCutout) / density);
1282         config.screenHeightDp =
1283                 (int)(mService.mPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation,
1284                         config.uiMode, mDisplayId, displayInfo.displayCutout) / density);
1285 
1286         mService.mPolicy.getNonDecorInsetsLw(displayInfo.rotation, dw, dh,
1287                 displayInfo.displayCutout, mTmpRect);
1288         final int leftInset = mTmpRect.left;
1289         final int topInset = mTmpRect.top;
1290         // appBounds at the root level should mirror the app screen size.
1291         config.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */,
1292                 leftInset + displayInfo.appWidth /* right */,
1293                 topInset + displayInfo.appHeight /* bottom */);
1294         final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90
1295                 || displayInfo.rotation == Surface.ROTATION_270);
1296 
1297         computeSizeRangesAndScreenLayout(displayInfo, mDisplayId, rotated, config.uiMode, dw, dh,
1298                 density, config);
1299 
1300         config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
1301                 | ((displayInfo.flags & Display.FLAG_ROUND) != 0
1302                 ? Configuration.SCREENLAYOUT_ROUND_YES
1303                 : Configuration.SCREENLAYOUT_ROUND_NO);
1304 
1305         config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
1306         config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
1307         config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, dw,
1308                 dh, mDisplayId);
1309         config.densityDpi = displayInfo.logicalDensityDpi;
1310 
1311         config.colorMode =
1312                 (displayInfo.isHdr()
1313                         ? Configuration.COLOR_MODE_HDR_YES
1314                         : Configuration.COLOR_MODE_HDR_NO)
1315                         | (displayInfo.isWideColorGamut() && mService.hasWideColorGamutSupport()
1316                         ? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES
1317                         : Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO);
1318 
1319         // Update the configuration based on available input devices, lid switch,
1320         // and platform configuration.
1321         config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
1322         config.keyboard = Configuration.KEYBOARD_NOKEYS;
1323         config.navigation = Configuration.NAVIGATION_NONAV;
1324 
1325         int keyboardPresence = 0;
1326         int navigationPresence = 0;
1327         final InputDevice[] devices = mService.mInputManager.getInputDevices();
1328         final int len = devices != null ? devices.length : 0;
1329         for (int i = 0; i < len; i++) {
1330             InputDevice device = devices[i];
1331             if (!device.isVirtual()) {
1332                 final int sources = device.getSources();
1333                 final int presenceFlag = device.isExternal() ?
1334                         WindowManagerPolicy.PRESENCE_EXTERNAL :
1335                         WindowManagerPolicy.PRESENCE_INTERNAL;
1336 
1337                 // TODO(multi-display): Configure on per-display basis.
1338                 if (mService.mIsTouchDevice) {
1339                     if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
1340                             InputDevice.SOURCE_TOUCHSCREEN) {
1341                         config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
1342                     }
1343                 } else {
1344                     config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
1345                 }
1346 
1347                 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
1348                     config.navigation = Configuration.NAVIGATION_TRACKBALL;
1349                     navigationPresence |= presenceFlag;
1350                 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
1351                         && config.navigation == Configuration.NAVIGATION_NONAV) {
1352                     config.navigation = Configuration.NAVIGATION_DPAD;
1353                     navigationPresence |= presenceFlag;
1354                 }
1355 
1356                 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
1357                     config.keyboard = Configuration.KEYBOARD_QWERTY;
1358                     keyboardPresence |= presenceFlag;
1359                 }
1360             }
1361         }
1362 
1363         if (config.navigation == Configuration.NAVIGATION_NONAV && mService.mHasPermanentDpad) {
1364             config.navigation = Configuration.NAVIGATION_DPAD;
1365             navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
1366         }
1367 
1368         // Determine whether a hard keyboard is available and enabled.
1369         // TODO(multi-display): Should the hardware keyboard be tied to a display or to a device?
1370         boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
1371         if (hardKeyboardAvailable != mService.mHardKeyboardAvailable) {
1372             mService.mHardKeyboardAvailable = hardKeyboardAvailable;
1373             mService.mH.removeMessages(WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
1374             mService.mH.sendEmptyMessage(WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
1375         }
1376 
1377         // Let the policy update hidden states.
1378         config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
1379         config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
1380         config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
1381         mService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
1382     }
1383 
computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh, int displayId)1384     private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh,
1385             int displayId) {
1386         mTmpDisplayMetrics.setTo(mDisplayMetrics);
1387         final DisplayMetrics tmpDm = mTmpDisplayMetrics;
1388         final int unrotDw, unrotDh;
1389         if (rotated) {
1390             unrotDw = dh;
1391             unrotDh = dw;
1392         } else {
1393             unrotDw = dw;
1394             unrotDh = dh;
1395         }
1396         int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh,
1397                 displayId);
1398         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw,
1399                 displayId);
1400         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh,
1401                 displayId);
1402         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw,
1403                 displayId);
1404         return sw;
1405     }
1406 
reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, DisplayMetrics dm, int dw, int dh, int displayId)1407     private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
1408             DisplayMetrics dm, int dw, int dh, int displayId) {
1409         dm.noncompatWidthPixels = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
1410                 displayId, mDisplayInfo.displayCutout);
1411         dm.noncompatHeightPixels = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
1412                 uiMode, displayId, mDisplayInfo.displayCutout);
1413         float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
1414         int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
1415         if (curSize == 0 || size < curSize) {
1416             curSize = size;
1417         }
1418         return curSize;
1419     }
1420 
computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, int displayId, boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig)1421     private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, int displayId,
1422             boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig) {
1423 
1424         // We need to determine the smallest width that will occur under normal
1425         // operation.  To this, start with the base screen size and compute the
1426         // width under the different possible rotations.  We need to un-rotate
1427         // the current screen dimensions before doing this.
1428         int unrotDw, unrotDh;
1429         if (rotated) {
1430             unrotDw = dh;
1431             unrotDh = dw;
1432         } else {
1433             unrotDw = dw;
1434             unrotDh = dh;
1435         }
1436         displayInfo.smallestNominalAppWidth = 1<<30;
1437         displayInfo.smallestNominalAppHeight = 1<<30;
1438         displayInfo.largestNominalAppWidth = 0;
1439         displayInfo.largestNominalAppHeight = 0;
1440         adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_0, uiMode, unrotDw,
1441                 unrotDh);
1442         adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_90, uiMode, unrotDh,
1443                 unrotDw);
1444         adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_180, uiMode, unrotDw,
1445                 unrotDh);
1446         adjustDisplaySizeRanges(displayInfo, displayId, Surface.ROTATION_270, uiMode, unrotDh,
1447                 unrotDw);
1448         int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
1449         sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode,
1450                 displayId);
1451         sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode,
1452                 displayId);
1453         sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode,
1454                 displayId);
1455         sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode,
1456                 displayId);
1457         outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
1458         outConfig.screenLayout = sl;
1459     }
1460 
reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, int uiMode, int displayId)1461     private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh,
1462             int uiMode, int displayId) {
1463         // Get the app screen size at this rotation.
1464         int w = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayId,
1465                 mDisplayInfo.displayCutout);
1466         int h = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayId,
1467                 mDisplayInfo.displayCutout);
1468 
1469         // Compute the screen layout size class for this rotation.
1470         int longSize = w;
1471         int shortSize = h;
1472         if (longSize < shortSize) {
1473             int tmp = longSize;
1474             longSize = shortSize;
1475             shortSize = tmp;
1476         }
1477         longSize = (int)(longSize/density);
1478         shortSize = (int)(shortSize/density);
1479         return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
1480     }
1481 
adjustDisplaySizeRanges(DisplayInfo displayInfo, int displayId, int rotation, int uiMode, int dw, int dh)1482     private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int displayId, int rotation,
1483             int uiMode, int dw, int dh) {
1484         final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
1485                 rotation).getDisplayCutout();
1486         final int width = mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode,
1487                 displayId, displayCutout);
1488         if (width < displayInfo.smallestNominalAppWidth) {
1489             displayInfo.smallestNominalAppWidth = width;
1490         }
1491         if (width > displayInfo.largestNominalAppWidth) {
1492             displayInfo.largestNominalAppWidth = width;
1493         }
1494         final int height = mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode,
1495                 displayId, displayCutout);
1496         if (height < displayInfo.smallestNominalAppHeight) {
1497             displayInfo.smallestNominalAppHeight = height;
1498         }
1499         if (height > displayInfo.largestNominalAppHeight) {
1500             displayInfo.largestNominalAppHeight = height;
1501         }
1502     }
1503 
getDockedDividerController()1504     DockedStackDividerController getDockedDividerController() {
1505         return mDividerControllerLocked;
1506     }
1507 
getPinnedStackController()1508     PinnedStackController getPinnedStackController() {
1509         return mPinnedStackControllerLocked;
1510     }
1511 
1512     /**
1513      * Returns true if the specified UID has access to this display.
1514      */
hasAccess(int uid)1515     boolean hasAccess(int uid) {
1516         return mDisplay.hasAccess(uid);
1517     }
1518 
isPrivate()1519     boolean isPrivate() {
1520         return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
1521     }
1522 
getHomeStack()1523     TaskStack getHomeStack() {
1524         return mTaskStackContainers.getHomeStack();
1525     }
1526 
1527     /**
1528      * @return The primary split-screen stack, but only if it is visible, and {@code null} otherwise.
1529      */
getSplitScreenPrimaryStack()1530     TaskStack getSplitScreenPrimaryStack() {
1531         TaskStack stack = mTaskStackContainers.getSplitScreenPrimaryStack();
1532         return (stack != null && stack.isVisible()) ? stack : null;
1533     }
1534 
hasSplitScreenPrimaryStack()1535     boolean hasSplitScreenPrimaryStack() {
1536         return getSplitScreenPrimaryStack() != null;
1537     }
1538 
1539     /**
1540      * Like {@link #getSplitScreenPrimaryStack}, but also returns the stack if it's currently
1541      * not visible.
1542      */
getSplitScreenPrimaryStackIgnoringVisibility()1543     TaskStack getSplitScreenPrimaryStackIgnoringVisibility() {
1544         return mTaskStackContainers.getSplitScreenPrimaryStack();
1545     }
1546 
getPinnedStack()1547     TaskStack getPinnedStack() {
1548         return mTaskStackContainers.getPinnedStack();
1549     }
1550 
hasPinnedStack()1551     private boolean hasPinnedStack() {
1552         return mTaskStackContainers.getPinnedStack() != null;
1553     }
1554 
1555     /**
1556      * Returns the topmost stack on the display that is compatible with the input windowing mode.
1557      * Null is no compatible stack on the display.
1558      */
getTopStackInWindowingMode(int windowingMode)1559     TaskStack getTopStackInWindowingMode(int windowingMode) {
1560         return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED);
1561     }
1562 
1563     /**
1564      * Returns the topmost stack on the display that is compatible with the input windowing mode and
1565      * activity type. Null is no compatible stack on the display.
1566      */
getStack(int windowingMode, int activityType)1567     TaskStack getStack(int windowingMode, int activityType) {
1568         return mTaskStackContainers.getStack(windowingMode, activityType);
1569     }
1570 
1571     @VisibleForTesting
getTopStack()1572     TaskStack getTopStack() {
1573         return mTaskStackContainers.getTopStack();
1574     }
1575 
getVisibleTasks()1576     ArrayList<Task> getVisibleTasks() {
1577         return mTaskStackContainers.getVisibleTasks();
1578     }
1579 
onStackWindowingModeChanged(TaskStack stack)1580     void onStackWindowingModeChanged(TaskStack stack) {
1581         mTaskStackContainers.onStackWindowingModeChanged(stack);
1582     }
1583 
1584     @Override
onConfigurationChanged(Configuration newParentConfig)1585     public void onConfigurationChanged(Configuration newParentConfig) {
1586         super.onConfigurationChanged(newParentConfig);
1587 
1588         // The display size information is heavily dependent on the resources in the current
1589         // configuration, so we need to reconfigure it every time the configuration changes.
1590         // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
1591         mService.reconfigureDisplayLocked(this);
1592 
1593         final DockedStackDividerController dividerController = getDockedDividerController();
1594 
1595         if (dividerController != null) {
1596             getDockedDividerController().onConfigurationChanged();
1597         }
1598 
1599         final PinnedStackController pinnedStackController = getPinnedStackController();
1600 
1601         if (pinnedStackController != null) {
1602             getPinnedStackController().onConfigurationChanged();
1603         }
1604     }
1605 
1606     /**
1607      * Callback used to trigger bounds update after configuration change and get ids of stacks whose
1608      * bounds were updated.
1609      */
updateStackBoundsAfterConfigChange(@onNull List<TaskStack> changedStackList)1610     void updateStackBoundsAfterConfigChange(@NonNull List<TaskStack> changedStackList) {
1611         for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
1612             final TaskStack stack = mTaskStackContainers.getChildAt(i);
1613             if (stack.updateBoundsAfterConfigChange()) {
1614                 changedStackList.add(stack);
1615             }
1616         }
1617 
1618         // If there was no pinned stack, we still need to notify the controller of the display info
1619         // update as a result of the config change.  We do this here to consolidate the flow between
1620         // changes when there is and is not a stack.
1621         if (!hasPinnedStack()) {
1622             mPinnedStackControllerLocked.onDisplayInfoChanged();
1623         }
1624     }
1625 
1626     @Override
fillsParent()1627     boolean fillsParent() {
1628         return true;
1629     }
1630 
1631     @Override
isVisible()1632     boolean isVisible() {
1633         return true;
1634     }
1635 
1636     @Override
onAppTransitionDone()1637     void onAppTransitionDone() {
1638         super.onAppTransitionDone();
1639         mService.mWindowsChanged = true;
1640     }
1641 
1642     /**
1643      * In split-screen mode we process the IME containers above the docked divider
1644      * rather than directly above their target.
1645      */
skipTraverseChild(WindowContainer child)1646     private boolean skipTraverseChild(WindowContainer child) {
1647         if (child == mImeWindowsContainers && mService.mInputMethodTarget != null
1648                 && !hasSplitScreenPrimaryStack()) {
1649             return true;
1650         }
1651         return false;
1652     }
1653 
1654     @Override
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)1655     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
1656         // Special handling so we can process IME windows with #forAllImeWindows above their IME
1657         // target, or here in order if there isn't an IME target.
1658         if (traverseTopToBottom) {
1659             for (int i = mChildren.size() - 1; i >= 0; --i) {
1660                 final DisplayChildWindowContainer child = mChildren.get(i);
1661                 if (skipTraverseChild(child)) {
1662                     continue;
1663                 }
1664 
1665                 if (child.forAllWindows(callback, traverseTopToBottom)) {
1666                     return true;
1667                 }
1668             }
1669         } else {
1670             final int count = mChildren.size();
1671             for (int i = 0; i < count; i++) {
1672                 final DisplayChildWindowContainer child = mChildren.get(i);
1673                 if (skipTraverseChild(child)) {
1674                     continue;
1675                 }
1676 
1677                 if (child.forAllWindows(callback, traverseTopToBottom)) {
1678                     return true;
1679                 }
1680             }
1681         }
1682         return false;
1683     }
1684 
forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)1685     boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
1686         return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
1687     }
1688 
1689     @Override
getOrientation()1690     int getOrientation() {
1691         final WindowManagerPolicy policy = mService.mPolicy;
1692 
1693         if (mService.mDisplayFrozen) {
1694             if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
1695                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
1696                         + " is frozen, return " + mLastWindowForcedOrientation);
1697                 // If the display is frozen, some activities may be in the middle of restarting, and
1698                 // thus have removed their old window. If the window has the flag to hide the lock
1699                 // screen, then the lock screen can re-appear and inflict its own orientation on us.
1700                 // Keep the orientation stable until this all settles down.
1701                 return mLastWindowForcedOrientation;
1702             } else if (policy.isKeyguardLocked()) {
1703                 // Use the last orientation the while the display is frozen with the keyguard
1704                 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED
1705                 // window. We don't want to check the show when locked window directly though as
1706                 // things aren't stable while the display is frozen, for example the window could be
1707                 // momentarily unavailable due to activity relaunch.
1708                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
1709                         + " is frozen while keyguard locked, return " + mLastOrientation);
1710                 return mLastOrientation;
1711             }
1712         } else {
1713             final int orientation = mAboveAppWindowsContainers.getOrientation();
1714             if (orientation != SCREEN_ORIENTATION_UNSET) {
1715                 return orientation;
1716             }
1717         }
1718 
1719         // Top system windows are not requesting an orientation. Start searching from apps.
1720         return mTaskStackContainers.getOrientation();
1721     }
1722 
updateDisplayInfo()1723     void updateDisplayInfo() {
1724         // Check if display metrics changed and update base values if needed.
1725         updateBaseDisplayMetricsIfNeeded();
1726 
1727         mDisplay.getDisplayInfo(mDisplayInfo);
1728         mDisplay.getMetrics(mDisplayMetrics);
1729 
1730         for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
1731             mTaskStackContainers.getChildAt(i).updateDisplayInfo(null);
1732         }
1733     }
1734 
initializeDisplayBaseInfo()1735     void initializeDisplayBaseInfo() {
1736         final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal;
1737         if (displayManagerInternal != null) {
1738             // Bootstrap the default logical display from the display manager.
1739             final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
1740             if (newDisplayInfo != null) {
1741                 mDisplayInfo.copyFrom(newDisplayInfo);
1742             }
1743         }
1744 
1745         updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
1746                 mDisplayInfo.logicalDensityDpi);
1747         mInitialDisplayWidth = mDisplayInfo.logicalWidth;
1748         mInitialDisplayHeight = mDisplayInfo.logicalHeight;
1749         mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
1750         mInitialDisplayCutout = mDisplayInfo.displayCutout;
1751     }
1752 
1753     /**
1754      * If display metrics changed, overrides are not set and it's not just a rotation - update base
1755      * values.
1756      */
updateBaseDisplayMetricsIfNeeded()1757     private void updateBaseDisplayMetricsIfNeeded() {
1758         // Get real display metrics without overrides from WM.
1759         mService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo);
1760         final int orientation = mDisplayInfo.rotation;
1761         final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
1762         final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
1763         final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
1764         final int newDensity = mDisplayInfo.logicalDensityDpi;
1765         final DisplayCutout newCutout = mDisplayInfo.displayCutout;
1766 
1767         final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth
1768                 || mInitialDisplayHeight != newHeight
1769                 || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi
1770                 || !Objects.equals(mInitialDisplayCutout, newCutout);
1771 
1772         if (displayMetricsChanged) {
1773             // Check if display size or density is forced.
1774             final boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth
1775                     || mBaseDisplayHeight != mInitialDisplayHeight;
1776             final boolean isDisplayDensityForced = mBaseDisplayDensity != mInitialDisplayDensity;
1777 
1778             // If there is an override set for base values - use it, otherwise use new values.
1779             updateBaseDisplayMetrics(isDisplaySizeForced ? mBaseDisplayWidth : newWidth,
1780                     isDisplaySizeForced ? mBaseDisplayHeight : newHeight,
1781                     isDisplayDensityForced ? mBaseDisplayDensity : newDensity);
1782 
1783             // Real display metrics changed, so we should also update initial values.
1784             mInitialDisplayWidth = newWidth;
1785             mInitialDisplayHeight = newHeight;
1786             mInitialDisplayDensity = newDensity;
1787             mInitialDisplayCutout = newCutout;
1788             mService.reconfigureDisplayLocked(this);
1789         }
1790     }
1791 
1792     /** Sets the maximum width the screen resolution can be */
setMaxUiWidth(int width)1793     void setMaxUiWidth(int width) {
1794         if (DEBUG_DISPLAY) {
1795             Slog.v(TAG_WM, "Setting max ui width:" + width + " on display:" + getDisplayId());
1796         }
1797 
1798         mMaxUiWidth = width;
1799 
1800         // Update existing metrics.
1801         updateBaseDisplayMetrics(mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity);
1802     }
1803 
1804     /** Update base (override) display metrics. */
updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity)1805     void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) {
1806         mBaseDisplayWidth = baseWidth;
1807         mBaseDisplayHeight = baseHeight;
1808         mBaseDisplayDensity = baseDensity;
1809 
1810         if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) {
1811             mBaseDisplayHeight = (mMaxUiWidth * mBaseDisplayHeight) / mBaseDisplayWidth;
1812             mBaseDisplayDensity = (mMaxUiWidth * mBaseDisplayDensity) / mBaseDisplayWidth;
1813             mBaseDisplayWidth = mMaxUiWidth;
1814 
1815             if (DEBUG_DISPLAY) {
1816                 Slog.v(TAG_WM, "Applying config restraints:" + mBaseDisplayWidth + "x"
1817                         + mBaseDisplayHeight + " at density:" + mBaseDisplayDensity
1818                         + " on display:" + getDisplayId());
1819             }
1820         }
1821 
1822         mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
1823 
1824         updateBounds();
1825     }
1826 
getStableRect(Rect out)1827     void getStableRect(Rect out) {
1828         out.set(mDisplayFrames.mStable);
1829     }
1830 
createStack(int stackId, boolean onTop, StackWindowController controller)1831     TaskStack createStack(int stackId, boolean onTop, StackWindowController controller) {
1832         if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
1833                 + mDisplayId);
1834 
1835         final TaskStack stack = new TaskStack(mService, stackId, controller);
1836         mTaskStackContainers.addStackToDisplay(stack, onTop);
1837         return stack;
1838     }
1839 
moveStackToDisplay(TaskStack stack, boolean onTop)1840     void moveStackToDisplay(TaskStack stack, boolean onTop) {
1841         final DisplayContent prevDc = stack.getDisplayContent();
1842         if (prevDc == null) {
1843             throw new IllegalStateException("Trying to move stackId=" + stack.mStackId
1844                     + " which is not currently attached to any display");
1845         }
1846         if (prevDc.getDisplayId() == mDisplayId) {
1847             throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId
1848                     + " to its current displayId=" + mDisplayId);
1849         }
1850 
1851         prevDc.mTaskStackContainers.removeChild(stack);
1852         mTaskStackContainers.addStackToDisplay(stack, onTop);
1853     }
1854 
1855     @Override
addChild(DisplayChildWindowContainer child, Comparator<DisplayChildWindowContainer> comparator)1856     protected void addChild(DisplayChildWindowContainer child,
1857             Comparator<DisplayChildWindowContainer> comparator) {
1858         throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1859     }
1860 
1861     @Override
addChild(DisplayChildWindowContainer child, int index)1862     protected void addChild(DisplayChildWindowContainer child, int index) {
1863         throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1864     }
1865 
1866     @Override
removeChild(DisplayChildWindowContainer child)1867     protected void removeChild(DisplayChildWindowContainer child) {
1868         // Only allow removal of direct children from this display if the display is in the process
1869         // of been removed.
1870         if (mRemovingDisplay) {
1871             super.removeChild(child);
1872             return;
1873         }
1874         throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1875     }
1876 
1877     @Override
positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents)1878     void positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents) {
1879         // Children of the display are statically ordered, so the real intention here is to perform
1880         // the operation on the display and not the static direct children.
1881         getParent().positionChildAt(position, this, includingParents);
1882     }
1883 
positionStackAt(int position, TaskStack child)1884     void positionStackAt(int position, TaskStack child) {
1885         mTaskStackContainers.positionChildAt(position, child, false /* includingParents */);
1886         layoutAndAssignWindowLayersIfNeeded();
1887     }
1888 
taskIdFromPoint(int x, int y)1889     int taskIdFromPoint(int x, int y) {
1890         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1891             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
1892             final int taskId = stack.taskIdFromPoint(x, y);
1893             if (taskId != -1) {
1894                 return taskId;
1895             }
1896         }
1897         return -1;
1898     }
1899 
1900     /**
1901      * Find the task whose outside touch area (for resizing) (x, y) falls within.
1902      * Returns null if the touch doesn't fall into a resizing area.
1903      */
findTaskForResizePoint(int x, int y)1904     Task findTaskForResizePoint(int x, int y) {
1905         final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
1906         mTmpTaskForResizePointSearchResult.reset();
1907         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1908             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
1909             if (!stack.getWindowConfiguration().canResizeTask()) {
1910                 return null;
1911             }
1912 
1913             stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult);
1914             if (mTmpTaskForResizePointSearchResult.searchDone) {
1915                 return mTmpTaskForResizePointSearchResult.taskForResize;
1916             }
1917         }
1918         return null;
1919     }
1920 
setTouchExcludeRegion(Task focusedTask)1921     void setTouchExcludeRegion(Task focusedTask) {
1922         // The provided task is the task on this display with focus, so if WindowManagerService's
1923         // focused app is not on this display, focusedTask will be null.
1924         if (focusedTask == null) {
1925             mTouchExcludeRegion.setEmpty();
1926         } else {
1927             mTouchExcludeRegion.set(mBaseDisplayRect);
1928             final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
1929             mTmpRect2.setEmpty();
1930             for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1931                 final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
1932                 stack.setTouchExcludeRegion(focusedTask, delta, mTouchExcludeRegion,
1933                         mDisplayFrames.mContent, mTmpRect2);
1934             }
1935             // If we removed the focused task above, add it back and only leave its
1936             // outside touch area in the exclusion. TapDectector is not interested in
1937             // any touch inside the focused task itself.
1938             if (!mTmpRect2.isEmpty()) {
1939                 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
1940             }
1941         }
1942         final WindowState inputMethod = mService.mInputMethodWindow;
1943         if (inputMethod != null && inputMethod.isVisibleLw()) {
1944             // If the input method is visible and the user is typing, we don't want these touch
1945             // events to be intercepted and used to change focus. This would likely cause a
1946             // disappearance of the input method.
1947             inputMethod.getTouchableRegion(mTmpRegion);
1948             if (inputMethod.getDisplayId() == mDisplayId) {
1949                 mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
1950             } else {
1951                 // IME is on a different display, so we need to update its tap detector.
1952                 // TODO(multidisplay): Remove when IME will always appear on same display.
1953                 inputMethod.getDisplayContent().setTouchExcludeRegion(null /* focusedTask */);
1954             }
1955         }
1956         for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
1957             final WindowState win = mTapExcludedWindows.get(i);
1958             win.getTouchableRegion(mTmpRegion);
1959             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
1960         }
1961         for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
1962             final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
1963             win.amendTapExcludeRegion(mTouchExcludeRegion);
1964         }
1965         // TODO(multi-display): Support docked stacks on secondary displays.
1966         if (mDisplayId == DEFAULT_DISPLAY && getSplitScreenPrimaryStack() != null) {
1967             mDividerControllerLocked.getTouchRegion(mTmpRect);
1968             mTmpRegion.set(mTmpRect);
1969             mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
1970         }
1971         if (mTapDetector != null) {
1972             mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
1973         }
1974     }
1975 
1976     @Override
switchUser()1977     void switchUser() {
1978         super.switchUser();
1979         mService.mWindowsChanged = true;
1980     }
1981 
resetAnimationBackgroundAnimator()1982     private void resetAnimationBackgroundAnimator() {
1983         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1984             mTaskStackContainers.getChildAt(stackNdx).resetAnimationBackgroundAnimator();
1985         }
1986     }
1987 
1988     @Override
removeIfPossible()1989     void removeIfPossible() {
1990         if (isAnimating()) {
1991             mDeferredRemoval = true;
1992             return;
1993         }
1994         removeImmediately();
1995     }
1996 
1997     @Override
removeImmediately()1998     void removeImmediately() {
1999         mRemovingDisplay = true;
2000         try {
2001             super.removeImmediately();
2002             if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
2003             if (mService.canDispatchPointerEvents()) {
2004                 if (mTapDetector != null) {
2005                     mService.unregisterPointerEventListener(mTapDetector);
2006                 }
2007                 if (mDisplayId == DEFAULT_DISPLAY && mService.mMousePositionTracker != null) {
2008                     mService.unregisterPointerEventListener(mService.mMousePositionTracker);
2009                 }
2010             }
2011             mService.mAnimator.removeDisplayLocked(mDisplayId);
2012         } finally {
2013             mRemovingDisplay = false;
2014         }
2015 
2016         mService.onDisplayRemoved(mDisplayId);
2017     }
2018 
2019     /** Returns true if a removal action is still being deferred. */
2020     @Override
checkCompleteDeferredRemoval()2021     boolean checkCompleteDeferredRemoval() {
2022         final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
2023 
2024         if (!stillDeferringRemoval && mDeferredRemoval) {
2025             removeImmediately();
2026             return false;
2027         }
2028         return true;
2029     }
2030 
2031     /** @return 'true' if removal of this display content is deferred due to active animation. */
isRemovalDeferred()2032     boolean isRemovalDeferred() {
2033         return mDeferredRemoval;
2034     }
2035 
animateForIme(float interpolatedValue, float animationTarget, float dividerAnimationTarget)2036     boolean animateForIme(float interpolatedValue, float animationTarget,
2037             float dividerAnimationTarget) {
2038         boolean updated = false;
2039 
2040         for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
2041             final TaskStack stack = mTaskStackContainers.getChildAt(i);
2042             if (stack == null || !stack.isAdjustedForIme()) {
2043                 continue;
2044             }
2045 
2046             if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) {
2047                 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
2048                 updated = true;
2049             } else {
2050                 mDividerControllerLocked.mLastAnimationProgress =
2051                         mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue);
2052                 mDividerControllerLocked.mLastDividerProgress =
2053                         mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue);
2054                 updated |= stack.updateAdjustForIme(
2055                         mDividerControllerLocked.mLastAnimationProgress,
2056                         mDividerControllerLocked.mLastDividerProgress,
2057                         false /* force */);
2058             }
2059             if (interpolatedValue >= 1f) {
2060                 stack.endImeAdjustAnimation();
2061             }
2062         }
2063 
2064         return updated;
2065     }
2066 
clearImeAdjustAnimation()2067     boolean clearImeAdjustAnimation() {
2068         boolean changed = false;
2069         for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
2070             final TaskStack stack = mTaskStackContainers.getChildAt(i);
2071             if (stack != null && stack.isAdjustedForIme()) {
2072                 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
2073                 changed  = true;
2074             }
2075         }
2076         return changed;
2077     }
2078 
beginImeAdjustAnimation()2079     void beginImeAdjustAnimation() {
2080         for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
2081             final TaskStack stack = mTaskStackContainers.getChildAt(i);
2082             if (stack.isVisible() && stack.isAdjustedForIme()) {
2083                 stack.beginImeAdjustAnimation();
2084             }
2085         }
2086     }
2087 
adjustForImeIfNeeded()2088     void adjustForImeIfNeeded() {
2089         final WindowState imeWin = mService.mInputMethodWindow;
2090         final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
2091                 && !mDividerControllerLocked.isImeHideRequested();
2092         final boolean dockVisible = isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
2093         final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
2094         final int imeDockSide = (dockVisible && imeTargetStack != null) ?
2095                 imeTargetStack.getDockSide() : DOCKED_INVALID;
2096         final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
2097         final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
2098         final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock();
2099         final int imeHeight = mDisplayFrames.getInputMethodWindowVisibleHeight();
2100         final boolean imeHeightChanged = imeVisible &&
2101                 imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
2102 
2103         // The divider could be adjusted for IME position, or be thinner than usual,
2104         // or both. There are three possible cases:
2105         // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
2106         // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
2107         // - If IME is not visible, divider is not moved and is normal width.
2108 
2109         if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
2110             for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
2111                 final TaskStack stack = mTaskStackContainers.getChildAt(i);
2112                 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
2113                 if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)
2114                         && stack.inSplitScreenWindowingMode()) {
2115                     stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
2116                 } else {
2117                     stack.resetAdjustedForIme(false);
2118                 }
2119             }
2120             mDividerControllerLocked.setAdjustedForIme(
2121                     imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
2122         } else {
2123             for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
2124                 final TaskStack stack = mTaskStackContainers.getChildAt(i);
2125                 stack.resetAdjustedForIme(!dockVisible);
2126             }
2127             mDividerControllerLocked.setAdjustedForIme(
2128                     false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
2129         }
2130         mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
2131     }
2132 
2133     /**
2134      * If a window that has an animation specifying a colored background and the current wallpaper
2135      * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
2136      * suddenly disappear.
2137      */
getLayerForAnimationBackground(WindowStateAnimator winAnimator)2138     int getLayerForAnimationBackground(WindowStateAnimator winAnimator) {
2139         final WindowState visibleWallpaper = mBelowAppWindowsContainers.getWindow(
2140                 w -> w.mIsWallpaper && w.isVisibleNow());
2141 
2142         if (visibleWallpaper != null) {
2143             return visibleWallpaper.mWinAnimator.mAnimLayer;
2144         }
2145         return winAnimator.mAnimLayer;
2146     }
2147 
prepareFreezingTaskBounds()2148     void prepareFreezingTaskBounds() {
2149         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2150             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
2151             stack.prepareFreezingTaskBounds();
2152         }
2153     }
2154 
rotateBounds(int oldRotation, int newRotation, Rect bounds)2155     void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
2156         getBounds(mTmpRect, newRotation);
2157 
2158         // Compute a transform matrix to undo the coordinate space transformation,
2159         // and present the window at the same physical position it previously occupied.
2160         final int deltaRotation = deltaRotation(newRotation, oldRotation);
2161         createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
2162 
2163         mTmpRectF.set(bounds);
2164         mTmpMatrix.mapRect(mTmpRectF);
2165         mTmpRectF.round(bounds);
2166     }
2167 
deltaRotation(int oldRotation, int newRotation)2168     static int deltaRotation(int oldRotation, int newRotation) {
2169         int delta = newRotation - oldRotation;
2170         if (delta < 0) delta += 4;
2171         return delta;
2172     }
2173 
createRotationMatrix(int rotation, float displayWidth, float displayHeight, Matrix outMatrix)2174     private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
2175             Matrix outMatrix) {
2176         // For rotations without Z-ordering we don't need the target rectangle's position.
2177         createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
2178                 displayHeight, outMatrix);
2179     }
2180 
createRotationMatrix(int rotation, float rectLeft, float rectTop, float displayWidth, float displayHeight, Matrix outMatrix)2181     static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
2182             float displayWidth, float displayHeight, Matrix outMatrix) {
2183         switch (rotation) {
2184             case ROTATION_0:
2185                 outMatrix.reset();
2186                 break;
2187             case ROTATION_270:
2188                 outMatrix.setRotate(270, 0, 0);
2189                 outMatrix.postTranslate(0, displayHeight);
2190                 outMatrix.postTranslate(rectTop, 0);
2191                 break;
2192             case ROTATION_180:
2193                 outMatrix.reset();
2194                 break;
2195             case ROTATION_90:
2196                 outMatrix.setRotate(90, 0, 0);
2197                 outMatrix.postTranslate(displayWidth, 0);
2198                 outMatrix.postTranslate(-rectTop, rectLeft);
2199                 break;
2200         }
2201     }
2202 
2203     @CallSuper
2204     @Override
writeToProto(ProtoOutputStream proto, long fieldId, boolean trim)2205     public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
2206         final long token = proto.start(fieldId);
2207         super.writeToProto(proto, WINDOW_CONTAINER, trim);
2208         proto.write(ID, mDisplayId);
2209         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2210             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
2211             stack.writeToProto(proto, STACKS, trim);
2212         }
2213         mDividerControllerLocked.writeToProto(proto, DOCKED_STACK_DIVIDER_CONTROLLER);
2214         mPinnedStackControllerLocked.writeToProto(proto, PINNED_STACK_CONTROLLER);
2215         for (int i = mAboveAppWindowsContainers.getChildCount() - 1; i >= 0; --i) {
2216             final WindowToken windowToken = mAboveAppWindowsContainers.getChildAt(i);
2217             windowToken.writeToProto(proto, ABOVE_APP_WINDOWS, trim);
2218         }
2219         for (int i = mBelowAppWindowsContainers.getChildCount() - 1; i >= 0; --i) {
2220             final WindowToken windowToken = mBelowAppWindowsContainers.getChildAt(i);
2221             windowToken.writeToProto(proto, BELOW_APP_WINDOWS, trim);
2222         }
2223         for (int i = mImeWindowsContainers.getChildCount() - 1; i >= 0; --i) {
2224             final WindowToken windowToken = mImeWindowsContainers.getChildAt(i);
2225             windowToken.writeToProto(proto, IME_WINDOWS, trim);
2226         }
2227         proto.write(DPI, mBaseDisplayDensity);
2228         mDisplayInfo.writeToProto(proto, DISPLAY_INFO);
2229         proto.write(ROTATION, mRotation);
2230         final ScreenRotationAnimation screenRotationAnimation =
2231                 mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
2232         if (screenRotationAnimation != null) {
2233             screenRotationAnimation.writeToProto(proto, SCREEN_ROTATION_ANIMATION);
2234         }
2235         mDisplayFrames.writeToProto(proto, DISPLAY_FRAMES);
2236         proto.end(token);
2237     }
2238 
2239     @Override
dump(PrintWriter pw, String prefix, boolean dumpAll)2240     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2241         super.dump(pw, prefix, dumpAll);
2242         pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
2243         final String subPrefix = "  " + prefix;
2244         pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
2245             pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
2246             pw.print("dpi");
2247             if (mInitialDisplayWidth != mBaseDisplayWidth
2248                     || mInitialDisplayHeight != mBaseDisplayHeight
2249                     || mInitialDisplayDensity != mBaseDisplayDensity) {
2250                 pw.print(" base=");
2251                 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
2252                 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
2253             }
2254             if (mDisplayScalingDisabled) {
2255                 pw.println(" noscale");
2256             }
2257             pw.print(" cur=");
2258             pw.print(mDisplayInfo.logicalWidth);
2259             pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
2260             pw.print(" app=");
2261             pw.print(mDisplayInfo.appWidth);
2262             pw.print("x"); pw.print(mDisplayInfo.appHeight);
2263             pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
2264             pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
2265             pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
2266             pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
2267             pw.print(subPrefix + "deferred=" + mDeferredRemoval
2268                     + " mLayoutNeeded=" + mLayoutNeeded);
2269             pw.println(" mTouchExcludeRegion=" + mTouchExcludeRegion);
2270 
2271         pw.println();
2272         pw.print(prefix); pw.print("mLayoutSeq="); pw.println(mLayoutSeq);
2273 
2274         pw.println();
2275         pw.println(prefix + "Application tokens in top down Z order:");
2276         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2277             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
2278             stack.dump(pw, prefix + "  ", dumpAll);
2279         }
2280 
2281         pw.println();
2282         if (!mExitingTokens.isEmpty()) {
2283             pw.println();
2284             pw.println("  Exiting tokens:");
2285             for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
2286                 final WindowToken token = mExitingTokens.get(i);
2287                 pw.print("  Exiting #"); pw.print(i);
2288                 pw.print(' '); pw.print(token);
2289                 pw.println(':');
2290                 token.dump(pw, "    ", dumpAll);
2291             }
2292         }
2293 
2294         pw.println();
2295 
2296         // Dump stack references
2297         final TaskStack homeStack = getHomeStack();
2298         if (homeStack != null) {
2299             pw.println(prefix + "homeStack=" + homeStack.getName());
2300         }
2301         final TaskStack pinnedStack = getPinnedStack();
2302         if (pinnedStack != null) {
2303             pw.println(prefix + "pinnedStack=" + pinnedStack.getName());
2304         }
2305         final TaskStack splitScreenPrimaryStack = getSplitScreenPrimaryStack();
2306         if (splitScreenPrimaryStack != null) {
2307             pw.println(prefix + "splitScreenPrimaryStack=" + splitScreenPrimaryStack.getName());
2308         }
2309 
2310         pw.println();
2311         mDividerControllerLocked.dump(prefix, pw);
2312         pw.println();
2313         mPinnedStackControllerLocked.dump(prefix, pw);
2314 
2315         pw.println();
2316         mDisplayFrames.dump(prefix, pw);
2317     }
2318 
2319     @Override
toString()2320     public String toString() {
2321         return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren;
2322     }
2323 
getName()2324     String getName() {
2325         return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
2326     }
2327 
2328     /** Returns true if the stack in the windowing mode is visible. */
isStackVisible(int windowingMode)2329     boolean isStackVisible(int windowingMode) {
2330         final TaskStack stack = getTopStackInWindowingMode(windowingMode);
2331         return stack != null && stack.isVisible();
2332     }
2333 
2334     /** Find the visible, touch-deliverable window under the given point */
getTouchableWinAtPointLocked(float xf, float yf)2335     WindowState getTouchableWinAtPointLocked(float xf, float yf) {
2336         final int x = (int) xf;
2337         final int y = (int) yf;
2338         final WindowState touchedWin = getWindow(w -> {
2339             final int flags = w.mAttrs.flags;
2340             if (!w.isVisibleLw()) {
2341                 return false;
2342             }
2343             if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
2344                 return false;
2345             }
2346 
2347             w.getVisibleBounds(mTmpRect);
2348             if (!mTmpRect.contains(x, y)) {
2349                 return false;
2350             }
2351 
2352             w.getTouchableRegion(mTmpRegion);
2353 
2354             final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
2355             return mTmpRegion.contains(x, y) || touchFlags == 0;
2356         });
2357 
2358         return touchedWin;
2359     }
2360 
canAddToastWindowForUid(int uid)2361     boolean canAddToastWindowForUid(int uid) {
2362         // We allow one toast window per UID being shown at a time.
2363         // Also if the app is focused adding more than one toast at
2364         // a time for better backwards compatibility.
2365         final WindowState focusedWindowForUid = getWindow(w ->
2366                 w.mOwnerUid == uid && w.isFocused());
2367         if (focusedWindowForUid != null) {
2368             return true;
2369         }
2370         final WindowState win = getWindow(w ->
2371                 w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden
2372                 && !w.mWindowRemovalAllowed);
2373         return win == null;
2374     }
2375 
scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus)2376     void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
2377         if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
2378             return;
2379         }
2380 
2381         // Used to communicate the old focus to the callback method.
2382         mTmpWindow = oldFocus;
2383 
2384         forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */);
2385     }
2386 
findFocusedWindow()2387     WindowState findFocusedWindow() {
2388         mTmpWindow = null;
2389 
2390         forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */);
2391 
2392         if (mTmpWindow == null) {
2393             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
2394             return null;
2395         }
2396         return mTmpWindow;
2397     }
2398 
2399     /** Updates the layer assignment of windows on this display. */
assignWindowLayers(boolean setLayoutNeeded)2400     void assignWindowLayers(boolean setLayoutNeeded) {
2401         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "assignWindowLayers");
2402         assignChildLayers(getPendingTransaction());
2403         if (setLayoutNeeded) {
2404             setLayoutNeeded();
2405         }
2406 
2407         // We accumlate the layer changes in-to "getPendingTransaction()" but we defer
2408         // the application of this transaction until the animation pass triggers
2409         // prepareSurfaces. This allows us to synchronize Z-ordering changes with
2410         // the hiding and showing of surfaces.
2411         scheduleAnimation();
2412         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
2413     }
2414 
2415     // TODO: This should probably be called any time a visual change is made to the hierarchy like
2416     // moving containers or resizing them. Need to investigate the best way to have it automatically
2417     // happen so we don't run into issues with programmers forgetting to do it.
layoutAndAssignWindowLayersIfNeeded()2418     void layoutAndAssignWindowLayersIfNeeded() {
2419         mService.mWindowsChanged = true;
2420         setLayoutNeeded();
2421 
2422         if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2423                 false /*updateInputWindows*/)) {
2424             assignWindowLayers(false /* setLayoutNeeded */);
2425         }
2426 
2427         mService.mInputMonitor.setUpdateInputWindowsNeededLw();
2428         mService.mWindowPlacerLocked.performSurfacePlacement();
2429         mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
2430     }
2431 
2432     /** Returns true if a leaked surface was destroyed */
destroyLeakedSurfaces()2433     boolean destroyLeakedSurfaces() {
2434         // Used to indicate that a surface was leaked.
2435         mTmpWindow = null;
2436         forAllWindows(w -> {
2437             final WindowStateAnimator wsa = w.mWinAnimator;
2438             if (wsa.mSurfaceController == null) {
2439                 return;
2440             }
2441             if (!mService.mSessions.contains(wsa.mSession)) {
2442                 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
2443                         + w + " surface=" + wsa.mSurfaceController
2444                         + " token=" + w.mToken
2445                         + " pid=" + w.mSession.mPid
2446                         + " uid=" + w.mSession.mUid);
2447                 wsa.destroySurface();
2448                 mService.mForceRemoves.add(w);
2449                 mTmpWindow = w;
2450             } else if (w.mAppToken != null && w.mAppToken.isClientHidden()) {
2451                 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
2452                         + w + " surface=" + wsa.mSurfaceController
2453                         + " token=" + w.mAppToken);
2454                 if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false);
2455                 wsa.destroySurface();
2456                 mTmpWindow = w;
2457             }
2458         }, false /* traverseTopToBottom */);
2459 
2460         return mTmpWindow != null;
2461     }
2462 
2463     /**
2464      * Determine and return the window that should be the IME target.
2465      * @param updateImeTarget If true the system IME target will be updated to match what we found.
2466      * @return The window that should be used as the IME target or null if there isn't any.
2467      */
computeImeTarget(boolean updateImeTarget)2468     WindowState computeImeTarget(boolean updateImeTarget) {
2469         if (mService.mInputMethodWindow == null) {
2470             // There isn't an IME so there shouldn't be a target...That was easy!
2471             if (updateImeTarget) {
2472                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
2473                         + mService.mInputMethodTarget + " to null since mInputMethodWindow is null");
2474                 setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim);
2475             }
2476             return null;
2477         }
2478 
2479         final WindowState curTarget = mService.mInputMethodTarget;
2480         if (!canUpdateImeTarget()) {
2481             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
2482             return curTarget;
2483         }
2484 
2485         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
2486         // same display. Or even when the current IME/target are not on the same screen as the next
2487         // IME/target. For now only look for input windows on the main screen.
2488         mUpdateImeTarget = updateImeTarget;
2489         WindowState target = getWindow(mComputeImeTargetPredicate);
2490 
2491 
2492         // Yet more tricksyness!  If this window is a "starting" window, we do actually want
2493         // to be on top of it, but it is not -really- where input will go. So look down below
2494         // for a real window to target...
2495         if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) {
2496             final AppWindowToken token = target.mAppToken;
2497             if (token != null) {
2498                 final WindowState betterTarget = token.getImeTargetBelowWindow(target);
2499                 if (betterTarget != null) {
2500                     target = betterTarget;
2501                 }
2502             }
2503         }
2504 
2505         if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
2506                 "Proposed new IME target: " + target);
2507 
2508         // Now, a special case -- if the last target's window is in the process of exiting, and the
2509         // new target is home, keep on the last target to avoid flicker. Home is a special case
2510         // since its above other stacks in the ordering list, but layed out below the others.
2511         if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing()
2512                 && (target == null || target.isActivityTypeHome())) {
2513             if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "New target is home while current target is "
2514                     + "closing, not changing");
2515             return curTarget;
2516         }
2517 
2518         if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target
2519                 + " updateImeTarget=" + updateImeTarget);
2520 
2521         if (target == null) {
2522             if (updateImeTarget) {
2523                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
2524                         + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
2525                         + Debug.getCallers(4) : ""));
2526                 setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim);
2527             }
2528 
2529             return null;
2530         }
2531 
2532         if (updateImeTarget) {
2533             AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
2534             if (token != null) {
2535 
2536                 // Now some fun for dealing with window animations that modify the Z order. We need
2537                 // to look at all windows below the current target that are in this app, finding the
2538                 // highest visible one in layering.
2539                 WindowState highestTarget = null;
2540                 if (token.isSelfAnimating()) {
2541                     highestTarget = token.getHighestAnimLayerWindow(curTarget);
2542                 }
2543 
2544                 if (highestTarget != null) {
2545                     final AppTransition appTransition = mService.mAppTransition;
2546                     if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget
2547                             + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
2548                             + " layer=" + highestTarget.mWinAnimator.mAnimLayer
2549                             + " new layer=" + target.mWinAnimator.mAnimLayer);
2550 
2551                     if (appTransition.isTransitionSet()) {
2552                         // If we are currently setting up for an animation, hold everything until we
2553                         // can find out what will happen.
2554                         setInputMethodTarget(highestTarget, true);
2555                         return highestTarget;
2556                     } else if (highestTarget.mWinAnimator.isAnimationSet() &&
2557                             highestTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer) {
2558                         // If the window we are currently targeting is involved with an animation,
2559                         // and it is on top of the next target we will be over, then hold off on
2560                         // moving until that is done.
2561                         setInputMethodTarget(highestTarget, true);
2562                         return highestTarget;
2563                     }
2564                 }
2565             }
2566 
2567             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
2568                     + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
2569             setInputMethodTarget(target, false);
2570         }
2571 
2572         return target;
2573     }
2574 
setInputMethodTarget(WindowState target, boolean targetWaitingAnim)2575     private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) {
2576         if (target == mService.mInputMethodTarget
2577                 && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim) {
2578             return;
2579         }
2580 
2581         mService.mInputMethodTarget = target;
2582         mService.mInputMethodTargetWaitingAnim = targetWaitingAnim;
2583         assignWindowLayers(false /* setLayoutNeeded */);
2584     }
2585 
getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom)2586     boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
2587         if (top.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
2588             return top.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
2589         }
2590 
2591         // Used to indicate we have reached the first window in the range we are interested in.
2592         mTmpWindow = null;
2593 
2594         // TODO: Figure-out a more efficient way to do this.
2595         final WindowState candidate = getWindow(w -> {
2596             if (w == top) {
2597                 // Reached the first window in the range we are interested in.
2598                 mTmpWindow = w;
2599             }
2600             if (mTmpWindow == null) {
2601                 return false;
2602             }
2603 
2604             if (w.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
2605                 return true;
2606             }
2607             // If we reached the bottom of the range of windows we are considering,
2608             // assume no menu is needed.
2609             if (w == bottom) {
2610                 return true;
2611             }
2612             return false;
2613         });
2614 
2615         return candidate != null && candidate.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
2616     }
2617 
setLayoutNeeded()2618     void setLayoutNeeded() {
2619         if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
2620         mLayoutNeeded = true;
2621     }
2622 
clearLayoutNeeded()2623     private void clearLayoutNeeded() {
2624         if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3));
2625         mLayoutNeeded = false;
2626     }
2627 
isLayoutNeeded()2628     boolean isLayoutNeeded() {
2629         return mLayoutNeeded;
2630     }
2631 
dumpTokens(PrintWriter pw, boolean dumpAll)2632     void dumpTokens(PrintWriter pw, boolean dumpAll) {
2633         if (mTokenMap.isEmpty()) {
2634             return;
2635         }
2636         pw.println("  Display #" + mDisplayId);
2637         final Iterator<WindowToken> it = mTokenMap.values().iterator();
2638         while (it.hasNext()) {
2639             final WindowToken token = it.next();
2640             pw.print("  ");
2641             pw.print(token);
2642             if (dumpAll) {
2643                 pw.println(':');
2644                 token.dump(pw, "    ", dumpAll);
2645             } else {
2646                 pw.println();
2647             }
2648         }
2649     }
2650 
dumpWindowAnimators(PrintWriter pw, String subPrefix)2651     void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
2652         final int[] index = new int[1];
2653         forAllWindows(w -> {
2654             final WindowStateAnimator wAnim = w.mWinAnimator;
2655             pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim);
2656             index[0] = index[0] + 1;
2657         }, false /* traverseTopToBottom */);
2658     }
2659 
2660     /**
2661      * Starts the Keyguard exit animation on all windows that don't belong to an app token.
2662      */
startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade)2663     void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) {
2664         final WindowManagerPolicy policy = mService.mPolicy;
2665         forAllWindows(w -> {
2666             if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)
2667                     && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
2668                 w.startAnimation(policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
2669             }
2670         }, true /* traverseTopToBottom */);
2671     }
2672 
checkWaitingForWindows()2673     boolean checkWaitingForWindows() {
2674 
2675         mHaveBootMsg = false;
2676         mHaveApp = false;
2677         mHaveWallpaper = false;
2678         mHaveKeyguard = true;
2679 
2680         final WindowState visibleWindow = getWindow(w -> {
2681             if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
2682                 return true;
2683             }
2684             if (w.isDrawnLw()) {
2685                 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
2686                     mHaveBootMsg = true;
2687                 } else if (w.mAttrs.type == TYPE_APPLICATION
2688                         || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
2689                     mHaveApp = true;
2690                 } else if (w.mAttrs.type == TYPE_WALLPAPER) {
2691                     mHaveWallpaper = true;
2692                 } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
2693                     mHaveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
2694                 }
2695             }
2696             return false;
2697         });
2698 
2699         if (visibleWindow != null) {
2700             // We have a visible window.
2701             return true;
2702         }
2703 
2704         // if the wallpaper service is disabled on the device, we're never going to have
2705         // wallpaper, don't bother waiting for it
2706         boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
2707                 com.android.internal.R.bool.config_enableWallpaperService)
2708                 && mService.mContext.getResources().getBoolean(
2709                         com.android.internal.R.bool.config_checkWallpaperAtBoot)
2710                 && !mService.mOnlyCore;
2711 
2712         if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
2713                 "******** booted=" + mService.mSystemBooted
2714                 + " msg=" + mService.mShowingBootMessages
2715                 + " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp
2716                 + " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled
2717                 + " haveKeyguard=" + mHaveKeyguard);
2718 
2719         // If we are turning on the screen to show the boot message, don't do it until the boot
2720         // message is actually displayed.
2721         if (!mService.mSystemBooted && !mHaveBootMsg) {
2722             return true;
2723         }
2724 
2725         // If we are turning on the screen after the boot is completed normally, don't do so until
2726         // we have the application and wallpaper.
2727         if (mService.mSystemBooted
2728                 && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) {
2729             return true;
2730         }
2731 
2732         return false;
2733     }
2734 
updateWindowsForAnimator(WindowAnimator animator)2735     void updateWindowsForAnimator(WindowAnimator animator) {
2736         mTmpWindowAnimator = animator;
2737         forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
2738     }
2739 
updateWallpaperForAnimator(WindowAnimator animator)2740     void updateWallpaperForAnimator(WindowAnimator animator) {
2741         resetAnimationBackgroundAnimator();
2742 
2743         // Used to indicate a detached wallpaper.
2744         mTmpWindow = null;
2745         mTmpWindowAnimator = animator;
2746 
2747         forAllWindows(mUpdateWallpaperForAnimator, true /* traverseTopToBottom */);
2748 
2749         if (animator.mWindowDetachedWallpaper != mTmpWindow) {
2750             if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from "
2751                     + animator.mWindowDetachedWallpaper + " to " + mTmpWindow);
2752             animator.mWindowDetachedWallpaper = mTmpWindow;
2753             animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
2754         }
2755     }
2756 
inputMethodClientHasFocus(IInputMethodClient client)2757     boolean inputMethodClientHasFocus(IInputMethodClient client) {
2758         final WindowState imFocus = computeImeTarget(false /* updateImeTarget */);
2759         if (imFocus == null) {
2760             return false;
2761         }
2762 
2763         if (DEBUG_INPUT_METHOD) {
2764             Slog.i(TAG_WM, "Desired input method target: " + imFocus);
2765             Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
2766             Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
2767         }
2768 
2769         final IInputMethodClient imeClient = imFocus.mSession.mClient;
2770 
2771         if (DEBUG_INPUT_METHOD) {
2772             Slog.i(TAG_WM, "IM target client: " + imeClient);
2773             if (imeClient != null) {
2774                 Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder());
2775                 Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
2776             }
2777         }
2778 
2779         return imeClient != null && imeClient.asBinder() == client.asBinder();
2780     }
2781 
hasSecureWindowOnScreen()2782     boolean hasSecureWindowOnScreen() {
2783         final WindowState win = getWindow(
2784                 w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0);
2785         return win != null;
2786     }
2787 
updateSystemUiVisibility(int visibility, int globalDiff)2788     void updateSystemUiVisibility(int visibility, int globalDiff) {
2789         forAllWindows(w -> {
2790             try {
2791                 final int curValue = w.mSystemUiVisibility;
2792                 final int diff = (curValue ^ visibility) & globalDiff;
2793                 final int newValue = (curValue & ~diff) | (visibility & diff);
2794                 if (newValue != curValue) {
2795                     w.mSeq++;
2796                     w.mSystemUiVisibility = newValue;
2797                 }
2798                 if (newValue != curValue || w.mAttrs.hasSystemUiListeners) {
2799                     w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq,
2800                             visibility, newValue, diff);
2801                 }
2802             } catch (RemoteException e) {
2803                 // so sorry
2804             }
2805         }, true /* traverseTopToBottom */);
2806     }
2807 
onWindowFreezeTimeout()2808     void onWindowFreezeTimeout() {
2809         Slog.w(TAG_WM, "Window freeze timeout expired.");
2810         mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
2811 
2812         forAllWindows(w -> {
2813             if (!w.getOrientationChanging()) {
2814                 return;
2815             }
2816             w.orientationChangeTimedOut();
2817             w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
2818                     - mService.mDisplayFreezeTime);
2819             Slog.w(TAG_WM, "Force clearing orientation change: " + w);
2820         }, true /* traverseTopToBottom */);
2821         mService.mWindowPlacerLocked.performSurfacePlacement();
2822     }
2823 
waitForAllWindowsDrawn()2824     void waitForAllWindowsDrawn() {
2825         final WindowManagerPolicy policy = mService.mPolicy;
2826         forAllWindows(w -> {
2827             final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
2828             if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
2829                 w.mWinAnimator.mDrawState = DRAW_PENDING;
2830                 // Force add to mResizingWindows.
2831                 w.mLastContentInsets.set(-1, -1, -1, -1);
2832                 mService.mWaitingForDrawn.add(w);
2833             }
2834         }, true /* traverseTopToBottom */);
2835     }
2836 
2837     // TODO: Super crazy long method that should be broken down...
applySurfaceChangesTransaction(boolean recoveringMemory)2838     boolean applySurfaceChangesTransaction(boolean recoveringMemory) {
2839 
2840         final int dw = mDisplayInfo.logicalWidth;
2841         final int dh = mDisplayInfo.logicalHeight;
2842         final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
2843 
2844         mTmpUpdateAllDrawn.clear();
2845 
2846         int repeats = 0;
2847         do {
2848             repeats++;
2849             if (repeats > 6) {
2850                 Slog.w(TAG, "Animation repeat aborted after too many iterations");
2851                 clearLayoutNeeded();
2852                 break;
2853             }
2854 
2855             if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
2856                     pendingLayoutChanges);
2857 
2858             // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid
2859             // the wallpaper window jumping across displays.
2860             // Remove check for default display when there will be support for multiple wallpaper
2861             // targets (on different displays).
2862             if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
2863                 mWallpaperController.adjustWallpaperWindows(this);
2864             }
2865 
2866             if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
2867                 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
2868                 if (mService.updateOrientationFromAppTokensLocked(mDisplayId)) {
2869                     setLayoutNeeded();
2870                     mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
2871                 }
2872             }
2873 
2874             if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
2875                 setLayoutNeeded();
2876             }
2877 
2878             // FIRST LOOP: Perform a layout, if needed.
2879             if (repeats < LAYOUT_REPEAT_THRESHOLD) {
2880                 performLayout(repeats == 1, false /* updateInputWindows */);
2881             } else {
2882                 Slog.w(TAG, "Layout repeat skipped after too many iterations");
2883             }
2884 
2885             // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
2886             pendingLayoutChanges = 0;
2887 
2888             if (isDefaultDisplay) {
2889                 mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
2890                 forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
2891                 pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
2892                 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
2893                         "after finishPostLayoutPolicyLw", pendingLayoutChanges);
2894             }
2895         } while (pendingLayoutChanges != 0);
2896 
2897         mTmpApplySurfaceChangesTransactionState.reset();
2898 
2899         mTmpRecoveringMemory = recoveringMemory;
2900         forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
2901         prepareSurfaces();
2902 
2903         mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
2904                 mTmpApplySurfaceChangesTransactionState.displayHasContent,
2905                 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
2906                 mTmpApplySurfaceChangesTransactionState.preferredModeId,
2907                 true /* inTraversal, must call performTraversalInTrans... below */);
2908 
2909         final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
2910         if (wallpaperVisible != mLastWallpaperVisible) {
2911             mLastWallpaperVisible = wallpaperVisible;
2912             mService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this);
2913         }
2914 
2915         while (!mTmpUpdateAllDrawn.isEmpty()) {
2916             final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
2917             // See if any windows have been drawn, so they (and others associated with them)
2918             // can now be shown.
2919             atoken.updateAllDrawn();
2920         }
2921 
2922         return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
2923     }
2924 
updateBounds()2925     private void updateBounds() {
2926         calculateBounds(mTmpBounds);
2927         setBounds(mTmpBounds);
2928     }
2929 
2930     // Determines the current display bounds based on the current state
calculateBounds(Rect out)2931     private void calculateBounds(Rect out) {
2932         // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
2933         final int orientation = mDisplayInfo.rotation;
2934         boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
2935         final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
2936         final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
2937         int width = mDisplayInfo.logicalWidth;
2938         int left = (physWidth - width) / 2;
2939         int height = mDisplayInfo.logicalHeight;
2940         int top = (physHeight - height) / 2;
2941         out.set(left, top, left + width, top + height);
2942     }
2943 
2944     @Override
getBounds(Rect out)2945     public void getBounds(Rect out) {
2946         calculateBounds(out);
2947     }
2948 
getBounds(Rect out, int orientation)2949     private void getBounds(Rect out, int orientation) {
2950         getBounds(out);
2951 
2952         // Rotate the Rect if needed.
2953         final int currentRotation = mDisplayInfo.rotation;
2954         final int rotationDelta = deltaRotation(currentRotation, orientation);
2955         if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
2956             createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
2957             mTmpRectF.set(out);
2958             mTmpMatrix.mapRect(mTmpRectF);
2959             mTmpRectF.round(out);
2960         }
2961     }
2962 
performLayout(boolean initial, boolean updateInputWindows)2963     void performLayout(boolean initial, boolean updateInputWindows) {
2964         if (!isLayoutNeeded()) {
2965             return;
2966         }
2967         clearLayoutNeeded();
2968 
2969         final int dw = mDisplayInfo.logicalWidth;
2970         final int dh = mDisplayInfo.logicalHeight;
2971         if (DEBUG_LAYOUT) {
2972             Slog.v(TAG, "-------------------------------------");
2973             Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh);
2974         }
2975 
2976         mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
2977                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
2978         // TODO: Not sure if we really need to set the rotation here since we are updating from the
2979         // display info above...
2980         mDisplayFrames.mRotation = mRotation;
2981         mService.mPolicy.beginLayoutLw(mDisplayFrames, getConfiguration().uiMode);
2982         if (isDefaultDisplay) {
2983             // Not needed on non-default displays.
2984             mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
2985             mService.mScreenRect.set(0, 0, dw, dh);
2986         }
2987 
2988         int seq = mLayoutSeq + 1;
2989         if (seq < 0) seq = 0;
2990         mLayoutSeq = seq;
2991 
2992         // Used to indicate that we have processed the dream window and all additional windows are
2993         // behind it.
2994         mTmpWindow = null;
2995         mTmpInitial = initial;
2996 
2997         // First perform layout of any root windows (not attached to another window).
2998         forAllWindows(mPerformLayout, true /* traverseTopToBottom */);
2999 
3000         // Used to indicate that we have processed the dream window and all additional attached
3001         // windows are behind it.
3002         mTmpWindow2 = mTmpWindow;
3003         mTmpWindow = null;
3004 
3005         // Now perform layout of attached windows, which usually depend on the position of the
3006         // window they are attached to. XXX does not deal with windows that are attached to windows
3007         // that are themselves attached.
3008         forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);
3009 
3010         // Window frames may have changed. Tell the input dispatcher about it.
3011         mService.mInputMonitor.layoutInputConsumers(dw, dh);
3012         mService.mInputMonitor.setUpdateInputWindowsNeededLw();
3013         if (updateInputWindows) {
3014             mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
3015         }
3016 
3017         mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
3018     }
3019 
3020     /**
3021      * Takes a snapshot of the display.  In landscape mode this grabs the whole screen.
3022      * In portrait mode, it grabs the full screenshot.
3023      *
3024      * @param config of the output bitmap
3025      */
screenshotDisplayLocked(Bitmap.Config config)3026     Bitmap screenshotDisplayLocked(Bitmap.Config config) {
3027         if (!mService.mPolicy.isScreenOn()) {
3028             if (DEBUG_SCREENSHOT) {
3029                 Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
3030             }
3031             return null;
3032         }
3033 
3034         int dw = mDisplayInfo.logicalWidth;
3035         int dh = mDisplayInfo.logicalHeight;
3036 
3037         if (dw <= 0 || dh <= 0) {
3038             return null;
3039         }
3040 
3041         final Rect frame = new Rect(0, 0, dw, dh);
3042 
3043         // The screenshot API does not apply the current screen rotation.
3044         int rot = mDisplay.getRotation();
3045 
3046         if (rot == ROTATION_90 || rot == ROTATION_270) {
3047             rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90;
3048         }
3049 
3050         // SurfaceFlinger is not aware of orientation, so convert our logical
3051         // crop to SurfaceFlinger's portrait orientation.
3052         convertCropForSurfaceFlinger(frame, rot, dw, dh);
3053 
3054         final ScreenRotationAnimation screenRotationAnimation =
3055                 mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
3056         final boolean inRotation = screenRotationAnimation != null &&
3057                 screenRotationAnimation.isAnimating();
3058         if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, "Taking screenshot while rotating");
3059 
3060         // TODO(b/68392460): We should screenshot Task controls directly
3061         // but it's difficult at the moment as the Task doesn't have the
3062         // correct size set.
3063         final Bitmap bitmap = SurfaceControl.screenshot(frame, dw, dh, 0, 1, inRotation, rot);
3064         if (bitmap == null) {
3065             Slog.w(TAG_WM, "Failed to take screenshot");
3066             return null;
3067         }
3068 
3069         // Create a copy of the screenshot that is immutable and backed in ashmem.
3070         // This greatly reduces the overhead of passing the bitmap between processes.
3071         final Bitmap ret = bitmap.createAshmemBitmap(config);
3072         bitmap.recycle();
3073         return ret;
3074     }
3075 
3076     // TODO: Can this use createRotationMatrix()?
convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh)3077     private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
3078         if (rot == Surface.ROTATION_90) {
3079             final int tmp = crop.top;
3080             crop.top = dw - crop.right;
3081             crop.right = crop.bottom;
3082             crop.bottom = dw - crop.left;
3083             crop.left = tmp;
3084         } else if (rot == Surface.ROTATION_180) {
3085             int tmp = crop.top;
3086             crop.top = dh - crop.bottom;
3087             crop.bottom = dh - tmp;
3088             tmp = crop.right;
3089             crop.right = dw - crop.left;
3090             crop.left = dw - tmp;
3091         } else if (rot == Surface.ROTATION_270) {
3092             final int tmp = crop.top;
3093             crop.top = crop.left;
3094             crop.left = dh - crop.bottom;
3095             crop.bottom = crop.right;
3096             crop.right = dh - tmp;
3097         }
3098     }
3099 
onSeamlessRotationTimeout()3100     void onSeamlessRotationTimeout() {
3101         // Used to indicate the layout is needed.
3102         mTmpWindow = null;
3103 
3104         forAllWindows(w -> {
3105             if (!w.mSeamlesslyRotated) {
3106                 return;
3107             }
3108             mTmpWindow = w;
3109             w.setDisplayLayoutNeeded();
3110             mService.markForSeamlessRotation(w, false);
3111         }, true /* traverseTopToBottom */);
3112 
3113         if (mTmpWindow != null) {
3114             mService.mWindowPlacerLocked.performSurfacePlacement();
3115         }
3116     }
3117 
setExitingTokensHasVisible(boolean hasVisible)3118     void setExitingTokensHasVisible(boolean hasVisible) {
3119         for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
3120             mExitingTokens.get(i).hasVisible = hasVisible;
3121         }
3122 
3123         // Initialize state of exiting applications.
3124         mTaskStackContainers.setExitingTokensHasVisible(hasVisible);
3125     }
3126 
removeExistingTokensIfPossible()3127     void removeExistingTokensIfPossible() {
3128         for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
3129             final WindowToken token = mExitingTokens.get(i);
3130             if (!token.hasVisible) {
3131                 mExitingTokens.remove(i);
3132             }
3133         }
3134 
3135         // Time to remove any exiting applications?
3136         mTaskStackContainers.removeExistingAppTokensIfPossible();
3137     }
3138 
3139     @Override
onDescendantOverrideConfigurationChanged()3140     void onDescendantOverrideConfigurationChanged() {
3141         setLayoutNeeded();
3142         mService.requestTraversal();
3143     }
3144 
okToDisplay()3145     boolean okToDisplay() {
3146         if (mDisplayId == DEFAULT_DISPLAY) {
3147             return !mService.mDisplayFrozen
3148                     && mService.mDisplayEnabled && mService.mPolicy.isScreenOn();
3149         }
3150         return mDisplayInfo.state == Display.STATE_ON;
3151     }
3152 
okToAnimate()3153     boolean okToAnimate() {
3154         return okToDisplay() &&
3155                 (mDisplayId != DEFAULT_DISPLAY || mService.mPolicy.okToAnimate());
3156     }
3157 
3158     static final class TaskForResizePointSearchResult {
3159         boolean searchDone;
3160         Task taskForResize;
3161 
reset()3162         void reset() {
3163             searchDone = false;
3164             taskForResize = null;
3165         }
3166     }
3167 
3168     private static final class ApplySurfaceChangesTransactionState {
3169         boolean displayHasContent;
3170         boolean obscured;
3171         boolean syswin;
3172         boolean focusDisplayed;
3173         float preferredRefreshRate;
3174         int preferredModeId;
3175 
reset()3176         void reset() {
3177             displayHasContent = false;
3178             obscured = false;
3179             syswin = false;
3180             focusDisplayed = false;
3181             preferredRefreshRate = 0;
3182             preferredModeId = 0;
3183         }
3184     }
3185 
3186     private static final class ScreenshotApplicationState {
3187         WindowState appWin;
3188         int maxLayer;
3189         int minLayer;
3190         boolean screenshotReady;
3191 
reset(boolean screenshotReady)3192         void reset(boolean screenshotReady) {
3193             appWin = null;
3194             maxLayer = 0;
3195             minLayer = 0;
3196             this.screenshotReady = screenshotReady;
3197             minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE;
3198         }
3199     }
3200 
3201     /**
3202      * Base class for any direct child window container of {@link #DisplayContent} need to inherit
3203      * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
3204      * homogeneous children type which is currently required by sub-classes of
3205      * {@link WindowContainer} class.
3206      */
3207     static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
3208 
DisplayChildWindowContainer(WindowManagerService service)3209         DisplayChildWindowContainer(WindowManagerService service) {
3210             super(service);
3211         }
3212 
3213         @Override
fillsParent()3214         boolean fillsParent() {
3215             return true;
3216         }
3217 
3218         @Override
isVisible()3219         boolean isVisible() {
3220             return true;
3221         }
3222     }
3223 
3224     /**
3225      * Window container class that contains all containers on this display relating to Apps.
3226      * I.e Activities.
3227      */
3228     private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
3229         /**
3230          * A control placed at the appropriate level for transitions to occur.
3231          */
3232         SurfaceControl mAppAnimationLayer = null;
3233         SurfaceControl mBoostedAppAnimationLayer = null;
3234         SurfaceControl mHomeAppAnimationLayer = null;
3235 
3236         /**
3237          * Given that the split-screen divider does not have an AppWindowToken, it
3238          * will have to live inside of a "NonAppWindowContainer", in particular
3239          * {@link DisplayContent#mAboveAppWindowsContainers}. However, in visual Z order
3240          * it will need to be interleaved with some of our children, appearing on top of
3241          * both docked stacks but underneath any assistant stacks.
3242          *
3243          * To solve this problem we have this anchor control, which will always exist so
3244          * we can always assign it the correct value in our {@link #assignChildLayers}.
3245          * Likewise since it always exists, {@link AboveAppWindowContainers} can always
3246          * assign the divider a layer relative to it. This way we prevent linking lifecycle
3247          * events between the two containers.
3248          */
3249         SurfaceControl mSplitScreenDividerAnchor = null;
3250 
3251         // Cached reference to some special stacks we tend to get a lot so we don't need to loop
3252         // through the list to find them.
3253         private TaskStack mHomeStack = null;
3254         private TaskStack mPinnedStack = null;
3255         private TaskStack mSplitScreenPrimaryStack = null;
3256 
TaskStackContainers(WindowManagerService service)3257         TaskStackContainers(WindowManagerService service) {
3258             super(service);
3259         }
3260 
3261         /**
3262          * Returns the topmost stack on the display that is compatible with the input windowing mode
3263          * and activity type. Null is no compatible stack on the display.
3264          */
getStack(int windowingMode, int activityType)3265         TaskStack getStack(int windowingMode, int activityType) {
3266             if (activityType == ACTIVITY_TYPE_HOME) {
3267                 return mHomeStack;
3268             }
3269             if (windowingMode == WINDOWING_MODE_PINNED) {
3270                 return mPinnedStack;
3271             } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
3272                 return mSplitScreenPrimaryStack;
3273             }
3274             for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
3275                 final TaskStack stack = mTaskStackContainers.getChildAt(i);
3276                 if (activityType == ACTIVITY_TYPE_UNDEFINED
3277                         && windowingMode == stack.getWindowingMode()) {
3278                     // Passing in undefined type means we want to match the topmost stack with the
3279                     // windowing mode.
3280                     return stack;
3281                 }
3282                 if (stack.isCompatible(windowingMode, activityType)) {
3283                     return stack;
3284                 }
3285             }
3286             return null;
3287         }
3288 
3289         @VisibleForTesting
getTopStack()3290         TaskStack getTopStack() {
3291             return mTaskStackContainers.getChildCount() > 0
3292                     ? mTaskStackContainers.getChildAt(mTaskStackContainers.getChildCount() - 1) : null;
3293         }
3294 
getHomeStack()3295         TaskStack getHomeStack() {
3296             if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
3297                 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
3298             }
3299             return mHomeStack;
3300         }
3301 
getPinnedStack()3302         TaskStack getPinnedStack() {
3303             return mPinnedStack;
3304         }
3305 
getSplitScreenPrimaryStack()3306         TaskStack getSplitScreenPrimaryStack() {
3307             return mSplitScreenPrimaryStack;
3308         }
3309 
getVisibleTasks()3310         ArrayList<Task> getVisibleTasks() {
3311             final ArrayList<Task> visibleTasks = new ArrayList<>();
3312             forAllTasks(task -> {
3313                 if (task.isVisible()) {
3314                     visibleTasks.add(task);
3315                 }
3316             });
3317             return visibleTasks;
3318         }
3319 
3320         /**
3321          * Adds the stack to this container.
3322          * @see DisplayContent#createStack(int, boolean, StackWindowController)
3323          */
addStackToDisplay(TaskStack stack, boolean onTop)3324         void addStackToDisplay(TaskStack stack, boolean onTop) {
3325             addStackReferenceIfNeeded(stack);
3326             addChild(stack, onTop);
3327             stack.onDisplayChanged(DisplayContent.this);
3328         }
3329 
onStackWindowingModeChanged(TaskStack stack)3330         void onStackWindowingModeChanged(TaskStack stack) {
3331             removeStackReferenceIfNeeded(stack);
3332             addStackReferenceIfNeeded(stack);
3333             if (stack == mPinnedStack && getTopStack() != stack) {
3334                 // Looks like this stack changed windowing mode to pinned. Move it to the top.
3335                 positionChildAt(POSITION_TOP, stack, false /* includingParents */);
3336             }
3337         }
3338 
addStackReferenceIfNeeded(TaskStack stack)3339         private void addStackReferenceIfNeeded(TaskStack stack) {
3340             if (stack.isActivityTypeHome()) {
3341                 if (mHomeStack != null) {
3342                     throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
3343                             + mHomeStack + " already exist on display=" + this + " stack=" + stack);
3344                 }
3345                 mHomeStack = stack;
3346             }
3347             final int windowingMode = stack.getWindowingMode();
3348             if (windowingMode == WINDOWING_MODE_PINNED) {
3349                 if (mPinnedStack != null) {
3350                     throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
3351                             + mPinnedStack + " already exist on display=" + this
3352                             + " stack=" + stack);
3353                 }
3354                 mPinnedStack = stack;
3355             } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
3356                 if (mSplitScreenPrimaryStack != null) {
3357                     throw new IllegalArgumentException("addStackReferenceIfNeeded:"
3358                             + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
3359                             + " already exist on display=" + this + " stack=" + stack);
3360                 }
3361                 mSplitScreenPrimaryStack = stack;
3362                 mDividerControllerLocked.notifyDockedStackExistsChanged(true);
3363             }
3364         }
3365 
removeStackReferenceIfNeeded(TaskStack stack)3366         private void removeStackReferenceIfNeeded(TaskStack stack) {
3367             if (stack == mHomeStack) {
3368                 mHomeStack = null;
3369             } else if (stack == mPinnedStack) {
3370                 mPinnedStack = null;
3371             } else if (stack == mSplitScreenPrimaryStack) {
3372                 mSplitScreenPrimaryStack = null;
3373                 // Re-set the split-screen create mode whenever the split-screen stack is removed.
3374                 mService.setDockedStackCreateStateLocked(
3375                         SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
3376                 mDividerControllerLocked.notifyDockedStackExistsChanged(false);
3377             }
3378         }
3379 
addChild(TaskStack stack, boolean toTop)3380         private void addChild(TaskStack stack, boolean toTop) {
3381             final int addIndex = findPositionForStack(toTop ? mChildren.size() : 0, stack,
3382                     true /* adding */);
3383             addChild(stack, addIndex);
3384             setLayoutNeeded();
3385         }
3386 
3387         @Override
removeChild(TaskStack stack)3388         protected void removeChild(TaskStack stack) {
3389             super.removeChild(stack);
3390             removeStackReferenceIfNeeded(stack);
3391         }
3392 
3393         @Override
isOnTop()3394         boolean isOnTop() {
3395             // Considered always on top
3396             return true;
3397         }
3398 
3399         @Override
positionChildAt(int position, TaskStack child, boolean includingParents)3400         void positionChildAt(int position, TaskStack child, boolean includingParents) {
3401             if (child.getWindowConfiguration().isAlwaysOnTop()
3402                     && position != POSITION_TOP) {
3403                 // This stack is always-on-top, override the default behavior.
3404                 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
3405 
3406                 // Moving to its current position, as we must call super but we don't want to
3407                 // perform any meaningful action.
3408                 final int currentPosition = mChildren.indexOf(child);
3409                 super.positionChildAt(currentPosition, child, false /* includingParents */);
3410                 return;
3411             }
3412 
3413             final int targetPosition = findPositionForStack(position, child, false /* adding */);
3414             super.positionChildAt(targetPosition, child, includingParents);
3415 
3416             setLayoutNeeded();
3417         }
3418 
3419         /**
3420          * When stack is added or repositioned, find a proper position for it.
3421          * This will make sure that pinned stack always stays on top.
3422          * @param requestedPosition Position requested by caller.
3423          * @param stack Stack to be added or positioned.
3424          * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
3425          * @return The proper position for the stack.
3426          */
findPositionForStack(int requestedPosition, TaskStack stack, boolean adding)3427         private int findPositionForStack(int requestedPosition, TaskStack stack, boolean adding) {
3428             final int topChildPosition = mChildren.size() - 1;
3429             boolean toTop = requestedPosition == POSITION_TOP;
3430             toTop |= adding ? requestedPosition >= topChildPosition + 1
3431                     : requestedPosition >= topChildPosition;
3432             int targetPosition = requestedPosition;
3433 
3434             if (toTop && stack.getWindowingMode() != WINDOWING_MODE_PINNED && hasPinnedStack()) {
3435                 // The pinned stack is always the top most stack (always-on-top) when it is present.
3436                 TaskStack topStack = mChildren.get(topChildPosition);
3437                 if (topStack.getWindowingMode() != WINDOWING_MODE_PINNED) {
3438                     throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
3439                 }
3440 
3441                 // So, stack is moved just below the pinned stack.
3442                 // When we're adding a new stack the target is the current pinned stack position.
3443                 // When we're positioning an existing stack the target is the position below pinned
3444                 // stack, because WindowContainer#positionAt() first removes element and then adds
3445                 // it to specified place.
3446                 targetPosition = adding ? topChildPosition : topChildPosition - 1;
3447             }
3448 
3449             return targetPosition;
3450         }
3451 
3452         @Override
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)3453         boolean forAllWindows(ToBooleanFunction<WindowState> callback,
3454                 boolean traverseTopToBottom) {
3455             if (traverseTopToBottom) {
3456                 if (super.forAllWindows(callback, traverseTopToBottom)) {
3457                     return true;
3458                 }
3459                 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
3460                     return true;
3461                 }
3462             } else {
3463                 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
3464                     return true;
3465                 }
3466                 if (super.forAllWindows(callback, traverseTopToBottom)) {
3467                     return true;
3468                 }
3469             }
3470             return false;
3471         }
3472 
forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)3473         private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
3474                 boolean traverseTopToBottom) {
3475             // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the
3476             // app tokens.
3477             // TODO: Investigate if we need to continue to do this or if we can just process them
3478             // in-order.
3479             if (traverseTopToBottom) {
3480                 for (int i = mChildren.size() - 1; i >= 0; --i) {
3481                     final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
3482                     for (int j = appTokens.size() - 1; j >= 0; --j) {
3483                         if (appTokens.get(j).forAllWindowsUnchecked(callback,
3484                                 traverseTopToBottom)) {
3485                             return true;
3486                         }
3487                     }
3488                 }
3489             } else {
3490                 final int count = mChildren.size();
3491                 for (int i = 0; i < count; ++i) {
3492                     final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
3493                     final int appTokensCount = appTokens.size();
3494                     for (int j = 0; j < appTokensCount; j++) {
3495                         if (appTokens.get(j).forAllWindowsUnchecked(callback,
3496                                 traverseTopToBottom)) {
3497                             return true;
3498                         }
3499                     }
3500                 }
3501             }
3502             return false;
3503         }
3504 
setExitingTokensHasVisible(boolean hasVisible)3505         void setExitingTokensHasVisible(boolean hasVisible) {
3506             for (int i = mChildren.size() - 1; i >= 0; --i) {
3507                 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
3508                 for (int j = appTokens.size() - 1; j >= 0; --j) {
3509                     appTokens.get(j).hasVisible = hasVisible;
3510                 }
3511             }
3512         }
3513 
removeExistingAppTokensIfPossible()3514         void removeExistingAppTokensIfPossible() {
3515             for (int i = mChildren.size() - 1; i >= 0; --i) {
3516                 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
3517                 for (int j = appTokens.size() - 1; j >= 0; --j) {
3518                     final AppWindowToken token = appTokens.get(j);
3519                     if (!token.hasVisible && !mService.mClosingApps.contains(token)
3520                             && (!token.mIsExiting || token.isEmpty())) {
3521                         // Make sure there is no animation running on this token, so any windows
3522                         // associated with it will be removed as soon as their animations are
3523                         // complete.
3524                         cancelAnimation();
3525                         if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
3526                                 "performLayout: App token exiting now removed" + token);
3527                         token.removeIfPossible();
3528                     }
3529                 }
3530             }
3531         }
3532 
3533         @Override
getOrientation()3534         int getOrientation() {
3535             if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
3536                     || isStackVisible(WINDOWING_MODE_FREEFORM)) {
3537                 // Apps and their containers are not allowed to specify an orientation while the
3538                 // docked or freeform stack is visible...except for the home stack/task if the
3539                 // docked stack is minimized and it actually set something.
3540                 if (mHomeStack != null && mHomeStack.isVisible()
3541                         && mDividerControllerLocked.isMinimizedDock()
3542                         // TODO(b/110159357): Work around to unblock the release for failing test
3543                         // ActivityManagerAppConfigurationTests#testSplitscreenPortraitAppOrientationRequests
3544                         // which shouldn't be failing since home stack shouldn't be visible. We need
3545                         // to dig deeper to see why it is failing. NOTE: Not failing on current
3546                         // master...
3547                         && !(mDividerControllerLocked.isHomeStackResizable()
3548                             && mHomeStack.matchParentBounds())) {
3549                     final int orientation = mHomeStack.getOrientation();
3550                     if (orientation != SCREEN_ORIENTATION_UNSET) {
3551                         return orientation;
3552                     }
3553                 }
3554                 return SCREEN_ORIENTATION_UNSPECIFIED;
3555             }
3556 
3557             final int orientation = super.getOrientation();
3558             boolean isCar = mService.mContext.getPackageManager().hasSystemFeature(
3559                     PackageManager.FEATURE_AUTOMOTIVE);
3560             if (isCar) {
3561                 // In a car, you cannot physically rotate the screen, so it doesn't make sense to
3562                 // allow anything but the default orientation.
3563                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3564                         "Forcing UNSPECIFIED orientation in car for display id=" + mDisplayId
3565                                 + ". Ignoring " + orientation);
3566                 return SCREEN_ORIENTATION_UNSPECIFIED;
3567             }
3568 
3569             if (orientation != SCREEN_ORIENTATION_UNSET
3570                     && orientation != SCREEN_ORIENTATION_BEHIND) {
3571                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3572                         "App is requesting an orientation, return " + orientation
3573                                 + " for display id=" + mDisplayId);
3574                 return orientation;
3575             }
3576 
3577             if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3578                     "No app is requesting an orientation, return " + mLastOrientation
3579                             + " for display id=" + mDisplayId);
3580             // The next app has not been requested to be visible, so we keep the current orientation
3581             // to prevent freezing/unfreezing the display too early.
3582             return mLastOrientation;
3583         }
3584 
3585         @Override
assignChildLayers(SurfaceControl.Transaction t)3586         void assignChildLayers(SurfaceControl.Transaction t) {
3587             assignStackOrdering(t);
3588 
3589             for (int i = 0; i < mChildren.size(); i++) {
3590                 final TaskStack s = mChildren.get(i);
3591                 s.assignChildLayers(t);
3592             }
3593         }
3594 
assignStackOrdering(SurfaceControl.Transaction t)3595         void assignStackOrdering(SurfaceControl.Transaction t) {
3596 
3597             final int HOME_STACK_STATE = 0;
3598             final int NORMAL_STACK_STATE = 1;
3599             final int ALWAYS_ON_TOP_STATE = 2;
3600 
3601             int layer = 0;
3602             int layerForAnimationLayer = 0;
3603             int layerForBoostedAnimationLayer = 0;
3604             int layerForHomeAnimationLayer = 0;
3605 
3606             for (int state = 0; state <= ALWAYS_ON_TOP_STATE; state++) {
3607                 for (int i = 0; i < mChildren.size(); i++) {
3608                     final TaskStack s = mChildren.get(i);
3609                     if (state == HOME_STACK_STATE && !s.isActivityTypeHome()) {
3610                         continue;
3611                     } else if (state == NORMAL_STACK_STATE && (s.isActivityTypeHome()
3612                             || s.isAlwaysOnTop())) {
3613                         continue;
3614                     } else if (state == ALWAYS_ON_TOP_STATE && !s.isAlwaysOnTop()) {
3615                         continue;
3616                     }
3617                     s.assignLayer(t, layer++);
3618                     if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) {
3619                         t.setLayer(mSplitScreenDividerAnchor, layer++);
3620                     }
3621                     if ((s.isTaskAnimating() || s.isAppAnimating())
3622                             && state != ALWAYS_ON_TOP_STATE) {
3623                         // Ensure the animation layer ends up above the
3624                         // highest animating stack and no higher.
3625                         layerForAnimationLayer = layer++;
3626                     }
3627                     if (state != ALWAYS_ON_TOP_STATE) {
3628                         layerForBoostedAnimationLayer = layer++;
3629                     }
3630                 }
3631                 if (state == HOME_STACK_STATE) {
3632                     layerForHomeAnimationLayer = layer++;
3633                 }
3634             }
3635             if (mAppAnimationLayer != null) {
3636                 t.setLayer(mAppAnimationLayer, layerForAnimationLayer);
3637             }
3638             if (mBoostedAppAnimationLayer != null) {
3639                 t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
3640             }
3641             if (mHomeAppAnimationLayer != null) {
3642                 t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer);
3643             }
3644         }
3645 
3646         @Override
getAppAnimationLayer(@nimationLayer int animationLayer)3647         SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
3648             switch (animationLayer) {
3649                 case ANIMATION_LAYER_BOOSTED:
3650                     return mBoostedAppAnimationLayer;
3651                 case ANIMATION_LAYER_HOME:
3652                     return mHomeAppAnimationLayer;
3653                 case ANIMATION_LAYER_STANDARD:
3654                 default:
3655                     return mAppAnimationLayer;
3656             }
3657         }
3658 
getSplitScreenDividerAnchor()3659         SurfaceControl getSplitScreenDividerAnchor() {
3660             return mSplitScreenDividerAnchor;
3661         }
3662 
3663         @Override
onParentSet()3664         void onParentSet() {
3665             super.onParentSet();
3666             if (getParent() != null) {
3667                 mAppAnimationLayer = makeChildSurface(null)
3668                         .setName("animationLayer")
3669                         .build();
3670                 mBoostedAppAnimationLayer = makeChildSurface(null)
3671                         .setName("boostedAnimationLayer")
3672                         .build();
3673                 mHomeAppAnimationLayer = makeChildSurface(null)
3674                         .setName("homeAnimationLayer")
3675                         .build();
3676                 mSplitScreenDividerAnchor = makeChildSurface(null)
3677                         .setName("splitScreenDividerAnchor")
3678                         .build();
3679                 getPendingTransaction()
3680                         .show(mAppAnimationLayer)
3681                         .show(mBoostedAppAnimationLayer)
3682                         .show(mHomeAppAnimationLayer)
3683                         .show(mSplitScreenDividerAnchor);
3684                 scheduleAnimation();
3685             } else {
3686                 mAppAnimationLayer.destroy();
3687                 mAppAnimationLayer = null;
3688                 mBoostedAppAnimationLayer.destroy();
3689                 mBoostedAppAnimationLayer = null;
3690                 mHomeAppAnimationLayer.destroy();
3691                 mHomeAppAnimationLayer = null;
3692                 mSplitScreenDividerAnchor.destroy();
3693                 mSplitScreenDividerAnchor = null;
3694             }
3695         }
3696     }
3697 
3698     private final class AboveAppWindowContainers extends NonAppWindowContainers {
AboveAppWindowContainers(String name, WindowManagerService service)3699         AboveAppWindowContainers(String name, WindowManagerService service) {
3700             super(name, service);
3701         }
3702 
3703         @Override
assignChildLayers(SurfaceControl.Transaction t)3704         void assignChildLayers(SurfaceControl.Transaction t) {
3705             assignChildLayers(t, null /* imeContainer */);
3706         }
3707 
assignChildLayers(SurfaceControl.Transaction t, WindowContainer imeContainer)3708         void assignChildLayers(SurfaceControl.Transaction t, WindowContainer imeContainer) {
3709             boolean needAssignIme = imeContainer != null
3710                     && imeContainer.getSurfaceControl() != null;
3711             for (int j = 0; j < mChildren.size(); ++j) {
3712                 final WindowToken wt = mChildren.get(j);
3713 
3714                 // See {@link mSplitScreenDividerAnchor}
3715                 if (wt.windowType == TYPE_DOCK_DIVIDER) {
3716                     wt.assignRelativeLayer(t, mTaskStackContainers.getSplitScreenDividerAnchor(), 1);
3717                     continue;
3718                 }
3719                 wt.assignLayer(t, j);
3720                 wt.assignChildLayers(t);
3721 
3722                 int layer = mService.mPolicy.getWindowLayerFromTypeLw(
3723                         wt.windowType, wt.mOwnerCanManageAppTokens);
3724 
3725                 if (needAssignIme && layer >= mService.mPolicy.getWindowLayerFromTypeLw(
3726                                 TYPE_INPUT_METHOD_DIALOG, true)) {
3727                     imeContainer.assignRelativeLayer(t, wt.getSurfaceControl(), -1);
3728                     needAssignIme = false;
3729                 }
3730             }
3731             if (needAssignIme) {
3732                 imeContainer.assignRelativeLayer(t, getSurfaceControl(), Integer.MAX_VALUE);
3733             }
3734         }
3735     }
3736 
3737     /**
3738      * Window container class that contains all containers on this display that are not related to
3739      * Apps. E.g. status bar.
3740      */
3741     private class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
3742         /**
3743          * Compares two child window tokens returns -1 if the first is lesser than the second in
3744          * terms of z-order and 1 otherwise.
3745          */
3746         private final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
3747                 // Tokens with higher base layer are z-ordered on-top.
3748                 mService.mPolicy.getWindowLayerFromTypeLw(token1.windowType,
3749                         token1.mOwnerCanManageAppTokens)
3750                 < mService.mPolicy.getWindowLayerFromTypeLw(token2.windowType,
3751                         token2.mOwnerCanManageAppTokens) ? -1 : 1;
3752 
3753         private final Predicate<WindowState> mGetOrientingWindow = w -> {
3754             if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) {
3755                 return false;
3756             }
3757             final int req = w.mAttrs.screenOrientation;
3758             if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND
3759                     || req == SCREEN_ORIENTATION_UNSET) {
3760                 return false;
3761             }
3762             return true;
3763         };
3764 
3765         private final String mName;
3766         private final Dimmer mDimmer = new Dimmer(this);
3767         private final Rect mTmpDimBoundsRect = new Rect();
3768 
NonAppWindowContainers(String name, WindowManagerService service)3769         NonAppWindowContainers(String name, WindowManagerService service) {
3770             super(service);
3771             mName = name;
3772         }
3773 
addChild(WindowToken token)3774         void addChild(WindowToken token) {
3775             addChild(token, mWindowComparator);
3776         }
3777 
3778         @Override
getOrientation()3779         int getOrientation() {
3780             final WindowManagerPolicy policy = mService.mPolicy;
3781             // Find a window requesting orientation.
3782             final WindowState win = getWindow(mGetOrientingWindow);
3783 
3784             if (win != null) {
3785                 final int req = win.mAttrs.screenOrientation;
3786                 if (policy.isKeyguardHostWindow(win.mAttrs)) {
3787                     mLastKeyguardForcedOrientation = req;
3788                     if (mService.mKeyguardGoingAway) {
3789                         // Keyguard can't affect the orientation if it is going away...
3790                         mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
3791                         return SCREEN_ORIENTATION_UNSET;
3792                     }
3793                 }
3794                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req
3795                         + " for display id=" + mDisplayId);
3796                 return (mLastWindowForcedOrientation = req);
3797             }
3798 
3799             mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
3800 
3801             // Only allow force setting the orientation when all unknown visibilities have been
3802             // resolved, as otherwise we just may be starting another occluding activity.
3803             final boolean isUnoccluding =
3804                     mService.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
3805                             && mService.mUnknownAppVisibilityController.allResolved();
3806             if (policy.isKeyguardShowingAndNotOccluded() || isUnoccluding) {
3807                 return mLastKeyguardForcedOrientation;
3808             }
3809 
3810             return SCREEN_ORIENTATION_UNSET;
3811         }
3812 
3813         @Override
getName()3814         String getName() {
3815             return mName;
3816         }
3817 
3818         @Override
getDimmer()3819         Dimmer getDimmer() {
3820             return mDimmer;
3821         }
3822 
3823         @Override
prepareSurfaces()3824         void prepareSurfaces() {
3825             mDimmer.resetDimStates();
3826             super.prepareSurfaces();
3827             getBounds(mTmpDimBoundsRect);
3828 
3829             if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
3830                 scheduleAnimation();
3831             }
3832         }
3833     }
3834 
3835     private class NonMagnifiableWindowContainers extends NonAppWindowContainers {
NonMagnifiableWindowContainers(String name, WindowManagerService service)3836         NonMagnifiableWindowContainers(String name, WindowManagerService service) {
3837             super(name, service);
3838         }
3839 
3840         @Override
applyMagnificationSpec(Transaction t, MagnificationSpec spec)3841         void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
3842         }
3843     };
3844 
makeSurface(SurfaceSession s)3845     SurfaceControl.Builder makeSurface(SurfaceSession s) {
3846         return mService.makeSurfaceBuilder(s)
3847                 .setParent(mWindowingLayer);
3848     }
3849 
3850     @Override
getSession()3851     SurfaceSession getSession() {
3852         return mSession;
3853     }
3854 
3855     @Override
makeChildSurface(WindowContainer child)3856     SurfaceControl.Builder makeChildSurface(WindowContainer child) {
3857         SurfaceSession s = child != null ? child.getSession() : getSession();
3858         final SurfaceControl.Builder b = mService.makeSurfaceBuilder(s);
3859         b.setSize(mSurfaceSize, mSurfaceSize);
3860 
3861         if (child == null) {
3862             return b;
3863         }
3864 
3865         return b.setName(child.getName())
3866                 .setParent(mWindowingLayer);
3867     }
3868 
3869     /**
3870      * The makeSurface variants are for use by the window-container
3871      * hierarchy. makeOverlay here is a function for various non windowing
3872      * overlays like the ScreenRotation screenshot, the Strict Mode Flash
3873      * and other potpourii.
3874      */
makeOverlay()3875     SurfaceControl.Builder makeOverlay() {
3876         return mService.makeSurfaceBuilder(mSession)
3877             .setParent(mOverlayLayer);
3878     }
3879 
3880     /**
3881      * Reparents the given surface to mOverlayLayer.
3882      */
reparentToOverlay(Transaction transaction, SurfaceControl surface)3883     void reparentToOverlay(Transaction transaction, SurfaceControl surface) {
3884         transaction.reparent(surface, mOverlayLayer.getHandle());
3885     }
3886 
applyMagnificationSpec(MagnificationSpec spec)3887     void applyMagnificationSpec(MagnificationSpec spec) {
3888         if (spec.scale != 1.0) {
3889             mMagnificationSpec = spec;
3890         } else {
3891             mMagnificationSpec = null;
3892         }
3893 
3894         applyMagnificationSpec(getPendingTransaction(), spec);
3895         getPendingTransaction().apply();
3896     }
3897 
reapplyMagnificationSpec()3898     void reapplyMagnificationSpec() {
3899         if (mMagnificationSpec != null) {
3900             applyMagnificationSpec(getPendingTransaction(), mMagnificationSpec);
3901         }
3902     }
3903 
3904     @Override
onParentSet()3905     void onParentSet() {
3906         // Since we are the top of the SurfaceControl hierarchy here
3907         // we create the root surfaces explicitly rather than chaining
3908         // up as the default implementation in onParentSet does. So we
3909         // explicitly do NOT call super here.
3910     }
3911 
3912     @Override
assignChildLayers(SurfaceControl.Transaction t)3913     void assignChildLayers(SurfaceControl.Transaction t) {
3914 
3915         // These are layers as children of "mWindowingLayer"
3916         mBelowAppWindowsContainers.assignLayer(t, 0);
3917         mTaskStackContainers.assignLayer(t, 1);
3918         mAboveAppWindowsContainers.assignLayer(t, 2);
3919 
3920         WindowState imeTarget = mService.mInputMethodTarget;
3921         boolean needAssignIme = true;
3922 
3923         // In the case where we have an IME target that is not in split-screen
3924         // mode IME assignment is easy. We just need the IME to go directly above
3925         // the target. This way children of the target will naturally go above the IME
3926         // and everyone is happy.
3927         //
3928         // In the case of split-screen windowing mode, we need to elevate the IME above the
3929         // docked divider while keeping the app itself below the docked divider, so instead
3930         // we use relative layering of the IME targets child windows, and place the
3931         // IME in the non-app layer (see {@link AboveAppWindowContainers#assignChildLayers}).
3932         //
3933         // In the case the IME target is animating, the animation Z order may be different
3934         // than the WindowContainer Z order, so it's difficult to be sure we have the correct
3935         // IME target. In this case we just layer the IME over all transitions by placing it in the
3936         // above applications layer.
3937         //
3938         // In the case where we have no IME target we assign it where it's base layer would
3939         // place it in the AboveAppWindowContainers.
3940         if (imeTarget != null && !(imeTarget.inSplitScreenWindowingMode()
3941                 || imeTarget.mToken.isAppAnimating())
3942                 && (imeTarget.getSurfaceControl() != null)) {
3943             mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
3944                     // TODO: We need to use an extra level on the app surface to ensure
3945                     // this is always above SurfaceView but always below attached window.
3946                     1);
3947             needAssignIme = false;
3948         }
3949 
3950         // Above we have assigned layers to our children, now we ask them to assign
3951         // layers to their children.
3952         mBelowAppWindowsContainers.assignChildLayers(t);
3953         mTaskStackContainers.assignChildLayers(t);
3954         mAboveAppWindowsContainers.assignChildLayers(t,
3955                 needAssignIme == true ? mImeWindowsContainers : null);
3956         mImeWindowsContainers.assignChildLayers(t);
3957     }
3958 
3959     /**
3960      * Here we satisfy an unfortunate special case of the IME in split-screen mode. Imagine
3961      * that the IME target is one of the docked applications. We'd like the docked divider to be
3962      * above both of the applications, and we'd like the IME to be above the docked divider.
3963      * However we need child windows of the applications to be above the IME (Text drag handles).
3964      * This is a non-strictly hierarcical layering and we need to break out of the Z ordering
3965      * somehow. We do this by relatively ordering children of the target to the IME in cooperation
3966      * with {@link #WindowState#assignLayer}
3967      */
assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child)3968     void assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child) {
3969         child.assignRelativeLayer(t, mImeWindowsContainers.getSurfaceControl(), 1);
3970     }
3971 
3972     @Override
prepareSurfaces()3973     void prepareSurfaces() {
3974         final ScreenRotationAnimation screenRotationAnimation =
3975                 mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
3976         if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
3977             screenRotationAnimation.getEnterTransformation().getMatrix().getValues(mTmpFloats);
3978             mPendingTransaction.setMatrix(mWindowingLayer,
3979                     mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
3980                     mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
3981             mPendingTransaction.setPosition(mWindowingLayer,
3982                     mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]);
3983             mPendingTransaction.setAlpha(mWindowingLayer,
3984                     screenRotationAnimation.getEnterTransformation().getAlpha());
3985         }
3986 
3987         super.prepareSurfaces();
3988     }
3989 
assignStackOrdering()3990     void assignStackOrdering() {
3991         mTaskStackContainers.assignStackOrdering(getPendingTransaction());
3992     }
3993 
3994     /**
3995      * Increment the deferral count to determine whether to update the IME target.
3996      */
deferUpdateImeTarget()3997     void deferUpdateImeTarget() {
3998         mDeferUpdateImeTargetCount++;
3999     }
4000 
4001     /**
4002      * Decrement the deferral count to determine whether to update the IME target. If the count
4003      * reaches 0, a new ime target will get computed.
4004      */
continueUpdateImeTarget()4005     void continueUpdateImeTarget() {
4006         if (mDeferUpdateImeTargetCount == 0) {
4007             return;
4008         }
4009 
4010         mDeferUpdateImeTargetCount--;
4011         if (mDeferUpdateImeTargetCount == 0) {
4012             computeImeTarget(true /* updateImeTarget */);
4013         }
4014     }
4015 
4016     /**
4017      * @return Whether a new IME target should be computed.
4018      */
canUpdateImeTarget()4019     private boolean canUpdateImeTarget() {
4020         return mDeferUpdateImeTargetCount == 0;
4021     }
4022 }
4023