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