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