1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
20 import static android.app.ActivityManager.StackId;
21 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
22 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
23 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
24 import static android.app.ActivityManager.isLowRamDeviceStatic;
25 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
26 import static android.view.Display.DEFAULT_DISPLAY;
27 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
28 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
29 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
30 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
31 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
32 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
33 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
34 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
35 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
36 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
37 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
38 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
39 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
40 import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
41 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
42 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
43 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
44 import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
45 import static android.view.WindowManager.LayoutParams.FORMAT_CHANGED;
46 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
47 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
48 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
49 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
50 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
51 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
52 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
53 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
54 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
55 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
56 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
57 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
58 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
59 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
60 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
61 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
62 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
63 import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED;
64 import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM;
65 import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
66 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
67 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
68 import static android.view.WindowManagerPolicy.TRANSIT_ENTER;
69 import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
70 import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
71 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
72 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
73 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
74 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
75 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
76 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
77 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
78 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
79 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
80 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
81 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
82 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
83 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
84 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
85 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
86 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
87 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
88 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
89 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
90 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
91 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
92 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
93 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
94 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
95 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
96 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
97 import static com.android.server.wm.WindowManagerService.localLOGV;
98 import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING;
99 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
100 import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
101 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
102 
103 import android.app.AppOpsManager;
104 import android.content.Context;
105 import android.content.res.Configuration;
106 import android.graphics.Matrix;
107 import android.graphics.PixelFormat;
108 import android.graphics.Point;
109 import android.graphics.Rect;
110 import android.graphics.Region;
111 import android.os.Binder;
112 import android.os.Debug;
113 import android.os.IBinder;
114 import android.os.PowerManager;
115 import android.os.RemoteCallbackList;
116 import android.os.RemoteException;
117 import android.os.SystemClock;
118 import android.os.Trace;
119 import android.os.UserHandle;
120 import android.os.WorkSource;
121 import android.util.MergedConfiguration;
122 import android.util.DisplayMetrics;
123 import android.util.Slog;
124 import android.util.TimeUtils;
125 import android.view.DisplayInfo;
126 import android.view.Gravity;
127 import android.view.IApplicationToken;
128 import android.view.IWindow;
129 import android.view.IWindowFocusObserver;
130 import android.view.IWindowId;
131 import android.view.InputChannel;
132 import android.view.InputEvent;
133 import android.view.InputEventReceiver;
134 import android.view.View;
135 import android.view.ViewTreeObserver;
136 import android.view.WindowInfo;
137 import android.view.WindowManager;
138 import android.view.WindowManagerPolicy;
139 
140 import com.android.internal.util.ToBooleanFunction;
141 import com.android.server.input.InputWindowHandle;
142 
143 import java.io.PrintWriter;
144 import java.lang.ref.WeakReference;
145 import java.util.ArrayList;
146 import java.util.Comparator;
147 import java.util.LinkedList;
148 import java.util.function.Predicate;
149 
150 /** A window in the window manager. */
151 class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState {
152     static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM;
153 
154     // The minimal size of a window within the usable area of the freeform stack.
155     // TODO(multi-window): fix the min sizes when we have mininum width/height support,
156     //                     use hard-coded min sizes for now.
157     static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48;
158     static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32;
159 
160     // The thickness of a window resize handle outside the window bounds on the free form workspace
161     // to capture touch events in that area.
162     static final int RESIZE_HANDLE_WIDTH_IN_DP = 30;
163 
164     private static final boolean DEBUG_DISABLE_SAVING_SURFACES = false ||
165             ENABLE_TASK_SNAPSHOTS;
166 
167     final WindowManagerService mService;
168     final WindowManagerPolicy mPolicy;
169     final Context mContext;
170     final Session mSession;
171     final IWindow mClient;
172     final int mAppOp;
173     // UserId and appId of the owner. Don't display windows of non-current user.
174     final int mOwnerUid;
175     /** The owner has {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} */
176     final boolean mOwnerCanAddInternalSystemWindow;
177     final WindowId mWindowId;
178     WindowToken mToken;
179     // The same object as mToken if this is an app window and null for non-app windows.
180     AppWindowToken mAppToken;
181 
182     // mAttrs.flags is tested in animation without being locked. If the bits tested are ever
183     // modified they will need to be locked.
184     final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
185     final DeathRecipient mDeathRecipient;
186     private boolean mIsChildWindow;
187     final int mBaseLayer;
188     final int mSubLayer;
189     final boolean mLayoutAttached;
190     final boolean mIsImWindow;
191     final boolean mIsWallpaper;
192     private final boolean mIsFloatingLayer;
193     int mSeq;
194     boolean mEnforceSizeCompat;
195     int mViewVisibility;
196     int mSystemUiVisibility;
197     /**
198      * The visibility of the window based on policy like {@link WindowManagerPolicy}.
199      * Normally set by calling {@link #showLw} and {@link #hideLw}.
200      */
201     boolean mPolicyVisibility = true;
202     /**
203      * What {@link #mPolicyVisibility} should be set to after a transition animation.
204      * For example, {@link #mPolicyVisibility} might true during an exit animation to hide it and
205      * then set to the value of {@link #mPolicyVisibilityAfterAnim} which is false after the exit
206      * animation is done.
207      */
208     boolean mPolicyVisibilityAfterAnim = true;
209     private boolean mAppOpVisibility = true;
210     boolean mPermanentlyHidden; // the window should never be shown again
211     boolean mAppFreezing;
212     boolean mHidden;    // Used to determine if to show child windows.
213     boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
214     private boolean mDragResizing;
215     private boolean mDragResizingChangeReported = true;
216     private int mResizeMode;
217 
218     private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
219 
220     /**
221      * The window size that was requested by the application.  These are in
222      * the application's coordinate space (without compatibility scale applied).
223      */
224     int mRequestedWidth;
225     int mRequestedHeight;
226     private int mLastRequestedWidth;
227     private int mLastRequestedHeight;
228 
229     int mLayer;
230     boolean mHaveFrame;
231     boolean mObscured;
232     boolean mTurnOnScreen;
233 
234     int mLayoutSeq = -1;
235 
236     /**
237      * Used to store last reported to client configuration and check if we have newer available.
238      * We'll send configuration to client only if it is different from the last applied one and
239      * client won't perform unnecessary updates.
240      */
241     private final Configuration mLastReportedConfiguration = new Configuration();
242 
243     /**
244      * Actual position of the surface shown on-screen (may be modified by animation). These are
245      * in the screen's coordinate space (WITH the compatibility scale applied).
246      */
247     final Point mShownPosition = new Point();
248 
249     /**
250      * Insets that determine the actually visible area.  These are in the application's
251      * coordinate space (without compatibility scale applied).
252      */
253     final Rect mVisibleInsets = new Rect();
254     private final Rect mLastVisibleInsets = new Rect();
255     private boolean mVisibleInsetsChanged;
256 
257     /**
258      * Insets that are covered by system windows (such as the status bar) and
259      * transient docking windows (such as the IME).  These are in the application's
260      * coordinate space (without compatibility scale applied).
261      */
262     final Rect mContentInsets = new Rect();
263     final Rect mLastContentInsets = new Rect();
264 
265     /**
266      * The last content insets returned to the client in relayout. We use
267      * these in the bounds animation to ensure we only observe inset changes
268      * at the same time that a client resizes it's surface so that we may use
269      * the geometryAppliesWithResize synchronization mechanism to keep
270      * the contents in place.
271      */
272     final Rect mLastRelayoutContentInsets = new Rect();
273 
274     private boolean mContentInsetsChanged;
275 
276     /**
277      * Insets that determine the area covered by the display overscan region.  These are in the
278      * application's coordinate space (without compatibility scale applied).
279      */
280     final Rect mOverscanInsets = new Rect();
281     private final Rect mLastOverscanInsets = new Rect();
282     private boolean mOverscanInsetsChanged;
283 
284     /**
285      * Insets that determine the area covered by the stable system windows.  These are in the
286      * application's coordinate space (without compatibility scale applied).
287      */
288     final Rect mStableInsets = new Rect();
289     private final Rect mLastStableInsets = new Rect();
290     private boolean mStableInsetsChanged;
291 
292     /**
293      * Outsets determine the area outside of the surface where we want to pretend that it's possible
294      * to draw anyway.
295      */
296     final Rect mOutsets = new Rect();
297     private final Rect mLastOutsets = new Rect();
298     private boolean mOutsetsChanged = false;
299 
300     /**
301      * Set to true if we are waiting for this window to receive its
302      * given internal insets before laying out other windows based on it.
303      */
304     boolean mGivenInsetsPending;
305 
306     /**
307      * These are the content insets that were given during layout for
308      * this window, to be applied to windows behind it.
309      */
310     final Rect mGivenContentInsets = new Rect();
311 
312     /**
313      * These are the visible insets that were given during layout for
314      * this window, to be applied to windows behind it.
315      */
316     final Rect mGivenVisibleInsets = new Rect();
317 
318     /**
319      * This is the given touchable area relative to the window frame, or null if none.
320      */
321     final Region mGivenTouchableRegion = new Region();
322 
323     /**
324      * Flag indicating whether the touchable region should be adjusted by
325      * the visible insets; if false the area outside the visible insets is
326      * NOT touchable, so we must use those to adjust the frame during hit
327      * tests.
328      */
329     int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
330 
331     // Current transformation being applied.
332     float mGlobalScale=1;
333     float mInvGlobalScale=1;
334     float mHScale=1, mVScale=1;
335     float mLastHScale=1, mLastVScale=1;
336     final Matrix mTmpMatrix = new Matrix();
337 
338     // "Real" frame that the application sees, in display coordinate space.
339     final Rect mFrame = new Rect();
340     final Rect mLastFrame = new Rect();
341     private boolean mFrameSizeChanged = false;
342     // Frame that is scaled to the application's coordinate space when in
343     // screen size compatibility mode.
344     final Rect mCompatFrame = new Rect();
345 
346     final Rect mContainingFrame = new Rect();
347 
348     private final Rect mParentFrame = new Rect();
349 
350     // The entire screen area of the {@link TaskStack} this window is in. Usually equal to the
351     // screen area of the device.
352     final Rect mDisplayFrame = new Rect();
353 
354     // The region of the display frame that the display type supports displaying content on. This
355     // is mostly a special case for TV where some displays 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 
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a, int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow)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 
attach()673     void attach() {
674         if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
675         mSession.windowAddedLocked(mAttrs.packageName);
676     }
677 
678     @Override
getOwningUid()679     public int getOwningUid() {
680         return mOwnerUid;
681     }
682 
683     @Override
getOwningPackage()684     public String getOwningPackage() {
685         return mAttrs.packageName;
686     }
687 
688     @Override
canAddInternalSystemWindow()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      */
subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame, Rect displayFrame)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
computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overscanFrame, Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame, Rect outsetFrame)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
getFrameLw()986     public Rect getFrameLw() {
987         return mFrame;
988     }
989 
990     @Override
getShownPositionLw()991     public Point getShownPositionLw() {
992         return mShownPosition;
993     }
994 
995     @Override
getDisplayFrameLw()996     public Rect getDisplayFrameLw() {
997         return mDisplayFrame;
998     }
999 
1000     @Override
getOverscanFrameLw()1001     public Rect getOverscanFrameLw() {
1002         return mOverscanFrame;
1003     }
1004 
1005     @Override
getContentFrameLw()1006     public Rect getContentFrameLw() {
1007         return mContentFrame;
1008     }
1009 
1010     @Override
getVisibleFrameLw()1011     public Rect getVisibleFrameLw() {
1012         return mVisibleFrame;
1013     }
1014 
getStableFrameLw()1015     Rect getStableFrameLw() {
1016         return mStableFrame;
1017     }
1018 
1019     @Override
getGivenInsetsPendingLw()1020     public boolean getGivenInsetsPendingLw() {
1021         return mGivenInsetsPending;
1022     }
1023 
1024     @Override
getGivenContentInsetsLw()1025     public Rect getGivenContentInsetsLw() {
1026         return mGivenContentInsets;
1027     }
1028 
1029     @Override
getGivenVisibleInsetsLw()1030     public Rect getGivenVisibleInsetsLw() {
1031         return mGivenVisibleInsets;
1032     }
1033 
1034     @Override
getAttrs()1035     public WindowManager.LayoutParams getAttrs() {
1036         return mAttrs;
1037     }
1038 
1039     @Override
getNeedsMenuLw(WindowManagerPolicy.WindowState bottom)1040     public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) {
1041         return getDisplayContent().getNeedsMenu(this, bottom);
1042     }
1043 
1044     @Override
getSystemUiVisibility()1045     public int getSystemUiVisibility() {
1046         return mSystemUiVisibility;
1047     }
1048 
1049     @Override
getSurfaceLayer()1050     public int getSurfaceLayer() {
1051         return mLayer;
1052     }
1053 
1054     @Override
getBaseType()1055     public int getBaseType() {
1056         return getTopParentWindow().mAttrs.type;
1057     }
1058 
1059     @Override
getAppToken()1060     public IApplicationToken getAppToken() {
1061         return mAppToken != null ? mAppToken.appToken : null;
1062     }
1063 
1064     @Override
isVoiceInteraction()1065     public boolean isVoiceInteraction() {
1066         return mAppToken != null && mAppToken.mVoiceInteraction;
1067     }
1068 
setReportResizeHints()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      */
updateResizingWindowIfNeeded()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 
getDisplayContent()1185     DisplayContent getDisplayContent() {
1186         return mToken.getDisplayContent();
1187     }
1188 
getDisplayInfo()1189     DisplayInfo getDisplayInfo() {
1190         final DisplayContent displayContent = getDisplayContent();
1191         return displayContent != null ? displayContent.getDisplayInfo() : null;
1192     }
1193 
1194     @Override
getDisplayId()1195     public int getDisplayId() {
1196         final DisplayContent displayContent = getDisplayContent();
1197         if (displayContent == null) {
1198             return -1;
1199         }
1200         return displayContent.getDisplayId();
1201     }
1202 
getTask()1203     Task getTask() {
1204         return mAppToken != null ? mAppToken.getTask() : null;
1205     }
1206 
getStack()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      */
getVisibleBounds(Rect bounds)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 
getInputDispatchingTimeoutNanos()1252     public long getInputDispatchingTimeoutNanos() {
1253         return mAppToken != null
1254                 ? mAppToken.mInputDispatchingTimeoutNanos
1255                 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
1256     }
1257 
1258     @Override
hasAppShownWindows()1259     public boolean hasAppShownWindows() {
1260         return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed);
1261     }
1262 
isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy)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 
prelayout()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
hasContentToDisplay()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
isVisible()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      */
wouldBeVisibleIfPolicyIgnored()1302     boolean wouldBeVisibleIfPolicyIgnored() {
1303         return mHasSurface && !isParentWindowHidden()
1304                 && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible);
1305     }
1306 
1307     @Override
isVisibleLw()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?
isWinVisibleLw()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      */
isVisibleNow()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      */
isPotentialDragTarget()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      */
isVisibleOrAdding()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      */
isOnScreen()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      */
mightAffectAllDrawn(boolean visibleOnly)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      */
isInteresting()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      */
isReadyForDisplay()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
canAffectSystemUiFlags()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
isDisplayedLw()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
isAnimatingLw()1439     public boolean isAnimatingLw() {
1440         return mWinAnimator.mAnimation != null
1441                 || (mAppToken != null && mAppToken.mAppAnimator.animation != null);
1442     }
1443 
1444     @Override
isGoneForLayoutLw()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      */
isDrawFinishedLw()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
isDrawnLw()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      */
isOpaqueDrawn()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
onMovedByResize()1492     void onMovedByResize() {
1493         if (DEBUG_RESIZE) Slog.d(TAG, "onMovedByResize: Moving " + this);
1494         mMovedByResize = true;
1495         super.onMovedByResize();
1496     }
1497 
onAppVisibilityChanged(boolean visible, boolean runningAppAnimation)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 
onSetAppExiting()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
onResize()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 
onUnfreezeBounds()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      */
handleWindowMovedIfNeeded()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      */
hasMoved()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 
isObscuringDisplay()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 
fillsDisplay()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. */
isConfigChanged()1683     boolean isConfigChanged() {
1684         return !mLastReportedConfiguration.equals(getConfiguration());
1685     }
1686 
onWindowReplacementTimeout()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
forceWindowsScaleableInTransaction(boolean force)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
removeImmediately()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
removeIfPossible()1758     void removeIfPossible() {
1759         super.removeIfPossible();
1760         removeIfPossible(false /*keepVisibleDeadWindow*/);
1761     }
1762 
removeIfPossible(boolean keepVisibleDeadWindow)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 
setupWindowForRemoveOnExit()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 
setHasSurface(boolean hasSurface)1912     void setHasSurface(boolean hasSurface) {
1913         mHasSurface = hasSurface;
1914     }
1915 
getAnimLayerAdjustment()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 
getSpecialWindowAnimLayerAdjustment()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 
canBeImeTarget()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 
scheduleAnimationIfDimming()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 {
DeadWindowEventReceiver(InputChannel inputChannel)1986         DeadWindowEventReceiver(InputChannel inputChannel) {
1987             super(inputChannel, mService.mH.getLooper());
1988         }
1989         @Override
onInputEvent(InputEvent event)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 
openInputChannel(InputChannel outInputChannel)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 
disposeInputChannel()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 
applyDimLayerIfNeeded()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 
getDimLayerUser()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. */
removeReplacedWindowIfNeeded(WindowState replacement)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 
removeReplacedWindow()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 
setReplacementWindowIfNeeded(WindowState replacementCandidate)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 
setDisplayLayoutNeeded()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.
inPinnedWorkspace()2125     boolean inPinnedWorkspace() {
2126         final Task task = getTask();
2127         return task != null && task.inPinnedWorkspace();
2128     }
2129 
applyAdjustForImeIfNeeded()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
switchUser()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 
getTouchableRegion(Region region, int flags)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 
checkPolicyVisibilityChange()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 
setRequestedSize(int requestedWidth, int requestedHeight)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 
prepareWindowToDisplayDuringRelayout(MergedConfiguration mergedConfiguration, boolean wasVisible)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 
adjustStartingWindowFlags()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 
setWindowScale(int requestedWidth, int requestedHeight)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
binderDied()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      */
shouldKeepVisibleDeadAppWindow()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. */
canReceiveKeys()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. */
canReceiveTouchInput()2346     boolean canReceiveTouchInput() {
2347         return mAppToken != null && mAppToken.getTask() != null
2348                 && mAppToken.getTask().mStack.shouldIgnoreInput();
2349     }
2350 
2351     @Override
hasDrawnLw()2352     public boolean hasDrawnLw() {
2353         return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN;
2354     }
2355 
2356     @Override
showLw(boolean doAnimation)2357     public boolean showLw(boolean doAnimation) {
2358         return showLw(doAnimation, true);
2359     }
2360 
showLw(boolean doAnimation, boolean requestAnim)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
hideLw(boolean doAnimation)2406     public boolean hideLw(boolean doAnimation) {
2407         return hideLw(doAnimation, true);
2408     }
2409 
hideLw(boolean doAnimation, boolean requestAnim)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 
setAppOpVisibilityLw(boolean state)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 
hidePermanentlyLw()2467     public void hidePermanentlyLw() {
2468         if (!mPermanentlyHidden) {
2469             mPermanentlyHidden = true;
2470             hideLw(true, true);
2471         }
2472     }
2473 
pokeDrawLockLw(long timeout)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
isAlive()2499     public boolean isAlive() {
2500         return mClient.asBinder().isBinderAlive();
2501     }
2502 
isClosing()2503     boolean isClosing() {
2504         return mAnimatingExit || (mService.mClosingApps.contains(mAppToken));
2505     }
2506 
isAnimatingWithSavedSurface()2507     boolean isAnimatingWithSavedSurface() {
2508         return mAnimatingWithSavedSurface;
2509     }
2510 
2511     @Override
isAnimating()2512     boolean isAnimating() {
2513         if (mWinAnimator.isAnimationSet() || mAnimatingExit) {
2514             return true;
2515         }
2516         return super.isAnimating();
2517     }
2518 
isAnimatingInvisibleWithSavedSurface()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 
stopUsingSavedSurface()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 
markSavedSurfaceExiting()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 
addWinAnimatorToList(ArrayList<WindowStateAnimator> animators)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 
sendAppVisibilityToClients()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 
setVisibleBeforeClientHidden()2599     public void setVisibleBeforeClientHidden() {
2600         mWasVisibleBeforeClientHidden |=
2601                 (mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface);
2602 
2603         super.setVisibleBeforeClientHidden();
2604     }
2605 
clearWasVisibleBeforeClientHidden()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 
wasVisibleBeforeClientHidden()2614     public boolean wasVisibleBeforeClientHidden() {
2615         return mWasVisibleBeforeClientHidden;
2616     }
2617 
onStartFreezingScreen()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 
onStopFreezingScreen()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 
shouldSaveSurface()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 
destroySurface(boolean cleanupOnResume, boolean appStopped)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}
destroyOrSaveSurfaceUnchecked()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 
destroySavedSurface()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.*/
restoreSavedSurfaceForInterestingWindow()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. */
restoreSavedSurface()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 
canRestoreSurface()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 
hasSavedSurface()2857     boolean hasSavedSurface() {
2858         return mSurfaceSaved;
2859     }
2860 
clearHasSavedSurface()2861     void clearHasSavedSurface() {
2862         mSurfaceSaved = false;
2863         mAnimatingWithSavedSurface = false;
2864         if (mWasVisibleBeforeClientHidden) {
2865             mAppToken.destroySavedSurfaces();
2866         }
2867     }
2868 
clearAnimatingWithSavedSurface()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
isDefaultDisplay()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
isDimming()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 
setShowToOwnerOnlyLocked(boolean showToOwnerOnly)2899     void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
2900         mShowToOwnerOnly = showToOwnerOnly;
2901     }
2902 
isHiddenFromUserLocked()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 
applyInsets(Region outRegion, Rect frame, Rect inset)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 
getTouchableRegion(Region outRegion)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 
cropRegionToStackBoundsIfNeeded(Region region)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      */
reportFocusChangedSerialized(boolean focused, boolean inTouchMode)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
getConfiguration()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 
reportResized()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 
getBackdropFrame(Rect frame)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
getStackId()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 
dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean reportOrientation, int displayId)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 
registerFocusObserver(IWindowFocusObserver observer)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 
unregisterFocusObserver(IWindowFocusObserver observer)3122     public void unregisterFocusObserver(IWindowFocusObserver observer) {
3123         synchronized(mService.mWindowMap) {
3124             if (mFocusCallbacks != null) {
3125                 mFocusCallbacks.unregister(observer);
3126             }
3127         }
3128     }
3129 
isFocused()3130     public boolean isFocused() {
3131         synchronized(mService.mWindowMap) {
3132             return mService.mCurrentFocus == this;
3133         }
3134     }
3135 
inFreeformWorkspace()3136     boolean inFreeformWorkspace() {
3137         final Task task = getTask();
3138         return task != null && task.inFreeformWorkspace();
3139     }
3140 
3141     @Override
isInMultiWindowMode()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? */
inFullscreenContainer()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. */
getContainerBounds(Rect outBounds)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 
isDragResizeChanged()3169     boolean isDragResizeChanged() {
3170         return mDragResizing != computeDragResizing();
3171     }
3172 
3173     @Override
setWaitingForDrawnIfResizingChanged()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      */
isDragResizingChangeReported()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
resetDragResizingChangeReported()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      */
setResizedWhileNotDragResizing(boolean resizedWhileNotDragResizing)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      */
isResizedWhileNotDragResizing()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      */
isResizedWhileNotDragResizingReported()3219     private boolean isResizedWhileNotDragResizingReported() {
3220         return mResizedWhileNotDragResizingReported;
3221     }
3222 
getResizeMode()3223     int getResizeMode() {
3224         return mResizeMode;
3225     }
3226 
computeDragResizing()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 
setDragResizing()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 
isDragResizing()3269     boolean isDragResizing() {
3270         return mDragResizing;
3271     }
3272 
isDockedResizing()3273     boolean isDockedResizing() {
3274         return (mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER)
3275                 || (isChildWindow() && getParentWindow().isDockedResizing());
3276     }
3277 
dump(PrintWriter pw, String prefix, boolean dumpAll)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
getName()3465     String getName() {
3466         return Integer.toHexString(System.identityHashCode(this))
3467             + " " + getWindowTag();
3468     }
3469 
getWindowTag()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
toString()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 
transformClipRectFromScreenToSurfaceSpace(Rect clipRect)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 
applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame)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 
isChildWindow()3587     boolean isChildWindow() {
3588         return mIsChildWindow;
3589     }
3590 
layoutInParentFrame()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. */
getParentWindow()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. */
getTopParentWindow()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 
isParentWindowHidden()3619     boolean isParentWindowHidden() {
3620         final WindowState parent = getParentWindow();
3621         return parent != null && parent.mHidden;
3622     }
3623 
setWillReplaceWindow(boolean animate)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 
clearWillReplaceWindow()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 
waitingForReplacement()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 
requestUpdateWallpaperIfNeeded()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 
translateToWindowX(float x)3681     float translateToWindowX(float x) {
3682         float winX = x - mFrame.left;
3683         if (mEnforceSizeCompat) {
3684             winX *= mGlobalScale;
3685         }
3686         return winX;
3687     }
3688 
translateToWindowY(float y)3689     float translateToWindowY(float y) {
3690         float winY = y - mFrame.top;
3691         if (mEnforceSizeCompat) {
3692             winY *= mGlobalScale;
3693         }
3694         return winY;
3695     }
3696 
transferDimToReplacement()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.
shouldBeReplacedWithChildren()3714     boolean shouldBeReplacedWithChildren() {
3715         return mIsChildWindow || mAttrs.type == TYPE_APPLICATION
3716                 || mAttrs.type == TYPE_DRAWN_APPLICATION;
3717     }
3718 
setWillReplaceChildWindows()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 
getReplacingWindow()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
getRotationAnimationHint()3744     public int getRotationAnimationHint() {
3745         if (mAppToken != null) {
3746             return mAppToken.mRotationAnimationHint;
3747         } else {
3748             return -1;
3749         }
3750     }
3751 
3752     @Override
isInputMethodWindow()3753     public boolean isInputMethodWindow() {
3754         return mIsImWindow;
3755     }
3756 
3757     // This must be called while inside a transaction.
performShowLocked()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 
logPerformShow(String prefix)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 
getWindowInfo()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 
getHighestAnimLayer()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
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)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 
forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback)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 
forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback)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 
applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)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 
getWindow(Predicate<WindowState> callback)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 
isWindowAnimationSet()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 
onExitAnimationDone()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 
clearAnimatingFlags()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 
isRtl()4152     public boolean isRtl() {
4153         return getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
4154     }
4155 
hideWallpaperWindow(boolean wasDeferred, String reason)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      */
dispatchWallpaperVisibility(final boolean visible)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 
hasVisibleNotDrawnWallpaper()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 
updateReportedVisibility(UpdateReportedVisibilityResults results)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      */
calculatePolicyCrop(Rect policyCrop)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      */
calculateSystemDecorRect(Rect systemDecorRect)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      */
expandForSurfaceInsets(Rect r)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 
surfaceInsetsChanging()4341     boolean surfaceInsetsChanging() {
4342         return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets);
4343     }
4344 
relayoutVisibleWindow(MergedConfiguration mergedConfiguration, int result, int attrChanges, int oldVisibility)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      */
isLaidOut()4422     boolean isLaidOut() {
4423         return mLayoutSeq != -1;
4424     }
4425 
4426     /**
4427      * Updates the last inset values to the current ones.
4428      */
updateLastInsetValues()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 
reset()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 
WindowId(WindowState outer)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
registerFocusObserver(IWindowFocusObserver observer)4468         public void registerFocusObserver(IWindowFocusObserver observer) {
4469             final WindowState outer = mOuter.get();
4470             if (outer != null) {
4471                 outer.registerFocusObserver(observer);
4472             }
4473         }
4474         @Override
unregisterFocusObserver(IWindowFocusObserver observer)4475         public void unregisterFocusObserver(IWindowFocusObserver observer) {
4476             final WindowState outer = mOuter.get();
4477             if (outer != null) {
4478                 outer.unregisterFocusObserver(observer);
4479             }
4480         }
4481         @Override
isFocused()4482         public boolean isFocused() {
4483             final WindowState outer = mOuter.get();
4484             return outer != null && outer.isFocused();
4485         }
4486     }
4487 
usesRelativeZOrdering()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