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