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