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