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