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