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