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