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