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