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