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