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