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