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