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