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