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