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.INVALID_TASK_ID; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; 23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 24 import static android.app.WindowConfiguration.ROTATION_UNDEFINED; 25 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 26 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 27 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; 28 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 29 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 30 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 31 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 32 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 33 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 34 import static android.content.res.Configuration.ORIENTATION_PORTRAIT; 35 import static android.content.res.Configuration.ORIENTATION_UNDEFINED; 36 import static android.os.Build.VERSION_CODES.N; 37 import static android.os.Process.SYSTEM_UID; 38 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 39 import static android.util.DisplayMetrics.DENSITY_DEFAULT; 40 import static android.util.RotationUtils.deltaRotation; 41 import static android.view.Display.DEFAULT_DISPLAY; 42 import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; 43 import static android.view.Display.FLAG_PRIVATE; 44 import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; 45 import static android.view.Display.INVALID_DISPLAY; 46 import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; 47 import static android.view.Display.STATE_UNKNOWN; 48 import static android.view.Display.isSuspendedState; 49 import static android.view.InsetsState.ITYPE_IME; 50 import static android.view.InsetsState.ITYPE_LEFT_GESTURES; 51 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; 52 import static android.view.InsetsState.ITYPE_RIGHT_GESTURES; 53 import static android.view.Surface.ROTATION_0; 54 import static android.view.Surface.ROTATION_270; 55 import static android.view.Surface.ROTATION_90; 56 import static android.view.View.GONE; 57 import static android.view.WindowInsets.Type.displayCutout; 58 import static android.view.WindowInsets.Type.ime; 59 import static android.view.WindowInsets.Type.systemBars; 60 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; 61 import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; 62 import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; 63 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; 64 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 65 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 66 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 67 import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; 68 import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; 69 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 70 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN; 71 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN; 72 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 73 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 74 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 75 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 76 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 77 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 78 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; 79 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 80 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 81 import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 82 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 83 import static android.view.WindowManager.TRANSIT_CHANGE; 84 import static android.view.WindowManager.TRANSIT_OPEN; 85 import static android.view.WindowManager.TRANSIT_TO_FRONT; 86 import static android.window.DisplayAreaOrganizer.FEATURE_ROOT; 87 import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION; 88 89 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; 90 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; 91 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT; 92 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; 93 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; 94 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; 95 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LAYER_MIRRORING; 96 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; 97 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON; 98 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WALLPAPER; 99 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; 100 import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN; 101 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 102 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 103 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 104 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 105 import static com.android.server.wm.ActivityRecord.State.RESUMED; 106 import static com.android.server.wm.DisplayContentProto.APP_TRANSITION; 107 import static com.android.server.wm.DisplayContentProto.CLOSING_APPS; 108 import static com.android.server.wm.DisplayContentProto.CURRENT_FOCUS; 109 import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES; 110 import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO; 111 import static com.android.server.wm.DisplayContentProto.DISPLAY_READY; 112 import static com.android.server.wm.DisplayContentProto.DISPLAY_ROTATION; 113 import static com.android.server.wm.DisplayContentProto.DPI; 114 import static com.android.server.wm.DisplayContentProto.FOCUSED_APP; 115 import static com.android.server.wm.DisplayContentProto.FOCUSED_ROOT_TASK_ID; 116 import static com.android.server.wm.DisplayContentProto.ID; 117 import static com.android.server.wm.DisplayContentProto.IME_INSETS_SOURCE_PROVIDER; 118 import static com.android.server.wm.DisplayContentProto.IME_POLICY; 119 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_CONTROL_TARGET; 120 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_INPUT_TARGET; 121 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_TARGET; 122 import static com.android.server.wm.DisplayContentProto.IS_SLEEPING; 123 import static com.android.server.wm.DisplayContentProto.OPENING_APPS; 124 import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY; 125 import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA; 126 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION; 127 import static com.android.server.wm.DisplayContentProto.SLEEP_TOKENS; 128 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; 129 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; 130 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; 131 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; 132 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; 133 import static com.android.server.wm.WindowContainerChildProto.DISPLAY_CONTENT; 134 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 135 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 136 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 137 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 138 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; 139 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 140 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 141 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 142 import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE; 143 import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; 144 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; 145 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES; 146 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS; 147 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 148 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; 149 import static com.android.server.wm.WindowManagerService.dipToPixel; 150 import static com.android.server.wm.WindowState.EXCLUSION_LEFT; 151 import static com.android.server.wm.WindowState.EXCLUSION_RIGHT; 152 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; 153 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; 154 import static com.android.server.wm.utils.RegionUtils.forEachRectReverse; 155 import static com.android.server.wm.utils.RegionUtils.rectListToRegion; 156 157 import android.annotation.IntDef; 158 import android.annotation.NonNull; 159 import android.annotation.Nullable; 160 import android.app.ActivityManager; 161 import android.app.ActivityManagerInternal; 162 import android.content.Context; 163 import android.content.pm.ActivityInfo; 164 import android.content.pm.ActivityInfo.ScreenOrientation; 165 import android.content.res.CompatibilityInfo; 166 import android.content.res.Configuration; 167 import android.graphics.Bitmap; 168 import android.graphics.ColorSpace; 169 import android.graphics.GraphicBuffer; 170 import android.graphics.Insets; 171 import android.graphics.Point; 172 import android.graphics.Rect; 173 import android.graphics.Region; 174 import android.graphics.Region.Op; 175 import android.hardware.HardwareBuffer; 176 import android.hardware.display.DisplayManagerInternal; 177 import android.metrics.LogMaker; 178 import android.os.Binder; 179 import android.os.Bundle; 180 import android.os.Debug; 181 import android.os.Handler; 182 import android.os.IBinder; 183 import android.os.Message; 184 import android.os.Process; 185 import android.os.RemoteCallbackList; 186 import android.os.RemoteException; 187 import android.os.SystemClock; 188 import android.os.Trace; 189 import android.os.UserHandle; 190 import android.provider.Settings; 191 import android.util.ArraySet; 192 import android.util.DisplayMetrics; 193 import android.util.IntArray; 194 import android.util.RotationUtils; 195 import android.util.Slog; 196 import android.util.SparseArray; 197 import android.util.SparseBooleanArray; 198 import android.util.proto.ProtoOutputStream; 199 import android.view.Display; 200 import android.view.DisplayCutout; 201 import android.view.DisplayCutout.CutoutPathParserInfo; 202 import android.view.DisplayInfo; 203 import android.view.Gravity; 204 import android.view.IDisplayWindowInsetsController; 205 import android.view.ISystemGestureExclusionListener; 206 import android.view.IWindow; 207 import android.view.InputChannel; 208 import android.view.InputDevice; 209 import android.view.InputWindowHandle; 210 import android.view.InsetsSource; 211 import android.view.InsetsState; 212 import android.view.InsetsState.InternalInsetsType; 213 import android.view.InsetsVisibilities; 214 import android.view.MagnificationSpec; 215 import android.view.PrivacyIndicatorBounds; 216 import android.view.RemoteAnimationDefinition; 217 import android.view.RoundedCorners; 218 import android.view.Surface; 219 import android.view.Surface.Rotation; 220 import android.view.SurfaceControl; 221 import android.view.SurfaceControl.Transaction; 222 import android.view.SurfaceSession; 223 import android.view.View; 224 import android.view.WindowInsets; 225 import android.view.WindowManager; 226 import android.view.WindowManager.DisplayImePolicy; 227 import android.view.WindowManagerPolicyConstants.PointerEventListener; 228 import android.window.IDisplayAreaOrganizer; 229 230 import com.android.internal.annotations.VisibleForTesting; 231 import com.android.internal.logging.MetricsLogger; 232 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 233 import com.android.internal.protolog.common.ProtoLog; 234 import com.android.internal.util.ToBooleanFunction; 235 import com.android.internal.util.function.TriConsumer; 236 import com.android.internal.util.function.pooled.PooledConsumer; 237 import com.android.internal.util.function.pooled.PooledFunction; 238 import com.android.internal.util.function.pooled.PooledLambda; 239 import com.android.internal.util.function.pooled.PooledPredicate; 240 import com.android.server.inputmethod.InputMethodManagerInternal; 241 import com.android.server.policy.WindowManagerPolicy; 242 import com.android.server.wm.utils.DisplayRotationUtil; 243 import com.android.server.wm.utils.RotationCache; 244 import com.android.server.wm.utils.WmDisplayCutout; 245 246 import java.io.PrintWriter; 247 import java.lang.annotation.Retention; 248 import java.lang.annotation.RetentionPolicy; 249 import java.util.ArrayList; 250 import java.util.HashMap; 251 import java.util.Iterator; 252 import java.util.LinkedList; 253 import java.util.List; 254 import java.util.Objects; 255 import java.util.Set; 256 import java.util.function.Consumer; 257 import java.util.function.Predicate; 258 259 /** 260 * Utility class for keeping track of the WindowStates and other pertinent contents of a 261 * particular Display. 262 */ 263 class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.DisplayContentInfo { 264 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM; 265 266 /** The default scaling mode that scales content automatically. */ 267 static final int FORCE_SCALING_MODE_AUTO = 0; 268 /** For {@link #setForcedScalingMode} to apply flag {@link Display#FLAG_SCALING_DISABLED}. */ 269 static final int FORCE_SCALING_MODE_DISABLED = 1; 270 271 @IntDef(prefix = { "FORCE_SCALING_MODE_" }, value = { 272 FORCE_SCALING_MODE_AUTO, 273 FORCE_SCALING_MODE_DISABLED 274 }) 275 @Retention(RetentionPolicy.SOURCE) 276 @interface ForceScalingMode {} 277 278 final ActivityTaskManagerService mAtmService; 279 280 /** 281 * Unique logical identifier of this display. 282 * 283 * @see DisplayInfo#displayId 284 */ 285 final int mDisplayId; 286 287 /** 288 * Unique physical identifier of this display. Unlike {@link #mDisplayId} this value can change 289 * at runtime if the underlying physical display changes. 290 * 291 * @see DisplayInfo#uniqueId 292 */ 293 @Nullable 294 String mCurrentUniqueDisplayId; 295 296 /** 297 * We organize all top-level Surfaces into the following layer. 298 * It contains a few Surfaces which are always on top of others, and omitted from 299 * Screen-Magnification, for example the strict mode flash or the fullscreen magnification 300 * overlay. 301 */ 302 private SurfaceControl mOverlayLayer; 303 304 /** 305 * The direct child layer of the display to put all non-overlay windows. This is also used for 306 * screen rotation animation so that there is a parent layer to put the animation leash. 307 */ 308 private SurfaceControl mWindowingLayer; 309 310 /** 311 * The window token of the layer of the hierarchy to mirror, or null if this DisplayContent 312 * is not being used for layer mirroring. 313 */ 314 @VisibleForTesting IBinder mTokenToMirror = null; 315 316 /** 317 * The surface for mirroring the contents of this hierarchy, or null if layer mirroring is 318 * temporarily disabled. 319 */ 320 private SurfaceControl mMirroredSurface = null; 321 322 /** 323 * The last bounds of the DisplayArea to mirror. 324 */ 325 private Rect mLastMirroredDisplayAreaBounds = null; 326 327 // Contains all IME window containers. Note that the z-ordering of the IME windows will depend 328 // on the IME target. We mainly have this container grouping so we can keep track of all the IME 329 // window containers together and move them in-sync if/when needed. We use a subclass of 330 // WindowContainer which is omitted from screen magnification, as the IME is never magnified. 331 // TODO(display-area): is "no magnification" in the comment still true? 332 private final ImeContainer mImeWindowsContainer = new ImeContainer(mWmService); 333 334 @VisibleForTesting 335 DisplayAreaPolicy mDisplayAreaPolicy; 336 337 private WindowState mTmpWindow; 338 private boolean mUpdateImeTarget; 339 private boolean mTmpInitial; 340 private int mMaxUiWidth; 341 342 final AppTransition mAppTransition; 343 final AppTransitionController mAppTransitionController; 344 boolean mSkipAppTransitionAnimation = false; 345 346 final ArraySet<ActivityRecord> mOpeningApps = new ArraySet<>(); 347 final ArraySet<ActivityRecord> mClosingApps = new ArraySet<>(); 348 final ArraySet<WindowContainer> mChangingContainers = new ArraySet<>(); 349 final UnknownAppVisibilityController mUnknownAppVisibilityController; 350 351 private MetricsLogger mMetricsLogger; 352 353 /** 354 * List of clients without a transtiton animation that we notify once we are done 355 * transitioning since they won't be notified through the app window animator. 356 */ 357 final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>(); 358 359 // Mapping from a token IBinder to a WindowToken object on this display. 360 private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap(); 361 362 // Initial display metrics. 363 int mInitialDisplayWidth = 0; 364 int mInitialDisplayHeight = 0; 365 int mInitialDisplayDensity = 0; 366 367 DisplayCutout mInitialDisplayCutout; 368 private final RotationCache<DisplayCutout, WmDisplayCutout> mDisplayCutoutCache 369 = new RotationCache<>(this::calculateDisplayCutoutForRotationUncached); 370 boolean mIgnoreDisplayCutout; 371 372 RoundedCorners mInitialRoundedCorners; 373 private final RotationCache<RoundedCorners, RoundedCorners> mRoundedCornerCache = 374 new RotationCache<>(this::calculateRoundedCornersForRotationUncached); 375 376 PrivacyIndicatorBounds mCurrentPrivacyIndicatorBounds = new PrivacyIndicatorBounds(); 377 private final RotationCache<PrivacyIndicatorBounds, PrivacyIndicatorBounds> 378 mPrivacyIndicatorBoundsCache = new 379 RotationCache<>(this::calculatePrivacyIndicatorBoundsForRotationUncached); 380 381 /** 382 * Overridden display size. Initialized with {@link #mInitialDisplayWidth} 383 * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size". 384 * @see WindowManagerService#setForcedDisplaySize(int, int, int) 385 */ 386 int mBaseDisplayWidth = 0; 387 int mBaseDisplayHeight = 0; 388 boolean mIsSizeForced = false; 389 390 /** 391 * Overridden display size and metrics to activity window bounds. Set via 392 * "adb shell wm set-sandbox-display-apis". Default to true, since only disable for debugging. 393 * @see WindowManagerService#setSandboxDisplayApis(int, boolean) 394 */ 395 private boolean mSandboxDisplayApis = true; 396 397 /** 398 * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity} 399 * but can be set from Settings or via shell command "adb shell wm density". 400 * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int) 401 */ 402 int mBaseDisplayDensity = 0; 403 boolean mIsDensityForced = false; 404 405 /** 406 * Whether to disable display scaling. This can be set via shell command "adb shell wm scaling". 407 * @see WindowManagerService#setForcedDisplayScalingMode(int, int) 408 */ 409 boolean mDisplayScalingDisabled; 410 final Display mDisplay; 411 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 412 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 413 private final DisplayPolicy mDisplayPolicy; 414 private final DisplayRotation mDisplayRotation; 415 DisplayFrames mDisplayFrames; 416 417 private final RemoteCallbackList<ISystemGestureExclusionListener> 418 mSystemGestureExclusionListeners = new RemoteCallbackList<>(); 419 private final Region mSystemGestureExclusion = new Region(); 420 private boolean mSystemGestureExclusionWasRestricted = false; 421 private final Region mSystemGestureExclusionUnrestricted = new Region(); 422 private int mSystemGestureExclusionLimit; 423 424 /** 425 * For default display it contains real metrics, empty for others. 426 * @see WindowManagerService#createWatermark() 427 */ 428 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 429 430 /** @see #computeCompatSmallestWidth(boolean, int, int, int) */ 431 private final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 432 433 /** 434 * Compat metrics computed based on {@link #mDisplayMetrics}. 435 * @see #updateDisplayAndOrientation(int) 436 */ 437 private final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 438 439 /** The desired scaling factor for compatible apps. */ 440 float mCompatibleScreenScale; 441 442 /** @see #getCurrentOverrideConfigurationChanges */ 443 private int mCurrentOverrideConfigurationChanges; 444 445 /** 446 * The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. The 447 * orientation requests from apps would be ignored if the display is close-to-square. 448 */ 449 @VisibleForTesting 450 final float mCloseToSquareMaxAspectRatio; 451 452 /** 453 * Keep track of wallpaper visibility to notify changes. 454 */ 455 private boolean mLastWallpaperVisible = false; 456 457 private Rect mBaseDisplayRect = new Rect(); 458 459 // Accessed directly by all users. 460 private boolean mLayoutNeeded; 461 int pendingLayoutChanges; 462 boolean mLayoutAndAssignWindowLayersScheduled; 463 464 /** 465 * Used to gate application window layout until we have sent the complete configuration. 466 * TODO: There are still scenarios where we may be out of sync with the client. Ideally 467 * we want to replace this flag with a mechanism that will confirm the configuration 468 * applied by the client is the one expected by the system server. 469 */ 470 boolean mWaitingForConfig; 471 472 // TODO(multi-display): remove some of the usages. 473 @VisibleForTesting 474 boolean isDefaultDisplay; 475 476 /** 477 * Flag indicating whether WindowManager should override info for this display in 478 * DisplayManager. 479 */ 480 boolean mShouldOverrideDisplayConfiguration = true; 481 482 /** Window tokens that are in the process of exiting, but still on screen for animations. */ 483 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>(); 484 485 /** Detect user tapping outside of current focused task bounds .*/ 486 @VisibleForTesting 487 final TaskTapPointerEventListener mTapDetector; 488 489 /** Detect user tapping outside of current focused root task bounds .*/ 490 private Region mTouchExcludeRegion = new Region(); 491 492 /** Save allocating when calculating rects */ 493 private final Rect mTmpRect = new Rect(); 494 private final Rect mTmpRect2 = new Rect(); 495 private final Region mTmpRegion = new Region(); 496 497 /** Used for handing back size of display */ 498 private final Rect mTmpBounds = new Rect(); 499 500 private final Configuration mTmpConfiguration = new Configuration(); 501 502 /** Remove this display when animation on it has completed. */ 503 private boolean mDeferredRemoval; 504 505 final DockedTaskDividerController mDividerControllerLocked; 506 final PinnedTaskController mPinnedTaskController; 507 508 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>(); 509 /** A collection of windows that provide tap exclude regions inside of them. */ 510 final ArraySet<WindowState> mTapExcludeProvidingWindows = new ArraySet<>(); 511 512 private final LinkedList<ActivityRecord> mTmpUpdateAllDrawn = new LinkedList(); 513 514 private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult = 515 new TaskForResizePointSearchResult(); 516 private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState = 517 new ApplySurfaceChangesTransactionState(); 518 519 // {@code false} if this display is in the processing of being created. 520 private boolean mDisplayReady = false; 521 522 WallpaperController mWallpaperController; 523 524 boolean mWallpaperMayChange = false; 525 526 private final SurfaceSession mSession = new SurfaceSession(); 527 528 /** 529 * Window that is currently interacting with the user. This window is responsible for receiving 530 * key events and pointer events from the user. 531 */ 532 WindowState mCurrentFocus = null; 533 534 /** 535 * The foreground app of this display. Windows below this app cannot be the focused window. If 536 * the user taps on the area outside of the task of the focused app, we will notify AM about the 537 * new task the user wants to interact with. 538 */ 539 ActivityRecord mFocusedApp = null; 540 541 /** 542 * We only respect the orientation request from apps below this {@link TaskDisplayArea}. 543 * It is the last focused {@link TaskDisplayArea} on this display that handles orientation 544 * request. 545 */ 546 @Nullable 547 private TaskDisplayArea mOrientationRequestingTaskDisplayArea = null; 548 549 /** 550 * The launching activity which is using fixed rotation transformation. 551 * 552 * @see #handleTopActivityLaunchingInDifferentOrientation 553 * @see #setFixedRotationLaunchingApp(ActivityRecord, int) 554 * @see DisplayRotation#shouldRotateSeamlessly 555 */ 556 private ActivityRecord mFixedRotationLaunchingApp; 557 558 /** The delay to avoid toggling the animation quickly. */ 559 private static final long FIXED_ROTATION_HIDE_ANIMATION_DEBOUNCE_DELAY_MS = 250; 560 private FadeRotationAnimationController mFadeRotationAnimationController; 561 562 final FixedRotationTransitionListener mFixedRotationTransitionListener = 563 new FixedRotationTransitionListener(); 564 565 /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */ 566 final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>(); 567 568 /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */ 569 final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>(); 570 571 /** Windows whose client's insets states are not up-to-date. */ 572 final ArrayList<WindowState> mWinInsetsChanged = new ArrayList<>(); 573 574 private ScreenRotationAnimation mScreenRotationAnimation; 575 576 /** 577 * Sequence number for the current layout pass. 578 */ 579 int mLayoutSeq = 0; 580 581 /** 582 * Specifies the count to determine whether to defer updating the IME target until ready. 583 */ 584 private int mDeferUpdateImeTargetCount; 585 private boolean mUpdateImeRequestedWhileDeferred; 586 587 private MagnificationSpec mMagnificationSpec; 588 589 private InputMonitor mInputMonitor; 590 591 /** Caches the value whether told display manager that we have content. */ 592 private boolean mLastHasContent; 593 594 private DisplayRotationUtil mRotationUtil = new DisplayRotationUtil(); 595 596 /** 597 * The input method window for this display. 598 */ 599 WindowState mInputMethodWindow; 600 601 /** 602 * This just indicates the window the input method is on top of, not 603 * necessarily the window its input is going to. 604 */ 605 private WindowState mImeLayeringTarget; 606 607 /** 608 * The window which receives input from the input method. This is also a candidate of the 609 * input method control target. 610 */ 611 private WindowState mImeInputTarget; 612 613 /** 614 * This controls the visibility and animation of the input method window. 615 */ 616 private InsetsControlTarget mImeControlTarget; 617 618 /** 619 * Used by {@link #getImeTarget} to return the IME target which the input method window on 620 * top of for adjusting input method window surface layer Z-Ordering. 621 * 622 * @see #mImeLayeringTarget 623 */ 624 static final int IME_TARGET_LAYERING = 0; 625 626 /** 627 * Used by {@link #getImeTarget} to return the IME target which received the input connection 628 * from IME. 629 * 630 * @see #mImeInputTarget 631 */ 632 static final int IME_TARGET_INPUT = 1; 633 634 /** 635 * Used by {@link #getImeTarget} to return the IME target which controls the IME insets 636 * visibility and animation. 637 * 638 * @see #mImeControlTarget 639 */ 640 static final int IME_TARGET_CONTROL = 2; 641 642 @IntDef(flag = false, prefix = { "IME_TARGET_" }, value = { 643 IME_TARGET_LAYERING, 644 IME_TARGET_INPUT, 645 IME_TARGET_CONTROL, 646 }) 647 @Retention(RetentionPolicy.SOURCE) 648 @interface InputMethodTarget {} 649 650 /** The surface parent of the IME container. */ 651 private SurfaceControl mInputMethodSurfaceParent; 652 653 /** If {@code true} hold off on modifying the animation layer of {@link #mImeLayeringTarget} */ 654 boolean mImeLayeringTargetWaitingAnim; 655 656 /** The screenshot IME surface to place on the task while transitioning to the next task. */ 657 SurfaceControl mImeScreenshot; 658 659 private final PointerEventDispatcher mPointerEventDispatcher; 660 661 private final InsetsStateController mInsetsStateController; 662 private final InsetsPolicy mInsetsPolicy; 663 664 /** @see #getParentWindow() */ 665 private WindowState mParentWindow; 666 667 private Point mLocationInParentWindow = new Point(); 668 private SurfaceControl mParentSurfaceControl; 669 private InputWindowHandle mPortalWindowHandle; 670 671 /** Corner radius that windows should have in order to match the display. */ 672 private final float mWindowCornerRadius; 673 674 final SparseArray<ShellRoot> mShellRoots = new SparseArray<>(); 675 RemoteInsetsControlTarget mRemoteInsetsControlTarget = null; 676 private final IBinder.DeathRecipient mRemoteInsetsDeath = 677 () -> { 678 synchronized (mWmService.mGlobalLock) { 679 mRemoteInsetsControlTarget = null; 680 } 681 }; 682 683 private RootWindowContainer mRootWindowContainer; 684 685 /** Array of all UIDs that are present on the display. */ 686 private IntArray mDisplayAccessUIDs = new IntArray(); 687 688 /** All tokens used to put activities on this root task to sleep (including mOffToken) */ 689 final ArrayList<RootWindowContainer.SleepToken> mAllSleepTokens = new ArrayList<>(); 690 /** The token acquirer to put root tasks on the display to sleep */ 691 private final ActivityTaskManagerInternal.SleepTokenAcquirer mOffTokenAcquirer; 692 693 private boolean mSleeping; 694 695 /** We started the process of removing the display from the system. */ 696 private boolean mRemoving; 697 698 /** 699 * The display is removed from the system and we are just waiting for all activities on it to be 700 * finished before removing this object. 701 */ 702 private boolean mRemoved; 703 704 /** Set of activities in foreground size compat mode. */ 705 private Set<ActivityRecord> mActiveSizeCompatActivities = new ArraySet<>(); 706 707 // Used in updating the display size 708 private Point mTmpDisplaySize = new Point(); 709 710 // Used in updating override configurations 711 private final Configuration mTempConfig = new Configuration(); 712 713 /** 714 * Used to prevent recursions when calling 715 * {@link #ensureActivitiesVisible(ActivityRecord, int, boolean, boolean)} 716 */ 717 private boolean mInEnsureActivitiesVisible = false; 718 719 // Used to indicate that the movement of child tasks to top will not move the display to top as 720 // well and thus won't change the top resumed / focused record 721 boolean mDontMoveToTop; 722 723 private final ArrayList<ActivityRecord> mTmpActivityList = new ArrayList<>(); 724 725 private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> { 726 WindowStateAnimator winAnimator = w.mWinAnimator; 727 final ActivityRecord activity = w.mActivityRecord; 728 if (winAnimator.mDrawState == READY_TO_SHOW) { 729 if (activity == null || activity.canShowWindows()) { 730 if (w.performShowLocked()) { 731 pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 732 if (DEBUG_LAYOUT_REPEATS) { 733 mWmService.mWindowPlacerLocked.debugLayoutRepeats( 734 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges); 735 } 736 } 737 } 738 } 739 }; 740 741 private final Consumer<WindowState> mScheduleToastTimeout = w -> { 742 final int lostFocusUid = mTmpWindow.mOwnerUid; 743 final Handler handler = mWmService.mH; 744 if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) { 745 if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) { 746 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w), 747 w.mAttrs.hideTimeoutMilliseconds); 748 } 749 } 750 }; 751 752 private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> { 753 final ActivityRecord focusedApp = mFocusedApp; 754 ProtoLog.v(WM_DEBUG_FOCUS, "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s", 755 w, w.mAttrs.flags, w.canReceiveKeys(), 756 w.canReceiveKeysReason(false /* fromUserTouch */)); 757 758 if (!w.canReceiveKeys()) { 759 return false; 760 } 761 762 // When switching the app task, we keep the IME window visibility for better 763 // transitioning experiences. 764 // However, in case IME created a child window or the IME selection dialog without 765 // dismissing during the task switching to keep the window focus because IME window has 766 // higher window hierarchy, we don't give it focus if the next IME layering target 767 // doesn't request IME visible. 768 if (w.mIsImWindow && w.isChildWindow() && (mImeLayeringTarget == null 769 || !mImeLayeringTarget.getRequestedVisibility(ITYPE_IME))) { 770 return false; 771 } 772 if (w.mAttrs.type == TYPE_INPUT_METHOD_DIALOG && mImeLayeringTarget != null 773 && !mImeLayeringTarget.getRequestedVisibility(ITYPE_IME) 774 && mImeLayeringTarget.isAnimating(PARENTS | TRANSITION, 775 ANIMATION_TYPE_APP_TRANSITION)) { 776 return false; 777 } 778 779 final ActivityRecord activity = w.mActivityRecord; 780 781 if (focusedApp == null) { 782 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, 783 "findFocusedWindow: focusedApp=null using new focus @ %s", w); 784 mTmpWindow = w; 785 return true; 786 } 787 788 if (!focusedApp.windowsAreFocusable()) { 789 // Current focused app windows aren't focusable... 790 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: focusedApp windows not" 791 + " focusable using new focus @ %s", w); 792 mTmpWindow = w; 793 return true; 794 } 795 796 // Descend through all of the app tokens and find the first that either matches 797 // win.mActivityRecord (return win) or mFocusedApp (return null). 798 if (activity != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) { 799 if (focusedApp.compareTo(activity) > 0) { 800 // App root task below focused app root task. No focus for you!!! 801 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, 802 "findFocusedWindow: Reached focused app=%s", focusedApp); 803 mTmpWindow = null; 804 return true; 805 } 806 807 // If the candidate activity is currently being embedded in the focused task, the 808 // activity cannot be focused unless it is on the same TaskFragment as the focusedApp's. 809 TaskFragment parent = activity.getTaskFragment(); 810 if (parent != null && parent.isEmbedded()) { 811 Task hostTask = focusedApp.getTask(); 812 if (hostTask.isEmbedded()) { 813 // Use the hosting task if the current task is embedded. 814 hostTask = hostTask.getParent().asTaskFragment().getTask(); 815 } 816 if (activity.isDescendantOf(hostTask) 817 && activity.getTaskFragment() != focusedApp.getTaskFragment()) { 818 return false; 819 } 820 } 821 } 822 823 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: Found new focus @ %s", w); 824 mTmpWindow = w; 825 return true; 826 }; 827 828 private final Consumer<WindowState> mPerformLayout = w -> { 829 // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid 830 // wasting time and funky changes while a window is animating away. 831 final boolean gone = w.isGoneForLayout(); 832 833 if (DEBUG_LAYOUT && !w.mLayoutAttached) { 834 Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame 835 + " mLayoutAttached=" + w.mLayoutAttached 836 + " config reported=" + w.isLastConfigReportedToClient()); 837 final ActivityRecord activity = w.mActivityRecord; 838 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility 839 + " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible() 840 + " visibleRequested=" + (activity != null && activity.mVisibleRequested) 841 + " parentHidden=" + w.isParentWindowHidden()); 842 else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility 843 + " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible() 844 + " visibleRequested=" + (activity != null && activity.mVisibleRequested) 845 + " parentHidden=" + w.isParentWindowHidden()); 846 } 847 848 // If this view is GONE, then skip it -- keep the current frame, and let the caller know 849 // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows, 850 // since that means "perform layout as normal, just don't display"). 851 if ((!gone || !w.mHaveFrame || w.mLayoutNeeded) && !w.mLayoutAttached) { 852 if (mTmpInitial) { 853 w.resetContentChanged(); 854 } 855 w.mSurfacePlacementNeeded = true; 856 w.mLayoutNeeded = false; 857 w.prelayout(); 858 final boolean firstLayout = !w.isLaidOut(); 859 getDisplayPolicy().layoutWindowLw(w, null, mDisplayFrames); 860 w.mLayoutSeq = mLayoutSeq; 861 862 // If this is the first layout, we need to initialize the last frames and inset values, 863 // as otherwise we'd immediately cause an unnecessary resize. 864 if (firstLayout) { 865 // The client may compute its actual requested size according to the first layout, 866 // so we still request the window to resize if the current frame is empty. 867 if (!w.getFrame().isEmpty()) { 868 w.updateLastFrames(); 869 } 870 w.onResizeHandled(); 871 w.updateLocationInParentDisplayIfNeeded(); 872 } 873 874 if (w.mActivityRecord != null) { 875 w.mActivityRecord.layoutLetterbox(w); 876 } 877 878 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrame() 879 + " mContainingFrame=" + w.getContainingFrame() 880 + " mDisplayFrame=" + w.getDisplayFrame()); 881 } 882 }; 883 884 private final Consumer<WindowState> mPerformLayoutAttached = w -> { 885 if (w.mLayoutAttached) { 886 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame 887 + " mViewVisibility=" + w.mViewVisibility 888 + " mRelayoutCalled=" + w.mRelayoutCalled); 889 // If this view is GONE, then skip it -- keep the current frame, and let the caller 890 // know so they can ignore it if they want. (We do the normal layout for INVISIBLE 891 // windows, since that means "perform layout as normal, just don't display"). 892 if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame 893 || w.mLayoutNeeded) { 894 if (mTmpInitial) { 895 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 896 w.resetContentChanged(); 897 } 898 w.mSurfacePlacementNeeded = true; 899 w.mLayoutNeeded = false; 900 w.prelayout(); 901 getDisplayPolicy().layoutWindowLw(w, w.getParentWindow(), mDisplayFrames); 902 w.mLayoutSeq = mLayoutSeq; 903 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrame() 904 + " mContainingFrame=" + w.getContainingFrame() 905 + " mDisplayFrame=" + w.getDisplayFrame()); 906 } 907 } 908 }; 909 910 private final Predicate<WindowState> mComputeImeTargetPredicate = w -> { 911 if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w 912 + " fl=0x" + Integer.toHexString(w.mAttrs.flags)); 913 return w.canBeImeTarget(); 914 }; 915 916 private final Consumer<WindowState> mApplyPostLayoutPolicy = 917 w -> getDisplayPolicy().applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(), 918 mImeLayeringTarget); 919 920 private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> { 921 final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked; 922 final boolean obscuredChanged = w.mObscured != 923 mTmpApplySurfaceChangesTransactionState.obscured; 924 final RootWindowContainer root = mWmService.mRoot; 925 926 // Update effect. 927 w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured; 928 929 if (!mTmpApplySurfaceChangesTransactionState.obscured) { 930 final boolean isDisplayed = w.isDisplayed(); 931 932 if (isDisplayed && w.isObscuringDisplay()) { 933 // This window completely covers everything behind it, so we want to leave all 934 // of them as undimmed (for performance reasons). 935 root.mObscuringWindow = w; 936 mTmpApplySurfaceChangesTransactionState.obscured = true; 937 } 938 939 final boolean displayHasContent = root.handleNotObscuredLocked(w, 940 mTmpApplySurfaceChangesTransactionState.obscured, 941 mTmpApplySurfaceChangesTransactionState.syswin); 942 943 if (!mTmpApplySurfaceChangesTransactionState.displayHasContent 944 && !getDisplayPolicy().isWindowExcludedFromContent(w)) { 945 mTmpApplySurfaceChangesTransactionState.displayHasContent |= displayHasContent; 946 } 947 948 if (w.mHasSurface && isDisplayed) { 949 final int type = w.mAttrs.type; 950 if (type == TYPE_SYSTEM_DIALOG 951 || type == TYPE_SYSTEM_ERROR 952 || (type == TYPE_NOTIFICATION_SHADE 953 && mWmService.mPolicy.isKeyguardShowing())) { 954 mTmpApplySurfaceChangesTransactionState.syswin = true; 955 } 956 if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0 957 && w.mAttrs.preferredRefreshRate != 0) { 958 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate 959 = w.mAttrs.preferredRefreshRate; 960 } 961 962 mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing 963 |= w.mAttrs.preferMinimalPostProcessing; 964 965 final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy() 966 .getPreferredModeId(w); 967 if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0 968 && preferredModeId != 0) { 969 mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId; 970 } 971 972 final float preferredMinRefreshRate = getDisplayPolicy().getRefreshRatePolicy() 973 .getPreferredMinRefreshRate(w); 974 if (mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate == 0 975 && preferredMinRefreshRate != 0) { 976 mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate = 977 preferredMinRefreshRate; 978 } 979 980 final float preferredMaxRefreshRate = getDisplayPolicy().getRefreshRatePolicy() 981 .getPreferredMaxRefreshRate(w); 982 if (mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate == 0 983 && preferredMaxRefreshRate != 0) { 984 mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate = 985 preferredMaxRefreshRate; 986 } 987 } 988 } 989 990 if (obscuredChanged && w.isVisible() && mWallpaperController.isWallpaperTarget(w)) { 991 // This is the wallpaper target and its obscured state changed... make sure the 992 // current wallpaper's visibility has been updated accordingly. 993 mWallpaperController.updateWallpaperVisibility(); 994 } 995 996 w.handleWindowMovedIfNeeded(); 997 998 final WindowStateAnimator winAnimator = w.mWinAnimator; 999 1000 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 1001 w.resetContentChanged(); 1002 1003 // Moved from updateWindowsAndWallpaperLocked(). 1004 if (w.mHasSurface) { 1005 // Take care of the window being ready to display. 1006 final boolean committed = winAnimator.commitFinishDrawingLocked(); 1007 if (isDefaultDisplay && committed) { 1008 if (w.hasWallpaper()) { 1009 ProtoLog.v(WM_DEBUG_WALLPAPER, 1010 "First draw done in potential wallpaper target %s", w); 1011 mWallpaperMayChange = true; 1012 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1013 if (DEBUG_LAYOUT_REPEATS) { 1014 surfacePlacer.debugLayoutRepeats( 1015 "wallpaper and commitFinishDrawingLocked true", 1016 pendingLayoutChanges); 1017 } 1018 } 1019 } 1020 } 1021 1022 final ActivityRecord activity = w.mActivityRecord; 1023 if (activity != null && activity.isVisibleRequested()) { 1024 activity.updateLetterboxSurface(w); 1025 final boolean updateAllDrawn = activity.updateDrawnWindowStates(w); 1026 if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(activity)) { 1027 mTmpUpdateAllDrawn.add(activity); 1028 } 1029 } 1030 1031 w.updateResizingWindowIfNeeded(); 1032 }; 1033 1034 /** 1035 * Create new {@link DisplayContent} instance, add itself to the root window container and 1036 * initialize direct children. 1037 * @param display May not be null. 1038 * @param root {@link RootWindowContainer} 1039 */ DisplayContent(Display display, RootWindowContainer root)1040 DisplayContent(Display display, RootWindowContainer root) { 1041 super(root.mWindowManager, "DisplayContent", FEATURE_ROOT); 1042 if (mWmService.mRoot.getDisplayContent(display.getDisplayId()) != null) { 1043 throw new IllegalArgumentException("Display with ID=" + display.getDisplayId() 1044 + " already exists=" 1045 + mWmService.mRoot.getDisplayContent(display.getDisplayId()) 1046 + " new=" + display); 1047 } 1048 1049 mRootWindowContainer = root; 1050 mAtmService = mWmService.mAtmService; 1051 mDisplay = display; 1052 mDisplayId = display.getDisplayId(); 1053 mCurrentUniqueDisplayId = display.getUniqueId(); 1054 mOffTokenAcquirer = mRootWindowContainer.mDisplayOffTokenAcquirer; 1055 mWallpaperController = new WallpaperController(mWmService, this); 1056 display.getDisplayInfo(mDisplayInfo); 1057 display.getMetrics(mDisplayMetrics); 1058 mSystemGestureExclusionLimit = mWmService.mConstants.mSystemGestureExclusionLimitDp 1059 * mDisplayMetrics.densityDpi / DENSITY_DEFAULT; 1060 isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; 1061 mInsetsStateController = new InsetsStateController(this); 1062 mDisplayFrames = new DisplayFrames(mDisplayId, mInsetsStateController.getRawInsetsState(), 1063 mDisplayInfo, calculateDisplayCutoutForRotation(mDisplayInfo.rotation), 1064 calculateRoundedCornersForRotation(mDisplayInfo.rotation), 1065 calculatePrivacyIndicatorBoundsForRotation(mDisplayInfo.rotation)); 1066 initializeDisplayBaseInfo(); 1067 1068 mAppTransition = new AppTransition(mWmService.mContext, mWmService, this); 1069 mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier); 1070 mAppTransition.registerListenerLocked(mFixedRotationTransitionListener); 1071 mAppTransitionController = new AppTransitionController(mWmService, this); 1072 mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this); 1073 1074 final InputChannel inputChannel = mWmService.mInputManager.monitorInput( 1075 "PointerEventDispatcher" + mDisplayId, mDisplayId); 1076 mPointerEventDispatcher = new PointerEventDispatcher(inputChannel, this); 1077 1078 // Tap Listeners are supported for: 1079 // 1. All physical displays (multi-display). 1080 // 2. VirtualDisplays on VR, AA (and everything else). 1081 mTapDetector = new TaskTapPointerEventListener(mWmService, this); 1082 registerPointerEventListener(mTapDetector); 1083 registerPointerEventListener(mWmService.mMousePositionTracker); 1084 if (mWmService.mAtmService.getRecentTasks() != null) { 1085 registerPointerEventListener( 1086 mWmService.mAtmService.getRecentTasks().getInputListener()); 1087 } 1088 1089 mDisplayPolicy = new DisplayPolicy(mWmService, this); 1090 mDisplayRotation = new DisplayRotation(mWmService, this); 1091 mCloseToSquareMaxAspectRatio = mWmService.mContext.getResources().getFloat( 1092 com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio); 1093 if (isDefaultDisplay) { 1094 // The policy may be invoked right after here, so it requires the necessary default 1095 // fields of this display content. 1096 mWmService.mPolicy.setDefaultDisplay(this); 1097 } 1098 if (mWmService.mDisplayReady) { 1099 mDisplayPolicy.onConfigurationChanged(); 1100 } 1101 if (mWmService.mSystemReady) { 1102 mDisplayPolicy.systemReady(); 1103 } 1104 mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius(); 1105 mDividerControllerLocked = new DockedTaskDividerController(this); 1106 mPinnedTaskController = new PinnedTaskController(mWmService, this); 1107 1108 final Transaction pendingTransaction = getPendingTransaction(); 1109 configureSurfaces(pendingTransaction); 1110 pendingTransaction.apply(); 1111 1112 // Sets the display content for the children. 1113 onDisplayChanged(this); 1114 updateDisplayAreaOrganizers(); 1115 1116 mInputMonitor = new InputMonitor(mWmService, this); 1117 mInsetsPolicy = new InsetsPolicy(mInsetsStateController, this); 1118 1119 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Creating display=" + display); 1120 1121 mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this); 1122 } 1123 1124 @Override migrateToNewSurfaceControl(Transaction t)1125 void migrateToNewSurfaceControl(Transaction t) { 1126 t.remove(mSurfaceControl); 1127 1128 mLastSurfacePosition.set(0, 0); 1129 1130 configureSurfaces(t); 1131 1132 for (int i = 0; i < mChildren.size(); i++) { 1133 SurfaceControl sc = mChildren.get(i).getSurfaceControl(); 1134 if (sc != null) { 1135 t.reparent(sc, mSurfaceControl); 1136 } 1137 } 1138 1139 scheduleAnimation(); 1140 } 1141 1142 /** 1143 * Configures the surfaces hierarchy for DisplayContent 1144 * This method always recreates the main surface control but reparents the children 1145 * if they are already created. 1146 * @param transaction as part of which to perform the configuration 1147 */ configureSurfaces(Transaction transaction)1148 private void configureSurfaces(Transaction transaction) { 1149 final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession) 1150 .setOpaque(true) 1151 .setContainerLayer() 1152 .setCallsite("DisplayContent"); 1153 mSurfaceControl = b.setName(getName()).setContainerLayer().build(); 1154 1155 if (mDisplayAreaPolicy == null) { 1156 // Setup the policy and build the display area hierarchy. 1157 // Build the hierarchy only after creating the surface so it is reparented correctly 1158 mDisplayAreaPolicy = mWmService.getDisplayAreaPolicyProvider().instantiate( 1159 mWmService, this /* content */, this /* root */, 1160 mImeWindowsContainer); 1161 } 1162 1163 final List<DisplayArea<? extends WindowContainer>> areas = 1164 mDisplayAreaPolicy.getDisplayAreas(FEATURE_WINDOWED_MAGNIFICATION); 1165 final DisplayArea<?> area = areas.size() == 1 ? areas.get(0) : null; 1166 1167 if (area != null && area.getParent() == this) { 1168 // The windowed magnification area should contain all non-overlay windows, so just use 1169 // it as the windowing layer. 1170 mWindowingLayer = area.mSurfaceControl; 1171 transaction.reparent(mWindowingLayer, mSurfaceControl); 1172 } else { 1173 // Need an additional layer for screen level animation, so move the layer containing 1174 // the windows to the new root. 1175 mWindowingLayer = mSurfaceControl; 1176 mSurfaceControl = b.setName("RootWrapper").build(); 1177 transaction.reparent(mWindowingLayer, mSurfaceControl) 1178 .show(mWindowingLayer); 1179 } 1180 1181 if (mOverlayLayer == null) { 1182 mOverlayLayer = b.setName("Display Overlays").setParent(mSurfaceControl).build(); 1183 } else { 1184 transaction.reparent(mOverlayLayer, mSurfaceControl); 1185 } 1186 1187 transaction 1188 .setLayer(mSurfaceControl, 0) 1189 .setLayerStack(mSurfaceControl, mDisplayId) 1190 .show(mSurfaceControl) 1191 .setLayer(mOverlayLayer, Integer.MAX_VALUE) 1192 .show(mOverlayLayer); 1193 } 1194 isReady()1195 boolean isReady() { 1196 // The display is ready when the system and the individual display are both ready. 1197 return mWmService.mDisplayReady && mDisplayReady; 1198 } 1199 getDisplayId()1200 int getDisplayId() { 1201 return mDisplayId; 1202 } 1203 getWindowCornerRadius()1204 float getWindowCornerRadius() { 1205 return mWindowCornerRadius; 1206 } 1207 getWindowToken(IBinder binder)1208 WindowToken getWindowToken(IBinder binder) { 1209 return mTokenMap.get(binder); 1210 } 1211 getActivityRecord(IBinder binder)1212 ActivityRecord getActivityRecord(IBinder binder) { 1213 final WindowToken token = getWindowToken(binder); 1214 if (token == null) { 1215 return null; 1216 } 1217 return token.asActivityRecord(); 1218 } 1219 addWindowToken(IBinder binder, WindowToken token)1220 void addWindowToken(IBinder binder, WindowToken token) { 1221 final DisplayContent dc = mWmService.mRoot.getWindowTokenDisplay(token); 1222 if (dc != null) { 1223 // We currently don't support adding a window token to the display if the display 1224 // already has the binder mapped to another token. If there is a use case for supporting 1225 // this moving forward we will either need to merge the WindowTokens some how or have 1226 // the binder map to a list of window tokens. 1227 throw new IllegalArgumentException("Can't map token=" + token + " to display=" 1228 + getName() + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap); 1229 } 1230 if (binder == null) { 1231 throw new IllegalArgumentException("Can't map token=" + token + " to display=" 1232 + getName() + " binder is null"); 1233 } 1234 if (token == null) { 1235 throw new IllegalArgumentException("Can't map null token to display=" 1236 + getName() + " binder=" + binder); 1237 } 1238 1239 mTokenMap.put(binder, token); 1240 1241 if (token.asActivityRecord() == null) { 1242 // Set displayContent for non-app token to prevent same token will add twice after 1243 // onDisplayChanged. 1244 // TODO: Check if it's fine that super.onDisplayChanged of WindowToken 1245 // (WindowsContainer#onDisplayChanged) may skipped when token.mDisplayContent assigned. 1246 token.mDisplayContent = this; 1247 // Add non-app token to container hierarchy on the display. App tokens are added through 1248 // the parent container managing them (e.g. Tasks). 1249 final DisplayArea.Tokens da = findAreaForToken(token).asTokens(); 1250 da.addChild(token); 1251 } 1252 } 1253 removeWindowToken(IBinder binder, boolean animateExit)1254 WindowToken removeWindowToken(IBinder binder, boolean animateExit) { 1255 final WindowToken token = mTokenMap.remove(binder); 1256 if (token != null && token.asActivityRecord() == null) { 1257 token.setExiting(animateExit); 1258 } 1259 return token; 1260 } 1261 addShellRoot(@onNull IWindow client, @WindowManager.ShellRootLayer int shellRootLayer)1262 SurfaceControl addShellRoot(@NonNull IWindow client, 1263 @WindowManager.ShellRootLayer int shellRootLayer) { 1264 ShellRoot root = mShellRoots.get(shellRootLayer); 1265 if (root != null) { 1266 if (root.getClient() == client) { 1267 return root.getSurfaceControl(); 1268 } 1269 root.clear(); 1270 mShellRoots.remove(shellRootLayer); 1271 } 1272 root = new ShellRoot(client, this, shellRootLayer); 1273 SurfaceControl rootLeash = root.getSurfaceControl(); 1274 if (rootLeash == null) { 1275 // Root didn't finish initializing, so don't add it. 1276 root.clear(); 1277 return null; 1278 } 1279 mShellRoots.put(shellRootLayer, root); 1280 SurfaceControl out = new SurfaceControl(rootLeash, "DisplayContent.addShellRoot"); 1281 return out; 1282 } 1283 removeShellRoot(int windowType)1284 void removeShellRoot(int windowType) { 1285 synchronized(mWmService.mGlobalLock) { 1286 ShellRoot root = mShellRoots.get(windowType); 1287 if (root == null) { 1288 return; 1289 } 1290 root.clear(); 1291 mShellRoots.remove(windowType); 1292 } 1293 } 1294 setRemoteInsetsController(IDisplayWindowInsetsController controller)1295 void setRemoteInsetsController(IDisplayWindowInsetsController controller) { 1296 if (mRemoteInsetsControlTarget != null) { 1297 mRemoteInsetsControlTarget.mRemoteInsetsController.asBinder().unlinkToDeath( 1298 mRemoteInsetsDeath, 0); 1299 mRemoteInsetsControlTarget = null; 1300 } 1301 if (controller != null) { 1302 try { 1303 controller.asBinder().linkToDeath(mRemoteInsetsDeath, 0); 1304 mRemoteInsetsControlTarget = new RemoteInsetsControlTarget(controller); 1305 } catch (RemoteException e) { 1306 return; 1307 } 1308 } 1309 } 1310 1311 /** Changes the display the input window token is housed on to this one. */ reParentWindowToken(WindowToken token)1312 void reParentWindowToken(WindowToken token) { 1313 final DisplayContent prevDc = token.getDisplayContent(); 1314 if (prevDc == this) { 1315 return; 1316 } 1317 if (prevDc != null) { 1318 if (prevDc.mTokenMap.remove(token.token) != null && token.asActivityRecord() == null) { 1319 // Removed the token from the map, but made sure it's not an app token before 1320 // removing from parent. 1321 token.getParent().removeChild(token); 1322 } 1323 } 1324 1325 addWindowToken(token.token, token); 1326 1327 if (mWmService.mAccessibilityController.hasCallbacks()) { 1328 final int prevDisplayId = prevDc != null ? prevDc.getDisplayId() : INVALID_DISPLAY; 1329 mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(prevDisplayId, 1330 getDisplayId()); 1331 } 1332 } 1333 removeAppToken(IBinder binder)1334 void removeAppToken(IBinder binder) { 1335 final WindowToken token = removeWindowToken(binder, true /* animateExit */); 1336 if (token == null) { 1337 Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder); 1338 return; 1339 } 1340 1341 final ActivityRecord activity = token.asActivityRecord(); 1342 1343 if (activity == null) { 1344 Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token); 1345 return; 1346 } 1347 1348 activity.onRemovedFromDisplay(); 1349 if (activity == mFixedRotationLaunchingApp) { 1350 // Make sure the states of associated tokens are also cleared. 1351 activity.finishFixedRotationTransform(); 1352 setFixedRotationLaunchingAppUnchecked(null); 1353 } 1354 } 1355 1356 @Override getDisplay()1357 public Display getDisplay() { 1358 return mDisplay; 1359 } 1360 getDisplayInfo()1361 DisplayInfo getDisplayInfo() { 1362 return mDisplayInfo; 1363 } 1364 getDisplayMetrics()1365 DisplayMetrics getDisplayMetrics() { 1366 return mDisplayMetrics; 1367 } 1368 getDisplayPolicy()1369 DisplayPolicy getDisplayPolicy() { 1370 return mDisplayPolicy; 1371 } 1372 1373 @Override getDisplayRotation()1374 public DisplayRotation getDisplayRotation() { 1375 return mDisplayRotation; 1376 } 1377 setInsetProvider(@nternalInsetsType int type, WindowState win, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider)1378 void setInsetProvider(@InternalInsetsType int type, WindowState win, 1379 @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider){ 1380 setInsetProvider(type, win, frameProvider, null /* imeFrameProvider */); 1381 } 1382 1383 /** 1384 * Marks a window as providing insets for the rest of the windows in the system. 1385 * 1386 * @param type The type of inset this window provides. 1387 * @param win The window. 1388 * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of 1389 * the window should be taken. 1390 * @param imeFrameProvider Function to compute the frame when dispatching insets to the IME, or 1391 * {@code null} if the normal frame should be taken. 1392 */ setInsetProvider(@nternalInsetsType int type, WindowState win, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider, @Nullable TriConsumer<DisplayFrames, WindowState, Rect> imeFrameProvider)1393 void setInsetProvider(@InternalInsetsType int type, WindowState win, 1394 @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider, 1395 @Nullable TriConsumer<DisplayFrames, WindowState, Rect> imeFrameProvider) { 1396 mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider, 1397 imeFrameProvider); 1398 } 1399 getInsetsStateController()1400 InsetsStateController getInsetsStateController() { 1401 return mInsetsStateController; 1402 } 1403 getInsetsPolicy()1404 InsetsPolicy getInsetsPolicy() { 1405 return mInsetsPolicy; 1406 } 1407 1408 @Rotation getRotation()1409 int getRotation() { 1410 return mDisplayRotation.getRotation(); 1411 } 1412 1413 @ScreenOrientation getLastOrientation()1414 int getLastOrientation() { 1415 return mDisplayRotation.getLastOrientation(); 1416 } 1417 registerRemoteAnimations(RemoteAnimationDefinition definition)1418 void registerRemoteAnimations(RemoteAnimationDefinition definition) { 1419 mAppTransitionController.registerRemoteAnimations(definition); 1420 } 1421 reconfigureDisplayLocked()1422 void reconfigureDisplayLocked() { 1423 if (!isReady()) { 1424 return; 1425 } 1426 configureDisplayPolicy(); 1427 setLayoutNeeded(); 1428 1429 boolean configChanged = updateOrientation(); 1430 final Configuration currentDisplayConfig = getConfiguration(); 1431 mTmpConfiguration.setTo(currentDisplayConfig); 1432 computeScreenConfiguration(mTmpConfiguration); 1433 final int changes = currentDisplayConfig.diff(mTmpConfiguration); 1434 configChanged |= changes != 0; 1435 1436 if (configChanged) { 1437 mWaitingForConfig = true; 1438 if (mTransitionController.isShellTransitionsEnabled()) { 1439 requestChangeTransitionIfNeeded(changes); 1440 } else { 1441 mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */, this); 1442 } 1443 sendNewConfiguration(); 1444 } 1445 1446 mWmService.mWindowPlacerLocked.performSurfacePlacement(); 1447 } 1448 sendNewConfiguration()1449 void sendNewConfiguration() { 1450 if (!isReady()) { 1451 return; 1452 } 1453 if (mDisplayRotation.isWaitingForRemoteRotation()) { 1454 return; 1455 } 1456 1457 final boolean configUpdated = updateDisplayOverrideConfigurationLocked(); 1458 if (configUpdated) { 1459 return; 1460 } 1461 1462 // The display configuration doesn't change. If there is a launching transformed app, that 1463 // means its request to change display configuration has been discarded, then it should 1464 // respect to the current configuration of display. 1465 clearFixedRotationLaunchingApp(); 1466 1467 // Something changed (E.g. device rotation), but no configuration update is needed. 1468 // E.g. changing device rotation by 180 degrees. Go ahead and perform surface placement to 1469 // unfreeze the display since we froze it when the rotation was updated in 1470 // DisplayContent#updateRotationUnchecked. 1471 if (mWaitingForConfig) { 1472 mWaitingForConfig = false; 1473 mWmService.mLastFinishedFreezeSource = "config-unchanged"; 1474 setLayoutNeeded(); 1475 mWmService.mWindowPlacerLocked.performSurfacePlacement(); 1476 } 1477 } 1478 1479 @Override onDescendantOrientationChanged(WindowContainer requestingContainer)1480 boolean onDescendantOrientationChanged(WindowContainer requestingContainer) { 1481 final Configuration config = updateOrientation( 1482 getRequestedOverrideConfiguration(), requestingContainer, false /* forceUpdate */); 1483 // If display rotation class tells us that it doesn't consider app requested orientation, 1484 // this display won't rotate just because of an app changes its requested orientation. Thus 1485 // it indicates that this display chooses not to handle this request. 1486 final boolean handled = handlesOrientationChangeFromDescendant(); 1487 if (config == null) { 1488 return handled; 1489 } 1490 1491 if (handled && requestingContainer instanceof ActivityRecord) { 1492 final ActivityRecord activityRecord = (ActivityRecord) requestingContainer; 1493 final boolean kept = updateDisplayOverrideConfigurationLocked(config, activityRecord, 1494 false /* deferResume */, null /* result */); 1495 activityRecord.frozenBeforeDestroy = true; 1496 if (!kept) { 1497 mRootWindowContainer.resumeFocusedTasksTopActivities(); 1498 } 1499 } else { 1500 // We have a new configuration to push so we need to update ATMS for now. 1501 // TODO: Clean up display configuration push between ATMS and WMS after unification. 1502 updateDisplayOverrideConfigurationLocked(config, null /* starting */, 1503 false /* deferResume */, null); 1504 } 1505 return handled; 1506 } 1507 1508 @Override handlesOrientationChangeFromDescendant()1509 boolean handlesOrientationChangeFromDescendant() { 1510 return !mIgnoreOrientationRequest && !getDisplayRotation().isFixedToUserRotation(); 1511 } 1512 1513 /** 1514 * Determine the new desired orientation of this display. 1515 * 1516 * @see #getOrientation() 1517 * @return {@code true} if the orientation is changed and the caller should call 1518 * {@link #sendNewConfiguration} if the method returns {@code true}. 1519 */ updateOrientation()1520 boolean updateOrientation() { 1521 return updateOrientation(false /* forceUpdate */); 1522 } 1523 1524 /** 1525 * Update orientation of the display, returning a non-null new Configuration if it has 1526 * changed from the current orientation. If a non-null configuration is returned, someone must 1527 * call {@link WindowManagerService#setNewDisplayOverrideConfiguration(Configuration, 1528 * DisplayContent)} to tell the window manager it can unfreeze the screen. This will typically 1529 * be done by calling {@link #sendNewConfiguration}. 1530 * 1531 * @param currentConfig The current requested override configuration (it is usually set from 1532 * the last {@link #sendNewConfiguration}) of the display. It is used to 1533 * check if the configuration container has the latest state. 1534 * @param freezeDisplayWindow Freeze the app window if the orientation is changed. 1535 * @param forceUpdate See {@link DisplayRotation#updateRotationUnchecked(boolean)} 1536 */ updateOrientation(Configuration currentConfig, WindowContainer freezeDisplayWindow, boolean forceUpdate)1537 Configuration updateOrientation(Configuration currentConfig, 1538 WindowContainer freezeDisplayWindow, boolean forceUpdate) { 1539 if (!mDisplayReady) { 1540 return null; 1541 } 1542 1543 Configuration config = null; 1544 if (updateOrientation(forceUpdate)) { 1545 // If we changed the orientation but mOrientationChangeComplete is already true, 1546 // we used seamless rotation, and we don't need to freeze the screen. 1547 if (freezeDisplayWindow != null && !mWmService.mRoot.mOrientationChangeComplete) { 1548 final ActivityRecord activity = freezeDisplayWindow.asActivityRecord(); 1549 if (activity != null && activity.mayFreezeScreenLocked()) { 1550 activity.startFreezingScreen(); 1551 } 1552 } 1553 config = new Configuration(); 1554 computeScreenConfiguration(config); 1555 } else if (currentConfig != null 1556 // If waiting for a remote rotation, don't prematurely update configuration. 1557 && !(mDisplayRotation.isWaitingForRemoteRotation() 1558 || mTransitionController.isCollecting(this))) { 1559 // No obvious action we need to take, but if our current state mismatches the 1560 // activity manager's, update it, disregarding font scale, which should remain set 1561 // to the value of the previous configuration. 1562 // Here we're calling Configuration#unset() instead of setToDefaults() because we 1563 // need to keep override configs clear of non-empty values (e.g. fontSize). 1564 mTmpConfiguration.unset(); 1565 mTmpConfiguration.updateFrom(currentConfig); 1566 computeScreenConfiguration(mTmpConfiguration); 1567 if (currentConfig.diff(mTmpConfiguration) != 0) { 1568 mWaitingForConfig = true; 1569 setLayoutNeeded(); 1570 mDisplayRotation.prepareNormalRotationAnimation(); 1571 config = new Configuration(mTmpConfiguration); 1572 } 1573 } 1574 1575 return config; 1576 } 1577 updateOrientation(boolean forceUpdate)1578 private boolean updateOrientation(boolean forceUpdate) { 1579 final int orientation = getOrientation(); 1580 // The last orientation source is valid only after getOrientation. 1581 final WindowContainer orientationSource = getLastOrientationSource(); 1582 final ActivityRecord r = 1583 orientationSource != null ? orientationSource.asActivityRecord() : null; 1584 if (r != null) { 1585 final Task task = r.getTask(); 1586 if (task != null && orientation != task.mLastReportedRequestedOrientation) { 1587 task.mLastReportedRequestedOrientation = orientation; 1588 mAtmService.getTaskChangeNotificationController() 1589 .notifyTaskRequestedOrientationChanged(task.mTaskId, orientation); 1590 } 1591 // Currently there is no use case from non-activity. 1592 if (handleTopActivityLaunchingInDifferentOrientation(r, true /* checkOpening */)) { 1593 // Display orientation should be deferred until the top fixed rotation is finished. 1594 return false; 1595 } 1596 } 1597 return mDisplayRotation.updateOrientation(orientation, forceUpdate); 1598 } 1599 1600 @Override isSyncFinished()1601 boolean isSyncFinished() { 1602 if (mDisplayRotation.isWaitingForRemoteRotation()) return false; 1603 return super.isSyncFinished(); 1604 } 1605 1606 /** 1607 * Returns a valid rotation if the activity can use different orientation than the display. 1608 * Otherwise {@link #ROTATION_UNDEFINED}. 1609 */ 1610 @Rotation rotationForActivityInDifferentOrientation(@onNull ActivityRecord r)1611 int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) { 1612 if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) { 1613 return ROTATION_UNDEFINED; 1614 } 1615 if (r.inMultiWindowMode() || r.getRequestedConfigurationOrientation(true /* forDisplay */) 1616 == getConfiguration().orientation) { 1617 return ROTATION_UNDEFINED; 1618 } 1619 final int currentRotation = getRotation(); 1620 final int rotation = mDisplayRotation.rotationForOrientation(r.getRequestedOrientation(), 1621 currentRotation); 1622 if (rotation == currentRotation) { 1623 return ROTATION_UNDEFINED; 1624 } 1625 return rotation; 1626 } 1627 1628 /** 1629 * We need to keep display rotation fixed for a while when the activity in different orientation 1630 * is launching until the launch animation is done to avoid showing the previous activity 1631 * inadvertently in a wrong orientation. 1632 * 1633 * @param r The launching activity which may change display orientation. 1634 * @param checkOpening Whether to check if the activity is animating by transition. Set to 1635 * {@code true} if the caller is not sure whether the activity is launching. 1636 * @return {@code true} if the fixed rotation is started. 1637 */ handleTopActivityLaunchingInDifferentOrientation(@onNull ActivityRecord r, boolean checkOpening)1638 boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r, 1639 boolean checkOpening) { 1640 if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) { 1641 return false; 1642 } 1643 if (r.isFinishingFixedRotationTransform()) { 1644 return false; 1645 } 1646 if (r.hasFixedRotationTransform()) { 1647 // It has been set and not yet finished. 1648 return true; 1649 } 1650 if (!r.occludesParent() || r.isVisible()) { 1651 // While entering or leaving a translucent or floating activity (e.g. dialog style), 1652 // there is a visible activity in the background. Then it still needs rotation animation 1653 // to cover the activity configuration change. 1654 return false; 1655 } 1656 if (checkOpening) { 1657 if (!mAppTransition.isTransitionSet() || !mOpeningApps.contains(r)) { 1658 // Apply normal rotation animation in case of the activity set different requested 1659 // orientation without activity switch, or the transition is unset due to starting 1660 // window was transferred ({@link #mSkipAppTransitionAnimation}). 1661 return false; 1662 } 1663 if (r.isState(RESUMED) && !r.getRootTask().mInResumeTopActivity) { 1664 // If the activity is executing or has done the lifecycle callback, use normal 1665 // rotation animation so the display info can be updated immediately (see 1666 // updateDisplayAndOrientation). This prevents a compatibility issue such as 1667 // calling setRequestedOrientation in Activity#onCreate and then get display info. 1668 // If fixed rotation is applied, the display rotation will still be the old one, 1669 // unless the client side gets the rotation again after the adjustments arrive. 1670 return false; 1671 } 1672 } else if (r != topRunningActivity()) { 1673 // If the transition has not started yet, the activity must be the top. 1674 return false; 1675 } 1676 if (mLastWallpaperVisible && r.windowsCanBeWallpaperTarget() 1677 && mFixedRotationTransitionListener.mAnimatingRecents == null) { 1678 // Use normal rotation animation for orientation change of visible wallpaper if recents 1679 // animation is not running (it may be swiping to home). 1680 return false; 1681 } 1682 final int rotation = rotationForActivityInDifferentOrientation(r); 1683 if (rotation == ROTATION_UNDEFINED) { 1684 // The display rotation won't be changed by current top activity. The client side 1685 // adjustments of previous rotated activity should be cleared earlier. Otherwise if 1686 // the current top is in the same process, it may get the rotated state. The transform 1687 // will be cleared later with transition callback to ensure smooth animation. 1688 if (hasTopFixedRotationLaunchingApp()) { 1689 mFixedRotationLaunchingApp.notifyFixedRotationTransform(false /* enabled */); 1690 } 1691 return false; 1692 } 1693 if (!r.getDisplayArea().matchParentBounds()) { 1694 // Because the fixed rotated configuration applies to activity directly, if its parent 1695 // has it own policy for bounds, the activity bounds based on parent is unknown. 1696 return false; 1697 } 1698 1699 setFixedRotationLaunchingApp(r, rotation); 1700 return true; 1701 } 1702 1703 /** Returns {@code true} if the IME is possible to show on the launching activity. */ mayImeShowOnLaunchingActivity(@onNull ActivityRecord r)1704 boolean mayImeShowOnLaunchingActivity(@NonNull ActivityRecord r) { 1705 final WindowState win = r.findMainWindow(); 1706 if (win == null) { 1707 return false; 1708 } 1709 // See InputMethodManagerService#shouldRestoreImeVisibility that we expecting the IME 1710 // should be hidden when the window set the hidden softInputMode. 1711 final int softInputMode = win.mAttrs.softInputMode; 1712 switch (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) { 1713 case SOFT_INPUT_STATE_ALWAYS_HIDDEN: 1714 case SOFT_INPUT_STATE_HIDDEN: 1715 return false; 1716 } 1717 return r.mLastImeShown && mInputMethodWindow != null && mInputMethodWindow.mHasSurface 1718 && mInputMethodWindow.mViewVisibility == View.VISIBLE; 1719 } 1720 1721 /** Returns {@code true} if the top activity is transformed with the new rotation of display. */ hasTopFixedRotationLaunchingApp()1722 boolean hasTopFixedRotationLaunchingApp() { 1723 return mFixedRotationLaunchingApp != null 1724 // Ignore animating recents because it hasn't really become the top. 1725 && mFixedRotationLaunchingApp != mFixedRotationTransitionListener.mAnimatingRecents; 1726 } 1727 isFixedRotationLaunchingApp(ActivityRecord r)1728 boolean isFixedRotationLaunchingApp(ActivityRecord r) { 1729 return mFixedRotationLaunchingApp == r; 1730 } 1731 1732 @VisibleForTesting getFadeRotationAnimationController()1733 @Nullable FadeRotationAnimationController getFadeRotationAnimationController() { 1734 return mFadeRotationAnimationController; 1735 } 1736 setFixedRotationLaunchingAppUnchecked(@ullable ActivityRecord r)1737 void setFixedRotationLaunchingAppUnchecked(@Nullable ActivityRecord r) { 1738 setFixedRotationLaunchingAppUnchecked(r, ROTATION_UNDEFINED); 1739 } 1740 setFixedRotationLaunchingAppUnchecked(@ullable ActivityRecord r, int rotation)1741 void setFixedRotationLaunchingAppUnchecked(@Nullable ActivityRecord r, int rotation) { 1742 if (mFixedRotationLaunchingApp == null && r != null) { 1743 mWmService.mDisplayNotificationController.dispatchFixedRotationStarted(this, rotation); 1744 startFadeRotationAnimation( 1745 // Delay the hide animation to avoid blinking by clicking navigation bar that 1746 // may toggle fixed rotation in a short time. 1747 r == mFixedRotationTransitionListener.mAnimatingRecents /* shouldDebounce */); 1748 } else if (mFixedRotationLaunchingApp != null && r == null) { 1749 mWmService.mDisplayNotificationController.dispatchFixedRotationFinished(this); 1750 finishFadeRotationAnimationIfPossible(); 1751 } 1752 mFixedRotationLaunchingApp = r; 1753 } 1754 1755 /** 1756 * Sets the provided record to {@link #mFixedRotationLaunchingApp} if possible to apply fixed 1757 * rotation transform to it and indicate that the display may be rotated after it is launched. 1758 */ setFixedRotationLaunchingApp(@onNull ActivityRecord r, @Rotation int rotation)1759 void setFixedRotationLaunchingApp(@NonNull ActivityRecord r, @Rotation int rotation) { 1760 final WindowToken prevRotatedLaunchingApp = mFixedRotationLaunchingApp; 1761 if (prevRotatedLaunchingApp == r 1762 && r.getWindowConfiguration().getRotation() == rotation) { 1763 // The given launching app and target rotation are the same as the existing ones. 1764 return; 1765 } 1766 if (prevRotatedLaunchingApp != null 1767 && prevRotatedLaunchingApp.getWindowConfiguration().getRotation() == rotation 1768 // It is animating so we can expect there will have a transition callback. 1769 && prevRotatedLaunchingApp.isAnimating(TRANSITION | PARENTS)) { 1770 // It may be the case that multiple activities launch consecutively. Because their 1771 // rotation are the same, the transformed state can be shared to avoid duplicating 1772 // the heavy operations. This also benefits that the states of multiple activities 1773 // are handled together. 1774 r.linkFixedRotationTransform(prevRotatedLaunchingApp); 1775 if (r != mFixedRotationTransitionListener.mAnimatingRecents) { 1776 // Only update the record for normal activity so the display orientation can be 1777 // updated when the transition is done if it becomes the top. And the case of 1778 // recents can be handled when the recents animation is finished. 1779 setFixedRotationLaunchingAppUnchecked(r, rotation); 1780 } 1781 return; 1782 } 1783 1784 if (!r.hasFixedRotationTransform()) { 1785 startFixedRotationTransform(r, rotation); 1786 } 1787 setFixedRotationLaunchingAppUnchecked(r, rotation); 1788 if (prevRotatedLaunchingApp != null) { 1789 prevRotatedLaunchingApp.finishFixedRotationTransform(); 1790 } 1791 } 1792 1793 /** 1794 * Continue updating the orientation change of display if it was deferred by a top activity 1795 * launched in a different orientation. 1796 */ continueUpdateOrientationForDiffOrienLaunchingApp()1797 void continueUpdateOrientationForDiffOrienLaunchingApp() { 1798 if (mFixedRotationLaunchingApp == null) { 1799 return; 1800 } 1801 if (mPinnedTaskController.shouldDeferOrientationChange()) { 1802 // Wait for the PiP animation to finish. 1803 return; 1804 } 1805 // Update directly because the app which will change the orientation of display is ready. 1806 if (mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */)) { 1807 sendNewConfiguration(); 1808 return; 1809 } 1810 if (mDisplayRotation.isWaitingForRemoteRotation()) { 1811 // There is pending rotation change to apply. 1812 return; 1813 } 1814 // The orientation of display is not changed. 1815 clearFixedRotationLaunchingApp(); 1816 } 1817 1818 /** 1819 * Clears the {@link #mFixedRotationLaunchingApp} without applying rotation to display. It is 1820 * used when the display won't rotate (e.g. the orientation from sensor has updated again before 1821 * applying rotation to display) but the launching app has been transformed. So the record need 1822 * to be cleared and restored to stop using seamless rotation and rotated configuration. 1823 */ clearFixedRotationLaunchingApp()1824 private void clearFixedRotationLaunchingApp() { 1825 if (mFixedRotationLaunchingApp == null) { 1826 return; 1827 } 1828 mFixedRotationLaunchingApp.finishFixedRotationTransform(); 1829 setFixedRotationLaunchingAppUnchecked(null); 1830 } 1831 startFixedRotationTransform(WindowToken token, int rotation)1832 private void startFixedRotationTransform(WindowToken token, int rotation) { 1833 mTmpConfiguration.unset(); 1834 final DisplayInfo info = computeScreenConfiguration(mTmpConfiguration, rotation); 1835 final WmDisplayCutout cutout = calculateDisplayCutoutForRotation(rotation); 1836 final RoundedCorners roundedCorners = calculateRoundedCornersForRotation(rotation); 1837 final PrivacyIndicatorBounds indicatorBounds = 1838 calculatePrivacyIndicatorBoundsForRotation(rotation); 1839 final DisplayFrames displayFrames = new DisplayFrames(mDisplayId, new InsetsState(), info, 1840 cutout, roundedCorners, indicatorBounds); 1841 token.applyFixedRotationTransform(info, displayFrames, mTmpConfiguration); 1842 } 1843 1844 /** 1845 * If the provided {@link ActivityRecord} can be displayed in an orientation different from the 1846 * display's, it will be rotated to match its requested orientation. 1847 * 1848 * @see #rotationForActivityInDifferentOrientation(ActivityRecord). 1849 * @see WindowToken#applyFixedRotationTransform(DisplayInfo, DisplayFrames, Configuration) 1850 */ rotateInDifferentOrientationIfNeeded(ActivityRecord activityRecord)1851 void rotateInDifferentOrientationIfNeeded(ActivityRecord activityRecord) { 1852 int rotation = rotationForActivityInDifferentOrientation(activityRecord); 1853 if (rotation != ROTATION_UNDEFINED) { 1854 startFixedRotationTransform(activityRecord, rotation); 1855 } 1856 } 1857 1858 /** 1859 * Starts the hide animation for the windows which will be rotated seamlessly. 1860 * 1861 * @return {@code true} if the animation is executed right now. 1862 */ startFadeRotationAnimation(boolean shouldDebounce)1863 private boolean startFadeRotationAnimation(boolean shouldDebounce) { 1864 if (shouldDebounce) { 1865 mWmService.mH.postDelayed(() -> { 1866 synchronized (mWmService.mGlobalLock) { 1867 if (mFixedRotationLaunchingApp != null 1868 && startFadeRotationAnimation(false /* shouldDebounce */)) { 1869 // Apply the transaction so the animation leash can take effect immediately. 1870 getPendingTransaction().apply(); 1871 } 1872 } 1873 }, FIXED_ROTATION_HIDE_ANIMATION_DEBOUNCE_DELAY_MS); 1874 return false; 1875 } 1876 if (mFadeRotationAnimationController == null) { 1877 mFadeRotationAnimationController = new FadeRotationAnimationController(this); 1878 mFadeRotationAnimationController.hide(); 1879 return true; 1880 } 1881 return false; 1882 } 1883 1884 /** Re-show the previously hidden windows if all seamless rotated windows are done. */ finishFadeRotationAnimationIfPossible()1885 void finishFadeRotationAnimationIfPossible() { 1886 final FadeRotationAnimationController controller = mFadeRotationAnimationController; 1887 if (controller != null && !mDisplayRotation.hasSeamlessRotatingWindow()) { 1888 controller.show(); 1889 mFadeRotationAnimationController = null; 1890 } 1891 } 1892 1893 /** Shows the given window which may be hidden for screen frozen. */ finishFadeRotationAnimation(WindowState w)1894 void finishFadeRotationAnimation(WindowState w) { 1895 final FadeRotationAnimationController controller = mFadeRotationAnimationController; 1896 if (controller != null && controller.show(w.mToken)) { 1897 mFadeRotationAnimationController = null; 1898 } 1899 } 1900 1901 /** Returns {@code true} if the display should wait for the given window to stop freezing. */ waitForUnfreeze(WindowState w)1902 boolean waitForUnfreeze(WindowState w) { 1903 if (w.mForceSeamlesslyRotate) { 1904 // The window should look no different before and after rotation. 1905 return false; 1906 } 1907 final FadeRotationAnimationController controller = mFadeRotationAnimationController; 1908 return controller == null || !controller.isHandledToken(w.mToken); 1909 } 1910 notifyInsetsChanged(Consumer<WindowState> dispatchInsetsChanged)1911 void notifyInsetsChanged(Consumer<WindowState> dispatchInsetsChanged) { 1912 if (mFixedRotationLaunchingApp != null) { 1913 // The insets state of fixed rotation app is a rotated copy. Make sure the visibilities 1914 // of insets sources are consistent with the latest state. 1915 final InsetsState rotatedState = 1916 mFixedRotationLaunchingApp.getFixedRotationTransformInsetsState(); 1917 if (rotatedState != null) { 1918 final InsetsState state = mInsetsStateController.getRawInsetsState(); 1919 for (int i = 0; i < InsetsState.SIZE; i++) { 1920 final InsetsSource source = state.peekSource(i); 1921 if (source != null) { 1922 rotatedState.setSourceVisible(i, source.isVisible()); 1923 } 1924 } 1925 } 1926 } 1927 forAllWindows(dispatchInsetsChanged, true /* traverseTopToBottom */); 1928 if (mRemoteInsetsControlTarget != null) { 1929 mRemoteInsetsControlTarget.notifyInsetsChanged(); 1930 } 1931 } 1932 1933 /** 1934 * Update rotation of the display. 1935 * 1936 * @return {@code true} if the rotation has been changed. In this case YOU MUST CALL 1937 * {@link #sendNewConfiguration} TO UNFREEZE THE SCREEN unless using Shell transitions. 1938 */ updateRotationUnchecked()1939 boolean updateRotationUnchecked() { 1940 return mDisplayRotation.updateRotationUnchecked(false /* forceUpdate */); 1941 } 1942 1943 /** 1944 * Applies the rotation transaction. This must be called after {@link #updateRotationUnchecked} 1945 * (if it returned {@code true}) to actually finish the rotation. 1946 * 1947 * @param oldRotation the rotation we are coming from. 1948 * @param rotation the rotation to apply. 1949 */ applyRotation(final int oldRotation, final int rotation)1950 private void applyRotation(final int oldRotation, final int rotation) { 1951 mDisplayRotation.applyCurrentRotation(rotation); 1952 final boolean shellTransitions = mTransitionController.getTransitionPlayer() != null; 1953 final boolean rotateSeamlessly = 1954 mDisplayRotation.isRotatingSeamlessly() && !shellTransitions; 1955 final Transaction transaction = 1956 shellTransitions ? getSyncTransaction() : getPendingTransaction(); 1957 ScreenRotationAnimation screenRotationAnimation = rotateSeamlessly 1958 ? null : getRotationAnimation(); 1959 // We need to update our screen size information to match the new rotation. If the rotation 1960 // has actually changed then this method will return true and, according to the comment at 1961 // the top of the method, the caller is obligated to call computeNewConfigurationLocked(). 1962 // By updating the Display info here it will be available to 1963 // #computeScreenConfiguration() later. 1964 updateDisplayAndOrientation(getConfiguration().uiMode, null /* outConfig */); 1965 1966 // NOTE: We disable the rotation in the emulator because 1967 // it doesn't support hardware OpenGL emulation yet. 1968 if (screenRotationAnimation != null && screenRotationAnimation.hasScreenshot()) { 1969 screenRotationAnimation.setRotation(transaction, rotation); 1970 } 1971 1972 if (!shellTransitions) { 1973 forAllWindows(w -> { 1974 w.seamlesslyRotateIfAllowed(transaction, oldRotation, rotation, rotateSeamlessly); 1975 }, true /* traverseTopToBottom */); 1976 mPinnedTaskController.startSeamlessRotationIfNeeded(transaction, oldRotation, rotation); 1977 } 1978 1979 mWmService.mDisplayManagerInternal.performTraversal(transaction); 1980 scheduleAnimation(); 1981 1982 forAllWindows(w -> { 1983 if (w.mHasSurface && !rotateSeamlessly) { 1984 ProtoLog.v(WM_DEBUG_ORIENTATION, "Set mOrientationChanging of %s", w); 1985 w.setOrientationChanging(true); 1986 } 1987 w.mReportOrientationChanged = true; 1988 }, true /* traverseTopToBottom */); 1989 1990 for (int i = mWmService.mRotationWatchers.size() - 1; i >= 0; i--) { 1991 final WindowManagerService.RotationWatcher rotationWatcher 1992 = mWmService.mRotationWatchers.get(i); 1993 if (rotationWatcher.mDisplayId == mDisplayId) { 1994 try { 1995 rotationWatcher.mWatcher.onRotationChanged(rotation); 1996 } catch (RemoteException e) { 1997 // Ignore 1998 } 1999 } 2000 } 2001 } 2002 configureDisplayPolicy()2003 void configureDisplayPolicy() { 2004 final int width = mBaseDisplayWidth; 2005 final int height = mBaseDisplayHeight; 2006 final int shortSize; 2007 final int longSize; 2008 if (width > height) { 2009 shortSize = height; 2010 longSize = width; 2011 } else { 2012 shortSize = width; 2013 longSize = height; 2014 } 2015 2016 final int shortSizeDp = shortSize * DENSITY_DEFAULT / mBaseDisplayDensity; 2017 final int longSizeDp = longSize * DENSITY_DEFAULT / mBaseDisplayDensity; 2018 2019 mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors(); 2020 mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp); 2021 } 2022 2023 /** 2024 * Update {@link #mDisplayInfo} and other internal variables when display is rotated or config 2025 * changed. 2026 * Do not call if {@link WindowManagerService#mDisplayReady} == false. 2027 */ updateDisplayAndOrientation(int uiMode, Configuration outConfig)2028 private DisplayInfo updateDisplayAndOrientation(int uiMode, Configuration outConfig) { 2029 // Use the effective "visual" dimensions based on current rotation 2030 final int rotation = getRotation(); 2031 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); 2032 final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 2033 final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 2034 2035 // Update application display metrics. 2036 final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation); 2037 final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout(); 2038 final RoundedCorners roundedCorners = calculateRoundedCornersForRotation(rotation); 2039 2040 final Point appSize = mDisplayPolicy.getNonDecorDisplaySize(dw, dh, rotation, uiMode, 2041 displayCutout); 2042 mDisplayInfo.rotation = rotation; 2043 mDisplayInfo.logicalWidth = dw; 2044 mDisplayInfo.logicalHeight = dh; 2045 mDisplayInfo.logicalDensityDpi = mBaseDisplayDensity; 2046 mDisplayInfo.appWidth = appSize.x; 2047 mDisplayInfo.appHeight = appSize.y; 2048 if (isDefaultDisplay) { 2049 mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics, 2050 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 2051 } 2052 mDisplayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout; 2053 mDisplayInfo.roundedCorners = roundedCorners; 2054 mDisplayInfo.getAppMetrics(mDisplayMetrics); 2055 if (mDisplayScalingDisabled) { 2056 mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED; 2057 } else { 2058 mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED; 2059 } 2060 2061 computeSizeRangesAndScreenLayout(mDisplayInfo, rotated, uiMode, dw, dh, 2062 mDisplayMetrics.density, outConfig); 2063 2064 // We usually set the override info in DisplayManager so that we get consistent display 2065 // metrics values when displays are changing and don't send out new values until WM is aware 2066 // of them. However, we don't do this for displays that serve as containers for ActivityView 2067 // because we don't want letter-/pillar-boxing during resize. 2068 final DisplayInfo overrideDisplayInfo = mShouldOverrideDisplayConfiguration 2069 ? mDisplayInfo : null; 2070 mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId, 2071 overrideDisplayInfo); 2072 2073 mBaseDisplayRect.set(0, 0, dw, dh); 2074 2075 if (isDefaultDisplay) { 2076 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics, 2077 mCompatDisplayMetrics); 2078 } 2079 2080 onDisplayInfoChanged(); 2081 2082 return mDisplayInfo; 2083 } 2084 calculateDisplayCutoutForRotation(int rotation)2085 WmDisplayCutout calculateDisplayCutoutForRotation(int rotation) { 2086 return mDisplayCutoutCache.getOrCompute(mInitialDisplayCutout, rotation); 2087 } 2088 calculateDisplayCutoutForRotationUncached( DisplayCutout cutout, int rotation)2089 private WmDisplayCutout calculateDisplayCutoutForRotationUncached( 2090 DisplayCutout cutout, int rotation) { 2091 if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) { 2092 return WmDisplayCutout.NO_CUTOUT; 2093 } 2094 if (rotation == ROTATION_0) { 2095 return WmDisplayCutout.computeSafeInsets( 2096 cutout, mInitialDisplayWidth, mInitialDisplayHeight); 2097 } 2098 final Insets waterfallInsets = 2099 RotationUtils.rotateInsets(cutout.getWaterfallInsets(), rotation); 2100 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); 2101 final Rect[] newBounds = mRotationUtil.getRotatedBounds( 2102 cutout.getBoundingRectsAll(), 2103 rotation, mInitialDisplayWidth, mInitialDisplayHeight); 2104 final CutoutPathParserInfo info = cutout.getCutoutPathParserInfo(); 2105 final CutoutPathParserInfo newInfo = new CutoutPathParserInfo( 2106 info.getDisplayWidth(), info.getDisplayHeight(), info.getDensity(), 2107 info.getCutoutSpec(), rotation, info.getScale()); 2108 return WmDisplayCutout.computeSafeInsets( 2109 DisplayCutout.constructDisplayCutout(newBounds, waterfallInsets, newInfo), 2110 rotated ? mInitialDisplayHeight : mInitialDisplayWidth, 2111 rotated ? mInitialDisplayWidth : mInitialDisplayHeight); 2112 } 2113 calculateRoundedCornersForRotation(int rotation)2114 RoundedCorners calculateRoundedCornersForRotation(int rotation) { 2115 return mRoundedCornerCache.getOrCompute(mInitialRoundedCorners, rotation); 2116 } 2117 calculateRoundedCornersForRotationUncached( RoundedCorners roundedCorners, int rotation)2118 private RoundedCorners calculateRoundedCornersForRotationUncached( 2119 RoundedCorners roundedCorners, int rotation) { 2120 if (roundedCorners == null || roundedCorners == RoundedCorners.NO_ROUNDED_CORNERS) { 2121 return RoundedCorners.NO_ROUNDED_CORNERS; 2122 } 2123 2124 if (rotation == ROTATION_0) { 2125 return roundedCorners; 2126 } 2127 2128 return roundedCorners.rotate(rotation, mInitialDisplayWidth, mInitialDisplayHeight); 2129 } 2130 calculatePrivacyIndicatorBoundsForRotation(int rotation)2131 PrivacyIndicatorBounds calculatePrivacyIndicatorBoundsForRotation(int rotation) { 2132 return mPrivacyIndicatorBoundsCache.getOrCompute(mCurrentPrivacyIndicatorBounds, rotation); 2133 } 2134 calculatePrivacyIndicatorBoundsForRotationUncached( PrivacyIndicatorBounds bounds, int rotation)2135 private PrivacyIndicatorBounds calculatePrivacyIndicatorBoundsForRotationUncached( 2136 PrivacyIndicatorBounds bounds, int rotation) { 2137 if (bounds == null) { 2138 return new PrivacyIndicatorBounds(new Rect[4], rotation); 2139 } 2140 2141 return bounds.rotate(rotation); 2142 } 2143 2144 /** 2145 * Compute display info and configuration according to the given rotation without changing 2146 * current display. 2147 */ computeScreenConfiguration(Configuration outConfig, int rotation)2148 DisplayInfo computeScreenConfiguration(Configuration outConfig, int rotation) { 2149 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); 2150 final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 2151 final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 2152 outConfig.windowConfiguration.setMaxBounds(0, 0, dw, dh); 2153 outConfig.windowConfiguration.setBounds(outConfig.windowConfiguration.getMaxBounds()); 2154 2155 final int uiMode = getConfiguration().uiMode; 2156 final DisplayCutout displayCutout = 2157 calculateDisplayCutoutForRotation(rotation).getDisplayCutout(); 2158 computeScreenAppConfiguration(outConfig, dw, dh, rotation, uiMode, displayCutout); 2159 2160 final DisplayInfo displayInfo = new DisplayInfo(mDisplayInfo); 2161 displayInfo.rotation = rotation; 2162 displayInfo.logicalWidth = dw; 2163 displayInfo.logicalHeight = dh; 2164 final Rect appBounds = outConfig.windowConfiguration.getAppBounds(); 2165 displayInfo.appWidth = appBounds.width(); 2166 displayInfo.appHeight = appBounds.height(); 2167 displayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout; 2168 computeSizeRangesAndScreenLayout(displayInfo, rotated, uiMode, dw, dh, 2169 mDisplayMetrics.density, outConfig); 2170 return displayInfo; 2171 } 2172 2173 /** Compute configuration related to application without changing current display. */ computeScreenAppConfiguration(Configuration outConfig, int dw, int dh, int rotation, int uiMode, DisplayCutout displayCutout)2174 private void computeScreenAppConfiguration(Configuration outConfig, int dw, int dh, 2175 int rotation, int uiMode, DisplayCutout displayCutout) { 2176 final Point appSize = mDisplayPolicy.getNonDecorDisplaySize(dw, dh, rotation, uiMode, 2177 displayCutout); 2178 mDisplayPolicy.getNonDecorInsetsLw(rotation, dw, dh, displayCutout, mTmpRect); 2179 final int leftInset = mTmpRect.left; 2180 final int topInset = mTmpRect.top; 2181 // AppBounds at the root level should mirror the app screen size. 2182 outConfig.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */, 2183 leftInset + appSize.x /* right */, topInset + appSize.y /* bottom */); 2184 outConfig.windowConfiguration.setRotation(rotation); 2185 outConfig.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; 2186 2187 final float density = mDisplayMetrics.density; 2188 final Point configSize = mDisplayPolicy.getConfigDisplaySize(dw, dh, rotation, uiMode, 2189 displayCutout); 2190 outConfig.screenWidthDp = (int) (configSize.x / density); 2191 outConfig.screenHeightDp = (int) (configSize.y / density); 2192 outConfig.compatScreenWidthDp = (int) (outConfig.screenWidthDp / mCompatibleScreenScale); 2193 outConfig.compatScreenHeightDp = (int) (outConfig.screenHeightDp / mCompatibleScreenScale); 2194 2195 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); 2196 outConfig.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, uiMode, dw, 2197 dh); 2198 } 2199 2200 /** 2201 * Compute display configuration based on display properties and policy settings. 2202 * Do not call if mDisplayReady == false. 2203 */ computeScreenConfiguration(Configuration config)2204 void computeScreenConfiguration(Configuration config) { 2205 final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config); 2206 calculateBounds(displayInfo, mTmpBounds); 2207 config.windowConfiguration.setBounds(mTmpBounds); 2208 config.windowConfiguration.setMaxBounds(mTmpBounds); 2209 config.windowConfiguration.setWindowingMode(getWindowingMode()); 2210 config.windowConfiguration.setDisplayWindowingMode(getWindowingMode()); 2211 2212 final int dw = displayInfo.logicalWidth; 2213 final int dh = displayInfo.logicalHeight; 2214 computeScreenAppConfiguration(config, dw, dh, displayInfo.rotation, config.uiMode, 2215 displayInfo.displayCutout); 2216 2217 config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK) 2218 | ((displayInfo.flags & Display.FLAG_ROUND) != 0 2219 ? Configuration.SCREENLAYOUT_ROUND_YES 2220 : Configuration.SCREENLAYOUT_ROUND_NO); 2221 2222 config.densityDpi = displayInfo.logicalDensityDpi; 2223 2224 config.colorMode = 2225 ((displayInfo.isHdr() && mWmService.hasHdrSupport()) 2226 ? Configuration.COLOR_MODE_HDR_YES 2227 : Configuration.COLOR_MODE_HDR_NO) 2228 | (displayInfo.isWideColorGamut() && mWmService.hasWideColorGamutSupport() 2229 ? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES 2230 : Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO); 2231 2232 // Update the configuration based on available input devices, lid switch, 2233 // and platform configuration. 2234 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 2235 config.keyboard = Configuration.KEYBOARD_NOKEYS; 2236 config.navigation = Configuration.NAVIGATION_NONAV; 2237 2238 int keyboardPresence = 0; 2239 int navigationPresence = 0; 2240 final InputDevice[] devices = mWmService.mInputManager.getInputDevices(); 2241 final int len = devices != null ? devices.length : 0; 2242 for (int i = 0; i < len; i++) { 2243 InputDevice device = devices[i]; 2244 // Ignore virtual input device. 2245 if (device.isVirtual()) { 2246 continue; 2247 } 2248 2249 // Check if input device can dispatch events to current display. 2250 if (!mWmService.mInputManager.canDispatchToDisplay(device.getId(), mDisplayId)) { 2251 continue; 2252 } 2253 2254 final int sources = device.getSources(); 2255 final int presenceFlag = device.isExternal() 2256 ? WindowManagerPolicy.PRESENCE_EXTERNAL : WindowManagerPolicy.PRESENCE_INTERNAL; 2257 2258 if (mWmService.mIsTouchDevice) { 2259 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) { 2260 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 2261 } 2262 } else { 2263 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 2264 } 2265 2266 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 2267 config.navigation = Configuration.NAVIGATION_TRACKBALL; 2268 navigationPresence |= presenceFlag; 2269 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 2270 && config.navigation == Configuration.NAVIGATION_NONAV) { 2271 config.navigation = Configuration.NAVIGATION_DPAD; 2272 navigationPresence |= presenceFlag; 2273 } 2274 2275 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 2276 config.keyboard = Configuration.KEYBOARD_QWERTY; 2277 keyboardPresence |= presenceFlag; 2278 } 2279 } 2280 2281 if (config.navigation == Configuration.NAVIGATION_NONAV && mWmService.mHasPermanentDpad) { 2282 config.navigation = Configuration.NAVIGATION_DPAD; 2283 navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL; 2284 } 2285 2286 // Determine whether a hard keyboard is available and enabled. 2287 // TODO(multi-display): Should the hardware keyboard be tied to a display or to a device? 2288 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 2289 if (hardKeyboardAvailable != mWmService.mHardKeyboardAvailable) { 2290 mWmService.mHardKeyboardAvailable = hardKeyboardAvailable; 2291 mWmService.mH.removeMessages(REPORT_HARD_KEYBOARD_STATUS_CHANGE); 2292 mWmService.mH.sendEmptyMessage(REPORT_HARD_KEYBOARD_STATUS_CHANGE); 2293 } 2294 2295 mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors(); 2296 2297 // Let the policy update hidden states. 2298 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 2299 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 2300 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 2301 mWmService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 2302 } 2303 computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh)2304 private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh) { 2305 mTmpDisplayMetrics.setTo(mDisplayMetrics); 2306 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 2307 final int unrotDw, unrotDh; 2308 if (rotated) { 2309 unrotDw = dh; 2310 unrotDh = dw; 2311 } else { 2312 unrotDw = dw; 2313 unrotDh = dh; 2314 } 2315 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, 2316 unrotDh); 2317 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, 2318 unrotDw); 2319 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, 2320 unrotDh); 2321 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, 2322 unrotDw); 2323 return sw; 2324 } 2325 reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, DisplayMetrics dm, int dw, int dh)2326 private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, 2327 DisplayMetrics dm, int dw, int dh) { 2328 final DisplayCutout displayCutout = calculateDisplayCutoutForRotation( 2329 rotation).getDisplayCutout(); 2330 final Point nonDecorSize = mDisplayPolicy.getNonDecorDisplaySize(dw, dh, rotation, uiMode, 2331 displayCutout); 2332 dm.noncompatWidthPixels = nonDecorSize.x; 2333 dm.noncompatHeightPixels = nonDecorSize.y; 2334 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 2335 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 2336 if (curSize == 0 || size < curSize) { 2337 curSize = size; 2338 } 2339 return curSize; 2340 } 2341 computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig)2342 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 2343 int uiMode, int dw, int dh, float density, Configuration outConfig) { 2344 2345 // We need to determine the smallest width that will occur under normal 2346 // operation. To this, start with the base screen size and compute the 2347 // width under the different possible rotations. We need to un-rotate 2348 // the current screen dimensions before doing this. 2349 int unrotDw, unrotDh; 2350 if (rotated) { 2351 unrotDw = dh; 2352 unrotDh = dw; 2353 } else { 2354 unrotDw = dw; 2355 unrotDh = dh; 2356 } 2357 displayInfo.smallestNominalAppWidth = 1<<30; 2358 displayInfo.smallestNominalAppHeight = 1<<30; 2359 displayInfo.largestNominalAppWidth = 0; 2360 displayInfo.largestNominalAppHeight = 0; 2361 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh); 2362 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw); 2363 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh); 2364 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw); 2365 2366 if (outConfig == null) { 2367 return; 2368 } 2369 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 2370 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode); 2371 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode); 2372 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode); 2373 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode); 2374 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 2375 outConfig.screenLayout = sl; 2376 } 2377 reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, int uiMode)2378 private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, 2379 int uiMode) { 2380 // Get the display cutout at this rotation. 2381 final DisplayCutout displayCutout = calculateDisplayCutoutForRotation( 2382 rotation).getDisplayCutout(); 2383 2384 // Get the app screen size at this rotation. 2385 final Point size = mDisplayPolicy.getNonDecorDisplaySize(dw, dh, rotation, uiMode, 2386 displayCutout); 2387 2388 // Compute the screen layout size class for this rotation. 2389 int longSize = size.x; 2390 int shortSize = size.y; 2391 if (longSize < shortSize) { 2392 int tmp = longSize; 2393 longSize = shortSize; 2394 shortSize = tmp; 2395 } 2396 longSize = (int)(longSize/density); 2397 shortSize = (int)(shortSize/density); 2398 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 2399 } 2400 adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode, int dw, int dh)2401 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, 2402 int uiMode, int dw, int dh) { 2403 final DisplayCutout displayCutout = calculateDisplayCutoutForRotation( 2404 rotation).getDisplayCutout(); 2405 final Point size = mDisplayPolicy.getConfigDisplaySize(dw, dh, rotation, uiMode, 2406 displayCutout); 2407 if (size.x < displayInfo.smallestNominalAppWidth) { 2408 displayInfo.smallestNominalAppWidth = size.x; 2409 } 2410 if (size.x > displayInfo.largestNominalAppWidth) { 2411 displayInfo.largestNominalAppWidth = size.x; 2412 } 2413 if (size.y < displayInfo.smallestNominalAppHeight) { 2414 displayInfo.smallestNominalAppHeight = size.y; 2415 } 2416 if (size.y > displayInfo.largestNominalAppHeight) { 2417 displayInfo.largestNominalAppHeight = size.y; 2418 } 2419 } 2420 2421 /** 2422 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 2423 * theme attribute) on devices that feature a physical options menu key attempt to position 2424 * their menu panel window along the edge of the screen nearest the physical menu key. 2425 * This lowers the travel distance between invoking the menu panel and selecting 2426 * a menu option. 2427 * 2428 * This method helps control where that menu is placed. Its current implementation makes 2429 * assumptions about the menu key and its relationship to the screen based on whether 2430 * the device's natural orientation is portrait (width < height) or landscape. 2431 * 2432 * The menu key is assumed to be located along the bottom edge of natural-portrait 2433 * devices and along the right edge of natural-landscape devices. If these assumptions 2434 * do not hold for the target device, this method should be changed to reflect that. 2435 * 2436 * @return A {@link Gravity} value for placing the options menu window. 2437 */ getPreferredOptionsPanelGravity()2438 int getPreferredOptionsPanelGravity() { 2439 final int rotation = getRotation(); 2440 if (mInitialDisplayWidth < mInitialDisplayHeight) { 2441 // On devices with a natural orientation of portrait. 2442 switch (rotation) { 2443 default: 2444 case Surface.ROTATION_0: 2445 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 2446 case Surface.ROTATION_90: 2447 return Gravity.RIGHT | Gravity.BOTTOM; 2448 case Surface.ROTATION_180: 2449 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 2450 case Surface.ROTATION_270: 2451 return Gravity.START | Gravity.BOTTOM; 2452 } 2453 } 2454 2455 // On devices with a natural orientation of landscape. 2456 switch (rotation) { 2457 default: 2458 case Surface.ROTATION_0: 2459 return Gravity.RIGHT | Gravity.BOTTOM; 2460 case Surface.ROTATION_90: 2461 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 2462 case Surface.ROTATION_180: 2463 return Gravity.START | Gravity.BOTTOM; 2464 case Surface.ROTATION_270: 2465 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 2466 } 2467 } 2468 getDockedDividerController()2469 DockedTaskDividerController getDockedDividerController() { 2470 return mDividerControllerLocked; 2471 } 2472 getPinnedTaskController()2473 PinnedTaskController getPinnedTaskController() { 2474 return mPinnedTaskController; 2475 } 2476 2477 /** 2478 * Returns true if the specified UID has access to this display. 2479 */ hasAccess(int uid)2480 boolean hasAccess(int uid) { 2481 return mDisplay.hasAccess(uid); 2482 } 2483 isPrivate()2484 boolean isPrivate() { 2485 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; 2486 } 2487 isTrusted()2488 boolean isTrusted() { 2489 return mDisplay.isTrusted(); 2490 } 2491 2492 /** 2493 * Returns the topmost root task on the display that is compatible with the input windowing 2494 * mode and activity type. Null is no compatible root task on the display. 2495 */ 2496 @Nullable getRootTask(int windowingMode, int activityType)2497 Task getRootTask(int windowingMode, int activityType) { 2498 return getItemFromTaskDisplayAreas(taskDisplayArea -> 2499 taskDisplayArea.getRootTask(windowingMode, activityType)); 2500 } 2501 2502 @Nullable getRootTask(int rootTaskId)2503 Task getRootTask(int rootTaskId) { 2504 return getRootTask(rootTask -> rootTask.getRootTaskId() == rootTaskId); 2505 } 2506 getRootTaskCount()2507 int getRootTaskCount() { 2508 final int[] count = new int[1]; 2509 forAllRootTasks(task -> { 2510 count[0]++; 2511 }); 2512 return count[0]; 2513 } 2514 2515 @Nullable getTopRootTask()2516 Task getTopRootTask() { 2517 return getRootTask(t -> true); 2518 } 2519 2520 /** 2521 * The value is only valid in the scope {@link #onRequestedOverrideConfigurationChanged} of the 2522 * changing hierarchy and the {@link #onConfigurationChanged} of its children. 2523 * 2524 * @return The current changes ({@link android.content.pm.ActivityInfo.Config}) of requested 2525 * override configuration. 2526 */ getCurrentOverrideConfigurationChanges()2527 int getCurrentOverrideConfigurationChanges() { 2528 return mCurrentOverrideConfigurationChanges; 2529 } 2530 2531 @Override onConfigurationChanged(Configuration newParentConfig)2532 public void onConfigurationChanged(Configuration newParentConfig) { 2533 final int lastOrientation = getConfiguration().orientation; 2534 super.onConfigurationChanged(newParentConfig); 2535 if (mDisplayPolicy != null) { 2536 mDisplayPolicy.onConfigurationChanged(); 2537 mPinnedTaskController.onPostDisplayConfigurationChanged(); 2538 } 2539 // Update IME parent if needed. 2540 updateImeParent(); 2541 2542 // Update mirroring surface for MediaProjection, if this DisplayContent is being used 2543 // for layer mirroring. 2544 if (isCurrentlyMirroring() && mLastMirroredDisplayAreaBounds != null) { 2545 // Mirroring has already begun, but update mirroring since the display is now on. 2546 final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer( 2547 mTokenToMirror); 2548 if (wc == null) { 2549 ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, 2550 "Unable to retrieve window container to update layer mirroring for " 2551 + "display %d", 2552 mDisplayId); 2553 return; 2554 } 2555 2556 ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, 2557 "Display %d was already layer mirroring, so apply transformations if necessary", 2558 mDisplayId); 2559 // Retrieve the size of the DisplayArea to mirror, and continue with the update 2560 // if the bounds or orientation has changed. 2561 final Rect displayAreaBounds = wc.getDisplayContent().getBounds(); 2562 int displayAreaOrientation = wc.getDisplayContent().getOrientation(); 2563 if (!mLastMirroredDisplayAreaBounds.equals(displayAreaBounds) 2564 || lastOrientation != displayAreaOrientation) { 2565 Point surfaceSize = fetchSurfaceSizeIfPresent(); 2566 if (surfaceSize != null) { 2567 ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, 2568 "Going ahead with updating layer mirroring for display %d to new " 2569 + "bounds %s and/or orientation %d.", 2570 mDisplayId, displayAreaBounds, displayAreaOrientation); 2571 updateMirroredSurface(mWmService.mTransactionFactory.get(), 2572 displayAreaBounds, surfaceSize); 2573 } else { 2574 // If the surface removed, do nothing. We will handle this via onDisplayChanged 2575 // (the display will be off if the surface is removed). 2576 ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, 2577 "Unable to update layer mirroring for display %d to new bounds %s" 2578 + " and/or orientation %d, since the surface is not available.", 2579 mDisplayId, displayAreaBounds, displayAreaOrientation); 2580 } 2581 } 2582 } 2583 2584 if (lastOrientation != getConfiguration().orientation) { 2585 getMetricsLogger().write( 2586 new LogMaker(MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED) 2587 .setSubtype(getConfiguration().orientation) 2588 .addTaggedData(MetricsEvent.FIELD_DISPLAY_ID, getDisplayId())); 2589 } 2590 } 2591 2592 @Override fillsParent()2593 boolean fillsParent() { 2594 return true; 2595 } 2596 2597 @Override isVisible()2598 boolean isVisible() { 2599 return true; 2600 } 2601 2602 @Override isVisibleRequested()2603 boolean isVisibleRequested() { 2604 return isVisible() && !mRemoved && !mRemoving; 2605 } 2606 2607 @Override onAppTransitionDone()2608 void onAppTransitionDone() { 2609 super.onAppTransitionDone(); 2610 mWmService.mWindowsChanged = true; 2611 // If the transition finished callback cannot match the token for some reason, make sure the 2612 // rotated state is cleared if it is already invisible. 2613 if (mFixedRotationLaunchingApp != null && !mFixedRotationLaunchingApp.mVisibleRequested 2614 && !mFixedRotationLaunchingApp.isVisible() 2615 && !mDisplayRotation.isRotatingSeamlessly()) { 2616 clearFixedRotationLaunchingApp(); 2617 } 2618 } 2619 2620 @Override setWindowingMode(int windowingMode)2621 public void setWindowingMode(int windowingMode) { 2622 // Intentionally call onRequestedOverrideConfigurationChanged() directly to change windowing 2623 // mode and display windowing mode atomically. 2624 mTmpConfiguration.setTo(getRequestedOverrideConfiguration()); 2625 mTmpConfiguration.windowConfiguration.setWindowingMode(windowingMode); 2626 mTmpConfiguration.windowConfiguration.setDisplayWindowingMode(windowingMode); 2627 onRequestedOverrideConfigurationChanged(mTmpConfiguration); 2628 } 2629 2630 @Override setDisplayWindowingMode(int windowingMode)2631 void setDisplayWindowingMode(int windowingMode) { 2632 setWindowingMode(windowingMode); 2633 } 2634 2635 /** 2636 * See {@code WindowState#applyImeWindowsIfNeeded} for the details that we won't traverse the 2637 * IME window in some cases. 2638 */ forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)2639 boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 2640 return mImeWindowsContainer.forAllWindowForce(callback, traverseTopToBottom); 2641 } 2642 2643 /** 2644 * In the general case, the orientation is computed from the above app windows first. If none of 2645 * the above app windows specify orientation, the orientation is computed from the child window 2646 * container, e.g. {@link ActivityRecord#getOrientation(int)}. 2647 */ 2648 @ScreenOrientation 2649 @Override getOrientation()2650 int getOrientation() { 2651 mLastOrientationSource = null; 2652 if (!handlesOrientationChangeFromDescendant()) { 2653 // Return SCREEN_ORIENTATION_UNSPECIFIED so that Display respect sensor rotation 2654 ProtoLog.v(WM_DEBUG_ORIENTATION, 2655 "Display id=%d is ignoring all orientation requests, return %d", 2656 mDisplayId, SCREEN_ORIENTATION_UNSPECIFIED); 2657 return SCREEN_ORIENTATION_UNSPECIFIED; 2658 } 2659 2660 if (mWmService.mDisplayFrozen) { 2661 if (mWmService.mPolicy.isKeyguardLocked()) { 2662 // Use the last orientation the while the display is frozen with the keyguard 2663 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED 2664 // window. We don't want to check the show when locked window directly though as 2665 // things aren't stable while the display is frozen, for example the window could be 2666 // momentarily unavailable due to activity relaunch. 2667 ProtoLog.v(WM_DEBUG_ORIENTATION, 2668 "Display id=%d is frozen while keyguard locked, return %d", 2669 mDisplayId, getLastOrientation()); 2670 return getLastOrientation(); 2671 } 2672 } 2673 2674 final int orientation = super.getOrientation(); 2675 if (orientation == SCREEN_ORIENTATION_UNSET) { 2676 // Return SCREEN_ORIENTATION_UNSPECIFIED so that Display respect sensor rotation 2677 ProtoLog.v(WM_DEBUG_ORIENTATION, 2678 "No app or window is requesting an orientation, return %d for display id=%d", 2679 SCREEN_ORIENTATION_UNSPECIFIED, mDisplayId); 2680 return SCREEN_ORIENTATION_UNSPECIFIED; 2681 } 2682 2683 return orientation; 2684 } 2685 updateDisplayInfo()2686 void updateDisplayInfo() { 2687 // Check if display metrics changed and update base values if needed. 2688 updateBaseDisplayMetricsIfNeeded(); 2689 2690 mDisplay.getDisplayInfo(mDisplayInfo); 2691 mDisplay.getMetrics(mDisplayMetrics); 2692 2693 onDisplayInfoChanged(); 2694 onDisplayChanged(this); 2695 } 2696 updatePrivacyIndicatorBounds(Rect[] staticBounds)2697 void updatePrivacyIndicatorBounds(Rect[] staticBounds) { 2698 PrivacyIndicatorBounds oldBounds = mCurrentPrivacyIndicatorBounds; 2699 mCurrentPrivacyIndicatorBounds = 2700 mCurrentPrivacyIndicatorBounds.updateStaticBounds(staticBounds); 2701 if (!Objects.equals(oldBounds, mCurrentPrivacyIndicatorBounds)) { 2702 final DisplayInfo info = mDisplayInfo; 2703 if (mDisplayFrames.onDisplayInfoUpdated(info, 2704 calculateDisplayCutoutForRotation(info.rotation), 2705 calculateRoundedCornersForRotation(info.rotation), 2706 calculatePrivacyIndicatorBoundsForRotation(info.rotation))) { 2707 mInsetsStateController.onDisplayInfoUpdated(true); 2708 } 2709 } 2710 } 2711 onDisplayInfoChanged()2712 void onDisplayInfoChanged() { 2713 final DisplayInfo info = mDisplayInfo; 2714 if (mDisplayFrames.onDisplayInfoUpdated(info, 2715 calculateDisplayCutoutForRotation(info.rotation), 2716 calculateRoundedCornersForRotation(info.rotation), 2717 calculatePrivacyIndicatorBoundsForRotation(info.rotation))) { 2718 // TODO(b/161810301): Set notifyInsetsChange to true while the server no longer performs 2719 // layout. 2720 mInsetsStateController.onDisplayInfoUpdated(false /* notifyInsetsChanged */); 2721 } 2722 mInputMonitor.layoutInputConsumers(info.logicalWidth, info.logicalHeight); 2723 mDisplayPolicy.onDisplayInfoChanged(info); 2724 } 2725 2726 @Override onDisplayChanged(DisplayContent dc)2727 void onDisplayChanged(DisplayContent dc) { 2728 super.onDisplayChanged(dc); 2729 updateSystemGestureExclusionLimit(); 2730 } 2731 updateSystemGestureExclusionLimit()2732 void updateSystemGestureExclusionLimit() { 2733 mSystemGestureExclusionLimit = mWmService.mConstants.mSystemGestureExclusionLimitDp 2734 * mDisplayMetrics.densityDpi / DENSITY_DEFAULT; 2735 updateSystemGestureExclusion(); 2736 } 2737 initializeDisplayBaseInfo()2738 void initializeDisplayBaseInfo() { 2739 final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal; 2740 if (displayManagerInternal != null) { 2741 // Bootstrap the default logical display from the display manager. 2742 final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId); 2743 if (newDisplayInfo != null) { 2744 mDisplayInfo.copyFrom(newDisplayInfo); 2745 } 2746 } 2747 2748 updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, 2749 mDisplayInfo.logicalDensityDpi); 2750 mInitialDisplayWidth = mDisplayInfo.logicalWidth; 2751 mInitialDisplayHeight = mDisplayInfo.logicalHeight; 2752 mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; 2753 mInitialDisplayCutout = mDisplayInfo.displayCutout; 2754 mInitialRoundedCorners = mDisplayInfo.roundedCorners; 2755 mCurrentPrivacyIndicatorBounds = new PrivacyIndicatorBounds(new Rect[4], 2756 mDisplayInfo.rotation); 2757 } 2758 2759 /** 2760 * If display metrics changed, overrides are not set and it's not just a rotation - update base 2761 * values. 2762 */ updateBaseDisplayMetricsIfNeeded()2763 private void updateBaseDisplayMetricsIfNeeded() { 2764 // Get real display metrics without overrides from WM. 2765 mWmService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo); 2766 final int orientation = mDisplayInfo.rotation; 2767 final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); 2768 final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth; 2769 final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight; 2770 final int newDensity = mDisplayInfo.logicalDensityDpi; 2771 final DisplayCutout newCutout = mIgnoreDisplayCutout 2772 ? DisplayCutout.NO_CUTOUT : mDisplayInfo.displayCutout; 2773 final String newUniqueId = mDisplayInfo.uniqueId; 2774 final RoundedCorners newRoundedCorners = mDisplayInfo.roundedCorners; 2775 2776 final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth 2777 || mInitialDisplayHeight != newHeight 2778 || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi 2779 || !Objects.equals(mInitialDisplayCutout, newCutout) 2780 || !Objects.equals(mInitialRoundedCorners, newRoundedCorners); 2781 final boolean physicalDisplayChanged = !newUniqueId.equals(mCurrentUniqueDisplayId); 2782 2783 if (displayMetricsChanged || physicalDisplayChanged) { 2784 if (physicalDisplayChanged) { 2785 // Reapply the window settings as the underlying physical display has changed. 2786 mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this); 2787 } 2788 2789 // If there is an override set for base values - use it, otherwise use new values. 2790 updateBaseDisplayMetrics(mIsSizeForced ? mBaseDisplayWidth : newWidth, 2791 mIsSizeForced ? mBaseDisplayHeight : newHeight, 2792 mIsDensityForced ? mBaseDisplayDensity : newDensity); 2793 2794 // Real display metrics changed, so we should also update initial values. 2795 mInitialDisplayWidth = newWidth; 2796 mInitialDisplayHeight = newHeight; 2797 mInitialDisplayDensity = newDensity; 2798 mInitialDisplayCutout = newCutout; 2799 mInitialRoundedCorners = newRoundedCorners; 2800 mCurrentUniqueDisplayId = newUniqueId; 2801 reconfigureDisplayLocked(); 2802 } 2803 } 2804 2805 /** Sets the maximum width the screen resolution can be */ setMaxUiWidth(int width)2806 void setMaxUiWidth(int width) { 2807 if (DEBUG_DISPLAY) { 2808 Slog.v(TAG_WM, "Setting max ui width:" + width + " on display:" + getDisplayId()); 2809 } 2810 2811 mMaxUiWidth = width; 2812 2813 // Update existing metrics. 2814 updateBaseDisplayMetrics(mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity); 2815 } 2816 2817 /** Update base (override) display metrics. */ updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity)2818 void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) { 2819 final int originalWidth = mBaseDisplayWidth; 2820 final int originalHeight = mBaseDisplayHeight; 2821 final int originalDensity = mBaseDisplayDensity; 2822 2823 mBaseDisplayWidth = baseWidth; 2824 mBaseDisplayHeight = baseHeight; 2825 mBaseDisplayDensity = baseDensity; 2826 2827 if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) { 2828 mBaseDisplayHeight = (mMaxUiWidth * mBaseDisplayHeight) / mBaseDisplayWidth; 2829 mBaseDisplayWidth = mMaxUiWidth; 2830 2831 if (DEBUG_DISPLAY) { 2832 Slog.v(TAG_WM, "Applying config restraints:" + mBaseDisplayWidth + "x" 2833 + mBaseDisplayHeight + " on display:" + getDisplayId()); 2834 } 2835 } 2836 2837 if (mBaseDisplayWidth != originalWidth || mBaseDisplayHeight != originalHeight 2838 || mBaseDisplayDensity != originalDensity) { 2839 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); 2840 updateBounds(); 2841 } 2842 } 2843 2844 /** 2845 * Forces this display to use the specified density. 2846 * 2847 * @param density The density in DPI to use. If the value equals to initial density, the setting 2848 * will be cleared. 2849 * @param userId The target user to apply. Only meaningful when this is default display. If the 2850 * user id is {@link UserHandle#USER_CURRENT}, it means to apply current settings 2851 * so only need to configure display. 2852 */ setForcedDensity(int density, int userId)2853 void setForcedDensity(int density, int userId) { 2854 mIsDensityForced = density != mInitialDisplayDensity; 2855 final boolean updateCurrent = userId == UserHandle.USER_CURRENT; 2856 if (mWmService.mCurrentUserId == userId || updateCurrent) { 2857 mBaseDisplayDensity = density; 2858 reconfigureDisplayLocked(); 2859 } 2860 if (updateCurrent) { 2861 // We are applying existing settings so no need to save it again. 2862 return; 2863 } 2864 2865 if (density == mInitialDisplayDensity) { 2866 density = 0; 2867 } 2868 mWmService.mDisplayWindowSettings.setForcedDensity(this, density, userId); 2869 } 2870 2871 /** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */ setForcedScalingMode(@orceScalingMode int mode)2872 void setForcedScalingMode(@ForceScalingMode int mode) { 2873 if (mode != FORCE_SCALING_MODE_DISABLED) { 2874 mode = FORCE_SCALING_MODE_AUTO; 2875 } 2876 2877 mDisplayScalingDisabled = (mode != FORCE_SCALING_MODE_AUTO); 2878 Slog.i(TAG_WM, "Using display scaling mode: " + (mDisplayScalingDisabled ? "off" : "auto")); 2879 reconfigureDisplayLocked(); 2880 2881 mWmService.mDisplayWindowSettings.setForcedScalingMode(this, mode); 2882 } 2883 2884 /** If the given width and height equal to initial size, the setting will be cleared. */ setForcedSize(int width, int height)2885 void setForcedSize(int width, int height) { 2886 mIsSizeForced = mInitialDisplayWidth != width || mInitialDisplayHeight != height; 2887 if (mIsSizeForced) { 2888 // Set some sort of reasonable bounds on the size of the display that we will try 2889 // to emulate. 2890 final int minSize = 200; 2891 final int maxScale = 2; 2892 width = Math.min(Math.max(width, minSize), mInitialDisplayWidth * maxScale); 2893 height = Math.min(Math.max(height, minSize), mInitialDisplayHeight * maxScale); 2894 } 2895 2896 Slog.i(TAG_WM, "Using new display size: " + width + "x" + height); 2897 updateBaseDisplayMetrics(width, height, mBaseDisplayDensity); 2898 reconfigureDisplayLocked(); 2899 2900 if (!mIsSizeForced) { 2901 width = height = 0; 2902 } 2903 mWmService.mDisplayWindowSettings.setForcedSize(this, width, height); 2904 } 2905 2906 @Override getStableRect(Rect out)2907 void getStableRect(Rect out) { 2908 final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState(); 2909 out.set(state.getDisplayFrame()); 2910 out.inset(state.calculateInsets(out, systemBars(), true /* ignoreVisibility */)); 2911 } 2912 2913 /** 2914 * Get the default display area on the display dedicated to app windows. This one should be used 2915 * only as a fallback location for activity launches when no target display area is specified, 2916 * or for cases when multi-instance is not supported yet (like Split-screen, PiP or Recents). 2917 */ getDefaultTaskDisplayArea()2918 TaskDisplayArea getDefaultTaskDisplayArea() { 2919 return mDisplayAreaPolicy.getDefaultTaskDisplayArea(); 2920 } 2921 2922 /** 2923 * Checks for all non-organized {@link DisplayArea}s for if there is any existing organizer for 2924 * their features. If so, registers them with the matched organizer. 2925 */ 2926 @VisibleForTesting updateDisplayAreaOrganizers()2927 void updateDisplayAreaOrganizers() { 2928 if (!isTrusted()) { 2929 // No need to update for untrusted display. 2930 return; 2931 } 2932 forAllDisplayAreas(displayArea -> { 2933 if (displayArea.isOrganized()) { 2934 return; 2935 } 2936 // Check if we have a registered organizer for the DA feature. 2937 final IDisplayAreaOrganizer organizer = 2938 mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController 2939 .getOrganizerByFeature(displayArea.mFeatureId); 2940 if (organizer != null) { 2941 displayArea.setOrganizer(organizer); 2942 } 2943 }); 2944 } 2945 2946 /** 2947 * Returns true if the input point is within an app window. 2948 */ pointWithinAppWindow(int x, int y)2949 boolean pointWithinAppWindow(int x, int y) { 2950 final int[] targetWindowType = {-1}; 2951 final PooledConsumer fn = PooledLambda.obtainConsumer((w, nonArg) -> { 2952 if (targetWindowType[0] != -1) { 2953 return; 2954 } 2955 2956 if (w.isOnScreen() && w.isVisible() && w.getFrame().contains(x, y)) { 2957 targetWindowType[0] = w.mAttrs.type; 2958 return; 2959 } 2960 }, PooledLambda.__(WindowState.class), mTmpRect); 2961 forAllWindows(fn, true /* traverseTopToBottom */); 2962 fn.recycle(); 2963 return FIRST_APPLICATION_WINDOW <= targetWindowType[0] 2964 && targetWindowType[0] <= LAST_APPLICATION_WINDOW; 2965 } 2966 2967 /** 2968 * Find the task whose outside touch area (for resizing) (x, y) falls within. 2969 * Returns null if the touch doesn't fall into a resizing area. 2970 */ 2971 @Nullable findTaskForResizePoint(int x, int y)2972 Task findTaskForResizePoint(int x, int y) { 2973 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 2974 return getItemFromTaskDisplayAreas(taskDisplayArea -> 2975 mTmpTaskForResizePointSearchResult.process(taskDisplayArea, x, y, delta)); 2976 } 2977 updateTouchExcludeRegion()2978 void updateTouchExcludeRegion() { 2979 final Task focusedTask = (mFocusedApp != null ? mFocusedApp.getTask() : null); 2980 if (focusedTask == null) { 2981 mTouchExcludeRegion.setEmpty(); 2982 } else { 2983 mTouchExcludeRegion.set(mBaseDisplayRect); 2984 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 2985 mTmpRect.setEmpty(); 2986 mTmpRect2.setEmpty(); 2987 2988 final PooledConsumer c = PooledLambda.obtainConsumer( 2989 DisplayContent::processTaskForTouchExcludeRegion, this, 2990 PooledLambda.__(Task.class), focusedTask, delta); 2991 forAllTasks(c); 2992 c.recycle(); 2993 2994 // If we removed the focused task above, add it back and only leave its 2995 // outside touch area in the exclusion. TapDetector is not interested in 2996 // any touch inside the focused task itself. 2997 if (!mTmpRect2.isEmpty()) { 2998 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION); 2999 } 3000 } 3001 if (mInputMethodWindow != null && mInputMethodWindow.isVisible()) { 3002 // If the input method is visible and the user is typing, we don't want these touch 3003 // events to be intercepted and used to change focus. This would likely cause a 3004 // disappearance of the input method. 3005 mInputMethodWindow.getTouchableRegion(mTmpRegion); 3006 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 3007 } 3008 for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) { 3009 final WindowState win = mTapExcludedWindows.get(i); 3010 if (!win.isVisible()) { 3011 continue; 3012 } 3013 win.getTouchableRegion(mTmpRegion); 3014 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 3015 } 3016 amendWindowTapExcludeRegion(mTouchExcludeRegion); 3017 // TODO(multi-display): Support docked root tasks on secondary displays & task containers. 3018 if (mDisplayId == DEFAULT_DISPLAY 3019 && getDefaultTaskDisplayArea().isSplitScreenModeActivated()) { 3020 mDividerControllerLocked.getTouchRegion(mTmpRect); 3021 mTmpRegion.set(mTmpRect); 3022 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 3023 } 3024 mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion); 3025 } 3026 processTaskForTouchExcludeRegion(Task task, Task focusedTask, int delta)3027 private void processTaskForTouchExcludeRegion(Task task, Task focusedTask, int delta) { 3028 final ActivityRecord topVisibleActivity = task.getTopVisibleActivity(); 3029 3030 if (topVisibleActivity == null || !topVisibleActivity.hasContentToDisplay()) { 3031 return; 3032 } 3033 3034 // Exclusion region is the region that TapDetector doesn't care about. 3035 // Here we want to remove all non-focused tasks from the exclusion region. 3036 // We also remove the outside touch area for resizing for all freeform 3037 // tasks (including the focused). 3038 // We save the focused task region once we find it, and add it back at the end. 3039 // If the task is root home task and it is resizable and visible (top of its root task), 3040 // we want to exclude the root docked task from touch so we need the entire screen area 3041 // and not just a small portion which the root home task currently is resized to. 3042 if (task.isActivityTypeHome() && task.isVisible() && task.isResizeable()) { 3043 task.getDisplayArea().getBounds(mTmpRect); 3044 } else { 3045 task.getDimBounds(mTmpRect); 3046 } 3047 3048 if (task == focusedTask) { 3049 // Add the focused task rect back into the exclude region once we are done 3050 // processing root tasks. 3051 // NOTE: this *looks* like a no-op, but this usage of mTmpRect2 is expected by 3052 // updateTouchExcludeRegion. 3053 mTmpRect2.set(mTmpRect); 3054 } 3055 3056 final boolean isFreeformed = task.inFreeformWindowingMode(); 3057 if (task != focusedTask || isFreeformed) { 3058 if (isFreeformed) { 3059 // If the task is freeformed, enlarge the area to account for outside 3060 // touch area for resize. 3061 mTmpRect.inset(-delta, -delta); 3062 // Intersect with display content frame. If we have system decor (status bar/ 3063 // navigation bar), we want to exclude that from the tap detection. 3064 // Otherwise, if the app is partially placed under some system button (eg. 3065 // Recents, Home), pressing that button would cause a full series of 3066 // unwanted transfer focus/resume/pause, before we could go home. 3067 mTmpRect.inset(getInsetsStateController().getRawInsetsState().calculateInsets( 3068 mTmpRect, systemBars() | ime(), false /* ignoreVisibility */)); 3069 } 3070 mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE); 3071 } 3072 } 3073 3074 /** 3075 * Union the region with all the tap exclude region provided by windows on this display. 3076 * 3077 * @param inOutRegion The region to be amended. 3078 */ amendWindowTapExcludeRegion(Region inOutRegion)3079 private void amendWindowTapExcludeRegion(Region inOutRegion) { 3080 final Region region = Region.obtain(); 3081 for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) { 3082 final WindowState win = mTapExcludeProvidingWindows.valueAt(i); 3083 win.getTapExcludeRegion(region); 3084 inOutRegion.op(region, Op.UNION); 3085 } 3086 region.recycle(); 3087 } 3088 3089 @Override switchUser(int userId)3090 void switchUser(int userId) { 3091 super.switchUser(userId); 3092 mWmService.mWindowsChanged = true; 3093 mDisplayPolicy.switchUser(); 3094 } 3095 3096 @Override removeIfPossible()3097 void removeIfPossible() { 3098 if (isAnimating(TRANSITION | PARENTS) 3099 // isAnimating is a legacy transition query and will be removed, so also add a 3100 // check for whether this is in a shell-transition when not using legacy. 3101 || mTransitionController.inTransition()) { 3102 mDeferredRemoval = true; 3103 return; 3104 } 3105 removeImmediately(); 3106 } 3107 3108 @Override removeImmediately()3109 void removeImmediately() { 3110 mDeferredRemoval = false; 3111 try { 3112 if (mParentWindow != null) { 3113 mParentWindow.removeEmbeddedDisplayContent(this); 3114 } 3115 // Clear all transitions & screen frozen states when removing display. 3116 mOpeningApps.clear(); 3117 mClosingApps.clear(); 3118 mChangingContainers.clear(); 3119 mUnknownAppVisibilityController.clear(); 3120 mAppTransition.removeAppTransitionTimeoutCallbacks(); 3121 handleAnimatingStoppedAndTransition(); 3122 mWmService.stopFreezingDisplayLocked(); 3123 super.removeImmediately(); 3124 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this); 3125 mPointerEventDispatcher.dispose(); 3126 setRotationAnimation(null); 3127 mWmService.mAnimator.removeDisplayLocked(mDisplayId); 3128 mOverlayLayer.release(); 3129 mInputMonitor.onDisplayRemoved(); 3130 mWmService.mDisplayNotificationController.dispatchDisplayRemoved(this); 3131 mWmService.mAccessibilityController.onDisplayRemoved(mDisplayId); 3132 } finally { 3133 mDisplayReady = false; 3134 } 3135 3136 // Apply the pending transaction here since we may not be able to reach the DisplayContent 3137 // on the next traversal if it's removed from RootWindowContainer child list. 3138 getPendingTransaction().apply(); 3139 mWmService.mWindowPlacerLocked.requestTraversal(); 3140 } 3141 3142 /** Returns true if a removal action is still being deferred. */ 3143 @Override handleCompleteDeferredRemoval()3144 boolean handleCompleteDeferredRemoval() { 3145 final boolean stillDeferringRemoval = super.handleCompleteDeferredRemoval(); 3146 3147 if (!stillDeferringRemoval && mDeferredRemoval) { 3148 removeImmediately(); 3149 return false; 3150 } 3151 return stillDeferringRemoval; 3152 } 3153 adjustForImeIfNeeded()3154 void adjustForImeIfNeeded() { 3155 final WindowState imeWin = mInputMethodWindow; 3156 final boolean imeVisible = imeWin != null && imeWin.isVisible() 3157 && imeWin.isDisplayed(); 3158 final int imeHeight = getInputMethodWindowVisibleHeight(); 3159 mPinnedTaskController.setAdjustedForIme(imeVisible, imeHeight); 3160 } 3161 getInputMethodWindowVisibleHeight()3162 int getInputMethodWindowVisibleHeight() { 3163 final InsetsState state = getInsetsStateController().getRawInsetsState(); 3164 final InsetsSource imeSource = state.peekSource(ITYPE_IME); 3165 if (imeSource == null || !imeSource.isVisible()) { 3166 return 0; 3167 } 3168 final Rect imeFrame = imeSource.getVisibleFrame() != null 3169 ? imeSource.getVisibleFrame() : imeSource.getFrame(); 3170 final Rect dockFrame = mTmpRect; 3171 dockFrame.set(state.getDisplayFrame()); 3172 dockFrame.inset(state.calculateInsets(dockFrame, systemBars() | displayCutout(), 3173 false /* ignoreVisibility */)); 3174 return dockFrame.bottom - imeFrame.top; 3175 } 3176 rotateBounds(@otation int oldRotation, @Rotation int newRotation, Rect inOutBounds)3177 void rotateBounds(@Rotation int oldRotation, @Rotation int newRotation, Rect inOutBounds) { 3178 // Get display bounds on oldRotation as parent bounds for the rotation. 3179 getBounds(mTmpRect, oldRotation); 3180 RotationUtils.rotateBounds(inOutBounds, mTmpRect, oldRotation, newRotation); 3181 } 3182 setRotationAnimation(ScreenRotationAnimation screenRotationAnimation)3183 public void setRotationAnimation(ScreenRotationAnimation screenRotationAnimation) { 3184 if (mScreenRotationAnimation != null) { 3185 mScreenRotationAnimation.kill(); 3186 } 3187 mScreenRotationAnimation = screenRotationAnimation; 3188 3189 // Hide the windows which are not significant in rotation animation. So that the windows 3190 // don't need to block the unfreeze time. 3191 if (screenRotationAnimation != null && screenRotationAnimation.hasScreenshot() 3192 // Do not fade for freezing without rotation change. 3193 && mDisplayRotation.getRotation() != getWindowConfiguration().getRotation() 3194 && mFadeRotationAnimationController == null) { 3195 startFadeRotationAnimation(false /* shouldDebounce */); 3196 } 3197 } 3198 getRotationAnimation()3199 public ScreenRotationAnimation getRotationAnimation() { 3200 return mScreenRotationAnimation; 3201 } 3202 3203 /** 3204 * Requests to start a transition for the display configuration change. The given changes must 3205 * be non-zero. This method is no-op if the display has been collected. 3206 */ requestChangeTransitionIfNeeded(@ctivityInfo.Config int changes)3207 void requestChangeTransitionIfNeeded(@ActivityInfo.Config int changes) { 3208 final TransitionController controller = mTransitionController; 3209 if (controller.isCollecting()) { 3210 if (!controller.isCollecting(this)) { 3211 controller.collect(this); 3212 } 3213 return; 3214 } 3215 final Transition t = controller.requestTransitionIfNeeded(TRANSIT_CHANGE, this); 3216 if (t != null) { 3217 if (getRotation() != getWindowConfiguration().getRotation()) { 3218 mWmService.mLatencyTracker.onActionStart(ACTION_ROTATE_SCREEN); 3219 controller.mTransitionMetricsReporter.associate(t, 3220 startTime -> mWmService.mLatencyTracker.onActionEnd(ACTION_ROTATE_SCREEN)); 3221 } 3222 t.setKnownConfigChanges(this, changes); 3223 } 3224 } 3225 3226 /** If the display is in transition, there should be a screenshot covering it. */ 3227 @Override inTransition()3228 boolean inTransition() { 3229 return mScreenRotationAnimation != null || super.inTransition(); 3230 } 3231 3232 @Override dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)3233 public void dumpDebug(ProtoOutputStream proto, long fieldId, 3234 @WindowTraceLogLevel int logLevel) { 3235 // Critical log level logs only visible elements to mitigate performance overheard 3236 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { 3237 return; 3238 } 3239 3240 final long token = proto.start(fieldId); 3241 super.dumpDebug(proto, ROOT_DISPLAY_AREA, logLevel); 3242 3243 proto.write(ID, mDisplayId); 3244 proto.write(DPI, mBaseDisplayDensity); 3245 mDisplayInfo.dumpDebug(proto, DISPLAY_INFO); 3246 mDisplayRotation.dumpDebug(proto, DISPLAY_ROTATION); 3247 final ScreenRotationAnimation screenRotationAnimation = getRotationAnimation(); 3248 if (screenRotationAnimation != null) { 3249 screenRotationAnimation.dumpDebug(proto, SCREEN_ROTATION_ANIMATION); 3250 } 3251 mDisplayFrames.dumpDebug(proto, DISPLAY_FRAMES); 3252 if (mTransitionController.isShellTransitionsEnabled()) { 3253 mTransitionController.dumpDebugLegacy(proto, APP_TRANSITION); 3254 } else { 3255 mAppTransition.dumpDebug(proto, APP_TRANSITION); 3256 } 3257 if (mFocusedApp != null) { 3258 mFocusedApp.writeNameToProto(proto, FOCUSED_APP); 3259 } 3260 for (int i = mOpeningApps.size() - 1; i >= 0; i--) { 3261 mOpeningApps.valueAt(i).writeIdentifierToProto(proto, OPENING_APPS); 3262 } 3263 for (int i = mClosingApps.size() - 1; i >= 0; i--) { 3264 mClosingApps.valueAt(i).writeIdentifierToProto(proto, CLOSING_APPS); 3265 } 3266 3267 final Task focusedRootTask = getFocusedRootTask(); 3268 if (focusedRootTask != null) { 3269 proto.write(FOCUSED_ROOT_TASK_ID, focusedRootTask.getRootTaskId()); 3270 final ActivityRecord focusedActivity = focusedRootTask.getDisplayArea() 3271 .getFocusedActivity(); 3272 if (focusedActivity != null) { 3273 focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY); 3274 } 3275 } else { 3276 proto.write(FOCUSED_ROOT_TASK_ID, INVALID_TASK_ID); 3277 } 3278 proto.write(DISPLAY_READY, isReady()); 3279 proto.write(IS_SLEEPING, isSleeping()); 3280 for (int i = 0; i < mAllSleepTokens.size(); ++i) { 3281 mAllSleepTokens.get(i).writeTagToProto(proto, SLEEP_TOKENS); 3282 } 3283 3284 if (mImeLayeringTarget != null) { 3285 mImeLayeringTarget.dumpDebug(proto, INPUT_METHOD_TARGET, logLevel); 3286 } 3287 if (mImeInputTarget != null) { 3288 mImeInputTarget.dumpDebug(proto, INPUT_METHOD_INPUT_TARGET, logLevel); 3289 } 3290 if (mImeControlTarget != null 3291 && mImeControlTarget.getWindow() != null) { 3292 mImeControlTarget.getWindow().dumpDebug(proto, INPUT_METHOD_CONTROL_TARGET, 3293 logLevel); 3294 } 3295 if (mCurrentFocus != null) { 3296 mCurrentFocus.dumpDebug(proto, CURRENT_FOCUS, logLevel); 3297 } 3298 if (mInsetsStateController != null 3299 && mInsetsStateController.getImeSourceProvider() != null) { 3300 mInsetsStateController.getImeSourceProvider().dumpDebug(proto, 3301 IME_INSETS_SOURCE_PROVIDER, logLevel); 3302 } 3303 proto.write(IME_POLICY, getImePolicy()); 3304 proto.end(token); 3305 } 3306 3307 @Override getProtoFieldId()3308 long getProtoFieldId() { 3309 return DISPLAY_CONTENT; 3310 } 3311 3312 @Override dump(PrintWriter pw, String prefix, boolean dumpAll)3313 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 3314 super.dump(pw, prefix, dumpAll); 3315 pw.print(prefix); 3316 pw.println("Display: mDisplayId=" + mDisplayId + " rootTasks=" + getRootTaskCount()); 3317 final String subPrefix = " " + prefix; 3318 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); 3319 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); 3320 pw.print("dpi"); 3321 if (mInitialDisplayWidth != mBaseDisplayWidth 3322 || mInitialDisplayHeight != mBaseDisplayHeight 3323 || mInitialDisplayDensity != mBaseDisplayDensity) { 3324 pw.print(" base="); 3325 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 3326 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); 3327 } 3328 if (mDisplayScalingDisabled) { 3329 pw.println(" noscale"); 3330 } 3331 pw.print(" cur="); 3332 pw.print(mDisplayInfo.logicalWidth); 3333 pw.print("x"); pw.print(mDisplayInfo.logicalHeight); 3334 pw.print(" app="); 3335 pw.print(mDisplayInfo.appWidth); 3336 pw.print("x"); pw.print(mDisplayInfo.appHeight); 3337 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); 3338 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); 3339 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); 3340 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); 3341 pw.print(subPrefix + "deferred=" + mDeferredRemoval 3342 + " mLayoutNeeded=" + mLayoutNeeded); 3343 pw.println(" mTouchExcludeRegion=" + mTouchExcludeRegion); 3344 3345 pw.println(); 3346 pw.print(prefix); pw.print("mLayoutSeq="); pw.println(mLayoutSeq); 3347 3348 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 3349 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 3350 if (mFixedRotationLaunchingApp != null) { 3351 pw.println(" mFixedRotationLaunchingApp=" + mFixedRotationLaunchingApp); 3352 } 3353 3354 pw.println(); 3355 mWallpaperController.dump(pw, " "); 3356 3357 if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() > 0) { 3358 pw.println(); 3359 pw.print(" mSystemGestureExclusion="); 3360 pw.println(mSystemGestureExclusion); 3361 } 3362 3363 pw.println(); 3364 pw.println(prefix + "Display areas in top down Z order:"); 3365 dumpChildDisplayArea(pw, subPrefix, dumpAll); 3366 3367 pw.println(); 3368 pw.println(prefix + "Task display areas in top down Z order:"); 3369 forAllTaskDisplayAreas(taskDisplayArea -> { 3370 taskDisplayArea.dump(pw, prefix + " ", dumpAll); 3371 }); 3372 3373 pw.println(); 3374 if (!mExitingTokens.isEmpty()) { 3375 pw.println(); 3376 pw.println(" Exiting tokens:"); 3377 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 3378 final WindowToken token = mExitingTokens.get(i); 3379 pw.print(" Exiting #"); pw.print(i); 3380 pw.print(' '); pw.print(token); 3381 pw.println(':'); 3382 token.dump(pw, " ", dumpAll); 3383 } 3384 } 3385 3386 final ScreenRotationAnimation rotationAnimation = getRotationAnimation(); 3387 if (rotationAnimation != null) { 3388 pw.println(" mScreenRotationAnimation:"); 3389 rotationAnimation.printTo(subPrefix, pw); 3390 } else if (dumpAll) { 3391 pw.println(" no ScreenRotationAnimation "); 3392 } 3393 3394 pw.println(); 3395 3396 // Dump root task references 3397 final Task rootHomeTask = getDefaultTaskDisplayArea().getRootHomeTask(); 3398 if (rootHomeTask != null) { 3399 pw.println(prefix + "rootHomeTask=" + rootHomeTask.getName()); 3400 } 3401 final Task rootPinnedTask = getDefaultTaskDisplayArea().getRootPinnedTask(); 3402 if (rootPinnedTask != null) { 3403 pw.println(prefix + "rootPinnedTask=" + rootPinnedTask.getName()); 3404 } 3405 final Task rootSplitScreenPrimaryTask = getDefaultTaskDisplayArea() 3406 .getRootSplitScreenPrimaryTask(); 3407 if (rootSplitScreenPrimaryTask != null) { 3408 pw.println( 3409 prefix + "rootSplitScreenPrimaryTask=" + rootSplitScreenPrimaryTask.getName()); 3410 } 3411 // TODO: Support recents on non-default task containers 3412 final Task rootRecentsTask = getDefaultTaskDisplayArea().getRootTask( 3413 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS); 3414 if (rootRecentsTask != null) { 3415 pw.println(prefix + "rootRecentsTask=" + rootRecentsTask.getName()); 3416 } 3417 final Task rootDreamTask = 3418 getRootTask(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_DREAM); 3419 if (rootDreamTask != null) { 3420 pw.println(prefix + "rootDreamTask=" + rootDreamTask.getName()); 3421 } 3422 3423 pw.println(); 3424 mPinnedTaskController.dump(prefix, pw); 3425 3426 pw.println(); 3427 mDisplayFrames.dump(prefix, pw); 3428 pw.println(); 3429 mDisplayPolicy.dump(prefix, pw); 3430 pw.println(); 3431 mDisplayRotation.dump(prefix, pw); 3432 pw.println(); 3433 mInputMonitor.dump(pw, " "); 3434 pw.println(); 3435 mInsetsStateController.dump(prefix, pw); 3436 } 3437 3438 @Override toString()3439 public String toString() { 3440 return "Display{#" + mDisplayId + " state=" + Display.stateToString(mDisplayInfo.state) 3441 + " size=" + mDisplayInfo.logicalWidth + "x" + mDisplayInfo.logicalHeight 3442 + " " + Surface.rotationToString(mDisplayInfo.rotation) + "}"; 3443 } 3444 getName()3445 String getName() { 3446 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\""; 3447 } 3448 3449 /** Find the visible, touch-deliverable window under the given point */ getTouchableWinAtPointLocked(float xf, float yf)3450 WindowState getTouchableWinAtPointLocked(float xf, float yf) { 3451 final int x = (int) xf; 3452 final int y = (int) yf; 3453 final WindowState touchedWin = getWindow(w -> { 3454 final int flags = w.mAttrs.flags; 3455 if (!w.isVisible()) { 3456 return false; 3457 } 3458 if ((flags & FLAG_NOT_TOUCHABLE) != 0) { 3459 return false; 3460 } 3461 3462 w.getVisibleBounds(mTmpRect); 3463 if (!mTmpRect.contains(x, y)) { 3464 return false; 3465 } 3466 3467 w.getTouchableRegion(mTmpRegion); 3468 3469 final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL); 3470 return mTmpRegion.contains(x, y) || touchFlags == 0; 3471 }); 3472 3473 return touchedWin; 3474 } 3475 canAddToastWindowForUid(int uid)3476 boolean canAddToastWindowForUid(int uid) { 3477 // We allow one toast window per UID being shown at a time. 3478 // Also if the app is focused adding more than one toast at 3479 // a time for better backwards compatibility. 3480 final WindowState focusedWindowForUid = getWindow(w -> 3481 w.mOwnerUid == uid && w.isFocused()); 3482 if (focusedWindowForUid != null) { 3483 return true; 3484 } 3485 final WindowState win = getWindow(w -> 3486 w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden 3487 && !w.mWindowRemovalAllowed); 3488 return win == null; 3489 } 3490 scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus)3491 void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) { 3492 if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) { 3493 return; 3494 } 3495 3496 // Used to communicate the old focus to the callback method. 3497 mTmpWindow = oldFocus; 3498 3499 forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */); 3500 } 3501 3502 /** 3503 * Looking for the focused window on this display if the top focused display hasn't been 3504 * found yet (topFocusedDisplayId is INVALID_DISPLAY) or per-display focused was allowed. 3505 * 3506 * @param topFocusedDisplayId Id of the top focused display. 3507 * @return The focused window or null if there isn't any or no need to seek. 3508 */ findFocusedWindowIfNeeded(int topFocusedDisplayId)3509 WindowState findFocusedWindowIfNeeded(int topFocusedDisplayId) { 3510 return (mWmService.mPerDisplayFocusEnabled || topFocusedDisplayId == INVALID_DISPLAY) 3511 ? findFocusedWindow() : null; 3512 } 3513 findFocusedWindow()3514 WindowState findFocusedWindow() { 3515 mTmpWindow = null; 3516 3517 forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */); 3518 3519 if (mTmpWindow == null) { 3520 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: No focusable windows, display=%d", 3521 getDisplayId()); 3522 return null; 3523 } 3524 return mTmpWindow; 3525 } 3526 3527 /** 3528 * Update the focused window and make some adjustments if the focus has changed. 3529 * 3530 * @param mode Indicates the situation we are in. Possible modes are: 3531 * {@link WindowManagerService#UPDATE_FOCUS_NORMAL}, 3532 * {@link WindowManagerService#UPDATE_FOCUS_PLACING_SURFACES}, 3533 * {@link WindowManagerService#UPDATE_FOCUS_WILL_PLACE_SURFACES}, 3534 * {@link WindowManagerService#UPDATE_FOCUS_REMOVING_FOCUS} 3535 * @param updateInputWindows Whether to sync the window information to the input module. 3536 * @param topFocusedDisplayId Display id of current top focused display. 3537 * @return {@code true} if the focused window has changed. 3538 */ updateFocusedWindowLocked(int mode, boolean updateInputWindows, int topFocusedDisplayId)3539 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows, 3540 int topFocusedDisplayId) { 3541 WindowState newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId); 3542 if (mCurrentFocus == newFocus) { 3543 return false; 3544 } 3545 boolean imWindowChanged = false; 3546 final WindowState imWindow = mInputMethodWindow; 3547 if (imWindow != null) { 3548 final WindowState prevTarget = mImeLayeringTarget; 3549 final WindowState newTarget = computeImeTarget(true /* updateImeTarget*/); 3550 imWindowChanged = prevTarget != newTarget; 3551 3552 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 3553 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) { 3554 assignWindowLayers(false /* setLayoutNeeded */); 3555 } 3556 3557 if (imWindowChanged) { 3558 mWmService.mWindowsChanged = true; 3559 setLayoutNeeded(); 3560 newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId); 3561 } 3562 } 3563 3564 ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "Changing focus from %s to %s displayId=%d Callers=%s", 3565 mCurrentFocus, newFocus, getDisplayId(), Debug.getCallers(4)); 3566 final WindowState oldFocus = mCurrentFocus; 3567 mCurrentFocus = newFocus; 3568 3569 if (newFocus != null) { 3570 mWinAddedSinceNullFocus.clear(); 3571 mWinRemovedSinceNullFocus.clear(); 3572 3573 if (newFocus.canReceiveKeys()) { 3574 // Displaying a window implicitly causes dispatching to be unpaused. 3575 // This is to protect against bugs if someone pauses dispatching but 3576 // forgets to resume. 3577 newFocus.mToken.paused = false; 3578 } 3579 } 3580 3581 getDisplayPolicy().focusChangedLw(oldFocus, newFocus); 3582 3583 if (imWindowChanged && oldFocus != mInputMethodWindow) { 3584 // Focus of the input method window changed. Perform layout if needed. 3585 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 3586 performLayout(true /*initial*/, updateInputWindows); 3587 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 3588 // Client will do the layout, but we need to assign layers 3589 // for handleNewWindowLocked() below. 3590 assignWindowLayers(false /* setLayoutNeeded */); 3591 } 3592 } 3593 3594 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 3595 // If we defer assigning layers, then the caller is responsible for doing this part. 3596 getInputMonitor().setInputFocusLw(newFocus, updateInputWindows); 3597 } 3598 3599 adjustForImeIfNeeded(); 3600 3601 // We may need to schedule some toast windows to be removed. The toasts for an app that 3602 // does not have input focus are removed within a timeout to prevent apps to redress 3603 // other apps' UI. 3604 scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus); 3605 3606 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 3607 pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 3608 } 3609 3610 // Notify the accessibility manager for the change so it has the windows before the newly 3611 // focused one starts firing events. 3612 // TODO(b/151179149) investigate what info accessibility service needs before input can 3613 // dispatch focus to clients. 3614 if (mWmService.mAccessibilityController.hasCallbacks()) { 3615 mWmService.mH.sendMessage(PooledLambda.obtainMessage( 3616 this::updateAccessibilityOnWindowFocusChanged, 3617 mWmService.mAccessibilityController)); 3618 } 3619 3620 return true; 3621 } 3622 updateAccessibilityOnWindowFocusChanged(AccessibilityController accessibilityController)3623 void updateAccessibilityOnWindowFocusChanged(AccessibilityController accessibilityController) { 3624 accessibilityController.onWindowFocusChangedNot(getDisplayId()); 3625 } 3626 3627 /** 3628 * Set the new focused app to this display. 3629 * 3630 * @param newFocus the new focused {@link ActivityRecord}. 3631 * @return true if the focused app is changed. 3632 */ setFocusedApp(ActivityRecord newFocus)3633 boolean setFocusedApp(ActivityRecord newFocus) { 3634 if (newFocus != null) { 3635 final DisplayContent appDisplay = newFocus.getDisplayContent(); 3636 if (appDisplay != this) { 3637 throw new IllegalStateException(newFocus + " is not on " + getName() 3638 + " but " + ((appDisplay != null) ? appDisplay.getName() : "none")); 3639 } 3640 3641 // Called even if the focused app is not changed in case the app is moved to a different 3642 // TaskDisplayArea. 3643 onLastFocusedTaskDisplayAreaChanged(newFocus.getDisplayArea()); 3644 } 3645 if (mFocusedApp == newFocus) { 3646 return false; 3647 } 3648 ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "setFocusedApp %s displayId=%d Callers=%s", 3649 newFocus, getDisplayId(), Debug.getCallers(4)); 3650 final Task oldTask = mFocusedApp != null ? mFocusedApp.getTask() : null; 3651 final Task newTask = newFocus != null ? newFocus.getTask() : null; 3652 mFocusedApp = newFocus; 3653 if (oldTask != newTask) { 3654 if (oldTask != null) oldTask.onAppFocusChanged(false); 3655 if (newTask != null) newTask.onAppFocusChanged(true); 3656 } 3657 3658 getInputMonitor().setFocusedAppLw(newFocus); 3659 updateTouchExcludeRegion(); 3660 return true; 3661 } 3662 3663 /** Called when the focused {@link TaskDisplayArea} on this display may have changed. */ onLastFocusedTaskDisplayAreaChanged(@ullable TaskDisplayArea taskDisplayArea)3664 void onLastFocusedTaskDisplayAreaChanged(@Nullable TaskDisplayArea taskDisplayArea) { 3665 // Only record the TaskDisplayArea that handles orientation request. 3666 if (taskDisplayArea != null && taskDisplayArea.handlesOrientationChangeFromDescendant()) { 3667 mOrientationRequestingTaskDisplayArea = taskDisplayArea; 3668 return; 3669 } 3670 3671 // If the previous TDA no longer handles orientation request, clear it. 3672 if (mOrientationRequestingTaskDisplayArea != null 3673 && !mOrientationRequestingTaskDisplayArea 3674 .handlesOrientationChangeFromDescendant()) { 3675 mOrientationRequestingTaskDisplayArea = null; 3676 } 3677 } 3678 3679 /** 3680 * Gets the {@link TaskDisplayArea} that we respect orientation requests from apps below it. 3681 */ 3682 @Nullable getOrientationRequestingTaskDisplayArea()3683 TaskDisplayArea getOrientationRequestingTaskDisplayArea() { 3684 return mOrientationRequestingTaskDisplayArea; 3685 } 3686 3687 /** Updates the layer assignment of windows on this display. */ assignWindowLayers(boolean setLayoutNeeded)3688 void assignWindowLayers(boolean setLayoutNeeded) { 3689 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "assignWindowLayers"); 3690 assignChildLayers(getSyncTransaction()); 3691 if (setLayoutNeeded) { 3692 setLayoutNeeded(); 3693 } 3694 3695 // We accumlate the layer changes in-to "getPendingTransaction()" but we defer 3696 // the application of this transaction until the animation pass triggers 3697 // prepareSurfaces. This allows us to synchronize Z-ordering changes with 3698 // the hiding and showing of surfaces. 3699 scheduleAnimation(); 3700 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 3701 } 3702 3703 // TODO: This should probably be called any time a visual change is made to the hierarchy like 3704 // moving containers or resizing them. Need to investigate the best way to have it automatically 3705 // happen so we don't run into issues with programmers forgetting to do it. layoutAndAssignWindowLayersIfNeeded()3706 void layoutAndAssignWindowLayersIfNeeded() { 3707 mWmService.mWindowsChanged = true; 3708 setLayoutNeeded(); 3709 3710 if (!mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 3711 false /*updateInputWindows*/)) { 3712 assignWindowLayers(false /* setLayoutNeeded */); 3713 } 3714 3715 mInputMonitor.setUpdateInputWindowsNeededLw(); 3716 mWmService.mWindowPlacerLocked.performSurfacePlacement(); 3717 mInputMonitor.updateInputWindowsLw(false /*force*/); 3718 } 3719 3720 /** Returns true if a leaked surface was destroyed */ destroyLeakedSurfaces()3721 boolean destroyLeakedSurfaces() { 3722 // Used to indicate that a surface was leaked. 3723 mTmpWindow = null; 3724 final Transaction t = mWmService.mTransactionFactory.get(); 3725 forAllWindows(w -> { 3726 final WindowStateAnimator wsa = w.mWinAnimator; 3727 if (wsa.mSurfaceController == null) { 3728 return; 3729 } 3730 if (!mWmService.mSessions.contains(wsa.mSession)) { 3731 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): " 3732 + w + " surface=" + wsa.mSurfaceController 3733 + " token=" + w.mToken 3734 + " pid=" + w.mSession.mPid 3735 + " uid=" + w.mSession.mUid); 3736 wsa.destroySurface(t); 3737 mWmService.mForceRemoves.add(w); 3738 mTmpWindow = w; 3739 } else if (w.mActivityRecord != null && !w.mActivityRecord.isClientVisible()) { 3740 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " 3741 + w + " surface=" + wsa.mSurfaceController 3742 + " token=" + w.mActivityRecord); 3743 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE LEAK DESTROY: %s", w); 3744 wsa.destroySurface(t); 3745 mTmpWindow = w; 3746 } 3747 }, false /* traverseTopToBottom */); 3748 t.apply(); 3749 3750 return mTmpWindow != null; 3751 } 3752 hasAlertWindowSurfaces()3753 boolean hasAlertWindowSurfaces() { 3754 for (int i = mWmService.mSessions.size() - 1; i >= 0; --i) { 3755 if (mWmService.mSessions.valueAt(i).hasAlertWindowSurfaces(this)) { 3756 return true; 3757 } 3758 } 3759 return false; 3760 } 3761 3762 /** 3763 * Set input method window for the display. 3764 * @param win Set when window added or Null when destroyed. 3765 */ setInputMethodWindowLocked(WindowState win)3766 void setInputMethodWindowLocked(WindowState win) { 3767 mInputMethodWindow = win; 3768 // Update display configuration for IME process. 3769 if (mInputMethodWindow != null) { 3770 final int imePid = mInputMethodWindow.mSession.mPid; 3771 mAtmService.onImeWindowSetOnDisplayArea(imePid, mImeWindowsContainer); 3772 } 3773 mInsetsStateController.getSourceProvider(ITYPE_IME).setWindow(win, 3774 mDisplayPolicy.getImeSourceFrameProvider(), null /* imeFrameProvider */); 3775 computeImeTarget(true /* updateImeTarget */); 3776 updateImeControlTarget(); 3777 } 3778 3779 /** 3780 * Determine and return the window that should be the IME target for layering the IME window. 3781 * @param updateImeTarget If true the system IME target will be updated to match what we found. 3782 * @return The window that should be used as the IME target or null if there isn't any. 3783 */ computeImeTarget(boolean updateImeTarget)3784 WindowState computeImeTarget(boolean updateImeTarget) { 3785 if (mInputMethodWindow == null) { 3786 // There isn't an IME so there shouldn't be a target...That was easy! 3787 if (updateImeTarget) { 3788 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " 3789 + mImeLayeringTarget + " to null since mInputMethodWindow is null"); 3790 setImeLayeringTargetInner(null); 3791 } 3792 return null; 3793 } 3794 3795 final WindowState curTarget = mImeLayeringTarget; 3796 if (!canUpdateImeTarget()) { 3797 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target"); 3798 mUpdateImeRequestedWhileDeferred = true; 3799 return curTarget; 3800 } 3801 3802 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 3803 // same display. Or even when the current IME/target are not on the same screen as the next 3804 // IME/target. For now only look for input windows on the main screen. 3805 mUpdateImeTarget = updateImeTarget; 3806 WindowState target = getWindow(mComputeImeTargetPredicate); 3807 3808 if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM, 3809 "Proposed new IME target: " + target + " for display: " + getDisplayId()); 3810 3811 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target 3812 + " updateImeTarget=" + updateImeTarget); 3813 3814 if (target == null) { 3815 if (updateImeTarget) { 3816 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget 3817 + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" 3818 + Debug.getCallers(4) : "")); 3819 setImeLayeringTargetInner(null); 3820 } 3821 3822 return null; 3823 } 3824 3825 if (updateImeTarget) { 3826 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to " 3827 + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 3828 setImeLayeringTargetInner(target); 3829 } 3830 3831 return target; 3832 } 3833 3834 /** 3835 * Calling {@link #computeImeTarget(boolean)} to update the input method target window in 3836 * the candidate app window token if needed. 3837 */ computeImeTargetIfNeeded(ActivityRecord candidate)3838 void computeImeTargetIfNeeded(ActivityRecord candidate) { 3839 if (mImeLayeringTarget != null && mImeLayeringTarget.mActivityRecord == candidate) { 3840 computeImeTarget(true /* updateImeTarget */); 3841 } 3842 } 3843 isImeControlledByApp()3844 private boolean isImeControlledByApp() { 3845 return mImeInputTarget != null && !mImeInputTarget.inMultiWindowMode(); 3846 } 3847 shouldImeAttachedToApp()3848 boolean shouldImeAttachedToApp() { 3849 // Force attaching IME to the display when magnifying, or it would be magnified with 3850 // target app together. 3851 final boolean allowAttachToApp = (mMagnificationSpec == null); 3852 3853 return allowAttachToApp && isImeControlledByApp() 3854 && mImeLayeringTarget != null 3855 && mImeLayeringTarget.mActivityRecord != null 3856 && mImeLayeringTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN 3857 // IME is attached to app windows that fill display area. This excludes 3858 // letterboxed windows. 3859 && mImeLayeringTarget.matchesDisplayAreaBounds(); 3860 } 3861 3862 /** 3863 * Unlike {@link #shouldImeAttachedToApp()}, this method returns {@code @true} only when both 3864 * the IME layering target is valid to attach the IME surface to the app, and the 3865 * {@link #mInputMethodSurfaceParent} of the {@link ImeContainer} has actually attached to 3866 * the app. (i.e. Even if {@link #shouldImeAttachedToApp()} returns {@code true}, calling this 3867 * method will return {@code false} if the IME surface doesn't actually attach to the app.) 3868 */ isImeAttachedToApp()3869 boolean isImeAttachedToApp() { 3870 return shouldImeAttachedToApp() 3871 && mInputMethodSurfaceParent != null 3872 && mInputMethodSurfaceParent.isSameSurface( 3873 mImeLayeringTarget.mActivityRecord.getSurfaceControl()); 3874 } 3875 3876 /** 3877 * Finds the window which can host IME if IME target cannot host it. 3878 * e.g. IME target cannot host IME when it's display has a parent display OR when display 3879 * doesn't support IME/system decorations. 3880 * 3881 * @param target current IME target. 3882 * @return {@link InsetsControlTarget} that can host IME. 3883 */ getImeHostOrFallback(WindowState target)3884 InsetsControlTarget getImeHostOrFallback(WindowState target) { 3885 if (target != null 3886 && target.getDisplayContent().getImePolicy() == DISPLAY_IME_POLICY_LOCAL) { 3887 return target; 3888 } 3889 return getImeFallback(); 3890 } 3891 getImeFallback()3892 InsetsControlTarget getImeFallback() { 3893 // host is in non-default display that doesn't support system decor, default to 3894 // default display's StatusBar to control IME (when available), else let system control it. 3895 final DisplayContent defaultDc = mWmService.getDefaultDisplayContentLocked(); 3896 WindowState statusBar = defaultDc.getDisplayPolicy().getStatusBar(); 3897 return statusBar != null ? statusBar : defaultDc.mRemoteInsetsControlTarget; 3898 } 3899 3900 /** 3901 * Returns the corresponding IME insets control target according the IME target type. 3902 * 3903 * @param type The type of the IME target. 3904 * @see #IME_TARGET_LAYERING 3905 * @see #IME_TARGET_INPUT 3906 * @see #IME_TARGET_CONTROL 3907 */ getImeTarget(@nputMethodTarget int type)3908 InsetsControlTarget getImeTarget(@InputMethodTarget int type) { 3909 switch (type) { 3910 case IME_TARGET_LAYERING: return mImeLayeringTarget; 3911 case IME_TARGET_INPUT: return mImeInputTarget; 3912 case IME_TARGET_CONTROL: return mImeControlTarget; 3913 default: 3914 return null; 3915 } 3916 } 3917 getImePolicy()3918 @DisplayImePolicy int getImePolicy() { 3919 if (!isTrusted()) { 3920 return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; 3921 } 3922 final int imePolicy = mWmService.mDisplayWindowSettings.getImePolicyLocked(this); 3923 if (imePolicy == DISPLAY_IME_POLICY_FALLBACK_DISPLAY && forceDesktopMode()) { 3924 // If the display has not explicitly requested for the IME to be hidden then it shall 3925 // show the IME locally. 3926 return DISPLAY_IME_POLICY_LOCAL; 3927 } 3928 return imePolicy; 3929 } 3930 forceDesktopMode()3931 boolean forceDesktopMode() { 3932 return mWmService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay && !isPrivate(); 3933 } 3934 3935 /** @see WindowManagerInternal#onToggleImeRequested */ onShowImeRequested()3936 void onShowImeRequested() { 3937 if (mImeLayeringTarget == null || mInputMethodWindow == null) { 3938 return; 3939 } 3940 // If IME window will be shown on the rotated activity, share the transformed state to 3941 // IME window so it can compute rotated frame with rotated configuration. 3942 if (mImeLayeringTarget.mToken.isFixedRotationTransforming()) { 3943 mInputMethodWindow.mToken.linkFixedRotationTransform(mImeLayeringTarget.mToken); 3944 // Hide the window until the rotation is done to avoid intermediate artifacts if the 3945 // parent surface of IME container is changed. 3946 if (mFadeRotationAnimationController != null) { 3947 mFadeRotationAnimationController.hideImmediately(mInputMethodWindow.mToken); 3948 } 3949 } 3950 } 3951 3952 @VisibleForTesting setImeLayeringTarget(WindowState target)3953 void setImeLayeringTarget(WindowState target) { 3954 mImeLayeringTarget = target; 3955 } 3956 3957 /** 3958 * Sets the window the IME is on top of. 3959 * @param target window to place the IME surface on top of. If {@code null}, the IME will be 3960 * placed at its parent's surface. 3961 */ setImeLayeringTargetInner(@ullable WindowState target)3962 private void setImeLayeringTargetInner(@Nullable WindowState target) { 3963 if (target == mImeLayeringTarget) { 3964 return; 3965 } 3966 // Prepare the IME screenshot for the last IME target when its task is applying app 3967 // transition. This is for the better IME transition to keep IME visibility when 3968 // transitioning to the next task. 3969 if (mImeLayeringTarget != null && mImeLayeringTarget.isAnimating(PARENTS | TRANSITION, 3970 ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)) { 3971 attachAndShowImeScreenshotOnTarget(); 3972 } 3973 3974 ProtoLog.i(WM_DEBUG_IME, "setInputMethodTarget %s", target); 3975 mImeLayeringTarget = target; 3976 3977 // 1. Reparent the IME container window to the target root DA to get the correct bounds and 3978 // config. (Only happens when the target window is in a different root DA) 3979 if (target != null) { 3980 RootDisplayArea targetRoot = target.getRootDisplayArea(); 3981 if (targetRoot != null && targetRoot != mImeWindowsContainer.getRootDisplayArea()) { 3982 // Reposition the IME container to the target root to get the correct bounds and 3983 // config. 3984 targetRoot.placeImeContainer(mImeWindowsContainer); 3985 // Directly hide the IME window so it doesn't flash immediately after reparenting. 3986 // InsetsController will make IME visible again before animating it. 3987 if (mInputMethodWindow != null) { 3988 mInputMethodWindow.hide(false /* doAnimation */, false /* requestAnim */); 3989 } 3990 } 3991 } 3992 // 2. Assign window layers based on the IME surface parent to make sure it is on top of the 3993 // app. 3994 assignWindowLayers(true /* setLayoutNeeded */); 3995 // 3. The z-order of IME might have been changed. Update the above insets state. 3996 mInsetsStateController.updateAboveInsetsState(mInputMethodWindow, 3997 mInsetsStateController.getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME)); 3998 // 4. Update the IME control target to apply any inset change and animation. 3999 // 5. Reparent the IME container surface to either the input target app, or the IME window 4000 // parent. 4001 updateImeControlTarget(true /* forceUpdateImeParent */); 4002 } 4003 4004 @VisibleForTesting setImeInputTarget(WindowState target)4005 void setImeInputTarget(WindowState target) { 4006 mImeInputTarget = target; 4007 boolean canScreenshot = mImeInputTarget == null || !mImeInputTarget.isSecureLocked(); 4008 if (mImeWindowsContainer.setCanScreenshot(canScreenshot)) { 4009 mWmService.requestTraversal(); 4010 } 4011 } 4012 4013 @VisibleForTesting setImeControlTarget(InsetsControlTarget target)4014 void setImeControlTarget(InsetsControlTarget target) { 4015 mImeControlTarget = target; 4016 } 4017 4018 @VisibleForTesting attachAndShowImeScreenshotOnTarget()4019 void attachAndShowImeScreenshotOnTarget() { 4020 // No need to attach screenshot if the IME target not exists or screen is off. 4021 if (!shouldImeAttachedToApp() || !mWmService.mPolicy.isScreenOn()) { 4022 return; 4023 } 4024 4025 final SurfaceControl.Transaction t = getPendingTransaction(); 4026 // Prepare IME screenshot for the target if it allows to attach into. 4027 if (mInputMethodWindow != null && mInputMethodWindow.isVisible()) { 4028 final Task task = mImeLayeringTarget.getTask(); 4029 // Re-new the IME screenshot when it does not exist or the size changed. 4030 final boolean renewImeSurface = mImeScreenshot == null 4031 || mImeScreenshot.getWidth() != mInputMethodWindow.getFrame().width() 4032 || mImeScreenshot.getHeight() != mInputMethodWindow.getFrame().height(); 4033 if (task != null && !task.isHomeOrRecentsRootTask()) { 4034 SurfaceControl.ScreenshotHardwareBuffer imeBuffer = renewImeSurface 4035 ? mWmService.mTaskSnapshotController.snapshotImeFromAttachedTask(task) 4036 : null; 4037 if (imeBuffer != null) { 4038 // Remove the last IME surface when the surface needs to renew. 4039 removeImeSurfaceImmediately(); 4040 mImeScreenshot = createImeSurface(imeBuffer, t); 4041 } 4042 } 4043 } 4044 4045 final boolean isValidSnapshot = mImeScreenshot != null && mImeScreenshot.isValid(); 4046 // Showing the IME screenshot if the target has already in app transition stage. 4047 // Note that if the current IME insets is not showing, no need to show IME screenshot 4048 // to reflect the true IME insets visibility and the app task layout as possible. 4049 if (isValidSnapshot && getInsetsStateController().getImeSourceProvider().isImeShowing()) { 4050 if (DEBUG_INPUT_METHOD) { 4051 Slog.d(TAG, "show IME snapshot, ime target=" + mImeLayeringTarget); 4052 } 4053 t.show(mImeScreenshot); 4054 } else if (!isValidSnapshot) { 4055 removeImeSurfaceImmediately(); 4056 } 4057 } 4058 4059 @VisibleForTesting createImeSurface(SurfaceControl.ScreenshotHardwareBuffer imeBuffer, Transaction t)4060 SurfaceControl createImeSurface(SurfaceControl.ScreenshotHardwareBuffer imeBuffer, 4061 Transaction t) { 4062 final HardwareBuffer buffer = imeBuffer.getHardwareBuffer(); 4063 if (DEBUG_INPUT_METHOD) Slog.d(TAG, "create IME snapshot for " 4064 + mImeLayeringTarget + ", buff width=" + buffer.getWidth() 4065 + ", height=" + buffer.getHeight()); 4066 final ActivityRecord activity = mImeLayeringTarget.mActivityRecord; 4067 final SurfaceControl imeSurface = mWmService.mSurfaceControlFactory.apply(null) 4068 .setName("IME-snapshot-surface") 4069 .setBLASTLayer() 4070 .setFormat(buffer.getFormat()) 4071 .setParent(activity.getSurfaceControl()) 4072 .setCallsite("DisplayContent.attachAndShowImeScreenshotOnTarget") 4073 .build(); 4074 // Make IME snapshot as trusted overlay 4075 InputMonitor.setTrustedOverlayInputInfo(imeSurface, t, getDisplayId(), 4076 "IME-snapshot-surface"); 4077 GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(buffer); 4078 t.setBuffer(imeSurface, graphicBuffer); 4079 t.setColorSpace(mSurfaceControl, ColorSpace.get(ColorSpace.Named.SRGB)); 4080 t.setRelativeLayer(imeSurface, activity.getSurfaceControl(), 1); 4081 t.setPosition(imeSurface, mInputMethodWindow.getDisplayFrame().left, 4082 mInputMethodWindow.getDisplayFrame().top); 4083 return imeSurface; 4084 } 4085 4086 /** 4087 * Shows the IME screenshot and attach to the IME target window. 4088 * 4089 * Used when the IME target window with IME visible is transitioning to the next target. 4090 * e.g. App transitioning or swiping this the task of the IME target window to recents app. 4091 */ showImeScreenshot()4092 void showImeScreenshot() { 4093 attachAndShowImeScreenshotOnTarget(); 4094 } 4095 4096 /** 4097 * Removes the IME screenshot when necessary. 4098 * 4099 * Used when app transition animation finished or obsoleted screenshot surface like size 4100 * changed by rotation. 4101 */ removeImeScreenshotIfPossible()4102 void removeImeScreenshotIfPossible() { 4103 if (mImeLayeringTarget == null 4104 || mImeLayeringTarget.mAttrs.type != TYPE_APPLICATION_STARTING 4105 && !mImeLayeringTarget.isAnimating(PARENTS | TRANSITION, 4106 ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)) { 4107 removeImeSurfaceImmediately(); 4108 } 4109 } 4110 4111 /** Removes the IME screenshot immediately. */ removeImeSurfaceImmediately()4112 void removeImeSurfaceImmediately() { 4113 if (mImeScreenshot != null) { 4114 if (DEBUG_INPUT_METHOD) Slog.d(TAG, "remove IME snapshot"); 4115 getSyncTransaction().remove(mImeScreenshot); 4116 mImeScreenshot = null; 4117 } 4118 } 4119 4120 /** 4121 * The IME input target is the window which receives input from IME. It is also a candidate 4122 * which controls the visibility and animation of the input method window. 4123 */ updateImeInputAndControlTarget(WindowState target)4124 void updateImeInputAndControlTarget(WindowState target) { 4125 if (mImeInputTarget != target) { 4126 ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target); 4127 setImeInputTarget(target); 4128 mInsetsStateController.updateAboveInsetsState(mInputMethodWindow, mInsetsStateController 4129 .getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME)); 4130 updateImeControlTarget(); 4131 } 4132 // Unfreeze IME insets after the new target updated, in case updateAboveInsetsState may 4133 // deliver unrelated IME insets change to the non-IME requester. 4134 if (target != null && target.mActivityRecord != null) { 4135 target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false; 4136 } 4137 } 4138 updateImeControlTarget()4139 void updateImeControlTarget() { 4140 updateImeControlTarget(false /* forceUpdateImeParent */); 4141 } 4142 updateImeControlTarget(boolean forceUpdateImeParent)4143 void updateImeControlTarget(boolean forceUpdateImeParent) { 4144 InsetsControlTarget prevImeControlTarget = mImeControlTarget; 4145 mImeControlTarget = computeImeControlTarget(); 4146 mInsetsStateController.onImeControlTargetChanged(mImeControlTarget); 4147 // Update Ime parent when IME insets leash created or the new IME layering target might 4148 // updated from setImeLayeringTarget, which is the best time that default IME visibility 4149 // has been settled down after IME control target changed. 4150 final boolean imeParentChanged = 4151 prevImeControlTarget != mImeControlTarget || forceUpdateImeParent; 4152 if (imeParentChanged) { 4153 updateImeParent(); 4154 } 4155 4156 final WindowState win = InsetsControlTarget.asWindowOrNull(mImeControlTarget); 4157 final IBinder token = win != null ? win.mClient.asBinder() : null; 4158 // Note: not allowed to call into IMMS with the WM lock held, hence the post. 4159 mWmService.mH.post(() -> 4160 InputMethodManagerInternal.get().reportImeControl(token, imeParentChanged) 4161 ); 4162 } 4163 updateImeParent()4164 void updateImeParent() { 4165 final SurfaceControl newParent = computeImeParent(); 4166 if (newParent != null && newParent != mInputMethodSurfaceParent) { 4167 mInputMethodSurfaceParent = newParent; 4168 getSyncTransaction().reparent(mImeWindowsContainer.mSurfaceControl, newParent); 4169 // When surface parent is removed, the relative layer will also be removed. We need to 4170 // do a force update to make sure there is a layer set for the new parent. 4171 assignRelativeLayerForIme(getSyncTransaction(), true /* forceUpdate */); 4172 scheduleAnimation(); 4173 } 4174 } 4175 4176 /** 4177 * Computes the window where we hand IME control to. 4178 */ 4179 @VisibleForTesting computeImeControlTarget()4180 InsetsControlTarget computeImeControlTarget() { 4181 if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null 4182 || (mImeInputTarget != null 4183 && getImeHostOrFallback(mImeInputTarget.getWindow()) 4184 == mRemoteInsetsControlTarget)) { 4185 return mRemoteInsetsControlTarget; 4186 } else { 4187 return mImeInputTarget; 4188 } 4189 } 4190 4191 /** 4192 * Computes the window the IME should be attached to. 4193 */ 4194 @VisibleForTesting computeImeParent()4195 SurfaceControl computeImeParent() { 4196 // Attach it to app if the target is part of an app and such app is covering the entire 4197 // screen. If it's not covering the entire screen the IME might extend beyond the apps 4198 // bounds. 4199 if (shouldImeAttachedToApp()) { 4200 if (mImeLayeringTarget.mActivityRecord != mImeInputTarget.mActivityRecord) { 4201 // Do not change parent if the window hasn't requested IME. 4202 return null; 4203 } 4204 return mImeLayeringTarget.mActivityRecord.getSurfaceControl(); 4205 } 4206 4207 // Otherwise, we just attach it to where the display area policy put it. 4208 return mImeWindowsContainer.getParent() != null 4209 ? mImeWindowsContainer.getParent().getSurfaceControl() : null; 4210 } 4211 setLayoutNeeded()4212 void setLayoutNeeded() { 4213 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3)); 4214 mLayoutNeeded = true; 4215 } 4216 clearLayoutNeeded()4217 private void clearLayoutNeeded() { 4218 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3)); 4219 mLayoutNeeded = false; 4220 } 4221 isLayoutNeeded()4222 boolean isLayoutNeeded() { 4223 return mLayoutNeeded; 4224 } 4225 dumpTokens(PrintWriter pw, boolean dumpAll)4226 void dumpTokens(PrintWriter pw, boolean dumpAll) { 4227 if (mTokenMap.isEmpty()) { 4228 return; 4229 } 4230 pw.println(" Display #" + mDisplayId); 4231 final Iterator<WindowToken> it = mTokenMap.values().iterator(); 4232 while (it.hasNext()) { 4233 final WindowToken token = it.next(); 4234 pw.print(" "); 4235 pw.print(token); 4236 if (dumpAll) { 4237 pw.println(':'); 4238 token.dump(pw, " ", dumpAll); 4239 } else { 4240 pw.println(); 4241 } 4242 } 4243 4244 if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty() || !mChangingContainers.isEmpty()) { 4245 pw.println(); 4246 if (mOpeningApps.size() > 0) { 4247 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 4248 } 4249 if (mClosingApps.size() > 0) { 4250 pw.print(" mClosingApps="); pw.println(mClosingApps); 4251 } 4252 if (mChangingContainers.size() > 0) { 4253 pw.print(" mChangingApps="); pw.println(mChangingContainers); 4254 } 4255 } 4256 4257 mUnknownAppVisibilityController.dump(pw, " "); 4258 } 4259 dumpWindowAnimators(PrintWriter pw, String subPrefix)4260 void dumpWindowAnimators(PrintWriter pw, String subPrefix) { 4261 final int[] index = new int[1]; 4262 forAllWindows(w -> { 4263 final WindowStateAnimator wAnim = w.mWinAnimator; 4264 pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim); 4265 index[0] = index[0] + 1; 4266 }, false /* traverseTopToBottom */); 4267 } 4268 4269 /** 4270 * Starts the Keyguard exit animation on all windows that don't belong to an app token. 4271 */ startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade, boolean subtle)4272 void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade, 4273 boolean subtle) { 4274 final WindowManagerPolicy policy = mWmService.mPolicy; 4275 forAllWindows(w -> { 4276 if (w.mActivityRecord == null && policy.canBeHiddenByKeyguardLw(w) 4277 && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) { 4278 w.startAnimation(policy.createHiddenByKeyguardExit( 4279 onWallpaper, goingToShade, subtle)); 4280 } 4281 }, true /* traverseTopToBottom */); 4282 for (int i = mShellRoots.size() - 1; i >= 0; --i) { 4283 mShellRoots.valueAt(i).startAnimation(policy.createHiddenByKeyguardExit( 4284 onWallpaper, goingToShade, subtle)); 4285 } 4286 } 4287 4288 /** @return {@code true} if there is window to wait before enabling the screen. */ shouldWaitForSystemDecorWindowsOnBoot()4289 boolean shouldWaitForSystemDecorWindowsOnBoot() { 4290 if (!isDefaultDisplay && !supportsSystemDecorations()) { 4291 // Nothing to wait because the secondary display doesn't support system decorations, 4292 // there is no wallpaper, keyguard (status bar) or application (home) window to show 4293 // during booting. 4294 return false; 4295 } 4296 4297 final SparseBooleanArray drawnWindowTypes = new SparseBooleanArray(); 4298 // Presuppose keyguard is drawn because if its window isn't attached, we don't know if it 4299 // wants to be shown or hidden, then it should not delay enabling the screen. 4300 drawnWindowTypes.put(TYPE_NOTIFICATION_SHADE, true); 4301 4302 final WindowState visibleNotDrawnWindow = getWindow(w -> { 4303 final boolean isVisible = w.isVisible() && !w.mObscured; 4304 final boolean isDrawn = w.isDrawn(); 4305 if (isVisible && !isDrawn) { 4306 ProtoLog.d(WM_DEBUG_BOOT, 4307 "DisplayContent: boot is waiting for window of type %d to be drawn", 4308 w.mAttrs.type); 4309 return true; 4310 } 4311 if (isDrawn) { 4312 switch (w.mAttrs.type) { 4313 case TYPE_BOOT_PROGRESS: 4314 case TYPE_BASE_APPLICATION: 4315 case TYPE_WALLPAPER: 4316 drawnWindowTypes.put(w.mAttrs.type, true); 4317 break; 4318 case TYPE_NOTIFICATION_SHADE: 4319 drawnWindowTypes.put(TYPE_NOTIFICATION_SHADE, 4320 mWmService.mPolicy.isKeyguardDrawnLw()); 4321 break; 4322 } 4323 } 4324 return false; 4325 }); 4326 4327 if (visibleNotDrawnWindow != null) { 4328 // Wait for the visible window to be drawn. 4329 return true; 4330 } 4331 4332 // if the wallpaper service is disabled on the device, we're never going to have 4333 // wallpaper, don't bother waiting for it 4334 boolean wallpaperEnabled = mWmService.mContext.getResources().getBoolean( 4335 com.android.internal.R.bool.config_enableWallpaperService) 4336 && mWmService.mContext.getResources().getBoolean( 4337 com.android.internal.R.bool.config_checkWallpaperAtBoot) 4338 && !mWmService.mOnlyCore; 4339 4340 final boolean haveBootMsg = drawnWindowTypes.get(TYPE_BOOT_PROGRESS); 4341 final boolean haveApp = drawnWindowTypes.get(TYPE_BASE_APPLICATION); 4342 final boolean haveWallpaper = drawnWindowTypes.get(TYPE_WALLPAPER); 4343 final boolean haveKeyguard = drawnWindowTypes.get(TYPE_NOTIFICATION_SHADE); 4344 4345 ProtoLog.i(WM_DEBUG_SCREEN_ON, 4346 "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b " 4347 + "wallEnabled=%b haveKeyguard=%b", 4348 mWmService.mSystemBooted, mWmService.mShowingBootMessages, haveBootMsg, 4349 haveApp, haveWallpaper, wallpaperEnabled, haveKeyguard); 4350 4351 // If we are turning on the screen to show the boot message, don't do it until the boot 4352 // message is actually displayed. 4353 if (!mWmService.mSystemBooted && !haveBootMsg) { 4354 return true; 4355 } 4356 4357 // If we are turning on the screen after the boot is completed normally, don't do so until 4358 // we have the application and wallpaper. 4359 if (mWmService.mSystemBooted 4360 && ((!haveApp && !haveKeyguard) || (wallpaperEnabled && !haveWallpaper))) { 4361 return true; 4362 } 4363 4364 return false; 4365 } 4366 updateWindowsForAnimator()4367 void updateWindowsForAnimator() { 4368 forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */); 4369 } 4370 isInputMethodClientFocus(int uid, int pid)4371 boolean isInputMethodClientFocus(int uid, int pid) { 4372 final WindowState imFocus = computeImeTarget(false /* updateImeTarget */); 4373 if (imFocus == null) { 4374 return false; 4375 } 4376 4377 if (DEBUG_INPUT_METHOD) { 4378 Slog.i(TAG_WM, "Desired input method target: " + imFocus); 4379 Slog.i(TAG_WM, "Current focus: " + mCurrentFocus + " displayId=" + mDisplayId); 4380 } 4381 4382 if (DEBUG_INPUT_METHOD) { 4383 Slog.i(TAG_WM, "IM target uid/pid: " + imFocus.mSession.mUid 4384 + "/" + imFocus.mSession.mPid); 4385 Slog.i(TAG_WM, "Requesting client uid/pid: " + uid + "/" + pid); 4386 } 4387 4388 return imFocus.mSession.mUid == uid && imFocus.mSession.mPid == pid; 4389 } 4390 hasSecureWindowOnScreen()4391 boolean hasSecureWindowOnScreen() { 4392 final WindowState win = getWindow(w -> w.isOnScreen() && w.isSecureLocked()); 4393 return win != null; 4394 } 4395 onWindowFreezeTimeout()4396 void onWindowFreezeTimeout() { 4397 Slog.w(TAG_WM, "Window freeze timeout expired."); 4398 mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 4399 4400 forAllWindows(w -> { 4401 if (!w.getOrientationChanging()) { 4402 return; 4403 } 4404 w.orientationChangeTimedOut(); 4405 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 4406 - mWmService.mDisplayFreezeTime); 4407 Slog.w(TAG_WM, "Force clearing orientation change: " + w); 4408 }, true /* traverseTopToBottom */); 4409 mWmService.mWindowPlacerLocked.performSurfacePlacement(); 4410 } 4411 4412 /** 4413 * Callbacks when the given type of {@link WindowContainer} animation finished running in the 4414 * hierarchy. 4415 */ onWindowAnimationFinished(@onNull WindowContainer wc, int type)4416 void onWindowAnimationFinished(@NonNull WindowContainer wc, int type) { 4417 if (type == ANIMATION_TYPE_APP_TRANSITION || type == ANIMATION_TYPE_RECENTS) { 4418 removeImeSurfaceImmediately(); 4419 } 4420 } 4421 4422 // TODO: Super unexpected long method that should be broken down... applySurfaceChangesTransaction()4423 void applySurfaceChangesTransaction() { 4424 final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked; 4425 4426 mTmpUpdateAllDrawn.clear(); 4427 4428 int repeats = 0; 4429 do { 4430 repeats++; 4431 if (repeats > 6) { 4432 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 4433 clearLayoutNeeded(); 4434 break; 4435 } 4436 4437 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner", 4438 pendingLayoutChanges); 4439 4440 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 4441 mWallpaperController.adjustWallpaperWindows(); 4442 } 4443 4444 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { 4445 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 4446 if (updateOrientation()) { 4447 setLayoutNeeded(); 4448 sendNewConfiguration(); 4449 } 4450 } 4451 4452 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) { 4453 setLayoutNeeded(); 4454 } 4455 4456 // FIRST LOOP: Perform a layout, if needed. 4457 if (repeats < LAYOUT_REPEAT_THRESHOLD) { 4458 performLayout(repeats == 1, false /* updateInputWindows */); 4459 } else { 4460 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 4461 } 4462 4463 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating. 4464 pendingLayoutChanges = 0; 4465 4466 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy"); 4467 try { 4468 mDisplayPolicy.beginPostLayoutPolicyLw(); 4469 forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */); 4470 pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw(); 4471 } finally { 4472 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4473 } 4474 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats( 4475 "after finishPostLayoutPolicyLw", pendingLayoutChanges); 4476 mInsetsStateController.onPostLayout(); 4477 } while (pendingLayoutChanges != 0); 4478 4479 mTmpApplySurfaceChangesTransactionState.reset(); 4480 4481 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges"); 4482 try { 4483 forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */); 4484 } finally { 4485 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4486 } 4487 prepareSurfaces(); 4488 4489 // This should be called after the insets have been dispatched to clients and we have 4490 // committed finish drawing windows. 4491 mInsetsStateController.getImeSourceProvider().checkShowImePostLayout(); 4492 4493 mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent; 4494 if (!mWmService.mDisplayFrozen) { 4495 mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId, 4496 mLastHasContent, 4497 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate, 4498 mTmpApplySurfaceChangesTransactionState.preferredModeId, 4499 mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate, 4500 mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate, 4501 mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing, 4502 true /* inTraversal, must call performTraversalInTrans... below */); 4503 } 4504 // If the display now has content, or no longer has content, update layer mirroring. 4505 updateMirroring(); 4506 4507 final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible(); 4508 if (wallpaperVisible != mLastWallpaperVisible) { 4509 mLastWallpaperVisible = wallpaperVisible; 4510 mWmService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this); 4511 } 4512 4513 while (!mTmpUpdateAllDrawn.isEmpty()) { 4514 final ActivityRecord activity = mTmpUpdateAllDrawn.removeLast(); 4515 // See if any windows have been drawn, so they (and others associated with them) 4516 // can now be shown. 4517 activity.updateAllDrawn(); 4518 } 4519 } 4520 updateBounds()4521 private void updateBounds() { 4522 calculateBounds(mDisplayInfo, mTmpBounds); 4523 setBounds(mTmpBounds); 4524 if (mPortalWindowHandle != null && mParentSurfaceControl != null) { 4525 mPortalWindowHandle.touchableRegion.getBounds(mTmpRect); 4526 if (!mTmpBounds.equals(mTmpRect)) { 4527 mPortalWindowHandle.touchableRegion.set(mTmpBounds); 4528 getPendingTransaction().setInputWindowInfo( 4529 mParentSurfaceControl, mPortalWindowHandle); 4530 } 4531 } 4532 } 4533 4534 // Determines the current display bounds based on the current state calculateBounds(DisplayInfo displayInfo, Rect out)4535 private void calculateBounds(DisplayInfo displayInfo, Rect out) { 4536 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. 4537 final int rotation = displayInfo.rotation; 4538 boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); 4539 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 4540 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 4541 int width = displayInfo.logicalWidth; 4542 int left = (physWidth - width) / 2; 4543 int height = displayInfo.logicalHeight; 4544 int top = (physHeight - height) / 2; 4545 out.set(left, top, left + width, top + height); 4546 } 4547 getBounds(Rect out, @Rotation int rotation)4548 private void getBounds(Rect out, @Rotation int rotation) { 4549 getBounds(out); 4550 4551 // Rotate the Rect if needed. 4552 final int currentRotation = mDisplayInfo.rotation; 4553 final int rotationDelta = deltaRotation(currentRotation, rotation); 4554 if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { 4555 out.set(0, 0, out.height(), out.width()); 4556 } 4557 } 4558 4559 /** @return the orientation of the display when it's rotation is ROTATION_0. */ getNaturalOrientation()4560 int getNaturalOrientation() { 4561 return mBaseDisplayWidth < mBaseDisplayHeight 4562 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; 4563 } 4564 performLayout(boolean initial, boolean updateInputWindows)4565 void performLayout(boolean initial, boolean updateInputWindows) { 4566 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performLayout"); 4567 try { 4568 performLayoutNoTrace(initial, updateInputWindows); 4569 } finally { 4570 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4571 } 4572 } 4573 performLayoutNoTrace(boolean initial, boolean updateInputWindows)4574 private void performLayoutNoTrace(boolean initial, boolean updateInputWindows) { 4575 if (!isLayoutNeeded()) { 4576 return; 4577 } 4578 clearLayoutNeeded(); 4579 4580 if (DEBUG_LAYOUT) { 4581 Slog.v(TAG, "-------------------------------------"); 4582 Slog.v(TAG, "performLayout: dw=" + mDisplayInfo.logicalWidth 4583 + " dh=" + mDisplayInfo.logicalHeight); 4584 } 4585 4586 int seq = mLayoutSeq + 1; 4587 if (seq < 0) seq = 0; 4588 mLayoutSeq = seq; 4589 4590 mTmpInitial = initial; 4591 4592 4593 // First perform layout of any root windows (not attached to another window). 4594 forAllWindows(mPerformLayout, true /* traverseTopToBottom */); 4595 4596 // Now perform layout of attached windows, which usually depend on the position of the 4597 // window they are attached to. XXX does not deal with windows that are attached to windows 4598 // that are themselves attached. 4599 forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */); 4600 4601 // Window frames may have changed. Tell the input dispatcher about it. 4602 mInputMonitor.setUpdateInputWindowsNeededLw(); 4603 if (updateInputWindows) { 4604 mInputMonitor.updateInputWindowsLw(false /*force*/); 4605 } 4606 } 4607 4608 /** 4609 * Takes a snapshot of the display. In landscape mode this grabs the whole screen. 4610 * In portrait mode, it grabs the full screenshot. 4611 */ screenshotDisplayLocked()4612 Bitmap screenshotDisplayLocked() { 4613 if (!mWmService.mPolicy.isScreenOn()) { 4614 if (DEBUG_SCREENSHOT) { 4615 Slog.i(TAG_WM, "Attempted to take screenshot while display was off."); 4616 } 4617 return null; 4618 } 4619 4620 final ScreenRotationAnimation screenRotationAnimation = 4621 mWmService.mRoot.getDisplayContent(DEFAULT_DISPLAY).getRotationAnimation(); 4622 final boolean inRotation = screenRotationAnimation != null && 4623 screenRotationAnimation.isAnimating(); 4624 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, "Taking screenshot while rotating"); 4625 4626 // Send invalid rect and no width and height since it will screenshot the entire display. 4627 final IBinder displayToken = SurfaceControl.getInternalDisplayToken(); 4628 final SurfaceControl.DisplayCaptureArgs captureArgs = 4629 new SurfaceControl.DisplayCaptureArgs.Builder(displayToken) 4630 .setUseIdentityTransform(inRotation) 4631 .build(); 4632 final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = 4633 SurfaceControl.captureDisplay(captureArgs); 4634 final Bitmap bitmap = screenshotBuffer == null ? null : screenshotBuffer.asBitmap(); 4635 if (bitmap == null) { 4636 Slog.w(TAG_WM, "Failed to take screenshot"); 4637 return null; 4638 } 4639 4640 // Create a copy of the screenshot that is immutable and backed in ashmem. 4641 // This greatly reduces the overhead of passing the bitmap between processes. 4642 final Bitmap ret = bitmap.asShared(); 4643 if (ret != bitmap) { 4644 bitmap.recycle(); 4645 } 4646 return ret; 4647 } 4648 setExitingTokensHasVisible(boolean hasVisible)4649 void setExitingTokensHasVisible(boolean hasVisible) { 4650 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 4651 mExitingTokens.get(i).hasVisible = hasVisible; 4652 } 4653 4654 // Initialize state of exiting applications. 4655 forAllRootTasks(task -> { 4656 final ArrayList<ActivityRecord> activities = task.mExitingActivities; 4657 for (int j = activities.size() - 1; j >= 0; --j) { 4658 activities.get(j).hasVisible = hasVisible; 4659 } 4660 }); 4661 } 4662 removeExistingTokensIfPossible()4663 void removeExistingTokensIfPossible() { 4664 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 4665 final WindowToken token = mExitingTokens.get(i); 4666 if (!token.hasVisible) { 4667 mExitingTokens.remove(i); 4668 } 4669 } 4670 4671 // clear first just in case. 4672 mTmpActivityList.clear(); 4673 // Time to remove any exiting applications? 4674 forAllRootTasks(task -> { 4675 final ArrayList<ActivityRecord> activities = task.mExitingActivities; 4676 for (int j = activities.size() - 1; j >= 0; --j) { 4677 final ActivityRecord activity = activities.get(j); 4678 if (!activity.hasVisible && !mDisplayContent.mClosingApps.contains(activity) 4679 && (!activity.mIsExiting || activity.isEmpty())) { 4680 mTmpActivityList.add(activity); 4681 } 4682 } 4683 }); 4684 if (!mTmpActivityList.isEmpty()) { 4685 // Make sure there is no animation running on this activity, so any windows 4686 // associated with it will be removed as soon as their animations are 4687 // complete. 4688 cancelAnimation(); 4689 } 4690 for (int i = 0; i < mTmpActivityList.size(); ++i) { 4691 final ActivityRecord activity = mTmpActivityList.get(i); 4692 ProtoLog.v(WM_DEBUG_ADD_REMOVE, 4693 "performLayout: Activity exiting now removed %s", activity); 4694 activity.removeIfPossible(); 4695 } 4696 // Clear afterwards so we don't hold references. 4697 mTmpActivityList.clear(); 4698 } 4699 4700 @Override onDescendantOverrideConfigurationChanged()4701 void onDescendantOverrideConfigurationChanged() { 4702 setLayoutNeeded(); 4703 mWmService.requestTraversal(); 4704 } 4705 4706 @Override okToDisplay()4707 boolean okToDisplay() { 4708 return okToDisplay(false /* ignoreFrozen */, false /* ignoreScreenOn */); 4709 } 4710 okToDisplay(boolean ignoreFrozen, boolean ignoreScreenOn)4711 boolean okToDisplay(boolean ignoreFrozen, boolean ignoreScreenOn) { 4712 if (mDisplayId == DEFAULT_DISPLAY) { 4713 return (!mWmService.mDisplayFrozen || ignoreFrozen) 4714 && mWmService.mDisplayEnabled 4715 && (ignoreScreenOn || mWmService.mPolicy.isScreenOn()); 4716 } 4717 return mDisplayInfo.state == Display.STATE_ON; 4718 } 4719 4720 @Override okToAnimate(boolean ignoreFrozen, boolean ignoreScreenOn)4721 boolean okToAnimate(boolean ignoreFrozen, boolean ignoreScreenOn) { 4722 return okToDisplay(ignoreFrozen, ignoreScreenOn) 4723 && (mDisplayId != DEFAULT_DISPLAY 4724 || mWmService.mPolicy.okToAnimate(ignoreScreenOn)) 4725 && getDisplayPolicy().isScreenOnFully(); 4726 } 4727 4728 static final class TaskForResizePointSearchResult { 4729 private Task taskForResize; 4730 private int x; 4731 private int y; 4732 private int delta; 4733 private Rect mTmpRect = new Rect(); 4734 process(WindowContainer root, int x, int y, int delta)4735 Task process(WindowContainer root, int x, int y, int delta) { 4736 taskForResize = null; 4737 this.x = x; 4738 this.y = y; 4739 this.delta = delta; 4740 mTmpRect.setEmpty(); 4741 4742 final PooledFunction f = PooledLambda.obtainFunction( 4743 TaskForResizePointSearchResult::processTask, this, PooledLambda.__(Task.class)); 4744 root.forAllTasks(f); 4745 f.recycle(); 4746 4747 return taskForResize; 4748 } 4749 processTask(Task task)4750 private boolean processTask(Task task) { 4751 if (!task.getRootTask().getWindowConfiguration().canResizeTask()) { 4752 return true; 4753 } 4754 4755 if (task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { 4756 return true; 4757 } 4758 4759 // TODO(b/165794880): Freeform task organizer doesn't support drag-resize yet. Remove 4760 // the special case when it does. 4761 if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FREEFORM) { 4762 return true; 4763 } 4764 4765 // We need to use the task's dim bounds (which is derived from the visible bounds of 4766 // its apps windows) for any touch-related tests. Can't use the task's original 4767 // bounds because it might be adjusted to fit the content frame. One example is when 4768 // the task is put to top-left quadrant, the actual visible area would not start at 4769 // (0,0) after it's adjusted for the status bar. 4770 task.getDimBounds(mTmpRect); 4771 mTmpRect.inset(-delta, -delta); 4772 if (mTmpRect.contains(x, y)) { 4773 mTmpRect.inset(delta, delta); 4774 4775 if (!mTmpRect.contains(x, y)) { 4776 taskForResize = task; 4777 return true; 4778 } 4779 // User touched inside the task. No need to look further, 4780 // focus transfer will be handled in ACTION_UP. 4781 return true; 4782 } 4783 4784 return false; 4785 } 4786 } 4787 4788 private static final class ApplySurfaceChangesTransactionState { 4789 public boolean displayHasContent; 4790 public boolean obscured; 4791 public boolean syswin; 4792 public boolean preferMinimalPostProcessing; 4793 public float preferredRefreshRate; 4794 public int preferredModeId; 4795 public float preferredMinRefreshRate; 4796 public float preferredMaxRefreshRate; 4797 reset()4798 void reset() { 4799 displayHasContent = false; 4800 obscured = false; 4801 syswin = false; 4802 preferMinimalPostProcessing = false; 4803 preferredRefreshRate = 0; 4804 preferredModeId = 0; 4805 preferredMinRefreshRate = 0; 4806 preferredMaxRefreshRate = 0; 4807 } 4808 } 4809 4810 /** 4811 * Container for IME windows. 4812 * 4813 * This has some special behaviors: 4814 * - layers assignment is ignored except if setNeedsLayer() has been called before (and no 4815 * layer has been assigned since), to facilitate assigning the layer from the IME target, or 4816 * fall back if there is no target. 4817 * - the container doesn't always participate in window traversal, according to 4818 * {@link #skipImeWindowsDuringTraversal()} 4819 */ 4820 private static class ImeContainer extends DisplayArea.Tokens { 4821 boolean mNeedsLayer = false; 4822 ImeContainer(WindowManagerService wms)4823 ImeContainer(WindowManagerService wms) { 4824 super(wms, Type.ABOVE_TASKS, "ImeContainer"); 4825 } 4826 setNeedsLayer()4827 public void setNeedsLayer() { 4828 mNeedsLayer = true; 4829 } 4830 4831 @Override getOrientation(int candidate)4832 int getOrientation(int candidate) { 4833 if (mIgnoreOrientationRequest) { 4834 return SCREEN_ORIENTATION_UNSET; 4835 } 4836 4837 // IME does not participate in orientation. 4838 return candidate; 4839 } 4840 4841 @Override forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4842 boolean forAllWindows(ToBooleanFunction<WindowState> callback, 4843 boolean traverseTopToBottom) { 4844 final DisplayContent dc = mDisplayContent; 4845 if (skipImeWindowsDuringTraversal(dc)) { 4846 return false; 4847 } 4848 return super.forAllWindows(callback, traverseTopToBottom); 4849 } 4850 skipImeWindowsDuringTraversal(DisplayContent dc)4851 private static boolean skipImeWindowsDuringTraversal(DisplayContent dc) { 4852 // We skip IME windows so they're processed just above their target, except 4853 // in split-screen mode where we process the IME containers above the docked divider. 4854 // Note that this method check should align with {@link 4855 // WindowState#applyImeWindowsIfNeeded} in case of any state mismatch. 4856 return dc.mImeLayeringTarget != null 4857 && (!dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated() 4858 || dc.mImeLayeringTarget.getTask() == null) 4859 // Make sure that the IME window won't be skipped to report that it has 4860 // completed the orientation change. 4861 && !dc.mWmService.mDisplayFrozen; 4862 } 4863 4864 /** Like {@link #forAllWindows}, but ignores {@link #skipImeWindowsDuringTraversal} */ forAllWindowForce(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)4865 boolean forAllWindowForce(ToBooleanFunction<WindowState> callback, 4866 boolean traverseTopToBottom) { 4867 return super.forAllWindows(callback, traverseTopToBottom); 4868 } 4869 4870 @Override assignLayer(Transaction t, int layer)4871 void assignLayer(Transaction t, int layer) { 4872 if (!mNeedsLayer) { 4873 return; 4874 } 4875 super.assignLayer(t, layer); 4876 mNeedsLayer = false; 4877 } 4878 4879 @Override assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer, boolean forceUpdate)4880 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer, 4881 boolean forceUpdate) { 4882 if (!mNeedsLayer) { 4883 return; 4884 } 4885 super.assignRelativeLayer(t, relativeTo, layer, forceUpdate); 4886 mNeedsLayer = false; 4887 } 4888 } 4889 4890 @Override getSession()4891 SurfaceSession getSession() { 4892 return mSession; 4893 } 4894 4895 @Override makeChildSurface(WindowContainer child)4896 SurfaceControl.Builder makeChildSurface(WindowContainer child) { 4897 SurfaceSession s = child != null ? child.getSession() : getSession(); 4898 final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer(); 4899 if (child == null) { 4900 return b; 4901 } 4902 4903 return b.setName(child.getName()) 4904 .setParent(mSurfaceControl); 4905 } 4906 4907 /** 4908 * The makeSurface variants are for use by the window-container 4909 * hierarchy. makeOverlay here is a function for various non windowing 4910 * overlays like the ScreenRotation screenshot, the Strict Mode Flash 4911 * and other potpourii. 4912 */ makeOverlay()4913 SurfaceControl.Builder makeOverlay() { 4914 return mWmService.makeSurfaceBuilder(mSession).setParent(getOverlayLayer()); 4915 } 4916 4917 @Override makeAnimationLeash()4918 public SurfaceControl.Builder makeAnimationLeash() { 4919 return mWmService.makeSurfaceBuilder(mSession).setParent(mSurfaceControl) 4920 .setContainerLayer(); 4921 } 4922 4923 /** 4924 * Reparents the given surface to {@link #mOverlayLayer} SurfaceControl. 4925 */ reparentToOverlay(Transaction transaction, SurfaceControl surface)4926 void reparentToOverlay(Transaction transaction, SurfaceControl surface) { 4927 transaction.reparent(surface, getOverlayLayer()); 4928 } 4929 applyMagnificationSpec(MagnificationSpec spec)4930 void applyMagnificationSpec(MagnificationSpec spec) { 4931 if (spec.scale != 1.0) { 4932 mMagnificationSpec = spec; 4933 } else { 4934 mMagnificationSpec = null; 4935 } 4936 // Re-parent IME's SurfaceControl when MagnificationSpec changed. 4937 updateImeParent(); 4938 4939 if (spec.scale != 1.0) { 4940 applyMagnificationSpec(getPendingTransaction(), spec); 4941 } else { 4942 clearMagnificationSpec(getPendingTransaction()); 4943 } 4944 getPendingTransaction().apply(); 4945 } 4946 reapplyMagnificationSpec()4947 void reapplyMagnificationSpec() { 4948 if (mMagnificationSpec != null) { 4949 applyMagnificationSpec(getPendingTransaction(), mMagnificationSpec); 4950 } 4951 } 4952 4953 @Override onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent)4954 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) { 4955 // Since we are the top of the SurfaceControl hierarchy here 4956 // we create the root surfaces explicitly rather than chaining 4957 // up as the default implementation in onParentChanged does. So we 4958 // explicitly do NOT call super here. 4959 4960 if (!isReady()) { 4961 // TODO(b/62541591): evaluate whether this is the best spot to declare the 4962 // {@link DisplayContent} ready for use. 4963 mDisplayReady = true; 4964 4965 mWmService.mAnimator.addDisplayLocked(mDisplayId); 4966 4967 if (mWmService.mDisplayManagerInternal != null) { 4968 mWmService.mDisplayManagerInternal 4969 .setDisplayInfoOverrideFromWindowManager(mDisplayId, getDisplayInfo()); 4970 configureDisplayPolicy(); 4971 } 4972 4973 reconfigureDisplayLocked(); 4974 onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration()); 4975 mWmService.mDisplayNotificationController.dispatchDisplayAdded(this); 4976 // Attach the SystemUiContext to this DisplayContent the get latest configuration. 4977 // Note that the SystemUiContext will be removed automatically if this DisplayContent 4978 // is detached. 4979 mWmService.mWindowContextListenerController.registerWindowContainerListener( 4980 getDisplayUiContext().getWindowContextToken(), this, SYSTEM_UID, 4981 INVALID_WINDOW_TYPE, null /* options */); 4982 } 4983 } 4984 4985 @Override assignChildLayers(SurfaceControl.Transaction t)4986 void assignChildLayers(SurfaceControl.Transaction t) { 4987 assignRelativeLayerForIme(t, false /* forceUpdate */); 4988 super.assignChildLayers(t); 4989 } 4990 assignRelativeLayerForIme(SurfaceControl.Transaction t, boolean forceUpdate)4991 private void assignRelativeLayerForIme(SurfaceControl.Transaction t, boolean forceUpdate) { 4992 mImeWindowsContainer.setNeedsLayer(); 4993 final WindowState imeTarget = mImeLayeringTarget; 4994 // In the case where we have an IME target that is not in split-screen mode IME 4995 // assignment is easy. We just need the IME to go directly above the target. This way 4996 // children of the target will naturally go above the IME and everyone is happy. 4997 // 4998 // In the case of split-screen windowing mode, we need to elevate the IME above the 4999 // docked divider while keeping the app itself below the docked divider, so instead 5000 // we will put the docked divider below the IME. @see #assignRelativeLayerForImeTargetChild 5001 // 5002 // In the case the IME target is animating, the animation Z order may be different 5003 // than the WindowContainer Z order, so it's difficult to be sure we have the correct 5004 // IME target. In this case we just layer the IME over its parent surface. 5005 // 5006 // In the case where we have no IME target we let its window parent to place it. 5007 // 5008 // Keep IME window in surface parent as long as app's starting window 5009 // exists so it get's layered above the starting window. 5010 if (imeTarget != null && !(imeTarget.mActivityRecord != null 5011 && imeTarget.mActivityRecord.hasStartingWindow())) { 5012 final WindowToken imeControlTargetToken = 5013 mImeControlTarget != null && mImeControlTarget.getWindow() != null 5014 ? mImeControlTarget.getWindow().mToken : null; 5015 final boolean canImeTargetSetRelativeLayer = imeTarget.getSurfaceControl() != null 5016 && imeTarget.mToken == imeControlTargetToken 5017 && !imeTarget.inMultiWindowMode() 5018 && imeTarget.mToken.getActivity(app -> app.isAnimating(TRANSITION | PARENTS, 5019 ANIMATION_TYPE_ALL & ~ANIMATION_TYPE_RECENTS)) == null; 5020 if (canImeTargetSetRelativeLayer) { 5021 mImeWindowsContainer.assignRelativeLayer(t, imeTarget.getSurfaceControl(), 5022 // TODO: We need to use an extra level on the app surface to ensure 5023 // this is always above SurfaceView but always below attached window. 5024 1, forceUpdate); 5025 return; 5026 } 5027 } 5028 if (mInputMethodSurfaceParent != null) { 5029 // The IME surface parent may not be its window parent's surface 5030 // (@see #computeImeParent), so set relative layer here instead of letting the window 5031 // parent to assign layer. 5032 mImeWindowsContainer.assignRelativeLayer(t, mInputMethodSurfaceParent, 1, forceUpdate); 5033 } 5034 } 5035 5036 /** 5037 * Here we satisfy an unfortunate special case of the IME in split-screen mode. Imagine 5038 * that the IME target is one of the docked applications. We'd like the docked divider to be 5039 * above both of the applications, and we'd like the IME to be above the docked divider. 5040 * However we need child windows of the applications to be above the IME (Text drag handles). 5041 * This is a non-strictly hierarcical layering and we need to break out of the Z ordering 5042 * somehow. We do this by relatively ordering children of the target to the IME in cooperation 5043 * with {@link WindowState#assignLayer} 5044 */ assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child)5045 void assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child) { 5046 child.assignRelativeLayer(t, mImeWindowsContainer.getSurfaceControl(), 1); 5047 } 5048 5049 @Override prepareSurfaces()5050 void prepareSurfaces() { 5051 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareSurfaces"); 5052 try { 5053 final Transaction transaction = getPendingTransaction(); 5054 super.prepareSurfaces(); 5055 5056 // TODO: Once we totally eliminate global transaction we will pass transaction in here 5057 // rather than merging to global. 5058 SurfaceControl.mergeToGlobalTransaction(transaction); 5059 } finally { 5060 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 5061 } 5062 } 5063 assignRootTaskOrdering()5064 void assignRootTaskOrdering() { 5065 forAllTaskDisplayAreas(taskDisplayArea -> { 5066 taskDisplayArea.assignRootTaskOrdering(getPendingTransaction()); 5067 }); 5068 } 5069 5070 /** 5071 * Increment the deferral count to determine whether to update the IME target. 5072 */ deferUpdateImeTarget()5073 void deferUpdateImeTarget() { 5074 if (mDeferUpdateImeTargetCount == 0) { 5075 mUpdateImeRequestedWhileDeferred = false; 5076 } 5077 mDeferUpdateImeTargetCount++; 5078 } 5079 5080 /** 5081 * Decrement the deferral count to determine whether to update the IME target. If the count 5082 * reaches 0, a new ime target will get computed. 5083 */ continueUpdateImeTarget()5084 void continueUpdateImeTarget() { 5085 if (mDeferUpdateImeTargetCount == 0) { 5086 return; 5087 } 5088 5089 mDeferUpdateImeTargetCount--; 5090 if (mDeferUpdateImeTargetCount == 0 && mUpdateImeRequestedWhileDeferred) { 5091 computeImeTarget(true /* updateImeTarget */); 5092 } 5093 } 5094 5095 /** 5096 * @return Whether a new IME target should be computed. 5097 */ canUpdateImeTarget()5098 private boolean canUpdateImeTarget() { 5099 return mDeferUpdateImeTargetCount == 0; 5100 } 5101 getInputMonitor()5102 InputMonitor getInputMonitor() { 5103 return mInputMonitor; 5104 } 5105 5106 /** 5107 * @return Cached value whether we told display manager that we have content. 5108 */ getLastHasContent()5109 boolean getLastHasContent() { 5110 return mLastHasContent; 5111 } 5112 registerPointerEventListener(@onNull PointerEventListener listener)5113 void registerPointerEventListener(@NonNull PointerEventListener listener) { 5114 mPointerEventDispatcher.registerInputEventListener(listener); 5115 } 5116 unregisterPointerEventListener(@onNull PointerEventListener listener)5117 void unregisterPointerEventListener(@NonNull PointerEventListener listener) { 5118 mPointerEventDispatcher.unregisterInputEventListener(listener); 5119 } 5120 5121 /** 5122 * Transfer app transition from other display to this display. 5123 * 5124 * @param from Display from where the app transition is transferred. 5125 * 5126 * TODO(new-app-transition): Remove this once the shell handles app transition. 5127 */ transferAppTransitionFrom(DisplayContent from)5128 void transferAppTransitionFrom(DisplayContent from) { 5129 final boolean prepared = mAppTransition.transferFrom(from.mAppTransition); 5130 if (prepared && okToAnimate()) { 5131 mSkipAppTransitionAnimation = false; 5132 } 5133 } 5134 5135 /** 5136 * @deprecated new transition should use {@link #requestTransitionAndLegacyPrepare(int, int)} 5137 */ 5138 @Deprecated prepareAppTransition(@indowManager.TransitionType int transit)5139 void prepareAppTransition(@WindowManager.TransitionType int transit) { 5140 prepareAppTransition(transit, 0 /* flags */); 5141 } 5142 5143 /** 5144 * @deprecated new transition should use {@link #requestTransitionAndLegacyPrepare(int, int)} 5145 */ 5146 @Deprecated prepareAppTransition(@indowManager.TransitionType int transit, @WindowManager.TransitionFlags int flags)5147 void prepareAppTransition(@WindowManager.TransitionType int transit, 5148 @WindowManager.TransitionFlags int flags) { 5149 final boolean prepared = mAppTransition.prepareAppTransition(transit, flags); 5150 if (prepared && okToAnimate()) { 5151 mSkipAppTransitionAnimation = false; 5152 } 5153 } 5154 5155 /** 5156 * Helper that both requests a transition (using the new transition system) and prepares 5157 * the legacy transition system. Use this when both systems have the same start-point. 5158 * 5159 * @see TransitionController#requestTransitionIfNeeded(int, int, WindowContainer, 5160 * WindowContainer) 5161 * @see AppTransition#prepareAppTransition 5162 */ requestTransitionAndLegacyPrepare(@indowManager.TransitionType int transit, @WindowManager.TransitionFlags int flags)5163 void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit, 5164 @WindowManager.TransitionFlags int flags) { 5165 prepareAppTransition(transit, flags); 5166 mTransitionController.requestTransitionIfNeeded(transit, flags, 5167 null /* trigger */, this); 5168 } 5169 5170 /** @see #requestTransitionAndLegacyPrepare(int, int) */ requestTransitionAndLegacyPrepare(@indowManager.TransitionType int transit, @Nullable WindowContainer trigger)5171 void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit, 5172 @Nullable WindowContainer trigger) { 5173 prepareAppTransition(transit); 5174 mTransitionController.requestTransitionIfNeeded(transit, 0 /* flags */, 5175 trigger, this); 5176 } 5177 executeAppTransition()5178 void executeAppTransition() { 5179 mTransitionController.setReady(this); 5180 if (mAppTransition.isTransitionSet()) { 5181 ProtoLog.w(WM_DEBUG_APP_TRANSITIONS, 5182 "Execute app transition: %s, displayId: %d Callers=%s", 5183 mAppTransition, mDisplayId, Debug.getCallers(5)); 5184 mAppTransition.setReady(); 5185 mWmService.mWindowPlacerLocked.requestTraversal(); 5186 } 5187 } 5188 cancelAppTransition()5189 void cancelAppTransition() { 5190 if (!mAppTransition.isTransitionSet() || mAppTransition.isRunning()) return; 5191 mAppTransition.abort(); 5192 } 5193 5194 /** 5195 * Update pendingLayoutChanges after app transition has finished. 5196 */ handleAnimatingStoppedAndTransition()5197 void handleAnimatingStoppedAndTransition() { 5198 int changes = 0; 5199 5200 mAppTransition.setIdle(); 5201 5202 for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) { 5203 final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i); 5204 mAppTransition.notifyAppTransitionFinishedLocked(token); 5205 } 5206 mNoAnimationNotifyOnTransitionFinished.clear(); 5207 5208 mWallpaperController.hideDeferredWallpapersIfNeededLegacy(); 5209 5210 onAppTransitionDone(); 5211 5212 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5213 ProtoLog.v(WM_DEBUG_WALLPAPER, "Wallpaper layer changed: assigning layers + relayout"); 5214 computeImeTarget(true /* updateImeTarget */); 5215 mWallpaperMayChange = true; 5216 // Since the window list has been rebuilt, focus might have to be recomputed since the 5217 // actual order of windows might have changed again. 5218 mWmService.mFocusMayChange = true; 5219 5220 pendingLayoutChanges |= changes; 5221 } 5222 5223 /** Check if pending app transition is for activity / task launch. */ isNextTransitionForward()5224 boolean isNextTransitionForward() { 5225 // TODO(b/191375840): decouple "forwardness" from transition system. 5226 if (mTransitionController.isShellTransitionsEnabled()) { 5227 @WindowManager.TransitionType int type = 5228 mTransitionController.getCollectingTransitionType(); 5229 return type == TRANSIT_OPEN || type == TRANSIT_TO_FRONT; 5230 } 5231 return mAppTransition.containsTransitRequest(TRANSIT_OPEN) 5232 || mAppTransition.containsTransitRequest(TRANSIT_TO_FRONT); 5233 } 5234 5235 /** 5236 * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 5237 */ supportsSystemDecorations()5238 boolean supportsSystemDecorations() { 5239 return (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this) 5240 || (mDisplay.getFlags() & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0 5241 || forceDesktopMode()) 5242 // VR virtual display will be used to run and render 2D app within a VR experience. 5243 && mDisplayId != mWmService.mVr2dDisplayId 5244 // Do not show system decorations on untrusted virtual display. 5245 && isTrusted(); 5246 } 5247 5248 /** 5249 * Get the window which owns the surface that this DisplayContent is re-parented to. 5250 * 5251 * @return the parent window. 5252 */ getParentWindow()5253 WindowState getParentWindow() { 5254 return mParentWindow; 5255 } 5256 5257 /** 5258 * Update the location of this display in the parent window. This enables windows in this 5259 * display to compute the global transformation matrix. 5260 * 5261 * @param win The parent window of this display. 5262 * @param x The x coordinate in the parent window. 5263 * @param y The y coordinate in the parent window. 5264 */ updateLocation(WindowState win, int x, int y)5265 void updateLocation(WindowState win, int x, int y) { 5266 if (mParentWindow != win) { 5267 throw new IllegalArgumentException( 5268 "The given window is not the parent window of this display."); 5269 } 5270 if (!mLocationInParentWindow.equals(x, y)) { 5271 mLocationInParentWindow.set(x, y); 5272 if (mWmService.mAccessibilityController.hasCallbacks()) { 5273 mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(mDisplayId); 5274 } 5275 notifyLocationInParentDisplayChanged(); 5276 } 5277 } 5278 getLocationInParentWindow()5279 Point getLocationInParentWindow() { 5280 return mLocationInParentWindow; 5281 } 5282 getLocationInParentDisplay()5283 Point getLocationInParentDisplay() { 5284 final Point location = new Point(); 5285 if (mParentWindow != null) { 5286 // LocationInParentWindow indicates the offset to (0,0) of window, but what we need is 5287 // the offset to (0,0) of display. 5288 DisplayContent dc = this; 5289 do { 5290 final WindowState displayParent = dc.getParentWindow(); 5291 location.x += displayParent.getFrame().left 5292 + (dc.getLocationInParentWindow().x * displayParent.mGlobalScale + 0.5f); 5293 location.y += displayParent.getFrame().top 5294 + (dc.getLocationInParentWindow().y * displayParent.mGlobalScale + 0.5f); 5295 dc = displayParent.getDisplayContent(); 5296 } while (dc != null && dc.getParentWindow() != null); 5297 } 5298 return location; 5299 } 5300 notifyLocationInParentDisplayChanged()5301 void notifyLocationInParentDisplayChanged() { 5302 forAllWindows(w -> { 5303 w.updateLocationInParentDisplayIfNeeded(); 5304 }, false /* traverseTopToBottom */); 5305 } 5306 getWindowingLayer()5307 SurfaceControl getWindowingLayer() { 5308 return mWindowingLayer; 5309 } 5310 getImeContainer()5311 DisplayArea.Tokens getImeContainer() { 5312 return mImeWindowsContainer; 5313 } 5314 getOverlayLayer()5315 SurfaceControl getOverlayLayer() { 5316 return mOverlayLayer; 5317 } 5318 5319 /** 5320 * Updates the display's system gesture exclusion. 5321 * 5322 * @return true, if the exclusion changed. 5323 */ updateSystemGestureExclusion()5324 boolean updateSystemGestureExclusion() { 5325 if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 0) { 5326 // No one's interested anyways. 5327 return false; 5328 } 5329 5330 final Region systemGestureExclusion = Region.obtain(); 5331 mSystemGestureExclusionWasRestricted = calculateSystemGestureExclusion( 5332 systemGestureExclusion, mSystemGestureExclusionUnrestricted); 5333 try { 5334 if (mSystemGestureExclusion.equals(systemGestureExclusion)) { 5335 return false; 5336 } 5337 mSystemGestureExclusion.set(systemGestureExclusion); 5338 final Region unrestrictedOrNull = mSystemGestureExclusionWasRestricted 5339 ? mSystemGestureExclusionUnrestricted : null; 5340 for (int i = mSystemGestureExclusionListeners.beginBroadcast() - 1; i >= 0; --i) { 5341 try { 5342 mSystemGestureExclusionListeners.getBroadcastItem(i) 5343 .onSystemGestureExclusionChanged(mDisplayId, systemGestureExclusion, 5344 unrestrictedOrNull); 5345 } catch (RemoteException e) { 5346 Slog.e(TAG, "Failed to notify SystemGestureExclusionListener", e); 5347 } 5348 } 5349 mSystemGestureExclusionListeners.finishBroadcast(); 5350 return true; 5351 } finally { 5352 systemGestureExclusion.recycle(); 5353 } 5354 } 5355 5356 /** 5357 * Calculates the system gesture exclusion. 5358 * 5359 * @param outExclusion will be set to the gesture exclusion region 5360 * @param outExclusionUnrestricted will be set to the gesture exclusion region without 5361 * any restrictions applied. 5362 * @return whether any restrictions were applied, i.e. outExclusion and outExclusionUnrestricted 5363 * differ. 5364 */ 5365 @VisibleForTesting calculateSystemGestureExclusion(Region outExclusion, @Nullable Region outExclusionUnrestricted)5366 boolean calculateSystemGestureExclusion(Region outExclusion, @Nullable 5367 Region outExclusionUnrestricted) { 5368 outExclusion.setEmpty(); 5369 if (outExclusionUnrestricted != null) { 5370 outExclusionUnrestricted.setEmpty(); 5371 } 5372 final Region unhandled = Region.obtain(); 5373 unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight); 5374 5375 final Rect leftEdge = mInsetsStateController.getSourceProvider(ITYPE_LEFT_GESTURES) 5376 .getSource().getFrame(); 5377 final Rect rightEdge = mInsetsStateController.getSourceProvider(ITYPE_RIGHT_GESTURES) 5378 .getSource().getFrame(); 5379 5380 final Region touchableRegion = Region.obtain(); 5381 final Region local = Region.obtain(); 5382 final int[] remainingLeftRight = 5383 {mSystemGestureExclusionLimit, mSystemGestureExclusionLimit}; 5384 5385 // Traverse all windows top down to assemble the gesture exclusion rects. 5386 // For each window, we only take the rects that fall within its touchable region. 5387 forAllWindows(w -> { 5388 if (!w.canReceiveTouchInput() || !w.isVisible() 5389 || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0 5390 || unhandled.isEmpty()) { 5391 return; 5392 } 5393 5394 // Get the touchable region of the window, and intersect with where the screen is still 5395 // touchable, i.e. touchable regions on top are not covering it yet. 5396 w.getEffectiveTouchableRegion(touchableRegion); 5397 touchableRegion.op(unhandled, Op.INTERSECT); 5398 5399 if (w.isImplicitlyExcludingAllSystemGestures()) { 5400 local.set(touchableRegion); 5401 } else { 5402 rectListToRegion(w.getSystemGestureExclusion(), local); 5403 5404 // Transform to display coordinates 5405 local.scale(w.mGlobalScale); 5406 final Rect frame = w.getWindowFrames().mFrame; 5407 local.translate(frame.left, frame.top); 5408 5409 // A window can only exclude system gestures where it is actually touchable 5410 local.op(touchableRegion, Op.INTERSECT); 5411 } 5412 5413 // Apply restriction if necessary. 5414 if (needsGestureExclusionRestrictions(w, false /* ignoreRequest */)) { 5415 5416 // Processes the region along the left edge. 5417 remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion, leftEdge, 5418 remainingLeftRight[0], w, EXCLUSION_LEFT); 5419 5420 // Processes the region along the right edge. 5421 remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, outExclusion, rightEdge, 5422 remainingLeftRight[1], w, EXCLUSION_RIGHT); 5423 5424 // Adds the middle (unrestricted area) 5425 final Region middle = Region.obtain(local); 5426 middle.op(leftEdge, Op.DIFFERENCE); 5427 middle.op(rightEdge, Op.DIFFERENCE); 5428 outExclusion.op(middle, Op.UNION); 5429 middle.recycle(); 5430 } else { 5431 boolean loggable = needsGestureExclusionRestrictions(w, true /* ignoreRequest */); 5432 if (loggable) { 5433 addToGlobalAndConsumeLimit(local, outExclusion, leftEdge, 5434 Integer.MAX_VALUE, w, EXCLUSION_LEFT); 5435 addToGlobalAndConsumeLimit(local, outExclusion, rightEdge, 5436 Integer.MAX_VALUE, w, EXCLUSION_RIGHT); 5437 } 5438 outExclusion.op(local, Op.UNION); 5439 } 5440 if (outExclusionUnrestricted != null) { 5441 outExclusionUnrestricted.op(local, Op.UNION); 5442 } 5443 unhandled.op(touchableRegion, Op.DIFFERENCE); 5444 }, true /* topToBottom */); 5445 local.recycle(); 5446 touchableRegion.recycle(); 5447 unhandled.recycle(); 5448 return remainingLeftRight[0] < mSystemGestureExclusionLimit 5449 || remainingLeftRight[1] < mSystemGestureExclusionLimit; 5450 } 5451 5452 /** 5453 * Returns whether gesture exclusion area should be restricted from the window depending on the 5454 * window/activity types and the requested navigation bar visibility and the behavior. 5455 * 5456 * @param win The target window. 5457 * @param ignoreRequest If this is {@code true}, only the window/activity types are considered. 5458 * @return {@code true} if the gesture exclusion restrictions are needed. 5459 */ needsGestureExclusionRestrictions(WindowState win, boolean ignoreRequest)5460 private static boolean needsGestureExclusionRestrictions(WindowState win, 5461 boolean ignoreRequest) { 5462 final int type = win.mAttrs.type; 5463 final boolean stickyHideNav = 5464 !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR) 5465 && win.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; 5466 return (!stickyHideNav || ignoreRequest) && type != TYPE_INPUT_METHOD 5467 && type != TYPE_NOTIFICATION_SHADE && win.getActivityType() != ACTIVITY_TYPE_HOME; 5468 } 5469 5470 /** 5471 * @return Whether gesture exclusion area should be logged for the given window 5472 */ logsGestureExclusionRestrictions(WindowState win)5473 static boolean logsGestureExclusionRestrictions(WindowState win) { 5474 if (win.mWmService.mConstants.mSystemGestureExclusionLogDebounceTimeoutMillis <= 0) { 5475 return false; 5476 } 5477 final WindowManager.LayoutParams attrs = win.getAttrs(); 5478 final int type = attrs.type; 5479 return type != TYPE_WALLPAPER 5480 && type != TYPE_APPLICATION_STARTING 5481 && type != TYPE_NAVIGATION_BAR 5482 && (attrs.flags & FLAG_NOT_TOUCHABLE) == 0 5483 && needsGestureExclusionRestrictions(win, true /* ignoreRequest */) 5484 && win.getDisplayContent().mDisplayPolicy.hasSideGestures(); 5485 } 5486 5487 /** 5488 * Adds a local gesture exclusion area to the global area while applying a limit per edge. 5489 * 5490 * @param local The gesture exclusion area to add. 5491 * @param global The destination. 5492 * @param edge Only processes the part in that region. 5493 * @param limit How much limit in pixels we have. 5494 * @param win The WindowState that is being processed 5495 * @param side The side that is being processed, either {@link WindowState#EXCLUSION_LEFT} or 5496 * {@link WindowState#EXCLUSION_RIGHT} 5497 * @return How much of the limit is remaining. 5498 */ addToGlobalAndConsumeLimit(Region local, Region global, Rect edge, int limit, WindowState win, int side)5499 private static int addToGlobalAndConsumeLimit(Region local, Region global, Rect edge, 5500 int limit, WindowState win, int side) { 5501 final Region r = Region.obtain(local); 5502 r.op(edge, Op.INTERSECT); 5503 5504 final int[] remaining = {limit}; 5505 final int[] requestedExclusion = {0}; 5506 forEachRectReverse(r, rect -> { 5507 if (remaining[0] <= 0) { 5508 return; 5509 } 5510 final int height = rect.height(); 5511 requestedExclusion[0] += height; 5512 if (height > remaining[0]) { 5513 rect.top = rect.bottom - remaining[0]; 5514 } 5515 remaining[0] -= height; 5516 global.op(rect, Op.UNION); 5517 }); 5518 5519 final int grantedExclusion = limit - remaining[0]; 5520 win.setLastExclusionHeights(side, requestedExclusion[0], grantedExclusion); 5521 5522 r.recycle(); 5523 return remaining[0]; 5524 } 5525 registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener)5526 void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) { 5527 mSystemGestureExclusionListeners.register(listener); 5528 final boolean changed; 5529 if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() == 1) { 5530 changed = updateSystemGestureExclusion(); 5531 } else { 5532 changed = false; 5533 } 5534 5535 if (!changed) { 5536 final Region unrestrictedOrNull = mSystemGestureExclusionWasRestricted 5537 ? mSystemGestureExclusionUnrestricted : null; 5538 // If updateSystemGestureExclusion changed the exclusion, it will already have 5539 // notified the listener. Otherwise, we'll do it here. 5540 try { 5541 listener.onSystemGestureExclusionChanged(mDisplayId, mSystemGestureExclusion, 5542 unrestrictedOrNull); 5543 } catch (RemoteException e) { 5544 Slog.e(TAG, "Failed to notify SystemGestureExclusionListener during register", e); 5545 } 5546 } 5547 } 5548 unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener)5549 void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener) { 5550 mSystemGestureExclusionListeners.unregister(listener); 5551 } 5552 5553 /** 5554 * Create a portal window handle for input. This window transports any touch to the display 5555 * indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window. 5556 * 5557 * @param name The name of the portal window handle. 5558 * @return the new portal window handle. 5559 */ createPortalWindowHandle(String name)5560 private InputWindowHandle createPortalWindowHandle(String name) { 5561 // Let surface flinger to set the display ID of this input window handle because we don't 5562 // know which display the parent surface control is on. 5563 final InputWindowHandle portalWindowHandle = new InputWindowHandle( 5564 null /* inputApplicationHandle */, INVALID_DISPLAY); 5565 portalWindowHandle.name = name; 5566 portalWindowHandle.token = new Binder(); 5567 portalWindowHandle.layoutParamsFlags = 5568 FLAG_SPLIT_TOUCH | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL; 5569 getBounds(mTmpBounds); 5570 portalWindowHandle.touchableRegion.set(mTmpBounds); 5571 portalWindowHandle.scaleFactor = 1f; 5572 portalWindowHandle.ownerPid = Process.myPid(); 5573 portalWindowHandle.ownerUid = Process.myUid(); 5574 portalWindowHandle.portalToDisplayId = mDisplayId; 5575 return portalWindowHandle; 5576 } 5577 5578 /** 5579 * @see IWindowManager#setForwardedInsets 5580 */ setForwardedInsets(Insets insets)5581 public void setForwardedInsets(Insets insets) { 5582 if (insets == null) { 5583 insets = Insets.NONE; 5584 } 5585 if (mDisplayPolicy.getForwardedInsets().equals(insets)) { 5586 return; 5587 } 5588 mDisplayPolicy.setForwardedInsets(insets); 5589 setLayoutNeeded(); 5590 mWmService.mWindowPlacerLocked.requestTraversal(); 5591 } 5592 getMetricsLogger()5593 protected MetricsLogger getMetricsLogger() { 5594 if (mMetricsLogger == null) { 5595 mMetricsLogger = new MetricsLogger(); 5596 } 5597 return mMetricsLogger; 5598 } 5599 onDisplayChanged()5600 void onDisplayChanged() { 5601 mDisplay.getRealSize(mTmpDisplaySize); 5602 setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y); 5603 final int lastDisplayState = mDisplayInfo.state; 5604 updateDisplayInfo(); 5605 5606 // The window policy is responsible for stopping activities on the default display. 5607 final int displayId = mDisplay.getDisplayId(); 5608 final int displayState = mDisplayInfo.state; 5609 if (displayId != DEFAULT_DISPLAY) { 5610 if (displayState == Display.STATE_OFF) { 5611 mOffTokenAcquirer.acquire(mDisplayId); 5612 } else if (displayState == Display.STATE_ON) { 5613 mOffTokenAcquirer.release(mDisplayId); 5614 } 5615 ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, 5616 "Display %d state is now (%d), so update layer mirroring?", 5617 mDisplayId, displayState); 5618 if (lastDisplayState != displayState) { 5619 // If state is on due to surface being added, then start layer mirroring. 5620 // If state is off due to surface being removed, then stop layer mirroring. 5621 updateMirroring(); 5622 } 5623 } 5624 // Dispatch pending Configuration to WindowContext if the associated display changes to 5625 // un-suspended state from suspended. 5626 if (isSuspendedState(lastDisplayState) 5627 && !isSuspendedState(displayState) && displayState != STATE_UNKNOWN) { 5628 mWmService.mWindowContextListenerController 5629 .dispatchPendingConfigurationIfNeeded(mDisplayId); 5630 } 5631 mWmService.requestTraversal(); 5632 } 5633 alwaysCreateRootTask(int windowingMode, int activityType)5634 static boolean alwaysCreateRootTask(int windowingMode, int activityType) { 5635 // Always create a root task for fullscreen, freeform, and split-screen-secondary windowing 5636 // modes so that we can manage visual ordering and return types correctly. 5637 return activityType == ACTIVITY_TYPE_STANDARD 5638 && (windowingMode == WINDOWING_MODE_FULLSCREEN 5639 || windowingMode == WINDOWING_MODE_FREEFORM 5640 || windowingMode == WINDOWING_MODE_PINNED 5641 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY 5642 || windowingMode == WINDOWING_MODE_MULTI_WINDOW); 5643 } 5644 5645 @Nullable getFocusedRootTask()5646 Task getFocusedRootTask() { 5647 return getItemFromTaskDisplayAreas(TaskDisplayArea::getFocusedRootTask); 5648 } 5649 5650 /** 5651 * Removes root tasks in the input windowing modes from the system if they are of activity type 5652 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED 5653 */ removeRootTasksInWindowingModes(int... windowingModes)5654 void removeRootTasksInWindowingModes(int... windowingModes) { 5655 if (windowingModes == null || windowingModes.length == 0) { 5656 return; 5657 } 5658 5659 // Collect the root tasks that are necessary to be removed instead of performing the removal 5660 // by looping the children, so that we don't miss any root tasks after the children size 5661 // changed or reordered. 5662 final ArrayList<Task> rootTasks = new ArrayList<>(); 5663 forAllRootTasks(rootTask -> { 5664 for (int windowingMode : windowingModes) { 5665 if (rootTask.mCreatedByOrganizer 5666 || rootTask.getWindowingMode() != windowingMode 5667 || !rootTask.isActivityTypeStandardOrUndefined()) { 5668 continue; 5669 } 5670 rootTasks.add(rootTask); 5671 } 5672 }); 5673 for (int i = rootTasks.size() - 1; i >= 0; --i) { 5674 mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i)); 5675 } 5676 } 5677 removeRootTasksWithActivityTypes(int... activityTypes)5678 void removeRootTasksWithActivityTypes(int... activityTypes) { 5679 if (activityTypes == null || activityTypes.length == 0) { 5680 return; 5681 } 5682 5683 // Collect the root tasks that are necessary to be removed instead of performing the removal 5684 // by looping the children, so that we don't miss any root tasks after the children size 5685 // changed or reordered. 5686 final ArrayList<Task> rootTasks = new ArrayList<>(); 5687 forAllRootTasks(rootTask -> { 5688 for (int activityType : activityTypes) { 5689 // Collect the root tasks that are currently being organized. 5690 if (rootTask.mCreatedByOrganizer) { 5691 for (int k = rootTask.getChildCount() - 1; k >= 0; --k) { 5692 final Task task = (Task) rootTask.getChildAt(k); 5693 if (task.getActivityType() == activityType) { 5694 rootTasks.add(task); 5695 } 5696 } 5697 } else if (rootTask.getActivityType() == activityType) { 5698 rootTasks.add(rootTask); 5699 } 5700 } 5701 }); 5702 for (int i = rootTasks.size() - 1; i >= 0; --i) { 5703 mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i)); 5704 } 5705 } 5706 topRunningActivity()5707 ActivityRecord topRunningActivity() { 5708 return topRunningActivity(false /* considerKeyguardState */); 5709 } 5710 5711 /** 5712 * Returns the top running activity in the focused root task. In the case the focused root 5713 * task has no such activity, the next focusable root task on this display is returned. 5714 * 5715 * @param considerKeyguardState Indicates whether the locked state should be considered. if 5716 * {@code true} and the keyguard is locked, only activities that 5717 * can be shown on top of the keyguard will be considered. 5718 * @return The top running activity. {@code null} if none is available. 5719 */ 5720 @Nullable topRunningActivity(boolean considerKeyguardState)5721 ActivityRecord topRunningActivity(boolean considerKeyguardState) { 5722 return getItemFromTaskDisplayAreas(taskDisplayArea -> 5723 taskDisplayArea.topRunningActivity(considerKeyguardState)); 5724 } 5725 updateDisplayOverrideConfigurationLocked()5726 boolean updateDisplayOverrideConfigurationLocked() { 5727 // Preemptively cancel the running recents animation -- SysUI can't currently handle this 5728 // case properly since the signals it receives all happen post-change 5729 final RecentsAnimationController recentsAnimationController = 5730 mWmService.getRecentsAnimationController(); 5731 if (recentsAnimationController != null) { 5732 recentsAnimationController.cancelAnimationForDisplayChange(); 5733 } 5734 5735 Configuration values = new Configuration(); 5736 computeScreenConfiguration(values); 5737 5738 mAtmService.mH.sendMessage(PooledLambda.obtainMessage( 5739 ActivityManagerInternal::updateOomLevelsForDisplay, mAtmService.mAmInternal, 5740 mDisplayId)); 5741 5742 Settings.System.clearConfiguration(values); 5743 updateDisplayOverrideConfigurationLocked(values, null /* starting */, 5744 false /* deferResume */, mAtmService.mTmpUpdateConfigurationResult); 5745 return mAtmService.mTmpUpdateConfigurationResult.changes != 0; 5746 } 5747 5748 /** 5749 * Updates override configuration specific for the selected display. If no config is provided, 5750 * new one will be computed in WM based on current display info. 5751 */ updateDisplayOverrideConfigurationLocked(Configuration values, ActivityRecord starting, boolean deferResume, ActivityTaskManagerService.UpdateConfigurationResult result)5752 boolean updateDisplayOverrideConfigurationLocked(Configuration values, 5753 ActivityRecord starting, boolean deferResume, 5754 ActivityTaskManagerService.UpdateConfigurationResult result) { 5755 5756 int changes = 0; 5757 boolean kept = true; 5758 5759 mAtmService.deferWindowLayout(); 5760 try { 5761 if (values != null) { 5762 if (mDisplayId == DEFAULT_DISPLAY) { 5763 // Override configuration of the default display duplicates global config, so 5764 // we're calling global config update instead for default display. It will also 5765 // apply the correct override config. 5766 changes = mAtmService.updateGlobalConfigurationLocked(values, 5767 false /* initLocale */, false /* persistent */, 5768 UserHandle.USER_NULL /* userId */); 5769 } else { 5770 changes = performDisplayOverrideConfigUpdate(values); 5771 } 5772 } 5773 5774 if (!deferResume) { 5775 kept = mAtmService.ensureConfigAndVisibilityAfterUpdate(starting, changes); 5776 } 5777 } finally { 5778 mAtmService.continueWindowLayout(); 5779 } 5780 5781 if (result != null) { 5782 result.changes = changes; 5783 result.activityRelaunched = !kept; 5784 } 5785 return kept; 5786 } 5787 performDisplayOverrideConfigUpdate(Configuration values)5788 int performDisplayOverrideConfigUpdate(Configuration values) { 5789 mTempConfig.setTo(getRequestedOverrideConfiguration()); 5790 final int changes = mTempConfig.updateFrom(values); 5791 if (changes != 0) { 5792 Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " " 5793 + mTempConfig + " for displayId=" + mDisplayId); 5794 onRequestedOverrideConfigurationChanged(mTempConfig); 5795 5796 final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0; 5797 if (isDensityChange && mDisplayId == DEFAULT_DISPLAY) { 5798 mAtmService.mAppWarnings.onDensityChanged(); 5799 5800 // Post message to start process to avoid possible deadlock of calling into AMS with 5801 // the ATMS lock held. 5802 final Message msg = PooledLambda.obtainMessage( 5803 ActivityManagerInternal::killAllBackgroundProcessesExcept, 5804 mAtmService.mAmInternal, N, 5805 ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND); 5806 mAtmService.mH.sendMessage(msg); 5807 } 5808 mWmService.mDisplayNotificationController.dispatchDisplayChanged( 5809 this, getConfiguration()); 5810 if (isReady() && mTransitionController.isShellTransitionsEnabled()) { 5811 requestChangeTransitionIfNeeded(changes); 5812 } 5813 } 5814 return changes; 5815 } 5816 5817 @Override onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration)5818 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) { 5819 final Configuration currOverrideConfig = getRequestedOverrideConfiguration(); 5820 final int currRotation = currOverrideConfig.windowConfiguration.getRotation(); 5821 final int overrideRotation = overrideConfiguration.windowConfiguration.getRotation(); 5822 if (currRotation != ROTATION_UNDEFINED && overrideRotation != ROTATION_UNDEFINED 5823 && currRotation != overrideRotation) { 5824 applyRotationAndFinishFixedRotation(currRotation, overrideRotation); 5825 } 5826 mCurrentOverrideConfigurationChanges = currOverrideConfig.diff(overrideConfiguration); 5827 super.onRequestedOverrideConfigurationChanged(overrideConfiguration); 5828 mCurrentOverrideConfigurationChanges = 0; 5829 mWmService.setNewDisplayOverrideConfiguration(currOverrideConfig, this); 5830 mAtmService.addWindowLayoutReasons( 5831 ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED); 5832 } 5833 5834 @Override onResize()5835 void onResize() { 5836 super.onResize(); 5837 if (mWmService.mAccessibilityController.hasCallbacks()) { 5838 mWmService.mAccessibilityController.onDisplaySizeChanged(this); 5839 } 5840 } 5841 5842 /** 5843 * If the launching rotated activity ({@link #mFixedRotationLaunchingApp}) is null, it simply 5844 * applies the rotation to display. Otherwise because the activity has shown as rotated, the 5845 * fixed rotation transform also needs to be cleared to make sure the rotated activity fits 5846 * the display naturally. 5847 */ applyRotationAndFinishFixedRotation(int oldRotation, int newRotation)5848 private void applyRotationAndFinishFixedRotation(int oldRotation, int newRotation) { 5849 final WindowToken rotatedLaunchingApp = mFixedRotationLaunchingApp; 5850 if (rotatedLaunchingApp == null) { 5851 applyRotation(oldRotation, newRotation); 5852 return; 5853 } 5854 5855 rotatedLaunchingApp.finishFixedRotationTransform( 5856 () -> applyRotation(oldRotation, newRotation)); 5857 setFixedRotationLaunchingAppUnchecked(null); 5858 } 5859 5860 /** Checks whether the given activity is in size compatibility mode and notifies the change. */ handleActivitySizeCompatModeIfNeeded(ActivityRecord r)5861 void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) { 5862 final Task organizedTask = r.getOrganizedTask(); 5863 if (organizedTask == null) { 5864 mActiveSizeCompatActivities.remove(r); 5865 return; 5866 } 5867 5868 if (r.isState(RESUMED) && r.inSizeCompatMode()) { 5869 if (mActiveSizeCompatActivities.add(r)) { 5870 // Trigger task event for new size compat activity. 5871 organizedTask.onSizeCompatActivityChanged(); 5872 } 5873 return; 5874 } 5875 5876 if (mActiveSizeCompatActivities.remove(r)) { 5877 // Trigger task event for activity no longer in foreground size compat. 5878 organizedTask.onSizeCompatActivityChanged(); 5879 } 5880 } 5881 isUidPresent(int uid)5882 boolean isUidPresent(int uid) { 5883 final PooledPredicate p = PooledLambda.obtainPredicate( 5884 ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid); 5885 final boolean isUidPresent = mDisplayContent.getActivity(p) != null; 5886 p.recycle(); 5887 return isUidPresent; 5888 } 5889 5890 /** 5891 * @see #mRemoved 5892 */ isRemoved()5893 boolean isRemoved() { 5894 return mRemoved; 5895 } 5896 5897 /** 5898 * @see #mRemoving 5899 */ isRemoving()5900 boolean isRemoving() { 5901 return mRemoving; 5902 } 5903 remove()5904 void remove() { 5905 mRemoving = true; 5906 Task lastReparentedRootTask; 5907 5908 mRootWindowContainer.mTaskSupervisor.beginDeferResume(); 5909 try { 5910 lastReparentedRootTask = reduceOnAllTaskDisplayAreas((taskDisplayArea, rootTask) -> { 5911 final Task lastReparentedRootTaskFromArea = taskDisplayArea.remove(); 5912 if (lastReparentedRootTaskFromArea != null) { 5913 return lastReparentedRootTaskFromArea; 5914 } 5915 return rootTask; 5916 }, null /* initValue */, false /* traverseTopToBottom */); 5917 } finally { 5918 mRootWindowContainer.mTaskSupervisor.endDeferResume(); 5919 } 5920 mRemoved = true; 5921 5922 if (mMirroredSurface != null) { 5923 // Do not wait for the mirrored surface to be garbage collected, but clean up 5924 // immediately. 5925 mWmService.mTransactionFactory.get().remove(mMirroredSurface).apply(); 5926 mMirroredSurface = null; 5927 } 5928 5929 // Only update focus/visibility for the last one because there may be many root tasks are 5930 // reparented and the intermediate states are unnecessary. 5931 if (lastReparentedRootTask != null) { 5932 lastReparentedRootTask.resumeNextFocusAfterReparent(); 5933 } 5934 releaseSelfIfNeeded(); 5935 mDisplayPolicy.release(); 5936 5937 if (!mAllSleepTokens.isEmpty()) { 5938 mAllSleepTokens.forEach(token -> 5939 mRootWindowContainer.mSleepTokens.remove(token.mHashKey)); 5940 mAllSleepTokens.clear(); 5941 mAtmService.updateSleepIfNeededLocked(); 5942 } 5943 } 5944 releaseSelfIfNeeded()5945 void releaseSelfIfNeeded() { 5946 if (!mRemoved) { 5947 return; 5948 } 5949 5950 // Check if all task display areas have only the empty home root tasks left. 5951 boolean hasNonEmptyHomeRootTask = forAllRootTasks(rootTask -> 5952 !rootTask.isActivityTypeHome() || rootTask.hasChild()); 5953 if (!hasNonEmptyHomeRootTask && getRootTaskCount() > 0) { 5954 // Release this display if only empty home root task(s) are left. This display will be 5955 // released along with the root task(s) removal. 5956 forAllRootTasks(t -> {t.removeIfPossible("releaseSelfIfNeeded");}); 5957 } else if (getTopRootTask() == null) { 5958 removeIfPossible(); 5959 mRootWindowContainer.mTaskSupervisor 5960 .getKeyguardController().onDisplayRemoved(mDisplayId); 5961 } 5962 } 5963 5964 /** Update and get all UIDs that are present on the display and have access to it. */ getPresentUIDs()5965 IntArray getPresentUIDs() { 5966 mDisplayAccessUIDs.clear(); 5967 final PooledConsumer c = PooledLambda.obtainConsumer(DisplayContent::addActivityUid, 5968 PooledLambda.__(ActivityRecord.class), mDisplayAccessUIDs); 5969 mDisplayContent.forAllActivities(c); 5970 c.recycle(); 5971 return mDisplayAccessUIDs; 5972 } 5973 addActivityUid(ActivityRecord r, IntArray uids)5974 private static void addActivityUid(ActivityRecord r, IntArray uids) { 5975 uids.add(r.getUid()); 5976 } 5977 5978 @VisibleForTesting shouldDestroyContentOnRemove()5979 boolean shouldDestroyContentOnRemove() { 5980 return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT; 5981 } 5982 shouldSleep()5983 boolean shouldSleep() { 5984 return (getRootTaskCount() == 0 || !mAllSleepTokens.isEmpty()) 5985 && (mAtmService.mRunningVoice == null); 5986 } 5987 5988 ensureActivitiesVisible(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients)5989 void ensureActivitiesVisible(ActivityRecord starting, int configChanges, 5990 boolean preserveWindows, boolean notifyClients) { 5991 if (mInEnsureActivitiesVisible) { 5992 // Don't do recursive work. 5993 return; 5994 } 5995 mInEnsureActivitiesVisible = true; 5996 mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate(); 5997 try { 5998 forAllRootTasks(rootTask -> { 5999 rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows, 6000 notifyClients); 6001 }); 6002 } finally { 6003 mAtmService.mTaskSupervisor.endActivityVisibilityUpdate(); 6004 mInEnsureActivitiesVisible = false; 6005 } 6006 } 6007 isSleeping()6008 boolean isSleeping() { 6009 return mSleeping; 6010 } 6011 setIsSleeping(boolean asleep)6012 void setIsSleeping(boolean asleep) { 6013 mSleeping = asleep; 6014 } 6015 6016 /** 6017 * Check if the display has {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied. 6018 */ canShowWithInsecureKeyguard()6019 boolean canShowWithInsecureKeyguard() { 6020 final int flags = mDisplay.getFlags(); 6021 return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0; 6022 } 6023 6024 @VisibleForTesting removeAllTasks()6025 void removeAllTasks() { 6026 forAllTasks((t) -> { t.getRootTask().removeChild(t, "removeAllTasks"); }); 6027 } 6028 getDisplayUiContext()6029 Context getDisplayUiContext() { 6030 return mDisplayPolicy.getSystemUiContext(); 6031 } 6032 6033 @Override setIgnoreOrientationRequest(boolean ignoreOrientationRequest)6034 boolean setIgnoreOrientationRequest(boolean ignoreOrientationRequest) { 6035 if (mIgnoreOrientationRequest == ignoreOrientationRequest) return false; 6036 final boolean rotationChanged = super.setIgnoreOrientationRequest(ignoreOrientationRequest); 6037 mWmService.mDisplayWindowSettings.setIgnoreOrientationRequest( 6038 this, mIgnoreOrientationRequest); 6039 return rotationChanged; 6040 } 6041 6042 /** 6043 * Locates the appropriate target window for scroll capture. The search progresses top to 6044 * bottom. 6045 * If {@code searchBehind} is non-null, the search will only consider windows behind this one. 6046 * If a valid taskId is specified, the target window must belong to the given task. 6047 * 6048 * @param searchBehind a window used to filter the search to windows behind it, or null to begin 6049 * the search at the top window of the display 6050 * @param taskId specifies the id of a task the result must belong to or 6051 * {@link android.app.ActivityTaskManager#INVALID_TASK_ID INVALID_TASK_ID} 6052 * to match any window 6053 * @return the located window or null if none could be found matching criteria 6054 */ 6055 @Nullable findScrollCaptureTargetWindow(@ullable WindowState searchBehind, int taskId)6056 WindowState findScrollCaptureTargetWindow(@Nullable WindowState searchBehind, int taskId) { 6057 return getWindow(new Predicate<WindowState>() { 6058 boolean behindTopWindow = (searchBehind == null); // optional filter 6059 @Override 6060 public boolean test(WindowState nextWindow) { 6061 // Skip through all windows until we pass topWindow (if specified) 6062 if (!behindTopWindow) { 6063 if (nextWindow == searchBehind) { 6064 behindTopWindow = true; 6065 } 6066 return false; /* continue */ 6067 } 6068 if (taskId == INVALID_TASK_ID) { 6069 if (!nextWindow.canReceiveKeys()) { 6070 return false; /* continue */ 6071 } 6072 } else { 6073 Task task = nextWindow.getTask(); 6074 if (task == null || !task.isTaskId(taskId)) { 6075 return false; /* continue */ 6076 } 6077 } 6078 if (nextWindow.isSecureLocked()) { 6079 return false; /* continue */ 6080 } 6081 return true; /* stop, match found */ 6082 } 6083 }); 6084 } 6085 6086 @Override providesMaxBounds()6087 public boolean providesMaxBounds() { 6088 return true; 6089 } 6090 6091 /** 6092 * Sets if Display APIs should be sandboxed to the activity window bounds. 6093 */ setSandboxDisplayApis(boolean sandboxDisplayApis)6094 void setSandboxDisplayApis(boolean sandboxDisplayApis) { 6095 mSandboxDisplayApis = sandboxDisplayApis; 6096 } 6097 6098 /** 6099 * Returns {@code true} is Display APIs should be sandboxed to the activity window bounds, 6100 * {@code false} otherwise. Default to true, unless set for debugging purposes. 6101 */ sandboxDisplayApis()6102 boolean sandboxDisplayApis() { 6103 return mSandboxDisplayApis; 6104 } 6105 6106 /** 6107 * Start mirroring to this DisplayContent if it does not have its own content. Captures the 6108 * content of a WindowContainer indicated by a WindowToken. If unable to start mirroring, falls 6109 * back to original MediaProjection approach. 6110 */ startMirrorIfNeeded()6111 private void startMirrorIfNeeded() { 6112 // Only mirror if this display does not have its own content, is not mirroring already, 6113 // and if this display is on (it has a surface to write output to). 6114 if (mLastHasContent || isCurrentlyMirroring() || mDisplay.getState() == Display.STATE_OFF) { 6115 return; 6116 } 6117 6118 // Given the WindowToken of the DisplayArea to mirror, retrieve the associated 6119 // SurfaceControl. 6120 IBinder tokenToMirror = mWmService.mDisplayManagerInternal.getWindowTokenClientToMirror( 6121 mDisplayId); 6122 if (tokenToMirror == null) { 6123 // This DisplayContent instance is not involved in layer mirroring. If the display 6124 // has been created for capturing, fall back to prior MediaProjection approach. 6125 return; 6126 } 6127 6128 final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer( 6129 tokenToMirror); 6130 if (wc == null) { 6131 // Un-set the window token to mirror for this VirtualDisplay, to fall back to the 6132 // original MediaProjection approach. 6133 mWmService.mDisplayManagerInternal.setWindowTokenClientToMirror(mDisplayId, null); 6134 ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, 6135 "Unable to retrieve window container to start layer mirroring for display %d", 6136 mDisplayId); 6137 return; 6138 } 6139 6140 Point surfaceSize = fetchSurfaceSizeIfPresent(); 6141 if (surfaceSize == null) { 6142 ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, 6143 "Unable to start layer mirroring for display %d since the surface is not " 6144 + "available.", 6145 mDisplayId); 6146 return; 6147 } 6148 ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, 6149 "Display %d has no content and is on, so start layer mirroring for state %d", 6150 mDisplayId, mDisplay.getState()); 6151 6152 // Create a mirrored hierarchy for the SurfaceControl of the DisplayArea to capture. 6153 SurfaceControl sc = wc.getDisplayContent().getSurfaceControl(); 6154 mMirroredSurface = SurfaceControl.mirrorSurface(sc); 6155 SurfaceControl.Transaction transaction = mWmService.mTransactionFactory.get() 6156 // Set the mMirroredSurface's parent to the root SurfaceControl for this 6157 // DisplayContent. This brings the new mirrored hierarchy under this DisplayContent, 6158 // so SurfaceControl will write the layers of this hierarchy to the output surface 6159 // provided by the app. 6160 .reparent(mMirroredSurface, mSurfaceControl) 6161 // Reparent the SurfaceControl of this DisplayContent to null, to prevent content 6162 // being added to it. This ensures that no app launched explicitly on the 6163 // VirtualDisplay will show up as part of the mirrored content. 6164 .reparent(mWindowingLayer, null) 6165 .reparent(mOverlayLayer, null); 6166 // Retrieve the size of the DisplayArea to mirror. 6167 updateMirroredSurface(transaction, wc.getDisplayContent().getBounds(), surfaceSize); 6168 mTokenToMirror = tokenToMirror; 6169 6170 // No need to clean up. In SurfaceFlinger, parents hold references to their children. The 6171 // mirrored SurfaceControl is alive since the parent DisplayContent SurfaceControl is 6172 // holding a reference to it. Therefore, the mirrored SurfaceControl will be cleaned up 6173 // when the VirtualDisplay is destroyed - which will clean up this DisplayContent. 6174 } 6175 6176 /** 6177 * Start mirroring if this DisplayContent no longer has content. Stop mirroring if it now 6178 * has content or the display is not on. 6179 */ updateMirroring()6180 private void updateMirroring() { 6181 if (isCurrentlyMirroring() && (mLastHasContent 6182 || mDisplay.getState() == Display.STATE_OFF)) { 6183 ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, 6184 "Display %d has content (%b) so disable layer mirroring", mDisplayId, 6185 mLastHasContent); 6186 // If the display is not on and it is a virtual display, then it no longer has an 6187 // associated surface to write output to. 6188 // If the display now has content, stop mirroring to it. 6189 mWmService.mTransactionFactory.get() 6190 // Remove the reference to mMirroredSurface, to clean up associated memory. 6191 .remove(mMirroredSurface) 6192 // Reparent the SurfaceControl of this DisplayContent back to mSurfaceControl, 6193 // to allow content to be added to it. This allows this DisplayContent to stop 6194 // mirroring and show content normally. 6195 .reparent(mWindowingLayer, mSurfaceControl) 6196 .reparent(mOverlayLayer, mSurfaceControl) 6197 .apply(); 6198 // Stop mirroring by destroying the reference to the mirrored layer. 6199 mMirroredSurface = null; 6200 // Do not un-set the token, in case content is removed and mirroring should begin again. 6201 } else { 6202 // Display no longer has content, or now has a surface to write to, so try to start 6203 // mirroring to it. 6204 startMirrorIfNeeded(); 6205 } 6206 } 6207 6208 /** 6209 * Apply transformations to the mirrored surface to ensure the captured contents are scaled to 6210 * fit and centred in the output surface. 6211 * 6212 * @param transaction the transaction to include transformations of mMirroredSurface 6213 * to. Transaction is not applied before returning. 6214 * @param displayAreaBounds bounds of the DisplayArea to mirror to the surface provided by 6215 * the app. 6216 * @param surfaceSize the default size of the surface to write the display area content to 6217 */ 6218 @VisibleForTesting updateMirroredSurface(SurfaceControl.Transaction transaction, Rect displayAreaBounds, Point surfaceSize)6219 void updateMirroredSurface(SurfaceControl.Transaction transaction, 6220 Rect displayAreaBounds, Point surfaceSize) { 6221 // Calculate the scale to apply to the root mirror SurfaceControl to fit the size of the 6222 // output surface. 6223 float scaleX = surfaceSize.x / (float) displayAreaBounds.width(); 6224 float scaleY = surfaceSize.y / (float) displayAreaBounds.height(); 6225 float scale = Math.min(scaleX, scaleY); 6226 int scaledWidth = Math.round(scale * (float) displayAreaBounds.width()); 6227 int scaledHeight = Math.round(scale * (float) displayAreaBounds.height()); 6228 6229 // Calculate the shift to apply to the root mirror SurfaceControl to centre the mirrored 6230 // contents in the output surface. 6231 int shiftedX = 0; 6232 if (scaledWidth != surfaceSize.x) { 6233 shiftedX = (surfaceSize.x - scaledWidth) / 2; 6234 } 6235 int shiftedY = 0; 6236 if (scaledHeight != surfaceSize.y) { 6237 shiftedY = (surfaceSize.y - scaledHeight) / 2; 6238 } 6239 6240 transaction 6241 // Crop the area to capture to exclude the 'extra' wallpaper that is used 6242 // for parallax (b/189930234). 6243 .setWindowCrop(mMirroredSurface, displayAreaBounds.width(), 6244 displayAreaBounds.height()) 6245 // Scale the root mirror SurfaceControl, based upon the size difference between the 6246 // source (DisplayArea to capture) and output (surface the app reads images from). 6247 .setMatrix(mMirroredSurface, scale, 0 /* dtdx */, 0 /* dtdy */, scale) 6248 // Position needs to be updated when the mirrored DisplayArea has changed, since 6249 // the content will no longer be centered in the output surface. 6250 .setPosition(mMirroredSurface, shiftedX /* x */, shiftedY /* y */) 6251 .apply(); 6252 mLastMirroredDisplayAreaBounds = new Rect(displayAreaBounds); 6253 } 6254 6255 /** 6256 * Returns a non-null {@link Point} if the surface is present, or null otherwise 6257 */ fetchSurfaceSizeIfPresent()6258 Point fetchSurfaceSizeIfPresent() { 6259 // Retrieve the default size of the surface the app provided to 6260 // MediaProjection#createVirtualDisplay. Note the app is the consumer of the surface, 6261 // since it reads out buffers from the surface, and SurfaceFlinger is the producer since 6262 // it writes the mirrored layers to the buffers. 6263 Point surfaceSize = mWmService.mDisplayManagerInternal.getDisplaySurfaceDefaultSize( 6264 mDisplayId); 6265 if (surfaceSize == null) { 6266 // Layer mirroring started with a null surface, so do not apply any transformations yet. 6267 // State of virtual display will change to 'ON' when the surface is set. 6268 // will get event DISPLAY_DEVICE_EVENT_CHANGED 6269 ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, 6270 "Provided surface for layer mirroring on display %d is not present, so do not" 6271 + " update the surface", 6272 mDisplayId); 6273 return null; 6274 } 6275 return surfaceSize; 6276 } 6277 6278 /** 6279 * Returns {@code true} if this DisplayContent is currently layer mirroring. 6280 */ isCurrentlyMirroring()6281 boolean isCurrentlyMirroring() { 6282 return mTokenToMirror != null && mMirroredSurface != null; 6283 } 6284 6285 /** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */ 6286 class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener { 6287 6288 /** 6289 * The animating activity which shows the recents task list. It is set between 6290 * {@link RecentsAnimationController#initialize} and 6291 * {@link RecentsAnimationController#cleanupAnimation}. 6292 */ 6293 private ActivityRecord mAnimatingRecents; 6294 6295 /** Whether {@link #mAnimatingRecents} is going to be the top activity. */ 6296 private boolean mRecentsWillBeTop; 6297 6298 /** 6299 * If the recents activity has a fixed orientation which is different from the current top 6300 * activity, it will be rotated before being shown so we avoid a screen rotation animation 6301 * when showing the Recents view. 6302 */ onStartRecentsAnimation(@onNull ActivityRecord r)6303 void onStartRecentsAnimation(@NonNull ActivityRecord r) { 6304 mAnimatingRecents = r; 6305 if (r.isVisible() && mFocusedApp != null && !mFocusedApp.occludesParent()) { 6306 // The recents activity has shown with the orientation determined by the top 6307 // activity, keep its current orientation to avoid flicking by the configuration 6308 // change of visible activity. 6309 return; 6310 } 6311 rotateInDifferentOrientationIfNeeded(r); 6312 if (r.hasFixedRotationTransform()) { 6313 // Set the record so we can recognize it to continue to update display orientation 6314 // if the recents activity becomes the top later. 6315 setFixedRotationLaunchingApp(r, r.getWindowConfiguration().getRotation()); 6316 } 6317 } 6318 6319 /** 6320 * If {@link #mAnimatingRecents} still has fixed rotation, it should be moved to top so we 6321 * don't clear {@link #mFixedRotationLaunchingApp} that will be handled by transition. 6322 */ onFinishRecentsAnimation()6323 void onFinishRecentsAnimation() { 6324 final ActivityRecord animatingRecents = mAnimatingRecents; 6325 final boolean recentsWillBeTop = mRecentsWillBeTop; 6326 mAnimatingRecents = null; 6327 mRecentsWillBeTop = false; 6328 if (recentsWillBeTop) { 6329 // The recents activity will be the top, such as staying at recents list or 6330 // returning to home (if home and recents are the same activity). 6331 return; 6332 } 6333 6334 if (animatingRecents != null && animatingRecents == mFixedRotationLaunchingApp 6335 && animatingRecents.isVisible() && animatingRecents != topRunningActivity()) { 6336 // The recents activity should be going to be invisible (switch to another app or 6337 // return to original top). Only clear the top launching record without finishing 6338 // the transform immediately because it won't affect display orientation. And before 6339 // the visibility is committed, the recents activity may perform relayout which may 6340 // cause unexpected configuration change if the rotated configuration is restored. 6341 // The transform will be finished when the transition is done. 6342 setFixedRotationLaunchingAppUnchecked(null); 6343 } else { 6344 // If there is already a launching activity that is not the recents, before its 6345 // transition is completed, the recents animation may be started. So if the recents 6346 // activity won't be the top, the display orientation should be updated according 6347 // to the current top activity. 6348 continueUpdateOrientationForDiffOrienLaunchingApp(); 6349 } 6350 } 6351 notifyRecentsWillBeTop()6352 void notifyRecentsWillBeTop() { 6353 mRecentsWillBeTop = true; 6354 } 6355 6356 /** 6357 * Return {@code true} if there is an ongoing animation to the "Recents" activity and this 6358 * activity as a fixed orientation so shouldn't be rotated. 6359 */ isTopFixedOrientationRecentsAnimating()6360 boolean isTopFixedOrientationRecentsAnimating() { 6361 return mAnimatingRecents != null 6362 && mAnimatingRecents.getRequestedConfigurationOrientation(true /* forDisplay */) 6363 != ORIENTATION_UNDEFINED && !hasTopFixedRotationLaunchingApp(); 6364 } 6365 6366 @Override onAppTransitionFinishedLocked(IBinder token)6367 public void onAppTransitionFinishedLocked(IBinder token) { 6368 final ActivityRecord r = getActivityRecord(token); 6369 // Ignore the animating recents so the fixed rotation transform won't be switched twice 6370 // by finishing the recents animation and moving it to top. That also avoids flickering 6371 // due to wait for previous activity to be paused if it supports PiP that ignores the 6372 // effect of resume-while-pausing. 6373 if (r == null || r == mAnimatingRecents) { 6374 return; 6375 } 6376 if (mAnimatingRecents != null && mRecentsWillBeTop) { 6377 // The activity is not the recents and it should be moved to back later, so it is 6378 // better to keep its current appearance for the next transition. Otherwise the 6379 // display orientation may be updated too early and the layout procedures at the 6380 // end of finishing recents animation is skipped. That causes flickering because 6381 // the surface of closing app hasn't updated to invisible. 6382 return; 6383 } 6384 if (mFixedRotationLaunchingApp == null) { 6385 // In most cases this is a no-op if the activity doesn't have fixed rotation. 6386 // Otherwise it could be from finishing recents animation while the display has 6387 // different orientation. 6388 r.finishFixedRotationTransform(); 6389 return; 6390 } 6391 if (mFixedRotationLaunchingApp.hasFixedRotationTransform(r)) { 6392 if (mFixedRotationLaunchingApp.hasAnimatingFixedRotationTransition()) { 6393 // Waiting until all of the associated activities have done animation, or the 6394 // orientation would be updated too early and cause flickering. 6395 return; 6396 } 6397 } else { 6398 // Handle a corner case that the task of {@link #mFixedRotationLaunchingApp} is no 6399 // longer animating but the corresponding transition finished event won't notify. 6400 // E.g. activity A transferred starting window to B, only A will receive transition 6401 // finished event. A doesn't have fixed rotation but B is the rotated launching app. 6402 final Task task = r.getTask(); 6403 if (task == null || task != mFixedRotationLaunchingApp.getTask()) { 6404 // Different tasks won't be in one activity transition animation. 6405 return; 6406 } 6407 if (task.isAppTransitioning()) { 6408 return; 6409 // Continue to update orientation because the transition of the top rotated 6410 // launching activity is done. 6411 } 6412 } 6413 continueUpdateOrientationForDiffOrienLaunchingApp(); 6414 } 6415 6416 @Override onAppTransitionCancelledLocked(boolean keyguardGoingAway)6417 public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) { 6418 continueUpdateOrientationForDiffOrienLaunchingApp(); 6419 } 6420 6421 @Override onAppTransitionTimeoutLocked()6422 public void onAppTransitionTimeoutLocked() { 6423 continueUpdateOrientationForDiffOrienLaunchingApp(); 6424 } 6425 } 6426 6427 class RemoteInsetsControlTarget implements InsetsControlTarget { 6428 private final IDisplayWindowInsetsController mRemoteInsetsController; 6429 private final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities(); 6430 RemoteInsetsControlTarget(IDisplayWindowInsetsController controller)6431 RemoteInsetsControlTarget(IDisplayWindowInsetsController controller) { 6432 mRemoteInsetsController = controller; 6433 } 6434 6435 /** 6436 * Notifies the remote insets controller that the top focused window has changed. 6437 * 6438 * @param packageName The name of the package that is open in the top focused window. 6439 */ topFocusedWindowChanged(String packageName)6440 void topFocusedWindowChanged(String packageName) { 6441 try { 6442 mRemoteInsetsController.topFocusedWindowChanged(packageName); 6443 } catch (RemoteException e) { 6444 Slog.w(TAG, "Failed to deliver package in top focused window change", e); 6445 } 6446 } 6447 notifyInsetsChanged()6448 void notifyInsetsChanged() { 6449 try { 6450 mRemoteInsetsController.insetsChanged( 6451 getInsetsStateController().getRawInsetsState()); 6452 } catch (RemoteException e) { 6453 Slog.w(TAG, "Failed to deliver inset state change", e); 6454 } 6455 } 6456 6457 @Override notifyInsetsControlChanged()6458 public void notifyInsetsControlChanged() { 6459 final InsetsStateController stateController = getInsetsStateController(); 6460 try { 6461 mRemoteInsetsController.insetsControlChanged(stateController.getRawInsetsState(), 6462 stateController.getControlsForDispatch(this)); 6463 } catch (RemoteException e) { 6464 Slog.w(TAG, "Failed to deliver inset state change", e); 6465 } 6466 } 6467 6468 @Override showInsets(@indowInsets.Type.InsetsType int types, boolean fromIme)6469 public void showInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) { 6470 try { 6471 mRemoteInsetsController.showInsets(types, fromIme); 6472 } catch (RemoteException e) { 6473 Slog.w(TAG, "Failed to deliver showInsets", e); 6474 } 6475 } 6476 6477 @Override hideInsets(@indowInsets.Type.InsetsType int types, boolean fromIme)6478 public void hideInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) { 6479 try { 6480 mRemoteInsetsController.hideInsets(types, fromIme); 6481 } catch (RemoteException e) { 6482 Slog.w(TAG, "Failed to deliver showInsets", e); 6483 } 6484 } 6485 6486 @Override getRequestedVisibility(@nternalInsetsType int type)6487 public boolean getRequestedVisibility(@InternalInsetsType int type) { 6488 if (type == ITYPE_IME) { 6489 return getInsetsStateController().getImeSourceProvider().isImeShowing(); 6490 } 6491 return mRequestedVisibilities.getVisibility(type); 6492 } 6493 setRequestedVisibilities(InsetsVisibilities requestedVisibilities)6494 void setRequestedVisibilities(InsetsVisibilities requestedVisibilities) { 6495 mRequestedVisibilities.set(requestedVisibilities); 6496 } 6497 } 6498 getMagnificationSpec()6499 MagnificationSpec getMagnificationSpec() { 6500 return mMagnificationSpec; 6501 } 6502 findAreaForWindowType(int windowType, Bundle options, boolean ownerCanManageAppToken, boolean roundedCornerOverlay)6503 DisplayArea findAreaForWindowType(int windowType, Bundle options, 6504 boolean ownerCanManageAppToken, boolean roundedCornerOverlay) { 6505 // TODO(b/159767464): figure out how to find an appropriate TDA. 6506 if (windowType >= FIRST_APPLICATION_WINDOW && windowType <= LAST_APPLICATION_WINDOW) { 6507 return getDefaultTaskDisplayArea(); 6508 } 6509 // Return IME container here because it could be in one of sub RootDisplayAreas depending on 6510 // the focused edit text. Also, the RootDisplayArea choosing strategy is implemented by 6511 // the server side, but not mSelectRootForWindowFunc customized by OEM. 6512 if (windowType == TYPE_INPUT_METHOD || windowType == TYPE_INPUT_METHOD_DIALOG) { 6513 return getImeContainer(); 6514 } 6515 return mDisplayAreaPolicy.findAreaForWindowType(windowType, options, 6516 ownerCanManageAppToken, roundedCornerOverlay); 6517 } 6518 6519 /** 6520 * Finds the {@link DisplayArea} for the {@link WindowToken} to attach to. 6521 * <p> 6522 * Note that the differences between this API and 6523 * {@link RootDisplayArea#findAreaForTokenInLayer(WindowToken)} is that this API finds a 6524 * {@link DisplayArea} in {@link DisplayContent} level, which may find a {@link DisplayArea} 6525 * from multiple {@link RootDisplayArea RootDisplayAreas} under this {@link DisplayContent}'s 6526 * hierarchy, while {@link RootDisplayArea#findAreaForTokenInLayer(WindowToken)} finds a 6527 * {@link DisplayArea.Tokens} from a {@link DisplayArea.Tokens} list mapped to window layers. 6528 * </p> 6529 * 6530 * @see DisplayContent#findAreaForTokenInLayer(WindowToken) 6531 */ findAreaForToken(WindowToken windowToken)6532 DisplayArea findAreaForToken(WindowToken windowToken) { 6533 return findAreaForWindowType(windowToken.getWindowType(), windowToken.mOptions, 6534 windowToken.mOwnerCanManageAppTokens, windowToken.mRoundedCornerOverlay); 6535 } 6536 6537 @Override asDisplayContent()6538 DisplayContent asDisplayContent() { 6539 return this; 6540 } 6541 } 6542