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