• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.app.ActivityTaskManager.INVALID_STACK_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.os.PowerManager.DRAW_WAKE_LOCK;
24 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
25 import static android.view.Display.DEFAULT_DISPLAY;
26 import static android.view.SurfaceControl.Transaction;
27 import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
28 import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
29 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
30 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
31 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
32 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
33 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
34 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
35 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
36 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
37 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
38 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
39 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
40 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
41 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
42 import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
43 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
44 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
45 import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
46 import static android.view.WindowManager.LayoutParams.FORMAT_CHANGED;
47 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
48 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
49 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
50 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
51 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
52 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
53 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
54 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
55 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
56 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
57 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
58 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
59 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
60 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
61 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
62 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
63 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
64 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
65 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
66 import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
67 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
68 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
69 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
70 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
71 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
72 import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED;
73 import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM;
74 import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
75 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
76 
77 import static com.android.server.am.ActivityManagerService.MY_PID;
78 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
79 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
80 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
81 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
82 import static com.android.server.wm.AnimationSpecProto.MOVE;
83 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
84 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
85 import static com.android.server.wm.IdentifierProto.HASH_CODE;
86 import static com.android.server.wm.IdentifierProto.TITLE;
87 import static com.android.server.wm.IdentifierProto.USER_ID;
88 import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS;
89 import static com.android.server.wm.MoveAnimationSpecProto.FROM;
90 import static com.android.server.wm.MoveAnimationSpecProto.TO;
91 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
92 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
93 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
94 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
95 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
96 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
97 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
98 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
99 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
100 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
101 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
102 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
103 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
104 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
105 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
106 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
107 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
108 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
109 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
110 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
111 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
112 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
113 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS;
114 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
115 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
116 import static com.android.server.wm.WindowManagerService.localLOGV;
117 import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING;
118 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
119 import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
120 import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER;
121 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
122 import static com.android.server.wm.WindowStateProto.ANIMATING_EXIT;
123 import static com.android.server.wm.WindowStateProto.ANIMATOR;
124 import static com.android.server.wm.WindowStateProto.ATTRIBUTES;
125 import static com.android.server.wm.WindowStateProto.CHILD_WINDOWS;
126 import static com.android.server.wm.WindowStateProto.DESTROYING;
127 import static com.android.server.wm.WindowStateProto.DISPLAY_ID;
128 import static com.android.server.wm.WindowStateProto.FINISHED_SEAMLESS_ROTATION_FRAME;
129 import static com.android.server.wm.WindowStateProto.FORCE_SEAMLESS_ROTATION;
130 import static com.android.server.wm.WindowStateProto.GIVEN_CONTENT_INSETS;
131 import static com.android.server.wm.WindowStateProto.HAS_SURFACE;
132 import static com.android.server.wm.WindowStateProto.IDENTIFIER;
133 import static com.android.server.wm.WindowStateProto.IS_ON_SCREEN;
134 import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY;
135 import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
136 import static com.android.server.wm.WindowStateProto.PENDING_SEAMLESS_ROTATION;
137 import static com.android.server.wm.WindowStateProto.REMOVED;
138 import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT;
139 import static com.android.server.wm.WindowStateProto.REQUESTED_HEIGHT;
140 import static com.android.server.wm.WindowStateProto.REQUESTED_WIDTH;
141 import static com.android.server.wm.WindowStateProto.STACK_ID;
142 import static com.android.server.wm.WindowStateProto.SURFACE_INSETS;
143 import static com.android.server.wm.WindowStateProto.SURFACE_POSITION;
144 import static com.android.server.wm.WindowStateProto.SYSTEM_UI_VISIBILITY;
145 import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
146 import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
147 import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
148 
149 import android.annotation.CallSuper;
150 import android.annotation.Nullable;
151 import android.app.AppOpsManager;
152 import android.content.Context;
153 import android.content.res.Configuration;
154 import android.graphics.Matrix;
155 import android.graphics.PixelFormat;
156 import android.graphics.Point;
157 import android.graphics.Rect;
158 import android.graphics.Region;
159 import android.os.Binder;
160 import android.os.Build;
161 import android.os.Debug;
162 import android.os.IBinder;
163 import android.os.PowerManager;
164 import android.os.PowerManager.WakeReason;
165 import android.os.RemoteCallbackList;
166 import android.os.RemoteException;
167 import android.os.SystemClock;
168 import android.os.Trace;
169 import android.os.UserHandle;
170 import android.os.WorkSource;
171 import android.provider.Settings;
172 import android.text.TextUtils;
173 import android.util.DisplayMetrics;
174 import android.util.MergedConfiguration;
175 import android.util.Slog;
176 import android.util.TimeUtils;
177 import android.util.proto.ProtoOutputStream;
178 import android.view.Display;
179 import android.view.DisplayCutout;
180 import android.view.DisplayInfo;
181 import android.view.Gravity;
182 import android.view.IApplicationToken;
183 import android.view.IWindow;
184 import android.view.IWindowFocusObserver;
185 import android.view.IWindowId;
186 import android.view.InputChannel;
187 import android.view.InputEvent;
188 import android.view.InputEventReceiver;
189 import android.view.InputWindowHandle;
190 import android.view.Surface.Rotation;
191 import android.view.SurfaceControl;
192 import android.view.SurfaceSession;
193 import android.view.View;
194 import android.view.ViewTreeObserver;
195 import android.view.WindowInfo;
196 import android.view.WindowManager;
197 import android.view.animation.Animation;
198 import android.view.animation.AnimationUtils;
199 import android.view.animation.Interpolator;
200 
201 import com.android.internal.annotations.VisibleForTesting;
202 import com.android.internal.util.ToBooleanFunction;
203 import com.android.server.policy.WindowManagerPolicy;
204 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
205 import com.android.server.wm.utils.InsetUtils;
206 import com.android.server.wm.utils.WmDisplayCutout;
207 
208 import java.io.PrintWriter;
209 import java.lang.ref.WeakReference;
210 import java.util.ArrayList;
211 import java.util.Comparator;
212 import java.util.List;
213 import java.util.function.Predicate;
214 
215 /** A window in the window manager. */
216 class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState {
217     static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM;
218 
219     // The minimal size of a window within the usable area of the freeform stack.
220     // TODO(multi-window): fix the min sizes when we have minimum width/height support,
221     //                     use hard-coded min sizes for now.
222     static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48;
223     static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32;
224 
225     // The thickness of a window resize handle outside the window bounds on the free form workspace
226     // to capture touch events in that area.
227     static final int RESIZE_HANDLE_WIDTH_IN_DP = 30;
228 
229     final WindowManagerPolicy mPolicy;
230     final Context mContext;
231     final Session mSession;
232     final IWindow mClient;
233     final int mAppOp;
234     // UserId and appId of the owner. Don't display windows of non-current user.
235     final int mOwnerUid;
236     /** The owner has {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} */
237     final boolean mOwnerCanAddInternalSystemWindow;
238     final WindowId mWindowId;
239     WindowToken mToken;
240     // The same object as mToken if this is an app window and null for non-app windows.
241     AppWindowToken mAppToken;
242 
243     // mAttrs.flags is tested in animation without being locked. If the bits tested are ever
244     // modified they will need to be locked.
245     final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
246     final DeathRecipient mDeathRecipient;
247     private boolean mIsChildWindow;
248     final int mBaseLayer;
249     final int mSubLayer;
250     final boolean mLayoutAttached;
251     final boolean mIsImWindow;
252     final boolean mIsWallpaper;
253     private final boolean mIsFloatingLayer;
254     int mSeq;
255     int mViewVisibility;
256     int mSystemUiVisibility;
257 
258     /**
259      * The visibility flag of the window based on policy like {@link WindowManagerPolicy}.
260      * Normally set by calling {@link #showLw} and {@link #hideLw}.
261      *
262      * TODO: b/131253938 This will eventually be split into individual visibility policy flags.
263      */
264     static final int LEGACY_POLICY_VISIBILITY = 1;
265     /**
266      * The visibility flag that determines whether this window is visible for the current user.
267      */
268     private static final int VISIBLE_FOR_USER = 1 << 1;
269     private static final int POLICY_VISIBILITY_ALL = VISIBLE_FOR_USER | LEGACY_POLICY_VISIBILITY;
270     /**
271      * The Bitwise-or of flags that contribute to visibility of the WindowState
272      */
273     private int mPolicyVisibility = POLICY_VISIBILITY_ALL;
274 
275     /**
276      * Whether {@link #LEGACY_POLICY_VISIBILITY} flag should be set after a transition animation.
277      * For example, {@link #LEGACY_POLICY_VISIBILITY} might be set during an exit animation to hide
278      * it and then unset when the value of {@link #mLegacyPolicyVisibilityAfterAnim} is false
279      * after the exit animation is done.
280      *
281      * TODO: b/131253938 Determine whether this can be changed to use a visibility flag instead.
282      */
283     boolean mLegacyPolicyVisibilityAfterAnim = true;
284     // overlay window is hidden because the owning app is suspended
285     private boolean mHiddenWhileSuspended;
286     private boolean mAppOpVisibility = true;
287     boolean mPermanentlyHidden; // the window should never be shown again
288     // This is a non-system overlay window that is currently force hidden.
289     private boolean mForceHideNonSystemOverlayWindow;
290     boolean mAppFreezing;
291     boolean mHidden = true;    // Used to determine if to show child windows.
292     boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
293     private boolean mDragResizing;
294     private boolean mDragResizingChangeReported = true;
295     private int mResizeMode;
296     /**
297      * Special mode that is intended only for the rounded corner overlay: during rotation
298      * transition, we un-rotate the window token such that the window appears as it did before the
299      * rotation.
300      */
301     final boolean mForceSeamlesslyRotate;
302     SeamlessRotator mPendingSeamlessRotate;
303     long mFinishSeamlessRotateFrameNumber;
304 
305     private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
306 
307     /**
308      * The window size that was requested by the application.  These are in
309      * the application's coordinate space (without compatibility scale applied).
310      */
311     int mRequestedWidth;
312     int mRequestedHeight;
313     private int mLastRequestedWidth;
314     private int mLastRequestedHeight;
315 
316     int mLayer;
317     boolean mHaveFrame;
318     boolean mObscured;
319 
320     int mLayoutSeq = -1;
321 
322     /**
323      * Used to store last reported to client configuration and check if we have newer available.
324      * We'll send configuration to client only if it is different from the last applied one and
325      * client won't perform unnecessary updates.
326      */
327     private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration();
328 
329     /** @see #isLastConfigReportedToClient() */
330     private boolean mLastConfigReportedToClient;
331 
332     private final Configuration mTempConfiguration = new Configuration();
333 
334     /**
335      * The last content insets returned to the client in relayout. We use
336      * these in the bounds animation to ensure we only observe inset changes
337      * at the same time that a client resizes it's surface so that we may use
338      * the geometryAppliesWithResize synchronization mechanism to keep
339      * the contents in place.
340      */
341     final Rect mLastRelayoutContentInsets = new Rect();
342 
343     /**
344      * Set to true if we are waiting for this window to receive its
345      * given internal insets before laying out other windows based on it.
346      */
347     boolean mGivenInsetsPending;
348 
349     /**
350      * These are the content insets that were given during layout for
351      * this window, to be applied to windows behind it.
352      */
353     final Rect mGivenContentInsets = new Rect();
354 
355     /**
356      * These are the visible insets that were given during layout for
357      * this window, to be applied to windows behind it.
358      */
359     final Rect mGivenVisibleInsets = new Rect();
360 
361     /**
362      * This is the given touchable area relative to the window frame, or null if none.
363      */
364     final Region mGivenTouchableRegion = new Region();
365 
366     /**
367      * Flag indicating whether the touchable region should be adjusted by
368      * the visible insets; if false the area outside the visible insets is
369      * NOT touchable, so we must use those to adjust the frame during hit
370      * tests.
371      */
372     int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
373 
374     // Current transformation being applied.
375     float mGlobalScale=1;
376     float mInvGlobalScale=1;
377     float mHScale=1, mVScale=1;
378     float mLastHScale=1, mLastVScale=1;
379     final Matrix mTmpMatrix = new Matrix();
380 
381     private final WindowFrames mWindowFrames = new WindowFrames();
382 
383     /**
384      * Usually empty. Set to the task's tempInsetFrame. See
385      *{@link android.app.IActivityTaskManager#resizeDockedStack}.
386      */
387     private final Rect mInsetFrame = new Rect();
388 
389     /**
390      * List of rects where system gestures should be ignored.
391      *
392      * Coordinates are relative to the window's position.
393      */
394     private final List<Rect> mExclusionRects = new ArrayList<>();
395 
396     // If a window showing a wallpaper: the requested offset for the
397     // wallpaper; if a wallpaper window: the currently applied offset.
398     float mWallpaperX = -1;
399     float mWallpaperY = -1;
400 
401     // If a window showing a wallpaper: what fraction of the offset
402     // range corresponds to a full virtual screen.
403     float mWallpaperXStep = -1;
404     float mWallpaperYStep = -1;
405 
406     // If a window showing a wallpaper: a raw pixel offset to forcibly apply
407     // to its window; if a wallpaper window: not used.
408     int mWallpaperDisplayOffsetX = Integer.MIN_VALUE;
409     int mWallpaperDisplayOffsetY = Integer.MIN_VALUE;
410 
411     /**
412      * This is set after IWindowSession.relayout() has been called at
413      * least once for the window.  It allows us to detect the situation
414      * where we don't yet have a surface, but should have one soon, so
415      * we can give the window focus before waiting for the relayout.
416      */
417     boolean mRelayoutCalled;
418 
419     boolean mInRelayout;
420 
421     /**
422      * If the application has called relayout() with changes that can
423      * impact its window's size, we need to perform a layout pass on it
424      * even if it is not currently visible for layout.  This is set
425      * when in that case until the layout is done.
426      */
427     boolean mLayoutNeeded;
428 
429     /** Currently running an exit animation? */
430     boolean mAnimatingExit;
431 
432     /** Currently on the mDestroySurface list? */
433     boolean mDestroying;
434 
435     /** Completely remove from window manager after exit animation? */
436     boolean mRemoveOnExit;
437 
438     /**
439      * Whether the app died while it was visible, if true we might need
440      * to continue to show it until it's restarted.
441      */
442     boolean mAppDied;
443 
444     /**
445      * Set when the orientation is changing and this window has not yet
446      * been updated for the new orientation.
447      */
448     private boolean mOrientationChanging;
449 
450     /**
451      * Sometimes in addition to the mOrientationChanging
452      * flag we report that the orientation is changing
453      * due to a mismatch in current and reported configuration.
454      *
455      * In the case of timeout we still need to make sure we
456      * leave the orientation changing state though, so we
457      * use this as a special time out escape hatch.
458      */
459     private boolean mOrientationChangeTimedOut;
460 
461     /**
462      * The orientation during the last visible call to relayout. If our
463      * current orientation is different, the window can't be ready
464      * to be shown.
465      */
466     int mLastVisibleLayoutRotation = -1;
467 
468     /**
469      * Set when we need to report the orientation change to client to trigger a relayout.
470      */
471     boolean mReportOrientationChanged;
472 
473     /**
474      * How long we last kept the screen frozen.
475      */
476     int mLastFreezeDuration;
477 
478     /** Is this window now (or just being) removed? */
479     boolean mRemoved;
480 
481     /**
482      * It is save to remove the window and destroy the surface because the client requested removal
483      * or some other higher level component said so (e.g. activity manager).
484      * TODO: We should either have different booleans for the removal reason or use a bit-field.
485      */
486     boolean mWindowRemovalAllowed;
487 
488     // Input channel and input window handle used by the input dispatcher.
489     final InputWindowHandle mInputWindowHandle;
490     InputChannel mInputChannel;
491     private InputChannel mClientChannel;
492 
493     // Used to improve performance of toString()
494     private String mStringNameCache;
495     private CharSequence mLastTitle;
496     private boolean mWasExiting;
497 
498     final WindowStateAnimator mWinAnimator;
499 
500     boolean mHasSurface = false;
501 
502     /** When true this window can be displayed on screens owther than mOwnerUid's */
503     private boolean mShowToOwnerOnly;
504 
505     // Whether the window was visible when we set the app to invisible last time. WM uses
506     // this as a hint to restore the surface (if available) for early animation next time
507     // the app is brought visible.
508     private boolean mWasVisibleBeforeClientHidden;
509 
510     // This window will be replaced due to relaunch. This allows window manager
511     // to differentiate between simple removal of a window and replacement. In the latter case it
512     // will preserve the old window until the new one is drawn.
513     boolean mWillReplaceWindow = false;
514     // If true, the replaced window was already requested to be removed.
515     private boolean mReplacingRemoveRequested = false;
516     // Whether the replacement of the window should trigger app transition animation.
517     private boolean mAnimateReplacingWindow = false;
518     // If not null, the window that will be used to replace the old one. This is being set when
519     // the window is added and unset when this window reports its first draw.
520     private WindowState mReplacementWindow = null;
521     // For the new window in the replacement transition, if we have
522     // requested to replace without animation, then we should
523     // make sure we also don't apply an enter animation for
524     // the new window.
525     boolean mSkipEnterAnimationForSeamlessReplacement = false;
526     // Whether this window is being moved via the resize API
527     private boolean mMovedByResize;
528 
529     /**
530      * Wake lock for drawing.
531      * Even though it's slightly more expensive to do so, we will use a separate wake lock
532      * for each app that is requesting to draw while dozing so that we can accurately track
533      * who is preventing the system from suspending.
534      * This lock is only acquired on first use.
535      */
536     private PowerManager.WakeLock mDrawLock;
537 
538     private final Rect mTmpRect = new Rect();
539     private final Point mTmpPoint = new Point();
540 
541     /**
542      * Whether the window was resized by us while it was gone for layout.
543      */
544     boolean mResizedWhileGone = false;
545 
546     /**
547      * During seamless rotation we have two phases, first the old window contents
548      * are rotated to look as if they didn't move in the new coordinate system. Then we
549      * have to freeze updates to this layer (to preserve the transformation) until
550      * the resize actually occurs. This is true from when the transformation is set
551      * and false until the transaction to resize is sent.
552      */
553     boolean mSeamlesslyRotated = false;
554 
555     /**
556      * Surface insets from the previous call to relayout(), used to track
557      * if we are changing the Surface insets.
558      */
559     final Rect mLastSurfaceInsets = new Rect();
560 
561     /**
562      * A flag set by the {@link WindowState} parent to indicate that the parent has examined this
563      * {@link WindowState} in its overall drawing context. This book-keeping allows the parent to
564      * make sure all children have been considered.
565      */
566     private boolean mDrawnStateEvaluated;
567 
568     private final Point mSurfacePosition = new Point();
569 
570     /**
571      * A region inside of this window to be excluded from touch.
572      */
573     private TapExcludeRegionHolder mTapExcludeRegionHolder;
574 
575     /**
576      * Used for testing because the real PowerManager is final.
577      */
578     private PowerManagerWrapper mPowerManagerWrapper;
579 
580     /**
581      * A frame number in which changes requested in this layout will be rendered.
582      */
583     private long mFrameNumber = -1;
584 
585     private static final StringBuilder sTmpSB = new StringBuilder();
586 
587     /**
588      * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
589      * of z-order and 1 otherwise.
590      */
591     private static final Comparator<WindowState> sWindowSubLayerComparator =
592             new Comparator<WindowState>() {
593                 @Override
594                 public int compare(WindowState w1, WindowState w2) {
595                     final int layer1 = w1.mSubLayer;
596                     final int layer2 = w2.mSubLayer;
597                     if (layer1 < layer2 || (layer1 == layer2 && layer2 < 0 )) {
598                         // We insert the child window into the list ordered by
599                         // the sub-layer.  For same sub-layers, the negative one
600                         // should go below others; the positive one should go
601                         // above others.
602                         return -1;
603                     }
604                     return 1;
605                 };
606             };
607 
608     /**
609      * Indicates whether we have requested a Dim (in the sense of {@link Dimmer}) from our host
610      * container.
611      */
612     private boolean mIsDimming = false;
613 
614     private @Nullable InsetsSourceProvider mInsetProvider;
615 
616     private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
617 
seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation, @Rotation int rotation, boolean requested)618     void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation,
619             @Rotation int rotation, boolean requested) {
620         // Invisible windows and the wallpaper do not participate in the seamless rotation animation
621         if (!isVisibleNow() || mIsWallpaper) {
622             return;
623         }
624 
625         if (mPendingSeamlessRotate != null) {
626             oldRotation = mPendingSeamlessRotate.getOldRotation();
627         }
628 
629         if (mForceSeamlesslyRotate || requested) {
630             mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo());
631             mPendingSeamlessRotate.unrotate(transaction, this);
632             mWmService.markForSeamlessRotation(this, true);
633         }
634     }
635 
finishSeamlessRotation(boolean timeout)636     void finishSeamlessRotation(boolean timeout) {
637         if (mPendingSeamlessRotate != null) {
638             mPendingSeamlessRotate.finish(this, timeout);
639             mFinishSeamlessRotateFrameNumber = getFrameNumber();
640             mPendingSeamlessRotate = null;
641             mWmService.markForSeamlessRotation(this, false);
642         }
643     }
644 
getSystemGestureExclusion()645     List<Rect> getSystemGestureExclusion() {
646         return mExclusionRects;
647     }
648 
649     /**
650      * Sets the system gesture exclusion rects.
651      *
652      * @return {@code true} if anything changed
653      */
setSystemGestureExclusion(List<Rect> exclusionRects)654     boolean setSystemGestureExclusion(List<Rect> exclusionRects) {
655         if (mExclusionRects.equals(exclusionRects)) {
656             return false;
657         }
658         mExclusionRects.clear();
659         mExclusionRects.addAll(exclusionRects);
660         return true;
661     }
662 
isImplicitlyExcludingAllSystemGestures()663     boolean isImplicitlyExcludingAllSystemGestures() {
664         final int immersiveStickyFlags =
665                 SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
666         final boolean immersiveSticky =
667                 (mSystemUiVisibility & immersiveStickyFlags) == immersiveStickyFlags;
668         return immersiveSticky && mWmService.mSystemGestureExcludedByPreQStickyImmersive
669                 && mAppToken != null && mAppToken.mTargetSdk < Build.VERSION_CODES.Q;
670     }
671 
672     interface PowerManagerWrapper {
wakeUp(long time, @WakeReason int reason, String details)673         void wakeUp(long time, @WakeReason int reason, String details);
674 
isInteractive()675         boolean isInteractive();
676 
677     }
678 
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a, int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow)679     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
680             WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
681             int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
682         this(service, s, c, token, parentWindow, appOp, seq, a, viewVisibility, ownerId,
683                 ownerCanAddInternalSystemWindow, new PowerManagerWrapper() {
684                     @Override
685                     public void wakeUp(long time, @WakeReason int reason, String details) {
686                         service.mPowerManager.wakeUp(time, reason, details);
687                     }
688 
689                     @Override
690                     public boolean isInteractive() {
691                         return service.mPowerManager.isInteractive();
692                     }
693                 });
694     }
695 
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a, int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow, PowerManagerWrapper powerManagerWrapper)696     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
697             WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
698             int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow,
699             PowerManagerWrapper powerManagerWrapper) {
700         super(service);
701         mSession = s;
702         mClient = c;
703         mAppOp = appOp;
704         mToken = token;
705         mAppToken = mToken.asAppWindowToken();
706         mOwnerUid = ownerId;
707         mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
708         mWindowId = new WindowId(this);
709         mAttrs.copyFrom(a);
710         mLastSurfaceInsets.set(mAttrs.surfaceInsets);
711         mViewVisibility = viewVisibility;
712         mPolicy = mWmService.mPolicy;
713         mContext = mWmService.mContext;
714         DeathRecipient deathRecipient = new DeathRecipient();
715         mSeq = seq;
716         mPowerManagerWrapper = powerManagerWrapper;
717         mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
718         if (localLOGV) Slog.v(
719             TAG, "Window " + this + " client=" + c.asBinder()
720             + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
721         try {
722             c.asBinder().linkToDeath(deathRecipient, 0);
723         } catch (RemoteException e) {
724             mDeathRecipient = null;
725             mIsChildWindow = false;
726             mLayoutAttached = false;
727             mIsImWindow = false;
728             mIsWallpaper = false;
729             mIsFloatingLayer = false;
730             mBaseLayer = 0;
731             mSubLayer = 0;
732             mInputWindowHandle = null;
733             mWinAnimator = null;
734             return;
735         }
736         mDeathRecipient = deathRecipient;
737 
738         if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
739             // The multiplier here is to reserve space for multiple
740             // windows in the same type layer.
741             mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)
742                     * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
743             mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
744             mIsChildWindow = true;
745 
746             if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + parentWindow);
747             parentWindow.addChild(this, sWindowSubLayerComparator);
748 
749             mLayoutAttached = mAttrs.type !=
750                     WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
751             mIsImWindow = parentWindow.mAttrs.type == TYPE_INPUT_METHOD
752                     || parentWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
753             mIsWallpaper = parentWindow.mAttrs.type == TYPE_WALLPAPER;
754         } else {
755             // The multiplier here is to reserve space for multiple
756             // windows in the same type layer.
757             mBaseLayer = mPolicy.getWindowLayerLw(this)
758                     * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
759             mSubLayer = 0;
760             mIsChildWindow = false;
761             mLayoutAttached = false;
762             mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
763                     || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
764             mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
765         }
766         mIsFloatingLayer = mIsImWindow || mIsWallpaper;
767 
768         if (mAppToken != null && mAppToken.mShowForAllUsers) {
769             // Windows for apps that can show for all users should also show when the device is
770             // locked.
771             mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
772         }
773 
774         mWinAnimator = new WindowStateAnimator(this);
775         mWinAnimator.mAlpha = a.alpha;
776 
777         mRequestedWidth = 0;
778         mRequestedHeight = 0;
779         mLastRequestedWidth = 0;
780         mLastRequestedHeight = 0;
781         mLayer = 0;
782         mInputWindowHandle = new InputWindowHandle(
783                 mAppToken != null ? mAppToken.mInputApplicationHandle : null, c,
784                     getDisplayId());
785     }
786 
attach()787     void attach() {
788         if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
789         mSession.windowAddedLocked(mAttrs.packageName);
790     }
791 
792     /**
793      * @return {@code true} if the application runs in size compatibility mode.
794      * @see android.content.res.CompatibilityInfo#supportsScreen
795      * @see ActivityRecord#inSizeCompatMode
796      */
inSizeCompatMode()797     boolean inSizeCompatMode() {
798         return (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0
799                 || (mAppToken != null && mAppToken.inSizeCompatMode()
800                         // Exclude starting window because it is not displayed by the application.
801                         && mAttrs.type != TYPE_APPLICATION_STARTING);
802     }
803 
804     /**
805      * Returns whether this {@link WindowState} has been considered for drawing by its parent.
806      */
getDrawnStateEvaluated()807     boolean getDrawnStateEvaluated() {
808         return mDrawnStateEvaluated;
809     }
810 
811     /**
812      * Sets whether this {@link WindowState} has been considered for drawing by its parent. Should
813      * be cleared when detached from parent.
814      */
setDrawnStateEvaluated(boolean evaluated)815     void setDrawnStateEvaluated(boolean evaluated) {
816         mDrawnStateEvaluated = evaluated;
817     }
818 
819     @Override
onParentChanged()820     void onParentChanged() {
821         super.onParentChanged();
822         setDrawnStateEvaluated(false /*evaluated*/);
823 
824         getDisplayContent().reapplyMagnificationSpec();
825     }
826 
827     @Override
getOwningUid()828     public int getOwningUid() {
829         return mOwnerUid;
830     }
831 
832     @Override
getOwningPackage()833     public String getOwningPackage() {
834         return mAttrs.packageName;
835     }
836 
837     @Override
canAddInternalSystemWindow()838     public boolean canAddInternalSystemWindow() {
839         return mOwnerCanAddInternalSystemWindow;
840     }
841 
842     @Override
canAcquireSleepToken()843     public boolean canAcquireSleepToken() {
844         return mSession.mCanAcquireSleepToken;
845     }
846 
847     /**
848      * Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame}
849      * from {@param frame}. In other words, it applies the insets that would result if
850      * {@param frame} would be shifted to {@param layoutFrame} and then applying the insets from
851      * {@param insetFrame}. Also it respects {@param displayFrame} in case window has minimum
852      * width/height applied and insets should be overridden.
853      */
subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame, Rect displayFrame)854     private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame, Rect displayFrame) {
855         final int left = Math.max(0, insetFrame.left - Math.max(layoutFrame.left, displayFrame.left));
856         final int top = Math.max(0, insetFrame.top - Math.max(layoutFrame.top, displayFrame.top));
857         final int right = Math.max(0, Math.min(layoutFrame.right, displayFrame.right) - insetFrame.right);
858         final int bottom = Math.max(0, Math.min(layoutFrame.bottom, displayFrame.bottom) - insetFrame.bottom);
859         frame.inset(left, top, right, bottom);
860     }
861 
862     @Override
getDisplayedBounds()863     public Rect getDisplayedBounds() {
864         final Task task = getTask();
865         if (task != null) {
866             Rect bounds = task.getOverrideDisplayedBounds();
867             if (!bounds.isEmpty()) {
868                 return bounds;
869             }
870         }
871         return super.getDisplayedBounds();
872     }
873 
874     @Override
computeFrameLw()875     public void computeFrameLw() {
876         if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
877             // This window is being replaced and either already got information that it's being
878             // removed or we are still waiting for some information. Because of this we don't
879             // want to apply any more changes to it, so it remains in this state until new window
880             // appears.
881             return;
882         }
883         mHaveFrame = true;
884 
885         final Task task = getTask();
886         final boolean isFullscreenAndFillsDisplay = !inMultiWindowMode() && matchesDisplayBounds();
887         final boolean windowsAreFloating = task != null && task.isFloating();
888         final DisplayContent dc = getDisplayContent();
889 
890         mInsetFrame.set(getBounds());
891 
892         // Denotes the actual frame used to calculate the insets and to perform the layout. When
893         // resizing in docked mode, we'd like to freeze the layout, so we also need to freeze the
894         // insets temporarily. By the notion of a task having a different layout frame, we can
895         // achieve that while still moving the task around.
896         final Rect layoutContainingFrame;
897         final Rect layoutDisplayFrame;
898 
899         // The offset from the layout containing frame to the actual containing frame.
900         final int layoutXDiff;
901         final int layoutYDiff;
902         final WindowState imeWin = mWmService.mRoot.getCurrentInputMethodWindow();
903         final boolean isImeTarget =
904                 imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget();
905         if (isFullscreenAndFillsDisplay || layoutInParentFrame()) {
906             // We use the parent frame as the containing frame for fullscreen and child windows
907             mWindowFrames.mContainingFrame.set(mWindowFrames.mParentFrame);
908             layoutDisplayFrame = mWindowFrames.mDisplayFrame;
909             layoutContainingFrame = mWindowFrames.mParentFrame;
910             layoutXDiff = 0;
911             layoutYDiff = 0;
912         } else {
913             mWindowFrames.mContainingFrame.set(getDisplayedBounds());
914             if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
915 
916                 // If the bounds are frozen, we still want to translate the window freely and only
917                 // freeze the size.
918                 Rect frozen = mAppToken.mFrozenBounds.peek();
919                 mWindowFrames.mContainingFrame.right =
920                         mWindowFrames.mContainingFrame.left + frozen.width();
921                 mWindowFrames.mContainingFrame.bottom =
922                         mWindowFrames.mContainingFrame.top + frozen.height();
923             }
924             // IME is up and obscuring this window. Adjust the window position so it is visible.
925             if (isImeTarget) {
926                 if (inFreeformWindowingMode()) {
927                     // Push the freeform window up to make room for the IME. However, don't push
928                     // it up past the top of the screen.
929                     final int bottomOverlap = mWindowFrames.mContainingFrame.bottom
930                             - mWindowFrames.mVisibleFrame.bottom;
931                     if (bottomOverlap > 0) {
932                         final int distanceToTop = Math.max(mWindowFrames.mContainingFrame.top
933                                 - mWindowFrames.mDisplayFrame.top, 0);
934                         int offs = Math.min(bottomOverlap, distanceToTop);
935                         mWindowFrames.mContainingFrame.top -= offs;
936                     }
937                 } else if (!inPinnedWindowingMode() && mWindowFrames.mContainingFrame.bottom
938                         > mWindowFrames.mParentFrame.bottom) {
939                     // But in docked we want to behave like fullscreen and behave as if the task
940                     // were given smaller bounds for the purposes of layout. Skip adjustments for
941                     // the pinned stack, they are handled separately in the PinnedStackController.
942                     mWindowFrames.mContainingFrame.bottom = mWindowFrames.mParentFrame.bottom;
943                 }
944             }
945 
946             if (windowsAreFloating) {
947                 // In floating modes (e.g. freeform, pinned) we have only to set the rectangle
948                 // if it wasn't set already. No need to intersect it with the (visible)
949                 // "content frame" since it is allowed to be outside the visible desktop.
950                 if (mWindowFrames.mContainingFrame.isEmpty()) {
951                     mWindowFrames.mContainingFrame.set(mWindowFrames.mContentFrame);
952                 }
953             }
954 
955             final TaskStack stack = getStack();
956             if (inPinnedWindowingMode() && stack != null
957                     && stack.lastAnimatingBoundsWasToFullscreen()) {
958                 // PIP edge case: When going from pinned to fullscreen, we apply a
959                 // tempInsetFrame for the full task - but we're still at the start of the animation.
960                 // To prevent a jump if there's a letterbox, restrict to the parent frame.
961                 mInsetFrame.intersectUnchecked(mWindowFrames.mParentFrame);
962                 mWindowFrames.mContainingFrame.intersectUnchecked(mWindowFrames.mParentFrame);
963             }
964 
965             layoutDisplayFrame = new Rect(mWindowFrames.mDisplayFrame);
966             mWindowFrames.mDisplayFrame.set(mWindowFrames.mContainingFrame);
967             layoutXDiff = mInsetFrame.left - mWindowFrames.mContainingFrame.left;
968             layoutYDiff = mInsetFrame.top - mWindowFrames.mContainingFrame.top;
969             layoutContainingFrame = mInsetFrame;
970             mTmpRect.set(0, 0, dc.getDisplayInfo().logicalWidth, dc.getDisplayInfo().logicalHeight);
971             subtractInsets(mWindowFrames.mDisplayFrame, layoutContainingFrame, layoutDisplayFrame,
972                     mTmpRect);
973             if (!layoutInParentFrame()) {
974                 subtractInsets(mWindowFrames.mContainingFrame, layoutContainingFrame,
975                         mWindowFrames.mParentFrame, mTmpRect);
976                 subtractInsets(mInsetFrame, layoutContainingFrame, mWindowFrames.mParentFrame,
977                         mTmpRect);
978             }
979             layoutDisplayFrame.intersect(layoutContainingFrame);
980         }
981 
982         final int pw = mWindowFrames.mContainingFrame.width();
983         final int ph = mWindowFrames.mContainingFrame.height();
984 
985         if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
986             mLastRequestedWidth = mRequestedWidth;
987             mLastRequestedHeight = mRequestedHeight;
988             mWindowFrames.setContentChanged(true);
989         }
990 
991         final int fw = mWindowFrames.mFrame.width();
992         final int fh = mWindowFrames.mFrame.height();
993 
994         applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
995 
996         // Calculate the outsets before the content frame gets shrinked to the window frame.
997         mWindowFrames.calculateOutsets();
998 
999         // Make sure the content and visible frames are inside of the
1000         // final window frame.
1001         if (windowsAreFloating && !mWindowFrames.mFrame.isEmpty()) {
1002             final int visBottom = mWindowFrames.mVisibleFrame.bottom;
1003             final int contentBottom = mWindowFrames.mContentFrame.bottom;
1004             mWindowFrames.mContentFrame.set(mWindowFrames.mFrame);
1005             mWindowFrames.mVisibleFrame.set(mWindowFrames.mContentFrame);
1006             mWindowFrames.mStableFrame.set(mWindowFrames.mContentFrame);
1007             if (isImeTarget && inFreeformWindowingMode()) {
1008                 // After displacing a freeform window to make room for the ime, any part of
1009                 // the window still covered by IME should be inset.
1010                 if (contentBottom + layoutYDiff < mWindowFrames.mContentFrame.bottom) {
1011                     mWindowFrames.mContentFrame.bottom = contentBottom + layoutYDiff;
1012                 }
1013                 if (visBottom + layoutYDiff < mWindowFrames.mVisibleFrame.bottom) {
1014                     mWindowFrames.mVisibleFrame.bottom = visBottom + layoutYDiff;
1015                 }
1016             }
1017         } else if (mAttrs.type == TYPE_DOCK_DIVIDER) {
1018             dc.getDockedDividerController().positionDockedStackedDivider(mWindowFrames.mFrame);
1019             mWindowFrames.mContentFrame.set(mWindowFrames.mFrame);
1020             if (!mWindowFrames.mFrame.equals(mWindowFrames.mLastFrame)) {
1021                 mMovedByResize = true;
1022             }
1023         } else {
1024             mWindowFrames.mContentFrame.set(
1025                     Math.max(mWindowFrames.mContentFrame.left, mWindowFrames.mFrame.left),
1026                     Math.max(mWindowFrames.mContentFrame.top, mWindowFrames.mFrame.top),
1027                     Math.min(mWindowFrames.mContentFrame.right, mWindowFrames.mFrame.right),
1028                     Math.min(mWindowFrames.mContentFrame.bottom, mWindowFrames.mFrame.bottom));
1029 
1030             mWindowFrames.mVisibleFrame.set(
1031                     Math.max(mWindowFrames.mVisibleFrame.left, mWindowFrames.mFrame.left),
1032                     Math.max(mWindowFrames.mVisibleFrame.top, mWindowFrames.mFrame.top),
1033                     Math.min(mWindowFrames.mVisibleFrame.right, mWindowFrames.mFrame.right),
1034                     Math.min(mWindowFrames.mVisibleFrame.bottom, mWindowFrames.mFrame.bottom));
1035 
1036             mWindowFrames.mStableFrame.set(
1037                     Math.max(mWindowFrames.mStableFrame.left, mWindowFrames.mFrame.left),
1038                     Math.max(mWindowFrames.mStableFrame.top, mWindowFrames.mFrame.top),
1039                     Math.min(mWindowFrames.mStableFrame.right, mWindowFrames.mFrame.right),
1040                     Math.min(mWindowFrames.mStableFrame.bottom, mWindowFrames.mFrame.bottom));
1041         }
1042 
1043         if (isFullscreenAndFillsDisplay && !windowsAreFloating) {
1044             // Windows that are not fullscreen can be positioned outside of the display frame,
1045             // but that is not a reason to provide them with overscan insets.
1046             InsetUtils.insetsBetweenFrames(layoutContainingFrame, mWindowFrames.mOverscanFrame,
1047                     mWindowFrames.mOverscanInsets);
1048         }
1049 
1050         if (mAttrs.type == TYPE_DOCK_DIVIDER) {
1051             final WmDisplayCutout c = mWindowFrames.mDisplayCutout.calculateRelativeTo(
1052                     mWindowFrames.mDisplayFrame);
1053             mWindowFrames.calculateDockedDividerInsets(c.getDisplayCutout().getSafeInsets());
1054         } else {
1055             getDisplayContent().getBounds(mTmpRect);
1056             mWindowFrames.calculateInsets(
1057                     windowsAreFloating, isFullscreenAndFillsDisplay, mTmpRect);
1058         }
1059 
1060         mWindowFrames.setDisplayCutout(
1061                 mWindowFrames.mDisplayCutout.calculateRelativeTo(mWindowFrames.mFrame));
1062 
1063         // Offset the actual frame by the amount layout frame is off.
1064         mWindowFrames.offsetFrames(-layoutXDiff, -layoutYDiff);
1065 
1066         mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame);
1067         if (inSizeCompatMode()) {
1068             // If there is a size compatibility scale being applied to the
1069             // window, we need to apply this to its insets so that they are
1070             // reported to the app in its coordinate space.
1071             mWindowFrames.scaleInsets(mInvGlobalScale);
1072 
1073             // Also the scaled frame that we report to the app needs to be
1074             // adjusted to be in its coordinate space.
1075             mWindowFrames.mCompatFrame.scale(mInvGlobalScale);
1076         }
1077 
1078         if (mIsWallpaper && (fw != mWindowFrames.mFrame.width()
1079                 || fh != mWindowFrames.mFrame.height())) {
1080             final DisplayContent displayContent = getDisplayContent();
1081             if (displayContent != null) {
1082                 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
1083                 getDisplayContent().mWallpaperController.updateWallpaperOffset(this,
1084                         displayInfo.logicalWidth, displayInfo.logicalHeight, false);
1085             }
1086         }
1087 
1088         if (DEBUG_LAYOUT || localLOGV) Slog.v(TAG,
1089                 "Resolving (mRequestedWidth="
1090                 + mRequestedWidth + ", mRequestedheight="
1091                 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
1092                 + "): frame=" + mWindowFrames.mFrame.toShortString()
1093                 + " " + mWindowFrames.getInsetsInfo()
1094                 + " " + mAttrs.getTitle());
1095     }
1096 
1097     // TODO: Look into whether this override is still necessary.
1098     @Override
getBounds()1099     public Rect getBounds() {
1100         if (mAppToken != null) {
1101             return mAppToken.getBounds();
1102         } else {
1103             return super.getBounds();
1104         }
1105     }
1106 
1107     @Override
getFrameLw()1108     public Rect getFrameLw() {
1109         return mWindowFrames.mFrame;
1110     }
1111 
1112     @Override
getDisplayFrameLw()1113     public Rect getDisplayFrameLw() {
1114         return mWindowFrames.mDisplayFrame;
1115     }
1116 
1117     @Override
getOverscanFrameLw()1118     public Rect getOverscanFrameLw() {
1119         return mWindowFrames.mOverscanFrame;
1120     }
1121 
1122     @Override
getContentFrameLw()1123     public Rect getContentFrameLw() {
1124         return mWindowFrames.mContentFrame;
1125     }
1126 
1127     @Override
getVisibleFrameLw()1128     public Rect getVisibleFrameLw() {
1129         return mWindowFrames.mVisibleFrame;
1130     }
1131 
getStableFrameLw()1132     Rect getStableFrameLw() {
1133         return mWindowFrames.mStableFrame;
1134     }
1135 
getDecorFrame()1136     Rect getDecorFrame() {
1137         return mWindowFrames.mDecorFrame;
1138     }
1139 
getParentFrame()1140     Rect getParentFrame() {
1141         return mWindowFrames.mParentFrame;
1142     }
1143 
getContainingFrame()1144     Rect getContainingFrame() {
1145         return mWindowFrames.mContainingFrame;
1146     }
1147 
getWmDisplayCutout()1148     WmDisplayCutout getWmDisplayCutout() {
1149         return mWindowFrames.mDisplayCutout;
1150     }
1151 
getCompatFrame(Rect outFrame)1152     void getCompatFrame(Rect outFrame) {
1153         outFrame.set(mWindowFrames.mCompatFrame);
1154     }
1155 
getCompatFrameSize(Rect outFrame)1156     void getCompatFrameSize(Rect outFrame) {
1157         outFrame.set(0, 0, mWindowFrames.mCompatFrame.width(), mWindowFrames.mCompatFrame.height());
1158     }
1159 
1160     @Override
getGivenInsetsPendingLw()1161     public boolean getGivenInsetsPendingLw() {
1162         return mGivenInsetsPending;
1163     }
1164 
1165     @Override
getGivenContentInsetsLw()1166     public Rect getGivenContentInsetsLw() {
1167         return mGivenContentInsets;
1168     }
1169 
1170     @Override
getGivenVisibleInsetsLw()1171     public Rect getGivenVisibleInsetsLw() {
1172         return mGivenVisibleInsets;
1173     }
1174 
1175     @Override
getAttrs()1176     public WindowManager.LayoutParams getAttrs() {
1177         return mAttrs;
1178     }
1179 
1180     @Override
getNeedsMenuLw(WindowManagerPolicy.WindowState bottom)1181     public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) {
1182         return getDisplayContent().getNeedsMenu(this, bottom);
1183     }
1184 
1185     @Override
getSystemUiVisibility()1186     public int getSystemUiVisibility() {
1187         return mSystemUiVisibility;
1188     }
1189 
1190     @Override
getSurfaceLayer()1191     public int getSurfaceLayer() {
1192         return mLayer;
1193     }
1194 
1195     @Override
getBaseType()1196     public int getBaseType() {
1197         return getTopParentWindow().mAttrs.type;
1198     }
1199 
1200     @Override
getAppToken()1201     public IApplicationToken getAppToken() {
1202         return mAppToken != null ? mAppToken.appToken : null;
1203     }
1204 
1205     @Override
isVoiceInteraction()1206     public boolean isVoiceInteraction() {
1207         return mAppToken != null && mAppToken.mVoiceInteraction;
1208     }
1209 
setReportResizeHints()1210     boolean setReportResizeHints() {
1211         return mWindowFrames.setReportResizeHints();
1212     }
1213 
1214     /**
1215      * Adds the window to the resizing list if any of the parameters we use to track the window
1216      * dimensions or insets have changed.
1217      */
updateResizingWindowIfNeeded()1218     void updateResizingWindowIfNeeded() {
1219         final WindowStateAnimator winAnimator = mWinAnimator;
1220         if (!mHasSurface || getDisplayContent().mLayoutSeq != mLayoutSeq || isGoneForLayoutLw()) {
1221             return;
1222         }
1223 
1224         final Task task = getTask();
1225         // In the case of stack bound animations, the window frames will update (unlike other
1226         // animations which just modify various transformation properties). We don't want to
1227         // notify the client of frame changes in this case. Not only is it a lot of churn, but
1228         // the frame may not correspond to the surface size or the onscreen area at various
1229         // phases in the animation, and the client will become sad and confused.
1230         if (task != null && task.mStack.isAnimatingBounds()) {
1231             return;
1232         }
1233 
1234         boolean didFrameInsetsChange = setReportResizeHints();
1235         boolean configChanged = !isLastConfigReportedToClient();
1236         if (DEBUG_CONFIGURATION && configChanged) {
1237             Slog.v(TAG_WM, "Win " + this + " config changed: " + getConfiguration());
1238         }
1239 
1240         final boolean dragResizingChanged = isDragResizeChanged()
1241                 && !isDragResizingChangeReported();
1242 
1243         if (localLOGV) Slog.v(TAG_WM, "Resizing " + this + ": configChanged=" + configChanged
1244                 + " dragResizingChanged=" + dragResizingChanged
1245                 + " last=" + mWindowFrames.mLastFrame + " frame=" + mWindowFrames.mFrame);
1246 
1247         // We update mLastFrame always rather than in the conditional with the last inset
1248         // variables, because mFrameSizeChanged only tracks the width and height changing.
1249         mWindowFrames.mLastFrame.set(mWindowFrames.mFrame);
1250 
1251         if (didFrameInsetsChange
1252                 || winAnimator.mSurfaceResized
1253                 || configChanged
1254                 || dragResizingChanged
1255                 || mReportOrientationChanged) {
1256             if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
1257                 Slog.v(TAG_WM, "Resize reasons for w=" + this + ": "
1258                         + " " + mWindowFrames.getInsetsChangedInfo()
1259                         + " surfaceResized=" + winAnimator.mSurfaceResized
1260                         + " configChanged=" + configChanged
1261                         + " dragResizingChanged=" + dragResizingChanged
1262                         + " reportOrientationChanged=" + mReportOrientationChanged);
1263             }
1264 
1265             // If it's a dead window left on screen, and the configuration changed, there is nothing
1266             // we can do about it. Remove the window now.
1267             if (mAppToken != null && mAppDied) {
1268                 mAppToken.removeDeadWindows();
1269                 return;
1270             }
1271 
1272             updateLastInsetValues();
1273             mWmService.makeWindowFreezingScreenIfNeededLocked(this);
1274 
1275             // If the orientation is changing, or we're starting or ending a drag resizing action,
1276             // then we need to hold off on unfreezing the display until this window has been
1277             // redrawn; to do that, we need to go through the process of getting informed by the
1278             // application when it has finished drawing.
1279             if (getOrientationChanging() || dragResizingChanged) {
1280                 if (DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
1281                     Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
1282                             + ", mDrawState=DRAW_PENDING in " + this
1283                             + ", surfaceController " + winAnimator.mSurfaceController);
1284                 }
1285                 winAnimator.mDrawState = DRAW_PENDING;
1286                 if (mAppToken != null) {
1287                     mAppToken.clearAllDrawn();
1288                 }
1289             }
1290             if (!mWmService.mResizingWindows.contains(this)) {
1291                 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM, "Resizing window " + this);
1292                 mWmService.mResizingWindows.add(this);
1293             }
1294         } else if (getOrientationChanging()) {
1295             if (isDrawnLw()) {
1296                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Orientation not waiting for draw in "
1297                         + this + ", surfaceController " + winAnimator.mSurfaceController);
1298                 setOrientationChanging(false);
1299                 mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
1300                         - mWmService.mDisplayFreezeTime);
1301             }
1302         }
1303     }
1304 
getOrientationChanging()1305     boolean getOrientationChanging() {
1306         // In addition to the local state flag, we must also consider the difference in the last
1307         // reported configuration vs. the current state. If the client code has not been informed of
1308         // the change, logic dependent on having finished processing the orientation, such as
1309         // unfreezing, could be improperly triggered.
1310         // TODO(b/62846907): Checking against {@link mLastReportedConfiguration} could be flaky as
1311         //                   this is not necessarily what the client has processed yet. Find a
1312         //                   better indicator consistent with the client.
1313         return (mOrientationChanging || (isVisible()
1314                 && getConfiguration().orientation != getLastReportedConfiguration().orientation))
1315                 && !mSeamlesslyRotated
1316                 && !mOrientationChangeTimedOut;
1317     }
1318 
setOrientationChanging(boolean changing)1319     void setOrientationChanging(boolean changing) {
1320         mOrientationChanging = changing;
1321         mOrientationChangeTimedOut = false;
1322     }
1323 
orientationChangeTimedOut()1324     void orientationChangeTimedOut() {
1325         mOrientationChangeTimedOut = true;
1326     }
1327 
1328     @Override
getDisplayContent()1329     DisplayContent getDisplayContent() {
1330         return mToken.getDisplayContent();
1331     }
1332 
1333     @Override
onDisplayChanged(DisplayContent dc)1334     void onDisplayChanged(DisplayContent dc) {
1335         super.onDisplayChanged(dc);
1336         // Window was not laid out for this display yet, so make sure mLayoutSeq does not match.
1337         if (dc != null && mInputWindowHandle.displayId != dc.getDisplayId()) {
1338             mLayoutSeq = dc.mLayoutSeq - 1;
1339             mInputWindowHandle.displayId = dc.getDisplayId();
1340         }
1341     }
1342 
getDisplayInfo()1343     DisplayInfo getDisplayInfo() {
1344         final DisplayContent displayContent = getDisplayContent();
1345         return displayContent != null ? displayContent.getDisplayInfo() : null;
1346     }
1347 
1348     @Override
getDisplayId()1349     public int getDisplayId() {
1350         final DisplayContent displayContent = getDisplayContent();
1351         if (displayContent == null) {
1352             return Display.INVALID_DISPLAY;
1353         }
1354         return displayContent.getDisplayId();
1355     }
1356 
getTask()1357     Task getTask() {
1358         return mAppToken != null ? mAppToken.getTask() : null;
1359     }
1360 
getStack()1361     TaskStack getStack() {
1362         Task task = getTask();
1363         if (task != null) {
1364             if (task.mStack != null) {
1365                 return task.mStack;
1366             }
1367         }
1368         // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
1369         // associate them with some stack to enable dimming.
1370         final DisplayContent dc = getDisplayContent();
1371         return mAttrs.type >= FIRST_SYSTEM_WINDOW && dc != null ? dc.getHomeStack() : null;
1372     }
1373 
1374     /**
1375      * Retrieves the visible bounds of the window.
1376      * @param bounds The rect which gets the bounds.
1377      */
getVisibleBounds(Rect bounds)1378     void getVisibleBounds(Rect bounds) {
1379         final Task task = getTask();
1380         boolean intersectWithStackBounds = task != null && task.cropWindowsToStackBounds();
1381         bounds.setEmpty();
1382         mTmpRect.setEmpty();
1383         if (intersectWithStackBounds) {
1384             final TaskStack stack = task.mStack;
1385             if (stack != null) {
1386                 stack.getDimBounds(mTmpRect);
1387             } else {
1388                 intersectWithStackBounds = false;
1389             }
1390         }
1391 
1392         bounds.set(mWindowFrames.mVisibleFrame);
1393         if (intersectWithStackBounds) {
1394             bounds.intersect(mTmpRect);
1395         }
1396 
1397         if (bounds.isEmpty()) {
1398             bounds.set(mWindowFrames.mFrame);
1399             if (intersectWithStackBounds) {
1400                 bounds.intersect(mTmpRect);
1401             }
1402             return;
1403         }
1404     }
1405 
getInputDispatchingTimeoutNanos()1406     public long getInputDispatchingTimeoutNanos() {
1407         return mAppToken != null
1408                 ? mAppToken.mInputDispatchingTimeoutNanos
1409                 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
1410     }
1411 
1412     @Override
hasAppShownWindows()1413     public boolean hasAppShownWindows() {
1414         return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed);
1415     }
1416 
isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy)1417     boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
1418         if (dsdx < .99999f || dsdx > 1.00001f) return false;
1419         if (dtdy < .99999f || dtdy > 1.00001f) return false;
1420         if (dtdx < -.000001f || dtdx > .000001f) return false;
1421         if (dsdy < -.000001f || dsdy > .000001f) return false;
1422         return true;
1423     }
1424 
prelayout()1425     void prelayout() {
1426         if (inSizeCompatMode()) {
1427             mGlobalScale = mToken.getSizeCompatScale();
1428             mInvGlobalScale = 1 / mGlobalScale;
1429         } else {
1430             mGlobalScale = mInvGlobalScale = 1;
1431         }
1432     }
1433 
1434     @Override
hasContentToDisplay()1435     boolean hasContentToDisplay() {
1436         if (!mAppFreezing && isDrawnLw() && (mViewVisibility == View.VISIBLE
1437                 || (isAnimating() && !getDisplayContent().mAppTransition.isTransitionSet()))) {
1438             return true;
1439         }
1440 
1441         return super.hasContentToDisplay();
1442     }
1443 
1444     @Override
isVisible()1445     boolean isVisible() {
1446         return wouldBeVisibleIfPolicyIgnored() && isVisibleByPolicy()
1447                 // If we don't have a provider, this window isn't used as a window generating
1448                 // insets, so nobody can hide it over the inset APIs.
1449                 && (mInsetProvider == null || mInsetProvider.isClientVisible());
1450     }
1451 
1452     /**
1453      * Ensures that all the policy visibility bits are set.
1454      * @return {@code true} if all flags about visiblity are set
1455      */
isVisibleByPolicy()1456     boolean isVisibleByPolicy() {
1457         return (mPolicyVisibility & POLICY_VISIBILITY_ALL) == POLICY_VISIBILITY_ALL;
1458     }
1459 
clearPolicyVisibilityFlag(int policyVisibilityFlag)1460     void clearPolicyVisibilityFlag(int policyVisibilityFlag) {
1461         mPolicyVisibility &= ~policyVisibilityFlag;
1462         mWmService.scheduleAnimationLocked();
1463     }
1464 
setPolicyVisibilityFlag(int policyVisibilityFlag)1465     void setPolicyVisibilityFlag(int policyVisibilityFlag) {
1466         mPolicyVisibility |= policyVisibilityFlag;
1467         mWmService.scheduleAnimationLocked();
1468     }
1469 
isLegacyPolicyVisibility()1470     private boolean isLegacyPolicyVisibility() {
1471         return (mPolicyVisibility & LEGACY_POLICY_VISIBILITY) != 0;
1472     }
1473 
1474     /**
1475      * @return {@code true} if the window would be visible if we'd ignore policy visibility,
1476      *         {@code false} otherwise.
1477      */
wouldBeVisibleIfPolicyIgnored()1478     boolean wouldBeVisibleIfPolicyIgnored() {
1479         return mHasSurface && !isParentWindowHidden()
1480                 && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible);
1481     }
1482 
1483     @Override
isVisibleLw()1484     public boolean isVisibleLw() {
1485         return isVisible();
1486     }
1487 
1488     /**
1489      * Is this window visible, ignoring its app token? It is not visible if there is no surface,
1490      * or we are in the process of running an exit animation that will remove the surface.
1491      */
1492     // TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this?
isWinVisibleLw()1493     boolean isWinVisibleLw() {
1494         return (mAppToken == null || !mAppToken.hiddenRequested || mAppToken.isSelfAnimating())
1495                 && isVisible();
1496     }
1497 
1498     /**
1499      * The same as isVisible(), but follows the current hidden state of the associated app token,
1500      * not the pending requested hidden state.
1501      */
isVisibleNow()1502     boolean isVisibleNow() {
1503         return (!mToken.isHidden() || mAttrs.type == TYPE_APPLICATION_STARTING)
1504                 && isVisible();
1505     }
1506 
1507     /**
1508      * Can this window possibly be a drag/drop target?  The test here is
1509      * a combination of the above "visible now" with the check that the
1510      * Input Manager uses when discarding windows from input consideration.
1511      */
isPotentialDragTarget()1512     boolean isPotentialDragTarget() {
1513         return isVisibleNow() && !mRemoved
1514                 && mInputChannel != null && mInputWindowHandle != null;
1515     }
1516 
1517     /**
1518      * Same as isVisible(), but we also count it as visible between the
1519      * call to IWindowSession.add() and the first relayout().
1520      */
isVisibleOrAdding()1521     boolean isVisibleOrAdding() {
1522         final AppWindowToken atoken = mAppToken;
1523         return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
1524                 && isVisibleByPolicy() && !isParentWindowHidden()
1525                 && (atoken == null || !atoken.hiddenRequested)
1526                 && !mAnimatingExit && !mDestroying;
1527     }
1528 
1529     /**
1530      * Is this window currently on-screen?  It is on-screen either if it
1531      * is visible or it is currently running an animation before no longer
1532      * being visible.
1533      */
isOnScreen()1534     boolean isOnScreen() {
1535         if (!mHasSurface || mDestroying || !isVisibleByPolicy()) {
1536             return false;
1537         }
1538         final AppWindowToken atoken = mAppToken;
1539         if (atoken != null) {
1540             return ((!isParentWindowHidden() && !atoken.hiddenRequested)
1541                     || isAnimating());
1542         }
1543         return !isParentWindowHidden() || isAnimating();
1544     }
1545 
1546     /**
1547      * Whether this window's drawn state might affect the drawn states of the app token.
1548      *
1549      * @return true if the window should be considered while evaluating allDrawn flags.
1550      */
mightAffectAllDrawn()1551     boolean mightAffectAllDrawn() {
1552         final boolean isAppType = mWinAnimator.mAttrType == TYPE_BASE_APPLICATION
1553                 || mWinAnimator.mAttrType == TYPE_DRAWN_APPLICATION;
1554         return (isOnScreen() || isAppType) && !mAnimatingExit && !mDestroying;
1555     }
1556 
1557     /**
1558      * Whether this window is "interesting" when evaluating allDrawn. If it's interesting,
1559      * it must be drawn before allDrawn can become true.
1560      */
isInteresting()1561     boolean isInteresting() {
1562         return mAppToken != null && !mAppDied
1563                 && (!mAppToken.isFreezingScreen() || !mAppFreezing)
1564                 && mViewVisibility == View.VISIBLE;
1565     }
1566 
1567     /**
1568      * Like isOnScreen(), but we don't return true if the window is part
1569      * of a transition that has not yet been started.
1570      */
isReadyForDisplay()1571     boolean isReadyForDisplay() {
1572         if (mToken.waitingToShow && getDisplayContent().mAppTransition.isTransitionSet()) {
1573             return false;
1574         }
1575         final boolean parentAndClientVisible = !isParentWindowHidden()
1576                 && mViewVisibility == View.VISIBLE && !mToken.isHidden();
1577         return mHasSurface && isVisibleByPolicy() && !mDestroying
1578                 && (parentAndClientVisible || isAnimating());
1579     }
1580 
1581     // TODO: Another visibility method that was added late in the release to minimize risk.
1582     @Override
canAffectSystemUiFlags()1583     public boolean canAffectSystemUiFlags() {
1584         final boolean translucent = mAttrs.alpha == 0.0f;
1585         if (translucent) {
1586             return false;
1587         }
1588         if (mAppToken == null) {
1589             final boolean shown = mWinAnimator.getShown();
1590             final boolean exiting = mAnimatingExit || mDestroying;
1591             return shown && !exiting;
1592         } else {
1593             final Task task = getTask();
1594             final boolean canFromTask = task != null && task.canAffectSystemUiFlags();
1595             return canFromTask && !mAppToken.isHidden();
1596         }
1597     }
1598 
1599     /**
1600      * Like isOnScreen, but returns false if the surface hasn't yet
1601      * been drawn.
1602      */
1603     @Override
isDisplayedLw()1604     public boolean isDisplayedLw() {
1605         final AppWindowToken atoken = mAppToken;
1606         return isDrawnLw() && isVisibleByPolicy()
1607                 && ((!isParentWindowHidden() && (atoken == null || !atoken.hiddenRequested))
1608                         || isAnimating());
1609     }
1610 
1611     /**
1612      * Return true if this window or its app token is currently animating.
1613      */
1614     @Override
isAnimatingLw()1615     public boolean isAnimatingLw() {
1616         return isAnimating();
1617     }
1618 
1619     @Override
isGoneForLayoutLw()1620     public boolean isGoneForLayoutLw() {
1621         final AppWindowToken atoken = mAppToken;
1622         return mViewVisibility == View.GONE
1623                 || !mRelayoutCalled
1624                 || (atoken == null && mToken.isHidden())
1625                 || (atoken != null && atoken.hiddenRequested)
1626                 || isParentWindowGoneForLayout()
1627                 || (mAnimatingExit && !isAnimatingLw())
1628                 || mDestroying;
1629     }
1630 
1631     /**
1632      * Returns true if the window has a surface that it has drawn a
1633      * complete UI in to.
1634      */
isDrawFinishedLw()1635     public boolean isDrawFinishedLw() {
1636         return mHasSurface && !mDestroying &&
1637                 (mWinAnimator.mDrawState == COMMIT_DRAW_PENDING
1638                 || mWinAnimator.mDrawState == READY_TO_SHOW
1639                 || mWinAnimator.mDrawState == HAS_DRAWN);
1640     }
1641 
1642     /**
1643      * Returns true if the window has a surface that it has drawn a
1644      * complete UI in to.
1645      */
1646     @Override
isDrawnLw()1647     public boolean isDrawnLw() {
1648         return mHasSurface && !mDestroying &&
1649                 (mWinAnimator.mDrawState == READY_TO_SHOW || mWinAnimator.mDrawState == HAS_DRAWN);
1650     }
1651 
1652     /**
1653      * Return true if the window is opaque and fully drawn.  This indicates
1654      * it may obscure windows behind it.
1655      */
isOpaqueDrawn()1656     private boolean isOpaqueDrawn() {
1657         // When there is keyguard, wallpaper could be placed over the secure app
1658         // window but invisible. We need to check wallpaper visibility explicitly
1659         // to determine if it's occluding apps.
1660         return ((!mIsWallpaper && mAttrs.format == PixelFormat.OPAQUE)
1661                 || (mIsWallpaper && mWallpaperVisible))
1662                 && isDrawnLw() && !isAnimating();
1663     }
1664 
1665     @Override
onMovedByResize()1666     void onMovedByResize() {
1667         if (DEBUG_RESIZE) Slog.d(TAG, "onMovedByResize: Moving " + this);
1668         mMovedByResize = true;
1669         super.onMovedByResize();
1670     }
1671 
onAppVisibilityChanged(boolean visible, boolean runningAppAnimation)1672     boolean onAppVisibilityChanged(boolean visible, boolean runningAppAnimation) {
1673         boolean changed = false;
1674 
1675         for (int i = mChildren.size() - 1; i >= 0; --i) {
1676             final WindowState c = mChildren.get(i);
1677             changed |= c.onAppVisibilityChanged(visible, runningAppAnimation);
1678         }
1679 
1680         if (mAttrs.type == TYPE_APPLICATION_STARTING) {
1681             // Starting window that's exiting will be removed when the animation finishes.
1682             // Mark all relevant flags for that onExitAnimationDone will proceed all the way
1683             // to actually remove it.
1684             if (!visible && isVisibleNow() && mAppToken.isSelfAnimating()) {
1685                 mAnimatingExit = true;
1686                 mRemoveOnExit = true;
1687                 mWindowRemovalAllowed = true;
1688             }
1689             return changed;
1690         }
1691 
1692         final boolean isVisibleNow = isVisibleNow();
1693         if (visible != isVisibleNow) {
1694             // Run exit animation if:
1695             // 1. App visibility and WS visibility are different
1696             // 2. App is not running an animation
1697             // 3. WS is currently visible
1698             if (!runningAppAnimation && isVisibleNow) {
1699                 final AccessibilityController accessibilityController =
1700                         mWmService.mAccessibilityController;
1701                 final int winTransit = TRANSIT_EXIT;
1702                 mWinAnimator.applyAnimationLocked(winTransit, false /* isEntrance */);
1703                 if (accessibilityController != null) {
1704                     accessibilityController.onWindowTransitionLocked(this, winTransit);
1705                 }
1706             }
1707             changed = true;
1708             setDisplayLayoutNeeded();
1709         }
1710 
1711         return changed;
1712     }
1713 
onSetAppExiting()1714     boolean onSetAppExiting() {
1715         final DisplayContent displayContent = getDisplayContent();
1716         boolean changed = false;
1717 
1718         if (isVisibleNow()) {
1719             mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
1720             if (mWmService.mAccessibilityController != null) {
1721                 mWmService.mAccessibilityController.onWindowTransitionLocked(this, TRANSIT_EXIT);
1722             }
1723             changed = true;
1724             if (displayContent != null) {
1725                 displayContent.setLayoutNeeded();
1726             }
1727         }
1728 
1729         for (int i = mChildren.size() - 1; i >= 0; --i) {
1730             final WindowState c = mChildren.get(i);
1731             changed |= c.onSetAppExiting();
1732         }
1733 
1734         return changed;
1735     }
1736 
1737     @Override
onResize()1738     void onResize() {
1739         final ArrayList<WindowState> resizingWindows = mWmService.mResizingWindows;
1740         if (mHasSurface && !isGoneForLayoutLw() && !resizingWindows.contains(this)) {
1741             if (DEBUG_RESIZE) Slog.d(TAG, "onResize: Resizing " + this);
1742             resizingWindows.add(this);
1743         }
1744         if (isGoneForLayoutLw()) {
1745             mResizedWhileGone = true;
1746         }
1747 
1748         super.onResize();
1749     }
1750 
onUnfreezeBounds()1751     void onUnfreezeBounds() {
1752         for (int i = mChildren.size() - 1; i >= 0; --i) {
1753             final WindowState c = mChildren.get(i);
1754             c.onUnfreezeBounds();
1755         }
1756 
1757         if (!mHasSurface) {
1758             return;
1759         }
1760 
1761         mLayoutNeeded = true;
1762         setDisplayLayoutNeeded();
1763         if (!mWmService.mResizingWindows.contains(this)) {
1764             mWmService.mResizingWindows.add(this);
1765         }
1766     }
1767 
1768     /**
1769      * If the window has moved due to its containing content frame changing, then notify the
1770      * listeners and optionally animate it. Simply checking a change of position is not enough,
1771      * because being move due to dock divider is not a trigger for animation.
1772      */
handleWindowMovedIfNeeded()1773     void handleWindowMovedIfNeeded() {
1774         if (!hasMoved()) {
1775             return;
1776         }
1777 
1778         // Frame has moved, containing content frame has also moved, and we're not currently
1779         // animating... let's do something.
1780         final int left = mWindowFrames.mFrame.left;
1781         final int top = mWindowFrames.mFrame.top;
1782         final Task task = getTask();
1783         final boolean adjustedForMinimizedDockOrIme = task != null
1784                 && (task.mStack.isAdjustedForMinimizedDockedStack()
1785                 || task.mStack.isAdjustedForIme());
1786         if (mToken.okToAnimate()
1787                 && (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
1788                 && !isDragResizing() && !adjustedForMinimizedDockOrIme
1789                 && getWindowConfiguration().hasMovementAnimations()
1790                 && !mWinAnimator.mLastHidden
1791                 && !mSeamlesslyRotated) {
1792             startMoveAnimation(left, top);
1793         }
1794 
1795         //TODO (multidisplay): Accessibility supported only for the default display.
1796         if (mWmService.mAccessibilityController != null
1797                 && getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) {
1798             mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
1799         }
1800 
1801         try {
1802             mClient.moved(left, top);
1803         } catch (RemoteException e) {
1804         }
1805         mMovedByResize = false;
1806     }
1807 
1808     /**
1809      * Return whether this window has moved. (Only makes
1810      * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
1811      */
hasMoved()1812     private boolean hasMoved() {
1813         return mHasSurface && (mWindowFrames.hasContentChanged() || mMovedByResize)
1814                 && !mAnimatingExit
1815                 && (mWindowFrames.mFrame.top != mWindowFrames.mLastFrame.top
1816                     || mWindowFrames.mFrame.left != mWindowFrames.mLastFrame.left)
1817                 && (!mIsChildWindow || !getParentWindow().hasMoved());
1818     }
1819 
isObscuringDisplay()1820     boolean isObscuringDisplay() {
1821         Task task = getTask();
1822         if (task != null && task.mStack != null && !task.mStack.fillsParent()) {
1823             return false;
1824         }
1825         return isOpaqueDrawn() && fillsDisplay();
1826     }
1827 
fillsDisplay()1828     boolean fillsDisplay() {
1829         final DisplayInfo displayInfo = getDisplayInfo();
1830         return mWindowFrames.mFrame.left <= 0 && mWindowFrames.mFrame.top <= 0
1831                 && mWindowFrames.mFrame.right >= displayInfo.appWidth
1832                 && mWindowFrames.mFrame.bottom >= displayInfo.appHeight;
1833     }
1834 
matchesDisplayBounds()1835     private boolean matchesDisplayBounds() {
1836         return getDisplayContent().getBounds().equals(getBounds());
1837     }
1838 
1839     /**
1840      * @return {@code true} if last applied config was reported to the client already, {@code false}
1841      *         otherwise.
1842      */
isLastConfigReportedToClient()1843     boolean isLastConfigReportedToClient() {
1844         return mLastConfigReportedToClient;
1845     }
1846 
1847     @Override
onMergedOverrideConfigurationChanged()1848     void onMergedOverrideConfigurationChanged() {
1849         super.onMergedOverrideConfigurationChanged();
1850         mLastConfigReportedToClient = false;
1851     }
1852 
onWindowReplacementTimeout()1853     void onWindowReplacementTimeout() {
1854         if (mWillReplaceWindow) {
1855             // Since the window already timed out, remove it immediately now.
1856             // Use WindowState#removeImmediately() instead of WindowState#removeIfPossible(), as the latter
1857             // delays removal on certain conditions, which will leave the stale window in the
1858             // stack and marked mWillReplaceWindow=false, so the window will never be removed.
1859             //
1860             // Also removes child windows.
1861             removeImmediately();
1862         } else {
1863             for (int i = mChildren.size() - 1; i >= 0; --i) {
1864                 final WindowState c = mChildren.get(i);
1865                 c.onWindowReplacementTimeout();
1866             }
1867         }
1868     }
1869 
1870     @Override
forceWindowsScaleableInTransaction(boolean force)1871     void forceWindowsScaleableInTransaction(boolean force) {
1872         if (mWinAnimator != null && mWinAnimator.hasSurface()) {
1873             mWinAnimator.mSurfaceController.forceScaleableInTransaction(force);
1874         }
1875 
1876         super.forceWindowsScaleableInTransaction(force);
1877     }
1878 
1879     @Override
removeImmediately()1880     void removeImmediately() {
1881         super.removeImmediately();
1882 
1883         if (mRemoved) {
1884             // Nothing to do.
1885             if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1886                     "WS.removeImmediately: " + this + " Already removed...");
1887             return;
1888         }
1889 
1890         mRemoved = true;
1891 
1892         mWillReplaceWindow = false;
1893         if (mReplacementWindow != null) {
1894             mReplacementWindow.mSkipEnterAnimationForSeamlessReplacement = false;
1895         }
1896 
1897         final DisplayContent dc = getDisplayContent();
1898         if (isInputMethodTarget()) {
1899             dc.computeImeTarget(true /* updateImeTarget */);
1900         }
1901 
1902         final int type = mAttrs.type;
1903         if (WindowManagerService.excludeWindowTypeFromTapOutTask(type)) {
1904             dc.mTapExcludedWindows.remove(this);
1905         }
1906         if (mTapExcludeRegionHolder != null) {
1907             // If a tap exclude region container was initialized for this window, then it should've
1908             // also been registered in display.
1909             dc.mTapExcludeProvidingWindows.remove(this);
1910         }
1911         dc.getDisplayPolicy().removeWindowLw(this);
1912 
1913         disposeInputChannel();
1914 
1915         mWinAnimator.destroyDeferredSurfaceLocked();
1916         mWinAnimator.destroySurfaceLocked();
1917         mSession.windowRemovedLocked();
1918         try {
1919             mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
1920         } catch (RuntimeException e) {
1921             // Ignore if it has already been removed (usually because
1922             // we are doing this as part of processing a death note.)
1923         }
1924 
1925         mWmService.postWindowRemoveCleanupLocked(this);
1926     }
1927 
1928     @Override
removeIfPossible()1929     void removeIfPossible() {
1930         super.removeIfPossible();
1931         removeIfPossible(false /*keepVisibleDeadWindow*/);
1932     }
1933 
removeIfPossible(boolean keepVisibleDeadWindow)1934     private void removeIfPossible(boolean keepVisibleDeadWindow) {
1935         mWindowRemovalAllowed = true;
1936         if (DEBUG_ADD_REMOVE) Slog.v(TAG,
1937                 "removeIfPossible: " + this + " callers=" + Debug.getCallers(5));
1938 
1939         final boolean startingWindow = mAttrs.type == TYPE_APPLICATION_STARTING;
1940         if (startingWindow && DEBUG_STARTING_WINDOW) Slog.d(TAG_WM,
1941                 "Starting window removed " + this);
1942 
1943         if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && isFocused())
1944             Slog.v(TAG_WM, "Remove " + this + " client="
1945                         + Integer.toHexString(System.identityHashCode(mClient.asBinder()))
1946                         + ", surfaceController=" + mWinAnimator.mSurfaceController + " Callers="
1947                         + Debug.getCallers(5));
1948 
1949         final long origId = Binder.clearCallingIdentity();
1950 
1951         try {
1952             disposeInputChannel();
1953 
1954             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Remove " + this
1955                     + ": mSurfaceController=" + mWinAnimator.mSurfaceController
1956                     + " mAnimatingExit=" + mAnimatingExit
1957                     + " mRemoveOnExit=" + mRemoveOnExit
1958                     + " mHasSurface=" + mHasSurface
1959                     + " surfaceShowing=" + mWinAnimator.getShown()
1960                     + " animating=" + isAnimating()
1961                     + " app-animation="
1962                     + (mAppToken != null ? mAppToken.isSelfAnimating() : "false")
1963                     + " mWillReplaceWindow=" + mWillReplaceWindow
1964                     + " inPendingTransaction="
1965                     + (mAppToken != null ? mAppToken.inPendingTransaction : false)
1966                     + " mDisplayFrozen=" + mWmService.mDisplayFrozen
1967                     + " callers=" + Debug.getCallers(6));
1968 
1969             // Visibility of the removed window. Will be used later to update orientation later on.
1970             boolean wasVisible = false;
1971 
1972             final int displayId = getDisplayId();
1973 
1974             // First, see if we need to run an animation. If we do, we have to hold off on removing the
1975             // window until the animation is done. If the display is frozen, just remove immediately,
1976             // since the animation wouldn't be seen.
1977             if (mHasSurface && mToken.okToAnimate()) {
1978                 if (mWillReplaceWindow) {
1979                     // This window is going to be replaced. We need to keep it around until the new one
1980                     // gets added, then we will get rid of this one.
1981                     if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1982                             "Preserving " + this + " until the new one is " + "added");
1983                     // TODO: We are overloading mAnimatingExit flag to prevent the window state from
1984                     // been removed. We probably need another flag to indicate that window removal
1985                     // should be deffered vs. overloading the flag that says we are playing an exit
1986                     // animation.
1987                     mAnimatingExit = true;
1988                     mReplacingRemoveRequested = true;
1989                     return;
1990                 }
1991 
1992                 // If we are not currently running the exit animation, we need to see about starting one
1993                 wasVisible = isWinVisibleLw();
1994 
1995                 if (keepVisibleDeadWindow) {
1996                     if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1997                             "Not removing " + this + " because app died while it's visible");
1998 
1999                     mAppDied = true;
2000                     setDisplayLayoutNeeded();
2001                     mWmService.mWindowPlacerLocked.performSurfacePlacement();
2002 
2003                     // Set up a replacement input channel since the app is now dead.
2004                     // We need to catch tapping on the dead window to restart the app.
2005                     openInputChannel(null);
2006                     getDisplayContent().getInputMonitor().updateInputWindowsLw(true /*force*/);
2007                     return;
2008                 }
2009 
2010                 if (wasVisible) {
2011                     final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;
2012 
2013                     // Try starting an animation.
2014                     if (mWinAnimator.applyAnimationLocked(transit, false)) {
2015                         mAnimatingExit = true;
2016 
2017                         // mAnimatingExit affects canAffectSystemUiFlags(). Run layout such that
2018                         // any change from that is performed immediately.
2019                         setDisplayLayoutNeeded();
2020                         mWmService.requestTraversal();
2021                     }
2022                     if (mWmService.mAccessibilityController != null) {
2023                         mWmService.mAccessibilityController.onWindowTransitionLocked(this, transit);
2024                     }
2025                 }
2026                 final boolean isAnimating = isAnimating()
2027                         && (mAppToken == null || !mAppToken.isWaitingForTransitionStart());
2028                 final boolean lastWindowIsStartingWindow = startingWindow && mAppToken != null
2029                         && mAppToken.isLastWindow(this);
2030                 // We delay the removal of a window if it has a showing surface that can be used to run
2031                 // exit animation and it is marked as exiting.
2032                 // Also, If isn't the an animating starting window that is the last window in the app.
2033                 // We allow the removal of the non-animating starting window now as there is no
2034                 // additional window or animation that will trigger its removal.
2035                 if (mWinAnimator.getShown() && mAnimatingExit
2036                         && (!lastWindowIsStartingWindow || isAnimating)) {
2037                     // The exit animation is running or should run... wait for it!
2038                     if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2039                             "Not removing " + this + " due to exit animation ");
2040                     setupWindowForRemoveOnExit();
2041                     if (mAppToken != null) {
2042                         mAppToken.updateReportedVisibilityLocked();
2043                     }
2044                     return;
2045                 }
2046             }
2047 
2048             removeImmediately();
2049             // Removing a visible window will effect the computed orientation
2050             // So just update orientation if needed.
2051             if (wasVisible) {
2052                 final DisplayContent displayContent = getDisplayContent();
2053                 if (displayContent.updateOrientationFromAppTokens()) {
2054                     displayContent.sendNewConfiguration();
2055                 }
2056             }
2057             mWmService.updateFocusedWindowLocked(isFocused()
2058                             ? UPDATE_FOCUS_REMOVING_FOCUS
2059                             : UPDATE_FOCUS_NORMAL,
2060                     true /*updateInputWindows*/);
2061         } finally {
2062             Binder.restoreCallingIdentity(origId);
2063         }
2064     }
2065 
setupWindowForRemoveOnExit()2066     private void setupWindowForRemoveOnExit() {
2067         mRemoveOnExit = true;
2068         setDisplayLayoutNeeded();
2069         // Request a focus update as this window's input channel is already gone. Otherwise
2070         // we could have no focused window in input manager.
2071         final boolean focusChanged = mWmService.updateFocusedWindowLocked(
2072                 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
2073         mWmService.mWindowPlacerLocked.performSurfacePlacement();
2074         if (focusChanged) {
2075             getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
2076         }
2077     }
2078 
setHasSurface(boolean hasSurface)2079     void setHasSurface(boolean hasSurface) {
2080         mHasSurface = hasSurface;
2081     }
2082 
canBeImeTarget()2083     boolean canBeImeTarget() {
2084         if (mIsImWindow) {
2085             // IME windows can't be IME targets. IME targets are required to be below the IME
2086             // windows and that wouldn't be possible if the IME window is its own target...silly.
2087             return false;
2088         }
2089 
2090         final boolean windowsAreFocusable = mAppToken == null || mAppToken.windowsAreFocusable();
2091         if (!windowsAreFocusable) {
2092             // This window can't be an IME target if the app's windows should not be focusable.
2093             return false;
2094         }
2095 
2096         final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
2097         final int type = mAttrs.type;
2098 
2099         // Can only be an IME target if both FLAG_NOT_FOCUSABLE and FLAG_ALT_FOCUSABLE_IM are set or
2100         // both are cleared...and not a starting window.
2101         if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
2102                 && type != TYPE_APPLICATION_STARTING) {
2103             return false;
2104         }
2105 
2106         if (DEBUG_INPUT_METHOD) {
2107             Slog.i(TAG_WM, "isVisibleOrAdding " + this + ": " + isVisibleOrAdding());
2108             if (!isVisibleOrAdding()) {
2109                 Slog.i(TAG_WM, "  mSurfaceController=" + mWinAnimator.mSurfaceController
2110                         + " relayoutCalled=" + mRelayoutCalled
2111                         + " viewVis=" + mViewVisibility
2112                         + " policyVis=" + isVisibleByPolicy()
2113                         + " policyVisAfterAnim=" + mLegacyPolicyVisibilityAfterAnim
2114                         + " parentHidden=" + isParentWindowHidden()
2115                         + " exiting=" + mAnimatingExit + " destroying=" + mDestroying);
2116                 if (mAppToken != null) {
2117                     Slog.i(TAG_WM, "  mAppToken.hiddenRequested=" + mAppToken.hiddenRequested);
2118                 }
2119             }
2120         }
2121         return isVisibleOrAdding();
2122     }
2123 
2124     private final class DeadWindowEventReceiver extends InputEventReceiver {
DeadWindowEventReceiver(InputChannel inputChannel)2125         DeadWindowEventReceiver(InputChannel inputChannel) {
2126             super(inputChannel, mWmService.mH.getLooper());
2127         }
2128         @Override
onInputEvent(InputEvent event)2129         public void onInputEvent(InputEvent event) {
2130             finishInputEvent(event, true);
2131         }
2132     }
2133     /**
2134      *  Dummy event receiver for windows that died visible.
2135      */
2136     private DeadWindowEventReceiver mDeadWindowEventReceiver;
2137 
openInputChannel(InputChannel outInputChannel)2138     void openInputChannel(InputChannel outInputChannel) {
2139         if (mInputChannel != null) {
2140             throw new IllegalStateException("Window already has an input channel.");
2141         }
2142         String name = getName();
2143         InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
2144         mInputChannel = inputChannels[0];
2145         mClientChannel = inputChannels[1];
2146         mInputWindowHandle.token = mClient.asBinder();
2147         if (outInputChannel != null) {
2148             mClientChannel.transferTo(outInputChannel);
2149             mClientChannel.dispose();
2150             mClientChannel = null;
2151         } else {
2152             // If the window died visible, we setup a dummy input channel, so that taps
2153             // can still detected by input monitor channel, and we can relaunch the app.
2154             // Create dummy event receiver that simply reports all events as handled.
2155             mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
2156         }
2157         mWmService.mInputManager.registerInputChannel(mInputChannel, mClient.asBinder());
2158     }
2159 
disposeInputChannel()2160     void disposeInputChannel() {
2161         if (mDeadWindowEventReceiver != null) {
2162             mDeadWindowEventReceiver.dispose();
2163             mDeadWindowEventReceiver = null;
2164         }
2165 
2166         // unregister server channel first otherwise it complains about broken channel
2167         if (mInputChannel != null) {
2168             mWmService.mInputManager.unregisterInputChannel(mInputChannel);
2169 
2170             mInputChannel.dispose();
2171             mInputChannel = null;
2172         }
2173         if (mClientChannel != null) {
2174             mClientChannel.dispose();
2175             mClientChannel = null;
2176         }
2177         mInputWindowHandle.token = null;
2178     }
2179 
2180     /** Returns true if the replacement window was removed. */
removeReplacedWindowIfNeeded(WindowState replacement)2181     boolean removeReplacedWindowIfNeeded(WindowState replacement) {
2182         if (mWillReplaceWindow && mReplacementWindow == replacement && replacement.hasDrawnLw()) {
2183             replacement.mSkipEnterAnimationForSeamlessReplacement = false;
2184             removeReplacedWindow();
2185             return true;
2186         }
2187 
2188         for (int i = mChildren.size() - 1; i >= 0; --i) {
2189             final WindowState c = mChildren.get(i);
2190             if (c.removeReplacedWindowIfNeeded(replacement)) {
2191                 return true;
2192             }
2193         }
2194         return false;
2195     }
2196 
removeReplacedWindow()2197     private void removeReplacedWindow() {
2198         if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + this);
2199         mWillReplaceWindow = false;
2200         mAnimateReplacingWindow = false;
2201         mReplacingRemoveRequested = false;
2202         mReplacementWindow = null;
2203         if (mAnimatingExit || !mAnimateReplacingWindow) {
2204             removeImmediately();
2205         }
2206     }
2207 
setReplacementWindowIfNeeded(WindowState replacementCandidate)2208     boolean setReplacementWindowIfNeeded(WindowState replacementCandidate) {
2209         boolean replacementSet = false;
2210 
2211         if (mWillReplaceWindow && mReplacementWindow == null
2212                 && getWindowTag().toString().equals(replacementCandidate.getWindowTag().toString())) {
2213 
2214             mReplacementWindow = replacementCandidate;
2215             replacementCandidate.mSkipEnterAnimationForSeamlessReplacement = !mAnimateReplacingWindow;
2216             replacementSet = true;
2217         }
2218 
2219         for (int i = mChildren.size() - 1; i >= 0; --i) {
2220             final WindowState c = mChildren.get(i);
2221             replacementSet |= c.setReplacementWindowIfNeeded(replacementCandidate);
2222         }
2223 
2224         return replacementSet;
2225     }
2226 
setDisplayLayoutNeeded()2227     void setDisplayLayoutNeeded() {
2228         final DisplayContent dc = getDisplayContent();
2229         if (dc != null) {
2230             dc.setLayoutNeeded();
2231         }
2232     }
2233 
applyAdjustForImeIfNeeded()2234     void applyAdjustForImeIfNeeded() {
2235         final Task task = getTask();
2236         if (task != null && task.mStack != null && task.mStack.isAdjustedForIme()) {
2237             task.mStack.applyAdjustForImeIfNeeded(task);
2238         }
2239     }
2240 
2241     @Override
switchUser()2242     void switchUser() {
2243         super.switchUser();
2244         if (isHiddenFromUserLocked()) {
2245             if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + this
2246                     + ", attrs=" + mAttrs.type + ", belonging to " + mOwnerUid);
2247             clearPolicyVisibilityFlag(VISIBLE_FOR_USER);
2248         } else {
2249             setPolicyVisibilityFlag(VISIBLE_FOR_USER);
2250         }
2251     }
2252 
getSurfaceTouchableRegion(InputWindowHandle inputWindowHandle, int flags)2253     int getSurfaceTouchableRegion(InputWindowHandle inputWindowHandle, int flags) {
2254         final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
2255         final Region region = inputWindowHandle.touchableRegion;
2256         setTouchableRegionCropIfNeeded(inputWindowHandle);
2257 
2258         final Rect appOverrideBounds = mAppToken != null
2259                 ? mAppToken.getResolvedOverrideBounds() : null;
2260         if (appOverrideBounds != null && !appOverrideBounds.isEmpty()) {
2261             // There may have touchable letterboxes around the activity, so in order to let the
2262             // letterboxes are able to receive touch event and slip to activity, the activity with
2263             // compatibility bounds cannot occupy full screen touchable region.
2264             if (modal) {
2265                 // A modal window uses the whole compatibility bounds.
2266                 flags |= FLAG_NOT_TOUCH_MODAL;
2267                 mTmpRect.set(0, 0, appOverrideBounds.width(), appOverrideBounds.height());
2268             } else {
2269                 // Non-modal uses the application based frame.
2270                 mTmpRect.set(mWindowFrames.mCompatFrame);
2271             }
2272             // The offset of compatibility bounds is applied to surface of {@link #AppWindowToken}
2273             // and frame, so it is unnecessary to translate twice in surface based coordinates.
2274             final int surfaceOffsetX = mAppToken.inSizeCompatMode()
2275                     ? mAppToken.getBounds().left : 0;
2276             mTmpRect.offset(surfaceOffsetX - mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
2277             region.set(mTmpRect);
2278             return flags;
2279         }
2280 
2281         if (modal && mAppToken != null) {
2282             // Limit the outer touch to the activity stack region.
2283             flags |= FLAG_NOT_TOUCH_MODAL;
2284             // If the inner bounds of letterbox is available, then it will be used as the touchable
2285             // region so it won't cover the touchable letterbox and the touch events can slip to
2286             // activity from letterbox.
2287             mAppToken.getLetterboxInnerBounds(mTmpRect);
2288             if (mTmpRect.isEmpty()) {
2289                 // If this is a modal window we need to dismiss it if it's not full screen and the
2290                 // touch happens outside of the frame that displays the content. This means we need
2291                 // to intercept touches outside of that window. The dim layer user associated with
2292                 // the window (task or stack) will give us the good bounds, as they would be used to
2293                 // display the dim layer.
2294                 final Task task = getTask();
2295                 if (task != null) {
2296                     task.getDimBounds(mTmpRect);
2297                 } else {
2298                     getStack().getDimBounds(mTmpRect);
2299                 }
2300             }
2301             if (inFreeformWindowingMode()) {
2302                 // For freeform windows we the touch region to include the whole surface for the
2303                 // shadows.
2304                 final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
2305                 final int delta = WindowManagerService.dipToPixel(
2306                         RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
2307                 mTmpRect.inset(-delta, -delta);
2308             }
2309             region.set(mTmpRect);
2310             cropRegionToStackBoundsIfNeeded(region);
2311             subtractTouchExcludeRegionIfNeeded(region);
2312         } else if (modal && mTapExcludeRegionHolder != null) {
2313             final Region touchExcludeRegion = Region.obtain();
2314             amendTapExcludeRegion(touchExcludeRegion);
2315             if (!touchExcludeRegion.isEmpty()) {
2316                 // Remove touch modal because there are some areas that cannot be touched.
2317                 flags |= FLAG_NOT_TOUCH_MODAL;
2318                 // Give it a large touchable region at first because it was touch modal. The window
2319                 // might be moved on the display, so the touchable region should be large enough to
2320                 // ensure it covers the whole display, no matter where it is moved.
2321                 getDisplayContent().getBounds(mTmpRect);
2322                 final int dw = mTmpRect.width();
2323                 final int dh = mTmpRect.height();
2324                 region.set(-dw, -dh, dw + dw, dh + dh);
2325                 // Subtract the area that cannot be touched.
2326                 region.op(touchExcludeRegion, Region.Op.DIFFERENCE);
2327                 inputWindowHandle.setTouchableRegionCrop(null);
2328             }
2329             touchExcludeRegion.recycle();
2330         } else {
2331             // Not modal or full screen modal
2332             getTouchableRegion(region);
2333         }
2334         // Translate to surface based coordinates.
2335         region.translate(-mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
2336 
2337         return flags;
2338     }
2339 
checkPolicyVisibilityChange()2340     void checkPolicyVisibilityChange() {
2341         if (isLegacyPolicyVisibility() != mLegacyPolicyVisibilityAfterAnim) {
2342             if (DEBUG_VISIBILITY) {
2343                 Slog.v(TAG, "Policy visibility changing after anim in " +
2344                         mWinAnimator + ": " + mLegacyPolicyVisibilityAfterAnim);
2345             }
2346             if (mLegacyPolicyVisibilityAfterAnim) {
2347                 setPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
2348             } else {
2349                 clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
2350             }
2351             if (!isVisibleByPolicy()) {
2352                 mWinAnimator.hide("checkPolicyVisibilityChange");
2353                 if (isFocused()) {
2354                     if (DEBUG_FOCUS_LIGHT) Slog.i(TAG,
2355                             "setAnimationLocked: setting mFocusMayChange true");
2356                     mWmService.mFocusMayChange = true;
2357                 }
2358                 setDisplayLayoutNeeded();
2359                 // Window is no longer visible -- make sure if we were waiting
2360                 // for it to be displayed before enabling the display, that
2361                 // we allow the display to be enabled now.
2362                 mWmService.enableScreenIfNeededLocked();
2363             }
2364         }
2365     }
2366 
setRequestedSize(int requestedWidth, int requestedHeight)2367     void setRequestedSize(int requestedWidth, int requestedHeight) {
2368         if ((mRequestedWidth != requestedWidth || mRequestedHeight != requestedHeight)) {
2369             mLayoutNeeded = true;
2370             mRequestedWidth = requestedWidth;
2371             mRequestedHeight = requestedHeight;
2372         }
2373     }
2374 
prepareWindowToDisplayDuringRelayout(boolean wasVisible)2375     void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
2376         // We need to turn on screen regardless of visibility.
2377         boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0;
2378 
2379         // The screen will turn on if the following conditions are met
2380         // 1. The window has the flag FLAG_TURN_SCREEN_ON
2381         // 2. The WMS allows theater mode.
2382         // 3. No AWT or the AWT allows the screen to be turned on. This should only be true once
2383         // per resume to prevent the screen getting getting turned on for each relayout. Set
2384         // canTurnScreenOn will be set to false so the window doesn't turn the screen on again
2385         // during this resume.
2386         // 4. When the screen is not interactive. This is because when the screen is already
2387         // interactive, the value may persist until the next animation, which could potentially
2388         // be occurring while turning off the screen. This would lead to the screen incorrectly
2389         // turning back on.
2390         if (hasTurnScreenOnFlag) {
2391             boolean allowTheaterMode = mWmService.mAllowTheaterModeWakeFromLayout
2392                     || Settings.Global.getInt(mWmService.mContext.getContentResolver(),
2393                             Settings.Global.THEATER_MODE_ON, 0) == 0;
2394             boolean canTurnScreenOn = mAppToken == null || mAppToken.canTurnScreenOn();
2395 
2396             if (allowTheaterMode && canTurnScreenOn && !mPowerManagerWrapper.isInteractive()) {
2397                 if (DEBUG_VISIBILITY || DEBUG_POWER) {
2398                     Slog.v(TAG, "Relayout window turning screen on: " + this);
2399                 }
2400                 mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),
2401                         PowerManager.WAKE_REASON_APPLICATION, "android.server.wm:SCREEN_ON_FLAG");
2402             }
2403 
2404             if (mAppToken != null) {
2405                 mAppToken.setCanTurnScreenOn(false);
2406             }
2407         }
2408 
2409         // If we were already visible, skip rest of preparation.
2410         if (wasVisible) {
2411             if (DEBUG_VISIBILITY) Slog.v(TAG,
2412                     "Already visible and does not turn on screen, skip preparing: " + this);
2413             return;
2414         }
2415 
2416         if ((mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
2417                 == SOFT_INPUT_ADJUST_RESIZE) {
2418             mLayoutNeeded = true;
2419         }
2420 
2421         if (isDrawnLw() && mToken.okToAnimate()) {
2422             mWinAnimator.applyEnterAnimationLocked();
2423         }
2424     }
2425 
getProcessGlobalConfiguration()2426     private Configuration getProcessGlobalConfiguration() {
2427         // For child windows we want to use the pid for the parent window in case the the child
2428         // window was added from another process.
2429         final WindowState parentWindow = getParentWindow();
2430         final int pid = parentWindow != null ? parentWindow.mSession.mPid : mSession.mPid;
2431         final Configuration processConfig =
2432                 mWmService.mAtmService.getGlobalConfigurationForPid(pid);
2433         return processConfig;
2434     }
2435 
getMergedConfiguration(MergedConfiguration outConfiguration)2436     void getMergedConfiguration(MergedConfiguration outConfiguration) {
2437         final Configuration globalConfig = getProcessGlobalConfiguration();
2438         final Configuration overrideConfig = getMergedOverrideConfiguration();
2439         outConfiguration.setConfiguration(globalConfig, overrideConfig);
2440     }
2441 
setLastReportedMergedConfiguration(MergedConfiguration config)2442     void setLastReportedMergedConfiguration(MergedConfiguration config) {
2443         mLastReportedConfiguration.setTo(config);
2444         mLastConfigReportedToClient = true;
2445     }
2446 
getLastReportedMergedConfiguration(MergedConfiguration config)2447     void getLastReportedMergedConfiguration(MergedConfiguration config) {
2448         config.setTo(mLastReportedConfiguration);
2449     }
2450 
getLastReportedConfiguration()2451     private Configuration getLastReportedConfiguration() {
2452         return mLastReportedConfiguration.getMergedConfiguration();
2453     }
2454 
adjustStartingWindowFlags()2455     void adjustStartingWindowFlags() {
2456         if (mAttrs.type == TYPE_BASE_APPLICATION && mAppToken != null
2457                 && mAppToken.startingWindow != null) {
2458             // Special handling of starting window over the base
2459             // window of the app: propagate lock screen flags to it,
2460             // to provide the correct semantics while starting.
2461             final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD
2462                     | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
2463             WindowManager.LayoutParams sa = mAppToken.startingWindow.mAttrs;
2464             sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask);
2465         }
2466     }
2467 
setWindowScale(int requestedWidth, int requestedHeight)2468     void setWindowScale(int requestedWidth, int requestedHeight) {
2469         final boolean scaledWindow = (mAttrs.flags & FLAG_SCALED) != 0;
2470 
2471         if (scaledWindow) {
2472             // requested{Width|Height} Surface's physical size
2473             // attrs.{width|height} Size on screen
2474             // TODO: We don't check if attrs != null here. Is it implicitly checked?
2475             mHScale = (mAttrs.width  != requestedWidth)  ?
2476                     (mAttrs.width  / (float)requestedWidth) : 1.0f;
2477             mVScale = (mAttrs.height != requestedHeight) ?
2478                     (mAttrs.height / (float)requestedHeight) : 1.0f;
2479         } else {
2480             mHScale = mVScale = 1;
2481         }
2482     }
2483 
2484     private class DeathRecipient implements IBinder.DeathRecipient {
2485         @Override
binderDied()2486         public void binderDied() {
2487             try {
2488                 boolean resetSplitScreenResizing = false;
2489                 synchronized (mWmService.mGlobalLock) {
2490                     final WindowState win = mWmService
2491                             .windowForClientLocked(mSession, mClient, false);
2492                     Slog.i(TAG, "WIN DEATH: " + win);
2493                     if (win != null) {
2494                         final DisplayContent dc = getDisplayContent();
2495                         if (win.mAppToken != null && win.mAppToken.findMainWindow() == win) {
2496                             mWmService.mTaskSnapshotController.onAppDied(win.mAppToken);
2497                         }
2498                         win.removeIfPossible(shouldKeepVisibleDeadAppWindow());
2499                         if (win.mAttrs.type == TYPE_DOCK_DIVIDER) {
2500                             // The owner of the docked divider died :( We reset the docked stack,
2501                             // just in case they have the divider at an unstable position. Better
2502                             // also reset drag resizing state, because the owner can't do it
2503                             // anymore.
2504                             final TaskStack stack =
2505                                     dc.getSplitScreenPrimaryStackIgnoringVisibility();
2506                             if (stack != null) {
2507                                 stack.resetDockedStackToMiddle();
2508                             }
2509                             resetSplitScreenResizing = true;
2510                         }
2511                     } else if (mHasSurface) {
2512                         Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
2513                         WindowState.this.removeIfPossible();
2514                     }
2515                 }
2516                 if (resetSplitScreenResizing) {
2517                     try {
2518                         // Note: this calls into ActivityManager, so we must *not* hold the window
2519                         // manager lock while calling this.
2520                         mWmService.mActivityTaskManager.setSplitScreenResizing(false);
2521                     } catch (RemoteException e) {
2522                         // Local call, shouldn't return RemoteException.
2523                         throw e.rethrowAsRuntimeException();
2524                     }
2525                 }
2526             } catch (IllegalArgumentException ex) {
2527                 // This will happen if the window has already been removed.
2528             }
2529         }
2530     }
2531 
2532     /**
2533      * Returns true if this window is visible and belongs to a dead app and shouldn't be removed,
2534      * because we want to preserve its location on screen to be re-activated later when the user
2535      * interacts with it.
2536      */
shouldKeepVisibleDeadAppWindow()2537     private boolean shouldKeepVisibleDeadAppWindow() {
2538         if (!isWinVisibleLw() || mAppToken == null || mAppToken.isClientHidden()) {
2539             // Not a visible app window or the app isn't dead.
2540             return false;
2541         }
2542 
2543         if (mAttrs.token != mClient.asBinder()) {
2544             // The window was add by a client using another client's app token. We don't want to
2545             // keep the dead window around for this case since this is meant for 'real' apps.
2546             return false;
2547         }
2548 
2549         if (mAttrs.type == TYPE_APPLICATION_STARTING) {
2550             // We don't keep starting windows since they were added by the window manager before
2551             // the app even launched.
2552             return false;
2553         }
2554 
2555         return getWindowConfiguration().keepVisibleDeadAppWindowOnScreen();
2556     }
2557 
2558     @Override
canReceiveKeys()2559     public boolean canReceiveKeys() {
2560         return isVisibleOrAdding()
2561                 && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
2562                 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
2563                 && (mAppToken == null || mAppToken.windowsAreFocusable())
2564                 && !cantReceiveTouchInput();
2565     }
2566 
2567     @Override
canShowWhenLocked()2568     public boolean canShowWhenLocked() {
2569         final boolean showBecauseOfActivity =
2570                 mAppToken != null && mAppToken.mActivityRecord.canShowWhenLocked();
2571         final boolean showBecauseOfWindow = (getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
2572         return showBecauseOfActivity || showBecauseOfWindow;
2573     }
2574 
2575     /** @return false if this window desires touch events. */
cantReceiveTouchInput()2576     boolean cantReceiveTouchInput() {
2577         return mAppToken != null && mAppToken.getTask() != null
2578                 && (mAppToken.getTask().mStack.shouldIgnoreInput() || mAppToken.hiddenRequested);
2579     }
2580 
2581     @Override
hasDrawnLw()2582     public boolean hasDrawnLw() {
2583         return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN;
2584     }
2585 
2586     @Override
showLw(boolean doAnimation)2587     public boolean showLw(boolean doAnimation) {
2588         return showLw(doAnimation, true);
2589     }
2590 
showLw(boolean doAnimation, boolean requestAnim)2591     boolean showLw(boolean doAnimation, boolean requestAnim) {
2592         if (isLegacyPolicyVisibility() && mLegacyPolicyVisibilityAfterAnim) {
2593             // Already showing.
2594             return false;
2595         }
2596         if (isHiddenFromUserLocked()) {
2597             return false;
2598         }
2599         if (!mAppOpVisibility) {
2600             // Being hidden due to app op request.
2601             return false;
2602         }
2603         if (mPermanentlyHidden) {
2604             // Permanently hidden until the app exists as apps aren't prepared
2605             // to handle their windows being removed from under them.
2606             return false;
2607         }
2608         if (mHiddenWhileSuspended) {
2609             // Being hidden due to owner package being suspended.
2610             return false;
2611         }
2612         if (mForceHideNonSystemOverlayWindow) {
2613             // This is an alert window that is currently force hidden.
2614             return false;
2615         }
2616         if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
2617         if (doAnimation) {
2618             if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
2619                     + isLegacyPolicyVisibility() + " animating=" + isAnimating());
2620             if (!mToken.okToAnimate()) {
2621                 doAnimation = false;
2622             } else if (isLegacyPolicyVisibility() && !isAnimating()) {
2623                 // Check for the case where we are currently visible and
2624                 // not animating; we do not want to do animation at such a
2625                 // point to become visible when we already are.
2626                 doAnimation = false;
2627             }
2628         }
2629         setPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
2630         mLegacyPolicyVisibilityAfterAnim = true;
2631         if (doAnimation) {
2632             mWinAnimator.applyAnimationLocked(TRANSIT_ENTER, true);
2633         }
2634         if (requestAnim) {
2635             mWmService.scheduleAnimationLocked();
2636         }
2637         if ((mAttrs.flags & FLAG_NOT_FOCUSABLE) == 0) {
2638             mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
2639         }
2640         return true;
2641     }
2642 
2643     @Override
hideLw(boolean doAnimation)2644     public boolean hideLw(boolean doAnimation) {
2645         return hideLw(doAnimation, true);
2646     }
2647 
hideLw(boolean doAnimation, boolean requestAnim)2648     boolean hideLw(boolean doAnimation, boolean requestAnim) {
2649         if (doAnimation) {
2650             if (!mToken.okToAnimate()) {
2651                 doAnimation = false;
2652             }
2653         }
2654         boolean current =
2655                 doAnimation ? mLegacyPolicyVisibilityAfterAnim : isLegacyPolicyVisibility();
2656         if (!current) {
2657             // Already hiding.
2658             return false;
2659         }
2660         if (doAnimation) {
2661             mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
2662             if (!isAnimating()) {
2663                 doAnimation = false;
2664             }
2665         }
2666         mLegacyPolicyVisibilityAfterAnim = false;
2667         final boolean isFocused = isFocused();
2668         if (!doAnimation) {
2669             if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
2670             clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
2671             // Window is no longer visible -- make sure if we were waiting
2672             // for it to be displayed before enabling the display, that
2673             // we allow the display to be enabled now.
2674             mWmService.enableScreenIfNeededLocked();
2675             if (isFocused) {
2676                 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG,
2677                         "WindowState.hideLw: setting mFocusMayChange true");
2678                 mWmService.mFocusMayChange = true;
2679             }
2680         }
2681         if (requestAnim) {
2682             mWmService.scheduleAnimationLocked();
2683         }
2684         if (isFocused) {
2685             mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
2686         }
2687         return true;
2688     }
2689 
setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide)2690     void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) {
2691         if (mOwnerCanAddInternalSystemWindow
2692                 || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
2693             return;
2694         }
2695         if (mForceHideNonSystemOverlayWindow == forceHide) {
2696             return;
2697         }
2698         mForceHideNonSystemOverlayWindow = forceHide;
2699         if (forceHide) {
2700             hideLw(true /* doAnimation */, true /* requestAnim */);
2701         } else {
2702             showLw(true /* doAnimation */, true /* requestAnim */);
2703         }
2704     }
2705 
setHiddenWhileSuspended(boolean hide)2706     void setHiddenWhileSuspended(boolean hide) {
2707         if (mOwnerCanAddInternalSystemWindow
2708                 || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
2709             return;
2710         }
2711         if (mHiddenWhileSuspended == hide) {
2712             return;
2713         }
2714         mHiddenWhileSuspended = hide;
2715         if (hide) {
2716             hideLw(true, true);
2717         } else {
2718             showLw(true, true);
2719         }
2720     }
2721 
setAppOpVisibilityLw(boolean state)2722     private void setAppOpVisibilityLw(boolean state) {
2723         if (mAppOpVisibility != state) {
2724             mAppOpVisibility = state;
2725             if (state) {
2726                 // If the policy visibility had last been to hide, then this
2727                 // will incorrectly show at this point since we lost that
2728                 // information.  Not a big deal -- for the windows that have app
2729                 // ops modifies they should only be hidden by policy due to the
2730                 // lock screen, and the user won't be changing this if locked.
2731                 // Plus it will quickly be fixed the next time we do a layout.
2732                 showLw(true, true);
2733             } else {
2734                 hideLw(true, true);
2735             }
2736         }
2737     }
2738 
initAppOpsState()2739     void initAppOpsState() {
2740         if (mAppOp == OP_NONE || !mAppOpVisibility) {
2741             return;
2742         }
2743         // If the app op was MODE_DEFAULT we would have checked the permission
2744         // and add the window only if the permission was granted. Therefore, if
2745         // the mode is MODE_DEFAULT we want the op to succeed as the window is
2746         // shown.
2747         final int mode = mWmService.mAppOps.startOpNoThrow(mAppOp,
2748                 getOwningUid(), getOwningPackage(), true);
2749         if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) {
2750             setAppOpVisibilityLw(false);
2751         }
2752     }
2753 
resetAppOpsState()2754     void resetAppOpsState() {
2755         if (mAppOp != OP_NONE && mAppOpVisibility) {
2756             mWmService.mAppOps.finishOp(mAppOp, getOwningUid(), getOwningPackage());
2757         }
2758     }
2759 
updateAppOpsState()2760     void updateAppOpsState() {
2761         if (mAppOp == OP_NONE) {
2762             return;
2763         }
2764         final int uid = getOwningUid();
2765         final String packageName = getOwningPackage();
2766         if (mAppOpVisibility) {
2767             // There is a race between the check and the finish calls but this is fine
2768             // as this would mean we will get another change callback and will reconcile.
2769             int mode = mWmService.mAppOps.checkOpNoThrow(mAppOp, uid, packageName);
2770             if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) {
2771                 mWmService.mAppOps.finishOp(mAppOp, uid, packageName);
2772                 setAppOpVisibilityLw(false);
2773             }
2774         } else {
2775             final int mode = mWmService.mAppOps.startOpNoThrow(mAppOp, uid, packageName, true);
2776             if (mode == MODE_ALLOWED || mode == MODE_DEFAULT) {
2777                 setAppOpVisibilityLw(true);
2778             }
2779         }
2780     }
2781 
hidePermanentlyLw()2782     public void hidePermanentlyLw() {
2783         if (!mPermanentlyHidden) {
2784             mPermanentlyHidden = true;
2785             hideLw(true, true);
2786         }
2787     }
2788 
pokeDrawLockLw(long timeout)2789     public void pokeDrawLockLw(long timeout) {
2790         if (isVisibleOrAdding()) {
2791             if (mDrawLock == null) {
2792                 // We want the tag name to be somewhat stable so that it is easier to correlate
2793                 // in wake lock statistics.  So in particular, we don't want to include the
2794                 // window's hash code as in toString().
2795                 final CharSequence tag = getWindowTag();
2796                 mDrawLock = mWmService.mPowerManager.newWakeLock(DRAW_WAKE_LOCK, "Window:" + tag);
2797                 mDrawLock.setReferenceCounted(false);
2798                 mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName));
2799             }
2800             // Each call to acquire resets the timeout.
2801             if (DEBUG_POWER) {
2802                 Slog.d(TAG, "pokeDrawLock: poking draw lock on behalf of visible window owned by "
2803                         + mAttrs.packageName);
2804             }
2805             mDrawLock.acquire(timeout);
2806         } else if (DEBUG_POWER) {
2807             Slog.d(TAG, "pokeDrawLock: suppressed draw lock request for invisible window "
2808                     + "owned by " + mAttrs.packageName);
2809         }
2810     }
2811 
2812     @Override
isAlive()2813     public boolean isAlive() {
2814         return mClient.asBinder().isBinderAlive();
2815     }
2816 
isClosing()2817     boolean isClosing() {
2818         return mAnimatingExit || (mAppToken != null && mAppToken.isClosingOrEnteringPip());
2819     }
2820 
addWinAnimatorToList(ArrayList<WindowStateAnimator> animators)2821     void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) {
2822         animators.add(mWinAnimator);
2823 
2824         for (int i = mChildren.size() - 1; i >= 0; --i) {
2825             final WindowState c = mChildren.get(i);
2826             c.addWinAnimatorToList(animators);
2827         }
2828     }
2829 
sendAppVisibilityToClients()2830     void sendAppVisibilityToClients() {
2831         super.sendAppVisibilityToClients();
2832 
2833         final boolean clientHidden = mAppToken.isClientHidden();
2834         if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) {
2835             // Don't hide the starting window.
2836             return;
2837         }
2838 
2839         if (clientHidden) {
2840             // Once we are notifying the client that it's visibility has changed, we need to prevent
2841             // it from destroying child surfaces until the animation has finished. We do this by
2842             // detaching any surface control the client added from the client.
2843             for (int i = mChildren.size() - 1; i >= 0; --i) {
2844                 final WindowState c = mChildren.get(i);
2845                 c.mWinAnimator.detachChildren();
2846             }
2847 
2848             mWinAnimator.detachChildren();
2849         }
2850 
2851         try {
2852             if (DEBUG_VISIBILITY) Slog.v(TAG,
2853                     "Setting visibility of " + this + ": " + (!clientHidden));
2854             mClient.dispatchAppVisibility(!clientHidden);
2855         } catch (RemoteException e) {
2856         }
2857     }
2858 
onStartFreezingScreen()2859     void onStartFreezingScreen() {
2860         mAppFreezing = true;
2861         for (int i = mChildren.size() - 1; i >= 0; --i) {
2862             final WindowState c = mChildren.get(i);
2863             c.onStartFreezingScreen();
2864         }
2865     }
2866 
onStopFreezingScreen()2867     boolean onStopFreezingScreen() {
2868         boolean unfrozeWindows = false;
2869         for (int i = mChildren.size() - 1; i >= 0; --i) {
2870             final WindowState c = mChildren.get(i);
2871             unfrozeWindows |= c.onStopFreezingScreen();
2872         }
2873 
2874         if (!mAppFreezing) {
2875             return unfrozeWindows;
2876         }
2877 
2878         mAppFreezing = false;
2879 
2880         if (mHasSurface && !getOrientationChanging()
2881                 && mWmService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
2882             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + this);
2883             setOrientationChanging(true);
2884             mWmService.mRoot.mOrientationChangeComplete = false;
2885         }
2886         mLastFreezeDuration = 0;
2887         setDisplayLayoutNeeded();
2888         return true;
2889     }
2890 
destroySurface(boolean cleanupOnResume, boolean appStopped)2891     boolean destroySurface(boolean cleanupOnResume, boolean appStopped) {
2892         boolean destroyedSomething = false;
2893 
2894         // Copying to a different list as multiple children can be removed.
2895         final ArrayList<WindowState> childWindows = new ArrayList<>(mChildren);
2896         for (int i = childWindows.size() - 1; i >= 0; --i) {
2897             final WindowState c = childWindows.get(i);
2898             destroyedSomething |= c.destroySurface(cleanupOnResume, appStopped);
2899         }
2900 
2901         if (!(appStopped || mWindowRemovalAllowed || cleanupOnResume)) {
2902             return destroyedSomething;
2903         }
2904 
2905         if (appStopped || mWindowRemovalAllowed) {
2906             mWinAnimator.destroyPreservedSurfaceLocked();
2907         }
2908 
2909         if (mDestroying) {
2910             if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + this
2911                     + " destroySurfaces: appStopped=" + appStopped
2912                     + " win.mWindowRemovalAllowed=" + mWindowRemovalAllowed
2913                     + " win.mRemoveOnExit=" + mRemoveOnExit);
2914             if (!cleanupOnResume || mRemoveOnExit) {
2915                 destroySurfaceUnchecked();
2916             }
2917             if (mRemoveOnExit) {
2918                 removeImmediately();
2919             }
2920             if (cleanupOnResume) {
2921                 requestUpdateWallpaperIfNeeded();
2922             }
2923             mDestroying = false;
2924             destroyedSomething = true;
2925 
2926             // Since mDestroying will affect AppWindowToken#allDrawn, we need to perform another
2927             // traversal in case we are waiting on this window to start the transition.
2928             if (getDisplayContent().mAppTransition.isTransitionSet()
2929                     && getDisplayContent().mOpeningApps.contains(mAppToken)) {
2930                 mWmService.mWindowPlacerLocked.requestTraversal();
2931             }
2932         }
2933 
2934         return destroyedSomething;
2935     }
2936 
2937     // Destroy or save the application surface without checking
2938     // various indicators of whether the client has released the surface.
2939     // This is in general unsafe, and most callers should use {@link #destroySurface}
destroySurfaceUnchecked()2940     void destroySurfaceUnchecked() {
2941         mWinAnimator.destroySurfaceLocked();
2942 
2943         // Clear animating flags now, since the surface is now gone. (Note this is true even
2944         // if the surface is saved, to outside world the surface is still NO_SURFACE.)
2945         mAnimatingExit = false;
2946     }
2947 
2948     @Override
isDefaultDisplay()2949     public boolean isDefaultDisplay() {
2950         final DisplayContent displayContent = getDisplayContent();
2951         if (displayContent == null) {
2952             // Only a window that was on a non-default display can be detached from it.
2953             return false;
2954         }
2955         return displayContent.isDefaultDisplay;
2956     }
2957 
setShowToOwnerOnlyLocked(boolean showToOwnerOnly)2958     void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
2959         mShowToOwnerOnly = showToOwnerOnly;
2960     }
2961 
isHiddenFromUserLocked()2962     private boolean isHiddenFromUserLocked() {
2963         // Child windows are evaluated based on their parent window.
2964         final WindowState win = getTopParentWindow();
2965         if (win.mAttrs.type < FIRST_SYSTEM_WINDOW
2966                 && win.mAppToken != null && win.mAppToken.mShowForAllUsers) {
2967 
2968             // All window frames that are fullscreen extend above status bar, but some don't extend
2969             // below navigation bar. Thus, check for display frame for top/left and stable frame for
2970             // bottom right.
2971             if (win.getFrameLw().left <= win.getDisplayFrameLw().left
2972                     && win.getFrameLw().top <= win.getDisplayFrameLw().top
2973                     && win.getFrameLw().right >= win.getStableFrameLw().right
2974                     && win.getFrameLw().bottom >= win.getStableFrameLw().bottom) {
2975                 // Is a fullscreen window, like the clock alarm. Show to everyone.
2976                 return false;
2977             }
2978         }
2979 
2980         return win.mShowToOwnerOnly
2981                 && !mWmService.isCurrentProfileLocked(UserHandle.getUserId(win.mOwnerUid));
2982     }
2983 
applyInsets(Region outRegion, Rect frame, Rect inset)2984     private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
2985         outRegion.set(
2986                 frame.left + inset.left, frame.top + inset.top,
2987                 frame.right - inset.right, frame.bottom - inset.bottom);
2988     }
2989 
2990     /** Get the touchable region in global coordinates. */
getTouchableRegion(Region outRegion)2991     void getTouchableRegion(Region outRegion) {
2992         final Rect frame = mWindowFrames.mFrame;
2993         switch (mTouchableInsets) {
2994             default:
2995             case TOUCHABLE_INSETS_FRAME:
2996                 outRegion.set(frame);
2997                 break;
2998             case TOUCHABLE_INSETS_CONTENT:
2999                 applyInsets(outRegion, frame, mGivenContentInsets);
3000                 break;
3001             case TOUCHABLE_INSETS_VISIBLE:
3002                 applyInsets(outRegion, frame, mGivenVisibleInsets);
3003                 break;
3004             case TOUCHABLE_INSETS_REGION: {
3005                 outRegion.set(mGivenTouchableRegion);
3006                 outRegion.translate(frame.left, frame.top);
3007                 break;
3008             }
3009         }
3010         cropRegionToStackBoundsIfNeeded(outRegion);
3011         subtractTouchExcludeRegionIfNeeded(outRegion);
3012     }
3013 
3014     /**
3015      * Get the effective touchable region in global coordinates.
3016      *
3017      * In contrast to {@link #getTouchableRegion}, this takes into account
3018      * {@link WindowManager.LayoutParams#FLAG_NOT_TOUCH_MODAL touch modality.}
3019      */
getEffectiveTouchableRegion(Region outRegion)3020     void getEffectiveTouchableRegion(Region outRegion) {
3021         final boolean modal = (mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
3022         final DisplayContent dc = getDisplayContent();
3023 
3024         if (modal && dc != null) {
3025             outRegion.set(dc.getBounds());
3026             cropRegionToStackBoundsIfNeeded(outRegion);
3027             subtractTouchExcludeRegionIfNeeded(outRegion);
3028         } else {
3029             getTouchableRegion(outRegion);
3030         }
3031     }
3032 
setTouchableRegionCropIfNeeded(InputWindowHandle handle)3033     private void setTouchableRegionCropIfNeeded(InputWindowHandle handle) {
3034         final Task task = getTask();
3035         if (task == null || !task.cropWindowsToStackBounds()) {
3036             return;
3037         }
3038 
3039         final TaskStack stack = task.mStack;
3040         if (stack == null) {
3041             return;
3042         }
3043 
3044         handle.setTouchableRegionCrop(stack.getSurfaceControl());
3045     }
3046 
cropRegionToStackBoundsIfNeeded(Region region)3047     private void cropRegionToStackBoundsIfNeeded(Region region) {
3048         final Task task = getTask();
3049         if (task == null || !task.cropWindowsToStackBounds()) {
3050             return;
3051         }
3052 
3053         final TaskStack stack = task.mStack;
3054         if (stack == null) {
3055             return;
3056         }
3057 
3058         stack.getDimBounds(mTmpRect);
3059         region.op(mTmpRect, Region.Op.INTERSECT);
3060     }
3061 
3062     /**
3063      * If this window has areas that cannot be touched, we subtract those areas from its touchable
3064      * region.
3065      */
subtractTouchExcludeRegionIfNeeded(Region touchableRegion)3066     private void subtractTouchExcludeRegionIfNeeded(Region touchableRegion) {
3067         if (mTapExcludeRegionHolder == null) {
3068             return;
3069         }
3070         final Region touchExcludeRegion = Region.obtain();
3071         amendTapExcludeRegion(touchExcludeRegion);
3072         if (!touchExcludeRegion.isEmpty()) {
3073             touchableRegion.op(touchExcludeRegion, Region.Op.DIFFERENCE);
3074         }
3075         touchExcludeRegion.recycle();
3076     }
3077 
3078     /**
3079      * Report a focus change.  Must be called with no locks held, and consistently
3080      * from the same serialized thread (such as dispatched from a handler).
3081      */
reportFocusChangedSerialized(boolean focused, boolean inTouchMode)3082     void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) {
3083         try {
3084             mClient.windowFocusChanged(focused, inTouchMode);
3085         } catch (RemoteException e) {
3086         }
3087         if (mFocusCallbacks != null) {
3088             final int N = mFocusCallbacks.beginBroadcast();
3089             for (int i=0; i<N; i++) {
3090                 IWindowFocusObserver obs = mFocusCallbacks.getBroadcastItem(i);
3091                 try {
3092                     if (focused) {
3093                         obs.focusGained(mWindowId.asBinder());
3094                     } else {
3095                         obs.focusLost(mWindowId.asBinder());
3096                     }
3097                 } catch (RemoteException e) {
3098                 }
3099             }
3100             mFocusCallbacks.finishBroadcast();
3101         }
3102     }
3103 
3104     @Override
getConfiguration()3105     public Configuration getConfiguration() {
3106         if (mAppToken != null && mAppToken.mFrozenMergedConfig.size() > 0) {
3107             return mAppToken.mFrozenMergedConfig.peek();
3108         }
3109 
3110         // If the process has not registered to any display to listen to the configuration change,
3111         // we can simply return the mFullConfiguration as default.
3112         if (!registeredForDisplayConfigChanges()) {
3113             return super.getConfiguration();
3114         }
3115 
3116         // We use the process config this window is associated with as the based global config since
3117         // the process can override its config, but isn't part of the window hierarchy.
3118         mTempConfiguration.setTo(getProcessGlobalConfiguration());
3119         mTempConfiguration.updateFrom(getMergedOverrideConfiguration());
3120         return mTempConfiguration;
3121     }
3122 
3123     /** @return {@code true} if the process registered to a display as a config listener. */
registeredForDisplayConfigChanges()3124     private boolean registeredForDisplayConfigChanges() {
3125         final WindowState parentWindow = getParentWindow();
3126         final Session session = parentWindow != null ? parentWindow.mSession : mSession;
3127         // System process or invalid process cannot register to display config change.
3128         if (session.mPid == MY_PID || session.mPid < 0) return false;
3129         WindowProcessController app =
3130                 mWmService.mAtmService.getProcessController(session.mPid, session.mUid);
3131         if (app == null || !app.registeredForDisplayConfigChanges()) return false;
3132         return true;
3133     }
3134 
reportResized()3135     void reportResized() {
3136         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
3137         try {
3138             if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
3139                     + ": " + mWindowFrames.mCompatFrame);
3140             final MergedConfiguration mergedConfiguration =
3141                     new MergedConfiguration(mWmService.mRoot.getConfiguration(),
3142                     getMergedOverrideConfiguration());
3143 
3144             setLastReportedMergedConfiguration(mergedConfiguration);
3145 
3146             if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING)
3147                 Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
3148 
3149             final Rect frame = mWindowFrames.mCompatFrame;
3150             final Rect overscanInsets = mWindowFrames.mLastOverscanInsets;
3151             final Rect contentInsets = mWindowFrames.mLastContentInsets;
3152             final Rect visibleInsets = mWindowFrames.mLastVisibleInsets;
3153             final Rect stableInsets = mWindowFrames.mLastStableInsets;
3154             final Rect outsets = mWindowFrames.mLastOutsets;
3155             final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING;
3156             final boolean reportOrientation = mReportOrientationChanged;
3157             final int displayId = getDisplayId();
3158             final DisplayCutout displayCutout = getWmDisplayCutout().getDisplayCutout();
3159             if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
3160                     && mClient instanceof IWindow.Stub) {
3161                 // To prevent deadlock simulate one-way call if win.mClient is a local object.
3162                 mWmService.mH.post(new Runnable() {
3163                     @Override
3164                     public void run() {
3165                         try {
3166                             dispatchResized(frame, overscanInsets, contentInsets, visibleInsets,
3167                                     stableInsets, outsets, reportDraw, mergedConfiguration,
3168                                     reportOrientation, displayId, displayCutout);
3169                         } catch (RemoteException e) {
3170                             // Not a remote call, RemoteException won't be raised.
3171                         }
3172                     }
3173                 });
3174             } else {
3175                 dispatchResized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets,
3176                         outsets, reportDraw, mergedConfiguration, reportOrientation, displayId,
3177                         displayCutout);
3178             }
3179 
3180             //TODO (multidisplay): Accessibility supported only for the default display.
3181             if (mWmService.mAccessibilityController != null && (getDisplayId() == DEFAULT_DISPLAY
3182                     || getDisplayContent().getParentWindow() != null)) {
3183                 mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
3184             }
3185 
3186             mWindowFrames.resetInsetsChanged();
3187             mWinAnimator.mSurfaceResized = false;
3188             mReportOrientationChanged = false;
3189         } catch (RemoteException e) {
3190             setOrientationChanging(false);
3191             mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
3192                     - mWmService.mDisplayFreezeTime);
3193             // We are assuming the hosting process is dead or in a zombie state.
3194             Slog.w(TAG, "Failed to report 'resized' to the client of " + this
3195                     + ", removing this window.");
3196             mWmService.mPendingRemove.add(this);
3197             mWmService.mWindowPlacerLocked.requestTraversal();
3198         }
3199         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3200     }
3201 
3202     /**
3203      * Called when the insets state changed.
3204      */
notifyInsetsChanged()3205     void notifyInsetsChanged() {
3206         try {
3207             mClient.insetsChanged(
3208                     getDisplayContent().getInsetsStateController().getInsetsForDispatch(this));
3209         } catch (RemoteException e) {
3210             Slog.w(TAG, "Failed to deliver inset state change", e);
3211         }
3212     }
3213 
notifyInsetsControlChanged()3214     void notifyInsetsControlChanged() {
3215         final InsetsStateController stateController =
3216                 getDisplayContent().getInsetsStateController();
3217         try {
3218             mClient.insetsControlChanged(stateController.getInsetsForDispatch(this),
3219                     stateController.getControlsForDispatch(this));
3220         } catch (RemoteException e) {
3221             Slog.w(TAG, "Failed to deliver inset state change", e);
3222         }
3223     }
3224 
getBackdropFrame(Rect frame)3225     Rect getBackdropFrame(Rect frame) {
3226         // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
3227         // start even if we haven't received the relayout window, so that the client requests
3228         // the relayout sooner. When dragging stops, backDropFrame needs to stay fullscreen
3229         // until the window to small size, otherwise the multithread renderer will shift last
3230         // one or more frame to wrong offset. So here we send fullscreen backdrop if either
3231         // isDragResizing() or isDragResizeChanged() is true.
3232         boolean resizing = isDragResizing() || isDragResizeChanged();
3233         if (getWindowConfiguration().useWindowFrameForBackdrop() || !resizing) {
3234             // Surface position is now inherited from parent, and BackdropFrameRenderer uses
3235             // backdrop frame to position content. Thus we just keep the size of backdrop frame, and
3236             // remove the offset to avoid double offset from display origin.
3237             mTmpRect.set(frame);
3238             mTmpRect.offsetTo(0, 0);
3239             return mTmpRect;
3240         }
3241         final DisplayInfo displayInfo = getDisplayInfo();
3242         mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
3243         return mTmpRect;
3244     }
3245 
getStackId()3246     private int getStackId() {
3247         final TaskStack stack = getStack();
3248         if (stack == null) {
3249             return INVALID_STACK_ID;
3250         }
3251         return stack.mStackId;
3252     }
3253 
dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, boolean reportOrientation, int displayId, DisplayCutout displayCutout)3254     private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
3255             Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
3256             MergedConfiguration mergedConfiguration, boolean reportOrientation, int displayId,
3257             DisplayCutout displayCutout)
3258             throws RemoteException {
3259         final boolean forceRelayout = isDragResizeChanged() || reportOrientation;
3260 
3261         mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets,
3262                 reportDraw, mergedConfiguration, getBackdropFrame(frame), forceRelayout,
3263                 getDisplayContent().getDisplayPolicy().areSystemBarsForcedShownLw(this), displayId,
3264                 new DisplayCutout.ParcelableWrapper(displayCutout));
3265         mDragResizingChangeReported = true;
3266     }
3267 
registerFocusObserver(IWindowFocusObserver observer)3268     public void registerFocusObserver(IWindowFocusObserver observer) {
3269         synchronized (mWmService.mGlobalLock) {
3270             if (mFocusCallbacks == null) {
3271                 mFocusCallbacks = new RemoteCallbackList<IWindowFocusObserver>();
3272             }
3273             mFocusCallbacks.register(observer);
3274         }
3275     }
3276 
unregisterFocusObserver(IWindowFocusObserver observer)3277     public void unregisterFocusObserver(IWindowFocusObserver observer) {
3278         synchronized (mWmService.mGlobalLock) {
3279             if (mFocusCallbacks != null) {
3280                 mFocusCallbacks.unregister(observer);
3281             }
3282         }
3283     }
3284 
isFocused()3285     boolean isFocused() {
3286         return getDisplayContent().mCurrentFocus == this;
3287     }
3288 
3289 
3290     /** Is this window in a container that takes up the entire screen space? */
inAppWindowThatMatchesParentBounds()3291     private boolean inAppWindowThatMatchesParentBounds() {
3292         return mAppToken == null || (mAppToken.matchParentBounds() && !inMultiWindowMode());
3293     }
3294 
3295     /** @return true when the window is in fullscreen mode, but has non-fullscreen bounds set, or
3296      *          is transitioning into/out-of fullscreen. */
isLetterboxedAppWindow()3297     boolean isLetterboxedAppWindow() {
3298         return !inMultiWindowMode() && !matchesDisplayBounds()
3299                 || isLetterboxedForDisplayCutoutLw();
3300     }
3301 
3302     @Override
isLetterboxedForDisplayCutoutLw()3303     public boolean isLetterboxedForDisplayCutoutLw() {
3304         if (mAppToken == null) {
3305             // Only windows with an AppWindowToken are letterboxed.
3306             return false;
3307         }
3308         if (!mWindowFrames.parentFrameWasClippedByDisplayCutout()) {
3309             // Cutout didn't make a difference, no letterbox
3310             return false;
3311         }
3312         if (mAttrs.layoutInDisplayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
3313             // Layout in cutout, no letterbox.
3314             return false;
3315         }
3316         if (!mAttrs.isFullscreen()) {
3317             // Not filling the parent frame, no letterbox
3318             return false;
3319         }
3320         // Otherwise we need a letterbox if the layout was smaller than the app window token allowed
3321         // it to be.
3322         return !frameCoversEntireAppTokenBounds();
3323     }
3324 
3325     /**
3326      * @return true if this window covers the entire bounds of its app window token
3327      * @throws NullPointerException if there is no app window token for this window
3328      */
frameCoversEntireAppTokenBounds()3329     private boolean frameCoversEntireAppTokenBounds() {
3330         mTmpRect.set(mAppToken.getBounds());
3331         mTmpRect.intersectUnchecked(mWindowFrames.mFrame);
3332         return mAppToken.getBounds().equals(mTmpRect);
3333     }
3334 
3335     @Override
isLetterboxedOverlappingWith(Rect rect)3336     public boolean isLetterboxedOverlappingWith(Rect rect) {
3337         return mAppToken != null && mAppToken.isLetterboxOverlappingWith(rect);
3338     }
3339 
isDragResizeChanged()3340     boolean isDragResizeChanged() {
3341         return mDragResizing != computeDragResizing();
3342     }
3343 
3344     @Override
setWaitingForDrawnIfResizingChanged()3345     void setWaitingForDrawnIfResizingChanged() {
3346         if (isDragResizeChanged()) {
3347             mWmService.mWaitingForDrawn.add(this);
3348         }
3349         super.setWaitingForDrawnIfResizingChanged();
3350     }
3351 
3352     /**
3353      * @return Whether we reported a drag resize change to the application or not already.
3354      */
isDragResizingChangeReported()3355     private boolean isDragResizingChangeReported() {
3356         return mDragResizingChangeReported;
3357     }
3358 
3359     /**
3360      * Resets the state whether we reported a drag resize change to the app.
3361      */
3362     @Override
resetDragResizingChangeReported()3363     void resetDragResizingChangeReported() {
3364         mDragResizingChangeReported = false;
3365         super.resetDragResizingChangeReported();
3366     }
3367 
getResizeMode()3368     int getResizeMode() {
3369         return mResizeMode;
3370     }
3371 
computeDragResizing()3372     private boolean computeDragResizing() {
3373         final Task task = getTask();
3374         if (task == null) {
3375             return false;
3376         }
3377         if (!inSplitScreenWindowingMode() && !inFreeformWindowingMode()) {
3378             return false;
3379         }
3380         if (mAttrs.width != MATCH_PARENT || mAttrs.height != MATCH_PARENT) {
3381             // Floating windows never enter drag resize mode.
3382             return false;
3383         }
3384         if (task.isDragResizing()) {
3385             return true;
3386         }
3387 
3388         // If the bounds are currently frozen, it means that the layout size that the app sees
3389         // and the bounds we clip this window to might be different. In order to avoid holes, we
3390         // simulate that we are still resizing so the app fills the hole with the resizing
3391         // background.
3392         return (getDisplayContent().mDividerControllerLocked.isResizing()
3393                         || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) &&
3394                 !task.inFreeformWindowingMode() && !isGoneForLayoutLw();
3395 
3396     }
3397 
setDragResizing()3398     void setDragResizing() {
3399         final boolean resizing = computeDragResizing();
3400         if (resizing == mDragResizing) {
3401             return;
3402         }
3403         mDragResizing = resizing;
3404         final Task task = getTask();
3405         if (task != null && task.isDragResizing()) {
3406             mResizeMode = task.getDragResizeMode();
3407         } else {
3408             mResizeMode = mDragResizing && getDisplayContent().mDividerControllerLocked.isResizing()
3409                     ? DRAG_RESIZE_MODE_DOCKED_DIVIDER
3410                     : DRAG_RESIZE_MODE_FREEFORM;
3411         }
3412     }
3413 
isDragResizing()3414     boolean isDragResizing() {
3415         return mDragResizing;
3416     }
3417 
isDockedResizing()3418     boolean isDockedResizing() {
3419         return (mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER)
3420                 || (isChildWindow() && getParentWindow().isDockedResizing());
3421     }
3422 
3423     @CallSuper
3424     @Override
writeToProto(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)3425     public void writeToProto(ProtoOutputStream proto, long fieldId,
3426             @WindowTraceLogLevel int logLevel) {
3427         boolean isVisible = isVisible();
3428         if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) {
3429             return;
3430         }
3431 
3432         final long token = proto.start(fieldId);
3433         super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
3434         writeIdentifierToProto(proto, IDENTIFIER);
3435         proto.write(DISPLAY_ID, getDisplayId());
3436         proto.write(STACK_ID, getStackId());
3437         mAttrs.writeToProto(proto, ATTRIBUTES);
3438         mGivenContentInsets.writeToProto(proto, GIVEN_CONTENT_INSETS);
3439         mWindowFrames.writeToProto(proto, WINDOW_FRAMES);
3440         mAttrs.surfaceInsets.writeToProto(proto, SURFACE_INSETS);
3441         mSurfacePosition.writeToProto(proto, SURFACE_POSITION);
3442         mWinAnimator.writeToProto(proto, ANIMATOR);
3443         proto.write(ANIMATING_EXIT, mAnimatingExit);
3444         for (int i = 0; i < mChildren.size(); i++) {
3445             mChildren.get(i).writeToProto(proto, CHILD_WINDOWS, logLevel);
3446         }
3447         proto.write(REQUESTED_WIDTH, mRequestedWidth);
3448         proto.write(REQUESTED_HEIGHT, mRequestedHeight);
3449         proto.write(VIEW_VISIBILITY, mViewVisibility);
3450         proto.write(SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
3451         proto.write(HAS_SURFACE, mHasSurface);
3452         proto.write(IS_READY_FOR_DISPLAY, isReadyForDisplay());
3453         proto.write(REMOVE_ON_EXIT, mRemoveOnExit);
3454         proto.write(DESTROYING, mDestroying);
3455         proto.write(REMOVED, mRemoved);
3456         proto.write(IS_ON_SCREEN, isOnScreen());
3457         proto.write(IS_VISIBLE, isVisible);
3458         proto.write(PENDING_SEAMLESS_ROTATION, mPendingSeamlessRotate != null);
3459         proto.write(FINISHED_SEAMLESS_ROTATION_FRAME, mFinishSeamlessRotateFrameNumber);
3460         proto.write(FORCE_SEAMLESS_ROTATION, mForceSeamlesslyRotate);
3461         proto.end(token);
3462     }
3463 
3464     @Override
writeIdentifierToProto(ProtoOutputStream proto, long fieldId)3465     public void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
3466         final long token = proto.start(fieldId);
3467         proto.write(HASH_CODE, System.identityHashCode(this));
3468         proto.write(USER_ID, UserHandle.getUserId(mOwnerUid));
3469         final CharSequence title = getWindowTag();
3470         if (title != null) {
3471             proto.write(TITLE, title.toString());
3472         }
3473         proto.end(token);
3474     }
3475 
3476     @Override
dump(PrintWriter pw, String prefix, boolean dumpAll)3477     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3478         final TaskStack stack = getStack();
3479         pw.print(prefix + "mDisplayId=" + getDisplayId());
3480         if (stack != null) {
3481             pw.print(" stackId=" + stack.mStackId);
3482         }
3483         pw.println(" mSession=" + mSession
3484                 + " mClient=" + mClient.asBinder());
3485         pw.println(prefix + "mOwnerUid=" + mOwnerUid
3486                 + " mShowToOwnerOnly=" + mShowToOwnerOnly
3487                 + " package=" + mAttrs.packageName
3488                 + " appop=" + AppOpsManager.opToName(mAppOp));
3489         pw.println(prefix + "mAttrs=" + mAttrs.toString(prefix));
3490         pw.println(prefix + "Requested w=" + mRequestedWidth
3491                 + " h=" + mRequestedHeight
3492                 + " mLayoutSeq=" + mLayoutSeq);
3493         if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
3494             pw.println(prefix + "LastRequested w=" + mLastRequestedWidth
3495                     + " h=" + mLastRequestedHeight);
3496         }
3497         if (mIsChildWindow || mLayoutAttached) {
3498             pw.println(prefix + "mParentWindow=" + getParentWindow()
3499                     + " mLayoutAttached=" + mLayoutAttached);
3500         }
3501         if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
3502             pw.println(prefix + "mIsImWindow=" + mIsImWindow
3503                     + " mIsWallpaper=" + mIsWallpaper
3504                     + " mIsFloatingLayer=" + mIsFloatingLayer
3505                     + " mWallpaperVisible=" + mWallpaperVisible);
3506         }
3507         if (dumpAll) {
3508             pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
3509                     pw.print(" mSubLayer="); pw.print(mSubLayer);
3510         }
3511         if (dumpAll) {
3512             pw.println(prefix + "mToken=" + mToken);
3513             if (mAppToken != null) {
3514                 pw.println(prefix + "mAppToken=" + mAppToken);
3515                 pw.print(prefix + "mAppDied=" + mAppDied);
3516                 pw.print(prefix + "drawnStateEvaluated=" + getDrawnStateEvaluated());
3517                 pw.println(prefix + "mightAffectAllDrawn=" + mightAffectAllDrawn());
3518             }
3519             pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility)
3520                     + " mHaveFrame=" + mHaveFrame
3521                     + " mObscured=" + mObscured);
3522             pw.println(prefix + "mSeq=" + mSeq
3523                     + " mSystemUiVisibility=0x" + Integer.toHexString(mSystemUiVisibility));
3524         }
3525         if (!isVisibleByPolicy() || !mLegacyPolicyVisibilityAfterAnim || !mAppOpVisibility
3526                 || isParentWindowHidden() || mPermanentlyHidden || mForceHideNonSystemOverlayWindow
3527                 || mHiddenWhileSuspended) {
3528             pw.println(prefix + "mPolicyVisibility=" + isVisibleByPolicy()
3529                     + " mLegacyPolicyVisibilityAfterAnim=" + mLegacyPolicyVisibilityAfterAnim
3530                     + " mAppOpVisibility=" + mAppOpVisibility
3531                     + " parentHidden=" + isParentWindowHidden()
3532                     + " mPermanentlyHidden=" + mPermanentlyHidden
3533                     + " mHiddenWhileSuspended=" + mHiddenWhileSuspended
3534                     + " mForceHideNonSystemOverlayWindow=" + mForceHideNonSystemOverlayWindow);
3535         }
3536         if (!mRelayoutCalled || mLayoutNeeded) {
3537             pw.println(prefix + "mRelayoutCalled=" + mRelayoutCalled
3538                     + " mLayoutNeeded=" + mLayoutNeeded);
3539         }
3540         if (dumpAll) {
3541             pw.println(prefix + "mGivenContentInsets=" + mGivenContentInsets.toShortString(sTmpSB)
3542                     + " mGivenVisibleInsets=" + mGivenVisibleInsets.toShortString(sTmpSB));
3543             if (mTouchableInsets != 0 || mGivenInsetsPending) {
3544                 pw.println(prefix + "mTouchableInsets=" + mTouchableInsets
3545                         + " mGivenInsetsPending=" + mGivenInsetsPending);
3546                 Region region = new Region();
3547                 getTouchableRegion(region);
3548                 pw.println(prefix + "touchable region=" + region);
3549             }
3550             pw.println(prefix + "mFullConfiguration=" + getConfiguration());
3551             pw.println(prefix + "mLastReportedConfiguration=" + getLastReportedConfiguration());
3552         }
3553         pw.println(prefix + "mHasSurface=" + mHasSurface
3554                 + " isReadyForDisplay()=" + isReadyForDisplay()
3555                 + " mWindowRemovalAllowed=" + mWindowRemovalAllowed);
3556         if (inSizeCompatMode()) {
3557             pw.println(prefix + "mCompatFrame=" + mWindowFrames.mCompatFrame.toShortString(sTmpSB));
3558         }
3559         if (dumpAll) {
3560             mWindowFrames.dump(pw, prefix);
3561             pw.println(prefix + " surface=" + mAttrs.surfaceInsets.toShortString(sTmpSB));
3562         }
3563         super.dump(pw, prefix, dumpAll);
3564         pw.println(prefix + mWinAnimator + ":");
3565         mWinAnimator.dump(pw, prefix + "  ", dumpAll);
3566         if (mAnimatingExit || mRemoveOnExit || mDestroying || mRemoved) {
3567             pw.println(prefix + "mAnimatingExit=" + mAnimatingExit
3568                     + " mRemoveOnExit=" + mRemoveOnExit
3569                     + " mDestroying=" + mDestroying
3570                     + " mRemoved=" + mRemoved);
3571         }
3572         if (getOrientationChanging() || mAppFreezing || mReportOrientationChanged) {
3573             pw.println(prefix + "mOrientationChanging=" + mOrientationChanging
3574                     + " configOrientationChanging="
3575                     + (getLastReportedConfiguration().orientation != getConfiguration().orientation)
3576                     + " mAppFreezing=" + mAppFreezing
3577                     + " mReportOrientationChanged=" + mReportOrientationChanged);
3578         }
3579         if (mLastFreezeDuration != 0) {
3580             pw.print(prefix + "mLastFreezeDuration=");
3581             TimeUtils.formatDuration(mLastFreezeDuration, pw);
3582             pw.println();
3583         }
3584         pw.print(prefix + "mForceSeamlesslyRotate=" + mForceSeamlesslyRotate
3585                 + " seamlesslyRotate: pending=");
3586         if (mPendingSeamlessRotate != null) {
3587             mPendingSeamlessRotate.dump(pw);
3588         } else {
3589             pw.print("null");
3590         }
3591         pw.println(" finishedFrameNumber=" + mFinishSeamlessRotateFrameNumber);
3592 
3593         if (mHScale != 1 || mVScale != 1) {
3594             pw.println(prefix + "mHScale=" + mHScale
3595                     + " mVScale=" + mVScale);
3596         }
3597         if (mWallpaperX != -1 || mWallpaperY != -1) {
3598             pw.println(prefix + "mWallpaperX=" + mWallpaperX
3599                     + " mWallpaperY=" + mWallpaperY);
3600         }
3601         if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
3602             pw.println(prefix + "mWallpaperXStep=" + mWallpaperXStep
3603                     + " mWallpaperYStep=" + mWallpaperYStep);
3604         }
3605         if (mWallpaperDisplayOffsetX != Integer.MIN_VALUE
3606                 || mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
3607             pw.println(prefix + "mWallpaperDisplayOffsetX=" + mWallpaperDisplayOffsetX
3608                     + " mWallpaperDisplayOffsetY=" + mWallpaperDisplayOffsetY);
3609         }
3610         if (mDrawLock != null) {
3611             pw.println(prefix + "mDrawLock=" + mDrawLock);
3612         }
3613         if (isDragResizing()) {
3614             pw.println(prefix + "isDragResizing=" + isDragResizing());
3615         }
3616         if (computeDragResizing()) {
3617             pw.println(prefix + "computeDragResizing=" + computeDragResizing());
3618         }
3619         pw.println(prefix + "isOnScreen=" + isOnScreen());
3620         pw.println(prefix + "isVisible=" + isVisible());
3621     }
3622 
3623     @Override
getName()3624     String getName() {
3625         return Integer.toHexString(System.identityHashCode(this))
3626                 + " " + getWindowTag();
3627     }
3628 
getWindowTag()3629     CharSequence getWindowTag() {
3630         CharSequence tag = mAttrs.getTitle();
3631         if (tag == null || tag.length() <= 0) {
3632             tag = mAttrs.packageName;
3633         }
3634         return tag;
3635     }
3636 
3637     @Override
toString()3638     public String toString() {
3639         final CharSequence title = getWindowTag();
3640         if (mStringNameCache == null || mLastTitle != title || mWasExiting != mAnimatingExit) {
3641             mLastTitle = title;
3642             mWasExiting = mAnimatingExit;
3643             mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
3644                     + " u" + UserHandle.getUserId(mOwnerUid)
3645                     + " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}");
3646         }
3647         return mStringNameCache;
3648     }
3649 
transformClipRectFromScreenToSurfaceSpace(Rect clipRect)3650     void transformClipRectFromScreenToSurfaceSpace(Rect clipRect) {
3651         if (mHScale == 1 && mVScale == 1) {
3652             return;
3653         }
3654         if (mHScale >= 0) {
3655             clipRect.left = (int) (clipRect.left / mHScale);
3656             clipRect.right = (int) Math.ceil(clipRect.right / mHScale);
3657         }
3658         if (mVScale >= 0) {
3659             clipRect.top = (int) (clipRect.top / mVScale);
3660             clipRect.bottom = (int) Math.ceil(clipRect.bottom / mVScale);
3661         }
3662     }
3663 
applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame)3664     private void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
3665         final int pw = containingFrame.width();
3666         final int ph = containingFrame.height();
3667         final Task task = getTask();
3668         final boolean inNonFullscreenContainer = !inAppWindowThatMatchesParentBounds();
3669         final boolean noLimits = (mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;
3670 
3671         // We need to fit it to the display if either
3672         // a) The window is in a fullscreen container, or we don't have a task (we assume fullscreen
3673         // for the taskless windows)
3674         // b) If it's a secondary app window, we also need to fit it to the display unless
3675         // FLAG_LAYOUT_NO_LIMITS is set. This is so we place Popups, dialogs, and similar windows on
3676         // screen, but SurfaceViews want to be always at a specific location so we don't fit it to
3677         // the display.
3678         final boolean fitToDisplay = (task == null || !inNonFullscreenContainer)
3679                 || ((mAttrs.type != TYPE_BASE_APPLICATION) && !noLimits);
3680         float x, y;
3681         int w,h;
3682 
3683         final boolean inSizeCompatMode = inSizeCompatMode();
3684         if ((mAttrs.flags & FLAG_SCALED) != 0) {
3685             if (mAttrs.width < 0) {
3686                 w = pw;
3687             } else if (inSizeCompatMode) {
3688                 w = (int)(mAttrs.width * mGlobalScale + .5f);
3689             } else {
3690                 w = mAttrs.width;
3691             }
3692             if (mAttrs.height < 0) {
3693                 h = ph;
3694             } else if (inSizeCompatMode) {
3695                 h = (int)(mAttrs.height * mGlobalScale + .5f);
3696             } else {
3697                 h = mAttrs.height;
3698             }
3699         } else {
3700             if (mAttrs.width == MATCH_PARENT) {
3701                 w = pw;
3702             } else if (inSizeCompatMode) {
3703                 w = (int)(mRequestedWidth * mGlobalScale + .5f);
3704             } else {
3705                 w = mRequestedWidth;
3706             }
3707             if (mAttrs.height == MATCH_PARENT) {
3708                 h = ph;
3709             } else if (inSizeCompatMode) {
3710                 h = (int)(mRequestedHeight * mGlobalScale + .5f);
3711             } else {
3712                 h = mRequestedHeight;
3713             }
3714         }
3715 
3716         if (inSizeCompatMode) {
3717             x = mAttrs.x * mGlobalScale;
3718             y = mAttrs.y * mGlobalScale;
3719         } else {
3720             x = mAttrs.x;
3721             y = mAttrs.y;
3722         }
3723 
3724         if (inNonFullscreenContainer && !layoutInParentFrame()) {
3725             // Make sure window fits in containing frame since it is in a non-fullscreen task as
3726             // required by {@link Gravity#apply} call.
3727             w = Math.min(w, pw);
3728             h = Math.min(h, ph);
3729         }
3730 
3731         // Set mFrame
3732         Gravity.apply(mAttrs.gravity, w, h, containingFrame,
3733                 (int) (x + mAttrs.horizontalMargin * pw),
3734                 (int) (y + mAttrs.verticalMargin * ph), mWindowFrames.mFrame);
3735 
3736         // Now make sure the window fits in the overall display frame.
3737         if (fitToDisplay) {
3738             Gravity.applyDisplay(mAttrs.gravity, displayFrame, mWindowFrames.mFrame);
3739         }
3740 
3741         // We need to make sure we update the CompatFrame as it is used for
3742         // cropping decisions, etc, on systems where we lack a decor layer.
3743         mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame);
3744         if (inSizeCompatMode) {
3745             // See comparable block in computeFrameLw.
3746             mWindowFrames.mCompatFrame.scale(mInvGlobalScale);
3747         }
3748     }
3749 
isChildWindow()3750     boolean isChildWindow() {
3751         return mIsChildWindow;
3752     }
3753 
layoutInParentFrame()3754     boolean layoutInParentFrame() {
3755         return mIsChildWindow
3756                 && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
3757     }
3758 
3759     /**
3760      * Returns true if any window added by an application process that if of type
3761      * {@link android.view.WindowManager.LayoutParams#TYPE_TOAST} or that requires that requires
3762      * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when
3763      * this window is visible.
3764      */
hideNonSystemOverlayWindowsWhenVisible()3765     boolean hideNonSystemOverlayWindowsWhenVisible() {
3766         return (mAttrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0
3767                 && mSession.mCanHideNonSystemOverlayWindows;
3768     }
3769 
3770     /** Returns the parent window if this is a child of another window, else null. */
getParentWindow()3771     WindowState getParentWindow() {
3772         // NOTE: We are not calling getParent() directly as the WindowState might be a child of a
3773         // WindowContainer that isn't a WindowState.
3774         return (mIsChildWindow) ? ((WindowState) super.getParent()) : null;
3775     }
3776 
3777     /** Returns the topmost parent window if this is a child of another window, else this. */
getTopParentWindow()3778     WindowState getTopParentWindow() {
3779         WindowState current = this;
3780         WindowState topParent = current;
3781         while (current != null && current.mIsChildWindow) {
3782             current = current.getParentWindow();
3783             // Parent window can be null if the child is detached from it's parent already, but
3784             // someone still has a reference to access it. So, we return the top parent value we
3785             // already have instead of null.
3786             if (current != null) {
3787                 topParent = current;
3788             }
3789         }
3790         return topParent;
3791     }
3792 
isParentWindowHidden()3793     boolean isParentWindowHidden() {
3794         final WindowState parent = getParentWindow();
3795         return parent != null && parent.mHidden;
3796     }
3797 
isParentWindowGoneForLayout()3798     private boolean isParentWindowGoneForLayout() {
3799         final WindowState parent = getParentWindow();
3800         return parent != null && parent.isGoneForLayoutLw();
3801     }
3802 
setWillReplaceWindow(boolean animate)3803     void setWillReplaceWindow(boolean animate) {
3804         for (int i = mChildren.size() - 1; i >= 0; i--) {
3805             final WindowState c = mChildren.get(i);
3806             c.setWillReplaceWindow(animate);
3807         }
3808 
3809         if ((mAttrs.privateFlags & PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH) != 0
3810                 || mAttrs.type == TYPE_APPLICATION_STARTING) {
3811             // We don't set replacing on starting windows since they are added by window manager and
3812             // not the client so won't be replaced by the client.
3813             return;
3814         }
3815 
3816         mWillReplaceWindow = true;
3817         mReplacementWindow = null;
3818         mAnimateReplacingWindow = animate;
3819     }
3820 
clearWillReplaceWindow()3821     void clearWillReplaceWindow() {
3822         mWillReplaceWindow = false;
3823         mReplacementWindow = null;
3824         mAnimateReplacingWindow = false;
3825 
3826         for (int i = mChildren.size() - 1; i >= 0; i--) {
3827             final WindowState c = mChildren.get(i);
3828             c.clearWillReplaceWindow();
3829         }
3830     }
3831 
waitingForReplacement()3832     boolean waitingForReplacement() {
3833         if (mWillReplaceWindow) {
3834             return true;
3835         }
3836 
3837         for (int i = mChildren.size() - 1; i >= 0; i--) {
3838             final WindowState c = mChildren.get(i);
3839             if (c.waitingForReplacement()) {
3840                 return true;
3841             }
3842         }
3843         return false;
3844     }
3845 
requestUpdateWallpaperIfNeeded()3846     void requestUpdateWallpaperIfNeeded() {
3847         final DisplayContent dc = getDisplayContent();
3848         if (dc != null && (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
3849             dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
3850             dc.setLayoutNeeded();
3851             mWmService.mWindowPlacerLocked.requestTraversal();
3852         }
3853 
3854         for (int i = mChildren.size() - 1; i >= 0; i--) {
3855             final WindowState c = mChildren.get(i);
3856             c.requestUpdateWallpaperIfNeeded();
3857         }
3858     }
3859 
translateToWindowX(float x)3860     float translateToWindowX(float x) {
3861         float winX = x - mWindowFrames.mFrame.left;
3862         if (inSizeCompatMode()) {
3863             winX *= mGlobalScale;
3864         }
3865         return winX;
3866     }
3867 
translateToWindowY(float y)3868     float translateToWindowY(float y) {
3869         float winY = y - mWindowFrames.mFrame.top;
3870         if (inSizeCompatMode()) {
3871             winY *= mGlobalScale;
3872         }
3873         return winY;
3874     }
3875 
3876     // During activity relaunch due to resize, we sometimes use window replacement
3877     // for only child windows (as the main window is handled by window preservation)
3878     // and the big surface.
3879     //
3880     // Though windows of TYPE_APPLICATION or TYPE_DRAWN_APPLICATION (as opposed to
3881     // TYPE_BASE_APPLICATION) are not children in the sense of an attached window,
3882     // we also want to replace them at such phases, as they won't be covered by window
3883     // preservation, and in general we expect them to return following relaunch.
shouldBeReplacedWithChildren()3884     boolean shouldBeReplacedWithChildren() {
3885         return mIsChildWindow || mAttrs.type == TYPE_APPLICATION
3886                 || mAttrs.type == TYPE_DRAWN_APPLICATION;
3887     }
3888 
setWillReplaceChildWindows()3889     void setWillReplaceChildWindows() {
3890         if (shouldBeReplacedWithChildren()) {
3891             setWillReplaceWindow(false /* animate */);
3892         }
3893         for (int i = mChildren.size() - 1; i >= 0; i--) {
3894             final WindowState c = mChildren.get(i);
3895             c.setWillReplaceChildWindows();
3896         }
3897     }
3898 
getReplacingWindow()3899     WindowState getReplacingWindow() {
3900         if (mAnimatingExit && mWillReplaceWindow && mAnimateReplacingWindow) {
3901             return this;
3902         }
3903         for (int i = mChildren.size() - 1; i >= 0; i--) {
3904             final WindowState c = mChildren.get(i);
3905             final WindowState replacing = c.getReplacingWindow();
3906             if (replacing != null) {
3907                 return replacing;
3908             }
3909         }
3910         return null;
3911     }
3912 
3913     @Override
getRotationAnimationHint()3914     public int getRotationAnimationHint() {
3915         if (mAppToken != null) {
3916             return mAppToken.mRotationAnimationHint;
3917         } else {
3918             return -1;
3919         }
3920     }
3921 
3922     @Override
isInputMethodWindow()3923     public boolean isInputMethodWindow() {
3924         return mIsImWindow;
3925     }
3926 
3927     // This must be called while inside a transaction.
performShowLocked()3928     boolean performShowLocked() {
3929         if (isHiddenFromUserLocked()) {
3930             if (DEBUG_VISIBILITY) Slog.w(TAG, "hiding " + this + ", belonging to " + mOwnerUid);
3931             clearPolicyVisibilityFlag(VISIBLE_FOR_USER);
3932             return false;
3933         }
3934 
3935         logPerformShow("performShow on ");
3936 
3937         final int drawState = mWinAnimator.mDrawState;
3938         if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW)
3939                 && mAttrs.type != TYPE_APPLICATION_STARTING && mAppToken != null) {
3940             mAppToken.onFirstWindowDrawn(this, mWinAnimator);
3941         }
3942 
3943         if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
3944             return false;
3945         }
3946 
3947         logPerformShow("Showing ");
3948 
3949         mWmService.enableScreenIfNeededLocked();
3950         mWinAnimator.applyEnterAnimationLocked();
3951 
3952         // Force the show in the next prepareSurfaceLocked() call.
3953         mWinAnimator.mLastAlpha = -1;
3954         if (DEBUG_ANIM) Slog.v(TAG,
3955                 "performShowLocked: mDrawState=HAS_DRAWN in " + this);
3956         mWinAnimator.mDrawState = HAS_DRAWN;
3957         mWmService.scheduleAnimationLocked();
3958 
3959         if (mHidden) {
3960             mHidden = false;
3961             final DisplayContent displayContent = getDisplayContent();
3962 
3963             for (int i = mChildren.size() - 1; i >= 0; --i) {
3964                 final WindowState c = mChildren.get(i);
3965                 if (c.mWinAnimator.mSurfaceController != null) {
3966                     c.performShowLocked();
3967                     // It hadn't been shown, which means layout not performed on it, so now we
3968                     // want to make sure to do a layout.  If called from within the transaction
3969                     // loop, this will cause it to restart with a new layout.
3970                     if (displayContent != null) {
3971                         displayContent.setLayoutNeeded();
3972                     }
3973                 }
3974             }
3975         }
3976 
3977         if (mAttrs.type == TYPE_INPUT_METHOD) {
3978             getDisplayContent().mDividerControllerLocked.resetImeHideRequested();
3979         }
3980 
3981         return true;
3982     }
3983 
logPerformShow(String prefix)3984     private void logPerformShow(String prefix) {
3985         if (DEBUG_VISIBILITY
3986                 || (DEBUG_STARTING_WINDOW_VERBOSE && mAttrs.type == TYPE_APPLICATION_STARTING)) {
3987             Slog.v(TAG, prefix + this
3988                     + ": mDrawState=" + mWinAnimator.drawStateToString()
3989                     + " readyForDisplay=" + isReadyForDisplay()
3990                     + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING)
3991                     + " during animation: policyVis=" + isVisibleByPolicy()
3992                     + " parentHidden=" + isParentWindowHidden()
3993                     + " tok.hiddenRequested="
3994                     + (mAppToken != null && mAppToken.hiddenRequested)
3995                     + " tok.hidden=" + (mAppToken != null && mAppToken.isHidden())
3996                     + " animating=" + isAnimating()
3997                     + " tok animating="
3998                     + (mAppToken != null && mAppToken.isSelfAnimating())
3999                     + " Callers=" + Debug.getCallers(4));
4000         }
4001     }
4002 
getWindowInfo()4003     WindowInfo getWindowInfo() {
4004         WindowInfo windowInfo = WindowInfo.obtain();
4005         windowInfo.type = mAttrs.type;
4006         windowInfo.layer = mLayer;
4007         windowInfo.token = mClient.asBinder();
4008         if (mAppToken != null) {
4009             windowInfo.activityToken = mAppToken.appToken.asBinder();
4010         }
4011         windowInfo.title = mAttrs.accessibilityTitle;
4012         // Panel windows have no public way to set the a11y title directly. Use the
4013         // regular title as a fallback.
4014         final boolean isPanelWindow = (mAttrs.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW)
4015                 && (mAttrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW);
4016         // Accessibility overlays should have titles that work for accessibility, and can't set
4017         // the a11y title themselves.
4018         final boolean isAccessibilityOverlay =
4019                 windowInfo.type == WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
4020         if (TextUtils.isEmpty(windowInfo.title) && (isPanelWindow || isAccessibilityOverlay)) {
4021             final CharSequence title = mAttrs.getTitle();
4022             windowInfo.title = TextUtils.isEmpty(title) ? null : title;
4023         }
4024         windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor;
4025         windowInfo.focused = isFocused();
4026         Task task = getTask();
4027         windowInfo.inPictureInPicture = (task != null) && task.inPinnedWindowingMode();
4028         windowInfo.hasFlagWatchOutsideTouch =
4029                 (mAttrs.flags & WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH) != 0;
4030 
4031         if (mIsChildWindow) {
4032             windowInfo.parentToken = getParentWindow().mClient.asBinder();
4033         }
4034 
4035         final int childCount = mChildren.size();
4036         if (childCount > 0) {
4037             if (windowInfo.childTokens == null) {
4038                 windowInfo.childTokens = new ArrayList(childCount);
4039             }
4040             for (int j = 0; j < childCount; j++) {
4041                 final WindowState child = mChildren.get(j);
4042                 windowInfo.childTokens.add(child.mClient.asBinder());
4043             }
4044         }
4045         return windowInfo;
4046     }
4047 
4048     @Override
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4049     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
4050         if (mChildren.isEmpty()) {
4051             // The window has no children so we just return it.
4052             return applyInOrderWithImeWindows(callback, traverseTopToBottom);
4053         }
4054 
4055         if (traverseTopToBottom) {
4056             return forAllWindowTopToBottom(callback);
4057         } else {
4058             return forAllWindowBottomToTop(callback);
4059         }
4060     }
4061 
forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback)4062     private boolean forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback) {
4063         // We want to consume the negative sublayer children first because they need to appear
4064         // below the parent, then this window (the parent), and then the positive sublayer children
4065         // because they need to appear above the parent.
4066         int i = 0;
4067         final int count = mChildren.size();
4068         WindowState child = mChildren.get(i);
4069 
4070         while (i < count && child.mSubLayer < 0) {
4071             if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
4072                 return true;
4073             }
4074             i++;
4075             if (i >= count) {
4076                 break;
4077             }
4078             child = mChildren.get(i);
4079         }
4080 
4081         if (applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
4082             return true;
4083         }
4084 
4085         while (i < count) {
4086             if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
4087                 return true;
4088             }
4089             i++;
4090             if (i >= count) {
4091                 break;
4092             }
4093             child = mChildren.get(i);
4094         }
4095 
4096         return false;
4097     }
4098 
forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback)4099     private boolean forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback) {
4100         // We want to consume the positive sublayer children first because they need to appear
4101         // above the parent, then this window (the parent), and then the negative sublayer children
4102         // because they need to appear above the parent.
4103         int i = mChildren.size() - 1;
4104         WindowState child = mChildren.get(i);
4105 
4106         while (i >= 0 && child.mSubLayer >= 0) {
4107             if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
4108                 return true;
4109             }
4110             --i;
4111             if (i < 0) {
4112                 break;
4113             }
4114             child = mChildren.get(i);
4115         }
4116 
4117         if (applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
4118             return true;
4119         }
4120 
4121         while (i >= 0) {
4122             if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
4123                 return true;
4124             }
4125             --i;
4126             if (i < 0) {
4127                 break;
4128             }
4129             child = mChildren.get(i);
4130         }
4131 
4132         return false;
4133     }
4134 
applyImeWindowsIfNeeded(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4135     private boolean applyImeWindowsIfNeeded(ToBooleanFunction<WindowState> callback,
4136             boolean traverseTopToBottom) {
4137         // If this window is the current IME target, so we need to process the IME windows
4138         // directly above it. The exception is if we are in split screen
4139         // in which case we process the IME at the DisplayContent level to
4140         // ensure it is above the docked divider.
4141         if (isInputMethodTarget() && !inSplitScreenWindowingMode()) {
4142             if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
4143                 return true;
4144             }
4145         }
4146         return false;
4147     }
4148 
applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4149     private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback,
4150             boolean traverseTopToBottom) {
4151         if (traverseTopToBottom) {
4152             if (applyImeWindowsIfNeeded(callback, traverseTopToBottom)
4153                     || callback.apply(this)) {
4154                 return true;
4155             }
4156         } else {
4157             if (callback.apply(this)
4158                     || applyImeWindowsIfNeeded(callback, traverseTopToBottom)) {
4159                 return true;
4160             }
4161         }
4162         return false;
4163     }
4164 
getWindow(Predicate<WindowState> callback)4165     WindowState getWindow(Predicate<WindowState> callback) {
4166         if (mChildren.isEmpty()) {
4167             return callback.test(this) ? this : null;
4168         }
4169 
4170         // We want to consume the positive sublayer children first because they need to appear
4171         // above the parent, then this window (the parent), and then the negative sublayer children
4172         // because they need to appear above the parent.
4173         int i = mChildren.size() - 1;
4174         WindowState child = mChildren.get(i);
4175 
4176         while (i >= 0 && child.mSubLayer >= 0) {
4177             if (callback.test(child)) {
4178                 return child;
4179             }
4180             --i;
4181             if (i < 0) {
4182                 break;
4183             }
4184             child = mChildren.get(i);
4185         }
4186 
4187         if (callback.test(this)) {
4188             return this;
4189         }
4190 
4191         while (i >= 0) {
4192             if (callback.test(child)) {
4193                 return child;
4194             }
4195             --i;
4196             if (i < 0) {
4197                 break;
4198             }
4199             child = mChildren.get(i);
4200         }
4201 
4202         return null;
4203     }
4204 
4205     /**
4206      * @return True if we our one of our ancestors has {@link #mAnimatingExit} set to true, false
4207      *         otherwise.
4208      */
4209     @VisibleForTesting
isSelfOrAncestorWindowAnimatingExit()4210     boolean isSelfOrAncestorWindowAnimatingExit() {
4211         WindowState window = this;
4212         do {
4213             if (window.mAnimatingExit) {
4214                 return true;
4215             }
4216             window = window.getParentWindow();
4217         } while (window != null);
4218         return false;
4219     }
4220 
onExitAnimationDone()4221     void onExitAnimationDone() {
4222         if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this
4223                 + ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit
4224                 + " selfAnimating=" + isSelfAnimating());
4225 
4226         if (!mChildren.isEmpty()) {
4227             // Copying to a different list as multiple children can be removed.
4228             final ArrayList<WindowState> childWindows = new ArrayList<>(mChildren);
4229             for (int i = childWindows.size() - 1; i >= 0; i--) {
4230                 childWindows.get(i).onExitAnimationDone();
4231             }
4232         }
4233 
4234         if (mWinAnimator.mEnteringAnimation) {
4235             mWinAnimator.mEnteringAnimation = false;
4236             mWmService.requestTraversal();
4237             // System windows don't have an activity and an app token as a result, but need a way
4238             // to be informed about their entrance animation end.
4239             if (mAppToken == null) {
4240                 try {
4241                     mClient.dispatchWindowShown();
4242                 } catch (RemoteException e) {
4243                 }
4244             }
4245         }
4246 
4247         if (isSelfAnimating()) {
4248             return;
4249         }
4250 
4251         //TODO (multidisplay): Accessibility is supported only for the default display.
4252         if (mWmService.mAccessibilityController != null && (getDisplayId() == DEFAULT_DISPLAY
4253                 || getDisplayContent().getParentWindow() != null)) {
4254             mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
4255         }
4256 
4257         if (!isSelfOrAncestorWindowAnimatingExit()) {
4258             return;
4259         }
4260 
4261         if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG,
4262                 "Exit animation finished in " + this + ": remove=" + mRemoveOnExit);
4263 
4264         mDestroying = true;
4265 
4266         final boolean hasSurface = mWinAnimator.hasSurface();
4267 
4268         // Use pendingTransaction here so hide is done the same transaction as the other
4269         // animations when exiting
4270         mWinAnimator.hide(getPendingTransaction(), "onExitAnimationDone");
4271 
4272         // If we have an app token, we ask it to destroy the surface for us, so that it can take
4273         // care to ensure the activity has actually stopped and the surface is not still in use.
4274         // Otherwise we add the service to mDestroySurface and allow it to be processed in our next
4275         // transaction.
4276         if (mAppToken != null) {
4277             mAppToken.destroySurfaces();
4278         } else {
4279             if (hasSurface) {
4280                 mWmService.mDestroySurface.add(this);
4281             }
4282             if (mRemoveOnExit) {
4283                 mWmService.mPendingRemove.add(this);
4284                 mRemoveOnExit = false;
4285             }
4286         }
4287         mAnimatingExit = false;
4288         getDisplayContent().mWallpaperController.hideWallpapers(this);
4289     }
4290 
clearAnimatingFlags()4291     boolean clearAnimatingFlags() {
4292         boolean didSomething = false;
4293         // We don't want to clear it out for windows that get replaced, because the
4294         // animation depends on the flag to remove the replaced window.
4295         //
4296         // We also don't clear the mAnimatingExit flag for windows which have the
4297         // mRemoveOnExit flag. This indicates an explicit remove request has been issued
4298         // by the client. We should let animation proceed and not clear this flag or
4299         // they won't eventually be removed by WindowStateAnimator#finishExit.
4300         if (!mWillReplaceWindow && !mRemoveOnExit) {
4301             // Clear mAnimating flag together with mAnimatingExit. When animation
4302             // changes from exiting to entering, we need to clear this flag until the
4303             // new animation gets applied, so that isAnimationStarting() becomes true
4304             // until then.
4305             // Otherwise applySurfaceChangesTransaction will fail to skip surface
4306             // placement for this window during this period, one or more frame will
4307             // show up with wrong position or scale.
4308             if (mAnimatingExit) {
4309                 mAnimatingExit = false;
4310                 didSomething = true;
4311             }
4312             if (mDestroying) {
4313                 mDestroying = false;
4314                 mWmService.mDestroySurface.remove(this);
4315                 didSomething = true;
4316             }
4317         }
4318 
4319         for (int i = mChildren.size() - 1; i >= 0; --i) {
4320             didSomething |= (mChildren.get(i)).clearAnimatingFlags();
4321         }
4322 
4323         return didSomething;
4324     }
4325 
isRtl()4326     public boolean isRtl() {
4327         return getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
4328     }
4329 
hideWallpaperWindow(boolean wasDeferred, String reason)4330     void hideWallpaperWindow(boolean wasDeferred, String reason) {
4331         for (int j = mChildren.size() - 1; j >= 0; --j) {
4332             final WindowState c = mChildren.get(j);
4333             c.hideWallpaperWindow(wasDeferred, reason);
4334         }
4335         if (!mWinAnimator.mLastHidden || wasDeferred) {
4336             mWinAnimator.hide(reason);
4337             getDisplayContent().mWallpaperController.mDeferredHideWallpaper = null;
4338             dispatchWallpaperVisibility(false);
4339             final DisplayContent displayContent = getDisplayContent();
4340             if (displayContent != null) {
4341                 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
4342                 if (DEBUG_LAYOUT_REPEATS) {
4343                     mWmService.mWindowPlacerLocked.debugLayoutRepeats("hideWallpaperWindow " + this,
4344                             displayContent.pendingLayoutChanges);
4345                 }
4346             }
4347         }
4348     }
4349 
4350     /**
4351      * Check wallpaper window for visibility change and notify window if so.
4352      * @param visible Current visibility.
4353      */
dispatchWallpaperVisibility(final boolean visible)4354     void dispatchWallpaperVisibility(final boolean visible) {
4355         final boolean hideAllowed =
4356                 getDisplayContent().mWallpaperController.mDeferredHideWallpaper == null;
4357 
4358         // Only send notification if the visibility actually changed and we are not trying to hide
4359         // the wallpaper when we are deferring hiding of the wallpaper.
4360         if (mWallpaperVisible != visible && (hideAllowed || visible)) {
4361             mWallpaperVisible = visible;
4362             try {
4363                 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
4364                         "Updating vis of wallpaper " + this
4365                                 + ": " + visible + " from:\n" + Debug.getCallers(4, "  "));
4366                 mClient.dispatchAppVisibility(visible);
4367             } catch (RemoteException e) {
4368             }
4369         }
4370     }
4371 
hasVisibleNotDrawnWallpaper()4372     boolean hasVisibleNotDrawnWallpaper() {
4373         if (mWallpaperVisible && !isDrawnLw()) {
4374             return true;
4375         }
4376         for (int j = mChildren.size() - 1; j >= 0; --j) {
4377             final WindowState c = mChildren.get(j);
4378             if (c.hasVisibleNotDrawnWallpaper()) {
4379                 return true;
4380             }
4381         }
4382         return false;
4383     }
4384 
updateReportedVisibility(UpdateReportedVisibilityResults results)4385     void updateReportedVisibility(UpdateReportedVisibilityResults results) {
4386         for (int i = mChildren.size() - 1; i >= 0; --i) {
4387             final WindowState c = mChildren.get(i);
4388             c.updateReportedVisibility(results);
4389         }
4390 
4391         if (mAppFreezing || mViewVisibility != View.VISIBLE
4392                 || mAttrs.type == TYPE_APPLICATION_STARTING
4393                 || mDestroying) {
4394             return;
4395         }
4396         if (DEBUG_VISIBILITY) {
4397             Slog.v(TAG, "Win " + this + ": isDrawn=" + isDrawnLw()
4398                     + ", animating=" + isAnimating());
4399             if (!isDrawnLw()) {
4400                 Slog.v(TAG, "Not displayed: s=" + mWinAnimator.mSurfaceController
4401                         + " pv=" + isVisibleByPolicy()
4402                         + " mDrawState=" + mWinAnimator.mDrawState
4403                         + " ph=" + isParentWindowHidden()
4404                         + " th=" + (mAppToken != null ? mAppToken.hiddenRequested : false)
4405                         + " a=" + isAnimating());
4406             }
4407         }
4408 
4409         results.numInteresting++;
4410         if (isDrawnLw()) {
4411             results.numDrawn++;
4412             if (!isAnimating()) {
4413                 results.numVisible++;
4414             }
4415             results.nowGone = false;
4416         } else if (isAnimating()) {
4417             results.nowGone = false;
4418         }
4419     }
4420 
skipDecorCrop()4421     private boolean skipDecorCrop() {
4422         // The decor frame is used to specify the region not covered by the system
4423         // decorations (nav bar, status bar). In case this is empty, for example with
4424         // FLAG_TRANSLUCENT_NAVIGATION, we don't need to do any cropping.
4425         if (mWindowFrames.mDecorFrame.isEmpty()) {
4426             return true;
4427         }
4428 
4429         // But if we have a frame, and are an application window, then we must be cropped.
4430         if (mAppToken != null) {
4431             return false;
4432         }
4433 
4434         // For non application windows, we may be allowed to extend over the decor bars
4435         // depending on our type and permissions assosciated with our token.
4436         return mToken.canLayerAboveSystemBars();
4437     }
4438 
4439     /**
4440      * Calculate the window crop according to system decor policy. In general this is
4441      * the system decor rect (see #calculateSystemDecorRect), but we also have some
4442      * special cases. This rectangle is in screen space.
4443      */
calculatePolicyCrop(Rect policyCrop)4444     void calculatePolicyCrop(Rect policyCrop) {
4445         final DisplayContent displayContent = getDisplayContent();
4446 
4447         if (!displayContent.isDefaultDisplay && !displayContent.supportsSystemDecorations()) {
4448             // On a different display there is no system decor. Crop the window
4449             // by the screen boundaries.
4450             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
4451             policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(),
4452                     mWindowFrames.mCompatFrame.height());
4453             policyCrop.intersect(-mWindowFrames.mCompatFrame.left, -mWindowFrames.mCompatFrame.top,
4454                     displayInfo.logicalWidth - mWindowFrames.mCompatFrame.left,
4455                     displayInfo.logicalHeight - mWindowFrames.mCompatFrame.top);
4456         } else if (skipDecorCrop()) {
4457             // Windows without policy decor aren't cropped.
4458             policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(),
4459                     mWindowFrames.mCompatFrame.height());
4460         } else {
4461             // Crop to the system decor specified by policy.
4462             calculateSystemDecorRect(policyCrop);
4463         }
4464     }
4465 
4466     /**
4467      * The system decor rect is the region of the window which is not covered
4468      * by system decorations.
4469      */
calculateSystemDecorRect(Rect systemDecorRect)4470     private void calculateSystemDecorRect(Rect systemDecorRect) {
4471         final Rect decorRect = mWindowFrames.mDecorFrame;
4472         final int width = mWindowFrames.mFrame.width();
4473         final int height = mWindowFrames.mFrame.height();
4474 
4475         final int left = mWindowFrames.mFrame.left;
4476         final int top = mWindowFrames.mFrame.top;
4477 
4478         // Initialize the decor rect to the entire frame.
4479         if (isDockedResizing()) {
4480             // If we are resizing with the divider, the task bounds might be smaller than the
4481             // stack bounds. The system decor is used to clip to the task bounds, which we don't
4482             // want in this case in order to avoid holes.
4483             //
4484             // We take care to not shrink the width, for surfaces which are larger than
4485             // the display region. Of course this area will not eventually be visible
4486             // but if we truncate the width now, we will calculate incorrectly
4487             // when adjusting to the stack bounds.
4488             final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
4489             systemDecorRect.set(0, 0,
4490                     Math.max(width, displayInfo.logicalWidth),
4491                     Math.max(height, displayInfo.logicalHeight));
4492         } else {
4493             systemDecorRect.set(0, 0, width, height);
4494         }
4495 
4496         // If a freeform window is animating from a position where it would be cutoff, it would be
4497         // cutoff during the animation. We don't want that, so for the duration of the animation
4498         // we ignore the decor cropping and depend on layering to position windows correctly.
4499 
4500         // We also ignore cropping when the window is currently being drag resized in split screen
4501         // to prevent issues with the crop for screenshot.
4502         final boolean cropToDecor =
4503                 !(inFreeformWindowingMode() && isAnimatingLw()) && !isDockedResizing();
4504         if (cropToDecor) {
4505             // Intersect with the decor rect, offsetted by window position.
4506             systemDecorRect.intersect(decorRect.left - left, decorRect.top - top,
4507                     decorRect.right - left, decorRect.bottom - top);
4508         }
4509 
4510         // If size compatibility is being applied to the window, the
4511         // surface is scaled relative to the screen.  Also apply this
4512         // scaling to the crop rect.  We aren't using the standard rect
4513         // scale function because we want to round things to make the crop
4514         // always round to a larger rect to ensure we don't crop too
4515         // much and hide part of the window that should be seen.
4516         if (mInvGlobalScale != 1.0f && inSizeCompatMode()) {
4517             final float scale = mInvGlobalScale;
4518             systemDecorRect.left = (int) (systemDecorRect.left * scale - 0.5f);
4519             systemDecorRect.top = (int) (systemDecorRect.top * scale - 0.5f);
4520             systemDecorRect.right = (int) ((systemDecorRect.right + 1) * scale - 0.5f);
4521             systemDecorRect.bottom = (int) ((systemDecorRect.bottom + 1) * scale - 0.5f);
4522         }
4523 
4524     }
4525 
4526     /**
4527      * Expand the given rectangle by this windows surface insets. This
4528      * takes you from the 'window size' to the 'surface size'.
4529      * The surface insets are positive in each direction, so we inset by
4530      * the inverse.
4531      */
expandForSurfaceInsets(Rect r)4532     void expandForSurfaceInsets(Rect r) {
4533         r.inset(-mAttrs.surfaceInsets.left,
4534                 -mAttrs.surfaceInsets.top,
4535                 -mAttrs.surfaceInsets.right,
4536                 -mAttrs.surfaceInsets.bottom);
4537     }
4538 
surfaceInsetsChanging()4539     boolean surfaceInsetsChanging() {
4540         return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets);
4541     }
4542 
relayoutVisibleWindow(int result, int attrChanges)4543     int relayoutVisibleWindow(int result, int attrChanges) {
4544         final boolean wasVisible = isVisibleLw();
4545 
4546         result |= (!wasVisible || !isDrawnLw()) ? RELAYOUT_RES_FIRST_TIME : 0;
4547 
4548         if (mAnimatingExit) {
4549             Slog.d(TAG, "relayoutVisibleWindow: " + this + " mAnimatingExit=true, mRemoveOnExit="
4550                     + mRemoveOnExit + ", mDestroying=" + mDestroying);
4551 
4552             // Cancel the existing exit animation for the next enter animation.
4553             if (isSelfAnimating()) {
4554                 cancelAnimation();
4555                 destroySurfaceUnchecked();
4556             }
4557             mAnimatingExit = false;
4558         }
4559         if (mDestroying) {
4560             mDestroying = false;
4561             mWmService.mDestroySurface.remove(this);
4562         }
4563         if (!wasVisible) {
4564             mWinAnimator.mEnterAnimationPending = true;
4565         }
4566 
4567         mLastVisibleLayoutRotation = getDisplayContent().getRotation();
4568 
4569         mWinAnimator.mEnteringAnimation = true;
4570 
4571         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareToDisplay");
4572         try {
4573             prepareWindowToDisplayDuringRelayout(wasVisible);
4574         } finally {
4575             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
4576         }
4577 
4578         if ((attrChanges & FORMAT_CHANGED) != 0) {
4579             // If the format can't be changed in place, preserve the old surface until the app draws
4580             // on the new one. This prevents blinking when we change elevation of freeform and
4581             // pinned windows.
4582             if (!mWinAnimator.tryChangeFormatInPlaceLocked()) {
4583                 mWinAnimator.preserveSurfaceLocked();
4584                 result |= RELAYOUT_RES_SURFACE_CHANGED
4585                         | RELAYOUT_RES_FIRST_TIME;
4586             }
4587         }
4588 
4589         // When we change the Surface size, in scenarios which may require changing
4590         // the surface position in sync with the resize, we use a preserved surface
4591         // so we can freeze it while waiting for the client to report draw on the newly
4592         // sized surface. At the moment this logic is only in place for switching
4593         // in and out of the big surface for split screen resize.
4594         if (isDragResizeChanged()) {
4595             setDragResizing();
4596             // We can only change top level windows to the full-screen surface when
4597             // resizing (as we only have one full-screen surface). So there is no need
4598             // to preserve and destroy windows which are attached to another, they
4599             // will keep their surface and its size may change over time.
4600             if (mHasSurface && !isChildWindow()) {
4601                 mWinAnimator.preserveSurfaceLocked();
4602                 result |= RELAYOUT_RES_SURFACE_CHANGED |
4603                     RELAYOUT_RES_FIRST_TIME;
4604             }
4605         }
4606         final boolean freeformResizing = isDragResizing()
4607                 && getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
4608         final boolean dockedResizing = isDragResizing()
4609                 && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER;
4610         result |= freeformResizing ? RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0;
4611         result |= dockedResizing ? RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0;
4612         return result;
4613     }
4614 
4615     /**
4616      * @return True if this window has been laid out at least once; false otherwise.
4617      */
isLaidOut()4618     boolean isLaidOut() {
4619         return mLayoutSeq != -1;
4620     }
4621 
4622     /**
4623      * Updates the last inset values to the current ones.
4624      */
updateLastInsetValues()4625     void updateLastInsetValues() {
4626         mWindowFrames.updateLastInsetValues();
4627     }
4628 
startAnimation(Animation anim)4629     void startAnimation(Animation anim) {
4630 
4631         // If we are an inset provider, all our animations are driven by the inset client.
4632         if (mInsetProvider != null && mInsetProvider.isControllable()) {
4633             return;
4634         }
4635 
4636         final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
4637         anim.initialize(mWindowFrames.mFrame.width(), mWindowFrames.mFrame.height(),
4638                 displayInfo.appWidth, displayInfo.appHeight);
4639         anim.restrictDuration(MAX_ANIMATION_DURATION);
4640         anim.scaleCurrentDuration(mWmService.getWindowAnimationScaleLocked());
4641         final AnimationAdapter adapter = new LocalAnimationAdapter(
4642                 new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */,
4643                         0 /* windowCornerRadius */),
4644                 mWmService.mSurfaceAnimationRunner);
4645         startAnimation(getPendingTransaction(), adapter);
4646         commitPendingTransaction();
4647     }
4648 
startMoveAnimation(int left, int top)4649     private void startMoveAnimation(int left, int top) {
4650 
4651         // If we are an inset provider, all our animations are driven by the inset client.
4652         if (mInsetProvider != null && mInsetProvider.isControllable()) {
4653             return;
4654         }
4655 
4656         if (DEBUG_ANIM) Slog.v(TAG, "Setting move animation on " + this);
4657         final Point oldPosition = new Point();
4658         final Point newPosition = new Point();
4659         transformFrameToSurfacePosition(mWindowFrames.mLastFrame.left, mWindowFrames.mLastFrame.top,
4660                 oldPosition);
4661         transformFrameToSurfacePosition(left, top, newPosition);
4662         final AnimationAdapter adapter = new LocalAnimationAdapter(
4663                 new MoveAnimationSpec(oldPosition.x, oldPosition.y, newPosition.x, newPosition.y),
4664                 mWmService.mSurfaceAnimationRunner);
4665         startAnimation(getPendingTransaction(), adapter);
4666     }
4667 
startAnimation(Transaction t, AnimationAdapter adapter)4668     private void startAnimation(Transaction t, AnimationAdapter adapter) {
4669         startAnimation(t, adapter, mWinAnimator.mLastHidden);
4670     }
4671 
4672     @Override
onAnimationFinished()4673     protected void onAnimationFinished() {
4674         super.onAnimationFinished();
4675         mWinAnimator.onAnimationFinished();
4676     }
4677 
4678     /**
4679      * Retrieves the current transformation matrix of the window, relative to the display.
4680      *
4681      * @param float9 A temporary array of 9 floats.
4682      * @param outMatrix Matrix to fill in the transformation.
4683      */
getTransformationMatrix(float[] float9, Matrix outMatrix)4684     void getTransformationMatrix(float[] float9, Matrix outMatrix) {
4685         float9[Matrix.MSCALE_X] = mWinAnimator.mDsDx;
4686         float9[Matrix.MSKEW_Y] = mWinAnimator.mDtDx;
4687         float9[Matrix.MSKEW_X] = mWinAnimator.mDtDy;
4688         float9[Matrix.MSCALE_Y] = mWinAnimator.mDsDy;
4689         int x = mSurfacePosition.x;
4690         int y = mSurfacePosition.y;
4691 
4692         // We might be on a display which has been re-parented to a view in another window, so here
4693         // computes the global location of our display.
4694         DisplayContent dc = getDisplayContent();
4695         while (dc != null && dc.getParentWindow() != null) {
4696             final WindowState displayParent = dc.getParentWindow();
4697             x += displayParent.mWindowFrames.mFrame.left - displayParent.mAttrs.surfaceInsets.left
4698                     + (dc.getLocationInParentWindow().x * displayParent.mGlobalScale + 0.5f);
4699             y += displayParent.mWindowFrames.mFrame.top - displayParent.mAttrs.surfaceInsets.top
4700                     + (dc.getLocationInParentWindow().y * displayParent.mGlobalScale + 0.5f);
4701             dc = displayParent.getDisplayContent();
4702         }
4703 
4704         // If changed, also adjust transformFrameToSurfacePosition
4705         final WindowContainer parent = getParent();
4706         if (isChildWindow()) {
4707             final WindowState parentWindow = getParentWindow();
4708             x += parentWindow.mWindowFrames.mFrame.left - parentWindow.mAttrs.surfaceInsets.left;
4709             y += parentWindow.mWindowFrames.mFrame.top - parentWindow.mAttrs.surfaceInsets.top;
4710         } else if (parent != null) {
4711             final Rect parentBounds = parent.getBounds();
4712             x += parentBounds.left;
4713             y += parentBounds.top;
4714         }
4715         float9[Matrix.MTRANS_X] = x;
4716         float9[Matrix.MTRANS_Y] = y;
4717         float9[Matrix.MPERSP_0] = 0;
4718         float9[Matrix.MPERSP_1] = 0;
4719         float9[Matrix.MPERSP_2] = 1;
4720         outMatrix.setValues(float9);
4721     }
4722 
4723     // TODO: Hack to work around the number of states AppWindowToken needs to access without having
4724     // access to its windows children. Need to investigate re-writing
4725     // {@link AppWindowToken#updateReportedVisibilityLocked} so this can be removed.
4726     static final class UpdateReportedVisibilityResults {
4727         int numInteresting;
4728         int numVisible;
4729         int numDrawn;
4730         boolean nowGone = true;
4731 
reset()4732         void reset() {
4733             numInteresting = 0;
4734             numVisible = 0;
4735             numDrawn = 0;
4736             nowGone = true;
4737         }
4738     }
4739 
4740     private static final class WindowId extends IWindowId.Stub {
4741         private final WeakReference<WindowState> mOuter;
4742 
WindowId(WindowState outer)4743         private WindowId(WindowState outer) {
4744 
4745             // Use a weak reference for the outer class. This is important to prevent the following
4746             // leak: Since we send this class to the client process, binder will keep it alive as
4747             // long as the client keeps it alive. Now, if the window is removed, we need to clear
4748             // out our reference so even though this class is kept alive we don't leak WindowState,
4749             // which can keep a whole lot of classes alive.
4750             mOuter = new WeakReference<>(outer);
4751         }
4752 
4753         @Override
registerFocusObserver(IWindowFocusObserver observer)4754         public void registerFocusObserver(IWindowFocusObserver observer) {
4755             final WindowState outer = mOuter.get();
4756             if (outer != null) {
4757                 outer.registerFocusObserver(observer);
4758             }
4759         }
4760         @Override
unregisterFocusObserver(IWindowFocusObserver observer)4761         public void unregisterFocusObserver(IWindowFocusObserver observer) {
4762             final WindowState outer = mOuter.get();
4763             if (outer != null) {
4764                 outer.unregisterFocusObserver(observer);
4765             }
4766         }
4767         @Override
isFocused()4768         public boolean isFocused() {
4769             final WindowState outer = mOuter.get();
4770             if (outer != null) {
4771                 synchronized (outer.mWmService.mGlobalLock) {
4772                     return outer.isFocused();
4773                 }
4774             }
4775             return false;
4776         }
4777     }
4778 
4779 
4780     @Override
shouldMagnify()4781     boolean shouldMagnify() {
4782         if (mAttrs.type == TYPE_INPUT_METHOD ||
4783                 mAttrs.type == TYPE_INPUT_METHOD_DIALOG ||
4784                 mAttrs.type == TYPE_MAGNIFICATION_OVERLAY ||
4785                 mAttrs.type == TYPE_NAVIGATION_BAR ||
4786                 // It's tempting to wonder: Have we forgotten the rounded corners overlay?
4787                 // worry not: it's a fake TYPE_NAVIGATION_BAR_PANEL
4788                 mAttrs.type == TYPE_NAVIGATION_BAR_PANEL) {
4789             return false;
4790         }
4791         return true;
4792     }
4793 
4794     @Override
getSession()4795     SurfaceSession getSession() {
4796         if (mSession.mSurfaceSession != null) {
4797             return mSession.mSurfaceSession;
4798         } else {
4799             return getParent().getSession();
4800         }
4801     }
4802 
4803     @Override
needsZBoost()4804     boolean needsZBoost() {
4805         final WindowState inputMethodTarget = getDisplayContent().mInputMethodTarget;
4806         if (mIsImWindow && inputMethodTarget != null) {
4807             final AppWindowToken appToken = inputMethodTarget.mAppToken;
4808             if (appToken != null) {
4809                 return appToken.needsZBoost();
4810             }
4811         }
4812         return mWillReplaceWindow;
4813     }
4814 
applyDims(Dimmer dimmer)4815     private void applyDims(Dimmer dimmer) {
4816         if (!mAnimatingExit && mAppDied) {
4817             mIsDimming = true;
4818             dimmer.dimAbove(getPendingTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
4819         } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isVisibleNow() && !mHidden) {
4820             // Only show a dim behind when the following is satisfied:
4821             // 1. The window has the flag FLAG_DIM_BEHIND
4822             // 2. The WindowToken is not hidden so dims aren't shown when the window is exiting.
4823             // 3. The WS is considered visible according to the isVisible() method
4824             // 4. The WS is not hidden.
4825             mIsDimming = true;
4826             dimmer.dimBelow(getPendingTransaction(), this, mAttrs.dimAmount);
4827         }
4828     }
4829 
4830     @Override
prepareSurfaces()4831     void prepareSurfaces() {
4832         final Dimmer dimmer = getDimmer();
4833         mIsDimming = false;
4834         if (dimmer != null) {
4835             applyDims(dimmer);
4836         }
4837         updateSurfacePosition();
4838 
4839         mWinAnimator.prepareSurfaceLocked(true);
4840         super.prepareSurfaces();
4841     }
4842 
4843     @Override
onAnimationLeashCreated(Transaction t, SurfaceControl leash)4844     public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
4845         super.onAnimationLeashCreated(t, leash);
4846 
4847         // Leash is now responsible for position, so set our position to 0.
4848         t.setPosition(mSurfaceControl, 0, 0);
4849         mLastSurfacePosition.set(0, 0);
4850     }
4851 
4852     @Override
onAnimationLeashLost(Transaction t)4853     public void onAnimationLeashLost(Transaction t) {
4854         super.onAnimationLeashLost(t);
4855         updateSurfacePosition(t);
4856     }
4857 
4858     @Override
updateSurfacePosition()4859     void updateSurfacePosition() {
4860         updateSurfacePosition(getPendingTransaction());
4861     }
4862 
4863     @VisibleForTesting
updateSurfacePosition(Transaction t)4864     void updateSurfacePosition(Transaction t) {
4865         if (mSurfaceControl == null) {
4866             return;
4867         }
4868 
4869         transformFrameToSurfacePosition(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top,
4870                 mSurfacePosition);
4871 
4872         // Freeze position while we're unrotated, so the surface remains at the position it was
4873         // prior to the rotation.
4874         if (!mSurfaceAnimator.hasLeash() && mPendingSeamlessRotate == null
4875                 && !mLastSurfacePosition.equals(mSurfacePosition)) {
4876             t.setPosition(mSurfaceControl, mSurfacePosition.x, mSurfacePosition.y);
4877             mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y);
4878             if (surfaceInsetsChanging() && mWinAnimator.hasSurface()) {
4879                 mLastSurfaceInsets.set(mAttrs.surfaceInsets);
4880                 t.deferTransactionUntil(mSurfaceControl,
4881                         mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(),
4882                         getFrameNumber());
4883             }
4884         }
4885     }
4886 
transformFrameToSurfacePosition(int left, int top, Point outPoint)4887     private void transformFrameToSurfacePosition(int left, int top, Point outPoint) {
4888         outPoint.set(left, top);
4889 
4890         // If changed, also adjust getTransformationMatrix
4891         final WindowContainer parentWindowContainer = getParent();
4892         if (isChildWindow()) {
4893             // TODO: This probably falls apart at some point and we should
4894             // actually compute relative coordinates.
4895 
4896             // Since the parent was outset by its surface insets, we need to undo the outsetting
4897             // with insetting by the same amount.
4898             final WindowState parent = getParentWindow();
4899             transformSurfaceInsetsPosition(mTmpPoint, parent.mAttrs.surfaceInsets);
4900             outPoint.offset(-parent.mWindowFrames.mFrame.left + mTmpPoint.x,
4901                     -parent.mWindowFrames.mFrame.top + mTmpPoint.y);
4902         } else if (parentWindowContainer != null) {
4903             final Rect parentBounds = parentWindowContainer.getDisplayedBounds();
4904             outPoint.offset(-parentBounds.left, -parentBounds.top);
4905         }
4906 
4907         TaskStack stack = getStack();
4908 
4909         // If we have stack outsets, that means the top-left
4910         // will be outset, and we need to inset ourselves
4911         // to account for it. If we actually have shadows we will
4912         // then un-inset ourselves by the surfaceInsets.
4913         if (stack != null) {
4914             final int outset = stack.getStackOutset();
4915             outPoint.offset(outset, outset);
4916         }
4917 
4918         // Expand for surface insets. See WindowState.expandForSurfaceInsets.
4919         transformSurfaceInsetsPosition(mTmpPoint, mAttrs.surfaceInsets);
4920         outPoint.offset(-mTmpPoint.x, -mTmpPoint.y);
4921     }
4922 
4923     /**
4924      * The surface insets from layout parameter are in application coordinate. If the window is
4925      * scaled, the insets also need to be scaled for surface position in global coordinate.
4926      */
transformSurfaceInsetsPosition(Point outPos, Rect surfaceInsets)4927     private void transformSurfaceInsetsPosition(Point outPos, Rect surfaceInsets) {
4928         if (!inSizeCompatMode()) {
4929             outPos.x = surfaceInsets.left;
4930             outPos.y = surfaceInsets.top;
4931             return;
4932         }
4933         outPos.x = (int) (surfaceInsets.left * mGlobalScale + 0.5f);
4934         outPos.y = (int) (surfaceInsets.top * mGlobalScale + 0.5f);
4935     }
4936 
needsRelativeLayeringToIme()4937     boolean needsRelativeLayeringToIme() {
4938         // We only use the relative layering mode in split screen, as part of elevating the IME
4939         // and windows above it's target above the docked divider.
4940         if (!inSplitScreenWindowingMode()) {
4941             return false;
4942         }
4943 
4944         if (isChildWindow()) {
4945             // If we are a child of the input method target we need this promotion.
4946             if (getParentWindow().isInputMethodTarget()) {
4947                 return true;
4948             }
4949         } else if (mAppToken != null) {
4950             // Likewise if we share a token with the Input method target and are ordered
4951             // above it but not necessarily a child (e.g. a Dialog) then we also need
4952             // this promotion.
4953             final WindowState imeTarget = getDisplayContent().mInputMethodTarget;
4954             boolean inTokenWithAndAboveImeTarget = imeTarget != null && imeTarget != this
4955                     && imeTarget.mToken == mToken && imeTarget.compareTo(this) <= 0;
4956             return inTokenWithAndAboveImeTarget;
4957         }
4958         return false;
4959     }
4960 
4961     @Override
assignLayer(Transaction t, int layer)4962     void assignLayer(Transaction t, int layer) {
4963         // See comment in assignRelativeLayerForImeTargetChild
4964         if (needsRelativeLayeringToIme()) {
4965             getDisplayContent().assignRelativeLayerForImeTargetChild(t, this);
4966             return;
4967         }
4968         super.assignLayer(t, layer);
4969     }
4970 
4971     @Override
isDimming()4972     public boolean isDimming() {
4973         return mIsDimming;
4974     }
4975 
4976     // TODO(b/70040778): We should aim to eliminate the last user of TYPE_APPLICATION_MEDIA
4977     // then we can drop all negative layering on the windowing side and simply inherit
4978     // the default implementation here.
assignChildLayers(Transaction t)4979     public void assignChildLayers(Transaction t) {
4980         // The surface of the main window might be preserved. So the child window on top of the main
4981         // window should be also on top of the preserved surface.
4982         int layer = PRESERVED_SURFACE_LAYER + 1;
4983         for (int i = 0; i < mChildren.size(); i++) {
4984             final WindowState w = mChildren.get(i);
4985 
4986             // APPLICATION_MEDIA_OVERLAY needs to go above APPLICATION_MEDIA
4987             // while they both need to go below the main window. However the
4988             // relative layering of multiple APPLICATION_MEDIA/OVERLAY has never
4989             // been defined and so we can use static layers and leave it that way.
4990             if (w.mAttrs.type == TYPE_APPLICATION_MEDIA) {
4991                 w.assignLayer(t, -2);
4992             } else if (w.mAttrs.type == TYPE_APPLICATION_MEDIA_OVERLAY) {
4993                 w.assignLayer(t, -1);
4994             } else {
4995                 w.assignLayer(t, layer);
4996             }
4997             w.assignChildLayers(t);
4998             layer++;
4999         }
5000     }
5001 
5002     /**
5003      * Update a tap exclude region identified by provided id. The requested area will be clipped to
5004      * the window bounds.
5005      */
updateTapExcludeRegion(int regionId, Region region)5006     void updateTapExcludeRegion(int regionId, Region region) {
5007         final DisplayContent currentDisplay = getDisplayContent();
5008         if (currentDisplay == null) {
5009             throw new IllegalStateException("Trying to update window not attached to any display.");
5010         }
5011 
5012         if (mTapExcludeRegionHolder == null) {
5013             mTapExcludeRegionHolder = new TapExcludeRegionHolder();
5014 
5015             // Make sure that this window is registered as one that provides a tap exclude region
5016             // for its containing display.
5017             currentDisplay.mTapExcludeProvidingWindows.add(this);
5018         }
5019 
5020         mTapExcludeRegionHolder.updateRegion(regionId, region);
5021         // Trigger touch exclude region update on current display.
5022         currentDisplay.updateTouchExcludeRegion();
5023         // Trigger touchable region update for this window.
5024         currentDisplay.getInputMonitor().updateInputWindowsLw(true /* force */);
5025     }
5026 
5027     /**
5028      * Union the region with current tap exclude region that this window provides.
5029      *
5030      * @param region The region to be amended. It is on the screen coordinates.
5031      */
amendTapExcludeRegion(Region region)5032     void amendTapExcludeRegion(Region region) {
5033         final Region tempRegion = Region.obtain();
5034         mTmpRect.set(mWindowFrames.mFrame);
5035         mTmpRect.offsetTo(0, 0);
5036         mTapExcludeRegionHolder.amendRegion(tempRegion, mTmpRect);
5037         // The region held by the holder is on the window coordinates. We need to translate it to
5038         // the screen coordinates.
5039         tempRegion.translate(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top);
5040         region.op(tempRegion, Region.Op.UNION);
5041         tempRegion.recycle();
5042     }
5043 
5044     @Override
isInputMethodTarget()5045     public boolean isInputMethodTarget() {
5046         return getDisplayContent().mInputMethodTarget == this;
5047     }
5048 
getFrameNumber()5049     long getFrameNumber() {
5050         return mFrameNumber;
5051     }
5052 
setFrameNumber(long frameNumber)5053     void setFrameNumber(long frameNumber) {
5054         mFrameNumber = frameNumber;
5055     }
5056 
getMaxVisibleBounds(Rect out)5057     public void getMaxVisibleBounds(Rect out) {
5058         if (out.isEmpty()) {
5059             out.set(mWindowFrames.mVisibleFrame);
5060             return;
5061         }
5062 
5063         if (mWindowFrames.mVisibleFrame.left < out.left) {
5064             out.left = mWindowFrames.mVisibleFrame.left;
5065         }
5066         if (mWindowFrames.mVisibleFrame.top < out.top) {
5067             out.top = mWindowFrames.mVisibleFrame.top;
5068         }
5069         if (mWindowFrames.mVisibleFrame.right > out.right) {
5070             out.right = mWindowFrames.mVisibleFrame.right;
5071         }
5072         if (mWindowFrames.mVisibleFrame.bottom > out.bottom) {
5073             out.bottom = mWindowFrames.mVisibleFrame.bottom;
5074         }
5075     }
5076 
5077     /**
5078      * Copy the inset values over so they can be sent back to the client when a relayout occurs.
5079      */
getInsetsForRelayout(Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets)5080     void getInsetsForRelayout(Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
5081             Rect outStableInsets, Rect outOutsets) {
5082         outOverscanInsets.set(mWindowFrames.mOverscanInsets);
5083         outContentInsets.set(mWindowFrames.mContentInsets);
5084         outVisibleInsets.set(mWindowFrames.mVisibleInsets);
5085         outStableInsets.set(mWindowFrames.mStableInsets);
5086         outOutsets.set(mWindowFrames.mOutsets);
5087 
5088         mLastRelayoutContentInsets.set(mWindowFrames.mContentInsets);
5089     }
5090 
getContentInsets(Rect outContentInsets)5091     void getContentInsets(Rect outContentInsets) {
5092         outContentInsets.set(mWindowFrames.mContentInsets);
5093     }
5094 
getContentInsets()5095     Rect getContentInsets() {
5096         return mWindowFrames.mContentInsets;
5097     }
5098 
getStableInsets(Rect outStableInsets)5099     void getStableInsets(Rect outStableInsets) {
5100         outStableInsets.set(mWindowFrames.mStableInsets);
5101     }
5102 
getStableInsets()5103     Rect getStableInsets() {
5104         return mWindowFrames.mStableInsets;
5105     }
5106 
resetLastContentInsets()5107     void resetLastContentInsets() {
5108         mWindowFrames.resetLastContentInsets();
5109     }
5110 
getVisibleInsets()5111     Rect getVisibleInsets() {
5112         return mWindowFrames.mVisibleInsets;
5113     }
5114 
5115     @Override
getWindowFrames()5116     public WindowFrames getWindowFrames() {
5117         return mWindowFrames;
5118     }
5119 
resetContentChanged()5120     void resetContentChanged() {
5121         mWindowFrames.setContentChanged(false);
5122     }
5123 
setInsetProvider(InsetsSourceProvider insetProvider)5124     void setInsetProvider(InsetsSourceProvider insetProvider) {
5125         mInsetProvider = insetProvider;
5126     }
5127 
getInsetProvider()5128     InsetsSourceProvider getInsetProvider() {
5129         return mInsetProvider;
5130     }
5131 
5132     private final class MoveAnimationSpec implements AnimationSpec {
5133 
5134         private final long mDuration;
5135         private Interpolator mInterpolator;
5136         private Point mFrom = new Point();
5137         private Point mTo = new Point();
5138 
MoveAnimationSpec(int fromX, int fromY, int toX, int toY)5139         private MoveAnimationSpec(int fromX, int fromY, int toX, int toY) {
5140             final Animation anim = AnimationUtils.loadAnimation(mContext,
5141                     com.android.internal.R.anim.window_move_from_decor);
5142             mDuration = (long)
5143                     (anim.computeDurationHint() * mWmService.getWindowAnimationScaleLocked());
5144             mInterpolator = anim.getInterpolator();
5145             mFrom.set(fromX, fromY);
5146             mTo.set(toX, toY);
5147         }
5148 
5149         @Override
getDuration()5150         public long getDuration() {
5151             return mDuration;
5152         }
5153 
5154         @Override
apply(Transaction t, SurfaceControl leash, long currentPlayTime)5155         public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {
5156             final float fraction = (float) currentPlayTime / getDuration();
5157             final float v = mInterpolator.getInterpolation(fraction);
5158             t.setPosition(leash, mFrom.x + (mTo.x - mFrom.x) * v,
5159                     mFrom.y + (mTo.y - mFrom.y) * v);
5160         }
5161 
5162         @Override
dump(PrintWriter pw, String prefix)5163         public void dump(PrintWriter pw, String prefix) {
5164             pw.println(prefix + "from=" + mFrom
5165                     + " to=" + mTo
5166                     + " duration=" + mDuration);
5167         }
5168 
5169         @Override
writeToProtoInner(ProtoOutputStream proto)5170         public void writeToProtoInner(ProtoOutputStream proto) {
5171             final long token = proto.start(MOVE);
5172             mFrom.writeToProto(proto, FROM);
5173             mTo.writeToProto(proto, TO);
5174             proto.write(DURATION_MS, mDuration);
5175             proto.end(token);
5176         }
5177     }
5178 }
5179