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