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