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