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