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