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