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