Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2011 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.INVALID_STACK_ID;
     20 import static android.app.AppOpsManager.MODE_ALLOWED;
     21 import static android.app.AppOpsManager.MODE_DEFAULT;
     22 import static android.app.AppOpsManager.OP_NONE;
     23 import static android.os.PowerManager.DRAW_WAKE_LOCK;
     24 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
     25 import static android.view.Display.DEFAULT_DISPLAY;
     26 import static android.view.SurfaceControl.Transaction;
     27 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
     28 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
     29 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
     30 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
     31 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
     32 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
     33 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
     34 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
     35 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
     36 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
     37 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
     38 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
     39 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
     40 import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
     41 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
     42 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
     43 import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
     44 import static android.view.WindowManager.LayoutParams.FORMAT_CHANGED;
     45 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
     46 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
     47 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
     48 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
     49 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
     50 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
     51 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
     52 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
     53 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
     54 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
     55 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
     56 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
     57 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
     58 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
     59 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
     60 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
     61 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
     62 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
     63 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
     64 import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
     65 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
     66 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
     67 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
     68 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
     69 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
     70 import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED;
     71 import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM;
     72 import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
     73 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
     74 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
     75 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
     76 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
     77 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
     78 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
     79 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
     80 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
     81 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
     82 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
     83 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
     84 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
     85 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
     86 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
     87 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
     88 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
     89 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
     90 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
     91 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
     92 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
     93 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
     94 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
     95 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
     96 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
     97 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
     98 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
     99 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
    100 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
    101 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
    102 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
    103 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
    104 import static com.android.server.wm.WindowManagerService.localLOGV;
    105 import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING;
    106 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
    107 import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
    108 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
    109 import static com.android.server.wm.IdentifierProto.HASH_CODE;
    110 import static com.android.server.wm.IdentifierProto.TITLE;
    111 import static com.android.server.wm.IdentifierProto.USER_ID;
    112 import static com.android.server.wm.AnimationSpecProto.MOVE;
    113 import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS;
    114 import static com.android.server.wm.MoveAnimationSpecProto.FROM;
    115 import static com.android.server.wm.MoveAnimationSpecProto.TO;
    116 import static com.android.server.wm.WindowStateProto.ANIMATING_EXIT;
    117 import static com.android.server.wm.WindowStateProto.ANIMATOR;
    118 import static com.android.server.wm.WindowStateProto.ATTRIBUTES;
    119 import static com.android.server.wm.WindowStateProto.CHILD_WINDOWS;
    120 import static com.android.server.wm.WindowStateProto.CONTAINING_FRAME;
    121 import static com.android.server.wm.WindowStateProto.CONTENT_FRAME;
    122 import static com.android.server.wm.WindowStateProto.CONTENT_INSETS;
    123 import static com.android.server.wm.WindowStateProto.CUTOUT;
    124 import static com.android.server.wm.WindowStateProto.DECOR_FRAME;
    125 import static com.android.server.wm.WindowStateProto.DESTROYING;
    126 import static com.android.server.wm.WindowStateProto.DISPLAY_FRAME;
    127 import static com.android.server.wm.WindowStateProto.DISPLAY_ID;
    128 import static com.android.server.wm.WindowStateProto.FRAME;
    129 import static com.android.server.wm.WindowStateProto.GIVEN_CONTENT_INSETS;
    130 import static com.android.server.wm.WindowStateProto.HAS_SURFACE;
    131 import static com.android.server.wm.WindowStateProto.IDENTIFIER;
    132 import static com.android.server.wm.WindowStateProto.IS_ON_SCREEN;
    133 import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY;
    134 import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
    135 import static com.android.server.wm.WindowStateProto.OUTSETS;
    136 import static com.android.server.wm.WindowStateProto.OUTSET_FRAME;
    137 import static com.android.server.wm.WindowStateProto.OVERSCAN_FRAME;
    138 import static com.android.server.wm.WindowStateProto.OVERSCAN_INSETS;
    139 import static com.android.server.wm.WindowStateProto.PARENT_FRAME;
    140 import static com.android.server.wm.WindowStateProto.REMOVED;
    141 import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT;
    142 import static com.android.server.wm.WindowStateProto.REQUESTED_HEIGHT;
    143 import static com.android.server.wm.WindowStateProto.REQUESTED_WIDTH;
    144 import static com.android.server.wm.WindowStateProto.STABLE_INSETS;
    145 import static com.android.server.wm.WindowStateProto.STACK_ID;
    146 import static com.android.server.wm.WindowStateProto.SURFACE_INSETS;
    147 import static com.android.server.wm.WindowStateProto.SURFACE_POSITION;
    148 import static com.android.server.wm.WindowStateProto.SYSTEM_UI_VISIBILITY;
    149 import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
    150 import static com.android.server.wm.WindowStateProto.VISIBLE_FRAME;
    151 import static com.android.server.wm.WindowStateProto.VISIBLE_INSETS;
    152 import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
    153 
    154 import android.annotation.CallSuper;
    155 import android.app.AppOpsManager;
    156 import android.content.Context;
    157 import android.content.res.Configuration;
    158 import android.graphics.Matrix;
    159 import android.graphics.PixelFormat;
    160 import android.graphics.Point;
    161 import android.graphics.Rect;
    162 import android.graphics.Region;
    163 import android.os.Binder;
    164 import android.os.Debug;
    165 import android.os.IBinder;
    166 import android.os.PowerManager;
    167 import android.os.RemoteCallbackList;
    168 import android.os.RemoteException;
    169 import android.os.SystemClock;
    170 import android.os.Trace;
    171 import android.os.UserHandle;
    172 import android.os.WorkSource;
    173 import android.provider.Settings;
    174 import android.text.TextUtils;
    175 import android.util.DisplayMetrics;
    176 import android.util.MergedConfiguration;
    177 import android.util.Slog;
    178 import android.util.TimeUtils;
    179 import android.util.proto.ProtoOutputStream;
    180 import android.view.Display;
    181 import android.view.DisplayCutout;
    182 import android.view.DisplayInfo;
    183 import android.view.Gravity;
    184 import android.view.IApplicationToken;
    185 import android.view.IWindow;
    186 import android.view.IWindowFocusObserver;
    187 import android.view.IWindowId;
    188 import android.view.InputChannel;
    189 import android.view.InputEvent;
    190 import android.view.InputEventReceiver;
    191 import android.view.SurfaceControl;
    192 import android.view.SurfaceSession;
    193 import android.view.View;
    194 import android.view.ViewTreeObserver;
    195 import android.view.WindowInfo;
    196 import android.view.WindowManager;
    197 import android.view.animation.Animation;
    198 import android.view.animation.AnimationUtils;
    199 import android.view.animation.Interpolator;
    200 
    201 import com.android.internal.annotations.VisibleForTesting;
    202 import com.android.internal.util.ToBooleanFunction;
    203 import com.android.server.input.InputWindowHandle;
    204 import com.android.server.policy.WindowManagerPolicy;
    205 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
    206 import com.android.server.wm.utils.WmDisplayCutout;
    207 
    208 import java.io.PrintWriter;
    209 import java.lang.ref.WeakReference;
    210 import java.util.ArrayList;
    211 import java.util.Comparator;
    212 import java.util.function.Predicate;
    213 
    214 /** A window in the window manager. */
    215 class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState {
    216     static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM;
    217 
    218     // The minimal size of a window within the usable area of the freeform stack.
    219     // TODO(multi-window): fix the min sizes when we have mininum width/height support,
    220     //                     use hard-coded min sizes for now.
    221     static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48;
    222     static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32;
    223 
    224     // The thickness of a window resize handle outside the window bounds on the free form workspace
    225     // to capture touch events in that area.
    226     static final int RESIZE_HANDLE_WIDTH_IN_DP = 30;
    227 
    228     final WindowManagerPolicy mPolicy;
    229     final Context mContext;
    230     final Session mSession;
    231     final IWindow mClient;
    232     final int mAppOp;
    233     // UserId and appId of the owner. Don't display windows of non-current user.
    234     final int mOwnerUid;
    235     /** The owner has {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} */
    236     final boolean mOwnerCanAddInternalSystemWindow;
    237     final WindowId mWindowId;
    238     WindowToken mToken;
    239     // The same object as mToken if this is an app window and null for non-app windows.
    240     AppWindowToken mAppToken;
    241 
    242     // mAttrs.flags is tested in animation without being locked. If the bits tested are ever
    243     // modified they will need to be locked.
    244     final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
    245     final DeathRecipient mDeathRecipient;
    246     private boolean mIsChildWindow;
    247     final int mBaseLayer;
    248     final int mSubLayer;
    249     final boolean mLayoutAttached;
    250     final boolean mIsImWindow;
    251     final boolean mIsWallpaper;
    252     private final boolean mIsFloatingLayer;
    253     int mSeq;
    254     boolean mEnforceSizeCompat;
    255     int mViewVisibility;
    256     int mSystemUiVisibility;
    257     /**
    258      * The visibility of the window based on policy like {@link WindowManagerPolicy}.
    259      * Normally set by calling {@link #showLw} and {@link #hideLw}.
    260      */
    261     boolean mPolicyVisibility = true;
    262     /**
    263      * What {@link #mPolicyVisibility} should be set to after a transition animation.
    264      * For example, {@link #mPolicyVisibility} might true during an exit animation to hide it and
    265      * then set to the value of {@link #mPolicyVisibilityAfterAnim} which is false after the exit
    266      * animation is done.
    267      */
    268     boolean mPolicyVisibilityAfterAnim = true;
    269     // overlay window is hidden because the owning app is suspended
    270     private boolean mHiddenWhileSuspended;
    271     private boolean mAppOpVisibility = true;
    272     boolean mPermanentlyHidden; // the window should never be shown again
    273     // This is a non-system overlay window that is currently force hidden.
    274     private boolean mForceHideNonSystemOverlayWindow;
    275     boolean mAppFreezing;
    276     boolean mHidden = true;    // Used to determine if to show child windows.
    277     boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
    278     private boolean mDragResizing;
    279     private boolean mDragResizingChangeReported = true;
    280     private int mResizeMode;
    281 
    282     private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
    283 
    284     /**
    285      * The window size that was requested by the application.  These are in
    286      * the application's coordinate space (without compatibility scale applied).
    287      */
    288     int mRequestedWidth;
    289     int mRequestedHeight;
    290     private int mLastRequestedWidth;
    291     private int mLastRequestedHeight;
    292 
    293     int mLayer;
    294     boolean mHaveFrame;
    295     boolean mObscured;
    296 
    297     int mLayoutSeq = -1;
    298 
    299     /**
    300      * Used to store last reported to client configuration and check if we have newer available.
    301      * We'll send configuration to client only if it is different from the last applied one and
    302      * client won't perform unnecessary updates.
    303      */
    304     private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration();
    305 
    306     /**
    307      * Insets that determine the actually visible area.  These are in the application's
    308      * coordinate space (without compatibility scale applied).
    309      */
    310     final Rect mVisibleInsets = new Rect();
    311     private final Rect mLastVisibleInsets = new Rect();
    312     private boolean mVisibleInsetsChanged;
    313 
    314     /**
    315      * Insets that are covered by system windows (such as the status bar) and
    316      * transient docking windows (such as the IME).  These are in the application's
    317      * coordinate space (without compatibility scale applied).
    318      */
    319     final Rect mContentInsets = new Rect();
    320     final Rect mLastContentInsets = new Rect();
    321 
    322     /**
    323      * The last content insets returned to the client in relayout. We use
    324      * these in the bounds animation to ensure we only observe inset changes
    325      * at the same time that a client resizes it's surface so that we may use
    326      * the geometryAppliesWithResize synchronization mechanism to keep
    327      * the contents in place.
    328      */
    329     final Rect mLastRelayoutContentInsets = new Rect();
    330 
    331     private boolean mContentInsetsChanged;
    332 
    333     /**
    334      * Insets that determine the area covered by the display overscan region.  These are in the
    335      * application's coordinate space (without compatibility scale applied).
    336      */
    337     final Rect mOverscanInsets = new Rect();
    338     private final Rect mLastOverscanInsets = new Rect();
    339     private boolean mOverscanInsetsChanged;
    340 
    341     /**
    342      * Insets that determine the area covered by the stable system windows.  These are in the
    343      * application's coordinate space (without compatibility scale applied).
    344      */
    345     final Rect mStableInsets = new Rect();
    346     private final Rect mLastStableInsets = new Rect();
    347     private boolean mStableInsetsChanged;
    348 
    349     /**
    350      * Outsets determine the area outside of the surface where we want to pretend that it's possible
    351      * to draw anyway.
    352      */
    353     final Rect mOutsets = new Rect();
    354     private final Rect mLastOutsets = new Rect();
    355     private boolean mOutsetsChanged = false;
    356 
    357     /** Part of the display that has been cut away. See {@link DisplayCutout}. */
    358     WmDisplayCutout mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
    359     private WmDisplayCutout mLastDisplayCutout = WmDisplayCutout.NO_CUTOUT;
    360     private boolean mDisplayCutoutChanged;
    361 
    362     /**
    363      * Set to true if we are waiting for this window to receive its
    364      * given internal insets before laying out other windows based on it.
    365      */
    366     boolean mGivenInsetsPending;
    367 
    368     /**
    369      * These are the content insets that were given during layout for
    370      * this window, to be applied to windows behind it.
    371      */
    372     final Rect mGivenContentInsets = new Rect();
    373 
    374     /**
    375      * These are the visible insets that were given during layout for
    376      * this window, to be applied to windows behind it.
    377      */
    378     final Rect mGivenVisibleInsets = new Rect();
    379 
    380     /**
    381      * This is the given touchable area relative to the window frame, or null if none.
    382      */
    383     final Region mGivenTouchableRegion = new Region();
    384 
    385     /**
    386      * Flag indicating whether the touchable region should be adjusted by
    387      * the visible insets; if false the area outside the visible insets is
    388      * NOT touchable, so we must use those to adjust the frame during hit
    389      * tests.
    390      */
    391     int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
    392 
    393     // Current transformation being applied.
    394     float mGlobalScale=1;
    395     float mInvGlobalScale=1;
    396     float mHScale=1, mVScale=1;
    397     float mLastHScale=1, mLastVScale=1;
    398     final Matrix mTmpMatrix = new Matrix();
    399 
    400     // "Real" frame that the application sees, in display coordinate space.
    401     final Rect mFrame = new Rect();
    402     final Rect mLastFrame = new Rect();
    403     private boolean mFrameSizeChanged = false;
    404     // Frame that is scaled to the application's coordinate space when in
    405     // screen size compatibility mode.
    406     final Rect mCompatFrame = new Rect();
    407 
    408     final Rect mContainingFrame = new Rect();
    409 
    410     final Rect mParentFrame = new Rect();
    411 
    412     /** Whether the parent frame would have been different if there was no display cutout. */
    413     private boolean mParentFrameWasClippedByDisplayCutout;
    414 
    415     // The entire screen area of the {@link TaskStack} this window is in. Usually equal to the
    416     // screen area of the device.
    417     final Rect mDisplayFrame = new Rect();
    418 
    419     // The region of the display frame that the display type supports displaying content on. This
    420     // is mostly a special case for TV where some displays dont have the entire display usable.
    421     // {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} flag can be used to allow
    422     // window display contents to extend into the overscan region.
    423     private final Rect mOverscanFrame = new Rect();
    424 
    425     // The display frame minus the stable insets. This value is always constant regardless of if
    426     // the status bar or navigation bar is visible.
    427     private final Rect mStableFrame = new Rect();
    428 
    429     // The area not occupied by the status and navigation bars. So, if both status and navigation
    430     // bars are visible, the decor frame is equal to the stable frame.
    431     final Rect mDecorFrame = new Rect();
    432 
    433     // Equal to the decor frame if the IME (e.g. keyboard) is not present. Equal to the decor frame
    434     // minus the area occupied by the IME if the IME is present.
    435     private final Rect mContentFrame = new Rect();
    436 
    437     // Legacy stuff. Generally equal to the content frame expect when the IME for older apps
    438     // displays hint text.
    439     final Rect mVisibleFrame = new Rect();
    440 
    441     // Frame that includes dead area outside of the surface but where we want to pretend that it's
    442     // possible to draw.
    443     private final Rect mOutsetFrame = new Rect();
    444 
    445     /**
    446      * Usually empty. Set to the task's tempInsetFrame. See
    447      *{@link android.app.IActivityManager#resizeDockedStack}.
    448      */
    449     private final Rect mInsetFrame = new Rect();
    450 
    451     boolean mContentChanged;
    452 
    453     // If a window showing a wallpaper: the requested offset for the
    454     // wallpaper; if a wallpaper window: the currently applied offset.
    455     float mWallpaperX = -1;
    456     float mWallpaperY = -1;
    457 
    458     // If a window showing a wallpaper: what fraction of the offset
    459     // range corresponds to a full virtual screen.
    460     float mWallpaperXStep = -1;
    461     float mWallpaperYStep = -1;
    462 
    463     // If a window showing a wallpaper: a raw pixel offset to forcibly apply
    464     // to its window; if a wallpaper window: not used.
    465     int mWallpaperDisplayOffsetX = Integer.MIN_VALUE;
    466     int mWallpaperDisplayOffsetY = Integer.MIN_VALUE;
    467 
    468     /**
    469      * This is set after IWindowSession.relayout() has been called at
    470      * least once for the window.  It allows us to detect the situation
    471      * where we don't yet have a surface, but should have one soon, so
    472      * we can give the window focus before waiting for the relayout.
    473      */
    474     boolean mRelayoutCalled;
    475 
    476     boolean mInRelayout;
    477 
    478     /**
    479      * If the application has called relayout() with changes that can
    480      * impact its window's size, we need to perform a layout pass on it
    481      * even if it is not currently visible for layout.  This is set
    482      * when in that case until the layout is done.
    483      */
    484     boolean mLayoutNeeded;
    485 
    486     /** Currently running an exit animation? */
    487     boolean mAnimatingExit;
    488 
    489     /** Currently on the mDestroySurface list? */
    490     boolean mDestroying;
    491 
    492     /** Completely remove from window manager after exit animation? */
    493     boolean mRemoveOnExit;
    494 
    495     /**
    496      * Whether the app died while it was visible, if true we might need
    497      * to continue to show it until it's restarted.
    498      */
    499     boolean mAppDied;
    500 
    501     /**
    502      * Set when the orientation is changing and this window has not yet
    503      * been updated for the new orientation.
    504      */
    505     private boolean mOrientationChanging;
    506 
    507     /**
    508      * Sometimes in addition to the mOrientationChanging
    509      * flag we report that the orientation is changing
    510      * due to a mismatch in current and reported configuration.
    511      *
    512      * In the case of timeout we still need to make sure we
    513      * leave the orientation changing state though, so we
    514      * use this as a special time out escape hatch.
    515      */
    516     private boolean mOrientationChangeTimedOut;
    517 
    518     /**
    519      * The orientation during the last visible call to relayout. If our
    520      * current orientation is different, the window can't be ready
    521      * to be shown.
    522      */
    523     int mLastVisibleLayoutRotation = -1;
    524 
    525     /**
    526      * Set when we need to report the orientation change to client to trigger a relayout.
    527      */
    528     boolean mReportOrientationChanged;
    529 
    530     /**
    531      * How long we last kept the screen frozen.
    532      */
    533     int mLastFreezeDuration;
    534 
    535     /** Is this window now (or just being) removed? */
    536     boolean mRemoved;
    537 
    538     /**
    539      * It is save to remove the window and destroy the surface because the client requested removal
    540      * or some other higher level component said so (e.g. activity manager).
    541      * TODO: We should either have different booleans for the removal reason or use a bit-field.
    542      */
    543     boolean mWindowRemovalAllowed;
    544 
    545     // Input channel and input window handle used by the input dispatcher.
    546     final InputWindowHandle mInputWindowHandle;
    547     InputChannel mInputChannel;
    548     private InputChannel mClientChannel;
    549 
    550     // Used to improve performance of toString()
    551     private String mStringNameCache;
    552     private CharSequence mLastTitle;
    553     private boolean mWasExiting;
    554 
    555     final WindowStateAnimator mWinAnimator;
    556 
    557     boolean mHasSurface = false;
    558 
    559     /** When true this window can be displayed on screens owther than mOwnerUid's */
    560     private boolean mShowToOwnerOnly;
    561 
    562     // Whether the window was visible when we set the app to invisible last time. WM uses
    563     // this as a hint to restore the surface (if available) for early animation next time
    564     // the app is brought visible.
    565     private boolean mWasVisibleBeforeClientHidden;
    566 
    567     // This window will be replaced due to relaunch. This allows window manager
    568     // to differentiate between simple removal of a window and replacement. In the latter case it
    569     // will preserve the old window until the new one is drawn.
    570     boolean mWillReplaceWindow = false;
    571     // If true, the replaced window was already requested to be removed.
    572     private boolean mReplacingRemoveRequested = false;
    573     // Whether the replacement of the window should trigger app transition animation.
    574     private boolean mAnimateReplacingWindow = false;
    575     // If not null, the window that will be used to replace the old one. This is being set when
    576     // the window is added and unset when this window reports its first draw.
    577     private WindowState mReplacementWindow = null;
    578     // For the new window in the replacement transition, if we have
    579     // requested to replace without animation, then we should
    580     // make sure we also don't apply an enter animation for
    581     // the new window.
    582     boolean mSkipEnterAnimationForSeamlessReplacement = false;
    583     // Whether this window is being moved via the resize API
    584     private boolean mMovedByResize;
    585 
    586     /**
    587      * Wake lock for drawing.
    588      * Even though it's slightly more expensive to do so, we will use a separate wake lock
    589      * for each app that is requesting to draw while dozing so that we can accurately track
    590      * who is preventing the system from suspending.
    591      * This lock is only acquired on first use.
    592      */
    593     private PowerManager.WakeLock mDrawLock;
    594 
    595     final private Rect mTmpRect = new Rect();
    596 
    597     /**
    598      * Whether the window was resized by us while it was gone for layout.
    599      */
    600     boolean mResizedWhileGone = false;
    601 
    602     /**
    603      * During seamless rotation we have two phases, first the old window contents
    604      * are rotated to look as if they didn't move in the new coordinate system. Then we
    605      * have to freeze updates to this layer (to preserve the transformation) until
    606      * the resize actually occurs. This is true from when the transformation is set
    607      * and false until the transaction to resize is sent.
    608      */
    609     boolean mSeamlesslyRotated = false;
    610 
    611     /**
    612      * Surface insets from the previous call to relayout(), used to track
    613      * if we are changing the Surface insets.
    614      */
    615     final Rect mLastSurfaceInsets = new Rect();
    616 
    617     /**
    618      * A flag set by the {@link WindowState} parent to indicate that the parent has examined this
    619      * {@link WindowState} in its overall drawing context. This book-keeping allows the parent to
    620      * make sure all children have been considered.
    621      */
    622     private boolean mDrawnStateEvaluated;
    623 
    624     private final Point mSurfacePosition = new Point();
    625 
    626     /**
    627      * A region inside of this window to be excluded from touch-related focus switches.
    628      */
    629     private TapExcludeRegionHolder mTapExcludeRegionHolder;
    630 
    631     /**
    632      * Used for testing because the real PowerManager is final.
    633      */
    634     private PowerManagerWrapper mPowerManagerWrapper;
    635 
    636     /**
    637      * A frame number in which changes requested in this layout will be rendered.
    638      */
    639     private long mFrameNumber = -1;
    640 
    641     /**
    642      * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
    643      * of z-order and 1 otherwise.
    644      */
    645     private static final Comparator<WindowState> sWindowSubLayerComparator =
    646             new Comparator<WindowState>() {
    647                 @Override
    648                 public int compare(WindowState w1, WindowState w2) {
    649                     final int layer1 = w1.mSubLayer;
    650                     final int layer2 = w2.mSubLayer;
    651                     if (layer1 < layer2 || (layer1 == layer2 && layer2 < 0 )) {
    652                         // We insert the child window into the list ordered by
    653                         // the sub-layer.  For same sub-layers, the negative one
    654                         // should go below others; the positive one should go
    655                         // above others.
    656                         return -1;
    657                     }
    658                     return 1;
    659                 };
    660             };
    661 
    662     /**
    663      * Indicates whether we have requested a Dim (in the sense of {@link Dimmer}) from our host
    664      * container.
    665      */
    666     private boolean mIsDimming = false;
    667 
    668     private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
    669 
    670     interface PowerManagerWrapper {
    671         void wakeUp(long time, String reason);
    672 
    673         boolean isInteractive();
    674 
    675     }
    676 
    677     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
    678             WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
    679             int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
    680         this(service, s, c, token, parentWindow, appOp, seq, a, viewVisibility, ownerId,
    681                 ownerCanAddInternalSystemWindow, new PowerManagerWrapper() {
    682                     @Override
    683                     public void wakeUp(long time, String reason) {
    684                         service.mPowerManager.wakeUp(time, reason);
    685                     }
    686 
    687                     @Override
    688                     public boolean isInteractive() {
    689                         return service.mPowerManager.isInteractive();
    690                     }
    691                 });
    692     }
    693 
    694     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
    695             WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
    696             int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow,
    697             PowerManagerWrapper powerManagerWrapper) {
    698         super(service);
    699         mSession = s;
    700         mClient = c;
    701         mAppOp = appOp;
    702         mToken = token;
    703         mAppToken = mToken.asAppWindowToken();
    704         mOwnerUid = ownerId;
    705         mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
    706         mWindowId = new WindowId(this);
    707         mAttrs.copyFrom(a);
    708         mLastSurfaceInsets.set(mAttrs.surfaceInsets);
    709         mViewVisibility = viewVisibility;
    710         mPolicy = mService.mPolicy;
    711         mContext = mService.mContext;
    712         DeathRecipient deathRecipient = new DeathRecipient();
    713         mSeq = seq;
    714         mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
    715         mPowerManagerWrapper = powerManagerWrapper;
    716         if (localLOGV) Slog.v(
    717             TAG, "Window " + this + " client=" + c.asBinder()
    718             + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
    719         try {
    720             c.asBinder().linkToDeath(deathRecipient, 0);
    721         } catch (RemoteException e) {
    722             mDeathRecipient = null;
    723             mIsChildWindow = false;
    724             mLayoutAttached = false;
    725             mIsImWindow = false;
    726             mIsWallpaper = false;
    727             mIsFloatingLayer = false;
    728             mBaseLayer = 0;
    729             mSubLayer = 0;
    730             mInputWindowHandle = null;
    731             mWinAnimator = null;
    732             return;
    733         }
    734         mDeathRecipient = deathRecipient;
    735 
    736         if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
    737             // The multiplier here is to reserve space for multiple
    738             // windows in the same type layer.
    739             mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)
    740                     * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
    741             mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
    742             mIsChildWindow = true;
    743 
    744             if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + parentWindow);
    745             parentWindow.addChild(this, sWindowSubLayerComparator);
    746 
    747             mLayoutAttached = mAttrs.type !=
    748                     WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
    749             mIsImWindow = parentWindow.mAttrs.type == TYPE_INPUT_METHOD
    750                     || parentWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
    751             mIsWallpaper = parentWindow.mAttrs.type == TYPE_WALLPAPER;
    752         } else {
    753             // The multiplier here is to reserve space for multiple
    754             // windows in the same type layer.
    755             mBaseLayer = mPolicy.getWindowLayerLw(this)
    756                     * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
    757             mSubLayer = 0;
    758             mIsChildWindow = false;
    759             mLayoutAttached = false;
    760             mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
    761                     || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
    762             mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
    763         }
    764         mIsFloatingLayer = mIsImWindow || mIsWallpaper;
    765 
    766         if (mAppToken != null && mAppToken.mShowForAllUsers) {
    767             // Windows for apps that can show for all users should also show when the device is
    768             // locked.
    769             mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
    770         }
    771 
    772         mWinAnimator = new WindowStateAnimator(this);
    773         mWinAnimator.mAlpha = a.alpha;
    774 
    775         mRequestedWidth = 0;
    776         mRequestedHeight = 0;
    777         mLastRequestedWidth = 0;
    778         mLastRequestedHeight = 0;
    779         mLayer = 0;
    780         mInputWindowHandle = new InputWindowHandle(
    781                 mAppToken != null ? mAppToken.mInputApplicationHandle : null, this, c,
    782                     getDisplayId());
    783     }
    784 
    785     void attach() {
    786         if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
    787         mSession.windowAddedLocked(mAttrs.packageName);
    788     }
    789 
    790     /**
    791      * Returns whether this {@link WindowState} has been considered for drawing by its parent.
    792      */
    793     boolean getDrawnStateEvaluated() {
    794         return mDrawnStateEvaluated;
    795     }
    796 
    797     /**
    798      * Sets whether this {@link WindowState} has been considered for drawing by its parent. Should
    799      * be cleared when detached from parent.
    800      */
    801     void setDrawnStateEvaluated(boolean evaluated) {
    802         mDrawnStateEvaluated = evaluated;
    803     }
    804 
    805     @Override
    806     void onParentSet() {
    807         super.onParentSet();
    808         setDrawnStateEvaluated(false /*evaluated*/);
    809 
    810         getDisplayContent().reapplyMagnificationSpec();
    811     }
    812 
    813     @Override
    814     public int getOwningUid() {
    815         return mOwnerUid;
    816     }
    817 
    818     @Override
    819     public String getOwningPackage() {
    820         return mAttrs.packageName;
    821     }
    822 
    823     @Override
    824     public boolean canAddInternalSystemWindow() {
    825         return mOwnerCanAddInternalSystemWindow;
    826     }
    827 
    828     @Override
    829     public boolean canAcquireSleepToken() {
    830         return mSession.mCanAcquireSleepToken;
    831     }
    832 
    833     /**
    834      * Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame}
    835      * from {@param frame}. In other words, it applies the insets that would result if
    836      * {@param frame} would be shifted to {@param layoutFrame} and then applying the insets from
    837      * {@param insetFrame}. Also it respects {@param displayFrame} in case window has minimum
    838      * width/height applied and insets should be overridden.
    839      */
    840     private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame, Rect displayFrame) {
    841         final int left = Math.max(0, insetFrame.left - Math.max(layoutFrame.left, displayFrame.left));
    842         final int top = Math.max(0, insetFrame.top - Math.max(layoutFrame.top, displayFrame.top));
    843         final int right = Math.max(0, Math.min(layoutFrame.right, displayFrame.right) - insetFrame.right);
    844         final int bottom = Math.max(0, Math.min(layoutFrame.bottom, displayFrame.bottom) - insetFrame.bottom);
    845         frame.inset(left, top, right, bottom);
    846     }
    847 
    848     @Override
    849     public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overscanFrame,
    850             Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame,
    851             Rect outsetFrame, WmDisplayCutout displayCutout,
    852             boolean parentFrameWasClippedByDisplayCutout) {
    853         if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
    854             // This window is being replaced and either already got information that it's being
    855             // removed or we are still waiting for some information. Because of this we don't
    856             // want to apply any more changes to it, so it remains in this state until new window
    857             // appears.
    858             return;
    859         }
    860         mHaveFrame = true;
    861         mParentFrameWasClippedByDisplayCutout = parentFrameWasClippedByDisplayCutout;
    862 
    863         final Task task = getTask();
    864         final boolean inFullscreenContainer = inFullscreenContainer();
    865         final boolean windowsAreFloating = task != null && task.isFloating();
    866         final DisplayContent dc = getDisplayContent();
    867 
    868         // If the task has temp inset bounds set, we have to make sure all its windows uses
    869         // the temp inset frame. Otherwise different display frames get applied to the main
    870         // window and the child window, making them misaligned.
    871         // Otherwise we need to clear the inset frame, to avoid using a stale frame after leaving
    872         // multi window mode.
    873         if (task != null && isInMultiWindowMode()) {
    874             task.getTempInsetBounds(mInsetFrame);
    875         } else {
    876             mInsetFrame.setEmpty();
    877         }
    878 
    879         // Denotes the actual frame used to calculate the insets and to perform the layout. When
    880         // resizing in docked mode, we'd like to freeze the layout, so we also need to freeze the
    881         // insets temporarily. By the notion of a task having a different layout frame, we can
    882         // achieve that while still moving the task around.
    883         final Rect layoutContainingFrame;
    884         final Rect layoutDisplayFrame;
    885 
    886         // The offset from the layout containing frame to the actual containing frame.
    887         final int layoutXDiff;
    888         final int layoutYDiff;
    889         if (inFullscreenContainer || layoutInParentFrame()) {
    890             // We use the parent frame as the containing frame for fullscreen and child windows
    891             mContainingFrame.set(parentFrame);
    892             mDisplayFrame.set(displayFrame);
    893             layoutDisplayFrame = displayFrame;
    894             layoutContainingFrame = parentFrame;
    895             layoutXDiff = 0;
    896             layoutYDiff = 0;
    897         } else {
    898             getBounds(mContainingFrame);
    899             if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
    900 
    901                 // If the bounds are frozen, we still want to translate the window freely and only
    902                 // freeze the size.
    903                 Rect frozen = mAppToken.mFrozenBounds.peek();
    904                 mContainingFrame.right = mContainingFrame.left + frozen.width();
    905                 mContainingFrame.bottom = mContainingFrame.top + frozen.height();
    906             }
    907             final WindowState imeWin = mService.mInputMethodWindow;
    908             // IME is up and obscuring this window. Adjust the window position so it is visible.
    909             if (imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget()) {
    910                 if (inFreeformWindowingMode()
    911                         && mContainingFrame.bottom > contentFrame.bottom) {
    912                     // In freeform we want to move the top up directly.
    913                     // TODO: Investigate why this is contentFrame not parentFrame.
    914                     mContainingFrame.top -= mContainingFrame.bottom - contentFrame.bottom;
    915                 } else if (!inPinnedWindowingMode()
    916                         && mContainingFrame.bottom > parentFrame.bottom) {
    917                     // But in docked we want to behave like fullscreen and behave as if the task
    918                     // were given smaller bounds for the purposes of layout. Skip adjustments for
    919                     // the pinned stack, they are handled separately in the PinnedStackController.
    920                     mContainingFrame.bottom = parentFrame.bottom;
    921                 }
    922             }
    923 
    924             if (windowsAreFloating) {
    925                 // In floating modes (e.g. freeform, pinned) we have only to set the rectangle
    926                 // if it wasn't set already. No need to intersect it with the (visible)
    927                 // "content frame" since it is allowed to be outside the visible desktop.
    928                 if (mContainingFrame.isEmpty()) {
    929                     mContainingFrame.set(contentFrame);
    930                 }
    931             }
    932 
    933             final TaskStack stack = getStack();
    934             if (inPinnedWindowingMode() && stack != null
    935                     && stack.lastAnimatingBoundsWasToFullscreen()) {
    936                 // PIP edge case: When going from pinned to fullscreen, we apply a
    937                 // tempInsetFrame for the full task - but we're still at the start of the animation.
    938                 // To prevent a jump if there's a letterbox, restrict to the parent frame.
    939                 mInsetFrame.intersectUnchecked(parentFrame);
    940                 mContainingFrame.intersectUnchecked(parentFrame);
    941             }
    942 
    943             mDisplayFrame.set(mContainingFrame);
    944             layoutXDiff = !mInsetFrame.isEmpty() ? mInsetFrame.left - mContainingFrame.left : 0;
    945             layoutYDiff = !mInsetFrame.isEmpty() ? mInsetFrame.top - mContainingFrame.top : 0;
    946             layoutContainingFrame = !mInsetFrame.isEmpty() ? mInsetFrame : mContainingFrame;
    947             mTmpRect.set(0, 0, dc.getDisplayInfo().logicalWidth, dc.getDisplayInfo().logicalHeight);
    948             subtractInsets(mDisplayFrame, layoutContainingFrame, displayFrame, mTmpRect);
    949             if (!layoutInParentFrame()) {
    950                 subtractInsets(mContainingFrame, layoutContainingFrame, parentFrame, mTmpRect);
    951                 subtractInsets(mInsetFrame, layoutContainingFrame, parentFrame, mTmpRect);
    952             }
    953             layoutDisplayFrame = displayFrame;
    954             layoutDisplayFrame.intersect(layoutContainingFrame);
    955         }
    956 
    957         final int pw = mContainingFrame.width();
    958         final int ph = mContainingFrame.height();
    959 
    960         if (!mParentFrame.equals(parentFrame)) {
    961             //Slog.i(TAG_WM, "Window " + this + " content frame from " + mParentFrame
    962             //        + " to " + parentFrame);
    963             mParentFrame.set(parentFrame);
    964             mContentChanged = true;
    965         }
    966         if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
    967             mLastRequestedWidth = mRequestedWidth;
    968             mLastRequestedHeight = mRequestedHeight;
    969             mContentChanged = true;
    970         }
    971 
    972         mOverscanFrame.set(overscanFrame);
    973         mContentFrame.set(contentFrame);
    974         mVisibleFrame.set(visibleFrame);
    975         mDecorFrame.set(decorFrame);
    976         mStableFrame.set(stableFrame);
    977         final boolean hasOutsets = outsetFrame != null;
    978         if (hasOutsets) {
    979             mOutsetFrame.set(outsetFrame);
    980         }
    981 
    982         final int fw = mFrame.width();
    983         final int fh = mFrame.height();
    984 
    985         applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
    986 
    987         // Calculate the outsets before the content frame gets shrinked to the window frame.
    988         if (hasOutsets) {
    989             mOutsets.set(Math.max(mContentFrame.left - mOutsetFrame.left, 0),
    990                     Math.max(mContentFrame.top - mOutsetFrame.top, 0),
    991                     Math.max(mOutsetFrame.right - mContentFrame.right, 0),
    992                     Math.max(mOutsetFrame.bottom - mContentFrame.bottom, 0));
    993         } else {
    994             mOutsets.set(0, 0, 0, 0);
    995         }
    996 
    997         // Make sure the content and visible frames are inside of the
    998         // final window frame.
    999         if (windowsAreFloating && !mFrame.isEmpty()) {
   1000             // For pinned workspace the frame isn't limited in any particular
   1001             // way since SystemUI controls the bounds. For freeform however
   1002             // we want to keep things inside the content frame.
   1003             final Rect limitFrame = task.inPinnedWindowingMode() ? mFrame : mContentFrame;
   1004             // Keep the frame out of the blocked system area, limit it in size to the content area
   1005             // and make sure that there is always a minimum visible so that the user can drag it
   1006             // into a usable area..
   1007             final int height = Math.min(mFrame.height(), limitFrame.height());
   1008             final int width = Math.min(limitFrame.width(), mFrame.width());
   1009             final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
   1010             final int minVisibleHeight = Math.min(height, WindowManagerService.dipToPixel(
   1011                     MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics));
   1012             final int minVisibleWidth = Math.min(width, WindowManagerService.dipToPixel(
   1013                     MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics));
   1014             final int top = Math.max(limitFrame.top,
   1015                     Math.min(mFrame.top, limitFrame.bottom - minVisibleHeight));
   1016             final int left = Math.max(limitFrame.left + minVisibleWidth - width,
   1017                     Math.min(mFrame.left, limitFrame.right - minVisibleWidth));
   1018             mFrame.set(left, top, left + width, top + height);
   1019             mContentFrame.set(mFrame);
   1020             mVisibleFrame.set(mContentFrame);
   1021             mStableFrame.set(mContentFrame);
   1022         } else if (mAttrs.type == TYPE_DOCK_DIVIDER) {
   1023             dc.getDockedDividerController().positionDockedStackedDivider(mFrame);
   1024             mContentFrame.set(mFrame);
   1025             if (!mFrame.equals(mLastFrame)) {
   1026                 mMovedByResize = true;
   1027             }
   1028         } else {
   1029             mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
   1030                     Math.max(mContentFrame.top, mFrame.top),
   1031                     Math.min(mContentFrame.right, mFrame.right),
   1032                     Math.min(mContentFrame.bottom, mFrame.bottom));
   1033 
   1034             mVisibleFrame.set(Math.max(mVisibleFrame.left, mFrame.left),
   1035                     Math.max(mVisibleFrame.top, mFrame.top),
   1036                     Math.min(mVisibleFrame.right, mFrame.right),
   1037                     Math.min(mVisibleFrame.bottom, mFrame.bottom));
   1038 
   1039             mStableFrame.set(Math.max(mStableFrame.left, mFrame.left),
   1040                     Math.max(mStableFrame.top, mFrame.top),
   1041                     Math.min(mStableFrame.right, mFrame.right),
   1042                     Math.min(mStableFrame.bottom, mFrame.bottom));
   1043         }
   1044 
   1045         if (inFullscreenContainer && !windowsAreFloating) {
   1046             // Windows that are not fullscreen can be positioned outside of the display frame,
   1047             // but that is not a reason to provide them with overscan insets.
   1048             mOverscanInsets.set(Math.max(mOverscanFrame.left - layoutContainingFrame.left, 0),
   1049                     Math.max(mOverscanFrame.top - layoutContainingFrame.top, 0),
   1050                     Math.max(layoutContainingFrame.right - mOverscanFrame.right, 0),
   1051                     Math.max(layoutContainingFrame.bottom - mOverscanFrame.bottom, 0));
   1052         }
   1053 
   1054         if (mAttrs.type == TYPE_DOCK_DIVIDER) {
   1055             // For the docked divider, we calculate the stable insets like a full-screen window
   1056             // so it can use it to calculate the snap positions.
   1057             final WmDisplayCutout c = displayCutout.calculateRelativeTo(mDisplayFrame);
   1058             mTmpRect.set(mDisplayFrame);
   1059             mTmpRect.inset(c.getDisplayCutout().getSafeInsets());
   1060             mTmpRect.intersectUnchecked(mStableFrame);
   1061 
   1062             mStableInsets.set(Math.max(mTmpRect.left - mDisplayFrame.left, 0),
   1063                     Math.max(mTmpRect.top - mDisplayFrame.top, 0),
   1064                     Math.max(mDisplayFrame.right - mTmpRect.right, 0),
   1065                     Math.max(mDisplayFrame.bottom - mTmpRect.bottom, 0));
   1066 
   1067             // The divider doesn't care about insets in any case, so set it to empty so we don't
   1068             // trigger a relayout when moving it.
   1069             mContentInsets.setEmpty();
   1070             mVisibleInsets.setEmpty();
   1071             displayCutout = WmDisplayCutout.NO_CUTOUT;
   1072         } else {
   1073             getDisplayContent().getBounds(mTmpRect);
   1074             // Override right and/or bottom insets in case if the frame doesn't fit the screen in
   1075             // non-fullscreen mode.
   1076             boolean overrideRightInset = !windowsAreFloating && !inFullscreenContainer
   1077                     && mFrame.right > mTmpRect.right;
   1078             boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer
   1079                     && mFrame.bottom > mTmpRect.bottom;
   1080             mContentInsets.set(mContentFrame.left - mFrame.left,
   1081                     mContentFrame.top - mFrame.top,
   1082                     overrideRightInset ? mTmpRect.right - mContentFrame.right
   1083                             : mFrame.right - mContentFrame.right,
   1084                     overrideBottomInset ? mTmpRect.bottom - mContentFrame.bottom
   1085                             : mFrame.bottom - mContentFrame.bottom);
   1086 
   1087             mVisibleInsets.set(mVisibleFrame.left - mFrame.left,
   1088                     mVisibleFrame.top - mFrame.top,
   1089                     overrideRightInset ? mTmpRect.right - mVisibleFrame.right
   1090                             : mFrame.right - mVisibleFrame.right,
   1091                     overrideBottomInset ? mTmpRect.bottom - mVisibleFrame.bottom
   1092                             : mFrame.bottom - mVisibleFrame.bottom);
   1093 
   1094             mStableInsets.set(Math.max(mStableFrame.left - mFrame.left, 0),
   1095                     Math.max(mStableFrame.top - mFrame.top, 0),
   1096                     overrideRightInset ? Math.max(mTmpRect.right - mStableFrame.right, 0)
   1097                             : Math.max(mFrame.right - mStableFrame.right, 0),
   1098                     overrideBottomInset ? Math.max(mTmpRect.bottom - mStableFrame.bottom, 0)
   1099                             :  Math.max(mFrame.bottom - mStableFrame.bottom, 0));
   1100         }
   1101 
   1102         mDisplayCutout = displayCutout.calculateRelativeTo(mFrame);
   1103 
   1104         // Offset the actual frame by the amount layout frame is off.
   1105         mFrame.offset(-layoutXDiff, -layoutYDiff);
   1106         mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
   1107         mContentFrame.offset(-layoutXDiff, -layoutYDiff);
   1108         mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
   1109         mStableFrame.offset(-layoutXDiff, -layoutYDiff);
   1110 
   1111         mCompatFrame.set(mFrame);
   1112         if (mEnforceSizeCompat) {
   1113             // If there is a size compatibility scale being applied to the
   1114             // window, we need to apply this to its insets so that they are
   1115             // reported to the app in its coordinate space.
   1116             mOverscanInsets.scale(mInvGlobalScale);
   1117             mContentInsets.scale(mInvGlobalScale);
   1118             mVisibleInsets.scale(mInvGlobalScale);
   1119             mStableInsets.scale(mInvGlobalScale);
   1120             mOutsets.scale(mInvGlobalScale);
   1121 
   1122             // Also the scaled frame that we report to the app needs to be
   1123             // adjusted to be in its coordinate space.
   1124             mCompatFrame.scale(mInvGlobalScale);
   1125         }
   1126 
   1127         if (mIsWallpaper && (fw != mFrame.width() || fh != mFrame.height())) {
   1128             final DisplayContent displayContent = getDisplayContent();
   1129             if (displayContent != null) {
   1130                 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   1131                 getDisplayContent().mWallpaperController.updateWallpaperOffset(
   1132                         this, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
   1133             }
   1134         }
   1135 
   1136         if (DEBUG_LAYOUT || localLOGV) Slog.v(TAG,
   1137                 "Resolving (mRequestedWidth="
   1138                 + mRequestedWidth + ", mRequestedheight="
   1139                 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
   1140                 + "): frame=" + mFrame.toShortString()
   1141                 + " ci=" + mContentInsets.toShortString()
   1142                 + " vi=" + mVisibleInsets.toShortString()
   1143                 + " si=" + mStableInsets.toShortString()
   1144                 + " of=" + mOutsets.toShortString());
   1145     }
   1146 
   1147     // TODO: Look into whether this override is still necessary.
   1148     @Override
   1149     public Rect getBounds() {
   1150         if (isInMultiWindowMode()) {
   1151             return getTask().getBounds();
   1152         } else if (mAppToken != null){
   1153             return mAppToken.getBounds();
   1154         } else {
   1155             return super.getBounds();
   1156         }
   1157     }
   1158 
   1159     @Override
   1160     public Rect getFrameLw() {
   1161         return mFrame;
   1162     }
   1163 
   1164     @Override
   1165     public Rect getDisplayFrameLw() {
   1166         return mDisplayFrame;
   1167     }
   1168 
   1169     @Override
   1170     public Rect getOverscanFrameLw() {
   1171         return mOverscanFrame;
   1172     }
   1173 
   1174     @Override
   1175     public Rect getContentFrameLw() {
   1176         return mContentFrame;
   1177     }
   1178 
   1179     @Override
   1180     public Rect getVisibleFrameLw() {
   1181         return mVisibleFrame;
   1182     }
   1183 
   1184     Rect getStableFrameLw() {
   1185         return mStableFrame;
   1186     }
   1187 
   1188     @Override
   1189     public boolean getGivenInsetsPendingLw() {
   1190         return mGivenInsetsPending;
   1191     }
   1192 
   1193     @Override
   1194     public Rect getGivenContentInsetsLw() {
   1195         return mGivenContentInsets;
   1196     }
   1197 
   1198     @Override
   1199     public Rect getGivenVisibleInsetsLw() {
   1200         return mGivenVisibleInsets;
   1201     }
   1202 
   1203     @Override
   1204     public WindowManager.LayoutParams getAttrs() {
   1205         return mAttrs;
   1206     }
   1207 
   1208     @Override
   1209     public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) {
   1210         return getDisplayContent().getNeedsMenu(this, bottom);
   1211     }
   1212 
   1213     @Override
   1214     public int getSystemUiVisibility() {
   1215         return mSystemUiVisibility;
   1216     }
   1217 
   1218     @Override
   1219     public int getSurfaceLayer() {
   1220         return mLayer;
   1221     }
   1222 
   1223     @Override
   1224     public int getBaseType() {
   1225         return getTopParentWindow().mAttrs.type;
   1226     }
   1227 
   1228     @Override
   1229     public IApplicationToken getAppToken() {
   1230         return mAppToken != null ? mAppToken.appToken : null;
   1231     }
   1232 
   1233     @Override
   1234     public boolean isVoiceInteraction() {
   1235         return mAppToken != null && mAppToken.mVoiceInteraction;
   1236     }
   1237 
   1238     boolean setReportResizeHints() {
   1239         mOverscanInsetsChanged |= !mLastOverscanInsets.equals(mOverscanInsets);
   1240         mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets);
   1241         mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets);
   1242         mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets);
   1243         mOutsetsChanged |= !mLastOutsets.equals(mOutsets);
   1244         mFrameSizeChanged |= (mLastFrame.width() != mFrame.width()) ||
   1245                 (mLastFrame.height() != mFrame.height());
   1246         mDisplayCutoutChanged |= !mLastDisplayCutout.equals(mDisplayCutout);
   1247         return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged
   1248                 || mOutsetsChanged || mFrameSizeChanged || mDisplayCutoutChanged;
   1249     }
   1250 
   1251     /**
   1252      * Adds the window to the resizing list if any of the parameters we use to track the window
   1253      * dimensions or insets have changed.
   1254      */
   1255     void updateResizingWindowIfNeeded() {
   1256         final WindowStateAnimator winAnimator = mWinAnimator;
   1257         if (!mHasSurface || getDisplayContent().mLayoutSeq != mLayoutSeq || isGoneForLayoutLw()) {
   1258             return;
   1259         }
   1260 
   1261         final Task task = getTask();
   1262         // In the case of stack bound animations, the window frames will update (unlike other
   1263         // animations which just modify various transformation properties). We don't want to
   1264         // notify the client of frame changes in this case. Not only is it a lot of churn, but
   1265         // the frame may not correspond to the surface size or the onscreen area at various
   1266         // phases in the animation, and the client will become sad and confused.
   1267         if (task != null && task.mStack.isAnimatingBounds()) {
   1268             return;
   1269         }
   1270 
   1271         setReportResizeHints();
   1272         boolean configChanged = isConfigChanged();
   1273         if (DEBUG_CONFIGURATION && configChanged) {
   1274             Slog.v(TAG_WM, "Win " + this + " config changed: " + getConfiguration());
   1275         }
   1276 
   1277         final boolean dragResizingChanged = isDragResizeChanged()
   1278                 && !isDragResizingChangeReported();
   1279 
   1280         if (localLOGV) Slog.v(TAG_WM, "Resizing " + this + ": configChanged=" + configChanged
   1281                 + " dragResizingChanged=" + dragResizingChanged + " last=" + mLastFrame
   1282                 + " frame=" + mFrame);
   1283 
   1284         // We update mLastFrame always rather than in the conditional with the last inset
   1285         // variables, because mFrameSizeChanged only tracks the width and height changing.
   1286         mLastFrame.set(mFrame);
   1287 
   1288         if (mContentInsetsChanged
   1289                 || mVisibleInsetsChanged
   1290                 || mStableInsetsChanged
   1291                 || winAnimator.mSurfaceResized
   1292                 || mOutsetsChanged
   1293                 || mFrameSizeChanged
   1294                 || mDisplayCutoutChanged
   1295                 || configChanged
   1296                 || dragResizingChanged
   1297                 || mReportOrientationChanged) {
   1298             if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
   1299                 Slog.v(TAG_WM, "Resize reasons for w=" + this + ": "
   1300                         + " contentInsetsChanged=" + mContentInsetsChanged
   1301                         + " " + mContentInsets.toShortString()
   1302                         + " visibleInsetsChanged=" + mVisibleInsetsChanged
   1303                         + " " + mVisibleInsets.toShortString()
   1304                         + " stableInsetsChanged=" + mStableInsetsChanged
   1305                         + " " + mStableInsets.toShortString()
   1306                         + " outsetsChanged=" + mOutsetsChanged
   1307                         + " " + mOutsets.toShortString()
   1308                         + " surfaceResized=" + winAnimator.mSurfaceResized
   1309                         + " configChanged=" + configChanged
   1310                         + " dragResizingChanged=" + dragResizingChanged
   1311                         + " reportOrientationChanged=" + mReportOrientationChanged
   1312                         + " displayCutoutChanged=" + mDisplayCutoutChanged);
   1313             }
   1314 
   1315             // If it's a dead window left on screen, and the configuration changed, there is nothing
   1316             // we can do about it. Remove the window now.
   1317             if (mAppToken != null && mAppDied) {
   1318                 mAppToken.removeDeadWindows();
   1319                 return;
   1320             }
   1321 
   1322             updateLastInsetValues();
   1323             mService.makeWindowFreezingScreenIfNeededLocked(this);
   1324 
   1325             // If the orientation is changing, or we're starting or ending a drag resizing action,
   1326             // then we need to hold off on unfreezing the display until this window has been
   1327             // redrawn; to do that, we need to go through the process of getting informed by the
   1328             // application when it has finished drawing.
   1329             if (getOrientationChanging() || dragResizingChanged) {
   1330                 if (DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
   1331                     Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
   1332                             + ", mDrawState=DRAW_PENDING in " + this
   1333                             + ", surfaceController " + winAnimator.mSurfaceController);
   1334                 }
   1335                 winAnimator.mDrawState = DRAW_PENDING;
   1336                 if (mAppToken != null) {
   1337                     mAppToken.clearAllDrawn();
   1338                 }
   1339             }
   1340             if (!mService.mResizingWindows.contains(this)) {
   1341                 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM, "Resizing window " + this);
   1342                 mService.mResizingWindows.add(this);
   1343             }
   1344         } else if (getOrientationChanging()) {
   1345             if (isDrawnLw()) {
   1346                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Orientation not waiting for draw in "
   1347                         + this + ", surfaceController " + winAnimator.mSurfaceController);
   1348                 setOrientationChanging(false);
   1349                 mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
   1350                         - mService.mDisplayFreezeTime);
   1351             }
   1352         }
   1353     }
   1354 
   1355     boolean getOrientationChanging() {
   1356         // In addition to the local state flag, we must also consider the difference in the last
   1357         // reported configuration vs. the current state. If the client code has not been informed of
   1358         // the change, logic dependent on having finished processing the orientation, such as
   1359         // unfreezing, could be improperly triggered.
   1360         // TODO(b/62846907): Checking against {@link mLastReportedConfiguration} could be flaky as
   1361         //                   this is not necessarily what the client has processed yet. Find a
   1362         //                   better indicator consistent with the client.
   1363         return (mOrientationChanging || (isVisible()
   1364                 && getConfiguration().orientation != getLastReportedConfiguration().orientation))
   1365                 && !mSeamlesslyRotated
   1366                 && !mOrientationChangeTimedOut;
   1367     }
   1368 
   1369     void setOrientationChanging(boolean changing) {
   1370         mOrientationChanging = changing;
   1371         mOrientationChangeTimedOut = false;
   1372     }
   1373 
   1374     void orientationChangeTimedOut() {
   1375         mOrientationChangeTimedOut = true;
   1376     }
   1377 
   1378     DisplayContent getDisplayContent() {
   1379         return mToken.getDisplayContent();
   1380     }
   1381 
   1382     @Override
   1383     void onDisplayChanged(DisplayContent dc) {
   1384         super.onDisplayChanged(dc);
   1385         // Window was not laid out for this display yet, so make sure mLayoutSeq does not match.
   1386         if (dc != null) {
   1387             mLayoutSeq = dc.mLayoutSeq - 1;
   1388             mInputWindowHandle.displayId = dc.getDisplayId();
   1389         }
   1390     }
   1391 
   1392     DisplayInfo getDisplayInfo() {
   1393         final DisplayContent displayContent = getDisplayContent();
   1394         return displayContent != null ? displayContent.getDisplayInfo() : null;
   1395     }
   1396 
   1397     @Override
   1398     public int getDisplayId() {
   1399         final DisplayContent displayContent = getDisplayContent();
   1400         if (displayContent == null) {
   1401             return Display.INVALID_DISPLAY;
   1402         }
   1403         return displayContent.getDisplayId();
   1404     }
   1405 
   1406     Task getTask() {
   1407         return mAppToken != null ? mAppToken.getTask() : null;
   1408     }
   1409 
   1410     TaskStack getStack() {
   1411         Task task = getTask();
   1412         if (task != null) {
   1413             if (task.mStack != null) {
   1414                 return task.mStack;
   1415             }
   1416         }
   1417         // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
   1418         // associate them with some stack to enable dimming.
   1419         final DisplayContent dc = getDisplayContent();
   1420         return mAttrs.type >= FIRST_SYSTEM_WINDOW && dc != null ? dc.getHomeStack() : null;
   1421     }
   1422 
   1423     /**
   1424      * Retrieves the visible bounds of the window.
   1425      * @param bounds The rect which gets the bounds.
   1426      */
   1427     void getVisibleBounds(Rect bounds) {
   1428         final Task task = getTask();
   1429         boolean intersectWithStackBounds = task != null && task.cropWindowsToStackBounds();
   1430         bounds.setEmpty();
   1431         mTmpRect.setEmpty();
   1432         if (intersectWithStackBounds) {
   1433             final TaskStack stack = task.mStack;
   1434             if (stack != null) {
   1435                 stack.getDimBounds(mTmpRect);
   1436             } else {
   1437                 intersectWithStackBounds = false;
   1438             }
   1439         }
   1440 
   1441         bounds.set(mVisibleFrame);
   1442         if (intersectWithStackBounds) {
   1443             bounds.intersect(mTmpRect);
   1444         }
   1445 
   1446         if (bounds.isEmpty()) {
   1447             bounds.set(mFrame);
   1448             if (intersectWithStackBounds) {
   1449                 bounds.intersect(mTmpRect);
   1450             }
   1451             return;
   1452         }
   1453     }
   1454 
   1455     public long getInputDispatchingTimeoutNanos() {
   1456         return mAppToken != null
   1457                 ? mAppToken.mInputDispatchingTimeoutNanos
   1458                 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
   1459     }
   1460 
   1461     @Override
   1462     public boolean hasAppShownWindows() {
   1463         return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed);
   1464     }
   1465 
   1466     boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
   1467         if (dsdx < .99999f || dsdx > 1.00001f) return false;
   1468         if (dtdy < .99999f || dtdy > 1.00001f) return false;
   1469         if (dtdx < -.000001f || dtdx > .000001f) return false;
   1470         if (dsdy < -.000001f || dsdy > .000001f) return false;
   1471         return true;
   1472     }
   1473 
   1474     void prelayout() {
   1475         if (mEnforceSizeCompat) {
   1476             mGlobalScale = getDisplayContent().mCompatibleScreenScale;
   1477             mInvGlobalScale = 1 / mGlobalScale;
   1478         } else {
   1479             mGlobalScale = mInvGlobalScale = 1;
   1480         }
   1481     }
   1482 
   1483     @Override
   1484     boolean hasContentToDisplay() {
   1485         if (!mAppFreezing && isDrawnLw() && (mViewVisibility == View.VISIBLE
   1486                 || (mWinAnimator.isAnimationSet() && !mService.mAppTransition.isTransitionSet()))) {
   1487             return true;
   1488         }
   1489 
   1490         return super.hasContentToDisplay();
   1491     }
   1492 
   1493     @Override
   1494     boolean isVisible() {
   1495         return wouldBeVisibleIfPolicyIgnored() && mPolicyVisibility;
   1496     }
   1497 
   1498     /**
   1499      * @return True if the window would be visible if we'd ignore policy visibility, false
   1500      *         otherwise.
   1501      */
   1502     boolean wouldBeVisibleIfPolicyIgnored() {
   1503         return mHasSurface && !isParentWindowHidden()
   1504                 && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible);
   1505     }
   1506 
   1507     @Override
   1508     public boolean isVisibleLw() {
   1509         return isVisible();
   1510     }
   1511 
   1512     /**
   1513      * Is this window visible, ignoring its app token? It is not visible if there is no surface,
   1514      * or we are in the process of running an exit animation that will remove the surface.
   1515      */
   1516     // TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this?
   1517     boolean isWinVisibleLw() {
   1518         return (mAppToken == null || !mAppToken.hiddenRequested || mAppToken.isSelfAnimating())
   1519                 && isVisible();
   1520     }
   1521 
   1522     /**
   1523      * The same as isVisible(), but follows the current hidden state of the associated app token,
   1524      * not the pending requested hidden state.
   1525      */
   1526     boolean isVisibleNow() {
   1527         return (!mToken.isHidden() || mAttrs.type == TYPE_APPLICATION_STARTING)
   1528                 && isVisible();
   1529     }
   1530 
   1531     /**
   1532      * Can this window possibly be a drag/drop target?  The test here is
   1533      * a combination of the above "visible now" with the check that the
   1534      * Input Manager uses when discarding windows from input consideration.
   1535      */
   1536     boolean isPotentialDragTarget() {
   1537         return isVisibleNow() && !mRemoved
   1538                 && mInputChannel != null && mInputWindowHandle != null;
   1539     }
   1540 
   1541     /**
   1542      * Same as isVisible(), but we also count it as visible between the
   1543      * call to IWindowSession.add() and the first relayout().
   1544      */
   1545     boolean isVisibleOrAdding() {
   1546         final AppWindowToken atoken = mAppToken;
   1547         return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
   1548                 && mPolicyVisibility && !isParentWindowHidden()
   1549                 && (atoken == null || !atoken.hiddenRequested)
   1550                 && !mAnimatingExit && !mDestroying;
   1551     }
   1552 
   1553     /**
   1554      * Is this window currently on-screen?  It is on-screen either if it
   1555      * is visible or it is currently running an animation before no longer
   1556      * being visible.
   1557      */
   1558     boolean isOnScreen() {
   1559         if (!mHasSurface || mDestroying || !mPolicyVisibility) {
   1560             return false;
   1561         }
   1562         final AppWindowToken atoken = mAppToken;
   1563         if (atoken != null) {
   1564             return ((!isParentWindowHidden() && !atoken.hiddenRequested)
   1565                     || mWinAnimator.isAnimationSet());
   1566         }
   1567         return !isParentWindowHidden() || mWinAnimator.isAnimationSet();
   1568     }
   1569 
   1570     /**
   1571      * Whether this window's drawn state might affect the drawn states of the app token.
   1572      *
   1573      * @return true if the window should be considered while evaluating allDrawn flags.
   1574      */
   1575     boolean mightAffectAllDrawn() {
   1576         final boolean isAppType = mWinAnimator.mAttrType == TYPE_BASE_APPLICATION
   1577                 || mWinAnimator.mAttrType == TYPE_DRAWN_APPLICATION;
   1578         return (isOnScreen() || isAppType) && !mAnimatingExit && !mDestroying;
   1579     }
   1580 
   1581     /**
   1582      * Whether this window is "interesting" when evaluating allDrawn. If it's interesting,
   1583      * it must be drawn before allDrawn can become true.
   1584      */
   1585     boolean isInteresting() {
   1586         return mAppToken != null && !mAppDied
   1587                 && (!mAppToken.isFreezingScreen() || !mAppFreezing);
   1588     }
   1589 
   1590     /**
   1591      * Like isOnScreen(), but we don't return true if the window is part
   1592      * of a transition that has not yet been started.
   1593      */
   1594     boolean isReadyForDisplay() {
   1595         if (mToken.waitingToShow && mService.mAppTransition.isTransitionSet()) {
   1596             return false;
   1597         }
   1598         return mHasSurface && mPolicyVisibility && !mDestroying
   1599                 && ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mToken.isHidden())
   1600                         || mWinAnimator.isAnimationSet());
   1601     }
   1602 
   1603     // TODO: Another visibility method that was added late in the release to minimize risk.
   1604     @Override
   1605     public boolean canAffectSystemUiFlags() {
   1606         final boolean translucent = mAttrs.alpha == 0.0f;
   1607         if (translucent) {
   1608             return false;
   1609         }
   1610         if (mAppToken == null) {
   1611             final boolean shown = mWinAnimator.getShown();
   1612             final boolean exiting = mAnimatingExit || mDestroying;
   1613             return shown && !exiting;
   1614         } else {
   1615             final Task task = getTask();
   1616             final boolean canFromTask = task != null && task.canAffectSystemUiFlags();
   1617             return canFromTask && !mAppToken.isHidden();
   1618         }
   1619     }
   1620 
   1621     /**
   1622      * Like isOnScreen, but returns false if the surface hasn't yet
   1623      * been drawn.
   1624      */
   1625     @Override
   1626     public boolean isDisplayedLw() {
   1627         final AppWindowToken atoken = mAppToken;
   1628         return isDrawnLw() && mPolicyVisibility
   1629                 && ((!isParentWindowHidden() && (atoken == null || !atoken.hiddenRequested))
   1630                         || mWinAnimator.isAnimationSet());
   1631     }
   1632 
   1633     /**
   1634      * Return true if this window or its app token is currently animating.
   1635      */
   1636     @Override
   1637     public boolean isAnimatingLw() {
   1638         return isAnimating();
   1639     }
   1640 
   1641     @Override
   1642     public boolean isGoneForLayoutLw() {
   1643         final AppWindowToken atoken = mAppToken;
   1644         return mViewVisibility == View.GONE
   1645                 || !mRelayoutCalled
   1646                 || (atoken == null && mToken.isHidden())
   1647                 || (atoken != null && atoken.hiddenRequested)
   1648                 || isParentWindowHidden()
   1649                 || (mAnimatingExit && !isAnimatingLw())
   1650                 || mDestroying;
   1651     }
   1652 
   1653     /**
   1654      * Returns true if the window has a surface that it has drawn a
   1655      * complete UI in to.
   1656      */
   1657     public boolean isDrawFinishedLw() {
   1658         return mHasSurface && !mDestroying &&
   1659                 (mWinAnimator.mDrawState == COMMIT_DRAW_PENDING
   1660                 || mWinAnimator.mDrawState == READY_TO_SHOW
   1661                 || mWinAnimator.mDrawState == HAS_DRAWN);
   1662     }
   1663 
   1664     /**
   1665      * Returns true if the window has a surface that it has drawn a
   1666      * complete UI in to.
   1667      */
   1668     @Override
   1669     public boolean isDrawnLw() {
   1670         return mHasSurface && !mDestroying &&
   1671                 (mWinAnimator.mDrawState == READY_TO_SHOW || mWinAnimator.mDrawState == HAS_DRAWN);
   1672     }
   1673 
   1674     /**
   1675      * Return true if the window is opaque and fully drawn.  This indicates
   1676      * it may obscure windows behind it.
   1677      */
   1678     private boolean isOpaqueDrawn() {
   1679         // When there is keyguard, wallpaper could be placed over the secure app
   1680         // window but invisible. We need to check wallpaper visibility explicitly
   1681         // to determine if it's occluding apps.
   1682         return ((!mIsWallpaper && mAttrs.format == PixelFormat.OPAQUE)
   1683                 || (mIsWallpaper && mWallpaperVisible))
   1684                 && isDrawnLw() && !mWinAnimator.isAnimationSet();
   1685     }
   1686 
   1687     @Override
   1688     void onMovedByResize() {
   1689         if (DEBUG_RESIZE) Slog.d(TAG, "onMovedByResize: Moving " + this);
   1690         mMovedByResize = true;
   1691         super.onMovedByResize();
   1692     }
   1693 
   1694     boolean onAppVisibilityChanged(boolean visible, boolean runningAppAnimation) {
   1695         boolean changed = false;
   1696 
   1697         for (int i = mChildren.size() - 1; i >= 0; --i) {
   1698             final WindowState c = mChildren.get(i);
   1699             changed |= c.onAppVisibilityChanged(visible, runningAppAnimation);
   1700         }
   1701 
   1702         if (mAttrs.type == TYPE_APPLICATION_STARTING) {
   1703             // Starting window that's exiting will be removed when the animation finishes.
   1704             // Mark all relevant flags for that onExitAnimationDone will proceed all the way
   1705             // to actually remove it.
   1706             if (!visible && isVisibleNow() && mAppToken.isSelfAnimating()) {
   1707                 mAnimatingExit = true;
   1708                 mRemoveOnExit = true;
   1709                 mWindowRemovalAllowed = true;
   1710             }
   1711             return changed;
   1712         }
   1713 
   1714         final boolean isVisibleNow = isVisibleNow();
   1715         if (visible != isVisibleNow) {
   1716             // Run exit animation if:
   1717             // 1. App visibility and WS visibility are different
   1718             // 2. App is not running an animation
   1719             // 3. WS is currently visible
   1720             if (!runningAppAnimation && isVisibleNow) {
   1721                 final AccessibilityController accessibilityController =
   1722                         mService.mAccessibilityController;
   1723                 final int winTransit = TRANSIT_EXIT;
   1724                 mWinAnimator.applyAnimationLocked(winTransit, false /* isEntrance */);
   1725                 //TODO (multidisplay): Magnification is supported only for the default
   1726                 if (accessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
   1727                     accessibilityController.onWindowTransitionLocked(this, winTransit);
   1728                 }
   1729             }
   1730             changed = true;
   1731             setDisplayLayoutNeeded();
   1732         }
   1733 
   1734         return changed;
   1735     }
   1736 
   1737     boolean onSetAppExiting() {
   1738         final DisplayContent displayContent = getDisplayContent();
   1739         boolean changed = false;
   1740 
   1741         if (isVisibleNow()) {
   1742             mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
   1743             //TODO (multidisplay): Magnification is supported only for the default
   1744             if (mService.mAccessibilityController != null && isDefaultDisplay()) {
   1745                 mService.mAccessibilityController.onWindowTransitionLocked(this, TRANSIT_EXIT);
   1746             }
   1747             changed = true;
   1748             if (displayContent != null) {
   1749                 displayContent.setLayoutNeeded();
   1750             }
   1751         }
   1752 
   1753         for (int i = mChildren.size() - 1; i >= 0; --i) {
   1754             final WindowState c = mChildren.get(i);
   1755             changed |= c.onSetAppExiting();
   1756         }
   1757 
   1758         return changed;
   1759     }
   1760 
   1761     @Override
   1762     void onResize() {
   1763         final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
   1764         if (mHasSurface && !isGoneForLayoutLw() && !resizingWindows.contains(this)) {
   1765             if (DEBUG_RESIZE) Slog.d(TAG, "onResize: Resizing " + this);
   1766             resizingWindows.add(this);
   1767         }
   1768         if (isGoneForLayoutLw()) {
   1769             mResizedWhileGone = true;
   1770         }
   1771 
   1772         super.onResize();
   1773     }
   1774 
   1775     void onUnfreezeBounds() {
   1776         for (int i = mChildren.size() - 1; i >= 0; --i) {
   1777             final WindowState c = mChildren.get(i);
   1778             c.onUnfreezeBounds();
   1779         }
   1780 
   1781         if (!mHasSurface) {
   1782             return;
   1783         }
   1784 
   1785         mLayoutNeeded = true;
   1786         setDisplayLayoutNeeded();
   1787         if (!mService.mResizingWindows.contains(this)) {
   1788             mService.mResizingWindows.add(this);
   1789         }
   1790     }
   1791 
   1792     /**
   1793      * If the window has moved due to its containing content frame changing, then notify the
   1794      * listeners and optionally animate it. Simply checking a change of position is not enough,
   1795      * because being move due to dock divider is not a trigger for animation.
   1796      */
   1797     void handleWindowMovedIfNeeded() {
   1798         if (!hasMoved()) {
   1799             return;
   1800         }
   1801 
   1802         // Frame has moved, containing content frame has also moved, and we're not currently
   1803         // animating... let's do something.
   1804         final int left = mFrame.left;
   1805         final int top = mFrame.top;
   1806         final Task task = getTask();
   1807         final boolean adjustedForMinimizedDockOrIme = task != null
   1808                 && (task.mStack.isAdjustedForMinimizedDockedStack()
   1809                 || task.mStack.isAdjustedForIme());
   1810         if (mToken.okToAnimate()
   1811                 && (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
   1812                 && !isDragResizing() && !adjustedForMinimizedDockOrIme
   1813                 && getWindowConfiguration().hasMovementAnimations()
   1814                 && !mWinAnimator.mLastHidden) {
   1815             startMoveAnimation(left, top);
   1816         }
   1817 
   1818         //TODO (multidisplay): Accessibility supported only for the default display.
   1819         if (mService.mAccessibilityController != null
   1820                 && getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) {
   1821             mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
   1822         }
   1823 
   1824         try {
   1825             mClient.moved(left, top);
   1826         } catch (RemoteException e) {
   1827         }
   1828         mMovedByResize = false;
   1829     }
   1830 
   1831     /**
   1832      * Return whether this window has moved. (Only makes
   1833      * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
   1834      */
   1835     private boolean hasMoved() {
   1836         return mHasSurface && (mContentChanged || mMovedByResize)
   1837                 && !mAnimatingExit
   1838                 && (mFrame.top != mLastFrame.top || mFrame.left != mLastFrame.left)
   1839                 && (!mIsChildWindow || !getParentWindow().hasMoved());
   1840     }
   1841 
   1842     boolean isObscuringDisplay() {
   1843         Task task = getTask();
   1844         if (task != null && task.mStack != null && !task.mStack.fillsParent()) {
   1845             return false;
   1846         }
   1847         return isOpaqueDrawn() && fillsDisplay();
   1848     }
   1849 
   1850     boolean fillsDisplay() {
   1851         final DisplayInfo displayInfo = getDisplayInfo();
   1852         return mFrame.left <= 0 && mFrame.top <= 0
   1853                 && mFrame.right >= displayInfo.appWidth && mFrame.bottom >= displayInfo.appHeight;
   1854     }
   1855 
   1856     /** Returns true if last applied config was not yet requested by client. */
   1857     boolean isConfigChanged() {
   1858         return !getLastReportedConfiguration().equals(getConfiguration());
   1859     }
   1860 
   1861     void onWindowReplacementTimeout() {
   1862         if (mWillReplaceWindow) {
   1863             // Since the window already timed out, remove it immediately now.
   1864             // Use WindowState#removeImmediately() instead of WindowState#removeIfPossible(), as the latter
   1865             // delays removal on certain conditions, which will leave the stale window in the
   1866             // stack and marked mWillReplaceWindow=false, so the window will never be removed.
   1867             //
   1868             // Also removes child windows.
   1869             removeImmediately();
   1870         } else {
   1871             for (int i = mChildren.size() - 1; i >= 0; --i) {
   1872                 final WindowState c = mChildren.get(i);
   1873                 c.onWindowReplacementTimeout();
   1874             }
   1875         }
   1876     }
   1877 
   1878     @Override
   1879     void forceWindowsScaleableInTransaction(boolean force) {
   1880         if (mWinAnimator != null && mWinAnimator.hasSurface()) {
   1881             mWinAnimator.mSurfaceController.forceScaleableInTransaction(force);
   1882         }
   1883 
   1884         super.forceWindowsScaleableInTransaction(force);
   1885     }
   1886 
   1887     @Override
   1888     void removeImmediately() {
   1889         super.removeImmediately();
   1890 
   1891         if (mRemoved) {
   1892             // Nothing to do.
   1893             if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
   1894                     "WS.removeImmediately: " + this + " Already removed...");
   1895             return;
   1896         }
   1897 
   1898         mRemoved = true;
   1899 
   1900         mWillReplaceWindow = false;
   1901         if (mReplacementWindow != null) {
   1902             mReplacementWindow.mSkipEnterAnimationForSeamlessReplacement = false;
   1903         }
   1904 
   1905         final DisplayContent dc = getDisplayContent();
   1906         if (isInputMethodTarget()) {
   1907             dc.computeImeTarget(true /* updateImeTarget */);
   1908         }
   1909 
   1910         final int type = mAttrs.type;
   1911         if (WindowManagerService.excludeWindowTypeFromTapOutTask(type)) {
   1912             dc.mTapExcludedWindows.remove(this);
   1913         }
   1914         if (mTapExcludeRegionHolder != null) {
   1915             // If a tap exclude region container was initialized for this window, then it should've
   1916             // also been registered in display.
   1917             dc.mTapExcludeProvidingWindows.remove(this);
   1918         }
   1919         mPolicy.removeWindowLw(this);
   1920 
   1921         disposeInputChannel();
   1922 
   1923         mWinAnimator.destroyDeferredSurfaceLocked();
   1924         mWinAnimator.destroySurfaceLocked();
   1925         mSession.windowRemovedLocked();
   1926         try {
   1927             mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
   1928         } catch (RuntimeException e) {
   1929             // Ignore if it has already been removed (usually because
   1930             // we are doing this as part of processing a death note.)
   1931         }
   1932 
   1933         mService.postWindowRemoveCleanupLocked(this);
   1934     }
   1935 
   1936     @Override
   1937     void removeIfPossible() {
   1938         super.removeIfPossible();
   1939         removeIfPossible(false /*keepVisibleDeadWindow*/);
   1940     }
   1941 
   1942     private void removeIfPossible(boolean keepVisibleDeadWindow) {
   1943         mWindowRemovalAllowed = true;
   1944         if (DEBUG_ADD_REMOVE) Slog.v(TAG,
   1945                 "removeIfPossible: " + this + " callers=" + Debug.getCallers(5));
   1946 
   1947         final boolean startingWindow = mAttrs.type == TYPE_APPLICATION_STARTING;
   1948         if (startingWindow && DEBUG_STARTING_WINDOW) Slog.d(TAG_WM,
   1949                 "Starting window removed " + this);
   1950 
   1951         if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && this == mService.mCurrentFocus)
   1952             Slog.v(TAG_WM, "Remove " + this + " client="
   1953                         + Integer.toHexString(System.identityHashCode(mClient.asBinder()))
   1954                         + ", surfaceController=" + mWinAnimator.mSurfaceController + " Callers="
   1955                         + Debug.getCallers(5));
   1956 
   1957         final long origId = Binder.clearCallingIdentity();
   1958 
   1959         try {
   1960             disposeInputChannel();
   1961 
   1962             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Remove " + this
   1963                     + ": mSurfaceController=" + mWinAnimator.mSurfaceController
   1964                     + " mAnimatingExit=" + mAnimatingExit
   1965                     + " mRemoveOnExit=" + mRemoveOnExit
   1966                     + " mHasSurface=" + mHasSurface
   1967                     + " surfaceShowing=" + mWinAnimator.getShown()
   1968                     + " isAnimationSet=" + mWinAnimator.isAnimationSet()
   1969                     + " app-animation="
   1970                     + (mAppToken != null ? mAppToken.isSelfAnimating() : "false")
   1971                     + " mWillReplaceWindow=" + mWillReplaceWindow
   1972                     + " inPendingTransaction="
   1973                     + (mAppToken != null ? mAppToken.inPendingTransaction : false)
   1974                     + " mDisplayFrozen=" + mService.mDisplayFrozen
   1975                     + " callers=" + Debug.getCallers(6));
   1976 
   1977             // Visibility of the removed window. Will be used later to update orientation later on.
   1978             boolean wasVisible = false;
   1979 
   1980             final int displayId = getDisplayId();
   1981 
   1982             // First, see if we need to run an animation. If we do, we have to hold off on removing the
   1983             // window until the animation is done. If the display is frozen, just remove immediately,
   1984             // since the animation wouldn't be seen.
   1985             if (mHasSurface && mToken.okToAnimate()) {
   1986                 if (mWillReplaceWindow) {
   1987                     // This window is going to be replaced. We need to keep it around until the new one
   1988                     // gets added, then we will get rid of this one.
   1989                     if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
   1990                             "Preserving " + this + " until the new one is " + "added");
   1991                     // TODO: We are overloading mAnimatingExit flag to prevent the window state from
   1992                     // been removed. We probably need another flag to indicate that window removal
   1993                     // should be deffered vs. overloading the flag that says we are playing an exit
   1994                     // animation.
   1995                     mAnimatingExit = true;
   1996                     mReplacingRemoveRequested = true;
   1997                     return;
   1998                 }
   1999 
   2000                 // If we are not currently running the exit animation, we need to see about starting one
   2001                 wasVisible = isWinVisibleLw();
   2002 
   2003                 if (keepVisibleDeadWindow) {
   2004                     if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
   2005                             "Not removing " + this + " because app died while it's visible");
   2006 
   2007                     mAppDied = true;
   2008                     setDisplayLayoutNeeded();
   2009                     mService.mWindowPlacerLocked.performSurfacePlacement();
   2010 
   2011                     // Set up a replacement input channel since the app is now dead.
   2012                     // We need to catch tapping on the dead window to restart the app.
   2013                     openInputChannel(null);
   2014                     mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
   2015                     return;
   2016                 }
   2017 
   2018                 if (wasVisible) {
   2019                     final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;
   2020 
   2021                     // Try starting an animation.
   2022                     if (mWinAnimator.applyAnimationLocked(transit, false)) {
   2023                         mAnimatingExit = true;
   2024 
   2025                         // mAnimatingExit affects canAffectSystemUiFlags(). Run layout such that
   2026                         // any change from that is performed immediately.
   2027                         setDisplayLayoutNeeded();
   2028                         mService.requestTraversal();
   2029                     }
   2030                     //TODO (multidisplay): Magnification is supported only for the default display.
   2031                     if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
   2032                         mService.mAccessibilityController.onWindowTransitionLocked(this, transit);
   2033                     }
   2034                 }
   2035                 final boolean isAnimating = mWinAnimator.isAnimationSet()
   2036                         && (mAppToken == null || !mAppToken.isWaitingForTransitionStart());
   2037                 final boolean lastWindowIsStartingWindow = startingWindow && mAppToken != null
   2038                         && mAppToken.isLastWindow(this);
   2039                 // We delay the removal of a window if it has a showing surface that can be used to run
   2040                 // exit animation and it is marked as exiting.
   2041                 // Also, If isn't the an animating starting window that is the last window in the app.
   2042                 // We allow the removal of the non-animating starting window now as there is no
   2043                 // additional window or animation that will trigger its removal.
   2044                 if (mWinAnimator.getShown() && mAnimatingExit
   2045                         && (!lastWindowIsStartingWindow || isAnimating)) {
   2046                     // The exit animation is running or should run... wait for it!
   2047                     if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
   2048                             "Not removing " + this + " due to exit animation ");
   2049                     setupWindowForRemoveOnExit();
   2050                     if (mAppToken != null) {
   2051                         mAppToken.updateReportedVisibilityLocked();
   2052                     }
   2053                     return;
   2054                 }
   2055             }
   2056 
   2057             removeImmediately();
   2058             // Removing a visible window will effect the computed orientation
   2059             // So just update orientation if needed.
   2060             if (wasVisible && mService.updateOrientationFromAppTokensLocked(displayId)) {
   2061                 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
   2062             }
   2063             mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
   2064         } finally {
   2065             Binder.restoreCallingIdentity(origId);
   2066         }
   2067     }
   2068 
   2069     private void setupWindowForRemoveOnExit() {
   2070         mRemoveOnExit = true;
   2071         setDisplayLayoutNeeded();
   2072         // Request a focus update as this window's input channel is already gone. Otherwise
   2073         // we could have no focused window in input manager.
   2074         final boolean focusChanged = mService.updateFocusedWindowLocked(
   2075                 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
   2076         mService.mWindowPlacerLocked.performSurfacePlacement();
   2077         if (focusChanged) {
   2078             mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
   2079         }
   2080     }
   2081 
   2082     void setHasSurface(boolean hasSurface) {
   2083         mHasSurface = hasSurface;
   2084     }
   2085 
   2086     boolean canBeImeTarget() {
   2087         if (mIsImWindow) {
   2088             // IME windows can't be IME targets. IME targets are required to be below the IME
   2089             // windows and that wouldn't be possible if the IME window is its own target...silly.
   2090             return false;
   2091         }
   2092 
   2093         final boolean windowsAreFocusable = mAppToken == null || mAppToken.windowsAreFocusable();
   2094         if (!windowsAreFocusable) {
   2095             // This window can't be an IME target if the app's windows should not be focusable.
   2096             return false;
   2097         }
   2098 
   2099         final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
   2100         final int type = mAttrs.type;
   2101 
   2102         // Can only be an IME target if both FLAG_NOT_FOCUSABLE and FLAG_ALT_FOCUSABLE_IM are set or
   2103         // both are cleared...and not a starting window.
   2104         if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
   2105                 && type != TYPE_APPLICATION_STARTING) {
   2106             return false;
   2107         }
   2108 
   2109         if (DEBUG_INPUT_METHOD) {
   2110             Slog.i(TAG_WM, "isVisibleOrAdding " + this + ": " + isVisibleOrAdding());
   2111             if (!isVisibleOrAdding()) {
   2112                 Slog.i(TAG_WM, "  mSurfaceController=" + mWinAnimator.mSurfaceController
   2113                         + " relayoutCalled=" + mRelayoutCalled
   2114                         + " viewVis=" + mViewVisibility
   2115                         + " policyVis=" + mPolicyVisibility
   2116                         + " policyVisAfterAnim=" + mPolicyVisibilityAfterAnim
   2117                         + " parentHidden=" + isParentWindowHidden()
   2118                         + " exiting=" + mAnimatingExit + " destroying=" + mDestroying);
   2119                 if (mAppToken != null) {
   2120                     Slog.i(TAG_WM, "  mAppToken.hiddenRequested=" + mAppToken.hiddenRequested);
   2121                 }
   2122             }
   2123         }
   2124         return isVisibleOrAdding();
   2125     }
   2126 
   2127     private final class DeadWindowEventReceiver extends InputEventReceiver {
   2128         DeadWindowEventReceiver(InputChannel inputChannel) {
   2129             super(inputChannel, mService.mH.getLooper());
   2130         }
   2131         @Override
   2132         public void onInputEvent(InputEvent event, int displayId) {
   2133             finishInputEvent(event, true);
   2134         }
   2135     }
   2136     /**
   2137      *  Dummy event receiver for windows that died visible.
   2138      */
   2139     private DeadWindowEventReceiver mDeadWindowEventReceiver;
   2140 
   2141     void openInputChannel(InputChannel outInputChannel) {
   2142         if (mInputChannel != null) {
   2143             throw new IllegalStateException("Window already has an input channel.");
   2144         }
   2145         String name = getName();
   2146         InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
   2147         mInputChannel = inputChannels[0];
   2148         mClientChannel = inputChannels[1];
   2149         mInputWindowHandle.inputChannel = inputChannels[0];
   2150         if (outInputChannel != null) {
   2151             mClientChannel.transferTo(outInputChannel);
   2152             mClientChannel.dispose();
   2153             mClientChannel = null;
   2154         } else {
   2155             // If the window died visible, we setup a dummy input channel, so that taps
   2156             // can still detected by input monitor channel, and we can relaunch the app.
   2157             // Create dummy event receiver that simply reports all events as handled.
   2158             mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
   2159         }
   2160         mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
   2161     }
   2162 
   2163     void disposeInputChannel() {
   2164         if (mDeadWindowEventReceiver != null) {
   2165             mDeadWindowEventReceiver.dispose();
   2166             mDeadWindowEventReceiver = null;
   2167         }
   2168 
   2169         // unregister server channel first otherwise it complains about broken channel
   2170         if (mInputChannel != null) {
   2171             mService.mInputManager.unregisterInputChannel(mInputChannel);
   2172             mInputChannel.dispose();
   2173             mInputChannel = null;
   2174         }
   2175         if (mClientChannel != null) {
   2176             mClientChannel.dispose();
   2177             mClientChannel = null;
   2178         }
   2179         mInputWindowHandle.inputChannel = null;
   2180     }
   2181 
   2182     /** Returns true if the replacement window was removed. */
   2183     boolean removeReplacedWindowIfNeeded(WindowState replacement) {
   2184         if (mWillReplaceWindow && mReplacementWindow == replacement && replacement.hasDrawnLw()) {
   2185             replacement.mSkipEnterAnimationForSeamlessReplacement = false;
   2186             removeReplacedWindow();
   2187             return true;
   2188         }
   2189 
   2190         for (int i = mChildren.size() - 1; i >= 0; --i) {
   2191             final WindowState c = mChildren.get(i);
   2192             if (c.removeReplacedWindowIfNeeded(replacement)) {
   2193                 return true;
   2194             }
   2195         }
   2196         return false;
   2197     }
   2198 
   2199     private void removeReplacedWindow() {
   2200         if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + this);
   2201         mWillReplaceWindow = false;
   2202         mAnimateReplacingWindow = false;
   2203         mReplacingRemoveRequested = false;
   2204         mReplacementWindow = null;
   2205         if (mAnimatingExit || !mAnimateReplacingWindow) {
   2206             removeImmediately();
   2207         }
   2208     }
   2209 
   2210     boolean setReplacementWindowIfNeeded(WindowState replacementCandidate) {
   2211         boolean replacementSet = false;
   2212 
   2213         if (mWillReplaceWindow && mReplacementWindow == null
   2214                 && getWindowTag().toString().equals(replacementCandidate.getWindowTag().toString())) {
   2215 
   2216             mReplacementWindow = replacementCandidate;
   2217             replacementCandidate.mSkipEnterAnimationForSeamlessReplacement = !mAnimateReplacingWindow;
   2218             replacementSet = true;
   2219         }
   2220 
   2221         for (int i = mChildren.size() - 1; i >= 0; --i) {
   2222             final WindowState c = mChildren.get(i);
   2223             replacementSet |= c.setReplacementWindowIfNeeded(replacementCandidate);
   2224         }
   2225 
   2226         return replacementSet;
   2227     }
   2228 
   2229     void setDisplayLayoutNeeded() {
   2230         final DisplayContent dc = getDisplayContent();
   2231         if (dc != null) {
   2232             dc.setLayoutNeeded();
   2233         }
   2234     }
   2235 
   2236     void applyAdjustForImeIfNeeded() {
   2237         final Task task = getTask();
   2238         if (task != null && task.mStack != null && task.mStack.isAdjustedForIme()) {
   2239             task.mStack.applyAdjustForImeIfNeeded(task);
   2240         }
   2241     }
   2242 
   2243     @Override
   2244     void switchUser() {
   2245         super.switchUser();
   2246         if (isHiddenFromUserLocked()) {
   2247             if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + this
   2248                     + ", attrs=" + mAttrs.type + ", belonging to " + mOwnerUid);
   2249             hideLw(false);
   2250         }
   2251     }
   2252 
   2253     int getTouchableRegion(Region region, int flags) {
   2254         final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
   2255         if (modal && mAppToken != null) {
   2256             // Limit the outer touch to the activity stack region.
   2257             flags |= FLAG_NOT_TOUCH_MODAL;
   2258             // If this is a modal window we need to dismiss it if it's not full screen and the
   2259             // touch happens outside of the frame that displays the content. This means we
   2260             // need to intercept touches outside of that window. The dim layer user
   2261             // associated with the window (task or stack) will give us the good bounds, as
   2262             // they would be used to display the dim layer.
   2263             final Task task = getTask();
   2264             if (task != null) {
   2265                 task.getDimBounds(mTmpRect);
   2266             } else {
   2267                 getStack().getDimBounds(mTmpRect);
   2268             }
   2269             if (inFreeformWindowingMode()) {
   2270                 // For freeform windows we the touch region to include the whole surface for the
   2271                 // shadows.
   2272                 final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
   2273                 final int delta = WindowManagerService.dipToPixel(
   2274                         RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
   2275                 mTmpRect.inset(-delta, -delta);
   2276             }
   2277             region.set(mTmpRect);
   2278             cropRegionToStackBoundsIfNeeded(region);
   2279         } else {
   2280             // Not modal or full screen modal
   2281             getTouchableRegion(region);
   2282         }
   2283         return flags;
   2284     }
   2285 
   2286     void checkPolicyVisibilityChange() {
   2287         if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
   2288             if (DEBUG_VISIBILITY) {
   2289                 Slog.v(TAG, "Policy visibility changing after anim in " +
   2290                         mWinAnimator + ": " + mPolicyVisibilityAfterAnim);
   2291             }
   2292             mPolicyVisibility = mPolicyVisibilityAfterAnim;
   2293             if (!mPolicyVisibility) {
   2294                 mWinAnimator.hide("checkPolicyVisibilityChange");
   2295                 if (mService.mCurrentFocus == this) {
   2296                     if (DEBUG_FOCUS_LIGHT) Slog.i(TAG,
   2297                             "setAnimationLocked: setting mFocusMayChange true");
   2298                     mService.mFocusMayChange = true;
   2299                 }
   2300                 setDisplayLayoutNeeded();
   2301                 // Window is no longer visible -- make sure if we were waiting
   2302                 // for it to be displayed before enabling the display, that
   2303                 // we allow the display to be enabled now.
   2304                 mService.enableScreenIfNeededLocked();
   2305             }
   2306         }
   2307     }
   2308 
   2309     void setRequestedSize(int requestedWidth, int requestedHeight) {
   2310         if ((mRequestedWidth != requestedWidth || mRequestedHeight != requestedHeight)) {
   2311             mLayoutNeeded = true;
   2312             mRequestedWidth = requestedWidth;
   2313             mRequestedHeight = requestedHeight;
   2314         }
   2315     }
   2316 
   2317     void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
   2318         // We need to turn on screen regardless of visibility.
   2319         boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0;
   2320         boolean allowTheaterMode =
   2321                 mService.mAllowTheaterModeWakeFromLayout || Settings.Global.getInt(
   2322                         mService.mContext.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0)
   2323                         == 0;
   2324         boolean canTurnScreenOn = mAppToken == null || mAppToken.canTurnScreenOn();
   2325 
   2326         // The screen will turn on if the following conditions are met
   2327         // 1. The window has the flag FLAG_TURN_SCREEN_ON
   2328         // 2. The WMS allows theater mode.
   2329         // 3. No AWT or the AWT allows the screen to be turned on. This should only be true once
   2330         // per resume to prevent the screen getting getting turned on for each relayout. Set
   2331         // canTurnScreenOn will be set to false so the window doesn't turn the screen on again
   2332         // during this resume.
   2333         // 4. When the screen is not interactive. This is because when the screen is already
   2334         // interactive, the value may persist until the next animation, which could potentially
   2335         // be occurring while turning off the screen. This would lead to the screen incorrectly
   2336         // turning back on.
   2337         if (hasTurnScreenOnFlag) {
   2338             if (allowTheaterMode && canTurnScreenOn && !mPowerManagerWrapper.isInteractive()) {
   2339                 if (DEBUG_VISIBILITY || DEBUG_POWER) {
   2340                     Slog.v(TAG, "Relayout window turning screen on: " + this);
   2341                 }
   2342                 mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),
   2343                         "android.server.wm:TURN_ON");
   2344             }
   2345 
   2346             if (mAppToken != null) {
   2347                 mAppToken.setCanTurnScreenOn(false);
   2348             }
   2349         }
   2350 
   2351         // If we were already visible, skip rest of preparation.
   2352         if (wasVisible) {
   2353             if (DEBUG_VISIBILITY) Slog.v(TAG,
   2354                     "Already visible and does not turn on screen, skip preparing: " + this);
   2355             return;
   2356         }
   2357 
   2358         if ((mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
   2359                 == SOFT_INPUT_ADJUST_RESIZE) {
   2360             mLayoutNeeded = true;
   2361         }
   2362 
   2363         if (isDrawnLw() && mToken.okToAnimate()) {
   2364             mWinAnimator.applyEnterAnimationLocked();
   2365         }
   2366     }
   2367 
   2368     void getMergedConfiguration(MergedConfiguration outConfiguration) {
   2369         final Configuration globalConfig = mService.mRoot.getConfiguration();
   2370         final Configuration overrideConfig = getMergedOverrideConfiguration();
   2371         outConfiguration.setConfiguration(globalConfig, overrideConfig);
   2372     }
   2373 
   2374     void setLastReportedMergedConfiguration(MergedConfiguration config) {
   2375         mLastReportedConfiguration.setTo(config);
   2376     }
   2377 
   2378     void getLastReportedMergedConfiguration(MergedConfiguration config) {
   2379         config.setTo(mLastReportedConfiguration);
   2380     }
   2381 
   2382     private Configuration getLastReportedConfiguration() {
   2383         return mLastReportedConfiguration.getMergedConfiguration();
   2384     }
   2385 
   2386     void adjustStartingWindowFlags() {
   2387         if (mAttrs.type == TYPE_BASE_APPLICATION && mAppToken != null
   2388                 && mAppToken.startingWindow != null) {
   2389             // Special handling of starting window over the base
   2390             // window of the app: propagate lock screen flags to it,
   2391             // to provide the correct semantics while starting.
   2392             final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD
   2393                     | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
   2394             WindowManager.LayoutParams sa = mAppToken.startingWindow.mAttrs;
   2395             sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask);
   2396         }
   2397     }
   2398 
   2399     void setWindowScale(int requestedWidth, int requestedHeight) {
   2400         final boolean scaledWindow = (mAttrs.flags & FLAG_SCALED) != 0;
   2401 
   2402         if (scaledWindow) {
   2403             // requested{Width|Height} Surface's physical size
   2404             // attrs.{width|height} Size on screen
   2405             // TODO: We don't check if attrs != null here. Is it implicitly checked?
   2406             mHScale = (mAttrs.width  != requestedWidth)  ?
   2407                     (mAttrs.width  / (float)requestedWidth) : 1.0f;
   2408             mVScale = (mAttrs.height != requestedHeight) ?
   2409                     (mAttrs.height / (float)requestedHeight) : 1.0f;
   2410         } else {
   2411             mHScale = mVScale = 1;
   2412         }
   2413     }
   2414 
   2415     private class DeathRecipient implements IBinder.DeathRecipient {
   2416         @Override
   2417         public void binderDied() {
   2418             try {
   2419                 boolean resetSplitScreenResizing = false;
   2420                 synchronized(mService.mWindowMap) {
   2421                     final WindowState win = mService.windowForClientLocked(mSession, mClient, false);
   2422                     Slog.i(TAG, "WIN DEATH: " + win);
   2423                     if (win != null) {
   2424                         final DisplayContent dc = getDisplayContent();
   2425                         if (win.mAppToken != null && win.mAppToken.findMainWindow() == win) {
   2426                             mService.mTaskSnapshotController.onAppDied(win.mAppToken);
   2427                         }
   2428                         win.removeIfPossible(shouldKeepVisibleDeadAppWindow());
   2429                         if (win.mAttrs.type == TYPE_DOCK_DIVIDER) {
   2430                             // The owner of the docked divider died :( We reset the docked stack,
   2431                             // just in case they have the divider at an unstable position. Better
   2432                             // also reset drag resizing state, because the owner can't do it
   2433                             // anymore.
   2434                             final TaskStack stack =
   2435                                     dc.getSplitScreenPrimaryStackIgnoringVisibility();
   2436                             if (stack != null) {
   2437                                 stack.resetDockedStackToMiddle();
   2438                             }
   2439                             resetSplitScreenResizing = true;
   2440                         }
   2441                     } else if (mHasSurface) {
   2442                         Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
   2443                         WindowState.this.removeIfPossible();
   2444                     }
   2445                 }
   2446                 if (resetSplitScreenResizing) {
   2447                     try {
   2448                         // Note: this calls into ActivityManager, so we must *not* hold the window
   2449                         // manager lock while calling this.
   2450                         mService.mActivityManager.setSplitScreenResizing(false);
   2451                     } catch (RemoteException e) {
   2452                         // Local call, shouldn't return RemoteException.
   2453                         throw e.rethrowAsRuntimeException();
   2454                     }
   2455                 }
   2456             } catch (IllegalArgumentException ex) {
   2457                 // This will happen if the window has already been removed.
   2458             }
   2459         }
   2460     }
   2461 
   2462     /**
   2463      * Returns true if this window is visible and belongs to a dead app and shouldn't be removed,
   2464      * because we want to preserve its location on screen to be re-activated later when the user
   2465      * interacts with it.
   2466      */
   2467     private boolean shouldKeepVisibleDeadAppWindow() {
   2468         if (!isWinVisibleLw() || mAppToken == null || mAppToken.isClientHidden()) {
   2469             // Not a visible app window or the app isn't dead.
   2470             return false;
   2471         }
   2472 
   2473         if (mAttrs.token != mClient.asBinder()) {
   2474             // The window was add by a client using another client's app token. We don't want to
   2475             // keep the dead window around for this case since this is meant for 'real' apps.
   2476             return false;
   2477         }
   2478 
   2479         if (mAttrs.type == TYPE_APPLICATION_STARTING) {
   2480             // We don't keep starting windows since they were added by the window manager before
   2481             // the app even launched.
   2482             return false;
   2483         }
   2484 
   2485         return getWindowConfiguration().keepVisibleDeadAppWindowOnScreen();
   2486     }
   2487 
   2488     /** @return true if this window desires key events. */
   2489     boolean canReceiveKeys() {
   2490         return isVisibleOrAdding()
   2491                 && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
   2492                 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
   2493                 && (mAppToken == null || mAppToken.windowsAreFocusable())
   2494                 && !canReceiveTouchInput();
   2495     }
   2496 
   2497     /** @return true if this window desires touch events. */
   2498     boolean canReceiveTouchInput() {
   2499         return mAppToken != null && mAppToken.getTask() != null
   2500                 && mAppToken.getTask().mStack.shouldIgnoreInput();
   2501     }
   2502 
   2503     @Override
   2504     public boolean hasDrawnLw() {
   2505         return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN;
   2506     }
   2507 
   2508     @Override
   2509     public boolean showLw(boolean doAnimation) {
   2510         return showLw(doAnimation, true);
   2511     }
   2512 
   2513     boolean showLw(boolean doAnimation, boolean requestAnim) {
   2514         if (isHiddenFromUserLocked()) {
   2515             return false;
   2516         }
   2517         if (!mAppOpVisibility) {
   2518             // Being hidden due to app op request.
   2519             return false;
   2520         }
   2521         if (mPermanentlyHidden) {
   2522             // Permanently hidden until the app exists as apps aren't prepared
   2523             // to handle their windows being removed from under them.
   2524             return false;
   2525         }
   2526         if (mHiddenWhileSuspended) {
   2527             // Being hidden due to owner package being suspended.
   2528             return false;
   2529         }
   2530         if (mForceHideNonSystemOverlayWindow) {
   2531             // This is an alert window that is currently force hidden.
   2532             return false;
   2533         }
   2534         if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
   2535             // Already showing.
   2536             return false;
   2537         }
   2538         if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
   2539         if (doAnimation) {
   2540             if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
   2541                     + mPolicyVisibility + " isAnimationSet=" + mWinAnimator.isAnimationSet());
   2542             if (!mToken.okToAnimate()) {
   2543                 doAnimation = false;
   2544             } else if (mPolicyVisibility && !mWinAnimator.isAnimationSet()) {
   2545                 // Check for the case where we are currently visible and
   2546                 // not animating; we do not want to do animation at such a
   2547                 // point to become visible when we already are.
   2548                 doAnimation = false;
   2549             }
   2550         }
   2551         mPolicyVisibility = true;
   2552         mPolicyVisibilityAfterAnim = true;
   2553         if (doAnimation) {
   2554             mWinAnimator.applyAnimationLocked(TRANSIT_ENTER, true);
   2555         }
   2556         if (requestAnim) {
   2557             mService.scheduleAnimationLocked();
   2558         }
   2559         if ((mAttrs.flags & FLAG_NOT_FOCUSABLE) == 0) {
   2560             mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
   2561         }
   2562         return true;
   2563     }
   2564 
   2565     @Override
   2566     public boolean hideLw(boolean doAnimation) {
   2567         return hideLw(doAnimation, true);
   2568     }
   2569 
   2570     boolean hideLw(boolean doAnimation, boolean requestAnim) {
   2571         if (doAnimation) {
   2572             if (!mToken.okToAnimate()) {
   2573                 doAnimation = false;
   2574             }
   2575         }
   2576         boolean current = doAnimation ? mPolicyVisibilityAfterAnim : mPolicyVisibility;
   2577         if (!current) {
   2578             // Already hiding.
   2579             return false;
   2580         }
   2581         if (doAnimation) {
   2582             mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
   2583             if (!mWinAnimator.isAnimationSet()) {
   2584                 doAnimation = false;
   2585             }
   2586         }
   2587         mPolicyVisibilityAfterAnim = false;
   2588         if (!doAnimation) {
   2589             if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
   2590             mPolicyVisibility = false;
   2591             // Window is no longer visible -- make sure if we were waiting
   2592             // for it to be displayed before enabling the display, that
   2593             // we allow the display to be enabled now.
   2594             mService.enableScreenIfNeededLocked();
   2595             if (mService.mCurrentFocus == this) {
   2596                 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG,
   2597                         "WindowState.hideLw: setting mFocusMayChange true");
   2598                 mService.mFocusMayChange = true;
   2599             }
   2600         }
   2601         if (requestAnim) {
   2602             mService.scheduleAnimationLocked();
   2603         }
   2604         if (mService.mCurrentFocus == this) {
   2605             mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
   2606         }
   2607         return true;
   2608     }
   2609 
   2610     void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) {
   2611         if (mOwnerCanAddInternalSystemWindow
   2612                 || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
   2613             return;
   2614         }
   2615         if (mForceHideNonSystemOverlayWindow == forceHide) {
   2616             return;
   2617         }
   2618         mForceHideNonSystemOverlayWindow = forceHide;
   2619         if (forceHide) {
   2620             hideLw(true /* doAnimation */, true /* requestAnim */);
   2621         } else {
   2622             showLw(true /* doAnimation */, true /* requestAnim */);
   2623         }
   2624     }
   2625 
   2626     void setHiddenWhileSuspended(boolean hide) {
   2627         if (mOwnerCanAddInternalSystemWindow
   2628                 || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
   2629             return;
   2630         }
   2631         if (mHiddenWhileSuspended == hide) {
   2632             return;
   2633         }
   2634         mHiddenWhileSuspended = hide;
   2635         if (hide) {
   2636             hideLw(true, true);
   2637         } else {
   2638             showLw(true, true);
   2639         }
   2640     }
   2641 
   2642     private void setAppOpVisibilityLw(boolean state) {
   2643         if (mAppOpVisibility != state) {
   2644             mAppOpVisibility = state;
   2645             if (state) {
   2646                 // If the policy visibility had last been to hide, then this
   2647                 // will incorrectly show at this point since we lost that
   2648                 // information.  Not a big deal -- for the windows that have app
   2649                 // ops modifies they should only be hidden by policy due to the
   2650                 // lock screen, and the user won't be changing this if locked.
   2651                 // Plus it will quickly be fixed the next time we do a layout.
   2652                 showLw(true, true);
   2653             } else {
   2654                 hideLw(true, true);
   2655             }
   2656         }
   2657     }
   2658 
   2659     void initAppOpsState() {
   2660         if (mAppOp == OP_NONE || !mAppOpVisibility) {
   2661             return;
   2662         }
   2663         // If the app op was MODE_DEFAULT we would have checked the permission
   2664         // and add the window only if the permission was granted. Therefore, if
   2665         // the mode is MODE_DEFAULT we want the op to succeed as the window is
   2666         // shown.
   2667         final int mode = mService.mAppOps.startOpNoThrow(mAppOp,
   2668                 getOwningUid(), getOwningPackage(), true);
   2669         if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) {
   2670             setAppOpVisibilityLw(false);
   2671         }
   2672     }
   2673 
   2674     void resetAppOpsState() {
   2675         if (mAppOp != OP_NONE && mAppOpVisibility) {
   2676             mService.mAppOps.finishOp(mAppOp, getOwningUid(), getOwningPackage());
   2677         }
   2678     }
   2679 
   2680     void updateAppOpsState() {
   2681         if (mAppOp == OP_NONE) {
   2682             return;
   2683         }
   2684         final int uid = getOwningUid();
   2685         final String packageName = getOwningPackage();
   2686         if (mAppOpVisibility) {
   2687             // There is a race between the check and the finish calls but this is fine
   2688             // as this would mean we will get another change callback and will reconcile.
   2689             int mode = mService.mAppOps.checkOpNoThrow(mAppOp, uid, packageName);
   2690             if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) {
   2691                 mService.mAppOps.finishOp(mAppOp, uid, packageName);
   2692                 setAppOpVisibilityLw(false);
   2693             }
   2694         } else {
   2695             final int mode = mService.mAppOps.startOpNoThrow(mAppOp, uid, packageName, true);
   2696             if (mode == MODE_ALLOWED || mode == MODE_DEFAULT) {
   2697                 setAppOpVisibilityLw(true);
   2698             }
   2699         }
   2700     }
   2701 
   2702     public void hidePermanentlyLw() {
   2703         if (!mPermanentlyHidden) {
   2704             mPermanentlyHidden = true;
   2705             hideLw(true, true);
   2706         }
   2707     }
   2708 
   2709     public void pokeDrawLockLw(long timeout) {
   2710         if (isVisibleOrAdding()) {
   2711             if (mDrawLock == null) {
   2712                 // We want the tag name to be somewhat stable so that it is easier to correlate
   2713                 // in wake lock statistics.  So in particular, we don't want to include the
   2714                 // window's hash code as in toString().
   2715                 final CharSequence tag = getWindowTag();
   2716                 mDrawLock = mService.mPowerManager.newWakeLock(DRAW_WAKE_LOCK, "Window:" + tag);
   2717                 mDrawLock.setReferenceCounted(false);
   2718                 mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName));
   2719             }
   2720             // Each call to acquire resets the timeout.
   2721             if (DEBUG_POWER) {
   2722                 Slog.d(TAG, "pokeDrawLock: poking draw lock on behalf of visible window owned by "
   2723                         + mAttrs.packageName);
   2724             }
   2725             mDrawLock.acquire(timeout);
   2726         } else if (DEBUG_POWER) {
   2727             Slog.d(TAG, "pokeDrawLock: suppressed draw lock request for invisible window "
   2728                     + "owned by " + mAttrs.packageName);
   2729         }
   2730     }
   2731 
   2732     @Override
   2733     public boolean isAlive() {
   2734         return mClient.asBinder().isBinderAlive();
   2735     }
   2736 
   2737     boolean isClosing() {
   2738         return mAnimatingExit || (mAppToken != null && mAppToken.isClosingOrEnteringPip());
   2739     }
   2740 
   2741     void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) {
   2742         animators.add(mWinAnimator);
   2743 
   2744         for (int i = mChildren.size() - 1; i >= 0; --i) {
   2745             final WindowState c = mChildren.get(i);
   2746             c.addWinAnimatorToList(animators);
   2747         }
   2748     }
   2749 
   2750     void sendAppVisibilityToClients() {
   2751         super.sendAppVisibilityToClients();
   2752 
   2753         final boolean clientHidden = mAppToken.isClientHidden();
   2754         if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) {
   2755             // Don't hide the starting window.
   2756             return;
   2757         }
   2758 
   2759         if (clientHidden) {
   2760             // Once we are notifying the client that it's visibility has changed, we need to prevent
   2761             // it from destroying child surfaces until the animation has finished. We do this by
   2762             // detaching any surface control the client added from the client.
   2763             for (int i = mChildren.size() - 1; i >= 0; --i) {
   2764                 final WindowState c = mChildren.get(i);
   2765                 c.mWinAnimator.detachChildren();
   2766             }
   2767 
   2768             mWinAnimator.detachChildren();
   2769         }
   2770 
   2771         try {
   2772             if (DEBUG_VISIBILITY) Slog.v(TAG,
   2773                     "Setting visibility of " + this + ": " + (!clientHidden));
   2774             mClient.dispatchAppVisibility(!clientHidden);
   2775         } catch (RemoteException e) {
   2776         }
   2777     }
   2778 
   2779     void onStartFreezingScreen() {
   2780         mAppFreezing = true;
   2781         for (int i = mChildren.size() - 1; i >= 0; --i) {
   2782             final WindowState c = mChildren.get(i);
   2783             c.onStartFreezingScreen();
   2784         }
   2785     }
   2786 
   2787     boolean onStopFreezingScreen() {
   2788         boolean unfrozeWindows = false;
   2789         for (int i = mChildren.size() - 1; i >= 0; --i) {
   2790             final WindowState c = mChildren.get(i);
   2791             unfrozeWindows |= c.onStopFreezingScreen();
   2792         }
   2793 
   2794         if (!mAppFreezing) {
   2795             return unfrozeWindows;
   2796         }
   2797 
   2798         mAppFreezing = false;
   2799 
   2800         if (mHasSurface && !getOrientationChanging()
   2801                 && mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
   2802             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + this);
   2803             setOrientationChanging(true);
   2804             mService.mRoot.mOrientationChangeComplete = false;
   2805         }
   2806         mLastFreezeDuration = 0;
   2807         setDisplayLayoutNeeded();
   2808         return true;
   2809     }
   2810 
   2811     boolean destroySurface(boolean cleanupOnResume, boolean appStopped) {
   2812         boolean destroyedSomething = false;
   2813 
   2814         // Copying to a different list as multiple children can be removed.
   2815         final ArrayList<WindowState> childWindows = new ArrayList<>(mChildren);
   2816         for (int i = childWindows.size() - 1; i >= 0; --i) {
   2817             final WindowState c = childWindows.get(i);
   2818             destroyedSomething |= c.destroySurface(cleanupOnResume, appStopped);
   2819         }
   2820 
   2821         if (!(appStopped || mWindowRemovalAllowed || cleanupOnResume)) {
   2822             return destroyedSomething;
   2823         }
   2824 
   2825         if (appStopped || mWindowRemovalAllowed) {
   2826             mWinAnimator.destroyPreservedSurfaceLocked();
   2827         }
   2828 
   2829         if (mDestroying) {
   2830             if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + this
   2831                     + " destroySurfaces: appStopped=" + appStopped
   2832                     + " win.mWindowRemovalAllowed=" + mWindowRemovalAllowed
   2833                     + " win.mRemoveOnExit=" + mRemoveOnExit);
   2834             if (!cleanupOnResume || mRemoveOnExit) {
   2835                 destroySurfaceUnchecked();
   2836             }
   2837             if (mRemoveOnExit) {
   2838                 removeImmediately();
   2839             }
   2840             if (cleanupOnResume) {
   2841                 requestUpdateWallpaperIfNeeded();
   2842             }
   2843             mDestroying = false;
   2844             destroyedSomething = true;
   2845         }
   2846 
   2847         return destroyedSomething;
   2848     }
   2849 
   2850     // Destroy or save the application surface without checking
   2851     // various indicators of whether the client has released the surface.
   2852     // This is in general unsafe, and most callers should use {@link #destroySurface}
   2853     void destroySurfaceUnchecked() {
   2854         mWinAnimator.destroySurfaceLocked();
   2855 
   2856         // Clear animating flags now, since the surface is now gone. (Note this is true even
   2857         // if the surface is saved, to outside world the surface is still NO_SURFACE.)
   2858         mAnimatingExit = false;
   2859     }
   2860 
   2861     @Override
   2862     public boolean isDefaultDisplay() {
   2863         final DisplayContent displayContent = getDisplayContent();
   2864         if (displayContent == null) {
   2865             // Only a window that was on a non-default display can be detached from it.
   2866             return false;
   2867         }
   2868         return displayContent.isDefaultDisplay;
   2869     }
   2870 
   2871     void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
   2872         mShowToOwnerOnly = showToOwnerOnly;
   2873     }
   2874 
   2875     private boolean isHiddenFromUserLocked() {
   2876         // Child windows are evaluated based on their parent window.
   2877         final WindowState win = getTopParentWindow();
   2878         if (win.mAttrs.type < FIRST_SYSTEM_WINDOW
   2879                 && win.mAppToken != null && win.mAppToken.mShowForAllUsers) {
   2880 
   2881             // All window frames that are fullscreen extend above status bar, but some don't extend
   2882             // below navigation bar. Thus, check for display frame for top/left and stable frame for
   2883             // bottom right.
   2884             if (win.mFrame.left <= win.mDisplayFrame.left
   2885                     && win.mFrame.top <= win.mDisplayFrame.top
   2886                     && win.mFrame.right >= win.mStableFrame.right
   2887                     && win.mFrame.bottom >= win.mStableFrame.bottom) {
   2888                 // Is a fullscreen window, like the clock alarm. Show to everyone.
   2889                 return false;
   2890             }
   2891         }
   2892 
   2893         return win.mShowToOwnerOnly
   2894                 && !mService.isCurrentProfileLocked(UserHandle.getUserId(win.mOwnerUid));
   2895     }
   2896 
   2897     private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
   2898         outRegion.set(
   2899                 frame.left + inset.left, frame.top + inset.top,
   2900                 frame.right - inset.right, frame.bottom - inset.bottom);
   2901     }
   2902 
   2903     void getTouchableRegion(Region outRegion) {
   2904         final Rect frame = mFrame;
   2905         switch (mTouchableInsets) {
   2906             default:
   2907             case TOUCHABLE_INSETS_FRAME:
   2908                 outRegion.set(frame);
   2909                 break;
   2910             case TOUCHABLE_INSETS_CONTENT:
   2911                 applyInsets(outRegion, frame, mGivenContentInsets);
   2912                 break;
   2913             case TOUCHABLE_INSETS_VISIBLE:
   2914                 applyInsets(outRegion, frame, mGivenVisibleInsets);
   2915                 break;
   2916             case TOUCHABLE_INSETS_REGION: {
   2917                 outRegion.set(mGivenTouchableRegion);
   2918                 outRegion.translate(frame.left, frame.top);
   2919                 break;
   2920             }
   2921         }
   2922         cropRegionToStackBoundsIfNeeded(outRegion);
   2923     }
   2924 
   2925     private void cropRegionToStackBoundsIfNeeded(Region region) {
   2926         final Task task = getTask();
   2927         if (task == null || !task.cropWindowsToStackBounds()) {
   2928             return;
   2929         }
   2930 
   2931         final TaskStack stack = task.mStack;
   2932         if (stack == null) {
   2933             return;
   2934         }
   2935 
   2936         stack.getDimBounds(mTmpRect);
   2937         region.op(mTmpRect, Region.Op.INTERSECT);
   2938     }
   2939 
   2940     /**
   2941      * Report a focus change.  Must be called with no locks held, and consistently
   2942      * from the same serialized thread (such as dispatched from a handler).
   2943      */
   2944     void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) {
   2945         try {
   2946             mClient.windowFocusChanged(focused, inTouchMode);
   2947         } catch (RemoteException e) {
   2948         }
   2949         if (mFocusCallbacks != null) {
   2950             final int N = mFocusCallbacks.beginBroadcast();
   2951             for (int i=0; i<N; i++) {
   2952                 IWindowFocusObserver obs = mFocusCallbacks.getBroadcastItem(i);
   2953                 try {
   2954                     if (focused) {
   2955                         obs.focusGained(mWindowId.asBinder());
   2956                     } else {
   2957                         obs.focusLost(mWindowId.asBinder());
   2958                     }
   2959                 } catch (RemoteException e) {
   2960                 }
   2961             }
   2962             mFocusCallbacks.finishBroadcast();
   2963         }
   2964     }
   2965 
   2966     @Override
   2967     public Configuration getConfiguration() {
   2968         if (mAppToken != null && mAppToken.mFrozenMergedConfig.size() > 0) {
   2969             return mAppToken.mFrozenMergedConfig.peek();
   2970         }
   2971 
   2972         return super.getConfiguration();
   2973     }
   2974 
   2975     void reportResized() {
   2976         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
   2977         try {
   2978             if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
   2979                     + ": " + mCompatFrame);
   2980             final MergedConfiguration mergedConfiguration =
   2981                     new MergedConfiguration(mService.mRoot.getConfiguration(),
   2982                     getMergedOverrideConfiguration());
   2983 
   2984             setLastReportedMergedConfiguration(mergedConfiguration);
   2985 
   2986             if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING)
   2987                 Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
   2988 
   2989             final Rect frame = mFrame;
   2990             final Rect overscanInsets = mLastOverscanInsets;
   2991             final Rect contentInsets = mLastContentInsets;
   2992             final Rect visibleInsets = mLastVisibleInsets;
   2993             final Rect stableInsets = mLastStableInsets;
   2994             final Rect outsets = mLastOutsets;
   2995             final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING;
   2996             final boolean reportOrientation = mReportOrientationChanged;
   2997             final int displayId = getDisplayId();
   2998             final DisplayCutout displayCutout = mDisplayCutout.getDisplayCutout();
   2999             if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
   3000                     && mClient instanceof IWindow.Stub) {
   3001                 // To prevent deadlock simulate one-way call if win.mClient is a local object.
   3002                 mService.mH.post(new Runnable() {
   3003                     @Override
   3004                     public void run() {
   3005                         try {
   3006                             dispatchResized(frame, overscanInsets, contentInsets, visibleInsets,
   3007                                     stableInsets, outsets, reportDraw, mergedConfiguration,
   3008                                     reportOrientation, displayId, displayCutout);
   3009                         } catch (RemoteException e) {
   3010                             // Not a remote call, RemoteException won't be raised.
   3011                         }
   3012                     }
   3013                 });
   3014             } else {
   3015                 dispatchResized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets,
   3016                         outsets, reportDraw, mergedConfiguration, reportOrientation, displayId,
   3017                         displayCutout);
   3018             }
   3019 
   3020             //TODO (multidisplay): Accessibility supported only for the default display.
   3021             if (mService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
   3022                 mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
   3023             }
   3024 
   3025             mOverscanInsetsChanged = false;
   3026             mContentInsetsChanged = false;
   3027             mVisibleInsetsChanged = false;
   3028             mStableInsetsChanged = false;
   3029             mOutsetsChanged = false;
   3030             mFrameSizeChanged = false;
   3031             mDisplayCutoutChanged = false;
   3032             mWinAnimator.mSurfaceResized = false;
   3033             mReportOrientationChanged = false;
   3034         } catch (RemoteException e) {
   3035             setOrientationChanging(false);
   3036             mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
   3037                     - mService.mDisplayFreezeTime);
   3038             // We are assuming the hosting process is dead or in a zombie state.
   3039             Slog.w(TAG, "Failed to report 'resized' to the client of " + this
   3040                     + ", removing this window.");
   3041             mService.mPendingRemove.add(this);
   3042             mService.mWindowPlacerLocked.requestTraversal();
   3043         }
   3044         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
   3045     }
   3046 
   3047     Rect getBackdropFrame(Rect frame) {
   3048         // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
   3049         // start even if we haven't received the relayout window, so that the client requests
   3050         // the relayout sooner. When dragging stops, backDropFrame needs to stay fullscreen
   3051         // until the window to small size, otherwise the multithread renderer will shift last
   3052         // one or more frame to wrong offset. So here we send fullscreen backdrop if either
   3053         // isDragResizing() or isDragResizeChanged() is true.
   3054         boolean resizing = isDragResizing() || isDragResizeChanged();
   3055         if (getWindowConfiguration().useWindowFrameForBackdrop() || !resizing) {
   3056             return frame;
   3057         }
   3058         final DisplayInfo displayInfo = getDisplayInfo();
   3059         mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
   3060         return mTmpRect;
   3061     }
   3062 
   3063     private int getStackId() {
   3064         final TaskStack stack = getStack();
   3065         if (stack == null) {
   3066             return INVALID_STACK_ID;
   3067         }
   3068         return stack.mStackId;
   3069     }
   3070 
   3071     private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
   3072             Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
   3073             MergedConfiguration mergedConfiguration, boolean reportOrientation, int displayId,
   3074             DisplayCutout displayCutout)
   3075             throws RemoteException {
   3076         final boolean forceRelayout = isDragResizeChanged() || reportOrientation;
   3077 
   3078         mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets,
   3079                 reportDraw, mergedConfiguration, getBackdropFrame(frame), forceRelayout,
   3080                 mPolicy.isNavBarForcedShownLw(this), displayId,
   3081                 new DisplayCutout.ParcelableWrapper(displayCutout));
   3082         mDragResizingChangeReported = true;
   3083     }
   3084 
   3085     public void registerFocusObserver(IWindowFocusObserver observer) {
   3086         synchronized(mService.mWindowMap) {
   3087             if (mFocusCallbacks == null) {
   3088                 mFocusCallbacks = new RemoteCallbackList<IWindowFocusObserver>();
   3089             }
   3090             mFocusCallbacks.register(observer);
   3091         }
   3092     }
   3093 
   3094     public void unregisterFocusObserver(IWindowFocusObserver observer) {
   3095         synchronized(mService.mWindowMap) {
   3096             if (mFocusCallbacks != null) {
   3097                 mFocusCallbacks.unregister(observer);
   3098             }
   3099         }
   3100     }
   3101 
   3102     public boolean isFocused() {
   3103         synchronized(mService.mWindowMap) {
   3104             return mService.mCurrentFocus == this;
   3105         }
   3106     }
   3107 
   3108     @Override
   3109     public boolean isInMultiWindowMode() {
   3110         final Task task = getTask();
   3111         return task != null && !task.isFullscreen();
   3112     }
   3113 
   3114     /** Is this window in a container that takes up the entire screen space? */
   3115     private boolean inFullscreenContainer() {
   3116         return mAppToken == null || (mAppToken.matchParentBounds() && !isInMultiWindowMode());
   3117     }
   3118 
   3119     /** @return true when the window is in fullscreen task, but has non-fullscreen bounds set. */
   3120     boolean isLetterboxedAppWindow() {
   3121         return !isInMultiWindowMode() && mAppToken != null && !mAppToken.matchParentBounds()
   3122                 || isLetterboxedForDisplayCutoutLw();
   3123     }
   3124 
   3125     @Override
   3126     public boolean isLetterboxedForDisplayCutoutLw() {
   3127         if (mAppToken == null) {
   3128             // Only windows with an AppWindowToken are letterboxed.
   3129             return false;
   3130         }
   3131         if (!mParentFrameWasClippedByDisplayCutout) {
   3132             // Cutout didn't make a difference, no letterbox
   3133             return false;
   3134         }
   3135         if (mAttrs.layoutInDisplayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
   3136             // Layout in cutout, no letterbox.
   3137             return false;
   3138         }
   3139         if (!mAttrs.isFullscreen()) {
   3140             // Not filling the parent frame, no letterbox
   3141             return false;
   3142         }
   3143         // Otherwise we need a letterbox if the layout was smaller than the app window token allowed
   3144         // it to be.
   3145         return !frameCoversEntireAppTokenBounds();
   3146     }
   3147 
   3148     /**
   3149      * @return true if this window covers the entire bounds of its app window token
   3150      * @throws NullPointerException if there is no app window token for this window
   3151      */
   3152     private boolean frameCoversEntireAppTokenBounds() {
   3153         mTmpRect.set(mAppToken.getBounds());
   3154         mTmpRect.intersectUnchecked(mFrame);
   3155         return mAppToken.getBounds().equals(mTmpRect);
   3156     }
   3157 
   3158     @Override
   3159     public boolean isLetterboxedOverlappingWith(Rect rect) {
   3160         return mAppToken != null && mAppToken.isLetterboxOverlappingWith(rect);
   3161     }
   3162 
   3163     boolean isDragResizeChanged() {
   3164         return mDragResizing != computeDragResizing();
   3165     }
   3166 
   3167     @Override
   3168     void setWaitingForDrawnIfResizingChanged() {
   3169         if (isDragResizeChanged()) {
   3170             mService.mWaitingForDrawn.add(this);
   3171         }
   3172         super.setWaitingForDrawnIfResizingChanged();
   3173     }
   3174 
   3175     /**
   3176      * @return Whether we reported a drag resize change to the application or not already.
   3177      */
   3178     private boolean isDragResizingChangeReported() {
   3179         return mDragResizingChangeReported;
   3180     }
   3181 
   3182     /**
   3183      * Resets the state whether we reported a drag resize change to the app.
   3184      */
   3185     @Override
   3186     void resetDragResizingChangeReported() {
   3187         mDragResizingChangeReported = false;
   3188         super.resetDragResizingChangeReported();
   3189     }
   3190 
   3191     int getResizeMode() {
   3192         return mResizeMode;
   3193     }
   3194 
   3195     private boolean computeDragResizing() {
   3196         final Task task = getTask();
   3197         if (task == null) {
   3198             return false;
   3199         }
   3200         if (!inSplitScreenWindowingMode() && !inFreeformWindowingMode()) {
   3201             return false;
   3202         }
   3203         if (mAttrs.width != MATCH_PARENT || mAttrs.height != MATCH_PARENT) {
   3204             // Floating windows never enter drag resize mode.
   3205             return false;
   3206         }
   3207         if (task.isDragResizing()) {
   3208             return true;
   3209         }
   3210 
   3211         // If the bounds are currently frozen, it means that the layout size that the app sees
   3212         // and the bounds we clip this window to might be different. In order to avoid holes, we
   3213         // simulate that we are still resizing so the app fills the hole with the resizing
   3214         // background.
   3215         return (getDisplayContent().mDividerControllerLocked.isResizing()
   3216                         || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) &&
   3217                 !task.inFreeformWindowingMode() && !isGoneForLayoutLw();
   3218 
   3219     }
   3220 
   3221     void setDragResizing() {
   3222         final boolean resizing = computeDragResizing();
   3223         if (resizing == mDragResizing) {
   3224             return;
   3225         }
   3226         mDragResizing = resizing;
   3227         final Task task = getTask();
   3228         if (task != null && task.isDragResizing()) {
   3229             mResizeMode = task.getDragResizeMode();
   3230         } else {
   3231             mResizeMode = mDragResizing && getDisplayContent().mDividerControllerLocked.isResizing()
   3232                     ? DRAG_RESIZE_MODE_DOCKED_DIVIDER
   3233                     : DRAG_RESIZE_MODE_FREEFORM;
   3234         }
   3235     }
   3236 
   3237     boolean isDragResizing() {
   3238         return mDragResizing;
   3239     }
   3240 
   3241     boolean isDockedResizing() {
   3242         return (mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER)
   3243                 || (isChildWindow() && getParentWindow().isDockedResizing());
   3244     }
   3245 
   3246     @CallSuper
   3247     @Override
   3248     public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
   3249         final long token = proto.start(fieldId);
   3250         super.writeToProto(proto, WINDOW_CONTAINER, trim);
   3251         writeIdentifierToProto(proto, IDENTIFIER);
   3252         proto.write(DISPLAY_ID, getDisplayId());
   3253         proto.write(STACK_ID, getStackId());
   3254         mAttrs.writeToProto(proto, ATTRIBUTES);
   3255         mGivenContentInsets.writeToProto(proto, GIVEN_CONTENT_INSETS);
   3256         mFrame.writeToProto(proto, FRAME);
   3257         mContainingFrame.writeToProto(proto, CONTAINING_FRAME);
   3258         mParentFrame.writeToProto(proto, PARENT_FRAME);
   3259         mContentFrame.writeToProto(proto, CONTENT_FRAME);
   3260         mContentInsets.writeToProto(proto, CONTENT_INSETS);
   3261         mAttrs.surfaceInsets.writeToProto(proto, SURFACE_INSETS);
   3262         mSurfacePosition.writeToProto(proto, SURFACE_POSITION);
   3263         mWinAnimator.writeToProto(proto, ANIMATOR);
   3264         proto.write(ANIMATING_EXIT, mAnimatingExit);
   3265         for (int i = 0; i < mChildren.size(); i++) {
   3266             mChildren.get(i).writeToProto(proto, CHILD_WINDOWS, trim);
   3267         }
   3268         proto.write(REQUESTED_WIDTH, mRequestedWidth);
   3269         proto.write(REQUESTED_HEIGHT, mRequestedHeight);
   3270         proto.write(VIEW_VISIBILITY, mViewVisibility);
   3271         proto.write(SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
   3272         proto.write(HAS_SURFACE, mHasSurface);
   3273         proto.write(IS_READY_FOR_DISPLAY, isReadyForDisplay());
   3274         mDisplayFrame.writeToProto(proto, DISPLAY_FRAME);
   3275         mOverscanFrame.writeToProto(proto, OVERSCAN_FRAME);
   3276         mVisibleFrame.writeToProto(proto, VISIBLE_FRAME);
   3277         mDecorFrame.writeToProto(proto, DECOR_FRAME);
   3278         mOutsetFrame.writeToProto(proto, OUTSET_FRAME);
   3279         mOverscanInsets.writeToProto(proto, OVERSCAN_INSETS);
   3280         mVisibleInsets.writeToProto(proto, VISIBLE_INSETS);
   3281         mStableInsets.writeToProto(proto, STABLE_INSETS);
   3282         mOutsets.writeToProto(proto, OUTSETS);
   3283         mDisplayCutout.getDisplayCutout().writeToProto(proto, CUTOUT);
   3284         proto.write(REMOVE_ON_EXIT, mRemoveOnExit);
   3285         proto.write(DESTROYING, mDestroying);
   3286         proto.write(REMOVED, mRemoved);
   3287         proto.write(IS_ON_SCREEN, isOnScreen());
   3288         proto.write(IS_VISIBLE, isVisible());
   3289         proto.end(token);
   3290     }
   3291 
   3292     @Override
   3293     public void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
   3294         final long token = proto.start(fieldId);
   3295         proto.write(HASH_CODE, System.identityHashCode(this));
   3296         proto.write(USER_ID, UserHandle.getUserId(mOwnerUid));
   3297         final CharSequence title = getWindowTag();
   3298         if (title != null) {
   3299             proto.write(TITLE, title.toString());
   3300         }
   3301         proto.end(token);
   3302     }
   3303 
   3304     @Override
   3305     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
   3306         final TaskStack stack = getStack();
   3307         pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId());
   3308                 if (stack != null) {
   3309                     pw.print(" stackId="); pw.print(stack.mStackId);
   3310                 }
   3311                 pw.print(" mSession="); pw.print(mSession);
   3312                 pw.print(" mClient="); pw.println(mClient.asBinder());
   3313         pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid);
   3314                 pw.print(" mShowToOwnerOnly="); pw.print(mShowToOwnerOnly);
   3315                 pw.print(" package="); pw.print(mAttrs.packageName);
   3316                 pw.print(" appop="); pw.println(AppOpsManager.opToName(mAppOp));
   3317         pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs.toString(prefix));
   3318         pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
   3319                 pw.print(" h="); pw.print(mRequestedHeight);
   3320                 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
   3321         if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
   3322             pw.print(prefix); pw.print("LastRequested w="); pw.print(mLastRequestedWidth);
   3323                     pw.print(" h="); pw.println(mLastRequestedHeight);
   3324         }
   3325         if (mIsChildWindow || mLayoutAttached) {
   3326             pw.print(prefix); pw.print("mParentWindow="); pw.print(getParentWindow());
   3327                     pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
   3328         }
   3329         if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
   3330             pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
   3331                     pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
   3332                     pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
   3333                     pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
   3334         }
   3335         if (dumpAll) {
   3336             pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
   3337                     pw.print(" mSubLayer="); pw.print(mSubLayer);
   3338                     pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
   3339                     pw.print("="); pw.print(mWinAnimator.mAnimLayer);
   3340                     pw.print(" mLastLayer="); pw.println(mWinAnimator.mLastLayer);
   3341         }
   3342         if (dumpAll) {
   3343             pw.print(prefix); pw.print("mToken="); pw.println(mToken);
   3344             if (mAppToken != null) {
   3345                 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
   3346                 pw.print(prefix); pw.print(" isAnimatingWithSavedSurface()=");
   3347                 pw.print(" mAppDied=");pw.print(mAppDied);
   3348                 pw.print(prefix); pw.print("drawnStateEvaluated=");
   3349                         pw.print(getDrawnStateEvaluated());
   3350                 pw.print(prefix); pw.print("mightAffectAllDrawn=");
   3351                         pw.println(mightAffectAllDrawn());
   3352             }
   3353             pw.print(prefix); pw.print("mViewVisibility=0x");
   3354             pw.print(Integer.toHexString(mViewVisibility));
   3355             pw.print(" mHaveFrame="); pw.print(mHaveFrame);
   3356             pw.print(" mObscured="); pw.println(mObscured);
   3357             pw.print(prefix); pw.print("mSeq="); pw.print(mSeq);
   3358             pw.print(" mSystemUiVisibility=0x");
   3359             pw.println(Integer.toHexString(mSystemUiVisibility));
   3360         }
   3361         if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility
   3362                 || isParentWindowHidden()|| mPermanentlyHidden || mForceHideNonSystemOverlayWindow
   3363                 || mHiddenWhileSuspended) {
   3364             pw.print(prefix); pw.print("mPolicyVisibility=");
   3365                     pw.print(mPolicyVisibility);
   3366                     pw.print(" mPolicyVisibilityAfterAnim=");
   3367                     pw.print(mPolicyVisibilityAfterAnim);
   3368                     pw.print(" mAppOpVisibility=");
   3369                     pw.print(mAppOpVisibility);
   3370                     pw.print(" parentHidden="); pw.print(isParentWindowHidden());
   3371                     pw.print(" mPermanentlyHidden="); pw.print(mPermanentlyHidden);
   3372                     pw.print(" mHiddenWhileSuspended="); pw.print(mHiddenWhileSuspended);
   3373                     pw.print(" mForceHideNonSystemOverlayWindow="); pw.println(
   3374                     mForceHideNonSystemOverlayWindow);
   3375         }
   3376         if (!mRelayoutCalled || mLayoutNeeded) {
   3377             pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled);
   3378                     pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded);
   3379         }
   3380         if (dumpAll) {
   3381             pw.print(prefix); pw.print("mGivenContentInsets=");
   3382                     mGivenContentInsets.printShortString(pw);
   3383                     pw.print(" mGivenVisibleInsets=");
   3384                     mGivenVisibleInsets.printShortString(pw);
   3385                     pw.println();
   3386             if (mTouchableInsets != 0 || mGivenInsetsPending) {
   3387                 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
   3388                         pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
   3389                 Region region = new Region();
   3390                 getTouchableRegion(region);
   3391                 pw.print(prefix); pw.print("touchable region="); pw.println(region);
   3392             }
   3393             pw.print(prefix); pw.print("mFullConfiguration="); pw.println(getConfiguration());
   3394             pw.print(prefix); pw.print("mLastReportedConfiguration=");
   3395                     pw.println(getLastReportedConfiguration());
   3396         }
   3397         pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
   3398                 pw.print(" isReadyForDisplay()="); pw.print(isReadyForDisplay());
   3399                 pw.print(" mWindowRemovalAllowed="); pw.println(mWindowRemovalAllowed);
   3400         if (dumpAll) {
   3401             pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
   3402                     pw.print(" last="); mLastFrame.printShortString(pw);
   3403                     pw.println();
   3404         }
   3405         if (mEnforceSizeCompat) {
   3406             pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
   3407                     pw.println();
   3408         }
   3409         if (dumpAll) {
   3410             pw.print(prefix); pw.print("Frames: containing=");
   3411                     mContainingFrame.printShortString(pw);
   3412                     pw.print(" parent="); mParentFrame.printShortString(pw);
   3413                     pw.println();
   3414             pw.print(prefix); pw.print("    display="); mDisplayFrame.printShortString(pw);
   3415                     pw.print(" overscan="); mOverscanFrame.printShortString(pw);
   3416                     pw.println();
   3417             pw.print(prefix); pw.print("    content="); mContentFrame.printShortString(pw);
   3418                     pw.print(" visible="); mVisibleFrame.printShortString(pw);
   3419                     pw.println();
   3420             pw.print(prefix); pw.print("    decor="); mDecorFrame.printShortString(pw);
   3421                     pw.println();
   3422             pw.print(prefix); pw.print("    outset="); mOutsetFrame.printShortString(pw);
   3423                     pw.println();
   3424             pw.print(prefix); pw.print("Cur insets: overscan=");
   3425                     mOverscanInsets.printShortString(pw);
   3426                     pw.print(" content="); mContentInsets.printShortString(pw);
   3427                     pw.print(" visible="); mVisibleInsets.printShortString(pw);
   3428                     pw.print(" stable="); mStableInsets.printShortString(pw);
   3429                     pw.print(" surface="); mAttrs.surfaceInsets.printShortString(pw);
   3430                     pw.print(" outsets="); mOutsets.printShortString(pw);
   3431             pw.print(" cutout=" + mDisplayCutout.getDisplayCutout());
   3432                     pw.println();
   3433             pw.print(prefix); pw.print("Lst insets: overscan=");
   3434                     mLastOverscanInsets.printShortString(pw);
   3435                     pw.print(" content="); mLastContentInsets.printShortString(pw);
   3436                     pw.print(" visible="); mLastVisibleInsets.printShortString(pw);
   3437                     pw.print(" stable="); mLastStableInsets.printShortString(pw);
   3438                     pw.print(" physical="); mLastOutsets.printShortString(pw);
   3439                     pw.print(" outset="); mLastOutsets.printShortString(pw);
   3440                     pw.print(" cutout=" + mLastDisplayCutout);
   3441                     pw.println();
   3442         }
   3443         super.dump(pw, prefix, dumpAll);
   3444         pw.print(prefix); pw.print(mWinAnimator); pw.println(":");
   3445         mWinAnimator.dump(pw, prefix + "  ", dumpAll);
   3446         if (mAnimatingExit || mRemoveOnExit || mDestroying || mRemoved) {
   3447             pw.print(prefix); pw.print("mAnimatingExit="); pw.print(mAnimatingExit);
   3448                     pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
   3449                     pw.print(" mDestroying="); pw.print(mDestroying);
   3450                     pw.print(" mRemoved="); pw.println(mRemoved);
   3451         }
   3452         if (getOrientationChanging() || mAppFreezing || mReportOrientationChanged) {
   3453             pw.print(prefix); pw.print("mOrientationChanging=");
   3454                     pw.print(mOrientationChanging);
   3455                     pw.print(" configOrientationChanging=");
   3456                     pw.print(getLastReportedConfiguration().orientation
   3457                             != getConfiguration().orientation);
   3458                     pw.print(" mAppFreezing="); pw.print(mAppFreezing);
   3459                     pw.print(" mReportOrientationChanged="); pw.println(mReportOrientationChanged);
   3460         }
   3461         if (mLastFreezeDuration != 0) {
   3462             pw.print(prefix); pw.print("mLastFreezeDuration=");
   3463                     TimeUtils.formatDuration(mLastFreezeDuration, pw); pw.println();
   3464         }
   3465         if (mHScale != 1 || mVScale != 1) {
   3466             pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
   3467                     pw.print(" mVScale="); pw.println(mVScale);
   3468         }
   3469         if (mWallpaperX != -1 || mWallpaperY != -1) {
   3470             pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
   3471                     pw.print(" mWallpaperY="); pw.println(mWallpaperY);
   3472         }
   3473         if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
   3474             pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
   3475                     pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
   3476         }
   3477         if (mWallpaperDisplayOffsetX != Integer.MIN_VALUE
   3478                 || mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
   3479             pw.print(prefix); pw.print("mWallpaperDisplayOffsetX=");
   3480                     pw.print(mWallpaperDisplayOffsetX);
   3481                     pw.print(" mWallpaperDisplayOffsetY=");
   3482                     pw.println(mWallpaperDisplayOffsetY);
   3483         }
   3484         if (mDrawLock != null) {
   3485             pw.print(prefix); pw.println("mDrawLock=" + mDrawLock);
   3486         }
   3487         if (isDragResizing()) {
   3488             pw.print(prefix); pw.println("isDragResizing=" + isDragResizing());
   3489         }
   3490         if (computeDragResizing()) {
   3491             pw.print(prefix); pw.println("computeDragResizing=" + computeDragResizing());
   3492         }
   3493         pw.print(prefix); pw.println("isOnScreen=" + isOnScreen());
   3494         pw.print(prefix); pw.println("isVisible=" + isVisible());
   3495     }
   3496 
   3497     @Override
   3498     String getName() {
   3499         return Integer.toHexString(System.identityHashCode(this))
   3500                 + " " + getWindowTag();
   3501     }
   3502 
   3503     CharSequence getWindowTag() {
   3504         CharSequence tag = mAttrs.getTitle();
   3505         if (tag == null || tag.length() <= 0) {
   3506             tag = mAttrs.packageName;
   3507         }
   3508         return tag;
   3509     }
   3510 
   3511     @Override
   3512     public String toString() {
   3513         final CharSequence title = getWindowTag();
   3514         if (mStringNameCache == null || mLastTitle != title || mWasExiting != mAnimatingExit) {
   3515             mLastTitle = title;
   3516             mWasExiting = mAnimatingExit;
   3517             mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
   3518                     + " u" + UserHandle.getUserId(mOwnerUid)
   3519                     + " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}");
   3520         }
   3521         return mStringNameCache;
   3522     }
   3523 
   3524     void transformClipRectFromScreenToSurfaceSpace(Rect clipRect) {
   3525          if (mHScale >= 0) {
   3526             clipRect.left = (int) (clipRect.left / mHScale);
   3527             clipRect.right = (int) Math.ceil(clipRect.right / mHScale);
   3528         }
   3529         if (mVScale >= 0) {
   3530             clipRect.top = (int) (clipRect.top / mVScale);
   3531             clipRect.bottom = (int) Math.ceil(clipRect.bottom / mVScale);
   3532         }
   3533     }
   3534 
   3535     void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
   3536         final int pw = containingFrame.width();
   3537         final int ph = containingFrame.height();
   3538         final Task task = getTask();
   3539         final boolean inNonFullscreenContainer = !inFullscreenContainer();
   3540         final boolean noLimits = (mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;
   3541 
   3542         // We need to fit it to the display if either
   3543         // a) The window is in a fullscreen container, or we don't have a task (we assume fullscreen
   3544         // for the taskless windows)
   3545         // b) If it's a secondary app window, we also need to fit it to the display unless
   3546         // FLAG_LAYOUT_NO_LIMITS is set. This is so we place Popups, dialogs, and similar windows on
   3547         // screen, but SurfaceViews want to be always at a specific location so we don't fit it to
   3548         // the display.
   3549         final boolean fitToDisplay = (task == null || !inNonFullscreenContainer)
   3550                 || ((mAttrs.type != TYPE_BASE_APPLICATION) && !noLimits);
   3551         float x, y;
   3552         int w,h;
   3553 
   3554         if ((mAttrs.flags & FLAG_SCALED) != 0) {
   3555             if (mAttrs.width < 0) {
   3556                 w = pw;
   3557             } else if (mEnforceSizeCompat) {
   3558                 w = (int)(mAttrs.width * mGlobalScale + .5f);
   3559             } else {
   3560                 w = mAttrs.width;
   3561             }
   3562             if (mAttrs.height < 0) {
   3563                 h = ph;
   3564             } else if (mEnforceSizeCompat) {
   3565                 h = (int)(mAttrs.height * mGlobalScale + .5f);
   3566             } else {
   3567                 h = mAttrs.height;
   3568             }
   3569         } else {
   3570             if (mAttrs.width == MATCH_PARENT) {
   3571                 w = pw;
   3572             } else if (mEnforceSizeCompat) {
   3573                 w = (int)(mRequestedWidth * mGlobalScale + .5f);
   3574             } else {
   3575                 w = mRequestedWidth;
   3576             }
   3577             if (mAttrs.height == MATCH_PARENT) {
   3578                 h = ph;
   3579             } else if (mEnforceSizeCompat) {
   3580                 h = (int)(mRequestedHeight * mGlobalScale + .5f);
   3581             } else {
   3582                 h = mRequestedHeight;
   3583             }
   3584         }
   3585 
   3586         if (mEnforceSizeCompat) {
   3587             x = mAttrs.x * mGlobalScale;
   3588             y = mAttrs.y * mGlobalScale;
   3589         } else {
   3590             x = mAttrs.x;
   3591             y = mAttrs.y;
   3592         }
   3593 
   3594         if (inNonFullscreenContainer && !layoutInParentFrame()) {
   3595             // Make sure window fits in containing frame since it is in a non-fullscreen task as
   3596             // required by {@link Gravity#apply} call.
   3597             w = Math.min(w, pw);
   3598             h = Math.min(h, ph);
   3599         }
   3600 
   3601         // Set mFrame
   3602         Gravity.apply(mAttrs.gravity, w, h, containingFrame,
   3603                 (int) (x + mAttrs.horizontalMargin * pw),
   3604                 (int) (y + mAttrs.verticalMargin * ph), mFrame);
   3605 
   3606         // Now make sure the window fits in the overall display frame.
   3607         if (fitToDisplay) {
   3608             Gravity.applyDisplay(mAttrs.gravity, displayFrame, mFrame);
   3609         }
   3610 
   3611         // We need to make sure we update the CompatFrame as it is used for
   3612         // cropping decisions, etc, on systems where we lack a decor layer.
   3613         mCompatFrame.set(mFrame);
   3614         if (mEnforceSizeCompat) {
   3615             // See comparable block in computeFrameLw.
   3616             mCompatFrame.scale(mInvGlobalScale);
   3617         }
   3618     }
   3619 
   3620     boolean isChildWindow() {
   3621         return mIsChildWindow;
   3622     }
   3623 
   3624     boolean layoutInParentFrame() {
   3625         return mIsChildWindow
   3626                 && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
   3627     }
   3628 
   3629     /**
   3630      * Returns true if any window added by an application process that if of type
   3631      * {@link android.view.WindowManager.LayoutParams#TYPE_TOAST} or that requires that requires
   3632      * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when
   3633      * this window is visible.
   3634      */
   3635     boolean hideNonSystemOverlayWindowsWhenVisible() {
   3636         return (mAttrs.privateFlags & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0
   3637                 && mSession.mCanHideNonSystemOverlayWindows;
   3638     }
   3639 
   3640     /** Returns the parent window if this is a child of another window, else null. */
   3641     WindowState getParentWindow() {
   3642         // NOTE: We are not calling getParent() directly as the WindowState might be a child of a
   3643         // WindowContainer that isn't a WindowState.
   3644         return (mIsChildWindow) ? ((WindowState) super.getParent()) : null;
   3645     }
   3646 
   3647     /** Returns the topmost parent window if this is a child of another window, else this. */
   3648     WindowState getTopParentWindow() {
   3649         WindowState current = this;
   3650         WindowState topParent = current;
   3651         while (current != null && current.mIsChildWindow) {
   3652             current = current.getParentWindow();
   3653             // Parent window can be null if the child is detached from it's parent already, but
   3654             // someone still has a reference to access it. So, we return the top parent value we
   3655             // already have instead of null.
   3656             if (current != null) {
   3657                 topParent = current;
   3658             }
   3659         }
   3660         return topParent;
   3661     }
   3662 
   3663     boolean isParentWindowHidden() {
   3664         final WindowState parent = getParentWindow();
   3665         return parent != null && parent.mHidden;
   3666     }
   3667 
   3668     void setWillReplaceWindow(boolean animate) {
   3669         for (int i = mChildren.size() - 1; i >= 0; i--) {
   3670             final WindowState c = mChildren.get(i);
   3671             c.setWillReplaceWindow(animate);
   3672         }
   3673 
   3674         if ((mAttrs.privateFlags & PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH) != 0
   3675                 || mAttrs.type == TYPE_APPLICATION_STARTING) {
   3676             // We don't set replacing on starting windows since they are added by window manager and
   3677             // not the client so won't be replaced by the client.
   3678             return;
   3679         }
   3680 
   3681         mWillReplaceWindow = true;
   3682         mReplacementWindow = null;
   3683         mAnimateReplacingWindow = animate;
   3684     }
   3685 
   3686     void clearWillReplaceWindow() {
   3687         mWillReplaceWindow = false;
   3688         mReplacementWindow = null;
   3689         mAnimateReplacingWindow = false;
   3690 
   3691         for (int i = mChildren.size() - 1; i >= 0; i--) {
   3692             final WindowState c = mChildren.get(i);
   3693             c.clearWillReplaceWindow();
   3694         }
   3695     }
   3696 
   3697     boolean waitingForReplacement() {
   3698         if (mWillReplaceWindow) {
   3699             return true;
   3700         }
   3701 
   3702         for (int i = mChildren.size() - 1; i >= 0; i--) {
   3703             final WindowState c = mChildren.get(i);
   3704             if (c.waitingForReplacement()) {
   3705                 return true;
   3706             }
   3707         }
   3708         return false;
   3709     }
   3710 
   3711     void requestUpdateWallpaperIfNeeded() {
   3712         final DisplayContent dc = getDisplayContent();
   3713         if (dc != null && (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
   3714             dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   3715             dc.setLayoutNeeded();
   3716             mService.mWindowPlacerLocked.requestTraversal();
   3717         }
   3718 
   3719         for (int i = mChildren.size() - 1; i >= 0; i--) {
   3720             final WindowState c = mChildren.get(i);
   3721             c.requestUpdateWallpaperIfNeeded();
   3722         }
   3723     }
   3724 
   3725     float translateToWindowX(float x) {
   3726         float winX = x - mFrame.left;
   3727         if (mEnforceSizeCompat) {
   3728             winX *= mGlobalScale;
   3729         }
   3730         return winX;
   3731     }
   3732 
   3733     float translateToWindowY(float y) {
   3734         float winY = y - mFrame.top;
   3735         if (mEnforceSizeCompat) {
   3736             winY *= mGlobalScale;
   3737         }
   3738         return winY;
   3739     }
   3740 
   3741     // During activity relaunch due to resize, we sometimes use window replacement
   3742     // for only child windows (as the main window is handled by window preservation)
   3743     // and the big surface.
   3744     //
   3745     // Though windows of TYPE_APPLICATION or TYPE_DRAWN_APPLICATION (as opposed to
   3746     // TYPE_BASE_APPLICATION) are not children in the sense of an attached window,
   3747     // we also want to replace them at such phases, as they won't be covered by window
   3748     // preservation, and in general we expect them to return following relaunch.
   3749     boolean shouldBeReplacedWithChildren() {
   3750         return mIsChildWindow || mAttrs.type == TYPE_APPLICATION
   3751                 || mAttrs.type == TYPE_DRAWN_APPLICATION;
   3752     }
   3753 
   3754     void setWillReplaceChildWindows() {
   3755         if (shouldBeReplacedWithChildren()) {
   3756             setWillReplaceWindow(false /* animate */);
   3757         }
   3758         for (int i = mChildren.size() - 1; i >= 0; i--) {
   3759             final WindowState c = mChildren.get(i);
   3760             c.setWillReplaceChildWindows();
   3761         }
   3762     }
   3763 
   3764     WindowState getReplacingWindow() {
   3765         if (mAnimatingExit && mWillReplaceWindow && mAnimateReplacingWindow) {
   3766             return this;
   3767         }
   3768         for (int i = mChildren.size() - 1; i >= 0; i--) {
   3769             final WindowState c = mChildren.get(i);
   3770             final WindowState replacing = c.getReplacingWindow();
   3771             if (replacing != null) {
   3772                 return replacing;
   3773             }
   3774         }
   3775         return null;
   3776     }
   3777 
   3778     @Override
   3779     public int getRotationAnimationHint() {
   3780         if (mAppToken != null) {
   3781             return mAppToken.mRotationAnimationHint;
   3782         } else {
   3783             return -1;
   3784         }
   3785     }
   3786 
   3787     @Override
   3788     public boolean isInputMethodWindow() {
   3789         return mIsImWindow;
   3790     }
   3791 
   3792     // This must be called while inside a transaction.
   3793     boolean performShowLocked() {
   3794         if (isHiddenFromUserLocked()) {
   3795             if (DEBUG_VISIBILITY) Slog.w(TAG, "hiding " + this + ", belonging to " + mOwnerUid);
   3796             hideLw(false);
   3797             return false;
   3798         }
   3799 
   3800         logPerformShow("performShow on ");
   3801 
   3802         final int drawState = mWinAnimator.mDrawState;
   3803         if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW)
   3804                 && mAttrs.type != TYPE_APPLICATION_STARTING && mAppToken != null) {
   3805             mAppToken.onFirstWindowDrawn(this, mWinAnimator);
   3806         }
   3807 
   3808         if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
   3809             return false;
   3810         }
   3811 
   3812         logPerformShow("Showing ");
   3813 
   3814         mService.enableScreenIfNeededLocked();
   3815         mWinAnimator.applyEnterAnimationLocked();
   3816 
   3817         // Force the show in the next prepareSurfaceLocked() call.
   3818         mWinAnimator.mLastAlpha = -1;
   3819         if (DEBUG_ANIM) Slog.v(TAG,
   3820                 "performShowLocked: mDrawState=HAS_DRAWN in " + this);
   3821         mWinAnimator.mDrawState = HAS_DRAWN;
   3822         mService.scheduleAnimationLocked();
   3823 
   3824         if (mHidden) {
   3825             mHidden = false;
   3826             final DisplayContent displayContent = getDisplayContent();
   3827 
   3828             for (int i = mChildren.size() - 1; i >= 0; --i) {
   3829                 final WindowState c = mChildren.get(i);
   3830                 if (c.mWinAnimator.mSurfaceController != null) {
   3831                     c.performShowLocked();
   3832                     // It hadn't been shown, which means layout not performed on it, so now we
   3833                     // want to make sure to do a layout.  If called from within the transaction
   3834                     // loop, this will cause it to restart with a new layout.
   3835                     if (displayContent != null) {
   3836                         displayContent.setLayoutNeeded();
   3837                     }
   3838                 }
   3839             }
   3840         }
   3841 
   3842         if (mAttrs.type == TYPE_INPUT_METHOD) {
   3843             getDisplayContent().mDividerControllerLocked.resetImeHideRequested();
   3844         }
   3845 
   3846         return true;
   3847     }
   3848 
   3849     private void logPerformShow(String prefix) {
   3850         if (DEBUG_VISIBILITY
   3851                 || (DEBUG_STARTING_WINDOW_VERBOSE && mAttrs.type == TYPE_APPLICATION_STARTING)) {
   3852             Slog.v(TAG, prefix + this
   3853                     + ": mDrawState=" + mWinAnimator.drawStateToString()
   3854                     + " readyForDisplay=" + isReadyForDisplay()
   3855                     + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING)
   3856                     + " during animation: policyVis=" + mPolicyVisibility
   3857                     + " parentHidden=" + isParentWindowHidden()
   3858                     + " tok.hiddenRequested="
   3859                     + (mAppToken != null && mAppToken.hiddenRequested)
   3860                     + " tok.hidden=" + (mAppToken != null && mAppToken.isHidden())
   3861                     + " animationSet=" + mWinAnimator.isAnimationSet()
   3862                     + " tok animating="
   3863                     + (mAppToken != null && mAppToken.isSelfAnimating())
   3864                     + " Callers=" + Debug.getCallers(4));
   3865         }
   3866     }
   3867 
   3868     WindowInfo getWindowInfo() {
   3869         WindowInfo windowInfo = WindowInfo.obtain();
   3870         windowInfo.type = mAttrs.type;
   3871         windowInfo.layer = mLayer;
   3872         windowInfo.token = mClient.asBinder();
   3873         if (mAppToken != null) {
   3874             windowInfo.activityToken = mAppToken.appToken.asBinder();
   3875         }
   3876         windowInfo.title = mAttrs.accessibilityTitle;
   3877         // Panel windows have no public way to set the a11y title directly. Use the
   3878         // regular title as a fallback.
   3879         final boolean isPanelWindow = (mAttrs.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW)
   3880                 && (mAttrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW);
   3881         // Accessibility overlays should have titles that work for accessibility, and can't set
   3882         // the a11y title themselves.
   3883         final boolean isAccessibilityOverlay =
   3884                 windowInfo.type == WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
   3885         if (TextUtils.isEmpty(windowInfo.title) && (isPanelWindow || isAccessibilityOverlay)) {
   3886             windowInfo.title = mAttrs.getTitle();
   3887         }
   3888         windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor;
   3889         windowInfo.focused = isFocused();
   3890         Task task = getTask();
   3891         windowInfo.inPictureInPicture = (task != null) && task.inPinnedWindowingMode();
   3892 
   3893         if (mIsChildWindow) {
   3894             windowInfo.parentToken = getParentWindow().mClient.asBinder();
   3895         }
   3896 
   3897         final int childCount = mChildren.size();
   3898         if (childCount > 0) {
   3899             if (windowInfo.childTokens == null) {
   3900                 windowInfo.childTokens = new ArrayList(childCount);
   3901             }
   3902             for (int j = 0; j < childCount; j++) {
   3903                 final WindowState child = mChildren.get(j);
   3904                 windowInfo.childTokens.add(child.mClient.asBinder());
   3905             }
   3906         }
   3907         return windowInfo;
   3908     }
   3909 
   3910     int getHighestAnimLayer() {
   3911         int highest = mWinAnimator.mAnimLayer;
   3912         for (int i = mChildren.size() - 1; i >= 0; i--) {
   3913             final WindowState c = mChildren.get(i);
   3914             final int childLayer = c.getHighestAnimLayer();
   3915             if (childLayer > highest) {
   3916                 highest = childLayer;
   3917             }
   3918         }
   3919         return highest;
   3920     }
   3921 
   3922     @Override
   3923     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
   3924         if (mChildren.isEmpty()) {
   3925             // The window has no children so we just return it.
   3926             return applyInOrderWithImeWindows(callback, traverseTopToBottom);
   3927         }
   3928 
   3929         if (traverseTopToBottom) {
   3930             return forAllWindowTopToBottom(callback);
   3931         } else {
   3932             return forAllWindowBottomToTop(callback);
   3933         }
   3934     }
   3935 
   3936     private boolean forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback) {
   3937         // We want to consume the negative sublayer children first because they need to appear
   3938         // below the parent, then this window (the parent), and then the positive sublayer children
   3939         // because they need to appear above the parent.
   3940         int i = 0;
   3941         final int count = mChildren.size();
   3942         WindowState child = mChildren.get(i);
   3943 
   3944         while (i < count && child.mSubLayer < 0) {
   3945             if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
   3946                 return true;
   3947             }
   3948             i++;
   3949             if (i >= count) {
   3950                 break;
   3951             }
   3952             child = mChildren.get(i);
   3953         }
   3954 
   3955         if (applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
   3956             return true;
   3957         }
   3958 
   3959         while (i < count) {
   3960             if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
   3961                 return true;
   3962             }
   3963             i++;
   3964             if (i >= count) {
   3965                 break;
   3966             }
   3967             child = mChildren.get(i);
   3968         }
   3969 
   3970         return false;
   3971     }
   3972 
   3973     private boolean forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback) {
   3974         // We want to consume the positive sublayer children first because they need to appear
   3975         // above the parent, then this window (the parent), and then the negative sublayer children
   3976         // because they need to appear above the parent.
   3977         int i = mChildren.size() - 1;
   3978         WindowState child = mChildren.get(i);
   3979 
   3980         while (i >= 0 && child.mSubLayer >= 0) {
   3981             if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
   3982                 return true;
   3983             }
   3984             --i;
   3985             if (i < 0) {
   3986                 break;
   3987             }
   3988             child = mChildren.get(i);
   3989         }
   3990 
   3991         if (applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
   3992             return true;
   3993         }
   3994 
   3995         while (i >= 0) {
   3996             if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
   3997                 return true;
   3998             }
   3999             --i;
   4000             if (i < 0) {
   4001                 break;
   4002             }
   4003             child = mChildren.get(i);
   4004         }
   4005 
   4006         return false;
   4007     }
   4008 
   4009     private boolean applyImeWindowsIfNeeded(ToBooleanFunction<WindowState> callback,
   4010             boolean traverseTopToBottom) {
   4011         // If this window is the current IME target, so we need to process the IME windows
   4012         // directly above it. The exception is if we are in split screen
   4013         // in which case we process the IME at the DisplayContent level to
   4014         // ensure it is above the docked divider.
   4015         if (isInputMethodTarget() && !inSplitScreenWindowingMode()) {
   4016             if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
   4017                 return true;
   4018             }
   4019         }
   4020         return false;
   4021     }
   4022 
   4023     private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback,
   4024             boolean traverseTopToBottom) {
   4025         if (traverseTopToBottom) {
   4026             if (applyImeWindowsIfNeeded(callback, traverseTopToBottom)
   4027                     || callback.apply(this)) {
   4028                 return true;
   4029             }
   4030         } else {
   4031             if (callback.apply(this)
   4032                     || applyImeWindowsIfNeeded(callback, traverseTopToBottom)) {
   4033                 return true;
   4034             }
   4035         }
   4036         return false;
   4037     }
   4038 
   4039     WindowState getWindow(Predicate<WindowState> callback) {
   4040         if (mChildren.isEmpty()) {
   4041             return callback.test(this) ? this : null;
   4042         }
   4043 
   4044         // We want to consume the positive sublayer children first because they need to appear
   4045         // above the parent, then this window (the parent), and then the negative sublayer children
   4046         // because they need to appear above the parent.
   4047         int i = mChildren.size() - 1;
   4048         WindowState child = mChildren.get(i);
   4049 
   4050         while (i >= 0 && child.mSubLayer >= 0) {
   4051             if (callback.test(child)) {
   4052                 return child;
   4053             }
   4054             --i;
   4055             if (i < 0) {
   4056                 break;
   4057             }
   4058             child = mChildren.get(i);
   4059         }
   4060 
   4061         if (callback.test(this)) {
   4062             return this;
   4063         }
   4064 
   4065         while (i >= 0) {
   4066             if (callback.test(child)) {
   4067                 return child;
   4068             }
   4069             --i;
   4070             if (i < 0) {
   4071                 break;
   4072             }
   4073             child = mChildren.get(i);
   4074         }
   4075 
   4076         return null;
   4077     }
   4078 
   4079     /**
   4080      * @return True if we our one of our ancestors has {@link #mAnimatingExit} set to true, false
   4081      *         otherwise.
   4082      */
   4083     @VisibleForTesting
   4084     boolean isSelfOrAncestorWindowAnimatingExit() {
   4085         WindowState window = this;
   4086         do {
   4087             if (window.mAnimatingExit) {
   4088                 return true;
   4089             }
   4090             window = window.getParentWindow();
   4091         } while (window != null);
   4092         return false;
   4093     }
   4094 
   4095     void onExitAnimationDone() {
   4096         if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this
   4097                 + ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit
   4098                 + " selfAnimating=" + isSelfAnimating());
   4099 
   4100         if (!mChildren.isEmpty()) {
   4101             // Copying to a different list as multiple children can be removed.
   4102             final ArrayList<WindowState> childWindows = new ArrayList<>(mChildren);
   4103             for (int i = childWindows.size() - 1; i >= 0; i--) {
   4104                 childWindows.get(i).onExitAnimationDone();
   4105             }
   4106         }
   4107 
   4108         if (mWinAnimator.mEnteringAnimation) {
   4109             mWinAnimator.mEnteringAnimation = false;
   4110             mService.requestTraversal();
   4111             // System windows don't have an activity and an app token as a result, but need a way
   4112             // to be informed about their entrance animation end.
   4113             if (mAppToken == null) {
   4114                 try {
   4115                     mClient.dispatchWindowShown();
   4116                 } catch (RemoteException e) {
   4117                 }
   4118             }
   4119         }
   4120 
   4121         if (isSelfAnimating()) {
   4122             return;
   4123         }
   4124 
   4125         //TODO (multidisplay): Accessibility is supported only for the default display.
   4126         if (mService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
   4127             mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
   4128         }
   4129 
   4130         if (!isSelfOrAncestorWindowAnimatingExit()) {
   4131             return;
   4132         }
   4133 
   4134         if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG,
   4135                 "Exit animation finished in " + this + ": remove=" + mRemoveOnExit);
   4136 
   4137         mDestroying = true;
   4138 
   4139         final boolean hasSurface = mWinAnimator.hasSurface();
   4140 
   4141         // Use pendingTransaction here so hide is done the same transaction as the other
   4142         // animations when exiting
   4143         mWinAnimator.hide(getPendingTransaction(), "onExitAnimationDone");
   4144 
   4145         // If we have an app token, we ask it to destroy the surface for us, so that it can take
   4146         // care to ensure the activity has actually stopped and the surface is not still in use.
   4147         // Otherwise we add the service to mDestroySurface and allow it to be processed in our next
   4148         // transaction.
   4149         if (mAppToken != null) {
   4150             mAppToken.destroySurfaces();
   4151         } else {
   4152             if (hasSurface) {
   4153                 mService.mDestroySurface.add(this);
   4154             }
   4155             if (mRemoveOnExit) {
   4156                 mService.mPendingRemove.add(this);
   4157                 mRemoveOnExit = false;
   4158             }
   4159         }
   4160         mAnimatingExit = false;
   4161         getDisplayContent().mWallpaperController.hideWallpapers(this);
   4162     }
   4163 
   4164     boolean clearAnimatingFlags() {
   4165         boolean didSomething = false;
   4166         // We don't want to clear it out for windows that get replaced, because the
   4167         // animation depends on the flag to remove the replaced window.
   4168         //
   4169         // We also don't clear the mAnimatingExit flag for windows which have the
   4170         // mRemoveOnExit flag. This indicates an explicit remove request has been issued
   4171         // by the client. We should let animation proceed and not clear this flag or
   4172         // they won't eventually be removed by WindowStateAnimator#finishExit.
   4173         if (!mWillReplaceWindow && !mRemoveOnExit) {
   4174             // Clear mAnimating flag together with mAnimatingExit. When animation
   4175             // changes from exiting to entering, we need to clear this flag until the
   4176             // new animation gets applied, so that isAnimationStarting() becomes true
   4177             // until then.
   4178             // Otherwise applySurfaceChangesTransaction will fail to skip surface
   4179             // placement for this window during this period, one or more frame will
   4180             // show up with wrong position or scale.
   4181             if (mAnimatingExit) {
   4182                 mAnimatingExit = false;
   4183                 didSomething = true;
   4184             }
   4185             if (mDestroying) {
   4186                 mDestroying = false;
   4187                 mService.mDestroySurface.remove(this);
   4188                 didSomething = true;
   4189             }
   4190         }
   4191 
   4192         for (int i = mChildren.size() - 1; i >= 0; --i) {
   4193             didSomething |= (mChildren.get(i)).clearAnimatingFlags();
   4194         }
   4195 
   4196         return didSomething;
   4197     }
   4198 
   4199     public boolean isRtl() {
   4200         return getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
   4201     }
   4202 
   4203     void hideWallpaperWindow(boolean wasDeferred, String reason) {
   4204         for (int j = mChildren.size() - 1; j >= 0; --j) {
   4205             final WindowState c = mChildren.get(j);
   4206             c.hideWallpaperWindow(wasDeferred, reason);
   4207         }
   4208         if (!mWinAnimator.mLastHidden || wasDeferred) {
   4209             mWinAnimator.hide(reason);
   4210             dispatchWallpaperVisibility(false);
   4211             final DisplayContent displayContent = getDisplayContent();
   4212             if (displayContent != null) {
   4213                 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
   4214             }
   4215         }
   4216     }
   4217 
   4218     /**
   4219      * Check wallpaper window for visibility change and notify window if so.
   4220      * @param visible Current visibility.
   4221      */
   4222     void dispatchWallpaperVisibility(final boolean visible) {
   4223         final boolean hideAllowed =
   4224                 getDisplayContent().mWallpaperController.mDeferredHideWallpaper == null;
   4225 
   4226         // Only send notification if the visibility actually changed and we are not trying to hide
   4227         // the wallpaper when we are deferring hiding of the wallpaper.
   4228         if (mWallpaperVisible != visible && (hideAllowed || visible)) {
   4229             mWallpaperVisible = visible;
   4230             try {
   4231                 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
   4232                         "Updating vis of wallpaper " + this
   4233                                 + ": " + visible + " from:\n" + Debug.getCallers(4, "  "));
   4234                 mClient.dispatchAppVisibility(visible);
   4235             } catch (RemoteException e) {
   4236             }
   4237         }
   4238     }
   4239 
   4240     boolean hasVisibleNotDrawnWallpaper() {
   4241         if (mWallpaperVisible && !isDrawnLw()) {
   4242             return true;
   4243         }
   4244         for (int j = mChildren.size() - 1; j >= 0; --j) {
   4245             final WindowState c = mChildren.get(j);
   4246             if (c.hasVisibleNotDrawnWallpaper()) {
   4247                 return true;
   4248             }
   4249         }
   4250         return false;
   4251     }
   4252 
   4253     void updateReportedVisibility(UpdateReportedVisibilityResults results) {
   4254         for (int i = mChildren.size() - 1; i >= 0; --i) {
   4255             final WindowState c = mChildren.get(i);
   4256             c.updateReportedVisibility(results);
   4257         }
   4258 
   4259         if (mAppFreezing || mViewVisibility != View.VISIBLE
   4260                 || mAttrs.type == TYPE_APPLICATION_STARTING
   4261                 || mDestroying) {
   4262             return;
   4263         }
   4264         if (DEBUG_VISIBILITY) {
   4265             Slog.v(TAG, "Win " + this + ": isDrawn=" + isDrawnLw()
   4266                     + ", isAnimationSet=" + mWinAnimator.isAnimationSet());
   4267             if (!isDrawnLw()) {
   4268                 Slog.v(TAG, "Not displayed: s=" + mWinAnimator.mSurfaceController
   4269                         + " pv=" + mPolicyVisibility
   4270                         + " mDrawState=" + mWinAnimator.mDrawState
   4271                         + " ph=" + isParentWindowHidden()
   4272                         + " th=" + (mAppToken != null ? mAppToken.hiddenRequested : false)
   4273                         + " a=" + mWinAnimator.isAnimationSet());
   4274             }
   4275         }
   4276 
   4277         results.numInteresting++;
   4278         if (isDrawnLw()) {
   4279             results.numDrawn++;
   4280             if (!mWinAnimator.isAnimationSet()) {
   4281                 results.numVisible++;
   4282             }
   4283             results.nowGone = false;
   4284         } else if (mWinAnimator.isAnimationSet()) {
   4285             results.nowGone = false;
   4286         }
   4287     }
   4288 
   4289     private boolean skipDecorCrop() {
   4290         // The decor frame is used to specify the region not covered by the system
   4291         // decorations (nav bar, status bar). In case this is empty, for example with
   4292         // FLAG_TRANSLUCENT_NAVIGATION, we don't need to do any cropping.
   4293         if (mDecorFrame.isEmpty()) {
   4294             return true;
   4295         }
   4296 
   4297         // But if we have a frame, and are an application window, then we must be cropped.
   4298         if (mAppToken != null) {
   4299             return false;
   4300         }
   4301 
   4302         // For non application windows, we may be allowed to extend over the decor bars
   4303         // depending on our type and permissions assosciated with our token.
   4304         return mToken.canLayerAboveSystemBars();
   4305     }
   4306 
   4307     /**
   4308      * Calculate the window crop according to system decor policy. In general this is
   4309      * the system decor rect (see #calculateSystemDecorRect), but we also have some
   4310      * special cases. This rectangle is in screen space.
   4311      */
   4312     void calculatePolicyCrop(Rect policyCrop) {
   4313         final DisplayContent displayContent = getDisplayContent();
   4314         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   4315 
   4316         if (!isDefaultDisplay()) {
   4317             // On a different display there is no system decor. Crop the window
   4318             // by the screen boundaries.
   4319             // TODO(multi-display)
   4320             policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
   4321             policyCrop.intersect(-mCompatFrame.left, -mCompatFrame.top,
   4322                     displayInfo.logicalWidth - mCompatFrame.left,
   4323                     displayInfo.logicalHeight - mCompatFrame.top);
   4324         } else if (skipDecorCrop()) {
   4325             // Windows without policy decor aren't cropped.
   4326             policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
   4327         } else {
   4328             // Crop to the system decor specified by policy.
   4329             calculateSystemDecorRect(policyCrop);
   4330         }
   4331     }
   4332 
   4333     /**
   4334      * The system decor rect is the region of the window which is not covered
   4335      * by system decorations.
   4336      */
   4337     private void calculateSystemDecorRect(Rect systemDecorRect) {
   4338         final Rect decorRect = mDecorFrame;
   4339         final int width = mFrame.width();
   4340         final int height = mFrame.height();
   4341 
   4342         final int left = mFrame.left;
   4343         final int top = mFrame.top;
   4344 
   4345         // Initialize the decor rect to the entire frame.
   4346         if (isDockedResizing()) {
   4347             // If we are resizing with the divider, the task bounds might be smaller than the
   4348             // stack bounds. The system decor is used to clip to the task bounds, which we don't
   4349             // want in this case in order to avoid holes.
   4350             //
   4351             // We take care to not shrink the width, for surfaces which are larger than
   4352             // the display region. Of course this area will not eventually be visible
   4353             // but if we truncate the width now, we will calculate incorrectly
   4354             // when adjusting to the stack bounds.
   4355             final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
   4356             systemDecorRect.set(0, 0,
   4357                     Math.max(width, displayInfo.logicalWidth),
   4358                     Math.max(height, displayInfo.logicalHeight));
   4359         } else {
   4360             systemDecorRect.set(0, 0, width, height);
   4361         }
   4362 
   4363         // If a freeform window is animating from a position where it would be cutoff, it would be
   4364         // cutoff during the animation. We don't want that, so for the duration of the animation
   4365         // we ignore the decor cropping and depend on layering to position windows correctly.
   4366 
   4367         // We also ignore cropping when the window is currently being drag resized in split screen
   4368         // to prevent issues with the crop for screenshot.
   4369         final boolean cropToDecor =
   4370                 !(inFreeformWindowingMode() && isAnimatingLw()) && !isDockedResizing();
   4371         if (cropToDecor) {
   4372             // Intersect with the decor rect, offsetted by window position.
   4373             systemDecorRect.intersect(decorRect.left - left, decorRect.top - top,
   4374                     decorRect.right - left, decorRect.bottom - top);
   4375         }
   4376 
   4377         // If size compatibility is being applied to the window, the
   4378         // surface is scaled relative to the screen.  Also apply this
   4379         // scaling to the crop rect.  We aren't using the standard rect
   4380         // scale function because we want to round things to make the crop
   4381         // always round to a larger rect to ensure we don't crop too
   4382         // much and hide part of the window that should be seen.
   4383         if (mEnforceSizeCompat && mInvGlobalScale != 1.0f) {
   4384             final float scale = mInvGlobalScale;
   4385             systemDecorRect.left = (int) (systemDecorRect.left * scale - 0.5f);
   4386             systemDecorRect.top = (int) (systemDecorRect.top * scale - 0.5f);
   4387             systemDecorRect.right = (int) ((systemDecorRect.right + 1) * scale - 0.5f);
   4388             systemDecorRect.bottom = (int) ((systemDecorRect.bottom + 1) * scale - 0.5f);
   4389         }
   4390 
   4391     }
   4392 
   4393     /**
   4394      * Expand the given rectangle by this windows surface insets. This
   4395      * takes you from the 'window size' to the 'surface size'.
   4396      * The surface insets are positive in each direction, so we inset by
   4397      * the inverse.
   4398      */
   4399     void expandForSurfaceInsets(Rect r) {
   4400         r.inset(-mAttrs.surfaceInsets.left,
   4401                 -mAttrs.surfaceInsets.top,
   4402                 -mAttrs.surfaceInsets.right,
   4403                 -mAttrs.surfaceInsets.bottom);
   4404     }
   4405 
   4406     boolean surfaceInsetsChanging() {
   4407         return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets);
   4408     }
   4409 
   4410     int relayoutVisibleWindow(int result, int attrChanges, int oldVisibility) {
   4411         final boolean wasVisible = isVisibleLw();
   4412 
   4413         result |= (!wasVisible || !isDrawnLw()) ? RELAYOUT_RES_FIRST_TIME : 0;
   4414 
   4415         if (mAnimatingExit) {
   4416             Slog.d(TAG, "relayoutVisibleWindow: " + this + " mAnimatingExit=true, mRemoveOnExit="
   4417                     + mRemoveOnExit + ", mDestroying=" + mDestroying);
   4418 
   4419             mWinAnimator.cancelExitAnimationForNextAnimationLocked();
   4420             mAnimatingExit = false;
   4421         }
   4422         if (mDestroying) {
   4423             mDestroying = false;
   4424             mService.mDestroySurface.remove(this);
   4425         }
   4426         if (oldVisibility == View.GONE) {
   4427             mWinAnimator.mEnterAnimationPending = true;
   4428         }
   4429 
   4430         mLastVisibleLayoutRotation = getDisplayContent().getRotation();
   4431 
   4432         mWinAnimator.mEnteringAnimation = true;
   4433 
   4434         prepareWindowToDisplayDuringRelayout(wasVisible);
   4435 
   4436         if ((attrChanges & FORMAT_CHANGED) != 0) {
   4437             // If the format can't be changed in place, preserve the old surface until the app draws
   4438             // on the new one. This prevents blinking when we change elevation of freeform and
   4439             // pinned windows.
   4440             if (!mWinAnimator.tryChangeFormatInPlaceLocked()) {
   4441                 mWinAnimator.preserveSurfaceLocked();
   4442                 result |= RELAYOUT_RES_SURFACE_CHANGED
   4443                         | RELAYOUT_RES_FIRST_TIME;
   4444             }
   4445         }
   4446 
   4447         // When we change the Surface size, in scenarios which may require changing
   4448         // the surface position in sync with the resize, we use a preserved surface
   4449         // so we can freeze it while waiting for the client to report draw on the newly
   4450         // sized surface. At the moment this logic is only in place for switching
   4451         // in and out of the big surface for split screen resize.
   4452         if (isDragResizeChanged()) {
   4453             setDragResizing();
   4454             // We can only change top level windows to the full-screen surface when
   4455             // resizing (as we only have one full-screen surface). So there is no need
   4456             // to preserve and destroy windows which are attached to another, they
   4457             // will keep their surface and its size may change over time.
   4458             if (mHasSurface && !isChildWindow()) {
   4459                 mWinAnimator.preserveSurfaceLocked();
   4460                 result |= RELAYOUT_RES_SURFACE_CHANGED |
   4461                     RELAYOUT_RES_FIRST_TIME;
   4462             }
   4463         }
   4464         final boolean freeformResizing = isDragResizing()
   4465                 && getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
   4466         final boolean dockedResizing = isDragResizing()
   4467                 && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER;
   4468         result |= freeformResizing ? RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0;
   4469         result |= dockedResizing ? RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0;
   4470         return result;
   4471     }
   4472 
   4473     /**
   4474      * @return True if this window has been laid out at least once; false otherwise.
   4475      */
   4476     boolean isLaidOut() {
   4477         return mLayoutSeq != -1;
   4478     }
   4479 
   4480     /**
   4481      * Updates the last inset values to the current ones.
   4482      */
   4483     void updateLastInsetValues() {
   4484         mLastOverscanInsets.set(mOverscanInsets);
   4485         mLastContentInsets.set(mContentInsets);
   4486         mLastVisibleInsets.set(mVisibleInsets);
   4487         mLastStableInsets.set(mStableInsets);
   4488         mLastOutsets.set(mOutsets);
   4489         mLastDisplayCutout = mDisplayCutout;
   4490     }
   4491 
   4492     void startAnimation(Animation anim) {
   4493         final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
   4494         anim.initialize(mFrame.width(), mFrame.height(),
   4495                 displayInfo.appWidth, displayInfo.appHeight);
   4496         anim.restrictDuration(MAX_ANIMATION_DURATION);
   4497         anim.scaleCurrentDuration(mService.getWindowAnimationScaleLocked());
   4498         final AnimationAdapter adapter = new LocalAnimationAdapter(
   4499                 new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */),
   4500                 mService.mSurfaceAnimationRunner);
   4501         startAnimation(mPendingTransaction, adapter);
   4502         commitPendingTransaction();
   4503     }
   4504 
   4505     private void startMoveAnimation(int left, int top) {
   4506         if (DEBUG_ANIM) Slog.v(TAG, "Setting move animation on " + this);
   4507         final Point oldPosition = new Point();
   4508         final Point newPosition = new Point();
   4509         transformFrameToSurfacePosition(mLastFrame.left, mLastFrame.top, oldPosition);
   4510         transformFrameToSurfacePosition(left, top, newPosition);
   4511         final AnimationAdapter adapter = new LocalAnimationAdapter(
   4512                 new MoveAnimationSpec(oldPosition.x, oldPosition.y, newPosition.x, newPosition.y),
   4513                 mService.mSurfaceAnimationRunner);
   4514         startAnimation(getPendingTransaction(), adapter);
   4515     }
   4516 
   4517     private void startAnimation(Transaction t, AnimationAdapter adapter) {
   4518         startAnimation(t, adapter, mWinAnimator.mLastHidden);
   4519     }
   4520 
   4521     @Override
   4522     protected void onAnimationFinished() {
   4523         mWinAnimator.onAnimationFinished();
   4524     }
   4525 
   4526     /**
   4527      * Retrieves the current transformation matrix of the window, relative to the display.
   4528      *
   4529      * @param float9 A temporary array of 9 floats.
   4530      * @param outMatrix Matrix to fill in the transformation.
   4531      */
   4532     void getTransformationMatrix(float[] float9, Matrix outMatrix) {
   4533         float9[Matrix.MSCALE_X] = mWinAnimator.mDsDx;
   4534         float9[Matrix.MSKEW_Y] = mWinAnimator.mDtDx;
   4535         float9[Matrix.MSKEW_X] = mWinAnimator.mDtDy;
   4536         float9[Matrix.MSCALE_Y] = mWinAnimator.mDsDy;
   4537         int x = mSurfacePosition.x;
   4538         int y = mSurfacePosition.y;
   4539 
   4540         // If changed, also adjust transformFrameToSurfacePosition
   4541         final WindowContainer parent = getParent();
   4542         if (isChildWindow()) {
   4543             final WindowState parentWindow = getParentWindow();
   4544             x += parentWindow.mFrame.left - parentWindow.mAttrs.surfaceInsets.left;
   4545             y += parentWindow.mFrame.top - parentWindow.mAttrs.surfaceInsets.top;
   4546         } else if (parent != null) {
   4547             final Rect parentBounds = parent.getBounds();
   4548             x += parentBounds.left;
   4549             y += parentBounds.top;
   4550         }
   4551         float9[Matrix.MTRANS_X] = x;
   4552         float9[Matrix.MTRANS_Y] = y;
   4553         float9[Matrix.MPERSP_0] = 0;
   4554         float9[Matrix.MPERSP_1] = 0;
   4555         float9[Matrix.MPERSP_2] = 1;
   4556         outMatrix.setValues(float9);
   4557     }
   4558 
   4559     // TODO: Hack to work around the number of states AppWindowToken needs to access without having
   4560     // access to its windows children. Need to investigate re-writing
   4561     // {@link AppWindowToken#updateReportedVisibilityLocked} so this can be removed.
   4562     static final class UpdateReportedVisibilityResults {
   4563         int numInteresting;
   4564         int numVisible;
   4565         int numDrawn;
   4566         boolean nowGone = true;
   4567 
   4568         void reset() {
   4569             numInteresting = 0;
   4570             numVisible = 0;
   4571             numDrawn = 0;
   4572             nowGone = true;
   4573         }
   4574     }
   4575 
   4576     private static final class WindowId extends IWindowId.Stub {
   4577         private final WeakReference<WindowState> mOuter;
   4578 
   4579         private WindowId(WindowState outer) {
   4580 
   4581             // Use a weak reference for the outer class. This is important to prevent the following
   4582             // leak: Since we send this class to the client process, binder will keep it alive as
   4583             // long as the client keeps it alive. Now, if the window is removed, we need to clear
   4584             // out our reference so even though this class is kept alive we don't leak WindowState,
   4585             // which can keep a whole lot of classes alive.
   4586             mOuter = new WeakReference<>(outer);
   4587         }
   4588 
   4589         @Override
   4590         public void registerFocusObserver(IWindowFocusObserver observer) {
   4591             final WindowState outer = mOuter.get();
   4592             if (outer != null) {
   4593                 outer.registerFocusObserver(observer);
   4594             }
   4595         }
   4596         @Override
   4597         public void unregisterFocusObserver(IWindowFocusObserver observer) {
   4598             final WindowState outer = mOuter.get();
   4599             if (outer != null) {
   4600                 outer.unregisterFocusObserver(observer);
   4601             }
   4602         }
   4603         @Override
   4604         public boolean isFocused() {
   4605             final WindowState outer = mOuter.get();
   4606             return outer != null && outer.isFocused();
   4607         }
   4608     }
   4609 
   4610 
   4611     @Override
   4612     boolean shouldMagnify() {
   4613         if (mAttrs.type == TYPE_INPUT_METHOD ||
   4614                 mAttrs.type == TYPE_INPUT_METHOD_DIALOG ||
   4615                 mAttrs.type == TYPE_MAGNIFICATION_OVERLAY ||
   4616                 mAttrs.type == TYPE_NAVIGATION_BAR ||
   4617                 // It's tempting to wonder: Have we forgotten the rounded corners overlay?
   4618                 // worry not: it's a fake TYPE_NAVIGATION_BAR_PANEL
   4619                 mAttrs.type == TYPE_NAVIGATION_BAR_PANEL) {
   4620             return false;
   4621         }
   4622         return true;
   4623     }
   4624 
   4625     @Override
   4626     SurfaceSession getSession() {
   4627         if (mSession.mSurfaceSession != null) {
   4628             return mSession.mSurfaceSession;
   4629         } else {
   4630             return getParent().getSession();
   4631         }
   4632     }
   4633 
   4634     @Override
   4635     boolean needsZBoost() {
   4636         if (mIsImWindow && mService.mInputMethodTarget != null) {
   4637             final AppWindowToken appToken = mService.mInputMethodTarget.mAppToken;
   4638             if (appToken != null) {
   4639                 return appToken.needsZBoost();
   4640             }
   4641         }
   4642         return mWillReplaceWindow;
   4643     }
   4644 
   4645     private void applyDims(Dimmer dimmer) {
   4646         if (!mAnimatingExit && mAppDied) {
   4647             mIsDimming = true;
   4648             dimmer.dimAbove(getPendingTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
   4649         } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isVisibleNow() && !mHidden) {
   4650             // Only show a dim behind when the following is satisfied:
   4651             // 1. The window has the flag FLAG_DIM_BEHIND
   4652             // 2. The WindowToken is not hidden so dims aren't shown when the window is exiting.
   4653             // 3. The WS is considered visible according to the isVisible() method
   4654             // 4. The WS is not hidden.
   4655             mIsDimming = true;
   4656             dimmer.dimBelow(getPendingTransaction(), this, mAttrs.dimAmount);
   4657         }
   4658     }
   4659 
   4660     @Override
   4661     void prepareSurfaces() {
   4662         final Dimmer dimmer = getDimmer();
   4663         mIsDimming = false;
   4664         if (dimmer != null) {
   4665             applyDims(dimmer);
   4666         }
   4667         updateSurfacePosition();
   4668 
   4669         mWinAnimator.prepareSurfaceLocked(true);
   4670         super.prepareSurfaces();
   4671     }
   4672 
   4673     @Override
   4674     public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
   4675         super.onAnimationLeashCreated(t, leash);
   4676 
   4677         // Leash is now responsible for position, so set our position to 0.
   4678         t.setPosition(mSurfaceControl, 0, 0);
   4679         mLastSurfacePosition.set(0, 0);
   4680     }
   4681 
   4682     @Override
   4683     public void onAnimationLeashDestroyed(Transaction t) {
   4684         super.onAnimationLeashDestroyed(t);
   4685         updateSurfacePosition(t);
   4686     }
   4687 
   4688     @Override
   4689     void updateSurfacePosition() {
   4690         updateSurfacePosition(getPendingTransaction());
   4691     }
   4692 
   4693     private void updateSurfacePosition(Transaction t) {
   4694         if (mSurfaceControl == null) {
   4695             return;
   4696         }
   4697 
   4698         transformFrameToSurfacePosition(mFrame.left, mFrame.top, mSurfacePosition);
   4699 
   4700         if (!mSurfaceAnimator.hasLeash() && !mLastSurfacePosition.equals(mSurfacePosition)) {
   4701             t.setPosition(mSurfaceControl, mSurfacePosition.x, mSurfacePosition.y);
   4702             mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y);
   4703             if (surfaceInsetsChanging() && mWinAnimator.hasSurface()) {
   4704                 mLastSurfaceInsets.set(mAttrs.surfaceInsets);
   4705                 t.deferTransactionUntil(mSurfaceControl,
   4706                         mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(),
   4707                         getFrameNumber());
   4708             }
   4709         }
   4710     }
   4711 
   4712     private void transformFrameToSurfacePosition(int left, int top, Point outPoint) {
   4713         outPoint.set(left, top);
   4714 
   4715         // If changed, also adjust getTransformationMatrix
   4716         final WindowContainer parentWindowContainer = getParent();
   4717         if (isChildWindow()) {
   4718             // TODO: This probably falls apart at some point and we should
   4719             // actually compute relative coordinates.
   4720 
   4721             // Since the parent was outset by its surface insets, we need to undo the outsetting
   4722             // with insetting by the same amount.
   4723             final WindowState parent = getParentWindow();
   4724             outPoint.offset(-parent.mFrame.left + parent.mAttrs.surfaceInsets.left,
   4725                     -parent.mFrame.top + parent.mAttrs.surfaceInsets.top);
   4726         } else if (parentWindowContainer != null) {
   4727             final Rect parentBounds = parentWindowContainer.getBounds();
   4728             outPoint.offset(-parentBounds.left, -parentBounds.top);
   4729         }
   4730 
   4731         TaskStack stack = getStack();
   4732 
   4733         // If we have stack outsets, that means the top-left
   4734         // will be outset, and we need to inset ourselves
   4735         // to account for it. If we actually have shadows we will
   4736         // then un-inset ourselves by the surfaceInsets.
   4737         if (stack != null) {
   4738             final int outset = stack.getStackOutset();
   4739             outPoint.offset(outset, outset);
   4740         }
   4741 
   4742         // Expand for surface insets. See WindowState.expandForSurfaceInsets.
   4743         outPoint.offset(-mAttrs.surfaceInsets.left, -mAttrs.surfaceInsets.top);
   4744     }
   4745 
   4746     boolean needsRelativeLayeringToIme() {
   4747         // We only use the relative layering mode in split screen, as part of elevating the IME
   4748         // and windows above it's target above the docked divider.
   4749         if (!inSplitScreenWindowingMode()) {
   4750             return false;
   4751         }
   4752 
   4753         if (isChildWindow()) {
   4754             // If we are a child of the input method target we need this promotion.
   4755             if (getParentWindow().isInputMethodTarget()) {
   4756                 return true;
   4757             }
   4758         } else if (mAppToken != null) {
   4759             // Likewise if we share a token with the Input method target and are ordered
   4760             // above it but not necessarily a child (e.g. a Dialog) then we also need
   4761             // this promotion.
   4762             final WindowState imeTarget = mService.mInputMethodTarget;
   4763             boolean inTokenWithAndAboveImeTarget = imeTarget != null && imeTarget != this
   4764                     && imeTarget.mToken == mToken && imeTarget.compareTo(this) <= 0;
   4765             return inTokenWithAndAboveImeTarget;
   4766         }
   4767         return false;
   4768     }
   4769 
   4770     @Override
   4771     void assignLayer(Transaction t, int layer) {
   4772         // See comment in assignRelativeLayerForImeTargetChild
   4773         if (needsRelativeLayeringToIme()) {
   4774             getDisplayContent().assignRelativeLayerForImeTargetChild(t, this);
   4775             return;
   4776         }
   4777         super.assignLayer(t, layer);
   4778     }
   4779 
   4780     @Override
   4781     public boolean isDimming() {
   4782         return mIsDimming;
   4783     }
   4784 
   4785     // TODO(b/70040778): We should aim to eliminate the last user of TYPE_APPLICATION_MEDIA
   4786     // then we can drop all negative layering on the windowing side and simply inherit
   4787     // the default implementation here.
   4788     public void assignChildLayers(Transaction t) {
   4789         int layer = 1;
   4790         for (int i = 0; i < mChildren.size(); i++) {
   4791             final WindowState w = mChildren.get(i);
   4792 
   4793             // APPLICATION_MEDIA_OVERLAY needs to go above APPLICATION_MEDIA
   4794             // while they both need to go below the main window. However the
   4795             // relative layering of multiple APPLICATION_MEDIA/OVERLAY has never
   4796             // been defined and so we can use static layers and leave it that way.
   4797             if (w.mAttrs.type == TYPE_APPLICATION_MEDIA) {
   4798                 w.assignLayer(t, -2);
   4799             } else if (w.mAttrs.type == TYPE_APPLICATION_MEDIA_OVERLAY) {
   4800                 w.assignLayer(t, -1);
   4801             } else {
   4802                 w.assignLayer(t, layer);
   4803             }
   4804             w.assignChildLayers(t);
   4805             layer++;
   4806         }
   4807     }
   4808 
   4809     /**
   4810      * Update a tap exclude region with a rectangular area identified by provided id. The requested
   4811      * area will be clipped to the window bounds.
   4812      */
   4813     void updateTapExcludeRegion(int regionId, int left, int top, int width, int height) {
   4814         final DisplayContent currentDisplay = getDisplayContent();
   4815         if (currentDisplay == null) {
   4816             throw new IllegalStateException("Trying to update window not attached to any display.");
   4817         }
   4818 
   4819         if (mTapExcludeRegionHolder == null) {
   4820             mTapExcludeRegionHolder = new TapExcludeRegionHolder();
   4821 
   4822             // Make sure that this window is registered as one that provides a tap exclude region
   4823             // for its containing display.
   4824             currentDisplay.mTapExcludeProvidingWindows.add(this);
   4825         }
   4826 
   4827         mTapExcludeRegionHolder.updateRegion(regionId, left, top, width, height);
   4828         // Trigger touch exclude region update on current display.
   4829         final boolean isAppFocusedOnDisplay = mService.mFocusedApp != null
   4830                 && mService.mFocusedApp.getDisplayContent() == currentDisplay;
   4831         currentDisplay.setTouchExcludeRegion(isAppFocusedOnDisplay ? mService.mFocusedApp.getTask()
   4832                 : null);
   4833     }
   4834 
   4835     /** Union the region with current tap exclude region that this window provides. */
   4836     void amendTapExcludeRegion(Region region) {
   4837         mTapExcludeRegionHolder.amendRegion(region, getBounds());
   4838     }
   4839 
   4840     @Override
   4841     public boolean isInputMethodTarget() {
   4842         return mService.mInputMethodTarget == this;
   4843     }
   4844 
   4845     long getFrameNumber() {
   4846         return mFrameNumber;
   4847     }
   4848 
   4849     void setFrameNumber(long frameNumber) {
   4850         mFrameNumber = frameNumber;
   4851     }
   4852 
   4853     private final class MoveAnimationSpec implements AnimationSpec {
   4854 
   4855         private final long mDuration;
   4856         private Interpolator mInterpolator;
   4857         private Point mFrom = new Point();
   4858         private Point mTo = new Point();
   4859 
   4860         private MoveAnimationSpec(int fromX, int fromY, int toX, int toY) {
   4861             final Animation anim = AnimationUtils.loadAnimation(mContext,
   4862                     com.android.internal.R.anim.window_move_from_decor);
   4863             mDuration = (long)
   4864                     (anim.computeDurationHint() * mService.getWindowAnimationScaleLocked());
   4865             mInterpolator = anim.getInterpolator();
   4866             mFrom.set(fromX, fromY);
   4867             mTo.set(toX, toY);
   4868         }
   4869 
   4870         @Override
   4871         public long getDuration() {
   4872             return mDuration;
   4873         }
   4874 
   4875         @Override
   4876         public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {
   4877             final float fraction = (float) currentPlayTime / getDuration();
   4878             final float v = mInterpolator.getInterpolation(fraction);
   4879             t.setPosition(leash, mFrom.x + (mTo.x - mFrom.x) * v,
   4880                     mFrom.y + (mTo.y - mFrom.y) * v);
   4881         }
   4882 
   4883         @Override
   4884         public void dump(PrintWriter pw, String prefix) {
   4885             pw.print(prefix); pw.print("from="); pw.print(mFrom);
   4886             pw.print(" to="); pw.print(mTo);
   4887             pw.print(" duration="); pw.println(mDuration);
   4888         }
   4889 
   4890         @Override
   4891         public void writeToProtoInner(ProtoOutputStream proto) {
   4892             final long token = proto.start(MOVE);
   4893             mFrom.writeToProto(proto, FROM);
   4894             mTo.writeToProto(proto, TO);
   4895             proto.write(DURATION_MS, mDuration);
   4896             proto.end(token);
   4897         }
   4898     }
   4899 }
   4900