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