1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 23 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 24 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 25 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; 26 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 27 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 28 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 29 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER; 30 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 31 import static android.content.res.Configuration.ORIENTATION_PORTRAIT; 32 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 33 import static android.util.DisplayMetrics.DENSITY_DEFAULT; 34 import static android.view.Display.DEFAULT_DISPLAY; 35 import static android.view.Display.FLAG_PRIVATE; 36 import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; 37 import static android.view.Display.INVALID_DISPLAY; 38 import static android.view.InsetsState.TYPE_IME; 39 import static android.view.InsetsState.TYPE_LEFT_GESTURES; 40 import static android.view.InsetsState.TYPE_RIGHT_GESTURES; 41 import static android.view.Surface.ROTATION_0; 42 import static android.view.Surface.ROTATION_180; 43 import static android.view.Surface.ROTATION_270; 44 import static android.view.Surface.ROTATION_90; 45 import static android.view.View.GONE; 46 import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 47 import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 48 import static android.view.WindowManager.DOCKED_BOTTOM; 49 import static android.view.WindowManager.DOCKED_INVALID; 50 import static android.view.WindowManager.DOCKED_TOP; 51 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; 52 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 53 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 54 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 55 import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 56 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 57 import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; 58 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 59 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE; 60 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET; 61 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 62 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 63 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 64 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 65 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 66 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; 67 import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 68 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 69 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 70 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 71 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 72 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 73 import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 74 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 75 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; 76 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; 77 import static android.view.WindowManager.TRANSIT_TASK_OPEN; 78 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT; 79 80 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 81 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 82 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 83 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 84 import static com.android.server.wm.DisplayContentProto.ABOVE_APP_WINDOWS; 85 import static com.android.server.wm.DisplayContentProto.APP_TRANSITION; 86 import static com.android.server.wm.DisplayContentProto.BELOW_APP_WINDOWS; 87 import static com.android.server.wm.DisplayContentProto.CHANGING_APPS; 88 import static com.android.server.wm.DisplayContentProto.CLOSING_APPS; 89 import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES; 90 import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO; 91 import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER; 92 import static com.android.server.wm.DisplayContentProto.DPI; 93 import static com.android.server.wm.DisplayContentProto.FOCUSED_APP; 94 import static com.android.server.wm.DisplayContentProto.ID; 95 import static com.android.server.wm.DisplayContentProto.IME_WINDOWS; 96 import static com.android.server.wm.DisplayContentProto.OPENING_APPS; 97 import static com.android.server.wm.DisplayContentProto.PINNED_STACK_CONTROLLER; 98 import static com.android.server.wm.DisplayContentProto.ROTATION; 99 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION; 100 import static com.android.server.wm.DisplayContentProto.STACKS; 101 import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER; 102 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 103 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 104 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; 105 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 106 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 107 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 108 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 109 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 110 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 111 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 112 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; 113 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON; 114 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; 115 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT; 116 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 117 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 118 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 119 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 120 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 121 import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION; 122 import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE; 123 import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE; 124 import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS; 125 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION; 126 import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER; 127 import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; 128 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; 129 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; 130 import static com.android.server.wm.WindowManagerService.SEAMLESS_ROTATION_TIMEOUT_DURATION; 131 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES; 132 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS; 133 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS; 134 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 135 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE; 136 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; 137 import static com.android.server.wm.WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION; 138 import static com.android.server.wm.WindowManagerService.dipToPixel; 139 import static com.android.server.wm.WindowManagerService.logSurface; 140 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; 141 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; 142 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; 143 import static com.android.server.wm.utils.RegionUtils.forEachRectReverse; 144 import static com.android.server.wm.utils.RegionUtils.rectListToRegion; 145 146 import android.animation.AnimationHandler; 147 import android.annotation.CallSuper; 148 import android.annotation.IntDef; 149 import android.annotation.NonNull; 150 import android.annotation.Nullable; 151 import android.content.pm.PackageManager; 152 import android.content.res.CompatibilityInfo; 153 import android.content.res.Configuration; 154 import android.graphics.Bitmap; 155 import android.graphics.Insets; 156 import android.graphics.Matrix; 157 import android.graphics.Point; 158 import android.graphics.Rect; 159 import android.graphics.RectF; 160 import android.graphics.Region; 161 import android.graphics.Region.Op; 162 import android.hardware.display.DisplayManagerInternal; 163 import android.metrics.LogMaker; 164 import android.os.Binder; 165 import android.os.Debug; 166 import android.os.Handler; 167 import android.os.IBinder; 168 import android.os.Process; 169 import android.os.RemoteCallbackList; 170 import android.os.RemoteException; 171 import android.os.SystemClock; 172 import android.os.Trace; 173 import android.os.UserHandle; 174 import android.util.ArraySet; 175 import android.util.DisplayMetrics; 176 import android.util.Slog; 177 import android.util.proto.ProtoOutputStream; 178 import android.view.Display; 179 import android.view.DisplayCutout; 180 import android.view.DisplayInfo; 181 import android.view.Gravity; 182 import android.view.ISystemGestureExclusionListener; 183 import android.view.InputChannel; 184 import android.view.InputDevice; 185 import android.view.InputWindowHandle; 186 import android.view.InsetsState.InternalInsetType; 187 import android.view.MagnificationSpec; 188 import android.view.RemoteAnimationDefinition; 189 import android.view.Surface; 190 import android.view.SurfaceControl; 191 import android.view.SurfaceControl.Transaction; 192 import android.view.SurfaceSession; 193 import android.view.View; 194 import android.view.WindowManager; 195 import android.view.WindowManagerPolicyConstants.PointerEventListener; 196 197 import com.android.internal.annotations.VisibleForTesting; 198 import com.android.internal.logging.MetricsLogger; 199 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 200 import com.android.internal.util.ToBooleanFunction; 201 import com.android.internal.util.function.TriConsumer; 202 import com.android.internal.util.function.pooled.PooledConsumer; 203 import com.android.internal.util.function.pooled.PooledLambda; 204 import com.android.server.AnimationThread; 205 import com.android.server.policy.WindowManagerPolicy; 206 import com.android.server.wm.utils.DisplayRotationUtil; 207 import com.android.server.wm.utils.RotationCache; 208 import com.android.server.wm.utils.WmDisplayCutout; 209 210 import java.io.PrintWriter; 211 import java.lang.annotation.Retention; 212 import java.lang.annotation.RetentionPolicy; 213 import java.util.ArrayList; 214 import java.util.Comparator; 215 import java.util.HashMap; 216 import java.util.Iterator; 217 import java.util.LinkedList; 218 import java.util.List; 219 import java.util.Objects; 220 import java.util.function.Consumer; 221 import java.util.function.Predicate; 222 223 /** 224 * Utility class for keeping track of the WindowStates and other pertinent contents of a 225 * particular Display. 226 */ 227 class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> 228 implements WindowManagerPolicy.DisplayContentInfo { 229 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM; 230 231 /** The default scaling mode that scales content automatically. */ 232 static final int FORCE_SCALING_MODE_AUTO = 0; 233 /** For {@link #setForcedScalingMode} to apply flag {@link Display#FLAG_SCALING_DISABLED}. */ 234 static final int FORCE_SCALING_MODE_DISABLED = 1; 235 236 @IntDef(prefix = { "FORCE_SCALING_MODE_" }, value = { 237 FORCE_SCALING_MODE_AUTO, 238 FORCE_SCALING_MODE_DISABLED 239 }) 240 @Retention(RetentionPolicy.SOURCE) 241 @interface ForceScalingMode {} 242 243 /** Unique identifier of this stack. */ 244 private final int mDisplayId; 245 246 // TODO: Remove once unification is complete. 247 ActivityDisplay mAcitvityDisplay; 248 249 /** The containers below are the only child containers the display can have. */ 250 // Contains all window containers that are related to apps (Activities) 251 private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(mWmService); 252 // Contains all non-app window containers that should be displayed above the app containers 253 // (e.g. Status bar) 254 private final AboveAppWindowContainers mAboveAppWindowsContainers = 255 new AboveAppWindowContainers("mAboveAppWindowsContainers", mWmService); 256 // Contains all non-app window containers that should be displayed below the app containers 257 // (e.g. Wallpaper). 258 private final NonAppWindowContainers mBelowAppWindowsContainers = 259 new NonAppWindowContainers("mBelowAppWindowsContainers", mWmService); 260 // Contains all IME window containers. Note that the z-ordering of the IME windows will depend 261 // on the IME target. We mainly have this container grouping so we can keep track of all the IME 262 // window containers together and move them in-sync if/when needed. We use a subclass of 263 // WindowContainer which is omitted from screen magnification, as the IME is never magnified. 264 private final NonAppWindowContainers mImeWindowsContainers = 265 new NonAppWindowContainers("mImeWindowsContainers", mWmService); 266 267 private WindowState mTmpWindow; 268 private WindowState mTmpWindow2; 269 private boolean mTmpRecoveringMemory; 270 private boolean mUpdateImeTarget; 271 private boolean mTmpInitial; 272 private int mMaxUiWidth; 273 274 final AppTransition mAppTransition; 275 final AppTransitionController mAppTransitionController; 276 boolean mSkipAppTransitionAnimation = false; 277 278 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>(); 279 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>(); 280 final ArraySet<AppWindowToken> mChangingApps = new ArraySet<>(); 281 final UnknownAppVisibilityController mUnknownAppVisibilityController; 282 BoundsAnimationController mBoundsAnimationController; 283 284 private MetricsLogger mMetricsLogger; 285 286 /** 287 * List of clients without a transtiton animation that we notify once we are done 288 * transitioning since they won't be notified through the app window animator. 289 */ 290 final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>(); 291 292 // Mapping from a token IBinder to a WindowToken object on this display. 293 private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap(); 294 295 // Initial display metrics. 296 int mInitialDisplayWidth = 0; 297 int mInitialDisplayHeight = 0; 298 int mInitialDisplayDensity = 0; 299 300 DisplayCutout mInitialDisplayCutout; 301 private final RotationCache<DisplayCutout, WmDisplayCutout> mDisplayCutoutCache 302 = new RotationCache<>(this::calculateDisplayCutoutForRotationUncached); 303 304 /** 305 * Overridden display size. Initialized with {@link #mInitialDisplayWidth} 306 * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size". 307 * @see WindowManagerService#setForcedDisplaySize(int, int, int) 308 */ 309 int mBaseDisplayWidth = 0; 310 int mBaseDisplayHeight = 0; 311 /** 312 * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity} 313 * but can be set from Settings or via shell command "adb shell wm density". 314 * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int) 315 */ 316 int mBaseDisplayDensity = 0; 317 318 /** 319 * Whether to disable display scaling. This can be set via shell command "adb shell wm scaling". 320 * @see WindowManagerService#setForcedDisplayScalingMode(int, int) 321 */ 322 boolean mDisplayScalingDisabled; 323 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 324 private final Display mDisplay; 325 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 326 private final DisplayPolicy mDisplayPolicy; 327 private DisplayRotation mDisplayRotation; 328 DisplayFrames mDisplayFrames; 329 330 private final RemoteCallbackList<ISystemGestureExclusionListener> 331 mSystemGestureExclusionListeners = new RemoteCallbackList<>(); 332 private final Region mSystemGestureExclusion = new Region(); 333 private int mSystemGestureExclusionLimit; 334 335 /** 336 * For default display it contains real metrics, empty for others. 337 * @see WindowManagerService#createWatermarkInTransaction() 338 */ 339 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 340 341 /** @see #computeCompatSmallestWidth(boolean, int, int, int, DisplayCutout) */ 342 private final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 343 344 /** 345 * Compat metrics computed based on {@link #mDisplayMetrics}. 346 * @see #updateDisplayAndOrientation(int) 347 */ 348 private final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 349 350 /** The desired scaling factor for compatible apps. */ 351 float mCompatibleScreenScale; 352 353 /** 354 * Current rotation of the display. 355 * Constants as per {@link android.view.Surface.Rotation}. 356 * 357 * @see #updateRotationUnchecked() 358 */ 359 private int mRotation = 0; 360 361 /** 362 * Last applied orientation of the display. 363 * Constants as per {@link android.content.pm.ActivityInfo.ScreenOrientation}. 364 * 365 * @see #updateOrientationFromAppTokens() 366 */ 367 private int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 368 369 /** 370 * Orientation forced by some window. If there is no visible window that specifies orientation 371 * it is set to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}. 372 * 373 * @see NonAppWindowContainers#getOrientation() 374 */ 375 private int mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 376 377 /** 378 * Last orientation forced by the keyguard. It is applied when keyguard is shown and is not 379 * occluded. 380 * 381 * @see NonAppWindowContainers#getOrientation() 382 */ 383 private int mLastKeyguardForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 384 385 /** 386 * The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. The 387 * orientation requests from apps would be ignored if the display is close-to-square. 388 */ 389 @VisibleForTesting 390 final float mCloseToSquareMaxAspectRatio; 391 392 /** 393 * If this is true, we would not rotate the display for apps. The rotation would be either the 394 * sensor rotation or the user rotation, controlled by 395 * {@link WindowManagerPolicy.UserRotationMode}. 396 */ 397 private boolean mIgnoreRotationForApps; 398 399 /** 400 * Keep track of wallpaper visibility to notify changes. 401 */ 402 private boolean mLastWallpaperVisible = false; 403 404 private Rect mBaseDisplayRect = new Rect(); 405 406 // Accessed directly by all users. 407 private boolean mLayoutNeeded; 408 int pendingLayoutChanges; 409 int mDeferredRotationPauseCount; 410 411 /** 412 * Used to gate application window layout until we have sent the complete configuration. 413 * TODO: There are still scenarios where we may be out of sync with the client. Ideally 414 * we want to replace this flag with a mechanism that will confirm the configuration 415 * applied by the client is the one expected by the system server. 416 */ 417 boolean mWaitingForConfig; 418 419 // TODO(multi-display): remove some of the usages. 420 @VisibleForTesting 421 boolean isDefaultDisplay; 422 423 /** 424 * Flag indicating whether WindowManager should override info for this display in 425 * DisplayManager. 426 */ 427 boolean mShouldOverrideDisplayConfiguration = true; 428 429 /** Window tokens that are in the process of exiting, but still on screen for animations. */ 430 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>(); 431 432 /** Detect user tapping outside of current focused task bounds .*/ 433 @VisibleForTesting 434 final TaskTapPointerEventListener mTapDetector; 435 436 /** Detect user tapping outside of current focused stack bounds .*/ 437 private Region mTouchExcludeRegion = new Region(); 438 439 /** Save allocating when calculating rects */ 440 private final Rect mTmpRect = new Rect(); 441 private final Rect mTmpRect2 = new Rect(); 442 private final RectF mTmpRectF = new RectF(); 443 private final Matrix mTmpMatrix = new Matrix(); 444 private final Region mTmpRegion = new Region(); 445 446 /** Used for handing back size of display */ 447 private final Rect mTmpBounds = new Rect(); 448 449 private final Configuration mTmpConfiguration = new Configuration(); 450 451 /** Remove this display when animation on it has completed. */ 452 private boolean mDeferredRemoval; 453 454 final DockedStackDividerController mDividerControllerLocked; 455 final PinnedStackController mPinnedStackControllerLocked; 456 457 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>(); 458 /** A collection of windows that provide tap exclude regions inside of them. */ 459 final ArraySet<WindowState> mTapExcludeProvidingWindows = new ArraySet<>(); 460 461 private boolean mHaveBootMsg = false; 462 private boolean mHaveApp = false; 463 private boolean mHaveWallpaper = false; 464 private boolean mHaveKeyguard = true; 465 466 private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList(); 467 468 private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult = 469 new TaskForResizePointSearchResult(); 470 private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState = 471 new ApplySurfaceChangesTransactionState(); 472 473 // True if this display is in the process of being removed. Used to determine if the removal of 474 // the display's direct children should be allowed. 475 private boolean mRemovingDisplay = false; 476 477 // {@code false} if this display is in the processing of being created. 478 private boolean mDisplayReady = false; 479 480 WallpaperController mWallpaperController; 481 482 boolean mWallpaperMayChange = false; 483 484 private final SurfaceSession mSession = new SurfaceSession(); 485 486 /** 487 * Window that is currently interacting with the user. This window is responsible for receiving 488 * key events and pointer events from the user. 489 */ 490 WindowState mCurrentFocus = null; 491 492 /** 493 * The last focused window that we've notified the client that the focus is changed. 494 */ 495 WindowState mLastFocus = null; 496 497 /** 498 * Windows that have lost input focus and are waiting for the new focus window to be displayed 499 * before they are told about this. 500 */ 501 ArrayList<WindowState> mLosingFocus = new ArrayList<>(); 502 503 /** 504 * The foreground app of this display. Windows below this app cannot be the focused window. If 505 * the user taps on the area outside of the task of the focused app, we will notify AM about the 506 * new task the user wants to interact with. 507 */ 508 AppWindowToken mFocusedApp = null; 509 510 /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */ 511 final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>(); 512 513 /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */ 514 final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>(); 515 516 /** 517 * We organize all top-level Surfaces in to the following layers. 518 * mOverlayLayer contains a few Surfaces which are always on top of others 519 * and omitted from Screen-Magnification, for example the strict mode flash or 520 * the magnification overlay itself. 521 * {@link #mWindowingLayer} contains everything else. 522 */ 523 private SurfaceControl mOverlayLayer; 524 525 /** 526 * See {@link #mOverlayLayer} 527 */ 528 private SurfaceControl mWindowingLayer; 529 530 /** 531 * Sequence number for the current layout pass. 532 */ 533 int mLayoutSeq = 0; 534 535 /** 536 * Specifies the count to determine whether to defer updating the IME target until ready. 537 */ 538 private int mDeferUpdateImeTargetCount; 539 540 /** Temporary float array to retrieve 3x3 matrix values. */ 541 private final float[] mTmpFloats = new float[9]; 542 543 private MagnificationSpec mMagnificationSpec; 544 545 private InputMonitor mInputMonitor; 546 547 /** Caches the value whether told display manager that we have content. */ 548 private boolean mLastHasContent; 549 550 private DisplayRotationUtil mRotationUtil = new DisplayRotationUtil(); 551 552 /** 553 * The input method window for this display. 554 */ 555 WindowState mInputMethodWindow; 556 557 /** 558 * This just indicates the window the input method is on top of, not 559 * necessarily the window its input is going to. 560 */ 561 WindowState mInputMethodTarget; 562 563 /** If true hold off on modifying the animation layer of mInputMethodTarget */ 564 boolean mInputMethodTargetWaitingAnim; 565 566 private final PointerEventDispatcher mPointerEventDispatcher; 567 568 private final InsetsStateController mInsetsStateController; 569 570 /** @see #getParentWindow() */ 571 private WindowState mParentWindow; 572 573 private Point mLocationInParentWindow = new Point(); 574 private SurfaceControl mParentSurfaceControl; 575 private InputWindowHandle mPortalWindowHandle; 576 577 // Last systemUiVisibility we received from status bar. 578 private int mLastStatusBarVisibility = 0; 579 // Last systemUiVisibility we dispatched to windows. 580 private int mLastDispatchedSystemUiVisibility = 0; 581 582 /** Corner radius that windows should have in order to match the display. */ 583 private final float mWindowCornerRadius; 584 585 private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> { 586 WindowStateAnimator winAnimator = w.mWinAnimator; 587 final AppWindowToken atoken = w.mAppToken; 588 if (winAnimator.mDrawState == READY_TO_SHOW) { 589 if (atoken == null || atoken.canShowWindows()) { 590 if (w.performShowLocked()) { 591 pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 592 if (DEBUG_LAYOUT_REPEATS) { 593 mWmService.mWindowPlacerLocked.debugLayoutRepeats( 594 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges); 595 } 596 } 597 } 598 } 599 }; 600 601 private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> { 602 final WindowStateAnimator winAnimator = w.mWinAnimator; 603 if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) { 604 return; 605 } 606 607 // If this window is animating, ensure the animation background is set. 608 final AnimationAdapter anim = w.mAppToken != null 609 ? w.mAppToken.getAnimation() 610 : w.getAnimation(); 611 if (anim != null) { 612 final int color = anim.getBackgroundColor(); 613 if (color != 0) { 614 final TaskStack stack = w.getStack(); 615 if (stack != null) { 616 stack.setAnimationBackground(winAnimator, color); 617 } 618 } 619 } 620 }; 621 622 private final Consumer<WindowState> mScheduleToastTimeout = w -> { 623 final int lostFocusUid = mTmpWindow.mOwnerUid; 624 final Handler handler = mWmService.mH; 625 if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) { 626 if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) { 627 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w), 628 w.mAttrs.hideTimeoutMilliseconds); 629 } 630 } 631 }; 632 633 private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> { 634 final AppWindowToken focusedApp = mFocusedApp; 635 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w 636 + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys()); 637 638 if (!w.canReceiveKeys()) { 639 return false; 640 } 641 642 final AppWindowToken wtoken = w.mAppToken; 643 644 // If this window's application has been removed, just skip it. 645 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 646 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because " 647 + (wtoken.removed ? "removed" : "sendingToBottom")); 648 return false; 649 } 650 651 if (focusedApp == null) { 652 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null" 653 + " using new focus @ " + w); 654 mTmpWindow = w; 655 return true; 656 } 657 658 if (!focusedApp.windowsAreFocusable()) { 659 // Current focused app windows aren't focusable... 660 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not" 661 + " focusable using new focus @ " + w); 662 mTmpWindow = w; 663 return true; 664 } 665 666 // Descend through all of the app tokens and find the first that either matches 667 // win.mAppToken (return win) or mFocusedApp (return null). 668 if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) { 669 if (focusedApp.compareTo(wtoken) > 0) { 670 // App stack below focused app stack. No focus for you!!! 671 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, 672 "findFocusedWindow: Reached focused app=" + focusedApp); 673 mTmpWindow = null; 674 return true; 675 } 676 } 677 678 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w); 679 mTmpWindow = w; 680 return true; 681 }; 682 683 private final Consumer<WindowState> mPerformLayout = w -> { 684 // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid 685 // wasting time and funky changes while a window is animating away. 686 final boolean gone = (mTmpWindow != null && mWmService.mPolicy.canBeHiddenByKeyguardLw(w)) 687 || w.isGoneForLayoutLw(); 688 689 if (DEBUG_LAYOUT && !w.mLayoutAttached) { 690 Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame 691 + " mLayoutAttached=" + w.mLayoutAttached 692 + " config reported=" + w.isLastConfigReportedToClient()); 693 final AppWindowToken atoken = w.mAppToken; 694 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility 695 + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden() 696 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) 697 + " parentHidden=" + w.isParentWindowHidden()); 698 else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility 699 + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden() 700 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) 701 + " parentHidden=" + w.isParentWindowHidden()); 702 } 703 704 // If this view is GONE, then skip it -- keep the current frame, and let the caller know 705 // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows, 706 // since that means "perform layout as normal, just don't display"). 707 if ((!gone || !w.mHaveFrame || w.mLayoutNeeded) && !w.mLayoutAttached) { 708 if (mTmpInitial) { 709 w.resetContentChanged(); 710 } 711 if (w.mAttrs.type == TYPE_DREAM) { 712 // Don't layout windows behind a dream, so that if it does stuff like hide 713 // the status bar we won't get a bad transition when it goes away. 714 mTmpWindow = w; 715 } 716 w.mLayoutNeeded = false; 717 w.prelayout(); 718 final boolean firstLayout = !w.isLaidOut(); 719 getDisplayPolicy().layoutWindowLw(w, null, mDisplayFrames); 720 w.mLayoutSeq = mLayoutSeq; 721 722 // If this is the first layout, we need to initialize the last inset values as 723 // otherwise we'd immediately cause an unnecessary resize. 724 if (firstLayout) { 725 w.updateLastInsetValues(); 726 } 727 728 if (w.mAppToken != null) { 729 w.mAppToken.layoutLetterbox(w); 730 } 731 732 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrameLw() 733 + " mContainingFrame=" + w.getContainingFrame() 734 + " mDisplayFrame=" + w.getDisplayFrameLw()); 735 } 736 }; 737 738 private final Consumer<WindowState> mPerformLayoutAttached = w -> { 739 if (w.mLayoutAttached) { 740 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame 741 + " mViewVisibility=" + w.mViewVisibility 742 + " mRelayoutCalled=" + w.mRelayoutCalled); 743 // If this view is GONE, then skip it -- keep the current frame, and let the caller 744 // know so they can ignore it if they want. (We do the normal layout for INVISIBLE 745 // windows, since that means "perform layout as normal, just don't display"). 746 if (mTmpWindow != null && mWmService.mPolicy.canBeHiddenByKeyguardLw(w)) { 747 return; 748 } 749 if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame 750 || w.mLayoutNeeded) { 751 if (mTmpInitial) { 752 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 753 w.resetContentChanged(); 754 } 755 w.mLayoutNeeded = false; 756 w.prelayout(); 757 getDisplayPolicy().layoutWindowLw(w, w.getParentWindow(), mDisplayFrames); 758 w.mLayoutSeq = mLayoutSeq; 759 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrameLw() 760 + " mContainingFrame=" + w.getContainingFrame() 761 + " mDisplayFrame=" + w.getDisplayFrameLw()); 762 } 763 } else if (w.mAttrs.type == TYPE_DREAM) { 764 // Don't layout windows behind a dream, so that if it does stuff like hide the 765 // status bar we won't get a bad transition when it goes away. 766 mTmpWindow = mTmpWindow2; 767 } 768 }; 769 770 private final Predicate<WindowState> mComputeImeTargetPredicate = w -> { 771 if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w 772 + " fl=0x" + Integer.toHexString(w.mAttrs.flags)); 773 return w.canBeImeTarget(); 774 }; 775 776 private final Consumer<WindowState> mApplyPostLayoutPolicy = 777 w -> getDisplayPolicy().applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(), 778 mInputMethodTarget); 779 780 private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> { 781 final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked; 782 final boolean obscuredChanged = w.mObscured != 783 mTmpApplySurfaceChangesTransactionState.obscured; 784 final RootWindowContainer root = mWmService.mRoot; 785 786 // Update effect. 787 w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured; 788 if (!mTmpApplySurfaceChangesTransactionState.obscured) { 789 final boolean isDisplayed = w.isDisplayedLw(); 790 791 if (isDisplayed && w.isObscuringDisplay()) { 792 // This window completely covers everything behind it, so we want to leave all 793 // of them as undimmed (for performance reasons). 794 root.mObscuringWindow = w; 795 mTmpApplySurfaceChangesTransactionState.obscured = true; 796 } 797 798 mTmpApplySurfaceChangesTransactionState.displayHasContent |= 799 root.handleNotObscuredLocked(w, 800 mTmpApplySurfaceChangesTransactionState.obscured, 801 mTmpApplySurfaceChangesTransactionState.syswin); 802 803 if (w.mHasSurface && isDisplayed) { 804 final int type = w.mAttrs.type; 805 if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR 806 || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 807 mTmpApplySurfaceChangesTransactionState.syswin = true; 808 } 809 if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0 810 && w.mAttrs.preferredRefreshRate != 0) { 811 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate 812 = w.mAttrs.preferredRefreshRate; 813 } 814 final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy() 815 .getPreferredModeId(w); 816 if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0 817 && preferredModeId != 0) { 818 mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId; 819 } 820 } 821 } 822 823 if (obscuredChanged && w.isVisibleLw() && mWallpaperController.isWallpaperTarget(w)) { 824 // This is the wallpaper target and its obscured state changed... make sure the 825 // current wallpaper's visibility has been updated accordingly. 826 mWallpaperController.updateWallpaperVisibility(); 827 } 828 829 w.handleWindowMovedIfNeeded(); 830 831 final WindowStateAnimator winAnimator = w.mWinAnimator; 832 833 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 834 w.resetContentChanged(); 835 836 // Moved from updateWindowsAndWallpaperLocked(). 837 if (w.mHasSurface) { 838 // Take care of the window being ready to display. 839 final boolean committed = winAnimator.commitFinishDrawingLocked(); 840 if (isDefaultDisplay && committed) { 841 if (w.mAttrs.type == TYPE_DREAM) { 842 // HACK: When a dream is shown, it may at that point hide the lock screen. 843 // So we need to redo the layout to let the phone window manager make this 844 // happen. 845 pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 846 if (DEBUG_LAYOUT_REPEATS) { 847 surfacePlacer.debugLayoutRepeats( 848 "dream and commitFinishDrawingLocked true", 849 pendingLayoutChanges); 850 } 851 } 852 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 853 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 854 "First draw done in potential wallpaper target " + w); 855 mWallpaperMayChange = true; 856 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 857 if (DEBUG_LAYOUT_REPEATS) { 858 surfacePlacer.debugLayoutRepeats( 859 "wallpaper and commitFinishDrawingLocked true", 860 pendingLayoutChanges); 861 } 862 } 863 } 864 } 865 866 final AppWindowToken atoken = w.mAppToken; 867 if (atoken != null) { 868 atoken.updateLetterboxSurface(w); 869 final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w); 870 if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) { 871 mTmpUpdateAllDrawn.add(atoken); 872 } 873 } 874 875 if (!mLosingFocus.isEmpty() && w.isFocused() && w.isDisplayedLw()) { 876 mWmService.mH.obtainMessage(REPORT_LOSING_FOCUS, this).sendToTarget(); 877 } 878 879 w.updateResizingWindowIfNeeded(); 880 }; 881 882 /** 883 * Create new {@link DisplayContent} instance, add itself to the root window container and 884 * initialize direct children. 885 * @param display May not be null. 886 * @param service You know. 887 * @param activityDisplay The ActivityDisplay for the display container. 888 */ DisplayContent(Display display, WindowManagerService service, ActivityDisplay activityDisplay)889 DisplayContent(Display display, WindowManagerService service, 890 ActivityDisplay activityDisplay) { 891 super(service); 892 mAcitvityDisplay = activityDisplay; 893 if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) { 894 throw new IllegalArgumentException("Display with ID=" + display.getDisplayId() 895 + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId()) 896 + " new=" + display); 897 } 898 899 mDisplay = display; 900 mDisplayId = display.getDisplayId(); 901 mWallpaperController = new WallpaperController(mWmService, this); 902 display.getDisplayInfo(mDisplayInfo); 903 display.getMetrics(mDisplayMetrics); 904 mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp 905 * mDisplayMetrics.densityDpi / DENSITY_DEFAULT; 906 isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; 907 mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo, 908 calculateDisplayCutoutForRotation(mDisplayInfo.rotation)); 909 initializeDisplayBaseInfo(); 910 911 mAppTransition = new AppTransition(service.mContext, service, this); 912 mAppTransition.registerListenerLocked(service.mActivityManagerAppTransitionNotifier); 913 mAppTransitionController = new AppTransitionController(service, this); 914 mUnknownAppVisibilityController = new UnknownAppVisibilityController(service, this); 915 916 AnimationHandler animationHandler = new AnimationHandler(); 917 mBoundsAnimationController = new BoundsAnimationController(service.mContext, 918 mAppTransition, AnimationThread.getHandler(), animationHandler); 919 920 final InputChannel inputChannel = mWmService.mInputManager.monitorInput( 921 "PointerEventDispatcher" + mDisplayId, mDisplayId); 922 mPointerEventDispatcher = new PointerEventDispatcher(inputChannel); 923 924 // Tap Listeners are supported for: 925 // 1. All physical displays (multi-display). 926 // 2. VirtualDisplays on VR, AA (and everything else). 927 mTapDetector = new TaskTapPointerEventListener(mWmService, this); 928 registerPointerEventListener(mTapDetector); 929 registerPointerEventListener(mWmService.mMousePositionTracker); 930 if (mWmService.mAtmService.getRecentTasks() != null) { 931 registerPointerEventListener( 932 mWmService.mAtmService.getRecentTasks().getInputListener()); 933 } 934 935 mDisplayPolicy = new DisplayPolicy(service, this); 936 mDisplayRotation = new DisplayRotation(service, this); 937 mCloseToSquareMaxAspectRatio = service.mContext.getResources().getFloat( 938 com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio); 939 if (isDefaultDisplay) { 940 // The policy may be invoked right after here, so it requires the necessary default 941 // fields of this display content. 942 mWmService.mPolicy.setDefaultDisplay(this); 943 } 944 if (mWmService.mDisplayReady) { 945 mDisplayPolicy.onConfigurationChanged(); 946 } 947 if (mWmService.mSystemReady) { 948 mDisplayPolicy.systemReady(); 949 } 950 mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius(); 951 mDividerControllerLocked = new DockedStackDividerController(service, this); 952 mPinnedStackControllerLocked = new PinnedStackController(service, this); 953 954 final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession) 955 .setOpaque(true) 956 .setContainerLayer(); 957 mWindowingLayer = b.setName("Display Root").build(); 958 mOverlayLayer = b.setName("Display Overlays").build(); 959 960 getPendingTransaction().setLayer(mWindowingLayer, 0) 961 .setLayerStack(mWindowingLayer, mDisplayId) 962 .show(mWindowingLayer) 963 .setLayer(mOverlayLayer, 1) 964 .setLayerStack(mOverlayLayer, mDisplayId) 965 .show(mOverlayLayer); 966 getPendingTransaction().apply(); 967 968 // These are the only direct children we should ever have and they are permanent. 969 super.addChild(mBelowAppWindowsContainers, null); 970 super.addChild(mTaskStackContainers, null); 971 super.addChild(mAboveAppWindowsContainers, null); 972 super.addChild(mImeWindowsContainers, null); 973 974 // Add itself as a child to the root container. 975 mWmService.mRoot.addChild(this, null); 976 977 // TODO(b/62541591): evaluate whether this is the best spot to declare the 978 // {@link DisplayContent} ready for use. 979 mDisplayReady = true; 980 981 mWmService.mAnimator.addDisplayLocked(mDisplayId); 982 mInputMonitor = new InputMonitor(service, mDisplayId); 983 mInsetsStateController = new InsetsStateController(this); 984 } 985 isReady()986 boolean isReady() { 987 // The display is ready when the system and the individual display are both ready. 988 return mWmService.mDisplayReady && mDisplayReady; 989 } 990 getDisplayId()991 int getDisplayId() { 992 return mDisplayId; 993 } 994 getWindowCornerRadius()995 float getWindowCornerRadius() { 996 return mWindowCornerRadius; 997 } 998 getWindowToken(IBinder binder)999 WindowToken getWindowToken(IBinder binder) { 1000 return mTokenMap.get(binder); 1001 } 1002 getAppWindowToken(IBinder binder)1003 AppWindowToken getAppWindowToken(IBinder binder) { 1004 final WindowToken token = getWindowToken(binder); 1005 if (token == null) { 1006 return null; 1007 } 1008 return token.asAppWindowToken(); 1009 } 1010 addWindowToken(IBinder binder, WindowToken token)1011 private void addWindowToken(IBinder binder, WindowToken token) { 1012 final DisplayContent dc = mWmService.mRoot.getWindowTokenDisplay(token); 1013 if (dc != null) { 1014 // We currently don't support adding a window token to the display if the display 1015 // already has the binder mapped to another token. If there is a use case for supporting 1016 // this moving forward we will either need to merge the WindowTokens some how or have 1017 // the binder map to a list of window tokens. 1018 throw new IllegalArgumentException("Can't map token=" + token + " to display=" 1019 + getName() + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap); 1020 } 1021 if (binder == null) { 1022 throw new IllegalArgumentException("Can't map token=" + token + " to display=" 1023 + getName() + " binder is null"); 1024 } 1025 if (token == null) { 1026 throw new IllegalArgumentException("Can't map null token to display=" 1027 + getName() + " binder=" + binder); 1028 } 1029 1030 mTokenMap.put(binder, token); 1031 1032 if (token.asAppWindowToken() == null) { 1033 // Add non-app token to container hierarchy on the display. App tokens are added through 1034 // the parent container managing them (e.g. Tasks). 1035 switch (token.windowType) { 1036 case TYPE_WALLPAPER: 1037 mBelowAppWindowsContainers.addChild(token); 1038 break; 1039 case TYPE_INPUT_METHOD: 1040 case TYPE_INPUT_METHOD_DIALOG: 1041 mImeWindowsContainers.addChild(token); 1042 break; 1043 default: 1044 mAboveAppWindowsContainers.addChild(token); 1045 break; 1046 } 1047 } 1048 } 1049 removeWindowToken(IBinder binder)1050 WindowToken removeWindowToken(IBinder binder) { 1051 final WindowToken token = mTokenMap.remove(binder); 1052 if (token != null && token.asAppWindowToken() == null) { 1053 token.setExiting(); 1054 } 1055 return token; 1056 } 1057 1058 /** Changes the display the input window token is housed on to this one. */ reParentWindowToken(WindowToken token)1059 void reParentWindowToken(WindowToken token) { 1060 final DisplayContent prevDc = token.getDisplayContent(); 1061 if (prevDc == this) { 1062 return; 1063 } 1064 if (prevDc != null) { 1065 if (prevDc.mTokenMap.remove(token.token) != null && token.asAppWindowToken() == null) { 1066 // Removed the token from the map, but made sure it's not an app token before 1067 // removing from parent. 1068 token.getParent().removeChild(token); 1069 } 1070 if (prevDc.mLastFocus == mCurrentFocus) { 1071 // The window has become the focus of this display, so it should not be notified 1072 // that it lost focus from the previous display. 1073 prevDc.mLastFocus = null; 1074 } 1075 } 1076 1077 addWindowToken(token.token, token); 1078 } 1079 removeAppToken(IBinder binder)1080 void removeAppToken(IBinder binder) { 1081 final WindowToken token = removeWindowToken(binder); 1082 if (token == null) { 1083 Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder); 1084 return; 1085 } 1086 1087 final AppWindowToken appToken = token.asAppWindowToken(); 1088 1089 if (appToken == null) { 1090 Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token); 1091 return; 1092 } 1093 1094 appToken.onRemovedFromDisplay(); 1095 } 1096 1097 @Override getDisplay()1098 public Display getDisplay() { 1099 return mDisplay; 1100 } 1101 getDisplayInfo()1102 DisplayInfo getDisplayInfo() { 1103 return mDisplayInfo; 1104 } 1105 getDisplayMetrics()1106 DisplayMetrics getDisplayMetrics() { 1107 return mDisplayMetrics; 1108 } 1109 getDisplayPolicy()1110 DisplayPolicy getDisplayPolicy() { 1111 return mDisplayPolicy; 1112 } 1113 1114 @Override getDisplayRotation()1115 public DisplayRotation getDisplayRotation() { 1116 return mDisplayRotation; 1117 } 1118 1119 /** 1120 * Marks a window as providing insets for the rest of the windows in the system. 1121 * 1122 * @param type The type of inset this window provides. 1123 * @param win The window. 1124 * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of 1125 * the window should be taken. 1126 */ setInsetProvider(@nternalInsetType int type, WindowState win, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider)1127 void setInsetProvider(@InternalInsetType int type, WindowState win, 1128 @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) { 1129 mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider); 1130 } 1131 getInsetsStateController()1132 InsetsStateController getInsetsStateController() { 1133 return mInsetsStateController; 1134 } 1135 1136 @VisibleForTesting setDisplayRotation(DisplayRotation displayRotation)1137 void setDisplayRotation(DisplayRotation displayRotation) { 1138 mDisplayRotation = displayRotation; 1139 } 1140 getRotation()1141 int getRotation() { 1142 return mRotation; 1143 } 1144 1145 @VisibleForTesting setRotation(int newRotation)1146 void setRotation(int newRotation) { 1147 mRotation = newRotation; 1148 mDisplayRotation.setRotation(newRotation); 1149 } 1150 getLastOrientation()1151 int getLastOrientation() { 1152 return mLastOrientation; 1153 } 1154 getLastWindowForcedOrientation()1155 int getLastWindowForcedOrientation() { 1156 return mLastWindowForcedOrientation; 1157 } 1158 registerRemoteAnimations(RemoteAnimationDefinition definition)1159 void registerRemoteAnimations(RemoteAnimationDefinition definition) { 1160 mAppTransitionController.registerRemoteAnimations(definition); 1161 } 1162 1163 /** 1164 * Temporarily pauses rotation changes until resumed. 1165 * 1166 * This can be used to prevent rotation changes from occurring while the user is 1167 * performing certain operations, such as drag and drop. 1168 * 1169 * This call nests and must be matched by an equal number of calls to 1170 * {@link #resumeRotationLocked}. 1171 */ pauseRotationLocked()1172 void pauseRotationLocked() { 1173 mDeferredRotationPauseCount++; 1174 } 1175 1176 /** 1177 * Resumes normal rotation changes after being paused. 1178 */ resumeRotationLocked()1179 void resumeRotationLocked() { 1180 if (mDeferredRotationPauseCount <= 0) { 1181 return; 1182 } 1183 1184 mDeferredRotationPauseCount--; 1185 if (mDeferredRotationPauseCount == 0) { 1186 updateRotationAndSendNewConfigIfNeeded(); 1187 } 1188 } 1189 1190 /** 1191 * If this is true we have updated our desired orientation, but not yet changed the real 1192 * orientation our applied our screen rotation animation. For example, because a previous 1193 * screen rotation was in progress. 1194 * 1195 * @return {@code true} if the there is an ongoing rotation change. 1196 */ rotationNeedsUpdate()1197 boolean rotationNeedsUpdate() { 1198 final int lastOrientation = getLastOrientation(); 1199 final int oldRotation = getRotation(); 1200 1201 final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation); 1202 return oldRotation != rotation; 1203 } 1204 1205 /** 1206 * The display content may have configuration set from {@link #DisplayWindowSettings}. This 1207 * callback let the owner of container know there is existing configuration to prevent the 1208 * values from being replaced by the initializing {@link #ActivityDisplay}. 1209 */ initializeDisplayOverrideConfiguration()1210 void initializeDisplayOverrideConfiguration() { 1211 if (mAcitvityDisplay != null) { 1212 mAcitvityDisplay.onInitializeOverrideConfiguration(getRequestedOverrideConfiguration()); 1213 } 1214 } 1215 1216 /** Notify the configuration change of this display. */ sendNewConfiguration()1217 void sendNewConfiguration() { 1218 mWmService.mH.obtainMessage(SEND_NEW_CONFIGURATION, this).sendToTarget(); 1219 } 1220 1221 @Override onDescendantOrientationChanged(IBinder freezeDisplayToken, ConfigurationContainer requestingContainer)1222 boolean onDescendantOrientationChanged(IBinder freezeDisplayToken, 1223 ConfigurationContainer requestingContainer) { 1224 final Configuration config = updateOrientationFromAppTokens( 1225 getRequestedOverrideConfiguration(), freezeDisplayToken, false); 1226 // If display rotation class tells us that it doesn't consider app requested orientation, 1227 // this display won't rotate just because of an app changes its requested orientation. Thus 1228 // it indicates that this display chooses not to handle this request. 1229 final boolean handled = getDisplayRotation().respectAppRequestedOrientation(); 1230 if (config == null) { 1231 return handled; 1232 } 1233 1234 if (handled && requestingContainer instanceof ActivityRecord) { 1235 final ActivityRecord activityRecord = (ActivityRecord) requestingContainer; 1236 final boolean kept = mWmService.mAtmService.updateDisplayOverrideConfigurationLocked( 1237 config, activityRecord, false /* deferResume */, getDisplayId()); 1238 activityRecord.frozenBeforeDestroy = true; 1239 if (!kept) { 1240 mWmService.mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities(); 1241 } 1242 } else { 1243 // We have a new configuration to push so we need to update ATMS for now. 1244 // TODO: Clean up display configuration push between ATMS and WMS after unification. 1245 mWmService.mAtmService.updateDisplayOverrideConfigurationLocked( 1246 config, null /* starting */, false /* deferResume */, getDisplayId()); 1247 } 1248 return handled; 1249 } 1250 1251 @Override handlesOrientationChangeFromDescendant()1252 boolean handlesOrientationChangeFromDescendant() { 1253 return getDisplayRotation().respectAppRequestedOrientation(); 1254 } 1255 1256 /** 1257 * Determine the new desired orientation of this display. 1258 * 1259 * The orientation is computed from non-application windows first. If none of the 1260 * non-application windows specify orientation, the orientation is computed from application 1261 * tokens. 1262 * 1263 * @return {@code true} if the orientation is changed. 1264 */ updateOrientationFromAppTokens()1265 boolean updateOrientationFromAppTokens() { 1266 return updateOrientationFromAppTokens(false /* forceUpdate */); 1267 } 1268 1269 /** 1270 * Update orientation of the target display, returning a non-null new Configuration if it has 1271 * changed from the current orientation. If a non-null configuration is returned, someone must 1272 * call {@link WindowManagerService#setNewDisplayOverrideConfiguration(Configuration, 1273 * DisplayContent)} to tell the window manager it can unfreeze the screen. This will typically 1274 * be done by calling {@link WindowManagerService#sendNewConfiguration(int)}. 1275 */ updateOrientationFromAppTokens(Configuration currentConfig, IBinder freezeDisplayToken, boolean forceUpdate)1276 Configuration updateOrientationFromAppTokens(Configuration currentConfig, 1277 IBinder freezeDisplayToken, boolean forceUpdate) { 1278 if (!mDisplayReady) { 1279 return null; 1280 } 1281 1282 Configuration config = null; 1283 if (updateOrientationFromAppTokens(forceUpdate)) { 1284 // If we changed the orientation but mOrientationChangeComplete is already true, 1285 // we used seamless rotation, and we don't need to freeze the screen. 1286 if (freezeDisplayToken != null && !mWmService.mRoot.mOrientationChangeComplete) { 1287 final AppWindowToken atoken = getAppWindowToken(freezeDisplayToken); 1288 if (atoken != null) { 1289 atoken.startFreezingScreen(); 1290 } 1291 } 1292 config = new Configuration(); 1293 computeScreenConfiguration(config); 1294 } else if (currentConfig != null) { 1295 // No obvious action we need to take, but if our current state mismatches the 1296 // activity manager's, update it, disregarding font scale, which should remain set 1297 // to the value of the previous configuration. 1298 // Here we're calling Configuration#unset() instead of setToDefaults() because we 1299 // need to keep override configs clear of non-empty values (e.g. fontSize). 1300 mTmpConfiguration.unset(); 1301 mTmpConfiguration.updateFrom(currentConfig); 1302 computeScreenConfiguration(mTmpConfiguration); 1303 if (currentConfig.diff(mTmpConfiguration) != 0) { 1304 mWaitingForConfig = true; 1305 setLayoutNeeded(); 1306 int[] anim = new int[2]; 1307 getDisplayPolicy().selectRotationAnimationLw(anim); 1308 1309 mWmService.startFreezingDisplayLocked(anim[0], anim[1], this); 1310 config = new Configuration(mTmpConfiguration); 1311 } 1312 } 1313 1314 return config; 1315 } 1316 1317 updateOrientationFromAppTokens(boolean forceUpdate)1318 private boolean updateOrientationFromAppTokens(boolean forceUpdate) { 1319 final int req = getOrientation(); 1320 if (req != mLastOrientation || forceUpdate) { 1321 mLastOrientation = req; 1322 mDisplayRotation.setCurrentOrientation(req); 1323 return updateRotationUnchecked(forceUpdate); 1324 } 1325 return false; 1326 } 1327 1328 /** 1329 * Update rotation of the display and send configuration if the rotation is changed. 1330 * 1331 * @return {@code true} if the rotation has been changed and the new config is sent. 1332 */ updateRotationAndSendNewConfigIfNeeded()1333 boolean updateRotationAndSendNewConfigIfNeeded() { 1334 final boolean changed = updateRotationUnchecked(false /* forceUpdate */); 1335 if (changed) { 1336 sendNewConfiguration(); 1337 } 1338 return changed; 1339 } 1340 1341 /** 1342 * Update rotation of the display. 1343 * 1344 * @return {@code true} if the rotation has been changed. In this case YOU MUST CALL 1345 * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN. 1346 */ updateRotationUnchecked()1347 boolean updateRotationUnchecked() { 1348 return updateRotationUnchecked(false /* forceUpdate */); 1349 } 1350 1351 /** 1352 * Update rotation of the DisplayContent with an option to force the update. This updates 1353 * the container's perception of rotation and, depending on the top activities, will freeze 1354 * the screen or start seamless rotation. The display itself gets rotated in 1355 * {@link #applyRotationLocked} during {@link WindowManagerService#sendNewConfiguration}. 1356 * 1357 * @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating 1358 * orientation because we're waiting for some rotation to finish or display 1359 * to unfreeze, which results in configuration of the previously visible 1360 * activity being applied to a newly visible one. Forcing the rotation 1361 * update allows to workaround this issue. 1362 * @return {@code true} if the rotation has been changed. In this case YOU MUST CALL 1363 * {@link WindowManagerService#sendNewConfiguration(int)} TO COMPLETE THE ROTATION AND 1364 * UNFREEZE THE SCREEN. 1365 */ updateRotationUnchecked(boolean forceUpdate)1366 boolean updateRotationUnchecked(boolean forceUpdate) { 1367 ScreenRotationAnimation screenRotationAnimation; 1368 if (!forceUpdate) { 1369 if (mDeferredRotationPauseCount > 0) { 1370 // Rotation updates have been paused temporarily. Defer the update until 1371 // updates have been resumed. 1372 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused."); 1373 return false; 1374 } 1375 1376 screenRotationAnimation = 1377 mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); 1378 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 1379 // Rotation updates cannot be performed while the previous rotation change 1380 // animation is still in progress. Skip this update. We will try updating 1381 // again after the animation is finished and the display is unfrozen. 1382 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress."); 1383 return false; 1384 } 1385 if (mWmService.mDisplayFrozen) { 1386 // Even if the screen rotation animation has finished (e.g. isAnimating 1387 // returns false), there is still some time where we haven't yet unfrozen 1388 // the display. We also need to abort rotation here. 1389 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 1390 "Deferring rotation, still finishing previous rotation"); 1391 return false; 1392 } 1393 } 1394 1395 if (!mWmService.mDisplayEnabled) { 1396 // No point choosing a rotation if the display is not enabled. 1397 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled."); 1398 return false; 1399 } 1400 1401 final int oldRotation = mRotation; 1402 final int lastOrientation = mLastOrientation; 1403 final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation); 1404 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id=" 1405 + mDisplayId + " based on lastOrientation=" + lastOrientation 1406 + " and oldRotation=" + oldRotation); 1407 boolean mayRotateSeamlessly = mDisplayPolicy.shouldRotateSeamlessly(mDisplayRotation, 1408 oldRotation, rotation); 1409 1410 if (mayRotateSeamlessly) { 1411 final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated); 1412 if (seamlessRotated != null && !forceUpdate) { 1413 // We can't rotate (seamlessly or not) while waiting for the last seamless rotation 1414 // to complete (that is, waiting for windows to redraw). It's tempting to check 1415 // w.mSeamlessRotationCount but that could be incorrect in the case of 1416 // window-removal. 1417 return false; 1418 } 1419 1420 // In the presence of the PINNED stack or System Alert 1421 // windows we unfortunately can not seamlessly rotate. 1422 if (hasPinnedStack()) { 1423 mayRotateSeamlessly = false; 1424 } 1425 for (int i = 0; i < mWmService.mSessions.size(); i++) { 1426 if (mWmService.mSessions.valueAt(i).hasAlertWindowSurfaces()) { 1427 mayRotateSeamlessly = false; 1428 break; 1429 } 1430 } 1431 } 1432 final boolean rotateSeamlessly = mayRotateSeamlessly; 1433 1434 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId 1435 + " selected orientation " + lastOrientation 1436 + ", got rotation " + rotation); 1437 1438 if (oldRotation == rotation) { 1439 // No change. 1440 return false; 1441 } 1442 1443 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId 1444 + " rotation changed to " + rotation 1445 + " from " + oldRotation 1446 + ", lastOrientation=" + lastOrientation); 1447 1448 if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) { 1449 mWaitingForConfig = true; 1450 } 1451 1452 mRotation = rotation; 1453 1454 mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; 1455 mWmService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT, 1456 this, WINDOW_FREEZE_TIMEOUT_DURATION); 1457 1458 setLayoutNeeded(); 1459 final int[] anim = new int[2]; 1460 mDisplayPolicy.selectRotationAnimationLw(anim); 1461 1462 if (!rotateSeamlessly) { 1463 mWmService.startFreezingDisplayLocked(anim[0], anim[1], this); 1464 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 1465 } else { 1466 // The screen rotation animation uses a screenshot to freeze the screen 1467 // while windows resize underneath. 1468 // When we are rotating seamlessly, we allow the elements to transition 1469 // to their rotated state independently and without a freeze required. 1470 mWmService.startSeamlessRotation(); 1471 } 1472 1473 return true; 1474 } 1475 1476 /** 1477 * Applies the rotation transaction. This must be called after {@link #updateRotationUnchecked} 1478 * (if it returned {@code true}) to actually finish the rotation. 1479 * 1480 * @param oldRotation the rotation we are coming from. 1481 * @param rotation the rotation to apply. 1482 */ applyRotationLocked(final int oldRotation, final int rotation)1483 void applyRotationLocked(final int oldRotation, final int rotation) { 1484 mDisplayRotation.setRotation(rotation); 1485 final boolean rotateSeamlessly = mWmService.isRotatingSeamlessly(); 1486 ScreenRotationAnimation screenRotationAnimation = rotateSeamlessly 1487 ? null : mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); 1488 // We need to update our screen size information to match the new rotation. If the rotation 1489 // has actually changed then this method will return true and, according to the comment at 1490 // the top of the method, the caller is obligated to call computeNewConfigurationLocked(). 1491 // By updating the Display info here it will be available to 1492 // #computeScreenConfiguration() later. 1493 updateDisplayAndOrientation(getConfiguration().uiMode, null /* outConfig */); 1494 1495 // NOTE: We disable the rotation in the emulator because 1496 // it doesn't support hardware OpenGL emulation yet. 1497 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 1498 && screenRotationAnimation.hasScreenshot()) { 1499 if (screenRotationAnimation.setRotation(getPendingTransaction(), rotation, 1500 MAX_ANIMATION_DURATION, mWmService.getTransitionAnimationScaleLocked(), 1501 mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) { 1502 mWmService.scheduleAnimationLocked(); 1503 } 1504 } 1505 1506 forAllWindows(w -> { 1507 w.seamlesslyRotateIfAllowed(getPendingTransaction(), oldRotation, rotation, 1508 rotateSeamlessly); 1509 }, true /* traverseTopToBottom */); 1510 1511 mWmService.mDisplayManagerInternal.performTraversal(getPendingTransaction()); 1512 scheduleAnimation(); 1513 1514 forAllWindows(w -> { 1515 if (w.mHasSurface && !rotateSeamlessly) { 1516 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w); 1517 w.setOrientationChanging(true); 1518 mWmService.mRoot.mOrientationChangeComplete = false; 1519 w.mLastFreezeDuration = 0; 1520 } 1521 w.mReportOrientationChanged = true; 1522 }, true /* traverseTopToBottom */); 1523 1524 if (rotateSeamlessly) { 1525 mWmService.mH.sendNewMessageDelayed(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT, 1526 this, SEAMLESS_ROTATION_TIMEOUT_DURATION); 1527 } 1528 1529 for (int i = mWmService.mRotationWatchers.size() - 1; i >= 0; i--) { 1530 final WindowManagerService.RotationWatcher rotationWatcher 1531 = mWmService.mRotationWatchers.get(i); 1532 if (rotationWatcher.mDisplayId == mDisplayId) { 1533 try { 1534 rotationWatcher.mWatcher.onRotationChanged(rotation); 1535 } catch (RemoteException e) { 1536 // Ignore 1537 } 1538 } 1539 } 1540 1541 // Announce rotation only if we will not animate as we already have the 1542 // windows in final state. Otherwise, we make this call at the rotation end. 1543 if (screenRotationAnimation == null && mWmService.mAccessibilityController != null) { 1544 mWmService.mAccessibilityController.onRotationChangedLocked(this); 1545 } 1546 } 1547 configureDisplayPolicy()1548 void configureDisplayPolicy() { 1549 final int width = mBaseDisplayWidth; 1550 final int height = mBaseDisplayHeight; 1551 final int shortSize; 1552 final int longSize; 1553 if (width > height) { 1554 shortSize = height; 1555 longSize = width; 1556 } else { 1557 shortSize = width; 1558 longSize = height; 1559 } 1560 1561 final int shortSizeDp = shortSize * DENSITY_DEFAULT / mBaseDisplayDensity; 1562 final int longSizeDp = longSize * DENSITY_DEFAULT / mBaseDisplayDensity; 1563 1564 mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors(); 1565 mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp); 1566 1567 mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo, 1568 calculateDisplayCutoutForRotation(mDisplayInfo.rotation)); 1569 1570 // Not much of use to rotate the display for apps since it's close to square. 1571 mIgnoreRotationForApps = isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height); 1572 } 1573 isNonDecorDisplayCloseToSquare(int rotation, int width, int height)1574 private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) { 1575 final DisplayCutout displayCutout = 1576 calculateDisplayCutoutForRotation(rotation).getDisplayCutout(); 1577 final int uiMode = mWmService.mPolicy.getUiMode(); 1578 final int w = mDisplayPolicy.getNonDecorDisplayWidth( 1579 width, height, rotation, uiMode, displayCutout); 1580 final int h = mDisplayPolicy.getNonDecorDisplayHeight( 1581 width, height, rotation, uiMode, displayCutout); 1582 final float aspectRatio = Math.max(w, h) / (float) Math.min(w, h); 1583 return aspectRatio <= mCloseToSquareMaxAspectRatio; 1584 } 1585 1586 /** 1587 * Update {@link #mDisplayInfo} and other internal variables when display is rotated or config 1588 * changed. 1589 * Do not call if {@link WindowManagerService#mDisplayReady} == false. 1590 */ updateDisplayAndOrientation(int uiMode, Configuration outConfig)1591 private DisplayInfo updateDisplayAndOrientation(int uiMode, Configuration outConfig) { 1592 // Use the effective "visual" dimensions based on current rotation 1593 final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270); 1594 final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 1595 final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 1596 1597 // Update application display metrics. 1598 final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(mRotation); 1599 final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout(); 1600 1601 final int appWidth = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode, 1602 displayCutout); 1603 final int appHeight = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode, 1604 displayCutout); 1605 mDisplayInfo.rotation = mRotation; 1606 mDisplayInfo.logicalWidth = dw; 1607 mDisplayInfo.logicalHeight = dh; 1608 mDisplayInfo.logicalDensityDpi = mBaseDisplayDensity; 1609 mDisplayInfo.appWidth = appWidth; 1610 mDisplayInfo.appHeight = appHeight; 1611 if (isDefaultDisplay) { 1612 mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics, 1613 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 1614 } 1615 mDisplayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout; 1616 mDisplayInfo.getAppMetrics(mDisplayMetrics); 1617 if (mDisplayScalingDisabled) { 1618 mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED; 1619 } else { 1620 mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED; 1621 } 1622 1623 computeSizeRangesAndScreenLayout(mDisplayInfo, rotated, uiMode, dw, dh, 1624 mDisplayMetrics.density, outConfig); 1625 1626 // We usually set the override info in DisplayManager so that we get consistent display 1627 // metrics values when displays are changing and don't send out new values until WM is aware 1628 // of them. However, we don't do this for displays that serve as containers for ActivityView 1629 // because we don't want letter-/pillar-boxing during resize. 1630 final DisplayInfo overrideDisplayInfo = mShouldOverrideDisplayConfiguration 1631 ? mDisplayInfo : null; 1632 mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId, 1633 overrideDisplayInfo); 1634 1635 mBaseDisplayRect.set(0, 0, dw, dh); 1636 1637 if (isDefaultDisplay) { 1638 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics, 1639 mCompatDisplayMetrics); 1640 } 1641 1642 return mDisplayInfo; 1643 } 1644 calculateDisplayCutoutForRotation(int rotation)1645 WmDisplayCutout calculateDisplayCutoutForRotation(int rotation) { 1646 return mDisplayCutoutCache.getOrCompute(mInitialDisplayCutout, rotation); 1647 } 1648 calculateDisplayCutoutForRotationUncached( DisplayCutout cutout, int rotation)1649 private WmDisplayCutout calculateDisplayCutoutForRotationUncached( 1650 DisplayCutout cutout, int rotation) { 1651 if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) { 1652 return WmDisplayCutout.NO_CUTOUT; 1653 } 1654 if (rotation == ROTATION_0) { 1655 return WmDisplayCutout.computeSafeInsets( 1656 cutout, mInitialDisplayWidth, mInitialDisplayHeight); 1657 } 1658 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); 1659 final Rect[] newBounds = mRotationUtil.getRotatedBounds( 1660 WmDisplayCutout.computeSafeInsets( 1661 cutout, mInitialDisplayWidth, mInitialDisplayHeight) 1662 .getDisplayCutout().getBoundingRectsAll(), 1663 rotation, mInitialDisplayWidth, mInitialDisplayHeight); 1664 return WmDisplayCutout.computeSafeInsets(DisplayCutout.fromBounds(newBounds), 1665 rotated ? mInitialDisplayHeight : mInitialDisplayWidth, 1666 rotated ? mInitialDisplayWidth : mInitialDisplayHeight); 1667 } 1668 1669 /** 1670 * Compute display configuration based on display properties and policy settings. 1671 * Do not call if mDisplayReady == false. 1672 */ computeScreenConfiguration(Configuration config)1673 void computeScreenConfiguration(Configuration config) { 1674 final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config); 1675 calculateBounds(displayInfo, mTmpBounds); 1676 config.windowConfiguration.setBounds(mTmpBounds); 1677 1678 final int dw = displayInfo.logicalWidth; 1679 final int dh = displayInfo.logicalHeight; 1680 config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; 1681 config.windowConfiguration.setWindowingMode(getWindowingMode()); 1682 config.windowConfiguration.setDisplayWindowingMode(getWindowingMode()); 1683 config.windowConfiguration.setRotation(displayInfo.rotation); 1684 1685 final float density = mDisplayMetrics.density; 1686 config.screenWidthDp = 1687 (int)(mDisplayPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation, 1688 config.uiMode, displayInfo.displayCutout) / density); 1689 config.screenHeightDp = 1690 (int)(mDisplayPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation, 1691 config.uiMode, displayInfo.displayCutout) / density); 1692 1693 mDisplayPolicy.getNonDecorInsetsLw(displayInfo.rotation, dw, dh, 1694 displayInfo.displayCutout, mTmpRect); 1695 final int leftInset = mTmpRect.left; 1696 final int topInset = mTmpRect.top; 1697 // appBounds at the root level should mirror the app screen size. 1698 config.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */, 1699 leftInset + displayInfo.appWidth /* right */, 1700 topInset + displayInfo.appHeight /* bottom */); 1701 final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90 1702 || displayInfo.rotation == Surface.ROTATION_270); 1703 1704 config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK) 1705 | ((displayInfo.flags & Display.FLAG_ROUND) != 0 1706 ? Configuration.SCREENLAYOUT_ROUND_YES 1707 : Configuration.SCREENLAYOUT_ROUND_NO); 1708 1709 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 1710 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 1711 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, dw, 1712 dh, displayInfo.displayCutout); 1713 config.densityDpi = displayInfo.logicalDensityDpi; 1714 1715 config.colorMode = 1716 ((displayInfo.isHdr() && mWmService.hasHdrSupport()) 1717 ? Configuration.COLOR_MODE_HDR_YES 1718 : Configuration.COLOR_MODE_HDR_NO) 1719 | (displayInfo.isWideColorGamut() && mWmService.hasWideColorGamutSupport() 1720 ? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES 1721 : Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO); 1722 1723 // Update the configuration based on available input devices, lid switch, 1724 // and platform configuration. 1725 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 1726 config.keyboard = Configuration.KEYBOARD_NOKEYS; 1727 config.navigation = Configuration.NAVIGATION_NONAV; 1728 1729 int keyboardPresence = 0; 1730 int navigationPresence = 0; 1731 final InputDevice[] devices = mWmService.mInputManager.getInputDevices(); 1732 final int len = devices != null ? devices.length : 0; 1733 for (int i = 0; i < len; i++) { 1734 InputDevice device = devices[i]; 1735 // Ignore virtual input device. 1736 if (device.isVirtual()) { 1737 continue; 1738 } 1739 1740 // Check if input device can dispatch events to current display. 1741 // If display type is virtual, will follow the default display. 1742 if (!mWmService.mInputManager.canDispatchToDisplay(device.getId(), 1743 displayInfo.type == Display.TYPE_VIRTUAL ? DEFAULT_DISPLAY : mDisplayId)) { 1744 continue; 1745 } 1746 1747 final int sources = device.getSources(); 1748 final int presenceFlag = device.isExternal() 1749 ? WindowManagerPolicy.PRESENCE_EXTERNAL : WindowManagerPolicy.PRESENCE_INTERNAL; 1750 1751 if (mWmService.mIsTouchDevice) { 1752 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) { 1753 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 1754 } 1755 } else { 1756 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 1757 } 1758 1759 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 1760 config.navigation = Configuration.NAVIGATION_TRACKBALL; 1761 navigationPresence |= presenceFlag; 1762 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 1763 && config.navigation == Configuration.NAVIGATION_NONAV) { 1764 config.navigation = Configuration.NAVIGATION_DPAD; 1765 navigationPresence |= presenceFlag; 1766 } 1767 1768 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 1769 config.keyboard = Configuration.KEYBOARD_QWERTY; 1770 keyboardPresence |= presenceFlag; 1771 } 1772 } 1773 1774 if (config.navigation == Configuration.NAVIGATION_NONAV && mWmService.mHasPermanentDpad) { 1775 config.navigation = Configuration.NAVIGATION_DPAD; 1776 navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL; 1777 } 1778 1779 // Determine whether a hard keyboard is available and enabled. 1780 // TODO(multi-display): Should the hardware keyboard be tied to a display or to a device? 1781 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 1782 if (hardKeyboardAvailable != mWmService.mHardKeyboardAvailable) { 1783 mWmService.mHardKeyboardAvailable = hardKeyboardAvailable; 1784 mWmService.mH.removeMessages(REPORT_HARD_KEYBOARD_STATUS_CHANGE); 1785 mWmService.mH.sendEmptyMessage(REPORT_HARD_KEYBOARD_STATUS_CHANGE); 1786 } 1787 1788 mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors(); 1789 1790 // Let the policy update hidden states. 1791 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 1792 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 1793 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 1794 mWmService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 1795 } 1796 computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh, DisplayCutout displayCutout)1797 private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh, 1798 DisplayCutout displayCutout) { 1799 mTmpDisplayMetrics.setTo(mDisplayMetrics); 1800 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 1801 final int unrotDw, unrotDh; 1802 if (rotated) { 1803 unrotDw = dh; 1804 unrotDh = dw; 1805 } else { 1806 unrotDw = dw; 1807 unrotDh = dh; 1808 } 1809 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh, 1810 displayCutout); 1811 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw, 1812 displayCutout); 1813 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh, 1814 displayCutout); 1815 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw, 1816 displayCutout); 1817 return sw; 1818 } 1819 reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, DisplayMetrics dm, int dw, int dh, DisplayCutout displayCutout)1820 private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, 1821 DisplayMetrics dm, int dw, int dh, DisplayCutout displayCutout) { 1822 dm.noncompatWidthPixels = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, 1823 displayCutout); 1824 dm.noncompatHeightPixels = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, 1825 displayCutout); 1826 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 1827 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 1828 if (curSize == 0 || size < curSize) { 1829 curSize = size; 1830 } 1831 return curSize; 1832 } 1833 computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig)1834 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 1835 int uiMode, int dw, int dh, float density, Configuration outConfig) { 1836 1837 // We need to determine the smallest width that will occur under normal 1838 // operation. To this, start with the base screen size and compute the 1839 // width under the different possible rotations. We need to un-rotate 1840 // the current screen dimensions before doing this. 1841 int unrotDw, unrotDh; 1842 if (rotated) { 1843 unrotDw = dh; 1844 unrotDh = dw; 1845 } else { 1846 unrotDw = dw; 1847 unrotDh = dh; 1848 } 1849 displayInfo.smallestNominalAppWidth = 1<<30; 1850 displayInfo.smallestNominalAppHeight = 1<<30; 1851 displayInfo.largestNominalAppWidth = 0; 1852 displayInfo.largestNominalAppHeight = 0; 1853 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh); 1854 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw); 1855 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh); 1856 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw); 1857 1858 if (outConfig == null) { 1859 return; 1860 } 1861 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 1862 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode, 1863 displayInfo.displayCutout); 1864 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode, 1865 displayInfo.displayCutout); 1866 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode, 1867 displayInfo.displayCutout); 1868 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode, 1869 displayInfo.displayCutout); 1870 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 1871 outConfig.screenLayout = sl; 1872 } 1873 reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, int uiMode, DisplayCutout displayCutout)1874 private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, 1875 int uiMode, DisplayCutout displayCutout) { 1876 // Get the app screen size at this rotation. 1877 int w = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayCutout); 1878 int h = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayCutout); 1879 1880 // Compute the screen layout size class for this rotation. 1881 int longSize = w; 1882 int shortSize = h; 1883 if (longSize < shortSize) { 1884 int tmp = longSize; 1885 longSize = shortSize; 1886 shortSize = tmp; 1887 } 1888 longSize = (int)(longSize/density); 1889 shortSize = (int)(shortSize/density); 1890 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 1891 } 1892 adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode, int dw, int dh)1893 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, 1894 int uiMode, int dw, int dh) { 1895 final DisplayCutout displayCutout = calculateDisplayCutoutForRotation( 1896 rotation).getDisplayCutout(); 1897 final int width = mDisplayPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode, 1898 displayCutout); 1899 if (width < displayInfo.smallestNominalAppWidth) { 1900 displayInfo.smallestNominalAppWidth = width; 1901 } 1902 if (width > displayInfo.largestNominalAppWidth) { 1903 displayInfo.largestNominalAppWidth = width; 1904 } 1905 final int height = mDisplayPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode, 1906 displayCutout); 1907 if (height < displayInfo.smallestNominalAppHeight) { 1908 displayInfo.smallestNominalAppHeight = height; 1909 } 1910 if (height > displayInfo.largestNominalAppHeight) { 1911 displayInfo.largestNominalAppHeight = height; 1912 } 1913 } 1914 1915 /** 1916 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 1917 * theme attribute) on devices that feature a physical options menu key attempt to position 1918 * their menu panel window along the edge of the screen nearest the physical menu key. 1919 * This lowers the travel distance between invoking the menu panel and selecting 1920 * a menu option. 1921 * 1922 * This method helps control where that menu is placed. Its current implementation makes 1923 * assumptions about the menu key and its relationship to the screen based on whether 1924 * the device's natural orientation is portrait (width < height) or landscape. 1925 * 1926 * The menu key is assumed to be located along the bottom edge of natural-portrait 1927 * devices and along the right edge of natural-landscape devices. If these assumptions 1928 * do not hold for the target device, this method should be changed to reflect that. 1929 * 1930 * @return A {@link Gravity} value for placing the options menu window. 1931 */ getPreferredOptionsPanelGravity()1932 int getPreferredOptionsPanelGravity() { 1933 final int rotation = getRotation(); 1934 if (mInitialDisplayWidth < mInitialDisplayHeight) { 1935 // On devices with a natural orientation of portrait. 1936 switch (rotation) { 1937 default: 1938 case Surface.ROTATION_0: 1939 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 1940 case Surface.ROTATION_90: 1941 return Gravity.RIGHT | Gravity.BOTTOM; 1942 case Surface.ROTATION_180: 1943 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 1944 case Surface.ROTATION_270: 1945 return Gravity.START | Gravity.BOTTOM; 1946 } 1947 } 1948 1949 // On devices with a natural orientation of landscape. 1950 switch (rotation) { 1951 default: 1952 case Surface.ROTATION_0: 1953 return Gravity.RIGHT | Gravity.BOTTOM; 1954 case Surface.ROTATION_90: 1955 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 1956 case Surface.ROTATION_180: 1957 return Gravity.START | Gravity.BOTTOM; 1958 case Surface.ROTATION_270: 1959 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 1960 } 1961 } 1962 getDockedDividerController()1963 DockedStackDividerController getDockedDividerController() { 1964 return mDividerControllerLocked; 1965 } 1966 getPinnedStackController()1967 PinnedStackController getPinnedStackController() { 1968 return mPinnedStackControllerLocked; 1969 } 1970 1971 /** 1972 * Returns true if the specified UID has access to this display. 1973 */ hasAccess(int uid)1974 boolean hasAccess(int uid) { 1975 return mDisplay.hasAccess(uid); 1976 } 1977 isPrivate()1978 boolean isPrivate() { 1979 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; 1980 } 1981 getHomeStack()1982 TaskStack getHomeStack() { 1983 return mTaskStackContainers.getHomeStack(); 1984 } 1985 1986 /** 1987 * @return The primary split-screen stack, but only if it is visible, and {@code null} otherwise. 1988 */ getSplitScreenPrimaryStack()1989 TaskStack getSplitScreenPrimaryStack() { 1990 TaskStack stack = mTaskStackContainers.getSplitScreenPrimaryStack(); 1991 return (stack != null && stack.isVisible()) ? stack : null; 1992 } 1993 hasSplitScreenPrimaryStack()1994 boolean hasSplitScreenPrimaryStack() { 1995 return getSplitScreenPrimaryStack() != null; 1996 } 1997 1998 /** 1999 * Like {@link #getSplitScreenPrimaryStack}, but also returns the stack if it's currently 2000 * not visible. 2001 */ getSplitScreenPrimaryStackIgnoringVisibility()2002 TaskStack getSplitScreenPrimaryStackIgnoringVisibility() { 2003 return mTaskStackContainers.getSplitScreenPrimaryStack(); 2004 } 2005 getPinnedStack()2006 TaskStack getPinnedStack() { 2007 return mTaskStackContainers.getPinnedStack(); 2008 } 2009 hasPinnedStack()2010 private boolean hasPinnedStack() { 2011 return mTaskStackContainers.getPinnedStack() != null; 2012 } 2013 2014 /** 2015 * Returns the topmost stack on the display that is compatible with the input windowing mode. 2016 * Null is no compatible stack on the display. 2017 */ getTopStackInWindowingMode(int windowingMode)2018 TaskStack getTopStackInWindowingMode(int windowingMode) { 2019 return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED); 2020 } 2021 2022 /** 2023 * Returns the topmost stack on the display that is compatible with the input windowing mode and 2024 * activity type. Null is no compatible stack on the display. 2025 */ getStack(int windowingMode, int activityType)2026 TaskStack getStack(int windowingMode, int activityType) { 2027 return mTaskStackContainers.getStack(windowingMode, activityType); 2028 } 2029 2030 @VisibleForTesting getStacks()2031 WindowList<TaskStack> getStacks() { 2032 return mTaskStackContainers.mChildren; 2033 } 2034 2035 @VisibleForTesting getTopStack()2036 TaskStack getTopStack() { 2037 return mTaskStackContainers.getTopStack(); 2038 } 2039 getVisibleTasks()2040 ArrayList<Task> getVisibleTasks() { 2041 return mTaskStackContainers.getVisibleTasks(); 2042 } 2043 onStackWindowingModeChanged(TaskStack stack)2044 void onStackWindowingModeChanged(TaskStack stack) { 2045 mTaskStackContainers.onStackWindowingModeChanged(stack); 2046 } 2047 2048 @Override onConfigurationChanged(Configuration newParentConfig)2049 public void onConfigurationChanged(Configuration newParentConfig) { 2050 final int lastOrientation = getConfiguration().orientation; 2051 super.onConfigurationChanged(newParentConfig); 2052 if (mDisplayPolicy != null) { 2053 mDisplayPolicy.onConfigurationChanged(); 2054 } 2055 2056 if (lastOrientation != getConfiguration().orientation) { 2057 getMetricsLogger().write( 2058 new LogMaker(MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED) 2059 .setSubtype(getConfiguration().orientation) 2060 .addTaggedData(MetricsEvent.FIELD_DISPLAY_ID, getDisplayId())); 2061 } 2062 2063 // If there was no pinned stack, we still need to notify the controller of the display info 2064 // update as a result of the config change. 2065 if (mPinnedStackControllerLocked != null && !hasPinnedStack()) { 2066 mPinnedStackControllerLocked.onDisplayInfoChanged(getDisplayInfo()); 2067 } 2068 } 2069 2070 /** 2071 * Updates the resources used by docked/pinned controllers. This needs to be called at the 2072 * beginning of a configuration update cascade since the metrics from these resources are used 2073 * for bounds calculations. Since ActivityDisplay initiates the configuration update, this 2074 * should be called from there instead of DisplayContent's onConfigurationChanged. 2075 */ preOnConfigurationChanged()2076 void preOnConfigurationChanged() { 2077 final DockedStackDividerController dividerController = getDockedDividerController(); 2078 2079 if (dividerController != null) { 2080 getDockedDividerController().onConfigurationChanged(); 2081 } 2082 2083 final PinnedStackController pinnedStackController = getPinnedStackController(); 2084 2085 if (pinnedStackController != null) { 2086 getPinnedStackController().onConfigurationChanged(); 2087 } 2088 } 2089 2090 @Override fillsParent()2091 boolean fillsParent() { 2092 return true; 2093 } 2094 2095 @Override isVisible()2096 boolean isVisible() { 2097 return true; 2098 } 2099 2100 @Override onAppTransitionDone()2101 void onAppTransitionDone() { 2102 super.onAppTransitionDone(); 2103 mWmService.mWindowsChanged = true; 2104 } 2105 2106 @Override setWindowingMode(int windowingMode)2107 public void setWindowingMode(int windowingMode) { 2108 super.setWindowingMode(windowingMode); 2109 super.setDisplayWindowingMode(windowingMode); 2110 } 2111 2112 @Override setDisplayWindowingMode(int windowingMode)2113 void setDisplayWindowingMode(int windowingMode) { 2114 setWindowingMode(windowingMode); 2115 } 2116 2117 /** 2118 * In split-screen mode we process the IME containers above the docked divider 2119 * rather than directly above their target. 2120 */ skipTraverseChild(WindowContainer child)2121 private boolean skipTraverseChild(WindowContainer child) { 2122 if (child == mImeWindowsContainers && mInputMethodTarget != null 2123 && !hasSplitScreenPrimaryStack()) { 2124 return true; 2125 } 2126 return false; 2127 } 2128 2129 @Override forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)2130 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 2131 // Special handling so we can process IME windows with #forAllImeWindows above their IME 2132 // target, or here in order if there isn't an IME target. 2133 if (traverseTopToBottom) { 2134 for (int i = mChildren.size() - 1; i >= 0; --i) { 2135 final DisplayChildWindowContainer child = mChildren.get(i); 2136 if (skipTraverseChild(child)) { 2137 continue; 2138 } 2139 2140 if (child.forAllWindows(callback, traverseTopToBottom)) { 2141 return true; 2142 } 2143 } 2144 } else { 2145 final int count = mChildren.size(); 2146 for (int i = 0; i < count; i++) { 2147 final DisplayChildWindowContainer child = mChildren.get(i); 2148 if (skipTraverseChild(child)) { 2149 continue; 2150 } 2151 2152 if (child.forAllWindows(callback, traverseTopToBottom)) { 2153 return true; 2154 } 2155 } 2156 } 2157 return false; 2158 } 2159 forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)2160 boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 2161 return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom); 2162 } 2163 2164 @Override getOrientation()2165 int getOrientation() { 2166 final WindowManagerPolicy policy = mWmService.mPolicy; 2167 2168 if (mIgnoreRotationForApps) { 2169 return SCREEN_ORIENTATION_USER; 2170 } 2171 2172 if (mWmService.mDisplayFrozen) { 2173 if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) { 2174 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId 2175 + " is frozen, return " + mLastWindowForcedOrientation); 2176 // If the display is frozen, some activities may be in the middle of restarting, and 2177 // thus have removed their old window. If the window has the flag to hide the lock 2178 // screen, then the lock screen can re-appear and inflict its own orientation on us. 2179 // Keep the orientation stable until this all settles down. 2180 return mLastWindowForcedOrientation; 2181 } else if (policy.isKeyguardLocked()) { 2182 // Use the last orientation the while the display is frozen with the keyguard 2183 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED 2184 // window. We don't want to check the show when locked window directly though as 2185 // things aren't stable while the display is frozen, for example the window could be 2186 // momentarily unavailable due to activity relaunch. 2187 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId 2188 + " is frozen while keyguard locked, return " + mLastOrientation); 2189 return mLastOrientation; 2190 } 2191 } else { 2192 final int orientation = mAboveAppWindowsContainers.getOrientation(); 2193 if (orientation != SCREEN_ORIENTATION_UNSET) { 2194 return orientation; 2195 } 2196 } 2197 2198 // Top system windows are not requesting an orientation. Start searching from apps. 2199 return mTaskStackContainers.getOrientation(); 2200 } 2201 updateDisplayInfo()2202 void updateDisplayInfo() { 2203 // Check if display metrics changed and update base values if needed. 2204 updateBaseDisplayMetricsIfNeeded(); 2205 2206 mDisplay.getDisplayInfo(mDisplayInfo); 2207 mDisplay.getMetrics(mDisplayMetrics); 2208 2209 onDisplayChanged(this); 2210 } 2211 2212 @Override onDisplayChanged(DisplayContent dc)2213 void onDisplayChanged(DisplayContent dc) { 2214 super.onDisplayChanged(dc); 2215 updateSystemGestureExclusionLimit(); 2216 } 2217 updateSystemGestureExclusionLimit()2218 void updateSystemGestureExclusionLimit() { 2219 mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp 2220 * mDisplayMetrics.densityDpi / DENSITY_DEFAULT; 2221 updateSystemGestureExclusion(); 2222 } 2223 initializeDisplayBaseInfo()2224 void initializeDisplayBaseInfo() { 2225 final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal; 2226 if (displayManagerInternal != null) { 2227 // Bootstrap the default logical display from the display manager. 2228 final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId); 2229 if (newDisplayInfo != null) { 2230 mDisplayInfo.copyFrom(newDisplayInfo); 2231 } 2232 } 2233 2234 updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, 2235 mDisplayInfo.logicalDensityDpi); 2236 mInitialDisplayWidth = mDisplayInfo.logicalWidth; 2237 mInitialDisplayHeight = mDisplayInfo.logicalHeight; 2238 mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; 2239 mInitialDisplayCutout = mDisplayInfo.displayCutout; 2240 } 2241 2242 /** 2243 * If display metrics changed, overrides are not set and it's not just a rotation - update base 2244 * values. 2245 */ updateBaseDisplayMetricsIfNeeded()2246 private void updateBaseDisplayMetricsIfNeeded() { 2247 // Get real display metrics without overrides from WM. 2248 mWmService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo); 2249 final int orientation = mDisplayInfo.rotation; 2250 final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); 2251 final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth; 2252 final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight; 2253 final int newDensity = mDisplayInfo.logicalDensityDpi; 2254 final DisplayCutout newCutout = mDisplayInfo.displayCutout; 2255 2256 final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth 2257 || mInitialDisplayHeight != newHeight 2258 || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi 2259 || !Objects.equals(mInitialDisplayCutout, newCutout); 2260 2261 if (displayMetricsChanged) { 2262 // Check if display size or density is forced. 2263 final boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth 2264 || mBaseDisplayHeight != mInitialDisplayHeight; 2265 final boolean isDisplayDensityForced = mBaseDisplayDensity != mInitialDisplayDensity; 2266 2267 // If there is an override set for base values - use it, otherwise use new values. 2268 updateBaseDisplayMetrics(isDisplaySizeForced ? mBaseDisplayWidth : newWidth, 2269 isDisplaySizeForced ? mBaseDisplayHeight : newHeight, 2270 isDisplayDensityForced ? mBaseDisplayDensity : newDensity); 2271 2272 // Real display metrics changed, so we should also update initial values. 2273 mInitialDisplayWidth = newWidth; 2274 mInitialDisplayHeight = newHeight; 2275 mInitialDisplayDensity = newDensity; 2276 mInitialDisplayCutout = newCutout; 2277 mWmService.reconfigureDisplayLocked(this); 2278 } 2279 } 2280 2281 /** Sets the maximum width the screen resolution can be */ setMaxUiWidth(int width)2282 void setMaxUiWidth(int width) { 2283 if (DEBUG_DISPLAY) { 2284 Slog.v(TAG_WM, "Setting max ui width:" + width + " on display:" + getDisplayId()); 2285 } 2286 2287 mMaxUiWidth = width; 2288 2289 // Update existing metrics. 2290 updateBaseDisplayMetrics(mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity); 2291 } 2292 2293 /** Update base (override) display metrics. */ updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity)2294 void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) { 2295 mBaseDisplayWidth = baseWidth; 2296 mBaseDisplayHeight = baseHeight; 2297 mBaseDisplayDensity = baseDensity; 2298 2299 if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) { 2300 mBaseDisplayHeight = (mMaxUiWidth * mBaseDisplayHeight) / mBaseDisplayWidth; 2301 mBaseDisplayDensity = (mMaxUiWidth * mBaseDisplayDensity) / mBaseDisplayWidth; 2302 mBaseDisplayWidth = mMaxUiWidth; 2303 2304 if (DEBUG_DISPLAY) { 2305 Slog.v(TAG_WM, "Applying config restraints:" + mBaseDisplayWidth + "x" 2306 + mBaseDisplayHeight + " at density:" + mBaseDisplayDensity 2307 + " on display:" + getDisplayId()); 2308 } 2309 } 2310 2311 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); 2312 2313 updateBounds(); 2314 } 2315 2316 /** 2317 * Forces this display to use the specified density. 2318 * 2319 * @param density The density in DPI to use. If the value equals to initial density, the setting 2320 * will be cleared. 2321 * @param userId The target user to apply. Only meaningful when this is default display. If the 2322 * user id is {@link UserHandle#USER_CURRENT}, it means to apply current settings 2323 * so only need to configure display. 2324 */ setForcedDensity(int density, int userId)2325 void setForcedDensity(int density, int userId) { 2326 final boolean clear = density == mInitialDisplayDensity; 2327 final boolean updateCurrent = userId == UserHandle.USER_CURRENT; 2328 if (mWmService.mCurrentUserId == userId || updateCurrent) { 2329 mBaseDisplayDensity = density; 2330 mWmService.reconfigureDisplayLocked(this); 2331 } 2332 if (updateCurrent) { 2333 // We are applying existing settings so no need to save it again. 2334 return; 2335 } 2336 2337 if (density == mInitialDisplayDensity) { 2338 density = 0; 2339 } 2340 mWmService.mDisplayWindowSettings.setForcedDensity(this, density, userId); 2341 } 2342 2343 /** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */ setForcedScalingMode(@orceScalingMode int mode)2344 void setForcedScalingMode(@ForceScalingMode int mode) { 2345 if (mode != FORCE_SCALING_MODE_DISABLED) { 2346 mode = FORCE_SCALING_MODE_AUTO; 2347 } 2348 2349 mDisplayScalingDisabled = (mode != FORCE_SCALING_MODE_AUTO); 2350 Slog.i(TAG_WM, "Using display scaling mode: " + (mDisplayScalingDisabled ? "off" : "auto")); 2351 mWmService.reconfigureDisplayLocked(this); 2352 2353 mWmService.mDisplayWindowSettings.setForcedScalingMode(this, mode); 2354 } 2355 2356 /** If the given width and height equal to initial size, the setting will be cleared. */ setForcedSize(int width, int height)2357 void setForcedSize(int width, int height) { 2358 final boolean clear = mInitialDisplayWidth == width && mInitialDisplayHeight == height; 2359 if (!clear) { 2360 // Set some sort of reasonable bounds on the size of the display that we will try 2361 // to emulate. 2362 final int minSize = 200; 2363 final int maxScale = 2; 2364 width = Math.min(Math.max(width, minSize), mInitialDisplayWidth * maxScale); 2365 height = Math.min(Math.max(height, minSize), mInitialDisplayHeight * maxScale); 2366 } 2367 2368 Slog.i(TAG_WM, "Using new display size: " + width + "x" + height); 2369 updateBaseDisplayMetrics(width, height, mBaseDisplayDensity); 2370 mWmService.reconfigureDisplayLocked(this); 2371 2372 if (clear) { 2373 width = height = 0; 2374 } 2375 mWmService.mDisplayWindowSettings.setForcedSize(this, width, height); 2376 } 2377 getStableRect(Rect out)2378 void getStableRect(Rect out) { 2379 out.set(mDisplayFrames.mStable); 2380 } 2381 setStackOnDisplay(int stackId, boolean onTop, TaskStack stack)2382 void setStackOnDisplay(int stackId, boolean onTop, TaskStack stack) { 2383 if (DEBUG_STACK) { 2384 Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" + mDisplayId); 2385 } 2386 2387 mTaskStackContainers.addStackToDisplay(stack, onTop); 2388 } 2389 moveStackToDisplay(TaskStack stack, boolean onTop)2390 void moveStackToDisplay(TaskStack stack, boolean onTop) { 2391 final DisplayContent prevDc = stack.getDisplayContent(); 2392 if (prevDc == null) { 2393 throw new IllegalStateException("Trying to move stackId=" + stack.mStackId 2394 + " which is not currently attached to any display"); 2395 } 2396 if (prevDc.getDisplayId() == mDisplayId) { 2397 throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId 2398 + " to its current displayId=" + mDisplayId); 2399 } 2400 2401 prevDc.mTaskStackContainers.removeChild(stack); 2402 mTaskStackContainers.addStackToDisplay(stack, onTop); 2403 } 2404 2405 @Override addChild(DisplayChildWindowContainer child, Comparator<DisplayChildWindowContainer> comparator)2406 protected void addChild(DisplayChildWindowContainer child, 2407 Comparator<DisplayChildWindowContainer> comparator) { 2408 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 2409 } 2410 2411 @Override addChild(DisplayChildWindowContainer child, int index)2412 protected void addChild(DisplayChildWindowContainer child, int index) { 2413 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 2414 } 2415 2416 @Override removeChild(DisplayChildWindowContainer child)2417 protected void removeChild(DisplayChildWindowContainer child) { 2418 // Only allow removal of direct children from this display if the display is in the process 2419 // of been removed. 2420 if (mRemovingDisplay) { 2421 super.removeChild(child); 2422 return; 2423 } 2424 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 2425 } 2426 2427 @Override positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents)2428 void positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents) { 2429 // Children of the display are statically ordered, so the real intention here is to perform 2430 // the operation on the display and not the static direct children. 2431 getParent().positionChildAt(position, this, includingParents); 2432 } 2433 positionStackAt(int position, TaskStack child, boolean includingParents)2434 void positionStackAt(int position, TaskStack child, boolean includingParents) { 2435 mTaskStackContainers.positionChildAt(position, child, includingParents); 2436 layoutAndAssignWindowLayersIfNeeded(); 2437 } 2438 2439 /** 2440 * Returns true if the input point is within an app window. 2441 */ pointWithinAppWindow(int x, int y)2442 boolean pointWithinAppWindow(int x, int y) { 2443 final int[] targetWindowType = {-1}; 2444 final Consumer fn = PooledLambda.obtainConsumer((w, nonArg) -> { 2445 if (targetWindowType[0] != -1) { 2446 return; 2447 } 2448 2449 if (w.isOnScreen() && w.isVisibleLw() && w.getFrameLw().contains(x, y)) { 2450 targetWindowType[0] = w.mAttrs.type; 2451 return; 2452 } 2453 }, PooledLambda.__(WindowState.class), mTmpRect); 2454 forAllWindows(fn, true /* traverseTopToBottom */); 2455 ((PooledConsumer) fn).recycle(); 2456 return FIRST_APPLICATION_WINDOW <= targetWindowType[0] 2457 && targetWindowType[0] <= LAST_APPLICATION_WINDOW; 2458 } 2459 2460 /** 2461 * Find the task whose outside touch area (for resizing) (x, y) falls within. 2462 * Returns null if the touch doesn't fall into a resizing area. 2463 */ findTaskForResizePoint(int x, int y)2464 Task findTaskForResizePoint(int x, int y) { 2465 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 2466 mTmpTaskForResizePointSearchResult.reset(); 2467 for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) { 2468 final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx); 2469 if (!stack.getWindowConfiguration().canResizeTask()) { 2470 return null; 2471 } 2472 2473 stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult); 2474 if (mTmpTaskForResizePointSearchResult.searchDone) { 2475 return mTmpTaskForResizePointSearchResult.taskForResize; 2476 } 2477 } 2478 return null; 2479 } 2480 updateTouchExcludeRegion()2481 void updateTouchExcludeRegion() { 2482 final Task focusedTask = (mFocusedApp != null ? mFocusedApp.getTask() : null); 2483 if (focusedTask == null) { 2484 mTouchExcludeRegion.setEmpty(); 2485 } else { 2486 mTouchExcludeRegion.set(mBaseDisplayRect); 2487 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 2488 mTmpRect2.setEmpty(); 2489 for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; 2490 --stackNdx) { 2491 final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx); 2492 stack.setTouchExcludeRegion(focusedTask, delta, mTouchExcludeRegion, 2493 mDisplayFrames.mContent, mTmpRect2); 2494 } 2495 // If we removed the focused task above, add it back and only leave its 2496 // outside touch area in the exclusion. TapDetector is not interested in 2497 // any touch inside the focused task itself. 2498 if (!mTmpRect2.isEmpty()) { 2499 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION); 2500 } 2501 } 2502 if (mInputMethodWindow != null && mInputMethodWindow.isVisibleLw()) { 2503 // If the input method is visible and the user is typing, we don't want these touch 2504 // events to be intercepted and used to change focus. This would likely cause a 2505 // disappearance of the input method. 2506 mInputMethodWindow.getTouchableRegion(mTmpRegion); 2507 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 2508 } 2509 for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) { 2510 final WindowState win = mTapExcludedWindows.get(i); 2511 win.getTouchableRegion(mTmpRegion); 2512 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 2513 } 2514 amendWindowTapExcludeRegion(mTouchExcludeRegion); 2515 // TODO(multi-display): Support docked stacks on secondary displays. 2516 if (mDisplayId == DEFAULT_DISPLAY && getSplitScreenPrimaryStack() != null) { 2517 mDividerControllerLocked.getTouchRegion(mTmpRect); 2518 mTmpRegion.set(mTmpRect); 2519 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 2520 } 2521 mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion); 2522 } 2523 2524 /** 2525 * Union the region with all the tap exclude region provided by windows on this display. 2526 * 2527 * @param inOutRegion The region to be amended. 2528 */ amendWindowTapExcludeRegion(Region inOutRegion)2529 void amendWindowTapExcludeRegion(Region inOutRegion) { 2530 for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) { 2531 final WindowState win = mTapExcludeProvidingWindows.valueAt(i); 2532 win.amendTapExcludeRegion(inOutRegion); 2533 } 2534 } 2535 2536 @Override switchUser()2537 void switchUser() { 2538 super.switchUser(); 2539 mWmService.mWindowsChanged = true; 2540 mDisplayPolicy.switchUser(); 2541 } 2542 resetAnimationBackgroundAnimator()2543 private void resetAnimationBackgroundAnimator() { 2544 for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) { 2545 mTaskStackContainers.getChildAt(stackNdx).resetAnimationBackgroundAnimator(); 2546 } 2547 } 2548 2549 @Override removeIfPossible()2550 void removeIfPossible() { 2551 if (isAnimating()) { 2552 mDeferredRemoval = true; 2553 return; 2554 } 2555 removeImmediately(); 2556 } 2557 2558 @Override removeImmediately()2559 void removeImmediately() { 2560 mRemovingDisplay = true; 2561 try { 2562 // Clear all transitions & screen frozen states when removing display. 2563 mOpeningApps.clear(); 2564 mClosingApps.clear(); 2565 mChangingApps.clear(); 2566 mUnknownAppVisibilityController.clear(); 2567 mAppTransition.removeAppTransitionTimeoutCallbacks(); 2568 handleAnimatingStoppedAndTransition(); 2569 mWmService.stopFreezingDisplayLocked(); 2570 super.removeImmediately(); 2571 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this); 2572 mPointerEventDispatcher.dispose(); 2573 mWmService.mAnimator.removeDisplayLocked(mDisplayId); 2574 mWindowingLayer.release(); 2575 mOverlayLayer.release(); 2576 mInputMonitor.onDisplayRemoved(); 2577 } finally { 2578 mDisplayReady = false; 2579 mRemovingDisplay = false; 2580 } 2581 2582 mWmService.mWindowPlacerLocked.requestTraversal(); 2583 } 2584 2585 /** Returns true if a removal action is still being deferred. */ 2586 @Override checkCompleteDeferredRemoval()2587 boolean checkCompleteDeferredRemoval() { 2588 final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval(); 2589 2590 if (!stillDeferringRemoval && mDeferredRemoval) { 2591 removeImmediately(); 2592 return false; 2593 } 2594 return true; 2595 } 2596 2597 /** @return 'true' if removal of this display content is deferred due to active animation. */ isRemovalDeferred()2598 boolean isRemovalDeferred() { 2599 return mDeferredRemoval; 2600 } 2601 animateForIme(float interpolatedValue, float animationTarget, float dividerAnimationTarget)2602 boolean animateForIme(float interpolatedValue, float animationTarget, 2603 float dividerAnimationTarget) { 2604 boolean updated = false; 2605 2606 for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) { 2607 final TaskStack stack = mTaskStackContainers.getChildAt(i); 2608 if (stack == null || !stack.isAdjustedForIme()) { 2609 continue; 2610 } 2611 2612 if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) { 2613 stack.resetAdjustedForIme(true /* adjustBoundsNow */); 2614 updated = true; 2615 } else { 2616 mDividerControllerLocked.mLastAnimationProgress = 2617 mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue); 2618 mDividerControllerLocked.mLastDividerProgress = 2619 mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue); 2620 updated |= stack.updateAdjustForIme( 2621 mDividerControllerLocked.mLastAnimationProgress, 2622 mDividerControllerLocked.mLastDividerProgress, 2623 false /* force */); 2624 } 2625 if (interpolatedValue >= 1f) { 2626 stack.endImeAdjustAnimation(); 2627 } 2628 } 2629 2630 return updated; 2631 } 2632 clearImeAdjustAnimation()2633 boolean clearImeAdjustAnimation() { 2634 boolean changed = false; 2635 for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) { 2636 final TaskStack stack = mTaskStackContainers.getChildAt(i); 2637 if (stack != null && stack.isAdjustedForIme()) { 2638 stack.resetAdjustedForIme(true /* adjustBoundsNow */); 2639 changed = true; 2640 } 2641 } 2642 return changed; 2643 } 2644 beginImeAdjustAnimation()2645 void beginImeAdjustAnimation() { 2646 for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) { 2647 final TaskStack stack = mTaskStackContainers.getChildAt(i); 2648 if (stack.isVisible() && stack.isAdjustedForIme()) { 2649 stack.beginImeAdjustAnimation(); 2650 } 2651 } 2652 } 2653 adjustForImeIfNeeded()2654 void adjustForImeIfNeeded() { 2655 final WindowState imeWin = mInputMethodWindow; 2656 final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw() 2657 && !mDividerControllerLocked.isImeHideRequested(); 2658 final TaskStack dockedStack = getSplitScreenPrimaryStack(); 2659 final boolean dockVisible = dockedStack != null; 2660 final Task topDockedTask = dockVisible ? dockedStack.getTopChild() : null; 2661 final TaskStack imeTargetStack = mWmService.getImeFocusStackLocked(); 2662 final int imeDockSide = (dockVisible && imeTargetStack != null) ? 2663 imeTargetStack.getDockSide() : DOCKED_INVALID; 2664 final boolean imeOnTop = (imeDockSide == DOCKED_TOP); 2665 final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM); 2666 final int imeHeight = mDisplayFrames.getInputMethodWindowVisibleHeight(); 2667 final boolean imeHeightChanged = imeVisible && 2668 imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor(); 2669 2670 // This includes a case where the docked stack is unminimizing and IME is visible for the 2671 // bottom side stack. The condition prevents adjusting the override task bounds for IME to 2672 // the minimized docked stack bounds. 2673 final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock() 2674 || (topDockedTask != null && imeOnBottom && !dockedStack.isAdjustedForIme() 2675 && dockedStack.getBounds().height() < topDockedTask.getBounds().height()); 2676 2677 // The divider could be adjusted for IME position, or be thinner than usual, 2678 // or both. There are three possible cases: 2679 // - If IME is visible, and focus is on top, divider is not moved for IME but thinner. 2680 // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner. 2681 // - If IME is not visible, divider is not moved and is normal width. 2682 2683 if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) { 2684 for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) { 2685 final TaskStack stack = mTaskStackContainers.getChildAt(i); 2686 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM; 2687 if (stack.isVisible() && (imeOnBottom || isDockedOnBottom) 2688 && stack.inSplitScreenWindowingMode()) { 2689 stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged); 2690 } else { 2691 stack.resetAdjustedForIme(false); 2692 } 2693 } 2694 mDividerControllerLocked.setAdjustedForIme( 2695 imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight); 2696 } else { 2697 for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) { 2698 final TaskStack stack = mTaskStackContainers.getChildAt(i); 2699 stack.resetAdjustedForIme(!dockVisible); 2700 } 2701 mDividerControllerLocked.setAdjustedForIme( 2702 false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight); 2703 } 2704 mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight); 2705 } 2706 prepareFreezingTaskBounds()2707 void prepareFreezingTaskBounds() { 2708 for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) { 2709 final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx); 2710 stack.prepareFreezingTaskBounds(); 2711 } 2712 } 2713 rotateBounds(int oldRotation, int newRotation, Rect bounds)2714 void rotateBounds(int oldRotation, int newRotation, Rect bounds) { 2715 getBounds(mTmpRect, newRotation); 2716 rotateBounds(mTmpRect, oldRotation, newRotation, bounds); 2717 } 2718 rotateBounds(Rect parentBounds, int oldRotation, int newRotation, Rect bounds)2719 void rotateBounds(Rect parentBounds, int oldRotation, int newRotation, Rect bounds) { 2720 // Compute a transform matrix to undo the coordinate space transformation, 2721 // and present the window at the same physical position it previously occupied. 2722 final int deltaRotation = deltaRotation(newRotation, oldRotation); 2723 createRotationMatrix( 2724 deltaRotation, parentBounds.width(), parentBounds.height(), mTmpMatrix); 2725 2726 mTmpRectF.set(bounds); 2727 mTmpMatrix.mapRect(mTmpRectF); 2728 mTmpRectF.round(bounds); 2729 } 2730 deltaRotation(int oldRotation, int newRotation)2731 static int deltaRotation(int oldRotation, int newRotation) { 2732 int delta = newRotation - oldRotation; 2733 if (delta < 0) delta += 4; 2734 return delta; 2735 } 2736 createRotationMatrix(int rotation, float displayWidth, float displayHeight, Matrix outMatrix)2737 private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight, 2738 Matrix outMatrix) { 2739 // For rotations without Z-ordering we don't need the target rectangle's position. 2740 createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth, 2741 displayHeight, outMatrix); 2742 } 2743 createRotationMatrix(int rotation, float rectLeft, float rectTop, float displayWidth, float displayHeight, Matrix outMatrix)2744 static void createRotationMatrix(int rotation, float rectLeft, float rectTop, 2745 float displayWidth, float displayHeight, Matrix outMatrix) { 2746 switch (rotation) { 2747 case ROTATION_0: 2748 outMatrix.reset(); 2749 break; 2750 case ROTATION_270: 2751 outMatrix.setRotate(270, 0, 0); 2752 outMatrix.postTranslate(0, displayHeight); 2753 outMatrix.postTranslate(rectTop, 0); 2754 break; 2755 case ROTATION_180: 2756 outMatrix.reset(); 2757 break; 2758 case ROTATION_90: 2759 outMatrix.setRotate(90, 0, 0); 2760 outMatrix.postTranslate(displayWidth, 0); 2761 outMatrix.postTranslate(-rectTop, rectLeft); 2762 break; 2763 } 2764 } 2765 2766 @CallSuper 2767 @Override writeToProto(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)2768 public void writeToProto(ProtoOutputStream proto, long fieldId, 2769 @WindowTraceLogLevel int logLevel) { 2770 // Critical log level logs only visible elements to mitigate performance overheard 2771 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { 2772 return; 2773 } 2774 2775 final long token = proto.start(fieldId); 2776 super.writeToProto(proto, WINDOW_CONTAINER, logLevel); 2777 proto.write(ID, mDisplayId); 2778 for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) { 2779 final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx); 2780 stack.writeToProto(proto, STACKS, logLevel); 2781 } 2782 mDividerControllerLocked.writeToProto(proto, DOCKED_STACK_DIVIDER_CONTROLLER); 2783 mPinnedStackControllerLocked.writeToProto(proto, PINNED_STACK_CONTROLLER); 2784 for (int i = mAboveAppWindowsContainers.getChildCount() - 1; i >= 0; --i) { 2785 final WindowToken windowToken = mAboveAppWindowsContainers.getChildAt(i); 2786 windowToken.writeToProto(proto, ABOVE_APP_WINDOWS, logLevel); 2787 } 2788 for (int i = mBelowAppWindowsContainers.getChildCount() - 1; i >= 0; --i) { 2789 final WindowToken windowToken = mBelowAppWindowsContainers.getChildAt(i); 2790 windowToken.writeToProto(proto, BELOW_APP_WINDOWS, logLevel); 2791 } 2792 for (int i = mImeWindowsContainers.getChildCount() - 1; i >= 0; --i) { 2793 final WindowToken windowToken = mImeWindowsContainers.getChildAt(i); 2794 windowToken.writeToProto(proto, IME_WINDOWS, logLevel); 2795 } 2796 proto.write(DPI, mBaseDisplayDensity); 2797 mDisplayInfo.writeToProto(proto, DISPLAY_INFO); 2798 proto.write(ROTATION, mRotation); 2799 final ScreenRotationAnimation screenRotationAnimation = 2800 mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); 2801 if (screenRotationAnimation != null) { 2802 screenRotationAnimation.writeToProto(proto, SCREEN_ROTATION_ANIMATION); 2803 } 2804 mDisplayFrames.writeToProto(proto, DISPLAY_FRAMES); 2805 mAppTransition.writeToProto(proto, APP_TRANSITION); 2806 if (mFocusedApp != null) { 2807 mFocusedApp.writeNameToProto(proto, FOCUSED_APP); 2808 } 2809 for (int i = mOpeningApps.size() - 1; i >= 0; i--) { 2810 mOpeningApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, OPENING_APPS); 2811 } 2812 for (int i = mClosingApps.size() - 1; i >= 0; i--) { 2813 mClosingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CLOSING_APPS); 2814 } 2815 for (int i = mChangingApps.size() - 1; i >= 0; i--) { 2816 mChangingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CHANGING_APPS); 2817 } 2818 proto.end(token); 2819 } 2820 2821 @Override dump(PrintWriter pw, String prefix, boolean dumpAll)2822 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 2823 super.dump(pw, prefix, dumpAll); 2824 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); 2825 final String subPrefix = " " + prefix; 2826 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); 2827 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); 2828 pw.print("dpi"); 2829 if (mInitialDisplayWidth != mBaseDisplayWidth 2830 || mInitialDisplayHeight != mBaseDisplayHeight 2831 || mInitialDisplayDensity != mBaseDisplayDensity) { 2832 pw.print(" base="); 2833 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 2834 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); 2835 } 2836 if (mDisplayScalingDisabled) { 2837 pw.println(" noscale"); 2838 } 2839 pw.print(" cur="); 2840 pw.print(mDisplayInfo.logicalWidth); 2841 pw.print("x"); pw.print(mDisplayInfo.logicalHeight); 2842 pw.print(" app="); 2843 pw.print(mDisplayInfo.appWidth); 2844 pw.print("x"); pw.print(mDisplayInfo.appHeight); 2845 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); 2846 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); 2847 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); 2848 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); 2849 pw.print(subPrefix + "deferred=" + mDeferredRemoval 2850 + " mLayoutNeeded=" + mLayoutNeeded); 2851 pw.println(" mTouchExcludeRegion=" + mTouchExcludeRegion); 2852 2853 pw.println(); 2854 pw.print(prefix); pw.print("mLayoutSeq="); pw.println(mLayoutSeq); 2855 pw.print(prefix); 2856 pw.print("mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 2857 2858 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 2859 if (mLastFocus != mCurrentFocus) { 2860 pw.print(" mLastFocus="); pw.println(mLastFocus); 2861 } 2862 if (mLosingFocus.size() > 0) { 2863 pw.println(); 2864 pw.println(" Windows losing focus:"); 2865 for (int i = mLosingFocus.size() - 1; i >= 0; i--) { 2866 final WindowState w = mLosingFocus.get(i); 2867 pw.print(" Losing #"); pw.print(i); pw.print(' '); 2868 pw.print(w); 2869 if (dumpAll) { 2870 pw.println(":"); 2871 w.dump(pw, " ", true); 2872 } else { 2873 pw.println(); 2874 } 2875 } 2876 } 2877 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 2878 if (mLastStatusBarVisibility != 0) { 2879 pw.print(" mLastStatusBarVisibility=0x"); 2880 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 2881 } 2882 2883 pw.println(); 2884 mWallpaperController.dump(pw, " "); 2885 2886 pw.println(); 2887 pw.print("mSystemGestureExclusion="); 2888 if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() > 0) { 2889 pw.println(mSystemGestureExclusion); 2890 } else { 2891 pw.println("<no lstnrs>"); 2892 } 2893 2894 pw.println(); 2895 pw.println(prefix + "Application tokens in top down Z order:"); 2896 for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) { 2897 final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx); 2898 stack.dump(pw, prefix + " ", dumpAll); 2899 } 2900 2901 pw.println(); 2902 if (!mExitingTokens.isEmpty()) { 2903 pw.println(); 2904 pw.println(" Exiting tokens:"); 2905 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 2906 final WindowToken token = mExitingTokens.get(i); 2907 pw.print(" Exiting #"); pw.print(i); 2908 pw.print(' '); pw.print(token); 2909 pw.println(':'); 2910 token.dump(pw, " ", dumpAll); 2911 } 2912 } 2913 2914 pw.println(); 2915 2916 // Dump stack references 2917 final TaskStack homeStack = getHomeStack(); 2918 if (homeStack != null) { 2919 pw.println(prefix + "homeStack=" + homeStack.getName()); 2920 } 2921 final TaskStack pinnedStack = getPinnedStack(); 2922 if (pinnedStack != null) { 2923 pw.println(prefix + "pinnedStack=" + pinnedStack.getName()); 2924 } 2925 final TaskStack splitScreenPrimaryStack = getSplitScreenPrimaryStack(); 2926 if (splitScreenPrimaryStack != null) { 2927 pw.println(prefix + "splitScreenPrimaryStack=" + splitScreenPrimaryStack.getName()); 2928 } 2929 2930 pw.println(); 2931 mDividerControllerLocked.dump(prefix, pw); 2932 pw.println(); 2933 mPinnedStackControllerLocked.dump(prefix, pw); 2934 2935 pw.println(); 2936 mDisplayFrames.dump(prefix, pw); 2937 pw.println(); 2938 mDisplayPolicy.dump(prefix, pw); 2939 pw.println(); 2940 mDisplayRotation.dump(prefix, pw); 2941 pw.println(); 2942 mInputMonitor.dump(pw, " "); 2943 pw.println(); 2944 mInsetsStateController.dump(prefix, pw); 2945 } 2946 2947 @Override toString()2948 public String toString() { 2949 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren; 2950 } 2951 getName()2952 String getName() { 2953 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\""; 2954 } 2955 2956 /** Returns true if the stack in the windowing mode is visible. */ isStackVisible(int windowingMode)2957 boolean isStackVisible(int windowingMode) { 2958 final TaskStack stack = getTopStackInWindowingMode(windowingMode); 2959 return stack != null && stack.isVisible(); 2960 } 2961 2962 /** Find the visible, touch-deliverable window under the given point */ getTouchableWinAtPointLocked(float xf, float yf)2963 WindowState getTouchableWinAtPointLocked(float xf, float yf) { 2964 final int x = (int) xf; 2965 final int y = (int) yf; 2966 final WindowState touchedWin = getWindow(w -> { 2967 final int flags = w.mAttrs.flags; 2968 if (!w.isVisibleLw()) { 2969 return false; 2970 } 2971 if ((flags & FLAG_NOT_TOUCHABLE) != 0) { 2972 return false; 2973 } 2974 2975 w.getVisibleBounds(mTmpRect); 2976 if (!mTmpRect.contains(x, y)) { 2977 return false; 2978 } 2979 2980 w.getTouchableRegion(mTmpRegion); 2981 2982 final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL); 2983 return mTmpRegion.contains(x, y) || touchFlags == 0; 2984 }); 2985 2986 return touchedWin; 2987 } 2988 canAddToastWindowForUid(int uid)2989 boolean canAddToastWindowForUid(int uid) { 2990 // We allow one toast window per UID being shown at a time. 2991 // Also if the app is focused adding more than one toast at 2992 // a time for better backwards compatibility. 2993 final WindowState focusedWindowForUid = getWindow(w -> 2994 w.mOwnerUid == uid && w.isFocused()); 2995 if (focusedWindowForUid != null) { 2996 return true; 2997 } 2998 final WindowState win = getWindow(w -> 2999 w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden 3000 && !w.mWindowRemovalAllowed); 3001 return win == null; 3002 } 3003 scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus)3004 void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) { 3005 if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) { 3006 return; 3007 } 3008 3009 // Used to communicate the old focus to the callback method. 3010 mTmpWindow = oldFocus; 3011 3012 forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */); 3013 } 3014 3015 /** 3016 * Looking for the focused window on this display if the top focused display hasn't been 3017 * found yet (topFocusedDisplayId is INVALID_DISPLAY) or per-display focused was allowed. 3018 * 3019 * @param topFocusedDisplayId Id of the top focused display. 3020 * @return The focused window or null if there isn't any or no need to seek. 3021 */ findFocusedWindowIfNeeded(int topFocusedDisplayId)3022 WindowState findFocusedWindowIfNeeded(int topFocusedDisplayId) { 3023 return (mWmService.mPerDisplayFocusEnabled || topFocusedDisplayId == INVALID_DISPLAY) 3024 ? findFocusedWindow() : null; 3025 } 3026 findFocusedWindow()3027 WindowState findFocusedWindow() { 3028 mTmpWindow = null; 3029 3030 forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */); 3031 3032 if (mTmpWindow == null) { 3033 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows."); 3034 return null; 3035 } 3036 return mTmpWindow; 3037 } 3038 3039 /** 3040 * Update the focused window and make some adjustments if the focus has changed. 3041 * 3042 * @param mode Indicates the situation we are in. Possible modes are: 3043 * {@link WindowManagerService#UPDATE_FOCUS_NORMAL}, 3044 * {@link WindowManagerService#UPDATE_FOCUS_PLACING_SURFACES}, 3045 * {@link WindowManagerService#UPDATE_FOCUS_WILL_PLACE_SURFACES}, 3046 * {@link WindowManagerService#UPDATE_FOCUS_REMOVING_FOCUS} 3047 * @param updateInputWindows Whether to sync the window information to the input module. 3048 * @param topFocusedDisplayId Display id of current top focused display. 3049 * @return {@code true} if the focused window has changed. 3050 */ updateFocusedWindowLocked(int mode, boolean updateInputWindows, int topFocusedDisplayId)3051 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows, 3052 int topFocusedDisplayId) { 3053 WindowState newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId); 3054 if (mCurrentFocus == newFocus) { 3055 return false; 3056 } 3057 boolean imWindowChanged = false; 3058 final WindowState imWindow = mInputMethodWindow; 3059 if (imWindow != null) { 3060 final WindowState prevTarget = mInputMethodTarget; 3061 final WindowState newTarget = computeImeTarget(true /* updateImeTarget*/); 3062 imWindowChanged = prevTarget != newTarget; 3063 3064 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 3065 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) { 3066 assignWindowLayers(false /* setLayoutNeeded */); 3067 } 3068 } 3069 3070 if (imWindowChanged) { 3071 mWmService.mWindowsChanged = true; 3072 setLayoutNeeded(); 3073 newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId); 3074 } 3075 if (mCurrentFocus != newFocus) { 3076 mWmService.mH.obtainMessage(REPORT_FOCUS_CHANGE, this).sendToTarget(); 3077 } 3078 3079 if (DEBUG_FOCUS_LIGHT || mWmService.localLOGV) Slog.v(TAG_WM, "Changing focus from " 3080 + mCurrentFocus + " to " + newFocus + " displayId=" + getDisplayId() 3081 + " Callers=" + Debug.getCallers(4)); 3082 final WindowState oldFocus = mCurrentFocus; 3083 mCurrentFocus = newFocus; 3084 mLosingFocus.remove(newFocus); 3085 3086 if (newFocus != null) { 3087 mWinAddedSinceNullFocus.clear(); 3088 mWinRemovedSinceNullFocus.clear(); 3089 3090 if (newFocus.canReceiveKeys()) { 3091 // Displaying a window implicitly causes dispatching to be unpaused. 3092 // This is to protect against bugs if someone pauses dispatching but 3093 // forgets to resume. 3094 newFocus.mToken.paused = false; 3095 } 3096 } 3097 3098 int focusChanged = getDisplayPolicy().focusChangedLw(oldFocus, newFocus); 3099 3100 if (imWindowChanged && oldFocus != mInputMethodWindow) { 3101 // Focus of the input method window changed. Perform layout if needed. 3102 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 3103 performLayout(true /*initial*/, updateInputWindows); 3104 focusChanged &= ~FINISH_LAYOUT_REDO_LAYOUT; 3105 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 3106 // Client will do the layout, but we need to assign layers 3107 // for handleNewWindowLocked() below. 3108 assignWindowLayers(false /* setLayoutNeeded */); 3109 } 3110 } 3111 3112 if ((focusChanged & FINISH_LAYOUT_REDO_LAYOUT) != 0) { 3113 // The change in focus caused us to need to do a layout. Okay. 3114 setLayoutNeeded(); 3115 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 3116 performLayout(true /*initial*/, updateInputWindows); 3117 } else if (mode == UPDATE_FOCUS_REMOVING_FOCUS) { 3118 mWmService.mRoot.performSurfacePlacement(false); 3119 } 3120 } 3121 3122 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 3123 // If we defer assigning layers, then the caller is responsible for doing this part. 3124 getInputMonitor().setInputFocusLw(newFocus, updateInputWindows); 3125 } 3126 3127 adjustForImeIfNeeded(); 3128 3129 // We may need to schedule some toast windows to be removed. The toasts for an app that 3130 // does not have input focus are removed within a timeout to prevent apps to redress 3131 // other apps' UI. 3132 scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus); 3133 3134 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 3135 pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 3136 } 3137 return true; 3138 } 3139 3140 /** 3141 * Set the new focused app to this display. 3142 * 3143 * @param newFocus the new focused AppWindowToken. 3144 * @return true if the focused app is changed. 3145 */ setFocusedApp(AppWindowToken newFocus)3146 boolean setFocusedApp(AppWindowToken newFocus) { 3147 if (newFocus != null) { 3148 final DisplayContent appDisplay = newFocus.getDisplayContent(); 3149 if (appDisplay != this) { 3150 throw new IllegalStateException(newFocus + " is not on " + getName() 3151 + " but " + ((appDisplay != null) ? appDisplay.getName() : "none")); 3152 } 3153 } 3154 if (mFocusedApp == newFocus) { 3155 return false; 3156 } 3157 mFocusedApp = newFocus; 3158 getInputMonitor().setFocusedAppLw(newFocus); 3159 updateTouchExcludeRegion(); 3160 return true; 3161 } 3162 3163 /** Updates the layer assignment of windows on this display. */ assignWindowLayers(boolean setLayoutNeeded)3164 void assignWindowLayers(boolean setLayoutNeeded) { 3165 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "assignWindowLayers"); 3166 assignChildLayers(getPendingTransaction()); 3167 if (setLayoutNeeded) { 3168 setLayoutNeeded(); 3169 } 3170 3171 // We accumlate the layer changes in-to "getPendingTransaction()" but we defer 3172 // the application of this transaction until the animation pass triggers 3173 // prepareSurfaces. This allows us to synchronize Z-ordering changes with 3174 // the hiding and showing of surfaces. 3175 scheduleAnimation(); 3176 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 3177 } 3178 3179 // TODO: This should probably be called any time a visual change is made to the hierarchy like 3180 // moving containers or resizing them. Need to investigate the best way to have it automatically 3181 // happen so we don't run into issues with programmers forgetting to do it. layoutAndAssignWindowLayersIfNeeded()3182 void layoutAndAssignWindowLayersIfNeeded() { 3183 mWmService.mWindowsChanged = true; 3184 setLayoutNeeded(); 3185 3186 if (!mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 3187 false /*updateInputWindows*/)) { 3188 assignWindowLayers(false /* setLayoutNeeded */); 3189 } 3190 3191 mInputMonitor.setUpdateInputWindowsNeededLw(); 3192 mWmService.mWindowPlacerLocked.performSurfacePlacement(); 3193 mInputMonitor.updateInputWindowsLw(false /*force*/); 3194 } 3195 3196 /** Returns true if a leaked surface was destroyed */ destroyLeakedSurfaces()3197 boolean destroyLeakedSurfaces() { 3198 // Used to indicate that a surface was leaked. 3199 mTmpWindow = null; 3200 forAllWindows(w -> { 3201 final WindowStateAnimator wsa = w.mWinAnimator; 3202 if (wsa.mSurfaceController == null) { 3203 return; 3204 } 3205 if (!mWmService.mSessions.contains(wsa.mSession)) { 3206 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): " 3207 + w + " surface=" + wsa.mSurfaceController 3208 + " token=" + w.mToken 3209 + " pid=" + w.mSession.mPid 3210 + " uid=" + w.mSession.mUid); 3211 wsa.destroySurface(); 3212 mWmService.mForceRemoves.add(w); 3213 mTmpWindow = w; 3214 } else if (w.mAppToken != null && w.mAppToken.isClientHidden()) { 3215 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " 3216 + w + " surface=" + wsa.mSurfaceController 3217 + " token=" + w.mAppToken); 3218 if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false); 3219 wsa.destroySurface(); 3220 mTmpWindow = w; 3221 } 3222 }, false /* traverseTopToBottom */); 3223 3224 return mTmpWindow != null; 3225 } 3226 3227 /** 3228 * Set input method window for the display. 3229 * @param win Set when window added or Null when destroyed. 3230 */ setInputMethodWindowLocked(WindowState win)3231 void setInputMethodWindowLocked(WindowState win) { 3232 mInputMethodWindow = win; 3233 // Update display configuration for IME process. 3234 if (mInputMethodWindow != null) { 3235 final int imePid = mInputMethodWindow.mSession.mPid; 3236 mWmService.mAtmInternal.onImeWindowSetOnDisplay(imePid, 3237 mInputMethodWindow.getDisplayId()); 3238 } 3239 computeImeTarget(true /* updateImeTarget */); 3240 mInsetsStateController.getSourceProvider(TYPE_IME).setWindow(win, 3241 null /* frameProvider */); 3242 } 3243 3244 /** 3245 * Determine and return the window that should be the IME target. 3246 * @param updateImeTarget If true the system IME target will be updated to match what we found. 3247 * @return The window that should be used as the IME target or null if there isn't any. 3248 */ computeImeTarget(boolean updateImeTarget)3249 WindowState computeImeTarget(boolean updateImeTarget) { 3250 if (mInputMethodWindow == null) { 3251 // There isn't an IME so there shouldn't be a target...That was easy! 3252 if (updateImeTarget) { 3253 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " 3254 + mInputMethodTarget + " to null since mInputMethodWindow is null"); 3255 setInputMethodTarget(null, mInputMethodTargetWaitingAnim); 3256 } 3257 return null; 3258 } 3259 3260 final WindowState curTarget = mInputMethodTarget; 3261 if (!canUpdateImeTarget()) { 3262 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target"); 3263 return curTarget; 3264 } 3265 3266 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 3267 // same display. Or even when the current IME/target are not on the same screen as the next 3268 // IME/target. For now only look for input windows on the main screen. 3269 mUpdateImeTarget = updateImeTarget; 3270 WindowState target = getWindow(mComputeImeTargetPredicate); 3271 3272 3273 // Yet more tricksyness! If this window is a "starting" window, we do actually want 3274 // to be on top of it, but it is not -really- where input will go. So look down below 3275 // for a real window to target... 3276 if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) { 3277 final AppWindowToken token = target.mAppToken; 3278 if (token != null) { 3279 final WindowState betterTarget = token.getImeTargetBelowWindow(target); 3280 if (betterTarget != null) { 3281 target = betterTarget; 3282 } 3283 } 3284 } 3285 3286 if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM, 3287 "Proposed new IME target: " + target + " for display: " + getDisplayId()); 3288 3289 // Now, a special case -- if the last target's window is in the process of exiting, but 3290 // not removed, keep on the last target to avoid IME flicker. 3291 if (curTarget != null && !curTarget.mRemoved && curTarget.isDisplayedLw() 3292 && curTarget.isClosing()) { 3293 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Not changing target till current window is" 3294 + " closing and not removed"); 3295 return curTarget; 3296 } 3297 3298 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target 3299 + " updateImeTarget=" + updateImeTarget); 3300 3301 if (target == null) { 3302 if (updateImeTarget) { 3303 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget 3304 + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" 3305 + Debug.getCallers(4) : "")); 3306 setInputMethodTarget(null, mInputMethodTargetWaitingAnim); 3307 } 3308 3309 return null; 3310 } 3311 3312 if (updateImeTarget) { 3313 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 3314 if (token != null) { 3315 3316 // Now some fun for dealing with window animations that modify the Z order. We need 3317 // to look at all windows below the current target that are in this app, finding the 3318 // highest visible one in layering. 3319 WindowState highestTarget = null; 3320 if (token.isSelfAnimating()) { 3321 highestTarget = token.getHighestAnimLayerWindow(curTarget); 3322 } 3323 3324 if (highestTarget != null) { 3325 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, mAppTransition + " " + highestTarget 3326 + " animating=" + highestTarget.isAnimating()); 3327 3328 if (mAppTransition.isTransitionSet()) { 3329 // If we are currently setting up for an animation, hold everything until we 3330 // can find out what will happen. 3331 setInputMethodTarget(highestTarget, true); 3332 return highestTarget; 3333 } 3334 } 3335 } 3336 3337 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to " 3338 + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 3339 setInputMethodTarget(target, false); 3340 } 3341 3342 return target; 3343 } 3344 3345 /** 3346 * Calling {@link #computeImeTarget(boolean)} to update the input method target window in 3347 * the candidate app window token if needed. 3348 */ computeImeTargetIfNeeded(AppWindowToken candidate)3349 void computeImeTargetIfNeeded(AppWindowToken candidate) { 3350 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == candidate) { 3351 computeImeTarget(true /* updateImeTarget */); 3352 } 3353 } 3354 setInputMethodTarget(WindowState target, boolean targetWaitingAnim)3355 private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) { 3356 if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) { 3357 return; 3358 } 3359 3360 mInputMethodTarget = target; 3361 mInputMethodTargetWaitingAnim = targetWaitingAnim; 3362 assignWindowLayers(false /* setLayoutNeeded */); 3363 mInsetsStateController.onImeTargetChanged(target); 3364 updateImeParent(); 3365 } 3366 updateImeParent()3367 private void updateImeParent() { 3368 // Force attaching IME to the display when magnifying, or it would be magnified with 3369 // target app together. 3370 final boolean shouldAttachToDisplay = (mMagnificationSpec != null); 3371 final SurfaceControl newParent = 3372 shouldAttachToDisplay ? mWindowingLayer : computeImeParent(); 3373 if (newParent != null) { 3374 getPendingTransaction().reparent(mImeWindowsContainers.mSurfaceControl, newParent); 3375 scheduleAnimation(); 3376 } 3377 } 3378 3379 /** 3380 * Computes the window the IME should be attached to. 3381 */ 3382 @VisibleForTesting computeImeParent()3383 SurfaceControl computeImeParent() { 3384 3385 // Attach it to app if the target is part of an app and such app is covering the entire 3386 // screen. If it's not covering the entire screen the IME might extend beyond the apps 3387 // bounds. 3388 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken != null 3389 && mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN 3390 // An activity with override bounds should be letterboxed inside its parent bounds, 3391 // so it doesn't fill the screen. 3392 && mInputMethodTarget.mAppToken.matchParentBounds()) { 3393 return mInputMethodTarget.mAppToken.getSurfaceControl(); 3394 } 3395 3396 // Otherwise, we just attach it to the display. 3397 return mWindowingLayer; 3398 } 3399 getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom)3400 boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) { 3401 if (top.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) { 3402 return top.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE; 3403 } 3404 3405 // Used to indicate we have reached the first window in the range we are interested in. 3406 mTmpWindow = null; 3407 3408 // TODO: Figure-out a more efficient way to do this. 3409 final WindowState candidate = getWindow(w -> { 3410 if (w == top) { 3411 // Reached the first window in the range we are interested in. 3412 mTmpWindow = w; 3413 } 3414 if (mTmpWindow == null) { 3415 return false; 3416 } 3417 3418 if (w.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) { 3419 return true; 3420 } 3421 // If we reached the bottom of the range of windows we are considering, 3422 // assume no menu is needed. 3423 if (w == bottom) { 3424 return true; 3425 } 3426 return false; 3427 }); 3428 3429 return candidate != null && candidate.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE; 3430 } 3431 setLayoutNeeded()3432 void setLayoutNeeded() { 3433 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3)); 3434 mLayoutNeeded = true; 3435 } 3436 clearLayoutNeeded()3437 private void clearLayoutNeeded() { 3438 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3)); 3439 mLayoutNeeded = false; 3440 } 3441 isLayoutNeeded()3442 boolean isLayoutNeeded() { 3443 return mLayoutNeeded; 3444 } 3445 dumpTokens(PrintWriter pw, boolean dumpAll)3446 void dumpTokens(PrintWriter pw, boolean dumpAll) { 3447 if (mTokenMap.isEmpty()) { 3448 return; 3449 } 3450 pw.println(" Display #" + mDisplayId); 3451 final Iterator<WindowToken> it = mTokenMap.values().iterator(); 3452 while (it.hasNext()) { 3453 final WindowToken token = it.next(); 3454 pw.print(" "); 3455 pw.print(token); 3456 if (dumpAll) { 3457 pw.println(':'); 3458 token.dump(pw, " ", dumpAll); 3459 } else { 3460 pw.println(); 3461 } 3462 } 3463 3464 if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty() || !mChangingApps.isEmpty()) { 3465 pw.println(); 3466 if (mOpeningApps.size() > 0) { 3467 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 3468 } 3469 if (mClosingApps.size() > 0) { 3470 pw.print(" mClosingApps="); pw.println(mClosingApps); 3471 } 3472 if (mChangingApps.size() > 0) { 3473 pw.print(" mChangingApps="); pw.println(mChangingApps); 3474 } 3475 } 3476 3477 mUnknownAppVisibilityController.dump(pw, " "); 3478 } 3479 dumpWindowAnimators(PrintWriter pw, String subPrefix)3480 void dumpWindowAnimators(PrintWriter pw, String subPrefix) { 3481 final int[] index = new int[1]; 3482 forAllWindows(w -> { 3483 final WindowStateAnimator wAnim = w.mWinAnimator; 3484 pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim); 3485 index[0] = index[0] + 1; 3486 }, false /* traverseTopToBottom */); 3487 } 3488 3489 /** 3490 * Starts the Keyguard exit animation on all windows that don't belong to an app token. 3491 */ startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade)3492 void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) { 3493 final WindowManagerPolicy policy = mWmService.mPolicy; 3494 forAllWindows(w -> { 3495 if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w) 3496 && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) { 3497 w.startAnimation(policy.createHiddenByKeyguardExit(onWallpaper, goingToShade)); 3498 } 3499 }, true /* traverseTopToBottom */); 3500 } 3501 checkWaitingForWindows()3502 boolean checkWaitingForWindows() { 3503 3504 mHaveBootMsg = false; 3505 mHaveApp = false; 3506 mHaveWallpaper = false; 3507 mHaveKeyguard = true; 3508 3509 final WindowState visibleWindow = getWindow(w -> { 3510 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 3511 return true; 3512 } 3513 if (w.isDrawnLw()) { 3514 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 3515 mHaveBootMsg = true; 3516 } else if (w.mAttrs.type == TYPE_APPLICATION 3517 || w.mAttrs.type == TYPE_DRAWN_APPLICATION) { 3518 mHaveApp = true; 3519 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 3520 mHaveWallpaper = true; 3521 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 3522 mHaveKeyguard = mWmService.mPolicy.isKeyguardDrawnLw(); 3523 } 3524 } 3525 return false; 3526 }); 3527 3528 if (visibleWindow != null) { 3529 // We have a visible window. 3530 return true; 3531 } 3532 3533 // if the wallpaper service is disabled on the device, we're never going to have 3534 // wallpaper, don't bother waiting for it 3535 boolean wallpaperEnabled = mWmService.mContext.getResources().getBoolean( 3536 com.android.internal.R.bool.config_enableWallpaperService) 3537 && mWmService.mContext.getResources().getBoolean( 3538 com.android.internal.R.bool.config_checkWallpaperAtBoot) 3539 && !mWmService.mOnlyCore; 3540 3541 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, 3542 "******** booted=" + mWmService.mSystemBooted 3543 + " msg=" + mWmService.mShowingBootMessages 3544 + " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp 3545 + " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled 3546 + " haveKeyguard=" + mHaveKeyguard); 3547 3548 // If we are turning on the screen to show the boot message, don't do it until the boot 3549 // message is actually displayed. 3550 if (!mWmService.mSystemBooted && !mHaveBootMsg) { 3551 return true; 3552 } 3553 3554 // If we are turning on the screen after the boot is completed normally, don't do so until 3555 // we have the application and wallpaper. 3556 if (mWmService.mSystemBooted 3557 && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) { 3558 return true; 3559 } 3560 3561 return false; 3562 } 3563 updateWindowsForAnimator()3564 void updateWindowsForAnimator() { 3565 forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */); 3566 } 3567 3568 /** 3569 * Updates the {@link TaskStack#setAnimationBackground} for all windows. 3570 */ updateBackgroundForAnimator()3571 void updateBackgroundForAnimator() { 3572 resetAnimationBackgroundAnimator(); 3573 forAllWindows(mUpdateWallpaperForAnimator, true /* traverseTopToBottom */); 3574 } 3575 isInputMethodClientFocus(int uid, int pid)3576 boolean isInputMethodClientFocus(int uid, int pid) { 3577 final WindowState imFocus = computeImeTarget(false /* updateImeTarget */); 3578 if (imFocus == null) { 3579 return false; 3580 } 3581 3582 if (DEBUG_INPUT_METHOD) { 3583 Slog.i(TAG_WM, "Desired input method target: " + imFocus); 3584 Slog.i(TAG_WM, "Current focus: " + mCurrentFocus + " displayId=" + mDisplayId); 3585 Slog.i(TAG_WM, "Last focus: " + mLastFocus + " displayId=" + mDisplayId); 3586 } 3587 3588 if (DEBUG_INPUT_METHOD) { 3589 Slog.i(TAG_WM, "IM target uid/pid: " + imFocus.mSession.mUid 3590 + "/" + imFocus.mSession.mPid); 3591 Slog.i(TAG_WM, "Requesting client uid/pid: " + uid + "/" + pid); 3592 } 3593 3594 return imFocus.mSession.mUid == uid && imFocus.mSession.mPid == pid; 3595 } 3596 hasSecureWindowOnScreen()3597 boolean hasSecureWindowOnScreen() { 3598 final WindowState win = getWindow( 3599 w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0); 3600 return win != null; 3601 } 3602 statusBarVisibilityChanged(int visibility)3603 void statusBarVisibilityChanged(int visibility) { 3604 mLastStatusBarVisibility = visibility; 3605 visibility = getDisplayPolicy().adjustSystemUiVisibilityLw(visibility); 3606 updateStatusBarVisibilityLocked(visibility); 3607 } 3608 updateStatusBarVisibilityLocked(int visibility)3609 private boolean updateStatusBarVisibilityLocked(int visibility) { 3610 if (mLastDispatchedSystemUiVisibility == visibility) { 3611 return false; 3612 } 3613 final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility) 3614 // We are only interested in differences of one of the 3615 // clearable flags... 3616 & View.SYSTEM_UI_CLEARABLE_FLAGS 3617 // ...if it has actually been cleared. 3618 & ~visibility; 3619 3620 mLastDispatchedSystemUiVisibility = visibility; 3621 if (isDefaultDisplay) { 3622 mWmService.mInputManager.setSystemUiVisibility(visibility); 3623 } 3624 updateSystemUiVisibility(visibility, globalDiff); 3625 return true; 3626 } 3627 updateSystemUiVisibility(int visibility, int globalDiff)3628 void updateSystemUiVisibility(int visibility, int globalDiff) { 3629 forAllWindows(w -> { 3630 try { 3631 final int curValue = w.mSystemUiVisibility; 3632 final int diff = (curValue ^ visibility) & globalDiff; 3633 final int newValue = (curValue & ~diff) | (visibility & diff); 3634 if (newValue != curValue) { 3635 w.mSeq++; 3636 w.mSystemUiVisibility = newValue; 3637 } 3638 if (newValue != curValue || w.mAttrs.hasSystemUiListeners) { 3639 w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq, 3640 visibility, newValue, diff); 3641 } 3642 } catch (RemoteException e) { 3643 // so sorry 3644 } 3645 }, true /* traverseTopToBottom */); 3646 } 3647 reevaluateStatusBarVisibility()3648 void reevaluateStatusBarVisibility() { 3649 int visibility = getDisplayPolicy().adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 3650 if (updateStatusBarVisibilityLocked(visibility)) { 3651 mWmService.mWindowPlacerLocked.requestTraversal(); 3652 } 3653 } 3654 onWindowFreezeTimeout()3655 void onWindowFreezeTimeout() { 3656 Slog.w(TAG_WM, "Window freeze timeout expired."); 3657 mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 3658 3659 forAllWindows(w -> { 3660 if (!w.getOrientationChanging()) { 3661 return; 3662 } 3663 w.orientationChangeTimedOut(); 3664 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 3665 - mWmService.mDisplayFreezeTime); 3666 Slog.w(TAG_WM, "Force clearing orientation change: " + w); 3667 }, true /* traverseTopToBottom */); 3668 mWmService.mWindowPlacerLocked.performSurfacePlacement(); 3669 } 3670 waitForAllWindowsDrawn()3671 void waitForAllWindowsDrawn() { 3672 final WindowManagerPolicy policy = mWmService.mPolicy; 3673 forAllWindows(w -> { 3674 final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs); 3675 if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) { 3676 w.mWinAnimator.mDrawState = DRAW_PENDING; 3677 // Force add to mResizingWindows. 3678 w.resetLastContentInsets(); 3679 mWmService.mWaitingForDrawn.add(w); 3680 } 3681 }, true /* traverseTopToBottom */); 3682 } 3683 3684 // TODO: Super crazy long method that should be broken down... applySurfaceChangesTransaction(boolean recoveringMemory)3685 void applySurfaceChangesTransaction(boolean recoveringMemory) { 3686 final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked; 3687 3688 mTmpUpdateAllDrawn.clear(); 3689 3690 int repeats = 0; 3691 do { 3692 repeats++; 3693 if (repeats > 6) { 3694 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 3695 clearLayoutNeeded(); 3696 break; 3697 } 3698 3699 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner", 3700 pendingLayoutChanges); 3701 3702 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 3703 mWallpaperController.adjustWallpaperWindows(); 3704 } 3705 3706 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { 3707 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 3708 if (updateOrientationFromAppTokens()) { 3709 setLayoutNeeded(); 3710 sendNewConfiguration(); 3711 } 3712 } 3713 3714 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) { 3715 setLayoutNeeded(); 3716 } 3717 3718 // FIRST LOOP: Perform a layout, if needed. 3719 if (repeats < LAYOUT_REPEAT_THRESHOLD) { 3720 performLayout(repeats == 1, false /* updateInputWindows */); 3721 } else { 3722 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 3723 } 3724 3725 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating. 3726 pendingLayoutChanges = 0; 3727 3728 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy"); 3729 try { 3730 mDisplayPolicy.beginPostLayoutPolicyLw(); 3731 forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */); 3732 pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw(); 3733 } finally { 3734 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 3735 } 3736 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats( 3737 "after finishPostLayoutPolicyLw", pendingLayoutChanges); 3738 mInsetsStateController.onPostLayout(); 3739 } while (pendingLayoutChanges != 0); 3740 3741 mTmpApplySurfaceChangesTransactionState.reset(); 3742 3743 mTmpRecoveringMemory = recoveringMemory; 3744 3745 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges"); 3746 try { 3747 forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */); 3748 } finally { 3749 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 3750 } 3751 prepareSurfaces(); 3752 3753 mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent; 3754 mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId, 3755 mLastHasContent, 3756 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate, 3757 mTmpApplySurfaceChangesTransactionState.preferredModeId, 3758 true /* inTraversal, must call performTraversalInTrans... below */); 3759 3760 final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible(); 3761 if (wallpaperVisible != mLastWallpaperVisible) { 3762 mLastWallpaperVisible = wallpaperVisible; 3763 mWmService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this); 3764 } 3765 3766 while (!mTmpUpdateAllDrawn.isEmpty()) { 3767 final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast(); 3768 // See if any windows have been drawn, so they (and others associated with them) 3769 // can now be shown. 3770 atoken.updateAllDrawn(); 3771 } 3772 } 3773 updateBounds()3774 private void updateBounds() { 3775 calculateBounds(mDisplayInfo, mTmpBounds); 3776 setBounds(mTmpBounds); 3777 if (mPortalWindowHandle != null && mParentSurfaceControl != null) { 3778 mPortalWindowHandle.touchableRegion.getBounds(mTmpRect); 3779 if (!mTmpBounds.equals(mTmpRect)) { 3780 mPortalWindowHandle.touchableRegion.set(mTmpBounds); 3781 getPendingTransaction().setInputWindowInfo( 3782 mParentSurfaceControl, mPortalWindowHandle); 3783 } 3784 } 3785 } 3786 3787 // Determines the current display bounds based on the current state calculateBounds(DisplayInfo displayInfo, Rect out)3788 private void calculateBounds(DisplayInfo displayInfo, Rect out) { 3789 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. 3790 final int rotation = displayInfo.rotation; 3791 boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); 3792 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 3793 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 3794 int width = displayInfo.logicalWidth; 3795 int left = (physWidth - width) / 2; 3796 int height = displayInfo.logicalHeight; 3797 int top = (physHeight - height) / 2; 3798 out.set(left, top, left + width, top + height); 3799 } 3800 getBounds(Rect out, int orientation)3801 private void getBounds(Rect out, int orientation) { 3802 getBounds(out); 3803 3804 // Rotate the Rect if needed. 3805 final int currentRotation = mDisplayInfo.rotation; 3806 final int rotationDelta = deltaRotation(currentRotation, orientation); 3807 if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { 3808 createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix); 3809 mTmpRectF.set(out); 3810 mTmpMatrix.mapRect(mTmpRectF); 3811 mTmpRectF.round(out); 3812 } 3813 } 3814 3815 /** @returns the orientation of the display when it's rotation is ROTATION_0. */ getNaturalOrientation()3816 int getNaturalOrientation() { 3817 return mBaseDisplayWidth < mBaseDisplayHeight 3818 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; 3819 } 3820 performLayout(boolean initial, boolean updateInputWindows)3821 void performLayout(boolean initial, boolean updateInputWindows) { 3822 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performLayout"); 3823 try { 3824 performLayoutNoTrace(initial, updateInputWindows); 3825 } finally { 3826 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 3827 } 3828 } 3829 performLayoutNoTrace(boolean initial, boolean updateInputWindows)3830 private void performLayoutNoTrace(boolean initial, boolean updateInputWindows) { 3831 if (!isLayoutNeeded()) { 3832 return; 3833 } 3834 clearLayoutNeeded(); 3835 3836 final int dw = mDisplayInfo.logicalWidth; 3837 final int dh = mDisplayInfo.logicalHeight; 3838 if (DEBUG_LAYOUT) { 3839 Slog.v(TAG, "-------------------------------------"); 3840 Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw 3841 + " dh=" + dh); 3842 } 3843 3844 mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo, 3845 calculateDisplayCutoutForRotation(mDisplayInfo.rotation)); 3846 // TODO: Not sure if we really need to set the rotation here since we are updating from 3847 // the display info above... 3848 mDisplayFrames.mRotation = mRotation; 3849 mDisplayPolicy.beginLayoutLw(mDisplayFrames, getConfiguration().uiMode); 3850 3851 int seq = mLayoutSeq + 1; 3852 if (seq < 0) seq = 0; 3853 mLayoutSeq = seq; 3854 3855 // Used to indicate that we have processed the dream window and all additional windows are 3856 // behind it. 3857 mTmpWindow = null; 3858 mTmpInitial = initial; 3859 3860 // First perform layout of any root windows (not attached to another window). 3861 forAllWindows(mPerformLayout, true /* traverseTopToBottom */); 3862 3863 // Used to indicate that we have processed the dream window and all additional attached 3864 // windows are behind it. 3865 mTmpWindow2 = mTmpWindow; 3866 mTmpWindow = null; 3867 3868 // Now perform layout of attached windows, which usually depend on the position of the 3869 // window they are attached to. XXX does not deal with windows that are attached to windows 3870 // that are themselves attached. 3871 forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */); 3872 3873 // Window frames may have changed. Tell the input dispatcher about it. 3874 mInputMonitor.layoutInputConsumers(dw, dh); 3875 mInputMonitor.setUpdateInputWindowsNeededLw(); 3876 if (updateInputWindows) { 3877 mInputMonitor.updateInputWindowsLw(false /*force*/); 3878 } 3879 3880 mWmService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER); 3881 } 3882 3883 /** 3884 * Takes a snapshot of the display. In landscape mode this grabs the whole screen. 3885 * In portrait mode, it grabs the full screenshot. 3886 * 3887 * @param config of the output bitmap 3888 */ screenshotDisplayLocked(Bitmap.Config config)3889 Bitmap screenshotDisplayLocked(Bitmap.Config config) { 3890 if (!mWmService.mPolicy.isScreenOn()) { 3891 if (DEBUG_SCREENSHOT) { 3892 Slog.i(TAG_WM, "Attempted to take screenshot while display was off."); 3893 } 3894 return null; 3895 } 3896 3897 int dw = mDisplayInfo.logicalWidth; 3898 int dh = mDisplayInfo.logicalHeight; 3899 3900 if (dw <= 0 || dh <= 0) { 3901 return null; 3902 } 3903 3904 final Rect frame = new Rect(0, 0, dw, dh); 3905 3906 // The screenshot API does not apply the current screen rotation. 3907 int rot = mDisplay.getRotation(); 3908 3909 if (rot == ROTATION_90 || rot == ROTATION_270) { 3910 rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90; 3911 } 3912 3913 // SurfaceFlinger is not aware of orientation, so convert our logical 3914 // crop to SurfaceFlinger's portrait orientation. 3915 convertCropForSurfaceFlinger(frame, rot, dw, dh); 3916 3917 final ScreenRotationAnimation screenRotationAnimation = 3918 mWmService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY); 3919 final boolean inRotation = screenRotationAnimation != null && 3920 screenRotationAnimation.isAnimating(); 3921 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, "Taking screenshot while rotating"); 3922 3923 // TODO(b/68392460): We should screenshot Task controls directly 3924 // but it's difficult at the moment as the Task doesn't have the 3925 // correct size set. 3926 final Bitmap bitmap = SurfaceControl.screenshot(frame, dw, dh, inRotation, rot); 3927 if (bitmap == null) { 3928 Slog.w(TAG_WM, "Failed to take screenshot"); 3929 return null; 3930 } 3931 3932 // Create a copy of the screenshot that is immutable and backed in ashmem. 3933 // This greatly reduces the overhead of passing the bitmap between processes. 3934 final Bitmap ret = bitmap.createAshmemBitmap(config); 3935 bitmap.recycle(); 3936 return ret; 3937 } 3938 3939 // TODO: Can this use createRotationMatrix()? convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh)3940 private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) { 3941 if (rot == Surface.ROTATION_90) { 3942 final int tmp = crop.top; 3943 crop.top = dw - crop.right; 3944 crop.right = crop.bottom; 3945 crop.bottom = dw - crop.left; 3946 crop.left = tmp; 3947 } else if (rot == Surface.ROTATION_180) { 3948 int tmp = crop.top; 3949 crop.top = dh - crop.bottom; 3950 crop.bottom = dh - tmp; 3951 tmp = crop.right; 3952 crop.right = dw - crop.left; 3953 crop.left = dw - tmp; 3954 } else if (rot == Surface.ROTATION_270) { 3955 final int tmp = crop.top; 3956 crop.top = crop.left; 3957 crop.left = dh - crop.bottom; 3958 crop.bottom = crop.right; 3959 crop.right = dh - tmp; 3960 } 3961 } 3962 onSeamlessRotationTimeout()3963 void onSeamlessRotationTimeout() { 3964 // Used to indicate the layout is needed. 3965 mTmpWindow = null; 3966 3967 forAllWindows(w -> { 3968 if (!w.mSeamlesslyRotated) { 3969 return; 3970 } 3971 mTmpWindow = w; 3972 w.setDisplayLayoutNeeded(); 3973 w.finishSeamlessRotation(true /* timeout */); 3974 mWmService.markForSeamlessRotation(w, false); 3975 }, true /* traverseTopToBottom */); 3976 3977 if (mTmpWindow != null) { 3978 mWmService.mWindowPlacerLocked.performSurfacePlacement(); 3979 } 3980 } 3981 setExitingTokensHasVisible(boolean hasVisible)3982 void setExitingTokensHasVisible(boolean hasVisible) { 3983 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 3984 mExitingTokens.get(i).hasVisible = hasVisible; 3985 } 3986 3987 // Initialize state of exiting applications. 3988 mTaskStackContainers.setExitingTokensHasVisible(hasVisible); 3989 } 3990 removeExistingTokensIfPossible()3991 void removeExistingTokensIfPossible() { 3992 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 3993 final WindowToken token = mExitingTokens.get(i); 3994 if (!token.hasVisible) { 3995 mExitingTokens.remove(i); 3996 } 3997 } 3998 3999 // Time to remove any exiting applications? 4000 mTaskStackContainers.removeExistingAppTokensIfPossible(); 4001 } 4002 4003 @Override onDescendantOverrideConfigurationChanged()4004 void onDescendantOverrideConfigurationChanged() { 4005 setLayoutNeeded(); 4006 mWmService.requestTraversal(); 4007 } 4008 okToDisplay()4009 boolean okToDisplay() { 4010 if (mDisplayId == DEFAULT_DISPLAY) { 4011 return !mWmService.mDisplayFrozen 4012 && mWmService.mDisplayEnabled && mWmService.mPolicy.isScreenOn(); 4013 } 4014 return mDisplayInfo.state == Display.STATE_ON; 4015 } 4016 okToAnimate()4017 boolean okToAnimate() { 4018 return okToDisplay() && 4019 (mDisplayId != DEFAULT_DISPLAY || mWmService.mPolicy.okToAnimate()); 4020 } 4021 4022 static final class TaskForResizePointSearchResult { 4023 boolean searchDone; 4024 Task taskForResize; 4025 reset()4026 void reset() { 4027 searchDone = false; 4028 taskForResize = null; 4029 } 4030 } 4031 4032 private static final class ApplySurfaceChangesTransactionState { 4033 boolean displayHasContent; 4034 boolean obscured; 4035 boolean syswin; 4036 float preferredRefreshRate; 4037 int preferredModeId; 4038 reset()4039 void reset() { 4040 displayHasContent = false; 4041 obscured = false; 4042 syswin = false; 4043 preferredRefreshRate = 0; 4044 preferredModeId = 0; 4045 } 4046 } 4047 4048 private static final class ScreenshotApplicationState { 4049 WindowState appWin; 4050 int maxLayer; 4051 int minLayer; 4052 boolean screenshotReady; 4053 reset(boolean screenshotReady)4054 void reset(boolean screenshotReady) { 4055 appWin = null; 4056 maxLayer = 0; 4057 minLayer = 0; 4058 this.screenshotReady = screenshotReady; 4059 minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE; 4060 } 4061 } 4062 4063 /** 4064 * Base class for any direct child window container of {@link #DisplayContent} need to inherit 4065 * from. This is mainly a pass through class that allows {@link #DisplayContent} to have 4066 * homogeneous children type which is currently required by sub-classes of 4067 * {@link WindowContainer} class. 4068 */ 4069 static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> { 4070 DisplayChildWindowContainer(WindowManagerService service)4071 DisplayChildWindowContainer(WindowManagerService service) { 4072 super(service); 4073 } 4074 4075 @Override fillsParent()4076 boolean fillsParent() { 4077 return true; 4078 } 4079 4080 @Override isVisible()4081 boolean isVisible() { 4082 return true; 4083 } 4084 } 4085 4086 /** 4087 * Window container class that contains all containers on this display relating to Apps. 4088 * I.e Activities. 4089 */ 4090 private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> { 4091 /** 4092 * A control placed at the appropriate level for transitions to occur. 4093 */ 4094 SurfaceControl mAppAnimationLayer = null; 4095 SurfaceControl mBoostedAppAnimationLayer = null; 4096 SurfaceControl mHomeAppAnimationLayer = null; 4097 4098 /** 4099 * Given that the split-screen divider does not have an AppWindowToken, it 4100 * will have to live inside of a "NonAppWindowContainer", in particular 4101 * {@link DisplayContent#mAboveAppWindowsContainers}. However, in visual Z order 4102 * it will need to be interleaved with some of our children, appearing on top of 4103 * both docked stacks but underneath any assistant stacks. 4104 * 4105 * To solve this problem we have this anchor control, which will always exist so 4106 * we can always assign it the correct value in our {@link #assignChildLayers}. 4107 * Likewise since it always exists, {@link AboveAppWindowContainers} can always 4108 * assign the divider a layer relative to it. This way we prevent linking lifecycle 4109 * events between the two containers. 4110 */ 4111 SurfaceControl mSplitScreenDividerAnchor = null; 4112 4113 // Cached reference to some special stacks we tend to get a lot so we don't need to loop 4114 // through the list to find them. 4115 private TaskStack mHomeStack = null; 4116 private TaskStack mPinnedStack = null; 4117 private TaskStack mSplitScreenPrimaryStack = null; 4118 TaskStackContainers(WindowManagerService service)4119 TaskStackContainers(WindowManagerService service) { 4120 super(service); 4121 } 4122 4123 /** 4124 * Returns the topmost stack on the display that is compatible with the input windowing mode 4125 * and activity type. Null is no compatible stack on the display. 4126 */ getStack(int windowingMode, int activityType)4127 TaskStack getStack(int windowingMode, int activityType) { 4128 if (activityType == ACTIVITY_TYPE_HOME) { 4129 return mHomeStack; 4130 } 4131 if (windowingMode == WINDOWING_MODE_PINNED) { 4132 return mPinnedStack; 4133 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 4134 return mSplitScreenPrimaryStack; 4135 } 4136 for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) { 4137 final TaskStack stack = mTaskStackContainers.getChildAt(i); 4138 if (activityType == ACTIVITY_TYPE_UNDEFINED 4139 && windowingMode == stack.getWindowingMode()) { 4140 // Passing in undefined type means we want to match the topmost stack with the 4141 // windowing mode. 4142 return stack; 4143 } 4144 if (stack.isCompatible(windowingMode, activityType)) { 4145 return stack; 4146 } 4147 } 4148 return null; 4149 } 4150 4151 @VisibleForTesting getTopStack()4152 TaskStack getTopStack() { 4153 return mTaskStackContainers.getChildCount() > 0 4154 ? mTaskStackContainers.getChildAt(mTaskStackContainers.getChildCount() - 1) : null; 4155 } 4156 getHomeStack()4157 TaskStack getHomeStack() { 4158 if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) { 4159 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this); 4160 } 4161 return mHomeStack; 4162 } 4163 getPinnedStack()4164 TaskStack getPinnedStack() { 4165 return mPinnedStack; 4166 } 4167 getSplitScreenPrimaryStack()4168 TaskStack getSplitScreenPrimaryStack() { 4169 return mSplitScreenPrimaryStack; 4170 } 4171 getVisibleTasks()4172 ArrayList<Task> getVisibleTasks() { 4173 final ArrayList<Task> visibleTasks = new ArrayList<>(); 4174 forAllTasks(task -> { 4175 if (task.isVisible()) { 4176 visibleTasks.add(task); 4177 } 4178 }); 4179 return visibleTasks; 4180 } 4181 4182 /** 4183 * Adds the stack to this container. 4184 */ addStackToDisplay(TaskStack stack, boolean onTop)4185 void addStackToDisplay(TaskStack stack, boolean onTop) { 4186 addStackReferenceIfNeeded(stack); 4187 addChild(stack, onTop); 4188 stack.onDisplayChanged(DisplayContent.this); 4189 } 4190 onStackWindowingModeChanged(TaskStack stack)4191 void onStackWindowingModeChanged(TaskStack stack) { 4192 removeStackReferenceIfNeeded(stack); 4193 addStackReferenceIfNeeded(stack); 4194 if (stack == mPinnedStack && getTopStack() != stack) { 4195 // Looks like this stack changed windowing mode to pinned. Move it to the top. 4196 positionChildAt(POSITION_TOP, stack, false /* includingParents */); 4197 } 4198 } 4199 addStackReferenceIfNeeded(TaskStack stack)4200 private void addStackReferenceIfNeeded(TaskStack stack) { 4201 if (stack.isActivityTypeHome()) { 4202 if (mHomeStack != null) { 4203 throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack=" 4204 + mHomeStack + " already exist on display=" + this + " stack=" + stack); 4205 4206 } 4207 mHomeStack = stack; 4208 } 4209 final int windowingMode = stack.getWindowingMode(); 4210 if (windowingMode == WINDOWING_MODE_PINNED) { 4211 if (mPinnedStack != null) { 4212 throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack=" 4213 + mPinnedStack + " already exist on display=" + this 4214 + " stack=" + stack); 4215 } 4216 mPinnedStack = stack; 4217 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 4218 if (mSplitScreenPrimaryStack != null) { 4219 throw new IllegalArgumentException("addStackReferenceIfNeeded:" 4220 + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack 4221 + " already exist on display=" + this + " stack=" + stack); 4222 } 4223 mSplitScreenPrimaryStack = stack; 4224 mDividerControllerLocked.notifyDockedStackExistsChanged(true); 4225 } 4226 } 4227 removeStackReferenceIfNeeded(TaskStack stack)4228 private void removeStackReferenceIfNeeded(TaskStack stack) { 4229 if (stack == mHomeStack) { 4230 mHomeStack = null; 4231 } else if (stack == mPinnedStack) { 4232 mPinnedStack = null; 4233 } else if (stack == mSplitScreenPrimaryStack) { 4234 mSplitScreenPrimaryStack = null; 4235 // Re-set the split-screen create mode whenever the split-screen stack is removed. 4236 mWmService.setDockedStackCreateStateLocked( 4237 SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */); 4238 mDividerControllerLocked.notifyDockedStackExistsChanged(false); 4239 } 4240 } 4241 addChild(TaskStack stack, boolean toTop)4242 private void addChild(TaskStack stack, boolean toTop) { 4243 final int addIndex = findPositionForStack(toTop ? mChildren.size() : 0, stack, 4244 true /* adding */); 4245 addChild(stack, addIndex); 4246 setLayoutNeeded(); 4247 } 4248 4249 @Override removeChild(TaskStack stack)4250 protected void removeChild(TaskStack stack) { 4251 super.removeChild(stack); 4252 removeStackReferenceIfNeeded(stack); 4253 } 4254 4255 @Override isOnTop()4256 boolean isOnTop() { 4257 // Considered always on top 4258 return true; 4259 } 4260 4261 @Override positionChildAt(int position, TaskStack child, boolean includingParents)4262 void positionChildAt(int position, TaskStack child, boolean includingParents) { 4263 if (child.getWindowConfiguration().isAlwaysOnTop() 4264 && position != POSITION_TOP) { 4265 // This stack is always-on-top, override the default behavior. 4266 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom"); 4267 4268 // Moving to its current position, as we must call super but we don't want to 4269 // perform any meaningful action. 4270 final int currentPosition = mChildren.indexOf(child); 4271 super.positionChildAt(currentPosition, child, false /* includingParents */); 4272 return; 4273 } 4274 4275 final int targetPosition = findPositionForStack(position, child, false /* adding */); 4276 super.positionChildAt(targetPosition, child, includingParents); 4277 4278 if (includingParents) { 4279 // We still want to move the display of this stack container to top because even the 4280 // target position is adjusted to non-top, the intention of the condition is to have 4281 // higher z-order to gain focus (e.g. moving a task of a fullscreen stack to front 4282 // in a non-top display which is using picture-in-picture mode). 4283 final int topChildPosition = getChildCount() - 1; 4284 if (targetPosition < topChildPosition && position >= topChildPosition) { 4285 getParent().positionChildAt(POSITION_TOP, this /* child */, 4286 true /* includingParents */); 4287 } 4288 } 4289 4290 setLayoutNeeded(); 4291 } 4292 4293 /** 4294 * When stack is added or repositioned, find a proper position for it. 4295 * This will make sure that pinned stack always stays on top. 4296 * @param requestedPosition Position requested by caller. 4297 * @param stack Stack to be added or positioned. 4298 * @param adding Flag indicates whether we're adding a new stack or positioning an existing. 4299 * @return The proper position for the stack. 4300 */ findPositionForStack(int requestedPosition, TaskStack stack, boolean adding)4301 private int findPositionForStack(int requestedPosition, TaskStack stack, boolean adding) { 4302 if (stack.inPinnedWindowingMode()) { 4303 return POSITION_TOP; 4304 } 4305 4306 final int topChildPosition = mChildren.size() - 1; 4307 int belowAlwaysOnTopPosition = POSITION_BOTTOM; 4308 for (int i = topChildPosition; i >= 0; --i) { 4309 if (getStacks().get(i) != stack && !getStacks().get(i).isAlwaysOnTop()) { 4310 belowAlwaysOnTopPosition = i; 4311 break; 4312 } 4313 } 4314 4315 // The max possible position we can insert the stack at. 4316 int maxPosition = POSITION_TOP; 4317 // The min possible position we can insert the stack at. 4318 int minPosition = POSITION_BOTTOM; 4319 4320 if (stack.isAlwaysOnTop()) { 4321 if (hasPinnedStack()) { 4322 // Always-on-top stacks go below the pinned stack. 4323 maxPosition = getStacks().indexOf(mPinnedStack) - 1; 4324 } 4325 // Always-on-top stacks need to be above all other stacks. 4326 minPosition = belowAlwaysOnTopPosition != 4327 POSITION_BOTTOM ? belowAlwaysOnTopPosition : topChildPosition; 4328 } else { 4329 // Other stacks need to be below the always-on-top stacks. 4330 maxPosition = belowAlwaysOnTopPosition != 4331 POSITION_BOTTOM ? belowAlwaysOnTopPosition : 0; 4332 } 4333 4334 int targetPosition = requestedPosition; 4335 targetPosition = Math.min(targetPosition, maxPosition); 4336 targetPosition = Math.max(targetPosition, minPosition); 4337 4338 int prevPosition = getStacks().indexOf(stack); 4339 // The positions we calculated above (maxPosition, minPosition) do not take into 4340 // consideration the following edge cases. 4341 // 1) We need to adjust the position depending on the value "adding". 4342 // 2) When we are moving a stack to another position, we also need to adjust the 4343 // position depending on whether the stack is moving to a higher or lower position. 4344 if ((targetPosition != requestedPosition) && 4345 (adding || targetPosition < prevPosition)) { 4346 targetPosition++; 4347 } 4348 4349 return targetPosition; 4350 } 4351 4352 @Override forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4353 boolean forAllWindows(ToBooleanFunction<WindowState> callback, 4354 boolean traverseTopToBottom) { 4355 if (traverseTopToBottom) { 4356 if (super.forAllWindows(callback, traverseTopToBottom)) { 4357 return true; 4358 } 4359 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) { 4360 return true; 4361 } 4362 } else { 4363 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) { 4364 return true; 4365 } 4366 if (super.forAllWindows(callback, traverseTopToBottom)) { 4367 return true; 4368 } 4369 } 4370 return false; 4371 } 4372 forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4373 private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, 4374 boolean traverseTopToBottom) { 4375 // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the 4376 // app tokens. 4377 // TODO: Investigate if we need to continue to do this or if we can just process them 4378 // in-order. 4379 if (traverseTopToBottom) { 4380 for (int i = mChildren.size() - 1; i >= 0; --i) { 4381 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 4382 for (int j = appTokens.size() - 1; j >= 0; --j) { 4383 if (appTokens.get(j).forAllWindowsUnchecked(callback, 4384 traverseTopToBottom)) { 4385 return true; 4386 } 4387 } 4388 } 4389 } else { 4390 final int count = mChildren.size(); 4391 for (int i = 0; i < count; ++i) { 4392 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 4393 final int appTokensCount = appTokens.size(); 4394 for (int j = 0; j < appTokensCount; j++) { 4395 if (appTokens.get(j).forAllWindowsUnchecked(callback, 4396 traverseTopToBottom)) { 4397 return true; 4398 } 4399 } 4400 } 4401 } 4402 return false; 4403 } 4404 setExitingTokensHasVisible(boolean hasVisible)4405 void setExitingTokensHasVisible(boolean hasVisible) { 4406 for (int i = mChildren.size() - 1; i >= 0; --i) { 4407 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 4408 for (int j = appTokens.size() - 1; j >= 0; --j) { 4409 appTokens.get(j).hasVisible = hasVisible; 4410 } 4411 } 4412 } 4413 removeExistingAppTokensIfPossible()4414 void removeExistingAppTokensIfPossible() { 4415 for (int i = mChildren.size() - 1; i >= 0; --i) { 4416 final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens; 4417 for (int j = appTokens.size() - 1; j >= 0; --j) { 4418 final AppWindowToken token = appTokens.get(j); 4419 if (!token.hasVisible && !mClosingApps.contains(token) 4420 && (!token.mIsExiting || token.isEmpty())) { 4421 // Make sure there is no animation running on this token, so any windows 4422 // associated with it will be removed as soon as their animations are 4423 // complete. 4424 cancelAnimation(); 4425 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4426 "performLayout: App token exiting now removed" + token); 4427 token.removeIfPossible(); 4428 } 4429 } 4430 } 4431 } 4432 4433 @Override getOrientation()4434 int getOrientation() { 4435 if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) 4436 || isStackVisible(WINDOWING_MODE_FREEFORM)) { 4437 // Apps and their containers are not allowed to specify an orientation while the 4438 // docked or freeform stack is visible...except for the home stack if the docked 4439 // stack is minimized and it actually set something and the bounds is different from 4440 // the display. 4441 if (mHomeStack != null && mHomeStack.isVisible() 4442 && mDividerControllerLocked.isMinimizedDock() 4443 && !(mDividerControllerLocked.isHomeStackResizable() 4444 && mHomeStack.matchParentBounds())) { 4445 final int orientation = mHomeStack.getOrientation(); 4446 if (orientation != SCREEN_ORIENTATION_UNSET) { 4447 return orientation; 4448 } 4449 } 4450 return SCREEN_ORIENTATION_UNSPECIFIED; 4451 } 4452 4453 final int orientation = super.getOrientation(); 4454 boolean isCar = mWmService.mContext.getPackageManager().hasSystemFeature( 4455 PackageManager.FEATURE_AUTOMOTIVE); 4456 if (isCar) { 4457 // In a car, you cannot physically rotate the screen, so it doesn't make sense to 4458 // allow anything but the default orientation. 4459 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 4460 "Forcing UNSPECIFIED orientation in car for display id=" + mDisplayId 4461 + ". Ignoring " + orientation); 4462 return SCREEN_ORIENTATION_UNSPECIFIED; 4463 } 4464 4465 if (orientation != SCREEN_ORIENTATION_UNSET 4466 && orientation != SCREEN_ORIENTATION_BEHIND) { 4467 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 4468 "App is requesting an orientation, return " + orientation 4469 + " for display id=" + mDisplayId); 4470 return orientation; 4471 } 4472 4473 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 4474 "No app is requesting an orientation, return " + mLastOrientation 4475 + " for display id=" + mDisplayId); 4476 // The next app has not been requested to be visible, so we keep the current orientation 4477 // to prevent freezing/unfreezing the display too early. 4478 return mLastOrientation; 4479 } 4480 4481 @Override assignChildLayers(SurfaceControl.Transaction t)4482 void assignChildLayers(SurfaceControl.Transaction t) { 4483 assignStackOrdering(t); 4484 4485 for (int i = 0; i < mChildren.size(); i++) { 4486 final TaskStack s = mChildren.get(i); 4487 s.assignChildLayers(t); 4488 } 4489 } 4490 assignStackOrdering(SurfaceControl.Transaction t)4491 void assignStackOrdering(SurfaceControl.Transaction t) { 4492 4493 final int HOME_STACK_STATE = 0; 4494 final int NORMAL_STACK_STATE = 1; 4495 final int ALWAYS_ON_TOP_STATE = 2; 4496 4497 int layer = 0; 4498 int layerForAnimationLayer = 0; 4499 int layerForBoostedAnimationLayer = 0; 4500 int layerForHomeAnimationLayer = 0; 4501 4502 for (int state = 0; state <= ALWAYS_ON_TOP_STATE; state++) { 4503 for (int i = 0; i < mChildren.size(); i++) { 4504 final TaskStack s = mChildren.get(i); 4505 if (state == HOME_STACK_STATE && !s.isActivityTypeHome()) { 4506 continue; 4507 } else if (state == NORMAL_STACK_STATE && (s.isActivityTypeHome() 4508 || s.isAlwaysOnTop())) { 4509 continue; 4510 } else if (state == ALWAYS_ON_TOP_STATE && !s.isAlwaysOnTop()) { 4511 continue; 4512 } 4513 s.assignLayer(t, layer++); 4514 if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) { 4515 t.setLayer(mSplitScreenDividerAnchor, layer++); 4516 } 4517 if ((s.isTaskAnimating() || s.isAppAnimating()) 4518 && state != ALWAYS_ON_TOP_STATE) { 4519 // Ensure the animation layer ends up above the 4520 // highest animating stack and no higher. 4521 layerForAnimationLayer = layer++; 4522 } 4523 if (state != ALWAYS_ON_TOP_STATE) { 4524 layerForBoostedAnimationLayer = layer++; 4525 } 4526 } 4527 if (state == HOME_STACK_STATE) { 4528 layerForHomeAnimationLayer = layer++; 4529 } 4530 } 4531 if (mAppAnimationLayer != null) { 4532 t.setLayer(mAppAnimationLayer, layerForAnimationLayer); 4533 } 4534 if (mBoostedAppAnimationLayer != null) { 4535 t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer); 4536 } 4537 if (mHomeAppAnimationLayer != null) { 4538 t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer); 4539 } 4540 } 4541 4542 @Override getAppAnimationLayer(@nimationLayer int animationLayer)4543 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) { 4544 switch (animationLayer) { 4545 case ANIMATION_LAYER_BOOSTED: 4546 return mBoostedAppAnimationLayer; 4547 case ANIMATION_LAYER_HOME: 4548 return mHomeAppAnimationLayer; 4549 case ANIMATION_LAYER_STANDARD: 4550 default: 4551 return mAppAnimationLayer; 4552 } 4553 } 4554 getSplitScreenDividerAnchor()4555 SurfaceControl getSplitScreenDividerAnchor() { 4556 return mSplitScreenDividerAnchor; 4557 } 4558 4559 @Override onParentChanged()4560 void onParentChanged() { 4561 super.onParentChanged(); 4562 if (getParent() != null) { 4563 mAppAnimationLayer = makeChildSurface(null) 4564 .setName("animationLayer") 4565 .build(); 4566 mBoostedAppAnimationLayer = makeChildSurface(null) 4567 .setName("boostedAnimationLayer") 4568 .build(); 4569 mHomeAppAnimationLayer = makeChildSurface(null) 4570 .setName("homeAnimationLayer") 4571 .build(); 4572 mSplitScreenDividerAnchor = makeChildSurface(null) 4573 .setName("splitScreenDividerAnchor") 4574 .build(); 4575 getPendingTransaction() 4576 .show(mAppAnimationLayer) 4577 .show(mBoostedAppAnimationLayer) 4578 .show(mHomeAppAnimationLayer) 4579 .show(mSplitScreenDividerAnchor); 4580 scheduleAnimation(); 4581 } else { 4582 mAppAnimationLayer.remove(); 4583 mAppAnimationLayer = null; 4584 mBoostedAppAnimationLayer.remove(); 4585 mBoostedAppAnimationLayer = null; 4586 mHomeAppAnimationLayer.remove(); 4587 mHomeAppAnimationLayer = null; 4588 mSplitScreenDividerAnchor.remove(); 4589 mSplitScreenDividerAnchor = null; 4590 } 4591 } 4592 } 4593 4594 private final class AboveAppWindowContainers extends NonAppWindowContainers { AboveAppWindowContainers(String name, WindowManagerService service)4595 AboveAppWindowContainers(String name, WindowManagerService service) { 4596 super(name, service); 4597 } 4598 4599 @Override makeChildSurface(WindowContainer child)4600 SurfaceControl.Builder makeChildSurface(WindowContainer child) { 4601 final SurfaceControl.Builder builder = super.makeChildSurface(child); 4602 if (child instanceof WindowToken && ((WindowToken) child).mRoundedCornerOverlay) { 4603 // To draw above the ColorFade layer during the screen off transition, the 4604 // rounded corner overlays need to be at the root of the surface hierarchy. 4605 // TODO: move the ColorLayer into the display overlay layer such that this is not 4606 // necessary anymore. 4607 builder.setParent(null); 4608 } 4609 return builder; 4610 } 4611 4612 @Override assignChildLayers(SurfaceControl.Transaction t)4613 void assignChildLayers(SurfaceControl.Transaction t) { 4614 assignChildLayers(t, null /* imeContainer */); 4615 } 4616 assignChildLayers(SurfaceControl.Transaction t, WindowContainer imeContainer)4617 void assignChildLayers(SurfaceControl.Transaction t, WindowContainer imeContainer) { 4618 boolean needAssignIme = imeContainer != null 4619 && imeContainer.getSurfaceControl() != null; 4620 for (int j = 0; j < mChildren.size(); ++j) { 4621 final WindowToken wt = mChildren.get(j); 4622 4623 // See {@link mSplitScreenDividerAnchor} 4624 if (wt.windowType == TYPE_DOCK_DIVIDER) { 4625 wt.assignRelativeLayer(t, mTaskStackContainers.getSplitScreenDividerAnchor(), 1); 4626 continue; 4627 } 4628 if (wt.mRoundedCornerOverlay) { 4629 wt.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1); 4630 continue; 4631 } 4632 wt.assignLayer(t, j); 4633 wt.assignChildLayers(t); 4634 4635 int layer = mWmService.mPolicy.getWindowLayerFromTypeLw( 4636 wt.windowType, wt.mOwnerCanManageAppTokens); 4637 4638 if (needAssignIme && layer >= mWmService.mPolicy.getWindowLayerFromTypeLw( 4639 TYPE_INPUT_METHOD_DIALOG, true)) { 4640 imeContainer.assignRelativeLayer(t, wt.getSurfaceControl(), -1); 4641 needAssignIme = false; 4642 } 4643 } 4644 if (needAssignIme) { 4645 imeContainer.assignRelativeLayer(t, getSurfaceControl(), Integer.MAX_VALUE); 4646 } 4647 } 4648 } 4649 4650 /** 4651 * Window container class that contains all containers on this display that are not related to 4652 * Apps. E.g. status bar. 4653 */ 4654 private class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> { 4655 /** 4656 * Compares two child window tokens returns -1 if the first is lesser than the second in 4657 * terms of z-order and 1 otherwise. 4658 */ 4659 private final Comparator<WindowToken> mWindowComparator = (token1, token2) -> 4660 // Tokens with higher base layer are z-ordered on-top. 4661 mWmService.mPolicy.getWindowLayerFromTypeLw(token1.windowType, 4662 token1.mOwnerCanManageAppTokens) 4663 < mWmService.mPolicy.getWindowLayerFromTypeLw(token2.windowType, 4664 token2.mOwnerCanManageAppTokens) ? -1 : 1; 4665 4666 private final Predicate<WindowState> mGetOrientingWindow = w -> { 4667 if (!w.isVisibleLw() || !w.mLegacyPolicyVisibilityAfterAnim) { 4668 return false; 4669 } 4670 final int req = w.mAttrs.screenOrientation; 4671 if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND 4672 || req == SCREEN_ORIENTATION_UNSET) { 4673 return false; 4674 } 4675 return true; 4676 }; 4677 4678 private final String mName; 4679 private final Dimmer mDimmer = new Dimmer(this); 4680 private final Rect mTmpDimBoundsRect = new Rect(); 4681 NonAppWindowContainers(String name, WindowManagerService service)4682 NonAppWindowContainers(String name, WindowManagerService service) { 4683 super(service); 4684 mName = name; 4685 } 4686 addChild(WindowToken token)4687 void addChild(WindowToken token) { 4688 addChild(token, mWindowComparator); 4689 } 4690 4691 @Override getOrientation()4692 int getOrientation() { 4693 final WindowManagerPolicy policy = mWmService.mPolicy; 4694 // Find a window requesting orientation. 4695 final WindowState win = getWindow(mGetOrientingWindow); 4696 4697 if (win != null) { 4698 final int req = win.mAttrs.screenOrientation; 4699 if (policy.isKeyguardHostWindow(win.mAttrs)) { 4700 mLastKeyguardForcedOrientation = req; 4701 if (mWmService.mKeyguardGoingAway) { 4702 // Keyguard can't affect the orientation if it is going away... 4703 mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 4704 return SCREEN_ORIENTATION_UNSET; 4705 } 4706 } 4707 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req 4708 + " for display id=" + mDisplayId); 4709 return (mLastWindowForcedOrientation = req); 4710 } 4711 4712 mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 4713 4714 // Only allow force setting the orientation when all unknown visibilities have been 4715 // resolved, as otherwise we just may be starting another occluding activity. 4716 final boolean isUnoccluding = 4717 mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE 4718 && mUnknownAppVisibilityController.allResolved(); 4719 if (policy.isKeyguardShowingAndNotOccluded() || isUnoccluding) { 4720 return mLastKeyguardForcedOrientation; 4721 } 4722 4723 return SCREEN_ORIENTATION_UNSET; 4724 } 4725 4726 @Override getName()4727 String getName() { 4728 return mName; 4729 } 4730 4731 @Override getDimmer()4732 Dimmer getDimmer() { 4733 return mDimmer; 4734 } 4735 4736 @Override prepareSurfaces()4737 void prepareSurfaces() { 4738 mDimmer.resetDimStates(); 4739 super.prepareSurfaces(); 4740 getBounds(mTmpDimBoundsRect); 4741 4742 if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) { 4743 scheduleAnimation(); 4744 } 4745 } 4746 } 4747 makeSurface(SurfaceSession s)4748 SurfaceControl.Builder makeSurface(SurfaceSession s) { 4749 return mWmService.makeSurfaceBuilder(s) 4750 .setParent(mWindowingLayer); 4751 } 4752 4753 @Override getSession()4754 SurfaceSession getSession() { 4755 return mSession; 4756 } 4757 4758 @Override makeChildSurface(WindowContainer child)4759 SurfaceControl.Builder makeChildSurface(WindowContainer child) { 4760 SurfaceSession s = child != null ? child.getSession() : getSession(); 4761 final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer(); 4762 if (child == null) { 4763 return b; 4764 } 4765 4766 return b.setName(child.getName()) 4767 .setParent(mWindowingLayer); 4768 } 4769 4770 /** 4771 * The makeSurface variants are for use by the window-container 4772 * hierarchy. makeOverlay here is a function for various non windowing 4773 * overlays like the ScreenRotation screenshot, the Strict Mode Flash 4774 * and other potpourii. 4775 */ makeOverlay()4776 SurfaceControl.Builder makeOverlay() { 4777 return mWmService.makeSurfaceBuilder(mSession) 4778 .setParent(mOverlayLayer); 4779 } 4780 4781 /** 4782 * Reparents the given surface to mOverlayLayer. 4783 */ reparentToOverlay(Transaction transaction, SurfaceControl surface)4784 void reparentToOverlay(Transaction transaction, SurfaceControl surface) { 4785 transaction.reparent(surface, mOverlayLayer); 4786 } 4787 applyMagnificationSpec(MagnificationSpec spec)4788 void applyMagnificationSpec(MagnificationSpec spec) { 4789 if (spec.scale != 1.0) { 4790 mMagnificationSpec = spec; 4791 } else { 4792 mMagnificationSpec = null; 4793 } 4794 // Re-parent IME's SurfaceControl when MagnificationSpec changed. 4795 updateImeParent(); 4796 4797 applyMagnificationSpec(getPendingTransaction(), spec); 4798 getPendingTransaction().apply(); 4799 } 4800 reapplyMagnificationSpec()4801 void reapplyMagnificationSpec() { 4802 if (mMagnificationSpec != null) { 4803 applyMagnificationSpec(getPendingTransaction(), mMagnificationSpec); 4804 } 4805 } 4806 4807 @Override onParentChanged()4808 void onParentChanged() { 4809 // Since we are the top of the SurfaceControl hierarchy here 4810 // we create the root surfaces explicitly rather than chaining 4811 // up as the default implementation in onParentChanged does. So we 4812 // explicitly do NOT call super here. 4813 } 4814 4815 @Override assignChildLayers(SurfaceControl.Transaction t)4816 void assignChildLayers(SurfaceControl.Transaction t) { 4817 4818 // These are layers as children of "mWindowingLayer" 4819 mBelowAppWindowsContainers.assignLayer(t, 0); 4820 mTaskStackContainers.assignLayer(t, 1); 4821 mAboveAppWindowsContainers.assignLayer(t, 2); 4822 4823 final WindowState imeTarget = mInputMethodTarget; 4824 boolean needAssignIme = true; 4825 4826 // In the case where we have an IME target that is not in split-screen 4827 // mode IME assignment is easy. We just need the IME to go directly above 4828 // the target. This way children of the target will naturally go above the IME 4829 // and everyone is happy. 4830 // 4831 // In the case of split-screen windowing mode, we need to elevate the IME above the 4832 // docked divider while keeping the app itself below the docked divider, so instead 4833 // we use relative layering of the IME targets child windows, and place the 4834 // IME in the non-app layer (see {@link AboveAppWindowContainers#assignChildLayers}). 4835 // 4836 // In the case the IME target is animating, the animation Z order may be different 4837 // than the WindowContainer Z order, so it's difficult to be sure we have the correct 4838 // IME target. In this case we just layer the IME over all transitions by placing it in the 4839 // above applications layer. 4840 // 4841 // In the case where we have no IME target we assign it where it's base layer would 4842 // place it in the AboveAppWindowContainers. 4843 if (imeTarget != null && !(imeTarget.inSplitScreenWindowingMode() 4844 || imeTarget.mToken.isAppAnimating()) 4845 && (imeTarget.getSurfaceControl() != null)) { 4846 mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(), 4847 // TODO: We need to use an extra level on the app surface to ensure 4848 // this is always above SurfaceView but always below attached window. 4849 1); 4850 needAssignIme = false; 4851 } 4852 4853 // Above we have assigned layers to our children, now we ask them to assign 4854 // layers to their children. 4855 mBelowAppWindowsContainers.assignChildLayers(t); 4856 mTaskStackContainers.assignChildLayers(t); 4857 mAboveAppWindowsContainers.assignChildLayers(t, 4858 needAssignIme == true ? mImeWindowsContainers : null); 4859 mImeWindowsContainers.assignChildLayers(t); 4860 } 4861 4862 /** 4863 * Here we satisfy an unfortunate special case of the IME in split-screen mode. Imagine 4864 * that the IME target is one of the docked applications. We'd like the docked divider to be 4865 * above both of the applications, and we'd like the IME to be above the docked divider. 4866 * However we need child windows of the applications to be above the IME (Text drag handles). 4867 * This is a non-strictly hierarcical layering and we need to break out of the Z ordering 4868 * somehow. We do this by relatively ordering children of the target to the IME in cooperation 4869 * with {@link WindowState#assignLayer} 4870 */ assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child)4871 void assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child) { 4872 child.assignRelativeLayer(t, mImeWindowsContainers.getSurfaceControl(), 1); 4873 } 4874 4875 @Override prepareSurfaces()4876 void prepareSurfaces() { 4877 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareSurfaces"); 4878 try { 4879 final ScreenRotationAnimation screenRotationAnimation = 4880 mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); 4881 final Transaction transaction = getPendingTransaction(); 4882 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 4883 screenRotationAnimation.getEnterTransformation().getMatrix().getValues(mTmpFloats); 4884 transaction.setMatrix(mWindowingLayer, 4885 mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y], 4886 mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]); 4887 transaction.setPosition(mWindowingLayer, 4888 mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]); 4889 transaction.setAlpha(mWindowingLayer, 4890 screenRotationAnimation.getEnterTransformation().getAlpha()); 4891 } 4892 4893 super.prepareSurfaces(); 4894 4895 // TODO: Once we totally eliminate global transaction we will pass transaction in here 4896 // rather than merging to global. 4897 SurfaceControl.mergeToGlobalTransaction(transaction); 4898 } finally { 4899 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4900 } 4901 } 4902 assignStackOrdering()4903 void assignStackOrdering() { 4904 mTaskStackContainers.assignStackOrdering(getPendingTransaction()); 4905 } 4906 4907 /** 4908 * Increment the deferral count to determine whether to update the IME target. 4909 */ deferUpdateImeTarget()4910 void deferUpdateImeTarget() { 4911 mDeferUpdateImeTargetCount++; 4912 } 4913 4914 /** 4915 * Decrement the deferral count to determine whether to update the IME target. If the count 4916 * reaches 0, a new ime target will get computed. 4917 */ continueUpdateImeTarget()4918 void continueUpdateImeTarget() { 4919 if (mDeferUpdateImeTargetCount == 0) { 4920 return; 4921 } 4922 4923 mDeferUpdateImeTargetCount--; 4924 if (mDeferUpdateImeTargetCount == 0) { 4925 computeImeTarget(true /* updateImeTarget */); 4926 } 4927 } 4928 4929 /** 4930 * @return Whether a new IME target should be computed. 4931 */ canUpdateImeTarget()4932 private boolean canUpdateImeTarget() { 4933 return mDeferUpdateImeTargetCount == 0; 4934 } 4935 getInputMonitor()4936 InputMonitor getInputMonitor() { 4937 return mInputMonitor; 4938 } 4939 4940 /** 4941 * @return Cached value whether we told display manager that we have content. 4942 */ getLastHasContent()4943 boolean getLastHasContent() { 4944 return mLastHasContent; 4945 } 4946 registerPointerEventListener(@onNull PointerEventListener listener)4947 void registerPointerEventListener(@NonNull PointerEventListener listener) { 4948 mPointerEventDispatcher.registerInputEventListener(listener); 4949 } 4950 unregisterPointerEventListener(@onNull PointerEventListener listener)4951 void unregisterPointerEventListener(@NonNull PointerEventListener listener) { 4952 mPointerEventDispatcher.unregisterInputEventListener(listener); 4953 } 4954 prepareAppTransition(@indowManager.TransitionType int transit, boolean alwaysKeepCurrent)4955 void prepareAppTransition(@WindowManager.TransitionType int transit, 4956 boolean alwaysKeepCurrent) { 4957 prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */); 4958 } 4959 prepareAppTransition(@indowManager.TransitionType int transit, boolean alwaysKeepCurrent, @WindowManager.TransitionFlags int flags, boolean forceOverride)4960 void prepareAppTransition(@WindowManager.TransitionType int transit, 4961 boolean alwaysKeepCurrent, @WindowManager.TransitionFlags int flags, 4962 boolean forceOverride) { 4963 final boolean prepared = mAppTransition.prepareAppTransitionLocked( 4964 transit, alwaysKeepCurrent, flags, forceOverride); 4965 if (prepared && okToAnimate()) { 4966 mSkipAppTransitionAnimation = false; 4967 } 4968 } 4969 executeAppTransition()4970 void executeAppTransition() { 4971 if (mAppTransition.isTransitionSet()) { 4972 if (DEBUG_APP_TRANSITIONS) { 4973 Slog.w(TAG_WM, "Execute app transition: " + mAppTransition + ", displayId: " 4974 + mDisplayId + " Callers=" + Debug.getCallers(5)); 4975 } 4976 mAppTransition.setReady(); 4977 mWmService.mWindowPlacerLocked.requestTraversal(); 4978 } 4979 } 4980 4981 /** 4982 * Update pendingLayoutChanges after app transition has finished. 4983 */ handleAnimatingStoppedAndTransition()4984 void handleAnimatingStoppedAndTransition() { 4985 int changes = 0; 4986 4987 mAppTransition.setIdle(); 4988 4989 for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) { 4990 final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i); 4991 mAppTransition.notifyAppTransitionFinishedLocked(token); 4992 } 4993 mNoAnimationNotifyOnTransitionFinished.clear(); 4994 4995 mWallpaperController.hideDeferredWallpapersIfNeeded(); 4996 4997 onAppTransitionDone(); 4998 4999 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5000 if (DEBUG_WALLPAPER_LIGHT) { 5001 Slog.v(TAG_WM, "Wallpaper layer changed: assigning layers + relayout"); 5002 } 5003 computeImeTarget(true /* updateImeTarget */); 5004 mWallpaperMayChange = true; 5005 // Since the window list has been rebuilt, focus might have to be recomputed since the 5006 // actual order of windows might have changed again. 5007 mWmService.mFocusMayChange = true; 5008 5009 pendingLayoutChanges |= changes; 5010 } 5011 5012 /** Check if pending app transition is for activity / task launch. */ isNextTransitionForward()5013 boolean isNextTransitionForward() { 5014 final int transit = mAppTransition.getAppTransition(); 5015 return transit == TRANSIT_ACTIVITY_OPEN 5016 || transit == TRANSIT_TASK_OPEN 5017 || transit == TRANSIT_TASK_TO_FRONT; 5018 } 5019 5020 /** 5021 * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 5022 */ supportsSystemDecorations()5023 boolean supportsSystemDecorations() { 5024 return (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this) 5025 || (mDisplay.getFlags() & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0 5026 || (mWmService.mForceDesktopModeOnExternalDisplays && !isUntrustedVirtualDisplay())) 5027 // VR virtual display will be used to run and render 2D app within a VR experience. 5028 && mDisplayId != mWmService.mVr2dDisplayId; 5029 } 5030 5031 /** 5032 * @return {@code true} if the display is non-system created virtual display. 5033 */ isUntrustedVirtualDisplay()5034 boolean isUntrustedVirtualDisplay() { 5035 return mDisplay.getType() == Display.TYPE_VIRTUAL 5036 && mDisplay.getOwnerUid() != Process.SYSTEM_UID; 5037 } 5038 5039 /** 5040 * Re-parent the DisplayContent's top surfaces, {@link #mWindowingLayer} and 5041 * {@link #mOverlayLayer} to the specified SurfaceControl. 5042 * 5043 * @param win The window which owns the SurfaceControl. This indicates the z-order of the 5044 * windows of this display against the windows on the parent display. 5045 * @param sc The new SurfaceControl, where the DisplayContent's surfaces will be re-parented to. 5046 */ reparentDisplayContent(WindowState win, SurfaceControl sc)5047 void reparentDisplayContent(WindowState win, SurfaceControl sc) { 5048 mParentWindow = win; 5049 mParentSurfaceControl = sc; 5050 if (mPortalWindowHandle == null) { 5051 mPortalWindowHandle = createPortalWindowHandle(sc.toString()); 5052 } 5053 getPendingTransaction().setInputWindowInfo(sc, mPortalWindowHandle) 5054 .reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc); 5055 } 5056 5057 /** 5058 * Get the window which owns the surface that this DisplayContent is re-parented to. 5059 * 5060 * @return the parent window. 5061 */ getParentWindow()5062 WindowState getParentWindow() { 5063 return mParentWindow; 5064 } 5065 5066 /** 5067 * Update the location of this display in the parent window. This enables windows in this 5068 * display to compute the global transformation matrix. 5069 * 5070 * @param win The parent window of this display. 5071 * @param x The x coordinate in the parent window. 5072 * @param y The y coordinate in the parent window. 5073 */ updateLocation(WindowState win, int x, int y)5074 void updateLocation(WindowState win, int x, int y) { 5075 if (mParentWindow != win) { 5076 throw new IllegalArgumentException( 5077 "The given window is not the parent window of this display."); 5078 } 5079 if (mLocationInParentWindow.x != x || mLocationInParentWindow.y != y) { 5080 mLocationInParentWindow.x = x; 5081 mLocationInParentWindow.y = y; 5082 if (mWmService.mAccessibilityController != null) { 5083 mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 5084 } 5085 } 5086 } 5087 getLocationInParentWindow()5088 Point getLocationInParentWindow() { 5089 return mLocationInParentWindow; 5090 } 5091 5092 @VisibleForTesting getWindowingLayer()5093 SurfaceControl getWindowingLayer() { 5094 return mWindowingLayer; 5095 } 5096 5097 /** 5098 * Updates the display's system gesture exclusion. 5099 * 5100 * @return true, if the exclusion changed. 5101 */ updateSystemGestureExclusion()5102 boolean updateSystemGestureExclusion() { 5103 if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 0) { 5104 // No one's interested anyways. 5105 return false; 5106 } 5107 5108 final Region systemGestureExclusion = calculateSystemGestureExclusion(); 5109 try { 5110 if (mSystemGestureExclusion.equals(systemGestureExclusion)) { 5111 return false; 5112 } 5113 mSystemGestureExclusion.set(systemGestureExclusion); 5114 for (int i = mSystemGestureExclusionListeners.beginBroadcast() - 1; i >= 0; --i) { 5115 try { 5116 mSystemGestureExclusionListeners.getBroadcastItem(i) 5117 .onSystemGestureExclusionChanged(mDisplayId, systemGestureExclusion); 5118 } catch (RemoteException e) { 5119 Slog.e(TAG, "Failed to notify SystemGestureExclusionListener", e); 5120 } 5121 } 5122 mSystemGestureExclusionListeners.finishBroadcast(); 5123 return true; 5124 } finally { 5125 systemGestureExclusion.recycle(); 5126 } 5127 } 5128 5129 @VisibleForTesting calculateSystemGestureExclusion()5130 Region calculateSystemGestureExclusion() { 5131 final Region unhandled = Region.obtain(); 5132 unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight); 5133 5134 final Rect leftEdge = mInsetsStateController.getSourceProvider(TYPE_LEFT_GESTURES) 5135 .getSource().getFrame(); 5136 final Rect rightEdge = mInsetsStateController.getSourceProvider(TYPE_RIGHT_GESTURES) 5137 .getSource().getFrame(); 5138 5139 final Region global = Region.obtain(); 5140 final Region touchableRegion = Region.obtain(); 5141 final Region local = Region.obtain(); 5142 final int[] remainingLeftRight = 5143 {mSystemGestureExclusionLimit, mSystemGestureExclusionLimit}; 5144 5145 // Traverse all windows top down to assemble the gesture exclusion rects. 5146 // For each window, we only take the rects that fall within its touchable region. 5147 forAllWindows(w -> { 5148 if (w.cantReceiveTouchInput() || !w.isVisible() 5149 || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0 5150 || unhandled.isEmpty()) { 5151 return; 5152 } 5153 5154 // Get the touchable region of the window, and intersect with where the screen is still 5155 // touchable, i.e. touchable regions on top are not covering it yet. 5156 w.getEffectiveTouchableRegion(touchableRegion); 5157 touchableRegion.op(unhandled, Op.INTERSECT); 5158 5159 if (w.isImplicitlyExcludingAllSystemGestures()) { 5160 local.set(touchableRegion); 5161 } else { 5162 rectListToRegion(w.getSystemGestureExclusion(), local); 5163 5164 // Transform to display coordinates 5165 local.scale(w.mGlobalScale); 5166 final Rect frame = w.getWindowFrames().mFrame; 5167 local.translate(frame.left, frame.top); 5168 5169 // A window can only exclude system gestures where it is actually touchable 5170 local.op(touchableRegion, Op.INTERSECT); 5171 } 5172 5173 // Apply restriction if necessary. 5174 if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) { 5175 5176 // Processes the region along the left edge. 5177 remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, global, leftEdge, 5178 remainingLeftRight[0]); 5179 5180 // Processes the region along the right edge. 5181 remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, global, rightEdge, 5182 remainingLeftRight[1]); 5183 5184 // Adds the middle (unrestricted area) 5185 final Region middle = Region.obtain(local); 5186 middle.op(leftEdge, Op.DIFFERENCE); 5187 middle.op(rightEdge, Op.DIFFERENCE); 5188 global.op(middle, Op.UNION); 5189 middle.recycle(); 5190 } else { 5191 global.op(local, Op.UNION); 5192 } 5193 unhandled.op(touchableRegion, Op.DIFFERENCE); 5194 }, true /* topToBottom */); 5195 local.recycle(); 5196 touchableRegion.recycle(); 5197 unhandled.recycle(); 5198 return global; 5199 } 5200 5201 /** 5202 * @return Whether gesture exclusion area should be restricted from the window depending on the 5203 * current SystemUI visibility flags. 5204 */ needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility)5205 private static boolean needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility) { 5206 final int type = win.mAttrs.type; 5207 final int stickyHideNavFlags = 5208 SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 5209 final boolean stickyHideNav = 5210 (sysUiVisibility & stickyHideNavFlags) == stickyHideNavFlags; 5211 return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_STATUS_BAR 5212 && win.getActivityType() != ACTIVITY_TYPE_HOME; 5213 } 5214 5215 /** 5216 * Adds a local gesture exclusion area to the global area while applying a limit per edge. 5217 * 5218 * @param local The gesture exclusion area to add. 5219 * @param global The destination. 5220 * @param edge Only processes the part in that region. 5221 * @param limit How much limit in pixels we have. 5222 * @return How much of the limit are remaining. 5223 */ addToGlobalAndConsumeLimit(Region local, Region global, Rect edge, int limit)5224 private static int addToGlobalAndConsumeLimit(Region local, Region global, Rect edge, 5225 int limit) { 5226 final Region r = Region.obtain(local); 5227 r.op(edge, Op.INTERSECT); 5228 5229 final int[] remaining = {limit}; 5230 forEachRectReverse(r, rect -> { 5231 if (remaining[0] <= 0) { 5232 return; 5233 } 5234 final int height = rect.height(); 5235 if (height > remaining[0]) { 5236 rect.top = rect.bottom - remaining[0]; 5237 } 5238 remaining[0] -= height; 5239 global.op(rect, Op.UNION); 5240 }); 5241 r.recycle(); 5242 return remaining[0]; 5243 } 5244 registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener)5245 void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) { 5246 mSystemGestureExclusionListeners.register(listener); 5247 final boolean changed; 5248 if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 1) { 5249 changed = updateSystemGestureExclusion(); 5250 } else { 5251 changed = false; 5252 } 5253 5254 if (!changed) { 5255 // If updateSystemGestureExclusion changed the exclusion, it will already have 5256 // notified the listener. Otherwise, we'll do it here. 5257 try { 5258 listener.onSystemGestureExclusionChanged(mDisplayId, mSystemGestureExclusion); 5259 } catch (RemoteException e) { 5260 Slog.e(TAG, "Failed to notify SystemGestureExclusionListener during register", e); 5261 } 5262 } 5263 } 5264 unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener)5265 void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener) { 5266 mSystemGestureExclusionListeners.unregister(listener); 5267 } 5268 5269 /** 5270 * Create a portal window handle for input. This window transports any touch to the display 5271 * indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window. 5272 * 5273 * @param name The name of the portal window handle. 5274 * @return the new portal window handle. 5275 */ createPortalWindowHandle(String name)5276 private InputWindowHandle createPortalWindowHandle(String name) { 5277 // Let surface flinger to set the display ID of this input window handle because we don't 5278 // know which display the parent surface control is on. 5279 final InputWindowHandle portalWindowHandle = new InputWindowHandle( 5280 null /* inputApplicationHandle */, null /* clientWindow */, INVALID_DISPLAY); 5281 portalWindowHandle.name = name; 5282 portalWindowHandle.token = new Binder(); 5283 portalWindowHandle.layoutParamsFlags = 5284 FLAG_SPLIT_TOUCH | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL; 5285 getBounds(mTmpBounds); 5286 portalWindowHandle.touchableRegion.set(mTmpBounds); 5287 portalWindowHandle.scaleFactor = 1f; 5288 portalWindowHandle.ownerPid = Process.myPid(); 5289 portalWindowHandle.ownerUid = Process.myUid(); 5290 portalWindowHandle.portalToDisplayId = mDisplayId; 5291 return portalWindowHandle; 5292 } 5293 5294 /** 5295 * @see IWindowManager#setForwardedInsets 5296 */ setForwardedInsets(Insets insets)5297 public void setForwardedInsets(Insets insets) { 5298 if (insets == null) { 5299 insets = Insets.NONE; 5300 } 5301 if (mDisplayPolicy.getForwardedInsets().equals(insets)) { 5302 return; 5303 } 5304 mDisplayPolicy.setForwardedInsets(insets); 5305 setLayoutNeeded(); 5306 mWmService.mWindowPlacerLocked.requestTraversal(); 5307 } 5308 getMetricsLogger()5309 protected MetricsLogger getMetricsLogger() { 5310 if (mMetricsLogger == null) { 5311 mMetricsLogger = new MetricsLogger(); 5312 } 5313 return mMetricsLogger; 5314 } 5315 } 5316