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