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