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