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