1 /* 2 * Copyright (C) 2007 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.Manifest.permission.ACCESS_SURFACE_FLINGER; 20 import static android.Manifest.permission.INPUT_CONSUMER; 21 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 22 import static android.Manifest.permission.MANAGE_APP_TOKENS; 23 import static android.Manifest.permission.MODIFY_TOUCH_MODE_STATE; 24 import static android.Manifest.permission.READ_FRAME_BUFFER; 25 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS; 26 import static android.Manifest.permission.START_TASKS_FROM_RECENTS; 27 import static android.Manifest.permission.STATUS_BAR_SERVICE; 28 import static android.Manifest.permission.WRITE_SECURE_SETTINGS; 29 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; 30 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; 31 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; 32 import static android.app.StatusBarManager.DISABLE_MASK; 33 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 34 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED; 35 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT; 36 import static android.content.pm.PackageManager.FEATURE_PC; 37 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 38 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 39 import static android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE; 40 import static android.os.Process.SYSTEM_UID; 41 import static android.os.Process.myPid; 42 import static android.os.Process.myUid; 43 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 44 import static android.permission.flags.Flags.sensitiveContentImprovements; 45 import static android.permission.flags.Flags.sensitiveContentMetricsBugfix; 46 import static android.permission.flags.Flags.sensitiveContentRecentsScreenshotBugfix; 47 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT; 48 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW; 49 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS; 50 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES; 51 import static android.provider.Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH; 52 import static android.service.dreams.Flags.dreamHandlesConfirmKeys; 53 import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK; 54 import static android.view.Display.DEFAULT_DISPLAY; 55 import static android.view.Display.INVALID_DISPLAY; 56 import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; 57 import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; 58 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; 59 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 60 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 61 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; 62 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 63 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 64 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 65 import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 66 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 67 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 68 import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY; 69 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 70 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SENSITIVE_FOR_PRIVACY; 71 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY; 72 import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; 73 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 74 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 75 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; 76 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; 77 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 78 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 79 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 80 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 81 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 82 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; 83 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; 84 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; 85 import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 86 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; 87 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 88 import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED; 89 import static android.view.WindowManager.TRANSIT_OPEN; 90 import static android.view.WindowManager.TRANSIT_TO_FRONT; 91 import static android.view.WindowManager.fixScale; 92 import static android.view.WindowManagerGlobal.ADD_OKAY; 93 import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW; 94 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; 95 import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER; 96 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW; 97 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN; 98 import static android.view.flags.Flags.sensitiveContentAppProtection; 99 import static android.window.WindowProviderService.isWindowProviderService; 100 101 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ADD_REMOVE; 102 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ANIM; 103 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_BOOT; 104 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_FOCUS; 105 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_FOCUS_LIGHT; 106 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_IME; 107 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ORIENTATION; 108 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_SCREEN_ON; 109 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_STARTING_WINDOW; 110 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_WINDOW_MOVEMENT; 111 import static com.android.internal.protolog.WmProtoLogGroups.WM_ERROR; 112 import static com.android.internal.protolog.WmProtoLogGroups.WM_SHOW_TRANSACTIONS; 113 import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_NOTIFICATION_APP_PROTECTION_APPLIED; 114 import static com.android.server.LockGuard.INDEX_WINDOW; 115 import static com.android.server.LockGuard.installLock; 116 import static com.android.server.policy.PhoneWindowManager.TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD; 117 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 118 import static com.android.server.wm.ActivityTaskManagerService.DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE; 119 import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND; 120 import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; 121 import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR; 122 import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; 123 import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL; 124 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; 125 import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_RECENT_TASKS; 126 import static com.android.server.wm.SensitiveContentPackages.PackageInfo; 127 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; 128 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; 129 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; 130 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; 131 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; 132 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; 133 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 134 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 135 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 136 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 137 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; 138 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 139 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; 140 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 141 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 142 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS; 143 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 144 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 145 import static com.android.server.wm.WindowManagerInternal.OnWindowRemovedListener; 146 import static com.android.server.wm.WindowManagerInternal.WindowFocusChangeListener; 147 import static com.android.server.wm.WindowManagerServiceDumpProto.BACK_NAVIGATION; 148 import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_APP; 149 import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_DISPLAY_ID; 150 import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_WINDOW; 151 import static com.android.server.wm.WindowManagerServiceDumpProto.HARD_KEYBOARD_AVAILABLE; 152 import static com.android.server.wm.WindowManagerServiceDumpProto.INPUT_METHOD_WINDOW; 153 import static com.android.server.wm.WindowManagerServiceDumpProto.POLICY; 154 import static com.android.server.wm.WindowManagerServiceDumpProto.ROOT_WINDOW_CONTAINER; 155 import static com.android.server.wm.WindowManagerServiceDumpProto.WINDOW_FRAMES_VALID; 156 import static com.android.window.flags.Flags.enableDisplayFocusInShellTransitions; 157 import static com.android.window.flags.Flags.enablePresentationForConnectedDisplays; 158 import static com.android.window.flags.Flags.multiCrop; 159 import static com.android.window.flags.Flags.setScPropertiesInClient; 160 161 import android.Manifest; 162 import android.Manifest.permission; 163 import android.animation.ValueAnimator; 164 import android.annotation.EnforcePermission; 165 import android.annotation.IntDef; 166 import android.annotation.IntRange; 167 import android.annotation.NonNull; 168 import android.annotation.Nullable; 169 import android.annotation.RequiresPermission; 170 import android.annotation.UserIdInt; 171 import android.app.ActivityManager; 172 import android.app.ActivityManagerInternal; 173 import android.app.ActivityThread; 174 import android.app.AppOpsManager; 175 import android.app.IActivityManager; 176 import android.app.IApplicationThread; 177 import android.app.IAssistDataReceiver; 178 import android.app.WindowConfiguration; 179 import android.content.BroadcastReceiver; 180 import android.content.ComponentName; 181 import android.content.ContentResolver; 182 import android.content.Context; 183 import android.content.Intent; 184 import android.content.IntentFilter; 185 import android.content.pm.ApplicationInfo; 186 import android.content.pm.PackageManager; 187 import android.content.pm.PackageManagerInternal; 188 import android.content.pm.TestUtilityService; 189 import android.content.res.Configuration; 190 import android.content.res.TypedArray; 191 import android.database.ContentObserver; 192 import android.graphics.Bitmap; 193 import android.graphics.Matrix; 194 import android.graphics.Point; 195 import android.graphics.Rect; 196 import android.graphics.Region; 197 import android.hardware.configstore.V1_0.OptionalBool; 198 import android.hardware.configstore.V1_1.ISurfaceFlingerConfigs; 199 import android.hardware.devicestate.DeviceState; 200 import android.hardware.devicestate.DeviceStateManager; 201 import android.hardware.display.DisplayManager; 202 import android.hardware.display.DisplayManagerInternal; 203 import android.hardware.input.InputSettings; 204 import android.net.Uri; 205 import android.os.Binder; 206 import android.os.Build; 207 import android.os.Bundle; 208 import android.os.Debug; 209 import android.os.Handler; 210 import android.os.HandlerExecutor; 211 import android.os.IBinder; 212 import android.os.IRemoteCallback; 213 import android.os.InputConfig; 214 import android.os.Looper; 215 import android.os.Message; 216 import android.os.Parcel; 217 import android.os.ParcelFileDescriptor; 218 import android.os.PowerManager; 219 import android.os.PowerManager.ServiceType; 220 import android.os.PowerManagerInternal; 221 import android.os.PowerSaveState; 222 import android.os.RemoteCallback; 223 import android.os.RemoteCallbackList; 224 import android.os.RemoteException; 225 import android.os.ResultReceiver; 226 import android.os.ServiceManager; 227 import android.os.ShellCallback; 228 import android.os.StrictMode; 229 import android.os.SystemClock; 230 import android.os.SystemProperties; 231 import android.os.SystemService; 232 import android.os.Trace; 233 import android.os.UserHandle; 234 import android.provider.DeviceConfigInterface; 235 import android.provider.Settings; 236 import android.service.vr.IVrManager; 237 import android.service.vr.IVrStateCallbacks; 238 import android.sysprop.SurfaceFlingerProperties; 239 import android.text.format.DateUtils; 240 import android.util.ArrayMap; 241 import android.util.ArraySet; 242 import android.util.DisplayMetrics; 243 import android.util.EventLog; 244 import android.util.IntArray; 245 import android.util.MergedConfiguration; 246 import android.util.Pair; 247 import android.util.Slog; 248 import android.util.SparseArray; 249 import android.util.SparseIntArray; 250 import android.util.TypedValue; 251 import android.util.proto.ProtoOutputStream; 252 import android.view.Choreographer; 253 import android.view.ContentRecordingSession; 254 import android.view.Display; 255 import android.view.DisplayInfo; 256 import android.view.Gravity; 257 import android.view.IAppTransitionAnimationSpecsFuture; 258 import android.view.ICrossWindowBlurEnabledListener; 259 import android.view.IDecorViewGestureListener; 260 import android.view.IDisplayChangeWindowController; 261 import android.view.IDisplayFoldListener; 262 import android.view.IDisplayWindowInsetsController; 263 import android.view.IDisplayWindowListener; 264 import android.view.IInputFilter; 265 import android.view.IOnKeyguardExitResult; 266 import android.view.IPinnedTaskListener; 267 import android.view.IRotationWatcher; 268 import android.view.IScrollCaptureResponseListener; 269 import android.view.ISystemGestureExclusionListener; 270 import android.view.IWallpaperVisibilityListener; 271 import android.view.IWindow; 272 import android.view.IWindowId; 273 import android.view.IWindowManager; 274 import android.view.IWindowSession; 275 import android.view.IWindowSessionCallback; 276 import android.view.InputApplicationHandle; 277 import android.view.InputChannel; 278 import android.view.InputDevice; 279 import android.view.InputWindowHandle; 280 import android.view.InsetsFrameProvider; 281 import android.view.InsetsSourceControl; 282 import android.view.InsetsState; 283 import android.view.KeyEvent; 284 import android.view.KeyboardShortcutGroup; 285 import android.view.MagnificationSpec; 286 import android.view.RemoteAnimationAdapter; 287 import android.view.ScrollCaptureResponse; 288 import android.view.Surface; 289 import android.view.SurfaceControl; 290 import android.view.SurfaceControlViewHost; 291 import android.view.View; 292 import android.view.View.FocusDirection; 293 import android.view.ViewDebug; 294 import android.view.WindowContentFrameStats; 295 import android.view.WindowInsets; 296 import android.view.WindowInsets.Type.InsetsType; 297 import android.view.WindowManager; 298 import android.view.WindowManager.DisplayImePolicy; 299 import android.view.WindowManager.LayoutParams; 300 import android.view.WindowManager.RemoveContentMode; 301 import android.view.WindowManagerGlobal; 302 import android.view.WindowManagerPolicyConstants.PointerEventListener; 303 import android.view.WindowRelayoutResult; 304 import android.view.displayhash.DisplayHash; 305 import android.view.displayhash.VerifiedDisplayHash; 306 import android.view.inputmethod.ImeTracker; 307 import android.widget.Toast; 308 import android.window.ActivityWindowInfo; 309 import android.window.AddToSurfaceSyncGroupResult; 310 import android.window.ClientWindowFrames; 311 import android.window.ConfigurationChangeSetting; 312 import android.window.DesktopModeFlags; 313 import android.window.IGlobalDragListener; 314 import android.window.IScreenRecordingCallback; 315 import android.window.ISurfaceSyncGroupCompletedListener; 316 import android.window.ITaskFpsCallback; 317 import android.window.ITrustedPresentationListener; 318 import android.window.InputTransferToken; 319 import android.window.ScreenCapture; 320 import android.window.ScreenCapture.ScreenshotHardwareBuffer; 321 import android.window.SystemPerformanceHinter; 322 import android.window.TaskSnapshot; 323 import android.window.TrustedPresentationThresholds; 324 import android.window.WindowContainerToken; 325 import android.window.WindowContextInfo; 326 327 import com.android.internal.R; 328 import com.android.internal.annotations.GuardedBy; 329 import com.android.internal.annotations.VisibleForTesting; 330 import com.android.internal.annotations.VisibleForTesting.Visibility; 331 import com.android.internal.os.IResultReceiver; 332 import com.android.internal.os.TransferPipe; 333 import com.android.internal.policy.IKeyguardDismissCallback; 334 import com.android.internal.policy.IKeyguardLockedStateListener; 335 import com.android.internal.policy.IShortcutService; 336 import com.android.internal.policy.KeyInterceptionInfo; 337 import com.android.internal.protolog.LegacyProtoLogImpl; 338 import com.android.internal.protolog.ProtoLog; 339 import com.android.internal.protolog.WmProtoLogGroups; 340 import com.android.internal.util.DumpUtils; 341 import com.android.internal.util.FastPrintWriter; 342 import com.android.internal.util.FrameworkStatsLog; 343 import com.android.internal.util.LatencyTracker; 344 import com.android.internal.util.ToBooleanFunction; 345 import com.android.internal.view.WindowManagerPolicyThread; 346 import com.android.server.AnimationThread; 347 import com.android.server.DisplayThread; 348 import com.android.server.FgThread; 349 import com.android.server.LocalServices; 350 import com.android.server.UiThread; 351 import com.android.server.Watchdog; 352 import com.android.server.input.InputManagerService; 353 import com.android.server.inputmethod.InputMethodManagerInternal; 354 import com.android.server.pm.UserManagerInternal; 355 import com.android.server.policy.WindowManagerPolicy; 356 import com.android.server.policy.WindowManagerPolicy.ScreenOffListener; 357 import com.android.server.power.ShutdownThread; 358 import com.android.server.utils.PriorityDump; 359 import com.android.window.flags.Flags; 360 361 import dalvik.annotation.optimization.NeverCompile; 362 363 import java.io.BufferedWriter; 364 import java.io.DataInputStream; 365 import java.io.File; 366 import java.io.FileDescriptor; 367 import java.io.FileInputStream; 368 import java.io.FileNotFoundException; 369 import java.io.IOException; 370 import java.io.OutputStream; 371 import java.io.OutputStreamWriter; 372 import java.io.PrintWriter; 373 import java.io.StringWriter; 374 import java.lang.annotation.Retention; 375 import java.lang.annotation.RetentionPolicy; 376 import java.net.Socket; 377 import java.text.DateFormat; 378 import java.util.ArrayList; 379 import java.util.Arrays; 380 import java.util.Collections; 381 import java.util.Date; 382 import java.util.HashMap; 383 import java.util.List; 384 import java.util.Map; 385 import java.util.NoSuchElementException; 386 import java.util.Objects; 387 import java.util.Optional; 388 import java.util.concurrent.CountDownLatch; 389 import java.util.concurrent.TimeUnit; 390 import java.util.function.Supplier; 391 392 /** {@hide} */ 393 public class WindowManagerService extends IWindowManager.Stub 394 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { 395 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM; 396 private static final int TRACE_MAX_SECTION_NAME_LENGTH = 127; 397 398 static final int LAYOUT_REPEAT_THRESHOLD = 4; 399 400 /** The maximum length we will accept for a loaded animation duration: 401 * this is 10 seconds. 402 */ 403 static final int MAX_ANIMATION_DURATION = 10 * 1000; 404 405 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 406 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 407 408 /** Amount of time to allow a last ANR message to exist before freeing the memory. */ 409 static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours 410 411 // Maximum number of milliseconds to wait for input devices to be enumerated before 412 // proceding with safe mode detection. 413 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 414 415 private static final int SYNC_INPUT_TRANSACTIONS_TIMEOUT_MS = 5000; 416 417 // Poll interval in milliseconds for watching boot animation finished. 418 // TODO(b/159045990) Migrate to SystemService.waitForState with dedicated thread. 419 private static final int BOOT_ANIMATION_POLL_INTERVAL = 50; 420 421 // The name of the boot animation service in init.rc. 422 private static final String BOOT_ANIMATION_SERVICE = "bootanim"; 423 424 static final int UPDATE_FOCUS_NORMAL = 0; 425 /** Caller will assign layers */ 426 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 427 /** Caller is performing surface placement */ 428 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 429 /** Caller will performSurfacePlacement */ 430 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 431 /** Indicates we are removing the focused window when updating the focus. */ 432 static final int UPDATE_FOCUS_REMOVING_FOCUS = 4; 433 434 private static final String SYSTEM_SECURE = "ro.secure"; 435 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 436 437 private static final String DENSITY_OVERRIDE = "ro.config.density_override"; 438 private static final String SIZE_OVERRIDE = "ro.config.size_override"; 439 440 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.boot.emulator.circular"; 441 442 static final int MY_PID = myPid(); 443 static final int MY_UID = myUid(); 444 445 static final int LOGTAG_INPUT_FOCUS = 62001; 446 447 /** 448 * Use WMShell for app transition. 449 */ 450 public static final boolean sEnableShellTransitions = getShellTransitEnabled(); 451 452 /** 453 * Allows a fullscreen windowing mode activity to launch in its desired orientation directly 454 * when the display has different orientation. 455 */ 456 static final boolean ENABLE_FIXED_ROTATION_TRANSFORM = 457 SystemProperties.getBoolean("persist.wm.fixed_rotation_transform", true); 458 459 // Enums for animation scale update types. 460 @Retention(RetentionPolicy.SOURCE) 461 @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE}) 462 private @interface UpdateAnimationScaleMode {}; 463 private static final int WINDOW_ANIMATION_SCALE = 0; 464 private static final int TRANSITION_ANIMATION_SCALE = 1; 465 private static final int ANIMATION_DURATION_SCALE = 2; 466 467 private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000; 468 469 final WindowManagerConstants mConstants; 470 471 final WindowTracing mWindowTracing; 472 final TransitionTracer mTransitionTracer; 473 474 private final DisplayAreaPolicy.Provider mDisplayAreaPolicyProvider; 475 476 final private KeyguardDisableHandler mKeyguardDisableHandler; 477 478 private final RemoteCallbackList<IKeyguardLockedStateListener> mKeyguardLockedStateListeners = 479 new RemoteCallbackList<>(); 480 481 private final List<OnWindowRemovedListener> mOnWindowRemovedListeners = new ArrayList<>(); 482 483 private boolean mDispatchedKeyguardLockedState = false; 484 485 // VR Vr2d Display Id. 486 int mVr2dDisplayId = INVALID_DISPLAY; 487 boolean mVrModeEnabled = false; 488 489 /** 490 * Tracks a map of input tokens to info that is used to decide whether to intercept 491 * a key event. 492 */ 493 final Map<IBinder, KeyInterceptionInfo> mKeyInterceptionInfoForToken = 494 Collections.synchronizedMap(new ArrayMap<>()); 495 496 final StartingSurfaceController mStartingSurfaceController; 497 498 final PresentationController mPresentationController; 499 500 private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() { 501 @Override 502 public void onVrStateChanged(boolean enabled) { 503 synchronized (mGlobalLock) { 504 mVrModeEnabled = enabled; 505 } 506 } 507 }; 508 509 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 510 @Override 511 public void onReceive(Context context, Intent intent) { 512 switch (intent.getAction()) { 513 case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED: 514 mKeyguardDisableHandler.updateKeyguardEnabled(getSendingUserId()); 515 break; 516 } 517 } 518 }; 519 final WindowSurfacePlacer mWindowPlacerLocked; 520 521 private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { 522 @Override 523 public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args, 524 boolean asProto) { 525 doDump(fd, pw, new String[] {"-a"}, asProto); 526 } 527 528 @Override 529 public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args, 530 boolean asProto) { 531 if (asProto) { 532 return; 533 } 534 535 final long timeoutMs = 1000L; 536 mAtmService.dumpActivity(fd, pw, /* name= */ "all", /* args= */ new String[]{}, 537 /* opti= */ 0, 538 /* dumpAll= */ true, 539 /* dumpVisibleRootTasksOnly= */ true, 540 /* dumpFocusedRootTaskOnly= */ false, INVALID_DISPLAY, UserHandle.USER_ALL, 541 timeoutMs 542 ); 543 dumpVisibleWindowClients(fd, pw, timeoutMs); 544 } 545 546 @Override 547 public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) { 548 doDump(fd, pw, args, asProto); 549 } 550 }; 551 552 /** 553 * Current user when multi-user is enabled. Don't show windows of non-current user. 554 */ 555 @UserIdInt int mCurrentUserId; 556 557 final Context mContext; 558 559 final boolean mHasPermanentDpad; 560 final long mDrawLockTimeoutMillis; 561 final boolean mAllowAnimationsInLowPowerMode; 562 final boolean mSupportsHighPerfTransitions; 563 final boolean mAllowBootMessages; 564 565 // Indicates whether the Assistant should show on top of the Dream (respectively, above 566 // everything else on screen). Otherwise, it will be put under always-on-top stacks. 567 final boolean mAssistantOnTopOfDream; 568 569 /** 570 * If true, don't relaunch the activity upon receiving a configuration change to transition to 571 * or from the {@link UI_MODE_TYPE_DESK} uiMode, which is sent when docking. The configuration 572 * change will still be sent regardless, only the relaunch is skipped. Apps with desk resources 573 * are exempt from this and will behave like normal, since they may expect the relaunch upon the 574 * desk uiMode change. 575 */ 576 @VisibleForTesting 577 boolean mSkipActivityRelaunchWhenDocking; 578 579 /** Device default insets types provided non-decor insets. */ 580 final int mDecorTypes; 581 582 /** Device default insets types shall be excluded from config app sizes. */ 583 final int mConfigTypes; 584 585 final int mOverrideConfigTypes; 586 587 final int mOverrideDecorTypes; 588 589 final boolean mLimitedAlphaCompositing; 590 final int mMaxUiWidth; 591 592 @NonNull 593 @VisibleForTesting 594 WindowManagerPolicy mPolicy; 595 596 final WindowManagerFlags mFlags; 597 598 final IActivityManager mActivityManager; 599 final ActivityManagerInternal mAmInternal; 600 final UserManagerInternal mUmInternal; 601 602 final AppOpsManager mAppOps; 603 final PackageManagerInternal mPmInternal; 604 private final TestUtilityService mTestUtilityService; 605 606 @NonNull 607 final DisplayWindowSettingsProvider mDisplayWindowSettingsProvider; 608 @NonNull 609 final DisplayWindowSettings mDisplayWindowSettings; 610 611 /** If the system should display notifications for apps displaying an alert window. */ 612 boolean mShowAlertWindowNotifications = true; 613 614 /** 615 * All currently active sessions with clients. 616 */ 617 final ArraySet<Session> mSessions = new ArraySet<>(); 618 619 /** Mapping from an IWindow IBinder to the server's Window object. */ 620 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>(); 621 622 /** Mapping from an InputWindowHandle token to the server's Window object. */ 623 final HashMap<IBinder, WindowState> mInputToWindowMap = new HashMap<>(); 624 625 /** Global service lock used by the package that owns this service. */ 626 final WindowManagerGlobalLock mGlobalLock; 627 628 /** 629 * Windows that are being resized. Used so we can tell the client about 630 * the resize after closing the transaction in which we resized the 631 * underlying surface. 632 */ 633 final ArrayList<WindowState> mResizingWindows = new ArrayList<>(); 634 635 /** 636 * Windows that their frames are being changed. Used so we can clear the frame-changing states 637 * after handling the moved or resized windows. 638 */ 639 final ArrayList<WindowState> mFrameChangingWindows = new ArrayList<>(); 640 641 /** 642 * Mapping of displayId to {@link DisplayImePolicy}. 643 * Note that this can be accessed without holding the lock. 644 */ 645 volatile Map<Integer, Integer> mDisplayImePolicyCache = Collections.unmodifiableMap( 646 new ArrayMap<>()); 647 648 /** 649 * Windows whose surface should be destroyed. 650 */ 651 final ArrayList<WindowState> mDestroySurface = new ArrayList<>(); 652 653 /** 654 * This is set when we have run out of memory, and will either be an empty 655 * list or contain windows that need to be force removed. 656 */ 657 final ArrayList<WindowState> mForceRemoves = new ArrayList<>(); 658 659 /** 660 * The callbacks to make when the windows all have been drawn for a given 661 * {@link WindowContainer}. 662 */ 663 final ArrayMap<WindowContainer<?>, Message> mWaitingForDrawnCallbacks = new ArrayMap<>(); 664 665 /** List of window currently causing non-system overlay windows to be hidden. */ 666 private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>(); 667 668 /** 669 * A map that tracks uid/count of windows that cause non-system overlay windows to be hidden. 670 * The key is the window's uid and the value is the number of windows with that uid that are 671 * requesting hiding non-system overlay 672 */ 673 private final ArrayMap<Integer, Integer> mHidingNonSystemOverlayWindowsCountPerUid = 674 new ArrayMap<>(); 675 676 /** 677 * In some cases (e.g. when {@link R.bool.config_reverseDefaultRotation} has value 678 * {@value true}) we need to map some orientation to others. This {@link SparseIntArray} 679 * contains the relation between the source orientation and the one to use. 680 */ 681 private final SparseIntArray mOrientationMapping = new SparseIntArray(); 682 683 final AccessibilityController mAccessibilityController; 684 685 Watermark mWatermark; 686 StrictModeFlash mStrictModeFlash; 687 EmulatorDisplayOverlay mEmulatorDisplayOverlay; 688 689 final Rect mTmpRect = new Rect(); 690 691 boolean mDisplayReady; 692 boolean mSafeMode; 693 boolean mDisplayEnabled = false; 694 boolean mSystemBooted = false; 695 boolean mForceDisplayEnabled = false; 696 boolean mShowingBootMessages = false; 697 boolean mSystemReady = false; 698 boolean mBootAnimationStopped = false; 699 long mBootWaitForWindowsStartTime = -1; 700 701 /** Dump of the windows and app tokens at the time of the last ANR. Cleared after 702 * LAST_ANR_LIFETIME_DURATION_MSECS */ 703 String mLastANRState; 704 705 // The root of the device window hierarchy. 706 @NonNull 707 final RootWindowContainer mRoot; 708 709 final BLASTSyncEngine mSyncEngine; 710 711 boolean mIsPc; 712 /** 713 * Flag that indicates that desktop mode is forced for public secondary screens. 714 * 715 * This includes several settings: 716 * - Set freeform windowing mode on external screen if it's supported and enabled. 717 * - Enable system decorations and IME on external screen. 718 * - TODO: Show mouse pointer on external screen. 719 */ 720 boolean mForceDesktopModeOnExternalDisplays; 721 722 boolean mDisableTransitionAnimation; 723 724 final RotationWatcherController mRotationWatcherController; 725 final WallpaperVisibilityListeners mWallpaperVisibilityListeners = 726 new WallpaperVisibilityListeners(); 727 728 IDisplayChangeWindowController mDisplayChangeController = null; 729 private final DeathRecipient mDisplayChangeControllerDeath = new DeathRecipient() { 730 @Override 731 public void binderDied() { 732 synchronized (mGlobalLock) { 733 mDisplayChangeController = null; 734 } 735 } 736 }; 737 738 final DisplayWindowListenerController mDisplayNotificationController; 739 final TaskSystemBarsListenerController mTaskSystemBarsListenerController; 740 741 /** Amount of time (in milliseconds) to delay the pointer down outside focus handling */ 742 private static final int POINTER_DOWN_OUTSIDE_FOCUS_TIMEOUT_MS = 50; 743 744 /** A runnable to handle pointer down outside focus event. */ 745 @Nullable 746 private Runnable mPointerDownOutsideFocusRunnable; 747 748 boolean mSwitchingUser = false; 749 750 @VisibleForTesting 751 boolean mPerDisplayFocusEnabled; 752 753 // State while inside of layoutAndPlaceSurfacesLocked(). 754 boolean mFocusMayChange; 755 756 // Number of windows whose insets state have been changed. 757 int mWindowsInsetsChanged = 0; 758 759 final TaskSnapshotController mTaskSnapshotController; 760 final SnapshotController mSnapshotController; 761 762 final BlurController mBlurController; 763 final TaskFpsCallbackController mTaskFpsCallbackController; 764 765 boolean mIsTouchDevice; 766 boolean mIsFakeTouchDevice; 767 768 final H mH = new H(); 769 770 /** 771 * Handler for things to run that have direct impact on an animation, i.e. animation tick, 772 * layout, starting window creation, whereas {@link H} runs things that are still important, but 773 * not as critical. 774 */ 775 final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper()); 776 777 boolean mHardKeyboardAvailable; 778 WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 779 WindowManagerInternal.OnImeRequestedChangedListener mOnImeRequestedChangedListener; 780 781 SettingsObserver mSettingsObserver; 782 final EmbeddedWindowController mEmbeddedWindowController; 783 final AnrController mAnrController; 784 785 private final DisplayHashController mDisplayHashController; 786 787 volatile float mMaximumObscuringOpacityForTouch = 788 InputSettings.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH; 789 790 @VisibleForTesting 791 final WindowContextListenerController mWindowContextListenerController = 792 new WindowContextListenerController(); 793 794 private InputTarget mFocusedInputTarget; 795 796 @VisibleForTesting 797 final ContentRecordingController mContentRecordingController = new ContentRecordingController(); 798 799 private final SurfaceSyncGroupController mSurfaceSyncGroupController = 800 new SurfaceSyncGroupController(); 801 802 final TrustedPresentationListenerController mTrustedPresentationListenerController = 803 new TrustedPresentationListenerController(); 804 805 @VisibleForTesting 806 final class SettingsObserver extends ContentObserver { 807 private final Uri mDisplayInversionEnabledUri = 808 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 809 private final Uri mWindowAnimationScaleUri = 810 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE); 811 private final Uri mTransitionAnimationScaleUri = 812 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE); 813 private final Uri mAnimationDurationScaleUri = 814 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE); 815 private final Uri mImmersiveModeConfirmationsUri = 816 Settings.Secure.getUriFor(Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS); 817 private final Uri mDisableSecureWindowsUri = 818 Settings.Secure.getUriFor(Settings.Secure.DISABLE_SECURE_WINDOWS); 819 private final Uri mPolicyControlUri = 820 Settings.Global.getUriFor(Settings.Global.POLICY_CONTROL); 821 private final Uri mForceDesktopModeOnExternalDisplaysUri = Settings.Global.getUriFor( 822 Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS); 823 private final Uri mFreeformWindowUri = Settings.Global.getUriFor( 824 Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT); 825 private final Uri mForceResizableUri = Settings.Global.getUriFor( 826 DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES); 827 private final Uri mDevEnableNonResizableMultiWindowUri = Settings.Global.getUriFor( 828 DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW); 829 private final Uri mDisplaySettingsPathUri = Settings.Global.getUriFor( 830 DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH); 831 private final Uri mMaximumObscuringOpacityForTouchUri = Settings.Global.getUriFor( 832 Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH); 833 private final Uri mDevelopmentOverrideDesktopExperienceUri = Settings.Global.getUriFor( 834 Settings.Global.DEVELOPMENT_OVERRIDE_DESKTOP_EXPERIENCE_FEATURES); 835 SettingsObserver()836 public SettingsObserver() { 837 super(new Handler()); 838 ContentResolver resolver = mContext.getContentResolver(); 839 resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this, 840 UserHandle.USER_ALL); 841 resolver.registerContentObserver(mWindowAnimationScaleUri, false, this, 842 UserHandle.USER_ALL); 843 resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this, 844 UserHandle.USER_ALL); 845 resolver.registerContentObserver(mAnimationDurationScaleUri, false, this, 846 UserHandle.USER_ALL); 847 resolver.registerContentObserver(mImmersiveModeConfirmationsUri, false, this, 848 UserHandle.USER_ALL); 849 resolver.registerContentObserver(mDisableSecureWindowsUri, false, this, 850 UserHandle.USER_ALL); 851 resolver.registerContentObserver(mPolicyControlUri, false, this, UserHandle.USER_ALL); 852 resolver.registerContentObserver(mForceDesktopModeOnExternalDisplaysUri, false, this, 853 UserHandle.USER_ALL); 854 resolver.registerContentObserver(mFreeformWindowUri, false, this, UserHandle.USER_ALL); 855 resolver.registerContentObserver(mForceResizableUri, false, this, UserHandle.USER_ALL); 856 resolver.registerContentObserver(mDevEnableNonResizableMultiWindowUri, false, this, 857 UserHandle.USER_ALL); 858 resolver.registerContentObserver(mDisplaySettingsPathUri, false, this, 859 UserHandle.USER_ALL); 860 resolver.registerContentObserver(mMaximumObscuringOpacityForTouchUri, false, this, 861 UserHandle.USER_ALL); 862 resolver.registerContentObserver(mDevelopmentOverrideDesktopExperienceUri, false, this, 863 UserHandle.USER_ALL); 864 } 865 866 @Override onChange(boolean selfChange, Uri uri)867 public void onChange(boolean selfChange, Uri uri) { 868 if (uri == null) { 869 return; 870 } 871 872 if (mForceDesktopModeOnExternalDisplaysUri.equals(uri)) { 873 updateForceDesktopModeOnExternalDisplays(); 874 return; 875 } 876 877 if (mFreeformWindowUri.equals(uri)) { 878 updateFreeformWindowManagement(); 879 return; 880 } 881 882 if (mForceResizableUri.equals(uri)) { 883 updateForceResizableTasks(); 884 return; 885 } 886 887 if (mDevEnableNonResizableMultiWindowUri.equals(uri)) { 888 updateDevEnableNonResizableMultiWindow(); 889 return; 890 } 891 892 if (mDisplaySettingsPathUri.equals(uri)) { 893 updateDisplaySettingsLocation(); 894 return; 895 } 896 897 if (mMaximumObscuringOpacityForTouchUri.equals(uri)) { 898 updateMaximumObscuringOpacityForTouch(); 899 return; 900 } 901 902 if (mDisableSecureWindowsUri.equals(uri)) { 903 updateDisableSecureWindows(); 904 return; 905 } 906 907 if (mDevelopmentOverrideDesktopExperienceUri.equals(uri)) { 908 updateDevelopmentOverrideDesktopExperience(); 909 return; 910 } 911 912 @UpdateAnimationScaleMode 913 final int mode; 914 if (mWindowAnimationScaleUri.equals(uri)) { 915 mode = WINDOW_ANIMATION_SCALE; 916 } else if (mTransitionAnimationScaleUri.equals(uri)) { 917 mode = TRANSITION_ANIMATION_SCALE; 918 } else if (mAnimationDurationScaleUri.equals(uri)) { 919 mode = ANIMATION_DURATION_SCALE; 920 } else { 921 // Ignoring unrecognized content changes 922 return; 923 } 924 Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0); 925 mH.sendMessage(m); 926 } 927 loadSettings()928 void loadSettings() { 929 updateMaximumObscuringOpacityForTouch(); 930 updateDisableSecureWindows(); 931 } 932 updateMaximumObscuringOpacityForTouch()933 void updateMaximumObscuringOpacityForTouch() { 934 ContentResolver resolver = mContext.getContentResolver(); 935 mMaximumObscuringOpacityForTouch = Settings.Global.getFloat(resolver, 936 Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH, 937 InputSettings.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH); 938 if (mMaximumObscuringOpacityForTouch < 0.0f 939 || mMaximumObscuringOpacityForTouch > 1.0f) { 940 mMaximumObscuringOpacityForTouch = 941 InputSettings.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH; 942 } 943 } 944 updateForceDesktopModeOnExternalDisplays()945 void updateForceDesktopModeOnExternalDisplays() { 946 ContentResolver resolver = mContext.getContentResolver(); 947 final boolean enableForceDesktopMode = Settings.Global.getInt(resolver, 948 DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0; 949 if (mForceDesktopModeOnExternalDisplays == enableForceDesktopMode) { 950 return; 951 } 952 setForceDesktopModeOnExternalDisplays(enableForceDesktopMode); 953 } 954 updateFreeformWindowManagement()955 void updateFreeformWindowManagement() { 956 ContentResolver resolver = mContext.getContentResolver(); 957 final boolean freeformWindowManagement = mContext.getPackageManager().hasSystemFeature( 958 FEATURE_FREEFORM_WINDOW_MANAGEMENT) || Settings.Global.getInt( 959 resolver, DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0; 960 961 if (mAtmService.mSupportsFreeformWindowManagement != freeformWindowManagement) { 962 mAtmService.mSupportsFreeformWindowManagement = freeformWindowManagement; 963 synchronized (mGlobalLock) { 964 // Notify the root window container that the display settings value may change. 965 mRoot.onSettingsRetrieved(); 966 } 967 } 968 } 969 updateForceResizableTasks()970 void updateForceResizableTasks() { 971 ContentResolver resolver = mContext.getContentResolver(); 972 final boolean forceResizable = Settings.Global.getInt(resolver, 973 DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0; 974 975 mAtmService.mForceResizableActivities = forceResizable; 976 } 977 updateDevelopmentOverrideDesktopExperience()978 void updateDevelopmentOverrideDesktopExperience() { 979 ContentResolver resolver = mContext.getContentResolver(); 980 final int overrideDesktopMode = Settings.Global.getInt(resolver, 981 Settings.Global.DEVELOPMENT_OVERRIDE_DESKTOP_EXPERIENCE_FEATURES, 982 DesktopModeFlags.ToggleOverride.OVERRIDE_UNSET.getSetting()); 983 984 SystemProperties.set(DesktopModeFlags.SYSTEM_PROPERTY_NAME, 985 Integer.toString(overrideDesktopMode)); 986 } 987 updateDevEnableNonResizableMultiWindow()988 void updateDevEnableNonResizableMultiWindow() { 989 ContentResolver resolver = mContext.getContentResolver(); 990 final boolean devEnableNonResizableMultiWindow = Settings.Global.getInt(resolver, 991 DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, 0) != 0; 992 993 mAtmService.mDevEnableNonResizableMultiWindow = devEnableNonResizableMultiWindow; 994 } 995 updateDisplaySettingsLocation()996 void updateDisplaySettingsLocation() { 997 final ContentResolver resolver = mContext.getContentResolver(); 998 final String filePath = Settings.Global.getString(resolver, 999 DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH); 1000 synchronized (mGlobalLock) { 1001 mDisplayWindowSettingsProvider.setBaseSettingsFilePath(filePath); 1002 mRoot.forAllDisplays(display -> { 1003 mDisplayWindowSettings.applySettingsToDisplayLocked(display); 1004 display.reconfigureDisplayLocked(); 1005 }); 1006 } 1007 } 1008 updateDisableSecureWindows()1009 void updateDisableSecureWindows() { 1010 if (!SystemProperties.getBoolean(SYSTEM_DEBUGGABLE, false)) { 1011 return; 1012 } 1013 1014 boolean disableSecureWindows; 1015 try { 1016 disableSecureWindows = Settings.Secure.getIntForUser(mContext.getContentResolver(), 1017 Settings.Secure.DISABLE_SECURE_WINDOWS, 0) != 0; 1018 } catch (Settings.SettingNotFoundException e) { 1019 disableSecureWindows = false; 1020 } 1021 if (mDisableSecureWindows == disableSecureWindows) { 1022 return; 1023 } 1024 1025 synchronized (mGlobalLock) { 1026 mDisableSecureWindows = disableSecureWindows; 1027 mRoot.refreshSecureSurfaceState(); 1028 } 1029 } 1030 } 1031 1032 PowerManager mPowerManager; 1033 PowerManagerInternal mPowerManagerInternal; 1034 1035 private DeviceStateManager mDeviceStateManager; 1036 private DeviceStateCallback mDeviceStateCallback; 1037 private class DeviceStateCallback implements DeviceStateManager.DeviceStateCallback { 1038 private DeviceState mCurrentDeviceState; 1039 @Override onDeviceStateChanged(@onNull DeviceState state)1040 public void onDeviceStateChanged(@NonNull DeviceState state) { 1041 mCurrentDeviceState = state; 1042 } 1043 isInRearDisplayOuterDefaultState()1044 boolean isInRearDisplayOuterDefaultState() { 1045 return mCurrentDeviceState != null && mCurrentDeviceState 1046 .hasProperties(DeviceState.PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT); 1047 } 1048 } 1049 1050 private float mWindowAnimationScaleSetting = 1.0f; 1051 private float mTransitionAnimationScaleSetting = 1.0f; 1052 private float mAnimatorDurationScaleSetting = 1.0f; 1053 private boolean mAnimationsDisabled = false; 1054 boolean mPointerLocationEnabled = false; 1055 1056 @NonNull 1057 final AppCompatConfiguration mAppCompatConfiguration; 1058 1059 private boolean mIsIgnoreOrientationRequestDisabled; 1060 1061 @NonNull 1062 final InputManagerService mInputManager; 1063 final DisplayManagerInternal mDisplayManagerInternal; 1064 final DisplayManager mDisplayManager; 1065 @NonNull 1066 final ActivityTaskManagerService mAtmService; 1067 1068 /** Indicates whether this device supports wide color gamut / HDR rendering */ 1069 private boolean mHasWideColorGamutSupport; 1070 private boolean mHasHdrSupport; 1071 1072 /** Whether or not a layout can cause a wake up when theater mode is enabled. */ 1073 boolean mAllowTheaterModeWakeFromLayout; 1074 1075 final DragDropController mDragDropController; 1076 1077 /** Skip repeated ActivityRecords initialization. Note that AppWindowsToken's version of this 1078 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 1079 int mTransactionSequence; 1080 1081 final WindowAnimator mAnimator; 1082 SurfaceAnimationRunner mSurfaceAnimationRunner; 1083 1084 /** 1085 * Keeps track of which animations got transferred to which animators. Entries will get cleaned 1086 * up when the animation finishes. 1087 */ 1088 final ArrayMap<AnimationAdapter, SurfaceAnimator> mAnimationTransferMap = new ArrayMap<>(); 1089 1090 private WindowContentFrameStats mTempWindowRenderStats; 1091 1092 final LatencyTracker mLatencyTracker; 1093 1094 private ViewServer mViewServer; 1095 final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>(); 1096 final ArrayList<WindowFocusChangeListener> mWindowFocusChangeListeners = new ArrayList<>(); 1097 boolean mWindowsChanged = false; 1098 1099 interface WindowChangeListener { 1100 /** Notify on windows changed */ windowsChanged()1101 void windowsChanged(); 1102 } 1103 1104 final HighRefreshRateDenylist mHighRefreshRateDenylist; 1105 1106 // Maintainer of a collection of all possible DisplayInfo for all configurations of the 1107 // logical displays. 1108 final PossibleDisplayInfoMapper mPossibleDisplayInfoMapper; 1109 1110 static WindowManagerThreadPriorityBooster sThreadPriorityBooster = 1111 new WindowManagerThreadPriorityBooster(); 1112 1113 @NonNull 1114 Supplier<SurfaceControl.Builder> mSurfaceControlFactory; 1115 @NonNull 1116 Supplier<SurfaceControl.Transaction> mTransactionFactory; 1117 1118 private final SurfaceControl.Transaction mTransaction; 1119 boostPriorityForLockedSection()1120 static void boostPriorityForLockedSection() { 1121 sThreadPriorityBooster.boost(); 1122 } 1123 resetPriorityAfterLockedSection()1124 static void resetPriorityAfterLockedSection() { 1125 sThreadPriorityBooster.reset(); 1126 } 1127 1128 SystemPerformanceHinter mSystemPerformanceHinter; 1129 1130 @GuardedBy("mGlobalLock") 1131 private long mSensitiveContentProtectionSessionId = 0; 1132 1133 @GuardedBy("mGlobalLock") 1134 final SensitiveContentPackages mSensitiveContentPackages = new SensitiveContentPackages(); 1135 /** 1136 * UIDs for which a Toast has been shown to indicate 1137 * {@link LocalService#addBlockScreenCaptureForApps(ArraySet) screen capture blocking}. This is 1138 * used to ensure we don't keep re-showing the Toast every time the window becomes visible. 1139 * UIDs are removed when the app is removed from the block list. 1140 */ 1141 @GuardedBy("mGlobalLock") 1142 private final IntArray mCaptureBlockedToastShownUids = new IntArray(); 1143 1144 /** Listener to notify activity manager about app transitions. */ 1145 final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier 1146 = new WindowManagerInternal.AppTransitionListener() { 1147 1148 @Override 1149 public void onAppTransitionCancelledLocked(boolean keyguardGoingAwayCancelled) { 1150 } 1151 1152 @Override 1153 public void onAppTransitionFinishedLocked(IBinder token) { 1154 final ActivityRecord atoken = ActivityRecord.forTokenLocked(token); 1155 if (atoken == null) { 1156 return; 1157 } 1158 1159 if (atoken.mLaunchTaskBehind) { 1160 mAtmService.mTaskSupervisor.scheduleLaunchTaskBehindComplete(atoken.token); 1161 atoken.mLaunchTaskBehind = false; 1162 } else { 1163 atoken.updateReportedVisibilityLocked(); 1164 if (atoken.mEnteringAnimation) { 1165 atoken.mEnteringAnimation = false; 1166 if (atoken.attachedToProcess()) { 1167 try { 1168 atoken.app.getThread().scheduleEnterAnimationComplete(atoken.token); 1169 } catch (RemoteException e) { 1170 } 1171 } 1172 } 1173 } 1174 } 1175 }; 1176 1177 private final ScreenRecordingCallbackController mScreenRecordingCallbackController; 1178 1179 private volatile boolean mDisableSecureWindows = false; 1180 1181 /** Creates an instance of the WindowManagerService for the system server. */ main(@onNull final Context context, @NonNull final InputManagerService im, final boolean showBootMsgs, @NonNull final WindowManagerPolicy policy, @NonNull final ActivityTaskManagerService atm)1182 public static WindowManagerService main(@NonNull final Context context, 1183 @NonNull final InputManagerService im, final boolean showBootMsgs, 1184 @NonNull final WindowManagerPolicy policy, 1185 @NonNull final ActivityTaskManagerService atm) { 1186 // Using SysUI context to have access to Material colors extracted from Wallpaper. 1187 final AppCompatConfiguration appCompat = new AppCompatConfiguration( 1188 ActivityThread.currentActivityThread().getSystemUiContext()); 1189 1190 final WindowManagerService wms = main(context, im, showBootMsgs, policy, atm, 1191 new DisplayWindowSettingsProvider(), SurfaceControl.Transaction::new, 1192 SurfaceControl.Builder::new, appCompat); 1193 WindowManagerGlobal.setWindowManagerServiceForSystemProcess(wms); 1194 return wms; 1195 } 1196 1197 /** 1198 * Creates and returns an instance of the WindowManagerService. This call allows the caller 1199 * to override factories that can be used to stub native calls during test. Tests should use 1200 * {@link WindowManagerServiceTestSupport} instead of calling this directly to ensure 1201 * proper initialization and cleanup of dependencies. 1202 */ 1203 @VisibleForTesting(visibility = Visibility.PRIVATE) main(@onNull final Context context, @NonNull final InputManagerService im, boolean showBootMsgs, @NonNull final WindowManagerPolicy policy, @NonNull final ActivityTaskManagerService atm, @NonNull final DisplayWindowSettingsProvider displayWindowSettingsProvider, @NonNull final Supplier<SurfaceControl.Transaction> transactionFactory, @NonNull final Supplier<SurfaceControl.Builder> surfaceControlFactory, @NonNull final AppCompatConfiguration appCompat)1204 static WindowManagerService main(@NonNull final Context context, 1205 @NonNull final InputManagerService im, boolean showBootMsgs, 1206 @NonNull final WindowManagerPolicy policy, 1207 @NonNull final ActivityTaskManagerService atm, 1208 @NonNull final DisplayWindowSettingsProvider displayWindowSettingsProvider, 1209 @NonNull final Supplier<SurfaceControl.Transaction> transactionFactory, 1210 @NonNull final Supplier<SurfaceControl.Builder> surfaceControlFactory, 1211 @NonNull final AppCompatConfiguration appCompat) { 1212 1213 final WindowManagerService[] wms = new WindowManagerService[1]; 1214 DisplayThread.getHandler().runWithScissors(() -> 1215 wms[0] = new WindowManagerService(context, im, showBootMsgs, policy, atm, 1216 displayWindowSettingsProvider, transactionFactory, 1217 surfaceControlFactory, appCompat), 0); 1218 return wms[0]; 1219 } 1220 initPolicy()1221 private void initPolicy() { 1222 UiThread.getHandler().runWithScissors(new Runnable() { 1223 @Override 1224 public void run() { 1225 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 1226 mPolicy.init(mContext, WindowManagerService.this); 1227 } 1228 }, 0); 1229 } 1230 1231 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver result)1232 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 1233 String[] args, ShellCallback callback, ResultReceiver result) { 1234 new WindowManagerShellCommand(this).exec(this, in, out, err, args, callback, result); 1235 } 1236 WindowManagerService(@onNull Context context, @NonNull InputManagerService inputManager, boolean showBootMsgs, @NonNull WindowManagerPolicy policy, @NonNull ActivityTaskManagerService atm, @NonNull DisplayWindowSettingsProvider displayWindowSettingsProvider, @NonNull Supplier<SurfaceControl.Transaction> transactionFactory, @NonNull Supplier<SurfaceControl.Builder> surfaceControlFactory, @NonNull AppCompatConfiguration appCompat)1237 private WindowManagerService(@NonNull Context context, 1238 @NonNull InputManagerService inputManager, boolean showBootMsgs, 1239 @NonNull WindowManagerPolicy policy, @NonNull ActivityTaskManagerService atm, 1240 @NonNull DisplayWindowSettingsProvider displayWindowSettingsProvider, 1241 @NonNull Supplier<SurfaceControl.Transaction> transactionFactory, 1242 @NonNull Supplier<SurfaceControl.Builder> surfaceControlFactory, 1243 @NonNull AppCompatConfiguration appCompat) { 1244 installLock(this, INDEX_WINDOW); 1245 mGlobalLock = atm.getGlobalLock(); 1246 mAtmService = atm; 1247 mContext = context; 1248 mFlags = new WindowManagerFlags(); 1249 mIsPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC); 1250 mAllowBootMessages = showBootMsgs; 1251 mLimitedAlphaCompositing = context.getResources().getBoolean( 1252 com.android.internal.R.bool.config_sf_limitedAlpha); 1253 mHasPermanentDpad = context.getResources().getBoolean( 1254 com.android.internal.R.bool.config_hasPermanentDpad); 1255 mDrawLockTimeoutMillis = context.getResources().getInteger( 1256 com.android.internal.R.integer.config_drawLockTimeoutMillis); 1257 mAllowAnimationsInLowPowerMode = context.getResources().getBoolean( 1258 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode); 1259 mMaxUiWidth = context.getResources().getInteger( 1260 com.android.internal.R.integer.config_maxUiWidth); 1261 mSupportsHighPerfTransitions = context.getResources().getBoolean( 1262 com.android.internal.R.bool.config_deviceSupportsHighPerfTransitions); 1263 mDisableTransitionAnimation = context.getResources().getBoolean( 1264 com.android.internal.R.bool.config_disableTransitionAnimation); 1265 mPerDisplayFocusEnabled = context.getResources().getBoolean( 1266 com.android.internal.R.bool.config_perDisplayFocusEnabled); 1267 mAssistantOnTopOfDream = context.getResources().getBoolean( 1268 com.android.internal.R.bool.config_assistantOnTopOfDream); 1269 mSkipActivityRelaunchWhenDocking = context.getResources() 1270 .getBoolean(R.bool.config_skipActivityRelaunchWhenDocking); 1271 final boolean isScreenSizeDecoupledFromStatusBarAndCutout = context.getResources() 1272 .getBoolean(R.bool.config_decoupleStatusBarAndDisplayCutoutFromScreenSize) 1273 && mFlags.mAllowsScreenSizeDecoupledFromStatusBarAndCutout; 1274 1275 if (mFlags.mInsetsDecoupledConfiguration) { 1276 mDecorTypes = 0; 1277 mConfigTypes = 0; 1278 } else { 1279 mDecorTypes = WindowInsets.Type.displayCutout() | WindowInsets.Type.navigationBars(); 1280 mConfigTypes = WindowInsets.Type.displayCutout() | WindowInsets.Type.statusBars() 1281 | WindowInsets.Type.navigationBars(); 1282 } 1283 if (isScreenSizeDecoupledFromStatusBarAndCutout && !mFlags.mInsetsDecoupledConfiguration) { 1284 // If the global new behavior is not there, but the partial decouple flag is on. 1285 mOverrideConfigTypes = 0; 1286 mOverrideDecorTypes = 0; 1287 } else { 1288 mOverrideConfigTypes = 1289 WindowInsets.Type.displayCutout() | WindowInsets.Type.statusBars() 1290 | WindowInsets.Type.navigationBars(); 1291 mOverrideDecorTypes = WindowInsets.Type.displayCutout() 1292 | WindowInsets.Type.navigationBars(); 1293 } 1294 1295 mAppCompatConfiguration = appCompat; 1296 1297 mInputManager = inputManager; // Must be before createDisplayContentLocked. 1298 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 1299 mPossibleDisplayInfoMapper = new PossibleDisplayInfoMapper(mDisplayManagerInternal); 1300 1301 mSurfaceControlFactory = surfaceControlFactory; 1302 mTransactionFactory = transactionFactory; 1303 mTransaction = mTransactionFactory.get(); 1304 1305 mPolicy = policy; 1306 mAnimator = new WindowAnimator(this); 1307 mRoot = new RootWindowContainer(this); 1308 1309 final ContentResolver resolver = context.getContentResolver(); 1310 1311 mSyncEngine = new BLASTSyncEngine(this); 1312 1313 mWindowPlacerLocked = new WindowSurfacePlacer(this); 1314 mSnapshotController = new SnapshotController(this); 1315 mTaskSnapshotController = mSnapshotController.mTaskSnapshotController; 1316 1317 mWindowTracing = WindowTracing.createDefaultAndStartLooper(this, 1318 Choreographer.getInstance()); 1319 1320 if (android.tracing.Flags.perfettoTransitionTracing()) { 1321 mTransitionTracer = new PerfettoTransitionTracer(); 1322 } else { 1323 mTransitionTracer = new LegacyTransitionTracer(); 1324 } 1325 1326 LocalServices.addService(WindowManagerPolicy.class, mPolicy); 1327 1328 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 1329 1330 mKeyguardDisableHandler = KeyguardDisableHandler.create(mContext, mPolicy, mH); 1331 1332 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 1333 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 1334 1335 mDeviceStateManager = context.getSystemService(DeviceStateManager.class); 1336 mDeviceStateCallback = new DeviceStateCallback(); 1337 mDeviceStateManager.registerCallback(new HandlerExecutor(mH), mDeviceStateCallback); 1338 1339 if (mPowerManagerInternal != null) { 1340 mPowerManagerInternal.registerLowPowerModeObserver( 1341 new PowerManagerInternal.LowPowerModeListener() { 1342 @Override 1343 public int getServiceType() { 1344 return ServiceType.ANIMATION; 1345 } 1346 1347 @Override 1348 public void onLowPowerModeChanged(PowerSaveState result) { 1349 synchronized (mGlobalLock) { 1350 final boolean enabled = result.batterySaverEnabled; 1351 if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) { 1352 mAnimationsDisabled = enabled; 1353 dispatchNewAnimatorScaleLocked(null); 1354 } 1355 } 1356 } 1357 }); 1358 mAnimationsDisabled = mPowerManagerInternal 1359 .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled; 1360 } 1361 1362 mRotationWatcherController = new RotationWatcherController(this); 1363 mDisplayNotificationController = new DisplayWindowListenerController(this); 1364 mTaskSystemBarsListenerController = new TaskSystemBarsListenerController(); 1365 1366 mActivityManager = ActivityManager.getService(); 1367 mAmInternal = LocalServices.getService(ActivityManagerInternal.class); 1368 mUmInternal = LocalServices.getService(UserManagerInternal.class); 1369 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 1370 AppOpsManager.OnOpChangedInternalListener opListener = 1371 new AppOpsManager.OnOpChangedInternalListener() { 1372 @Override public void onOpChanged(int op, String packageName) { 1373 updateAppOpsState(); 1374 } 1375 }; 1376 mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener); 1377 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener); 1378 1379 mPmInternal = LocalServices.getService(PackageManagerInternal.class); 1380 mTestUtilityService = LocalServices.getService(TestUtilityService.class); 1381 final IntentFilter suspendPackagesFilter = new IntentFilter(); 1382 suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED); 1383 suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED); 1384 context.registerReceiverAsUser(new BroadcastReceiver() { 1385 @Override 1386 public void onReceive(Context context, Intent intent) { 1387 final String[] affectedPackages = 1388 intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 1389 final boolean suspended = 1390 Intent.ACTION_PACKAGES_SUSPENDED.equals(intent.getAction()); 1391 updateHiddenWhileSuspendedState(new ArraySet<>(Arrays.asList(affectedPackages)), 1392 suspended); 1393 } 1394 }, UserHandle.ALL, suspendPackagesFilter, null, null); 1395 1396 // Get persisted window scale setting 1397 mWindowAnimationScaleSetting = getWindowAnimationScaleSetting(); 1398 mTransitionAnimationScaleSetting = getTransitionAnimationScaleSetting(); 1399 1400 setAnimatorDurationScale(getAnimatorDurationScaleSetting()); 1401 1402 mForceDesktopModeOnExternalDisplays = Settings.Global.getInt(resolver, 1403 DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0; 1404 1405 final String displaySettingsPath = Settings.Global.getString(resolver, 1406 DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH); 1407 mDisplayWindowSettingsProvider = displayWindowSettingsProvider; 1408 if (displaySettingsPath != null) { 1409 mDisplayWindowSettingsProvider.setBaseSettingsFilePath(displaySettingsPath); 1410 } 1411 mDisplayWindowSettings = new DisplayWindowSettings(this, mDisplayWindowSettingsProvider); 1412 1413 IntentFilter filter = new IntentFilter(); 1414 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 1415 filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 1416 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); 1417 1418 mLatencyTracker = LatencyTracker.getInstance(context); 1419 1420 mSettingsObserver = new SettingsObserver(); 1421 1422 mSurfaceAnimationRunner = new SurfaceAnimationRunner(mTransactionFactory, 1423 mPowerManagerInternal); 1424 1425 mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean( 1426 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout); 1427 1428 mDragDropController = new DragDropController(this, mH.getLooper()); 1429 1430 mHighRefreshRateDenylist = HighRefreshRateDenylist.create(context.getResources()); 1431 1432 mConstants = new WindowManagerConstants(this, DeviceConfigInterface.REAL); 1433 mConstants.start(new HandlerExecutor(mH)); 1434 1435 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 1436 LocalServices.addService( 1437 ImeTargetVisibilityPolicy.class, new ImeTargetVisibilityPolicyImpl()); 1438 mEmbeddedWindowController = new EmbeddedWindowController(mAtmService, inputManager); 1439 1440 mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources( 1441 mContext.getResources()); 1442 1443 mDisplayHashController = new DisplayHashController(mContext); 1444 setGlobalShadowSettings(); 1445 mAnrController = new AnrController(this); 1446 mStartingSurfaceController = new StartingSurfaceController(this); 1447 mPresentationController = new PresentationController(); 1448 1449 mBlurController = new BlurController(mContext, mPowerManager); 1450 mTaskFpsCallbackController = new TaskFpsCallbackController(); 1451 mAccessibilityController = new AccessibilityController(this); 1452 mScreenRecordingCallbackController = new ScreenRecordingCallbackController(this); 1453 mSystemPerformanceHinter = new SystemPerformanceHinter(mContext, displayId -> { 1454 synchronized (mGlobalLock) { 1455 DisplayContent dc = mRoot.getDisplayContent(displayId); 1456 return (dc == null) ? null : dc.getSurfaceControl(); 1457 } 1458 }, mTransactionFactory); 1459 mSystemPerformanceHinter.mTraceTag = TRACE_TAG_WINDOW_MANAGER; 1460 1461 if (Flags.condenseConfigurationChangeForSimpleMode()) { 1462 LocalServices.addService( 1463 ConfigurationChangeSetting.ConfigurationChangeSettingInternal.class, 1464 new ConfigurationChangeSettingInternalImpl()); 1465 } 1466 } 1467 getDisplayAreaPolicyProvider()1468 DisplayAreaPolicy.Provider getDisplayAreaPolicyProvider() { 1469 return mDisplayAreaPolicyProvider; 1470 } 1471 setGlobalShadowSettings()1472 private void setGlobalShadowSettings() { 1473 final TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0); 1474 float lightY = a.getDimension(R.styleable.Lighting_lightY, 0); 1475 float lightZ = a.getDimension(R.styleable.Lighting_lightZ, 0); 1476 float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0); 1477 float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0); 1478 float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0); 1479 a.recycle(); 1480 float[] ambientColor = {0.f, 0.f, 0.f, ambientShadowAlpha}; 1481 float[] spotColor = {0.f, 0.f, 0.f, spotShadowAlpha}; 1482 SurfaceControl.setGlobalShadowSettings(ambientColor, spotColor, lightY, lightZ, 1483 lightRadius); 1484 } 1485 getTransitionAnimationScaleSetting()1486 private float getTransitionAnimationScaleSetting() { 1487 return fixScale(Settings.Global.getFloat(mContext.getContentResolver(), 1488 Settings.Global.TRANSITION_ANIMATION_SCALE, mContext.getResources().getFloat( 1489 R.dimen.config_appTransitionAnimationDurationScaleDefault))); 1490 } 1491 getAnimatorDurationScaleSetting()1492 private float getAnimatorDurationScaleSetting() { 1493 return fixScale(Settings.Global.getFloat(mContext.getContentResolver(), 1494 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 1495 } 1496 getWindowAnimationScaleSetting()1497 private float getWindowAnimationScaleSetting() { 1498 return fixScale(Settings.Global.getFloat(mContext.getContentResolver(), 1499 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting)); 1500 } 1501 1502 /** 1503 * Called after all entities (such as the {@link ActivityManagerService}) have been set up and 1504 * associated with the {@link WindowManagerService}. 1505 */ onInitReady()1506 public void onInitReady() { 1507 initPolicy(); 1508 1509 // Add ourself to the Watchdog monitors. 1510 Watchdog.getInstance().addMonitor(this); 1511 createWatermark(); 1512 showEmulatorDisplayOverlayIfNeeded(); 1513 } 1514 getInputManagerCallback()1515 public InputManagerCallback getInputManagerCallback() { 1516 return mInputManagerCallback; 1517 } 1518 1519 @Override onTransact(int code, Parcel data, Parcel reply, int flags)1520 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 1521 throws RemoteException { 1522 try { 1523 return super.onTransact(code, data, reply, flags); 1524 } catch (RuntimeException e) { 1525 // The window manager only throws security exceptions, so let's 1526 // log all others. 1527 if (!(e instanceof SecurityException)) { 1528 ProtoLog.wtf(WM_ERROR, "Window Manager Crash %s", e); 1529 } 1530 throw e; 1531 } 1532 } 1533 addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility, int displayId, int requestUserId, @InsetsType int requestedVisibleTypes, InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame, float[] outSizeCompatScale)1534 public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility, 1535 int displayId, int requestUserId, @InsetsType int requestedVisibleTypes, 1536 InputChannel outInputChannel, InsetsState outInsetsState, 1537 InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame, 1538 float[] outSizeCompatScale) { 1539 outActiveControls.set(null, false /* copyControls */); 1540 int[] appOp = new int[1]; 1541 final boolean isRoundedCornerOverlay = (attrs.privateFlags 1542 & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0; 1543 int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName, 1544 appOp, displayId); 1545 if (res != ADD_OKAY) { 1546 return res; 1547 } 1548 1549 WindowState parentWindow = null; 1550 final int callingUid = Binder.getCallingUid(); 1551 final int callingPid = Binder.getCallingPid(); 1552 final long origId = Binder.clearCallingIdentity(); 1553 final int type = attrs.type; 1554 1555 synchronized (mGlobalLock) { 1556 if (!mDisplayReady) { 1557 throw new IllegalStateException("Display has not been initialialized"); 1558 } 1559 if (session.isClientDead()) { 1560 ProtoLog.w(WM_ERROR, "Attempted to add window with a client %s " 1561 + "that is dead. Aborting.", session); 1562 return WindowManagerGlobal.ADD_APP_EXITING; 1563 } 1564 1565 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 1566 parentWindow = windowForClientLocked(null, attrs.token, false); 1567 if (parentWindow == null) { 1568 ProtoLog.w(WM_ERROR, "Attempted to add window with token that is not a window: " 1569 + "%s. Aborting.", attrs.token); 1570 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 1571 } 1572 if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW 1573 && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) { 1574 ProtoLog.w(WM_ERROR, "Attempted to add window with token that is a sub-window: " 1575 + "%s. Aborting.", attrs.token); 1576 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 1577 } 1578 } 1579 final DisplayContent displayContent = parentWindow != null 1580 ? parentWindow.mDisplayContent 1581 : getDisplayContentOrCreate(displayId, attrs.token); 1582 1583 if (displayContent == null) { 1584 ProtoLog.w(WM_ERROR, "Attempted to add window to a display that does " 1585 + "not exist: %d. Aborting.", displayId); 1586 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1587 } 1588 if (!displayContent.hasAccess(session.mUid)) { 1589 ProtoLog.w(WM_ERROR, 1590 "Attempted to add window to a display for which the application " 1591 + "does not have access: %d. Aborting.", 1592 displayContent.getDisplayId()); 1593 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1594 } 1595 1596 if (mWindowMap.containsKey(client.asBinder())) { 1597 ProtoLog.w(WM_ERROR, "Window %s is already added", client); 1598 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 1599 } 1600 1601 if (type == TYPE_PRIVATE_PRESENTATION 1602 && !mPresentationController.canPresent(null /*win*/, displayContent, type, 1603 callingUid)) { 1604 ProtoLog.w(WM_ERROR, 1605 "Attempted to add private presentation window to a non-private display. " 1606 + "Aborting."); 1607 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 1608 } 1609 1610 if (type == TYPE_PRESENTATION 1611 && !mPresentationController.canPresent(null /*win*/, displayContent, type, 1612 callingUid)) { 1613 ProtoLog.w(WM_ERROR, 1614 "Attempted to add presentation window to a non-suitable display. " 1615 + "Aborting."); 1616 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1617 } 1618 1619 int userId = UserHandle.getUserId(session.mUid); 1620 if (requestUserId != userId) { 1621 try { 1622 mAmInternal.handleIncomingUser(callingPid, callingUid, requestUserId, 1623 false /*allowAll*/, ALLOW_NON_FULL, null, null); 1624 } catch (Exception exp) { 1625 ProtoLog.w(WM_ERROR, "Trying to add window with invalid user=%d", 1626 requestUserId); 1627 return WindowManagerGlobal.ADD_INVALID_USER; 1628 } 1629 // It's fine to use this userId 1630 userId = requestUserId; 1631 } 1632 1633 ActivityRecord activity = null; 1634 final boolean hasParent = parentWindow != null; 1635 // Use existing parent window token for child windows since they go in the same token 1636 // as there parent window so we can apply the same policy on them. 1637 WindowToken token = displayContent.getWindowToken( 1638 hasParent ? parentWindow.mAttrs.token : attrs.token); 1639 // If this is a child window, we want to apply the same type checking rules as the 1640 // parent window type. 1641 final int rootType = hasParent ? parentWindow.mAttrs.type : type; 1642 1643 boolean addToastWindowRequiresToken = false; 1644 1645 final IBinder windowContextToken = attrs.mWindowContextToken; 1646 1647 if (token == null) { 1648 if (!unprivilegedAppCanCreateTokenWith(parentWindow, callingUid, type, 1649 rootType, attrs.token, attrs.packageName)) { 1650 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1651 } 1652 if (hasParent) { 1653 // Use existing parent window token for child windows. 1654 token = parentWindow.mToken; 1655 } else if (mWindowContextListenerController.hasListener(windowContextToken)) { 1656 // Respect the window context token if the user provided it. 1657 final IBinder binder = attrs.token != null ? attrs.token : windowContextToken; 1658 final Bundle options = mWindowContextListenerController 1659 .getOptions(windowContextToken); 1660 token = new WindowToken.Builder(this, binder, type) 1661 .setDisplayContent(displayContent) 1662 .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow) 1663 .setRoundedCornerOverlay(isRoundedCornerOverlay) 1664 .setFromClientToken(true) 1665 .setOptions(options) 1666 .build(); 1667 } else { 1668 final IBinder binder = attrs.token != null ? attrs.token : client.asBinder(); 1669 token = new WindowToken.Builder(this, binder, type) 1670 .setDisplayContent(displayContent) 1671 .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow) 1672 .setRoundedCornerOverlay(isRoundedCornerOverlay) 1673 .build(); 1674 } 1675 } else if (rootType >= FIRST_APPLICATION_WINDOW 1676 && rootType <= LAST_APPLICATION_WINDOW) { 1677 activity = token.asActivityRecord(); 1678 if (activity == null) { 1679 ProtoLog.w(WM_ERROR, "Attempted to add window with non-application token " 1680 + ".%s Aborting.", token); 1681 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 1682 } else if (activity.getParent() == null) { 1683 ProtoLog.w(WM_ERROR, "Attempted to add window with exiting application token " 1684 + ".%s Aborting.", token); 1685 return WindowManagerGlobal.ADD_APP_EXITING; 1686 } else if (type == TYPE_APPLICATION_STARTING) { 1687 if (activity.mStartingWindow != null) { 1688 ProtoLog.w(WM_ERROR, "Attempted to add starting window to " 1689 + "token with already existing starting window"); 1690 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 1691 } 1692 if (activity.mStartingData == null) { 1693 ProtoLog.w(WM_ERROR, "Attempted to add starting window to " 1694 + "token but already cleaned"); 1695 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 1696 } 1697 } 1698 } else if (rootType == TYPE_INPUT_METHOD) { 1699 if (token.windowType != TYPE_INPUT_METHOD) { 1700 ProtoLog.w(WM_ERROR, "Attempted to add input method window with bad token " 1701 + "%s. Aborting.", attrs.token); 1702 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1703 } 1704 } else if (rootType == TYPE_VOICE_INTERACTION) { 1705 if (token.windowType != TYPE_VOICE_INTERACTION) { 1706 ProtoLog.w(WM_ERROR, "Attempted to add voice interaction window with bad token " 1707 + "%s. Aborting.", attrs.token); 1708 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1709 } 1710 } else if (rootType == TYPE_WALLPAPER) { 1711 if (token.windowType != TYPE_WALLPAPER) { 1712 ProtoLog.w(WM_ERROR, "Attempted to add wallpaper window with bad token " 1713 + "%s. Aborting.", attrs.token); 1714 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1715 } 1716 } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) { 1717 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) { 1718 ProtoLog.w(WM_ERROR, 1719 "Attempted to add Accessibility overlay window with bad token " 1720 + "%s. Aborting.", attrs.token); 1721 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1722 } 1723 } else if (type == TYPE_TOAST) { 1724 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows. 1725 addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName, 1726 callingUid, parentWindow); 1727 if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) { 1728 ProtoLog.w(WM_ERROR, "Attempted to add a toast window with bad token " 1729 + "%s. Aborting.", attrs.token); 1730 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1731 } 1732 } else if (type == TYPE_QS_DIALOG) { 1733 if (token.windowType != TYPE_QS_DIALOG) { 1734 ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with bad token " 1735 + "%s. Aborting.", attrs.token); 1736 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1737 } 1738 } else if (token.asActivityRecord() != null) { 1739 ProtoLog.w(WM_ERROR, "Non-null activity for system window of rootType=%d", 1740 rootType); 1741 // It is not valid to use an app token with other system types; we will 1742 // instead make a new token for it (as if null had been passed in for the token). 1743 attrs.token = null; 1744 token = new WindowToken.Builder(this, client.asBinder(), type) 1745 .setDisplayContent(displayContent) 1746 .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow) 1747 .build(); 1748 } 1749 1750 final WindowState win = new WindowState(this, session, client, token, parentWindow, 1751 appOp[0], attrs, viewVisibility, session.mUid, userId, 1752 session.mCanAddInternalSystemWindow); 1753 final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy(); 1754 displayPolicy.adjustWindowParamsLw(win, win.mAttrs); 1755 attrs.flags = sanitizeFlagSlippery(attrs.flags, win.getName(), callingUid, callingPid); 1756 attrs.inputFeatures = sanitizeInputFeatures(attrs.inputFeatures, win.getName(), 1757 callingUid, callingPid, win.isTrustedOverlay()); 1758 win.setRequestedVisibleTypes(requestedVisibleTypes); 1759 1760 res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid); 1761 if (res != ADD_OKAY) { 1762 return res; 1763 } 1764 1765 final boolean openInputChannels = (outInputChannel != null 1766 && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0); 1767 if (openInputChannels) { 1768 win.openInputChannel(outInputChannel); 1769 } 1770 1771 // If adding a toast requires a token for this app we always schedule hiding 1772 // toast windows to make sure they don't stick around longer then necessary. 1773 // We hide instead of remove such windows as apps aren't prepared to handle 1774 // windows being removed under them. 1775 // 1776 // If the app is older it can add toasts without a token and hence overlay 1777 // other apps. To be maximally compatible with these apps we will hide the 1778 // window after the toast timeout only if the focused window is from another 1779 // UID, otherwise we allow unlimited duration. When a UID looses focus we 1780 // schedule hiding all of its toast windows. 1781 if (type == TYPE_TOAST) { 1782 if (!displayContent.canAddToastWindowForUid(callingUid)) { 1783 ProtoLog.w(WM_ERROR, "Adding more than one toast window for UID at a time."); 1784 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 1785 } 1786 // Make sure this happens before we moved focus as one can make the 1787 // toast focusable to force it not being hidden after the timeout. 1788 // Focusable toasts are always timed out to prevent a focused app to 1789 // show a focusable toasts while it has focus which will be kept on 1790 // the screen after the activity goes away. 1791 if (addToastWindowRequiresToken 1792 || (attrs.flags & FLAG_NOT_FOCUSABLE) == 0 1793 || displayContent.mCurrentFocus == null 1794 || displayContent.mCurrentFocus.mOwnerUid != callingUid) { 1795 mH.sendMessageDelayed( 1796 mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win), 1797 win.mAttrs.hideTimeoutMilliseconds); 1798 } 1799 } 1800 1801 // Switch to listen to the {@link WindowToken token}'s configuration changes when 1802 // adding a window to the window context. Filter sub window type here because the sub 1803 // window must be attached to the parent window, which is attached to the window context 1804 // created window token. 1805 if (!win.isChildWindow() 1806 && mWindowContextListenerController.hasListener(windowContextToken)) { 1807 final int windowContextType = mWindowContextListenerController 1808 .getWindowType(windowContextToken); 1809 final Bundle options = mWindowContextListenerController 1810 .getOptions(windowContextToken); 1811 if (type != windowContextType) { 1812 ProtoLog.w(WM_ERROR, "Window types in WindowContext and" 1813 + " LayoutParams.type should match! Type from LayoutParams is %d," 1814 + " but type from WindowContext is %d", type, windowContextType); 1815 // We allow WindowProviderService to add window other than windowContextType, 1816 // but the WindowProviderService won't be associated with the window's 1817 // WindowToken. 1818 if (!isWindowProviderService(options)) { 1819 return WindowManagerGlobal.ADD_INVALID_TYPE; 1820 } 1821 } else { 1822 mWindowContextListenerController.updateContainerForWindowContextListener( 1823 windowContextToken, token); 1824 } 1825 } 1826 1827 // From now on, no exceptions or errors allowed! 1828 if (displayContent.mCurrentFocus == null) { 1829 displayContent.mWinAddedSinceNullFocus.add(win); 1830 } 1831 1832 win.mSession.onWindowAdded(win); 1833 mWindowMap.put(client.asBinder(), win); 1834 win.initAppOpsState(); 1835 1836 final boolean suspended = mPmInternal.isPackageSuspended(win.getOwningPackage(), 1837 UserHandle.getUserId(win.getOwningUid())); 1838 win.setHiddenWhileSuspended(suspended); 1839 1840 final boolean hideSystemAlertWindows = shouldHideNonSystemOverlayWindow(win); 1841 win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows); 1842 1843 // Only a presentation window needs a transition because its visibility affets the 1844 // lifecycle of apps below (b/390481865). 1845 if (enablePresentationForConnectedDisplays() && win.isPresentation()) { 1846 final boolean wasTransitionOnDisplay = 1847 win.mTransitionController.isCollectingTransitionOnDisplay(displayContent); 1848 Transition newlyCreatedTransition = null; 1849 if (!win.mTransitionController.isCollecting()) { 1850 newlyCreatedTransition = 1851 win.mTransitionController.createAndStartCollecting(TRANSIT_OPEN); 1852 } 1853 win.mTransitionController.collect(win.mToken); 1854 res |= addWindowInner(win, displayPolicy, activity, displayContent, outInsetsState, 1855 outAttachedFrame, outActiveControls, client, outSizeCompatScale, attrs, 1856 callingUid); 1857 // A presentation hides all activities behind on the same display. 1858 win.mDisplayContent.ensureActivitiesVisible(/*starting=*/ null, 1859 /*notifyClients=*/ true); 1860 if (!wasTransitionOnDisplay && win.mTransitionController 1861 .isCollectingTransitionOnDisplay(displayContent)) { 1862 // Set the display ready only when the display gets added to the collecting 1863 // transition in this operation. 1864 win.mTransitionController.setReady(win.mToken); 1865 } 1866 if (newlyCreatedTransition != null) { 1867 win.mTransitionController.requestStartTransition(newlyCreatedTransition, null, 1868 null /* remoteTransition */, null /* displayChange */); 1869 } 1870 } else { 1871 res |= addWindowInner(win, displayPolicy, activity, displayContent, outInsetsState, 1872 outAttachedFrame, outActiveControls, client, outSizeCompatScale, attrs, 1873 callingUid); 1874 } 1875 } 1876 1877 Binder.restoreCallingIdentity(origId); 1878 1879 return res; 1880 } 1881 addWindowInner(@onNull WindowState win, @NonNull DisplayPolicy displayPolicy, @NonNull ActivityRecord activity, @NonNull DisplayContent displayContent, @NonNull InsetsState outInsetsState, @NonNull Rect outAttachedFrame, @NonNull InsetsSourceControl.Array outActiveControls, @NonNull IWindow client, @NonNull float[] outSizeCompatScale, @NonNull LayoutParams attrs, int uid)1882 private int addWindowInner(@NonNull WindowState win, @NonNull DisplayPolicy displayPolicy, 1883 @NonNull ActivityRecord activity, @NonNull DisplayContent displayContent, 1884 @NonNull InsetsState outInsetsState, @NonNull Rect outAttachedFrame, 1885 @NonNull InsetsSourceControl.Array outActiveControls, @NonNull IWindow client, 1886 @NonNull float[] outSizeCompatScale, @NonNull LayoutParams attrs, int uid) { 1887 int res = 0; 1888 final int type = attrs.type; 1889 boolean imMayMove = true; 1890 1891 win.mToken.addWindow(win); 1892 displayPolicy.addWindowLw(win, attrs); 1893 displayPolicy.setDropInputModePolicy(win, win.mAttrs); 1894 if (type == TYPE_APPLICATION_STARTING && activity != null) { 1895 activity.attachStartingWindow(win); 1896 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s", 1897 activity, win); 1898 } else if (type == TYPE_INPUT_METHOD 1899 // IME window is always touchable. 1900 // Ignore non-touchable windows e.g. Stylus InkWindow.java. 1901 && (win.mAttrs.flags & FLAG_NOT_TOUCHABLE) == 0) { 1902 displayContent.setInputMethodWindowLocked(win); 1903 imMayMove = false; 1904 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 1905 displayContent.computeImeTarget(true /* updateImeTarget */); 1906 imMayMove = false; 1907 } else { 1908 if (type == TYPE_WALLPAPER) { 1909 displayContent.mWallpaperController.clearLastWallpaperTimeoutTime(); 1910 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1911 } else if (win.hasWallpaper()) { 1912 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1913 } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) { 1914 // If there is currently a wallpaper being shown, and 1915 // the base layer of the new window is below the current 1916 // layer of the target window, then adjust the wallpaper. 1917 // This is to avoid a new window being placed between the 1918 // wallpaper and its target. 1919 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1920 } 1921 } 1922 1923 final WindowStateAnimator winAnimator = win.mWinAnimator; 1924 winAnimator.mEnterAnimationPending = true; 1925 winAnimator.mEnteringAnimation = true; 1926 1927 if (displayPolicy.areSystemBarsForcedConsumedLw()) { 1928 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS; 1929 } 1930 if (displayContent.isInTouchMode()) { 1931 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 1932 } 1933 if (win.mActivityRecord == null || win.mActivityRecord.isClientVisible()) { 1934 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 1935 } 1936 1937 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw(); 1938 1939 boolean focusChanged = false; 1940 if (win.canReceiveKeys()) { 1941 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 1942 false /*updateInputWindows*/); 1943 if (focusChanged) { 1944 imMayMove = false; 1945 } 1946 } 1947 1948 if (imMayMove) { 1949 displayContent.computeImeTarget(true /* updateImeTarget */); 1950 if (win.isImeOverlayLayeringTarget()) { 1951 dispatchImeTargetOverlayVisibilityChanged(client.asBinder(), win.mAttrs.type, 1952 win.isVisibleRequestedOrAdding(), false /* removed */, 1953 displayContent.getDisplayId()); 1954 } 1955 } 1956 1957 // Don't do layout here, the window must call 1958 // relayout to be displayed, so we'll do it there. 1959 if (win.mActivityRecord != null && win.mActivityRecord.isEmbedded()) { 1960 // Assign child layers from the parent Task if the Activity is embedded. 1961 win.getTask().assignChildLayers(); 1962 } else { 1963 win.getParent().assignChildLayers(); 1964 } 1965 1966 if (focusChanged) { 1967 displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus, 1968 false /*updateInputWindows*/); 1969 } 1970 displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/); 1971 1972 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addWindow: New client %s" 1973 + ": window=%s Callers=%s", client.asBinder(), win, Debug.getCallers(5)); 1974 1975 boolean needToSendNewConfiguration = 1976 win.isVisibleRequestedOrAdding() && displayContent.updateOrientation(); 1977 if (win.providesDisplayDecorInsets()) { 1978 needToSendNewConfiguration |= displayPolicy.updateDecorInsetsInfo(); 1979 } 1980 if (needToSendNewConfiguration) { 1981 displayContent.sendNewConfiguration(); 1982 } 1983 1984 // This window doesn't have a frame yet. Don't let this window cause the insets change. 1985 displayContent.getInsetsStateController().updateAboveInsetsState( 1986 false /* notifyInsetsChanged */); 1987 1988 win.fillInsetsState(outInsetsState, true /* copySources */); 1989 getInsetsSourceControls(win, outActiveControls); 1990 1991 if (win.mLayoutAttached) { 1992 outAttachedFrame.set(win.getParentWindow().getFrame()); 1993 if (win.mInvGlobalScale != 1f) { 1994 outAttachedFrame.scale(win.mInvGlobalScale); 1995 } 1996 } else { 1997 // Make this invalid which indicates a null attached frame. 1998 outAttachedFrame.set(0, 0, -1, -1); 1999 } 2000 outSizeCompatScale[0] = win.getCompatScaleForClient(); 2001 2002 if (res >= ADD_OKAY && win.isPresentation()) { 2003 mPresentationController.onPresentationAdded(win, uid); 2004 } 2005 2006 return res; 2007 } 2008 unprivilegedAppCanCreateTokenWith(WindowState parentWindow, int callingUid, int type, int rootType, IBinder tokenForLog, String packageName)2009 private boolean unprivilegedAppCanCreateTokenWith(WindowState parentWindow, 2010 int callingUid, int type, int rootType, IBinder tokenForLog, String packageName) { 2011 if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) { 2012 ProtoLog.w(WM_ERROR, "Attempted to add application window with unknown token " 2013 + "%s. Aborting.", tokenForLog); 2014 return false; 2015 } 2016 if (rootType == TYPE_INPUT_METHOD) { 2017 ProtoLog.w(WM_ERROR, "Attempted to add input method window with unknown token " 2018 + "%s. Aborting.", tokenForLog); 2019 return false; 2020 } 2021 if (rootType == TYPE_VOICE_INTERACTION) { 2022 ProtoLog.w(WM_ERROR, 2023 "Attempted to add voice interaction window with unknown token " 2024 + "%s. Aborting.", tokenForLog); 2025 return false; 2026 } 2027 if (rootType == TYPE_WALLPAPER) { 2028 ProtoLog.w(WM_ERROR, "Attempted to add wallpaper window with unknown token " 2029 + "%s. Aborting.", tokenForLog); 2030 return false; 2031 } 2032 if (rootType == TYPE_QS_DIALOG) { 2033 ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with unknown token " 2034 + "%s. Aborting.", tokenForLog); 2035 return false; 2036 } 2037 if (rootType == TYPE_ACCESSIBILITY_OVERLAY) { 2038 ProtoLog.w(WM_ERROR, 2039 "Attempted to add Accessibility overlay window with unknown token " 2040 + "%s. Aborting.", tokenForLog); 2041 return false; 2042 } 2043 if (type == TYPE_TOAST) { 2044 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows. 2045 if (doesAddToastWindowRequireToken(packageName, callingUid, parentWindow)) { 2046 ProtoLog.w(WM_ERROR, "Attempted to add a toast window with unknown token " 2047 + "%s. Aborting.", tokenForLog); 2048 return false; 2049 } 2050 } 2051 return true; 2052 } 2053 2054 /** 2055 * Get existing {@link DisplayContent} or create a new one if the display is registered in 2056 * DisplayManager. 2057 * 2058 * NOTE: This should only be used in cases when there is a chance that a {@link DisplayContent} 2059 * that corresponds to a display just added to DisplayManager has not yet been created. This 2060 * usually means that the call of this method was initiated from outside of Activity or Window 2061 * Manager. In most cases the regular getter should be used. 2062 * @param displayId The preferred display Id. 2063 * @param token The window token associated with the window we are trying to get display for. 2064 * if not null then the display of the window token will be returned. Set to null 2065 * is there isn't an a token associated with the request. 2066 * @see RootWindowContainer#getDisplayContent(int) 2067 */ getDisplayContentOrCreate(int displayId, IBinder token)2068 private DisplayContent getDisplayContentOrCreate(int displayId, IBinder token) { 2069 if (token != null) { 2070 final WindowToken wToken = mRoot.getWindowToken(token); 2071 if (wToken != null) { 2072 return wToken.getDisplayContent(); 2073 } 2074 } 2075 2076 return mRoot.getDisplayContentOrCreate(displayId); 2077 } 2078 doesAddToastWindowRequireToken(String packageName, int callingUid, WindowState attachedWindow)2079 private boolean doesAddToastWindowRequireToken(String packageName, int callingUid, 2080 WindowState attachedWindow) { 2081 // Try using the target SDK of the root window 2082 if (attachedWindow != null) { 2083 return attachedWindow.mActivityRecord != null 2084 && attachedWindow.mActivityRecord.mTargetSdk >= Build.VERSION_CODES.O; 2085 } else { 2086 // Otherwise, look at the package 2087 final ApplicationInfo appInfo = mPmInternal.getApplicationInfo( 2088 packageName, 0 /* flags */, SYSTEM_UID, UserHandle.getUserId(callingUid)); 2089 if (appInfo == null 2090 || !mPmInternal.isSameApp( 2091 packageName, callingUid, UserHandle.getUserId(callingUid))) { 2092 throw new SecurityException("Package " + packageName + " not in UID " 2093 + callingUid); 2094 } 2095 return appInfo.targetSdkVersion >= Build.VERSION_CODES.O; 2096 } 2097 } 2098 shouldHideNonSystemOverlayWindow(WindowState win)2099 private boolean shouldHideNonSystemOverlayWindow(WindowState win) { 2100 if (!Flags.fixHideOverlayApi()) { 2101 return !mHidingNonSystemOverlayWindows.isEmpty(); 2102 } 2103 2104 if (mHidingNonSystemOverlayWindows.isEmpty()) { 2105 return false; 2106 } 2107 2108 if (mHidingNonSystemOverlayWindowsCountPerUid.size() == 1 2109 && mHidingNonSystemOverlayWindowsCountPerUid.containsKey(win.getOwningUid())) { 2110 return false; 2111 } 2112 return true; 2113 } 2114 2115 /** 2116 * Set whether screen capture is disabled for all windows of a specific user from 2117 * the device policy cache, or specific windows based on sensitive content protections. 2118 */ 2119 @Override refreshScreenCaptureDisabled()2120 public void refreshScreenCaptureDisabled() { 2121 int callingUid = Binder.getCallingUid(); 2122 // MY_UID (Process.myUid()) should always be SYSTEM_UID here, but using MY_UID for tests 2123 if (callingUid != MY_UID) { 2124 throw new SecurityException("Only system can call refreshScreenCaptureDisabled."); 2125 } 2126 2127 synchronized (mGlobalLock) { 2128 // Refresh secure surface for all windows. 2129 mRoot.refreshSecureSurfaceState(); 2130 } 2131 } 2132 removeClientToken(Session session, IBinder client)2133 void removeClientToken(Session session, IBinder client) { 2134 synchronized (mGlobalLock) { 2135 WindowState win = windowForClientLocked(session, client, false); 2136 if (win != null) { 2137 win.removeIfPossible(); 2138 return; 2139 } 2140 2141 // Remove embedded window map if the token belongs to an embedded window 2142 mEmbeddedWindowController.remove(client); 2143 } 2144 } 2145 2146 /** 2147 * Performs some centralized bookkeeping clean-up on the window that is being removed. 2148 * NOTE: Should only be called from {@link WindowState#removeImmediately()} 2149 * TODO: Maybe better handled with a method {@link WindowContainer#removeChild} if we can 2150 * figure-out a good way to have all parents of a WindowState doing the same thing without 2151 * forgetting to add the wiring when a new parent of WindowState is added. 2152 */ postWindowRemoveCleanupLocked(WindowState win)2153 void postWindowRemoveCleanupLocked(WindowState win) { 2154 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "postWindowRemoveCleanupLocked: %s", win); 2155 final IBinder client = win.mClient.asBinder(); 2156 mWindowMap.remove(client); 2157 if (sensitiveContentAppProtection()) { 2158 notifyWindowRemovedListeners(client); 2159 } 2160 2161 final DisplayContent dc = win.getDisplayContent(); 2162 2163 win.resetAppOpsState(); 2164 2165 if (dc.mCurrentFocus == null) { 2166 dc.mWinRemovedSinceNullFocus.add(win); 2167 } 2168 mEmbeddedWindowController.onWindowRemoved(win); 2169 mResizingWindows.remove(win); 2170 updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */); 2171 mWindowsChanged = true; 2172 ProtoLog.v(WM_DEBUG_WINDOW_MOVEMENT, "Final remove of window: %s", win); 2173 2174 final DisplayContent displayContent = win.getDisplayContent(); 2175 if (displayContent.mInputMethodWindow == win) { 2176 displayContent.setInputMethodWindowLocked(null); 2177 } 2178 2179 final WindowToken token = win.mToken; 2180 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Removing %s from %s", win, token); 2181 // Window will already be removed from token before this post clean-up method is called. 2182 if (token.isEmpty() && !token.mPersistOnEmpty) { 2183 token.removeIfPossible(); 2184 } 2185 2186 if (win.mActivityRecord != null) { 2187 win.mActivityRecord.postWindowRemoveStartingWindowCleanup(win); 2188 } 2189 2190 if (win.mAttrs.type == TYPE_WALLPAPER) { 2191 dc.mWallpaperController.clearLastWallpaperTimeoutTime(); 2192 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2193 } else if (dc.mWallpaperController.isWallpaperTarget(win)) { 2194 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2195 } 2196 2197 if (dc != null && !mWindowPlacerLocked.isInLayout()) { 2198 dc.assignWindowLayers(true /* setLayoutNeeded */); 2199 mWindowPlacerLocked.performSurfacePlacement(); 2200 if (win.mActivityRecord != null) { 2201 win.mActivityRecord.updateReportedVisibilityLocked(); 2202 } 2203 } 2204 2205 dc.getInputMonitor().updateInputWindowsLw(true /*force*/); 2206 } 2207 updateHiddenWhileSuspendedState(ArraySet<String> packages, boolean suspended)2208 private void updateHiddenWhileSuspendedState(ArraySet<String> packages, boolean suspended) { 2209 synchronized (mGlobalLock) { 2210 mRoot.updateHiddenWhileSuspendedState(packages, suspended); 2211 } 2212 } 2213 updateAppOpsState()2214 private void updateAppOpsState() { 2215 synchronized (mGlobalLock) { 2216 mRoot.updateAppOpsState(); 2217 } 2218 } 2219 logSurface(WindowState w, String msg, boolean withStackTrace)2220 static void logSurface(WindowState w, String msg, boolean withStackTrace) { 2221 String str = " SURFACE " + msg + ": " + w; 2222 if (withStackTrace) { 2223 logWithStack(TAG, str); 2224 } else { 2225 Slog.i(TAG_WM, str); 2226 } 2227 } 2228 logWithStack(String tag, String s)2229 static void logWithStack(String tag, String s) { 2230 RuntimeException e = null; 2231 if (SHOW_STACK_CRAWLS) { 2232 e = new RuntimeException(); 2233 e.fillInStackTrace(); 2234 } 2235 Slog.i(tag, s, e); 2236 } 2237 clearTouchableRegion(Session session, IWindow client)2238 void clearTouchableRegion(Session session, IWindow client) { 2239 final long origId = Binder.clearCallingIdentity(); 2240 try { 2241 synchronized (mGlobalLock) { 2242 WindowState w = windowForClientLocked(session, client, false); 2243 w.clearClientTouchableRegion(); 2244 } 2245 } finally { 2246 Binder.restoreCallingIdentity(origId); 2247 } 2248 } 2249 setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableRegion)2250 void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets, 2251 Rect visibleInsets, Region touchableRegion) { 2252 int uid = Binder.getCallingUid(); 2253 final long origId = Binder.clearCallingIdentity(); 2254 try { 2255 synchronized (mGlobalLock) { 2256 WindowState w = windowForClientLocked(session, client, false); 2257 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w 2258 + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets 2259 + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets 2260 + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion 2261 + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets); 2262 if (w != null) { 2263 final boolean wasGivenInsetsPending = w.mGivenInsetsPending; 2264 w.mGivenInsetsPending = false; 2265 if ((!wasGivenInsetsPending || !w.hasInsetsSourceProvider()) 2266 && w.mTouchableInsets == touchableInsets 2267 && w.mGivenContentInsets.equals(contentInsets) 2268 && w.mGivenVisibleInsets.equals(visibleInsets) 2269 && w.mGivenTouchableRegion.equals(touchableRegion)) { 2270 return; 2271 } 2272 w.mGivenContentInsets.set(contentInsets); 2273 w.mGivenVisibleInsets.set(visibleInsets); 2274 w.mGivenTouchableRegion.set(touchableRegion); 2275 w.mTouchableInsets = touchableInsets; 2276 if (w.mGlobalScale != 1) { 2277 w.mGivenContentInsets.scale(w.mGlobalScale); 2278 w.mGivenVisibleInsets.scale(w.mGlobalScale); 2279 w.mGivenTouchableRegion.scale(w.mGlobalScale); 2280 } 2281 w.setDisplayLayoutNeeded(); 2282 w.updateSourceFrame(w.getFrame()); 2283 mWindowPlacerLocked.performSurfacePlacement(); 2284 w.getDisplayContent().getInputMonitor().updateInputWindowsLw(true); 2285 2286 // We need to report touchable region changes to accessibility. 2287 if (mAccessibilityController.hasCallbacks()) { 2288 mAccessibilityController.onSomeWindowResizedOrMovedWithCallingUid( 2289 uid, w.getDisplayContent().getDisplayId()); 2290 } 2291 } 2292 } 2293 } finally { 2294 Binder.restoreCallingIdentity(origId); 2295 } 2296 } 2297 onRectangleOnScreenRequested(IBinder token, Rect rectangle)2298 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 2299 final AccessibilityController.AccessibilityControllerInternalImpl a11yControllerInternal = 2300 AccessibilityController.getAccessibilityControllerInternal(this); 2301 synchronized (mGlobalLock) { 2302 if (a11yControllerInternal.hasWindowManagerEventDispatcher()) { 2303 WindowState window = mWindowMap.get(token); 2304 if (window != null) { 2305 a11yControllerInternal.onRectangleOnScreenRequested( 2306 window.getDisplayId(), rectangle); 2307 } 2308 } 2309 } 2310 } 2311 getWindowId(IBinder token)2312 public IWindowId getWindowId(IBinder token) { 2313 synchronized (mGlobalLock) { 2314 WindowState window = mWindowMap.get(token); 2315 return window != null ? window.mWindowId : null; 2316 } 2317 } 2318 pokeDrawLock(Session session, IBinder token)2319 public void pokeDrawLock(Session session, IBinder token) { 2320 synchronized (mGlobalLock) { 2321 WindowState window = windowForClientLocked(session, token, false); 2322 if (window != null) { 2323 window.pokeDrawLockLw(mDrawLockTimeoutMillis); 2324 } 2325 } 2326 } 2327 hasStatusBarPermission(int pid, int uid)2328 private boolean hasStatusBarPermission(int pid, int uid) { 2329 return mContext.checkPermission(permission.STATUS_BAR, pid, uid) 2330 == PackageManager.PERMISSION_GRANTED; 2331 } 2332 2333 /** 2334 * Returns whether this window can proceed with drawing or needs to retry later. 2335 */ cancelDraw(Session session, IWindow client)2336 public boolean cancelDraw(Session session, IWindow client) { 2337 synchronized (mGlobalLock) { 2338 final WindowState win = windowForClientLocked(session, client, false); 2339 if (win == null) { 2340 return false; 2341 } 2342 2343 return win.cancelAndRedraw(); 2344 } 2345 } 2346 2347 /** Relayouts window. */ relayoutWindow(Session session, IWindow client, LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq, int lastSyncSeqId, WindowRelayoutResult outRelayoutResult)2348 public int relayoutWindow(Session session, IWindow client, LayoutParams attrs, 2349 int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq, 2350 int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) { 2351 final ClientWindowFrames outFrames; 2352 final MergedConfiguration outMergedConfiguration; 2353 final SurfaceControl outSurfaceControl; 2354 final InsetsState outInsetsState; 2355 final InsetsSourceControl.Array outActiveControls; 2356 if (outRelayoutResult != null) { 2357 outFrames = outRelayoutResult.frames; 2358 outMergedConfiguration = outRelayoutResult.mergedConfiguration; 2359 outSurfaceControl = outRelayoutResult.surfaceControl; 2360 outInsetsState = outRelayoutResult.insetsState; 2361 outActiveControls = outRelayoutResult.activeControls; 2362 } else { 2363 outFrames = null; 2364 outMergedConfiguration = null; 2365 outSurfaceControl = null; 2366 outInsetsState = null; 2367 outActiveControls = null; 2368 } 2369 2370 if (outActiveControls != null) { 2371 outActiveControls.set(null, false /* copyControls */); 2372 } 2373 int result = 0; 2374 boolean configChanged = false; 2375 final int pid = Binder.getCallingPid(); 2376 final int uid = Binder.getCallingUid(); 2377 final long origId = Binder.clearCallingIdentity(); 2378 synchronized (mGlobalLock) { 2379 final WindowState win = windowForClientLocked(session, client, false); 2380 if (win == null) { 2381 return 0; 2382 } 2383 if (win.mRelayoutSeq < seq) { 2384 win.mRelayoutSeq = seq; 2385 } else if (win.mRelayoutSeq > seq) { 2386 return 0; 2387 } 2388 2389 if (win.cancelAndRedraw() && win.mPrepareSyncSeqId <= lastSyncSeqId) { 2390 // The client has reported the sync draw, but we haven't finished it yet. 2391 // Don't let the client perform a non-sync draw at this time. 2392 result |= RELAYOUT_RES_CANCEL_AND_REDRAW; 2393 } 2394 2395 final DisplayContent displayContent = win.getDisplayContent(); 2396 final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy(); 2397 2398 WindowStateAnimator winAnimator = win.mWinAnimator; 2399 if (viewVisibility != View.GONE) { 2400 win.setRequestedSize(requestedWidth, requestedHeight); 2401 } 2402 2403 int attrChanges = 0; 2404 int flagChanges = 0; 2405 int privateFlagChanges = 0; 2406 if (attrs != null) { 2407 displayPolicy.adjustWindowParamsLw(win, attrs); 2408 attrs.flags = sanitizeFlagSlippery(attrs.flags, win.getName(), uid, pid); 2409 attrs.inputFeatures = sanitizeInputFeatures(attrs.inputFeatures, win.getName(), uid, 2410 pid, win.isTrustedOverlay()); 2411 int disableFlags = 2412 (attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility) & DISABLE_MASK; 2413 if (disableFlags != 0 && !hasStatusBarPermission(pid, uid)) { 2414 disableFlags = 0; 2415 } 2416 win.mDisableFlags = disableFlags; 2417 if (win.mAttrs.type != attrs.type) { 2418 throw new IllegalArgumentException( 2419 "Window type can not be changed after the window is added."); 2420 } 2421 if (!(win.mAttrs.providedInsets == null && attrs.providedInsets == null)) { 2422 if (win.mAttrs.providedInsets == null || attrs.providedInsets == null 2423 || (win.mAttrs.providedInsets.length != attrs.providedInsets.length)) { 2424 throw new IllegalArgumentException( 2425 "Insets amount can not be changed after the window is added."); 2426 } else { 2427 final int insetsTypes = attrs.providedInsets.length; 2428 for (int i = 0; i < insetsTypes; i++) { 2429 if (!win.mAttrs.providedInsets[i].idEquals(attrs.providedInsets[i])) { 2430 throw new IllegalArgumentException( 2431 "Insets ID can not be changed after the window is added."); 2432 } 2433 final InsetsFrameProvider.InsetsSizeOverride[] overrides = 2434 win.mAttrs.providedInsets[i].getInsetsSizeOverrides(); 2435 final InsetsFrameProvider.InsetsSizeOverride[] newOverrides = 2436 attrs.providedInsets[i].getInsetsSizeOverrides(); 2437 if (!(overrides == null && newOverrides == null)) { 2438 if (overrides == null || newOverrides == null 2439 || (overrides.length != newOverrides.length)) { 2440 throw new IllegalArgumentException( 2441 "Insets override types can not be changed after the " 2442 + "window is added."); 2443 } else { 2444 final int overrideTypes = overrides.length; 2445 for (int j = 0; j < overrideTypes; j++) { 2446 if (overrides[j].getWindowType() 2447 != newOverrides[j].getWindowType()) { 2448 throw new IllegalArgumentException( 2449 "Insets override types can not be changed after" 2450 + " the window is added."); 2451 } 2452 } 2453 } 2454 } 2455 } 2456 } 2457 } 2458 2459 final boolean wasTrustedOverlay = win.isWindowTrustedOverlay(); 2460 flagChanges = win.mAttrs.flags ^ attrs.flags; 2461 privateFlagChanges = win.mAttrs.privateFlags ^ attrs.privateFlags; 2462 attrChanges = win.mAttrs.copyFrom(attrs); 2463 final boolean layoutChanged = 2464 (attrChanges & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0; 2465 if (layoutChanged || (attrChanges 2466 & WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) { 2467 win.mLayoutNeeded = true; 2468 } 2469 if (layoutChanged && win.providesDisplayDecorInsets()) { 2470 configChanged = displayPolicy.updateDecorInsetsInfo(); 2471 } 2472 if (wasTrustedOverlay != win.isWindowTrustedOverlay()) { 2473 win.updateTrustedOverlay(); 2474 } 2475 if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0 2476 || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) { 2477 win.mActivityRecord.checkKeyguardFlagsChanged(); 2478 } 2479 2480 if ((privateFlagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) { 2481 updateNonSystemOverlayWindowsVisibilityIfNeeded( 2482 win, win.mWinAnimator.getShown()); 2483 } 2484 if (!setScPropertiesInClient()) { 2485 if ((attrChanges & (WindowManager.LayoutParams.PRIVATE_FLAGS_CHANGED)) != 0) { 2486 winAnimator.setColorSpaceAgnosticLocked((win.mAttrs.privateFlags 2487 & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) 2488 != 0); 2489 } 2490 } 2491 // See if the DisplayWindowPolicyController wants to keep the activity on the window 2492 if (displayContent.mDwpcHelper.hasController() 2493 && win.mActivityRecord != null && (!win.mRelayoutCalled || flagChanges != 0 2494 || privateFlagChanges != 0)) { 2495 int newOrChangedFlags = !win.mRelayoutCalled ? win.mAttrs.flags : flagChanges; 2496 int newOrChangedPrivateFlags = 2497 !win.mRelayoutCalled ? win.mAttrs.privateFlags : privateFlagChanges; 2498 2499 if (!displayContent.mDwpcHelper.keepActivityOnWindowFlagsChanged( 2500 win.mActivityRecord.info, newOrChangedFlags, newOrChangedPrivateFlags, 2501 win.mAttrs.flags, 2502 win.mAttrs.privateFlags)) { 2503 mH.sendMessage(mH.obtainMessage(H.REPARENT_TASK_TO_DEFAULT_DISPLAY, 2504 win.mActivityRecord.getTask())); 2505 Slog.w(TAG_WM, "Activity " + win.mActivityRecord + " window flag changed," 2506 + " can't remain on display " + displayContent.getDisplayId()); 2507 return 0; 2508 } 2509 } 2510 } 2511 2512 if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility 2513 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs); 2514 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { 2515 winAnimator.mAlpha = attrs.alpha; 2516 } 2517 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight); 2518 2519 if (win.mAttrs.surfaceInsets.left != 0 2520 || win.mAttrs.surfaceInsets.top != 0 2521 || win.mAttrs.surfaceInsets.right != 0 2522 || win.mAttrs.surfaceInsets.bottom != 0) { 2523 winAnimator.setOpaqueLocked(false); 2524 } 2525 2526 final int oldVisibility = win.mViewVisibility; 2527 2528 // If the window is becoming visible, visibleOrAdding may change which may in turn 2529 // change the IME target. 2530 final boolean becameVisible = 2531 (oldVisibility == View.INVISIBLE || oldVisibility == View.GONE) 2532 && viewVisibility == View.VISIBLE; 2533 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0 2534 || becameVisible; 2535 boolean focusMayChange = win.mViewVisibility != viewVisibility 2536 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0) 2537 || (!win.mRelayoutCalled); 2538 2539 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility 2540 && win.hasWallpaper(); 2541 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0; 2542 if ((flagChanges & FLAG_SECURE) != 0) { 2543 win.setSecureLocked(win.isSecureLocked()); 2544 } 2545 2546 final boolean wasVisible = win.isVisible(); 2547 2548 win.mRelayoutCalled = true; 2549 win.mInRelayout = true; 2550 2551 win.setViewVisibility(viewVisibility); 2552 ProtoLog.i(WM_DEBUG_SCREEN_ON, 2553 "Relayout %s: oldVis=%d newVis=%d. %s", win, oldVisibility, 2554 viewVisibility, new RuntimeException().fillInStackTrace()); 2555 if (becameVisible) { 2556 onWindowVisible(win); 2557 } 2558 2559 win.setDisplayLayoutNeeded(); 2560 win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; 2561 2562 // We should only relayout if the view is visible, it is a starting window, or the 2563 // associated appToken is not hidden. 2564 final boolean shouldRelayout = viewVisibility == View.VISIBLE && 2565 (win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING 2566 || win.mActivityRecord.isClientVisible()); 2567 2568 // If we are not currently running the exit animation, we need to see about starting 2569 // one. 2570 // This must be called before the call to performSurfacePlacement. 2571 if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) { 2572 if (DEBUG_VISIBILITY) { 2573 Slog.i(TAG_WM, 2574 "Relayout invis " + win + ": mAnimatingExit=" + win.mAnimatingExit); 2575 } 2576 result |= RELAYOUT_RES_SURFACE_CHANGED; 2577 // When FLAG_SHOW_WALLPAPER flag is removed from a window, we usually set a flag 2578 // in DC#pendingLayoutChanges and update the wallpaper target later. 2579 // However it's possible that FLAG_SHOW_WALLPAPER flag is removed from a window 2580 // when the window is about to exit, so we update the wallpaper target 2581 // immediately here. Otherwise this window will be stuck in exiting and its 2582 // surface remains on the screen. 2583 // TODO(b/189856716): Allow destroying surface even if it belongs to the 2584 // keyguard target. 2585 if (wallpaperMayMove) { 2586 displayContent.mWallpaperController.adjustWallpaperWindows(); 2587 } 2588 tryStartExitingAnimation(win, winAnimator); 2589 } 2590 2591 // Create surfaceControl before surface placement otherwise layout will be skipped 2592 // (because WS.isGoneForLayout() is true when there is no surface. 2593 if (shouldRelayout && outSurfaceControl != null) { 2594 try { 2595 result = createSurfaceControl(outSurfaceControl, result, win, winAnimator); 2596 } catch (Exception e) { 2597 displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/); 2598 2599 ProtoLog.w(WM_ERROR, 2600 "Exception thrown when creating surface for client %s (%s). %s", 2601 client, win.mAttrs.getTitle(), e); 2602 Binder.restoreCallingIdentity(origId); 2603 return 0; 2604 } 2605 } 2606 2607 // We may be deferring layout passes at the moment, but since the client is interested 2608 // in the new out values right now we need to force a layout. 2609 mWindowPlacerLocked.performSurfacePlacement(true /* force */); 2610 2611 if (!win.mHaveFrame && displayContent.mWaitingForConfig) { 2612 // We just forcibly triggered the layout, but this could still be intercepted by 2613 // mWaitingForConfig. Here, we are forcefully marking a value for mLayoutSeq to 2614 // ensure that the resize can occur properly later. Otherwise, the window's frame 2615 // will remain empty forever. 2616 win.mLayoutSeq = displayContent.mLayoutSeq; 2617 } 2618 2619 if (shouldRelayout) { 2620 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1"); 2621 2622 result = win.relayoutVisibleWindow(result); 2623 2624 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { 2625 focusMayChange = true; 2626 } 2627 if (win.mAttrs.type == TYPE_INPUT_METHOD 2628 && displayContent.mInputMethodWindow == null) { 2629 displayContent.setInputMethodWindowLocked(win); 2630 imMayMove = true; 2631 } 2632 win.adjustStartingWindowFlags(); 2633 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2634 } else { 2635 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_2"); 2636 2637 winAnimator.mEnterAnimationPending = false; 2638 winAnimator.mEnteringAnimation = false; 2639 2640 if (outSurfaceControl != null) { 2641 if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) { 2642 // We already told the client to go invisible, but the message may not be 2643 // handled yet, or it might want to draw a last frame. If we already have a 2644 // surface, let the client use that, but don't create new surface at this 2645 // point. 2646 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface"); 2647 winAnimator.getSurfaceControl(outSurfaceControl); 2648 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2649 } else { 2650 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win); 2651 2652 try { 2653 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_" 2654 + win.mAttrs.getTitle()); 2655 outSurfaceControl.release(); 2656 } finally { 2657 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2658 } 2659 } 2660 } 2661 2662 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2663 } 2664 2665 if (focusMayChange) { 2666 if (updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/)) { 2667 imMayMove = false; 2668 } 2669 } 2670 2671 // updateFocusedWindowLocked() already assigned layers so we only need to 2672 // reassign them at this point if the IM window state gets shuffled 2673 boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0; 2674 if (imMayMove) { 2675 displayContent.computeImeTarget(true /* updateImeTarget */); 2676 if (toBeDisplayed) { 2677 // Little hack here -- we -should- be able to rely on the function to return 2678 // true if the IME has moved and needs its layer recomputed. However, if the IME 2679 // was hidden and isn't actually moved in the list, its layer may be out of data 2680 // so we make sure to recompute it. 2681 displayContent.assignWindowLayers(false /* setLayoutNeeded */); 2682 } 2683 } 2684 2685 if (wallpaperMayMove) { 2686 displayContent.pendingLayoutChanges |= 2687 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2688 } 2689 2690 if (win.mActivityRecord != null) { 2691 displayContent.mUnknownAppVisibilityController.notifyRelayouted(win.mActivityRecord); 2692 } 2693 2694 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: updateOrientation"); 2695 configChanged |= displayContent.updateOrientation(); 2696 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2697 2698 if (toBeDisplayed && win.mIsWallpaper) { 2699 displayContent.mWallpaperController.updateWallpaperOffset(win, false /* sync */); 2700 } 2701 if (win.mActivityRecord != null) { 2702 win.mActivityRecord.updateReportedVisibilityLocked(); 2703 } 2704 if (displayPolicy.areSystemBarsForcedConsumedLw()) { 2705 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS; 2706 } 2707 2708 if (outFrames != null && outMergedConfiguration != null) { 2709 final boolean shouldReportActivityWindowInfo = outRelayoutResult != null 2710 && win.mLastReportedActivityWindowInfo != null; 2711 final ActivityWindowInfo outActivityWindowInfo = shouldReportActivityWindowInfo 2712 ? new ActivityWindowInfo() 2713 : null; 2714 2715 win.fillClientWindowFramesAndConfiguration(outFrames, outMergedConfiguration, 2716 outActivityWindowInfo, false /* useLatestConfig */, shouldRelayout); 2717 2718 if (shouldReportActivityWindowInfo) { 2719 outRelayoutResult.activityWindowInfo = outActivityWindowInfo; 2720 } 2721 2722 // Set resize-handled here because the values are sent back to the client. 2723 win.onResizeHandled(); 2724 } 2725 2726 if (outInsetsState != null) { 2727 win.fillInsetsState(outInsetsState, true /* copySources */); 2728 } 2729 2730 ProtoLog.v(WM_DEBUG_FOCUS, "Relayout of %s: focusMayChange=%b", 2731 win, focusMayChange); 2732 2733 if (DEBUG_LAYOUT) { 2734 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrames=" + outFrames); 2735 } 2736 win.mInRelayout = false; 2737 2738 final boolean winVisibleChanged = win.isVisible() != wasVisible; 2739 if (win.isImeOverlayLayeringTarget() && winVisibleChanged) { 2740 dispatchImeTargetOverlayVisibilityChanged(client.asBinder(), win.mAttrs.type, 2741 win.isVisible(), false /* removed */, win.getDisplayId()); 2742 } 2743 // Notify listeners about IME input target window visibility change. 2744 final boolean isImeInputTarget = win.getDisplayContent().getImeInputTarget() == win; 2745 if (isImeInputTarget && winVisibleChanged) { 2746 dispatchImeInputTargetVisibilityChanged(win.mClient.asBinder(), 2747 win.isVisible() /* visible */, false /* removed */, win.getDisplayId()); 2748 } 2749 2750 if (outRelayoutResult != null) { 2751 if (win.syncNextBuffer() && viewVisibility == View.VISIBLE 2752 && win.mSyncSeqId > lastSyncSeqId && !displayContent.mWaitingForConfig) { 2753 outRelayoutResult.syncSeqId = win.shouldSyncWithBuffers() 2754 ? win.mSyncSeqId 2755 : -1; 2756 win.markRedrawForSyncReported(); 2757 } else { 2758 outRelayoutResult.syncSeqId = -1; 2759 } 2760 } 2761 2762 if (configChanged) { 2763 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, 2764 "relayoutWindow: postNewConfigurationToHandler"); 2765 displayContent.sendNewConfiguration(); 2766 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2767 } 2768 if (outActiveControls != null) { 2769 getInsetsSourceControls(win, outActiveControls); 2770 } 2771 } 2772 2773 Binder.restoreCallingIdentity(origId); 2774 return result; 2775 } 2776 getInsetsSourceControls(WindowState win, InsetsSourceControl.Array outArray)2777 private void getInsetsSourceControls(WindowState win, InsetsSourceControl.Array outArray) { 2778 // We will leave the critical section before returning the leash to the client, 2779 // so we need to copy the leash to prevent others release the one that we are 2780 // about to return. 2781 win.fillInsetsSourceControls(outArray, true /* copyControls */); 2782 // This source control is an extra copy if the client is not local. By setting 2783 // PARCELABLE_WRITE_RETURN_VALUE, the leash will be released at the end of 2784 // SurfaceControl.writeToParcel. 2785 outArray.setParcelableFlags(PARCELABLE_WRITE_RETURN_VALUE); 2786 } 2787 tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator)2788 private void tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator) { 2789 // Try starting an animation; if there isn't one, we 2790 // can destroy the surface right away. 2791 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2792 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2793 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2794 } 2795 2796 if (win.isVisible() && win.isDisplayed() && win.mDisplayContent.okToAnimate()) { 2797 String reason = null; 2798 if (winAnimator.applyAnimationLocked(transit, false)) { 2799 // This is a WMCore-driven window animation. 2800 reason = "applyAnimation"; 2801 } else if (win.isSelfAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION)) { 2802 // This is already animating via a WMCore-driven window animation. 2803 reason = "selfAnimating"; 2804 } else { 2805 if (win.mTransitionController.isShellTransitionsEnabled()) { 2806 // Already animating as part of a shell-transition. Currently this only handles 2807 // activity window because other types should be WMCore-driven. 2808 if ((win.mActivityRecord != null && win.mActivityRecord.inTransition())) { 2809 win.mTransitionController.mAnimatingExitWindows.add(win); 2810 reason = "inTransition"; 2811 } 2812 } else if (win.isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_APP_TRANSITION)) { 2813 // Already animating as part of a legacy app-transition. 2814 reason = "inLegacyTransition"; 2815 } 2816 } 2817 if (reason != null) { 2818 win.mAnimatingExit = true; 2819 ProtoLog.d(WM_DEBUG_ANIM, 2820 "Set animatingExit: reason=startExitingAnimation/%s win=%s", reason, win); 2821 } 2822 } 2823 if (!win.mAnimatingExit) { 2824 boolean stopped = win.mActivityRecord == null || win.mActivityRecord.mAppStopped; 2825 // We set mDestroying=true so ActivityRecord#notifyAppStopped in-to destroy surfaces 2826 // will later actually destroy the surface if we do not do so here. Normally we leave 2827 // this to the exit animation. 2828 win.mDestroying = true; 2829 win.destroySurface(false, stopped); 2830 } 2831 if (mAccessibilityController.hasCallbacks()) { 2832 mAccessibilityController.onWindowTransition(win, transit); 2833 } 2834 } 2835 createSurfaceControl(SurfaceControl outSurfaceControl, int result, WindowState win, WindowStateAnimator winAnimator)2836 private int createSurfaceControl(SurfaceControl outSurfaceControl, int result, 2837 WindowState win, WindowStateAnimator winAnimator) { 2838 if (!win.mHasSurface) { 2839 result |= RELAYOUT_RES_SURFACE_CHANGED; 2840 } 2841 2842 SurfaceControl surfaceControl; 2843 try { 2844 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl"); 2845 surfaceControl = winAnimator.createSurfaceLocked(); 2846 } finally { 2847 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2848 } 2849 if (surfaceControl != null) { 2850 winAnimator.getSurfaceControl(outSurfaceControl); 2851 ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl); 2852 2853 } else { 2854 // For some reason there isn't a surface. Clear the 2855 // caller's object so they see the same state. 2856 ProtoLog.w(WM_ERROR, "Failed to create surface control for %s", win); 2857 outSurfaceControl.release(); 2858 } 2859 2860 return result; 2861 } 2862 outOfMemoryWindow(Session session, IWindow client)2863 public boolean outOfMemoryWindow(Session session, IWindow client) { 2864 final long origId = Binder.clearCallingIdentity(); 2865 2866 try { 2867 synchronized (mGlobalLock) { 2868 WindowState win = windowForClientLocked(session, client, false); 2869 if (win == null) { 2870 return false; 2871 } 2872 return mRoot.reclaimSomeSurfaceMemory(win.mWinAnimator, "from-client", false); 2873 } 2874 } finally { 2875 Binder.restoreCallingIdentity(origId); 2876 } 2877 } 2878 finishDrawingWindow(Session session, IWindow client, @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId)2879 void finishDrawingWindow(Session session, IWindow client, 2880 @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) { 2881 if (postDrawTransaction != null) { 2882 postDrawTransaction.sanitize(Binder.getCallingPid(), Binder.getCallingUid()); 2883 } 2884 2885 final long origId = Binder.clearCallingIdentity(); 2886 try { 2887 synchronized (mGlobalLock) { 2888 WindowState win = windowForClientLocked(session, client, false); 2889 ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s", 2890 win, (win != null ? win.mWinAnimator.drawStateToString() : "null")); 2891 if (win != null && win.finishDrawing(postDrawTransaction, seqId)) { 2892 if (win.hasWallpaper()) { 2893 win.getDisplayContent().pendingLayoutChanges |= 2894 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2895 } 2896 win.setDisplayLayoutNeeded(); 2897 mWindowPlacerLocked.requestTraversal(); 2898 } 2899 } 2900 } finally { 2901 Binder.restoreCallingIdentity(origId); 2902 } 2903 } 2904 checkCallingPermission(String permission, String func)2905 boolean checkCallingPermission(String permission, String func) { 2906 return checkCallingPermission(permission, func, true /* printLog */); 2907 } 2908 checkCallingPermission(String permission, String func, boolean printLog)2909 boolean checkCallingPermission(String permission, String func, boolean printLog) { 2910 if (Binder.getCallingPid() == MY_PID) { 2911 return true; 2912 } 2913 2914 if (mContext.checkCallingPermission(permission) 2915 == PackageManager.PERMISSION_GRANTED) { 2916 return true; 2917 } 2918 if (printLog) { 2919 ProtoLog.w(WM_ERROR, "Permission Denial: %s from pid=%d, uid=%d requires %s", 2920 func, Binder.getCallingPid(), Binder.getCallingUid(), permission); 2921 } 2922 return false; 2923 } 2924 2925 @Override addWindowToken(@onNull IBinder binder, int type, int displayId, @Nullable Bundle options)2926 public void addWindowToken(@NonNull IBinder binder, int type, int displayId, 2927 @Nullable Bundle options) { 2928 if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) { 2929 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 2930 } 2931 2932 synchronized (mGlobalLock) { 2933 final DisplayContent dc = getDisplayContentOrCreate(displayId, null /* token */); 2934 if (dc == null) { 2935 ProtoLog.w(WM_ERROR, "addWindowToken: Attempted to add token: %s" 2936 + " for non-exiting displayId=%d", binder, displayId); 2937 return; 2938 } 2939 2940 WindowToken token = dc.getWindowToken(binder); 2941 if (token != null) { 2942 ProtoLog.w(WM_ERROR, "addWindowToken: Attempted to add binder token: %s" 2943 + " for already created window token: %s" 2944 + " displayId=%d", binder, token, displayId); 2945 return; 2946 } 2947 if (type == TYPE_WALLPAPER) { 2948 new WallpaperWindowToken(this, binder, true, dc, 2949 true /* ownerCanManageAppTokens */, options); 2950 } else { 2951 new WindowToken.Builder(this, binder, type) 2952 .setDisplayContent(dc) 2953 .setPersistOnEmpty(true) 2954 .setOwnerCanManageAppTokens(true) 2955 .setOptions(options) 2956 .build(); 2957 } 2958 } 2959 } 2960 2961 @Nullable 2962 @Override attachWindowContextToDisplayArea(@onNull IApplicationThread appThread, @NonNull IBinder clientToken, @LayoutParams.WindowType int type, int displayId, @Nullable Bundle options)2963 public WindowContextInfo attachWindowContextToDisplayArea(@NonNull IApplicationThread appThread, 2964 @NonNull IBinder clientToken, @LayoutParams.WindowType int type, int displayId, 2965 @Nullable Bundle options) { 2966 Objects.requireNonNull(appThread); 2967 Objects.requireNonNull(clientToken); 2968 final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS, 2969 "attachWindowContextToDisplayArea", false /* printLog */); 2970 final int callingPid = Binder.getCallingPid(); 2971 final int callingUid = Binder.getCallingUid(); 2972 final long origId = Binder.clearCallingIdentity(); 2973 try { 2974 synchronized (mGlobalLock) { 2975 final WindowProcessController wpc = mAtmService.getProcessController(appThread); 2976 if (wpc == null) { 2977 ProtoLog.w(WM_ERROR, "attachWindowContextToDisplayArea: calling from" 2978 + " non-existing process pid=%d uid=%d", callingPid, callingUid); 2979 return null; 2980 } 2981 final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId); 2982 if (dc == null) { 2983 ProtoLog.w(WM_ERROR, "attachWindowContextToDisplayArea: trying to attach" 2984 + " to a non-existing display:%d", displayId); 2985 return null; 2986 } 2987 // TODO(b/155340867): Investigate if we still need roundedCornerOverlay after 2988 // the feature b/155340867 is completed. 2989 final DisplayArea<?> da = dc.findAreaForWindowType(type, options, 2990 callerCanManageAppTokens, false /* roundedCornerOverlay */); 2991 mWindowContextListenerController.registerWindowContainerListener(wpc, clientToken, 2992 da, type, options, false /* shouldDispatchConfigWhenRegistering */); 2993 return new WindowContextInfo(da.getConfiguration(), displayId); 2994 } 2995 } finally { 2996 Binder.restoreCallingIdentity(origId); 2997 } 2998 } 2999 3000 @Nullable 3001 @Override attachWindowContextToDisplayContent( @onNull IApplicationThread appThread, @NonNull IBinder clientToken, int displayId)3002 public WindowContextInfo attachWindowContextToDisplayContent( 3003 @NonNull IApplicationThread appThread, @NonNull IBinder clientToken, int displayId) { 3004 Objects.requireNonNull(appThread); 3005 Objects.requireNonNull(clientToken); 3006 final int callingPid = Binder.getCallingPid(); 3007 final int callingUid = Binder.getCallingUid(); 3008 final long origId = Binder.clearCallingIdentity(); 3009 try { 3010 synchronized (mGlobalLock) { 3011 final WindowProcessController wpc = mAtmService.getProcessController(appThread); 3012 if (wpc == null) { 3013 ProtoLog.w(WM_ERROR, "attachWindowContextToDisplayContent: calling from" 3014 + " non-existing process pid=%d uid=%d", callingPid, callingUid); 3015 return null; 3016 } 3017 // We use "getDisplayContent" instead of "getDisplayContentOrCreate" because 3018 // this method may be called in DisplayPolicy's constructor and may cause 3019 // infinite loop. In this scenario, we early return here and switch to do the 3020 // registration in DisplayContent#onParentChanged at DisplayContent initialization. 3021 final DisplayContent dc = mRoot.getDisplayContent(displayId); 3022 if (dc == null) { 3023 if (callingPid != MY_PID) { 3024 throw new IllegalArgumentException( 3025 "attachWindowContextToDisplayContent: trying to attach to a" 3026 + " non-existing display:" + displayId); 3027 } 3028 // Early return if this method is invoked from system process. 3029 // See above comments for more detail. 3030 return null; 3031 } 3032 3033 mWindowContextListenerController.registerWindowContainerListener(wpc, clientToken, 3034 dc, INVALID_WINDOW_TYPE, null /* options */, 3035 false /* shouldDispatchConfigWhenRegistering */); 3036 return new WindowContextInfo(dc.getConfiguration(), displayId); 3037 } 3038 } finally { 3039 Binder.restoreCallingIdentity(origId); 3040 } 3041 } 3042 3043 @Nullable 3044 @Override attachWindowContextToWindowToken(@onNull IApplicationThread appThread, @NonNull IBinder clientToken, @NonNull IBinder token)3045 public WindowContextInfo attachWindowContextToWindowToken(@NonNull IApplicationThread appThread, 3046 @NonNull IBinder clientToken, @NonNull IBinder token) { 3047 Objects.requireNonNull(appThread); 3048 Objects.requireNonNull(clientToken); 3049 Objects.requireNonNull(token); 3050 final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS, 3051 "attachWindowContextToWindowToken", false /* printLog */); 3052 final int callingPid = Binder.getCallingPid(); 3053 final int callingUid = Binder.getCallingUid(); 3054 final long origId = Binder.clearCallingIdentity(); 3055 try { 3056 synchronized (mGlobalLock) { 3057 final WindowProcessController wpc = mAtmService.getProcessController(appThread); 3058 if (wpc == null) { 3059 ProtoLog.w(WM_ERROR, "attachWindowContextToWindowToken: calling from" 3060 + " non-existing process pid=%d uid=%d", callingPid, callingUid); 3061 return null; 3062 } 3063 final WindowToken windowToken = mRoot.getWindowToken(token); 3064 if (windowToken == null) { 3065 ProtoLog.w(WM_ERROR, "Then token:%s is invalid. It might be " 3066 + "removed", token); 3067 return null; 3068 } 3069 final int type = mWindowContextListenerController.getWindowType(clientToken); 3070 if (type == INVALID_WINDOW_TYPE) { 3071 throw new IllegalArgumentException("The clientToken:" + clientToken 3072 + " should have been attached."); 3073 } 3074 if (type != windowToken.windowType) { 3075 throw new IllegalArgumentException("The WindowToken's type should match" 3076 + " the created WindowContext's type. WindowToken's type is " 3077 + windowToken.windowType + ", while WindowContext's is " + type); 3078 } 3079 if (!mWindowContextListenerController.assertCallerCanModifyListener(clientToken, 3080 callerCanManageAppTokens, callingUid)) { 3081 return null; 3082 } 3083 mWindowContextListenerController.registerWindowContainerListener(wpc, clientToken, 3084 windowToken, windowToken.windowType, windowToken.mOptions, 3085 false /* shouldDispatchConfigWhenRegistering */); 3086 return new WindowContextInfo(windowToken.getConfiguration(), 3087 windowToken.getDisplayContent().getDisplayId()); 3088 } 3089 } finally { 3090 Binder.restoreCallingIdentity(origId); 3091 } 3092 } 3093 3094 @Override detachWindowContext(@onNull IBinder clientToken)3095 public void detachWindowContext(@NonNull IBinder clientToken) { 3096 Objects.requireNonNull(clientToken); 3097 final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS, 3098 "detachWindowContext", false /* printLog */); 3099 final int callingUid = Binder.getCallingUid(); 3100 final long origId = Binder.clearCallingIdentity(); 3101 try { 3102 synchronized (mGlobalLock) { 3103 if (!mWindowContextListenerController.assertCallerCanModifyListener(clientToken, 3104 callerCanManageAppTokens, callingUid)) { 3105 return; 3106 } 3107 final WindowContainer wc = mWindowContextListenerController 3108 .getContainer(clientToken); 3109 3110 mWindowContextListenerController.unregisterWindowContainerListener(clientToken); 3111 3112 final WindowToken token = wc != null ? wc.asWindowToken() : null; 3113 if (token != null && token.isFromClient() && token.getDisplayContent() != null) { 3114 removeWindowToken(token.token, token.getDisplayContent().getDisplayId()); 3115 } 3116 } 3117 } finally { 3118 Binder.restoreCallingIdentity(origId); 3119 } 3120 } 3121 3122 @Override reparentWindowContextToDisplayArea( @onNull IApplicationThread appThread, @NonNull IBinder clientToken, int displayId)3123 public boolean reparentWindowContextToDisplayArea( 3124 @NonNull IApplicationThread appThread, @NonNull IBinder clientToken, int displayId) { 3125 if (!Flags.reparentWindowTokenApi()) { 3126 return false; 3127 } 3128 Objects.requireNonNull(appThread); 3129 Objects.requireNonNull(clientToken); 3130 final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS, 3131 "reparentWindowContextToDisplayArea", false /* printLog */); 3132 final int callingPid = Binder.getCallingPid(); 3133 final int callingUid = Binder.getCallingUid(); 3134 final long origId = Binder.clearCallingIdentity(); 3135 try { 3136 synchronized (mGlobalLock) { 3137 final WindowProcessController wpc = mAtmService.getProcessController(appThread); 3138 if (wpc == null) { 3139 ProtoLog.w(WM_ERROR, "reparentWindowContextToDisplayArea: calling from" 3140 + " non-existing process pid=%d uid=%d", callingPid, callingUid); 3141 return false; 3142 } 3143 final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId); 3144 if (dc == null) { 3145 ProtoLog.w(WM_ERROR, "reparentWindowContextToDisplayArea: trying to attach" 3146 + " to a non-existing display:%d", displayId); 3147 return false; 3148 } 3149 3150 if (!mWindowContextListenerController.assertCallerCanReparentListener(clientToken, 3151 callerCanManageAppTokens, callingUid, displayId)) { 3152 return false; 3153 } 3154 final WindowContainer<?> container = mWindowContextListenerController.getContainer( 3155 clientToken); 3156 3157 final WindowToken token = container != null ? container.asWindowToken() : null; 3158 if (token != null && token.isFromClient()) { 3159 ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Reparenting from dc to displayId=%d", 3160 displayId); 3161 // Reparent the window created for this window context. 3162 dc.reParentWindowToken(token); 3163 hideUntilNextDraw(token); 3164 // Prevent a race condition where VRI temporarily reverts the context display ID 3165 // before the onDisplayMoved callback arrives. This caused incorrect display IDs 3166 // during configuration changes, breaking SysUI layouts dependent on it. 3167 // Forcing a resize report ensures VRI has the correct ID before the update. 3168 forceReportResizing(token); 3169 // This makes sure there is a traversal scheduled that will eventually report 3170 // the window resize to the client. 3171 dc.setLayoutNeeded(); 3172 requestTraversal(); 3173 return true; 3174 } 3175 3176 final int type = mWindowContextListenerController.getWindowType(clientToken); 3177 final Bundle options = mWindowContextListenerController.getOptions(clientToken); 3178 // No window yet, switch listening DA. 3179 final DisplayArea<?> da = dc.findAreaForWindowType(type, options, 3180 callerCanManageAppTokens, false /* roundedCornerOverlay */); 3181 mWindowContextListenerController.registerWindowContainerListener(wpc, clientToken, 3182 da, type, options, true /* shouldDispatchConfigWhenRegistering */); 3183 return true; 3184 } 3185 } finally { 3186 Binder.restoreCallingIdentity(origId); 3187 } 3188 } 3189 forceReportResizing(@onNull WindowContainer<?> wc)3190 private void forceReportResizing(@NonNull WindowContainer<?> wc) { 3191 wc.forAllWindows(w -> { 3192 if (!mResizingWindows.contains(w)) { 3193 mResizingWindows.add(w); 3194 } 3195 }, true /* traverseTopToBottom */); 3196 } 3197 hideUntilNextDraw(@onNull WindowToken token)3198 private void hideUntilNextDraw(@NonNull WindowToken token) { 3199 final WindowState topChild = token.getTopChild(); 3200 if (topChild != null) { 3201 mTransactionFactory.get().hide(token.mSurfaceControl).apply(); 3202 topChild.applyWithNextDraw(t -> { 3203 if (token.mSurfaceControl != null) { 3204 t.show(token.mSurfaceControl); 3205 } 3206 }); 3207 } 3208 } 3209 3210 /** Returns {@code true} if this binder is a registered window token. */ 3211 @Override isWindowToken(IBinder binder)3212 public boolean isWindowToken(IBinder binder) { 3213 synchronized (mGlobalLock) { 3214 return mRoot.getWindowToken(binder) != null; 3215 } 3216 3217 } 3218 removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit, int displayId)3219 void removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit, 3220 int displayId) { 3221 synchronized (mGlobalLock) { 3222 final DisplayContent dc = mRoot.getDisplayContent(displayId); 3223 3224 if (dc == null) { 3225 ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s" 3226 + " for non-exiting displayId=%d", binder, displayId); 3227 return; 3228 } 3229 final WindowToken token = dc.removeWindowToken(binder, animateExit); 3230 if (token == null) { 3231 ProtoLog.w(WM_ERROR, 3232 "removeWindowToken: Attempted to remove non-existing token: %s", 3233 binder); 3234 return; 3235 } 3236 3237 if (removeWindows) { 3238 token.removeAllWindowsIfPossible(); 3239 } 3240 dc.getInputMonitor().updateInputWindowsLw(true /* force */); 3241 } 3242 } 3243 3244 @Override removeWindowToken(IBinder binder, int displayId)3245 public void removeWindowToken(IBinder binder, int displayId) { 3246 if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) { 3247 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3248 } 3249 final long origId = Binder.clearCallingIdentity(); 3250 try { 3251 removeWindowToken(binder, false /* removeWindows */, true /* animateExit */, displayId); 3252 } finally { 3253 Binder.restoreCallingIdentity(origId); 3254 } 3255 } 3256 3257 /** @see WindowManagerInternal#moveWindowTokenToDisplay(IBinder, int) */ moveWindowTokenToDisplay(IBinder binder, int displayId)3258 public void moveWindowTokenToDisplay(IBinder binder, int displayId) { 3259 synchronized (mGlobalLock) { 3260 final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId); 3261 if (dc == null) { 3262 ProtoLog.w(WM_ERROR, "moveWindowTokenToDisplay: Attempted to move token: %s" 3263 + " to non-exiting displayId=%d", binder, displayId); 3264 return; 3265 } 3266 final WindowToken token = mRoot.getWindowToken(binder); 3267 if (token == null) { 3268 ProtoLog.w(WM_ERROR, 3269 "moveWindowTokenToDisplay: Attempted to move non-existing token: %s", 3270 binder); 3271 return; 3272 } 3273 if (token.getDisplayContent() == dc) { 3274 ProtoLog.w(WM_ERROR, 3275 "moveWindowTokenToDisplay: Cannot move to the original display " 3276 + "for token: %s", binder); 3277 return; 3278 } 3279 dc.reParentWindowToken(token); 3280 } 3281 } 3282 3283 @Override overridePendingAppTransitionMultiThumbFuture( IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback, boolean scaleUp, int displayId)3284 public void overridePendingAppTransitionMultiThumbFuture( 3285 IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback, 3286 boolean scaleUp, int displayId) { 3287 // TODO(b/365884835): remove this method and callers. 3288 } 3289 3290 @Override overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter, int displayId)3291 public void overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter, 3292 int displayId) { 3293 // TODO(b/365884835): remove this method and callers. 3294 } 3295 3296 @Override endProlongedAnimations()3297 public void endProlongedAnimations() { 3298 // TODO: Remove once clients are updated. 3299 } 3300 3301 // TODO(multi-display): remove when no default display use case. 3302 // (i.e. KeyguardController) executeAppTransition()3303 public void executeAppTransition() { 3304 if (!checkCallingPermission(MANAGE_APP_TOKENS, "executeAppTransition()")) { 3305 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3306 } 3307 getDefaultDisplayContentLocked().executeAppTransition(); 3308 } 3309 isValidPictureInPictureAspectRatio(DisplayContent displayContent, float aspectRatio)3310 boolean isValidPictureInPictureAspectRatio(DisplayContent displayContent, float aspectRatio) { 3311 return displayContent.getPinnedTaskController().isValidPictureInPictureAspectRatio( 3312 aspectRatio); 3313 } 3314 isValidExpandedPictureInPictureAspectRatio(DisplayContent displayContent, float aspectRatio)3315 boolean isValidExpandedPictureInPictureAspectRatio(DisplayContent displayContent, 3316 float aspectRatio) { 3317 return displayContent.getPinnedTaskController().isValidExpandedPictureInPictureAspectRatio( 3318 aspectRatio); 3319 } 3320 3321 @Override notifyKeyguardTrustedChanged()3322 public void notifyKeyguardTrustedChanged() { 3323 final long origId = Binder.clearCallingIdentity(); 3324 try { 3325 synchronized (mGlobalLock) { 3326 if (mAtmService.mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)) { 3327 mRoot.ensureActivitiesVisible(); 3328 } 3329 } 3330 } finally { 3331 Binder.restoreCallingIdentity(origId); 3332 } 3333 } 3334 3335 @Override screenTurningOff(int displayId, ScreenOffListener listener)3336 public void screenTurningOff(int displayId, ScreenOffListener listener) { 3337 mTaskSnapshotController.screenTurningOff(displayId, listener); 3338 } 3339 3340 @Override onKeyguardShowingAndNotOccludedChanged()3341 public void onKeyguardShowingAndNotOccludedChanged() { 3342 mH.sendEmptyMessage(H.RECOMPUTE_FOCUS); 3343 dispatchKeyguardLockedState(); 3344 } 3345 3346 @Override onPowerKeyDown(boolean isScreenOn)3347 public void onPowerKeyDown(boolean isScreenOn) { 3348 mRoot.forAllDisplayPolicies(p -> p.onPowerKeyDown(isScreenOn)); 3349 } 3350 3351 @Override onUserSwitched()3352 public void onUserSwitched() { 3353 synchronized (mGlobalLock) { 3354 // force a re-application of focused window sysui visibility on each display. 3355 mRoot.forAllDisplayPolicies(DisplayPolicy::resetSystemBarAttributes); 3356 } 3357 } 3358 3359 @Override moveDisplayToTopIfAllowed(int displayId)3360 public void moveDisplayToTopIfAllowed(int displayId) { 3361 moveDisplayToTopInternal(displayId); 3362 syncInputTransactions(true /* waitForAnimations */); 3363 } 3364 3365 /** 3366 * Moves the given display to the top. If it cannot be moved to the top this method does 3367 * nothing (e.g. if the display has the flag FLAG_STEAL_TOP_FOCUS_DISABLED set). 3368 * @param displayId The display to move to the top. 3369 */ moveDisplayToTopInternal(int displayId)3370 void moveDisplayToTopInternal(int displayId) { 3371 synchronized (mGlobalLock) { 3372 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 3373 if (displayContent != null && mRoot.getTopChild() != displayContent) { 3374 // Check whether anything prevents us from moving the display to the top. 3375 if (!displayContent.canStealTopFocus()) { 3376 ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, 3377 "Not moving display (displayId=%d) to top. Top focused displayId=%d. " 3378 + "Reason: FLAG_STEAL_TOP_FOCUS_DISABLED", 3379 displayId, mRoot.getTopFocusedDisplayContent().getDisplayId()); 3380 return; 3381 } 3382 3383 Transition transition = null; 3384 boolean transitionNewlyCreated = false; 3385 if (enableDisplayFocusInShellTransitions()) { 3386 transition = mAtmService.getTransitionController().requestTransitionIfNeeded( 3387 TRANSIT_TO_FRONT, 0 /* flags */, null /* trigger */, 3388 displayContent); 3389 if (transition != null) { 3390 transitionNewlyCreated = true; 3391 } else { 3392 transition = 3393 mAtmService.getTransitionController().getCollectingTransition(); 3394 } 3395 if (transition != null) { 3396 transition.recordTaskOrder(displayContent); 3397 } 3398 } 3399 // Nothing prevented us from moving the display to the top. Let's do it! 3400 displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP, 3401 displayContent, true /* includingParents */); 3402 if (transitionNewlyCreated) { 3403 transition.setReady(displayContent, true /* ready */); 3404 } 3405 } 3406 } 3407 } 3408 3409 @Override disableKeyguard(IBinder token, String tag, int userId)3410 public void disableKeyguard(IBinder token, String tag, int userId) { 3411 userId = mAmInternal.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 3412 userId, false /* allowAll */, ALLOW_FULL_ONLY, "disableKeyguard", null); 3413 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 3414 != PackageManager.PERMISSION_GRANTED) { 3415 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 3416 } 3417 final int callingUid = Binder.getCallingUid(); 3418 final long origIdentity = Binder.clearCallingIdentity(); 3419 try { 3420 mKeyguardDisableHandler.disableKeyguard(token, tag, callingUid, userId); 3421 } finally { 3422 Binder.restoreCallingIdentity(origIdentity); 3423 } 3424 } 3425 3426 @Override reenableKeyguard(IBinder token, int userId)3427 public void reenableKeyguard(IBinder token, int userId) { 3428 userId = mAmInternal.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 3429 userId, false /* allowAll */, ALLOW_FULL_ONLY, "reenableKeyguard", null); 3430 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 3431 != PackageManager.PERMISSION_GRANTED) { 3432 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 3433 } 3434 Objects.requireNonNull(token, "token is null"); 3435 final int callingUid = Binder.getCallingUid(); 3436 final long origIdentity = Binder.clearCallingIdentity(); 3437 try { 3438 mKeyguardDisableHandler.reenableKeyguard(token, callingUid, userId); 3439 } finally { 3440 Binder.restoreCallingIdentity(origIdentity); 3441 } 3442 } 3443 3444 @EnforcePermission(android.Manifest.permission.DISABLE_KEYGUARD) 3445 /** 3446 * @see android.app.KeyguardManager#exitKeyguardSecurely 3447 */ 3448 @Override exitKeyguardSecurely(final IOnKeyguardExitResult callback)3449 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 3450 exitKeyguardSecurely_enforcePermission(); 3451 3452 if (callback == null) { 3453 throw new IllegalArgumentException("callback == null"); 3454 } 3455 3456 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 3457 @Override 3458 public void onKeyguardExitResult(boolean success) { 3459 try { 3460 callback.onKeyguardExitResult(success); 3461 } catch (RemoteException e) { 3462 // Client has died, we don't care. 3463 } 3464 } 3465 }); 3466 } 3467 3468 @Override isKeyguardLocked()3469 public boolean isKeyguardLocked() { 3470 return mPolicy.isKeyguardLocked(); 3471 } 3472 isKeyguardShowingAndNotOccluded()3473 public boolean isKeyguardShowingAndNotOccluded() { 3474 return mPolicy.isKeyguardShowingAndNotOccluded(); 3475 } 3476 3477 @Override isKeyguardSecure(int userId)3478 public boolean isKeyguardSecure(int userId) { 3479 if (userId != UserHandle.getCallingUserId() 3480 && !checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS, 3481 "isKeyguardSecure")) { 3482 throw new SecurityException("Requires INTERACT_ACROSS_USERS permission"); 3483 } 3484 3485 final long origId = Binder.clearCallingIdentity(); 3486 try { 3487 return mPolicy.isKeyguardSecure(userId); 3488 } finally { 3489 Binder.restoreCallingIdentity(origId); 3490 } 3491 } 3492 3493 @Override dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message)3494 public void dismissKeyguard(IKeyguardDismissCallback callback, CharSequence message) { 3495 if (!checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard")) { 3496 throw new SecurityException("Requires CONTROL_KEYGUARD permission"); 3497 } 3498 synchronized (mGlobalLock) { 3499 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked(); 3500 if (!dreamHandlesConfirmKeys() 3501 && defaultDisplayContent.getDisplayPolicy().isShowingDreamLw()) { 3502 mAtmService.mTaskSupervisor.wakeUp( 3503 defaultDisplayContent.getDisplayId(), "leaveDream"); 3504 } 3505 mPolicy.dismissKeyguardLw(callback, message); 3506 } 3507 } 3508 3509 @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) 3510 @Override addKeyguardLockedStateListener(IKeyguardLockedStateListener listener)3511 public void addKeyguardLockedStateListener(IKeyguardLockedStateListener listener) { 3512 enforceSubscribeToKeyguardLockedStatePermission(); 3513 boolean registered = mKeyguardLockedStateListeners.register(listener); 3514 if (!registered) { 3515 Slog.w(TAG, "Failed to register listener: " + listener); 3516 } 3517 } 3518 3519 @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) 3520 @Override removeKeyguardLockedStateListener(IKeyguardLockedStateListener listener)3521 public void removeKeyguardLockedStateListener(IKeyguardLockedStateListener listener) { 3522 enforceSubscribeToKeyguardLockedStatePermission(); 3523 mKeyguardLockedStateListeners.unregister(listener); 3524 } 3525 enforceSubscribeToKeyguardLockedStatePermission()3526 private void enforceSubscribeToKeyguardLockedStatePermission() { 3527 mContext.enforceCallingOrSelfPermission( 3528 Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE, 3529 Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE 3530 + " permission required to subscribe to keyguard locked state changes"); 3531 } 3532 dispatchKeyguardLockedState()3533 private void dispatchKeyguardLockedState() { 3534 mH.post(() -> { 3535 final boolean isKeyguardLocked = mPolicy.isKeyguardShowing(); 3536 if (mDispatchedKeyguardLockedState == isKeyguardLocked) { 3537 return; 3538 } 3539 final int n = mKeyguardLockedStateListeners.beginBroadcast(); 3540 for (int i = 0; i < n; i++) { 3541 try { 3542 mKeyguardLockedStateListeners.getBroadcastItem(i).onKeyguardLockedStateChanged( 3543 isKeyguardLocked); 3544 } catch (RemoteException e) { 3545 // Handled by the RemoteCallbackList. 3546 } 3547 } 3548 mKeyguardLockedStateListeners.finishBroadcast(); 3549 mDispatchedKeyguardLockedState = isKeyguardLocked; 3550 }); 3551 } 3552 dispatchImeTargetOverlayVisibilityChanged(@onNull IBinder token, @WindowManager.LayoutParams.WindowType int windowType, boolean visible, boolean removed, int displayId)3553 void dispatchImeTargetOverlayVisibilityChanged(@NonNull IBinder token, 3554 @WindowManager.LayoutParams.WindowType int windowType, boolean visible, 3555 boolean removed, int displayId) { 3556 if (DEBUG_INPUT_METHOD) { 3557 Slog.d(TAG, "onImeTargetOverlayVisibilityChanged, win=" + mWindowMap.get(token) 3558 + ", type=" + ViewDebug.intToString(WindowManager.LayoutParams.class, 3559 "type", windowType) + "visible=" + visible + ", removed=" + removed 3560 + ", displayId=" + displayId); 3561 } 3562 // Ignoring the starting window since it's ok to cover the IME target 3563 // window in temporary without affecting the IME visibility. 3564 final boolean hasOverlay = visible && !removed && windowType != TYPE_APPLICATION_STARTING; 3565 mH.post(() -> InputMethodManagerInternal.get().setHasVisibleImeLayeringOverlay(hasOverlay, 3566 displayId)); 3567 } 3568 dispatchImeInputTargetVisibilityChanged(@onNull IBinder token, boolean visible, boolean removed, int displayId)3569 void dispatchImeInputTargetVisibilityChanged(@NonNull IBinder token, boolean visible, 3570 boolean removed, int displayId) { 3571 if (DEBUG_INPUT_METHOD) { 3572 Slog.d(TAG, "onImeInputTargetVisibilityChanged, win=" + mWindowMap.get(token) 3573 + "visible=" + visible + ", removed=" + removed + ", displayId=" + displayId); 3574 } 3575 final boolean visibleAndNotRemoved = visible && !removed; 3576 mH.post(() -> InputMethodManagerInternal.get().onImeInputTargetVisibilityChanged(token, 3577 visibleAndNotRemoved, displayId)); 3578 } 3579 3580 @Override setSwitchingUser(boolean switching)3581 public void setSwitchingUser(boolean switching) { 3582 if (!checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, 3583 "setSwitchingUser()")) { 3584 throw new SecurityException("Requires INTERACT_ACROSS_USERS_FULL permission"); 3585 } 3586 mPolicy.setSwitchingUser(switching); 3587 synchronized (mGlobalLock) { 3588 mSwitchingUser = switching; 3589 } 3590 } 3591 3592 @RequiresPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW) 3593 @Override showGlobalActions()3594 public void showGlobalActions() { 3595 if (!checkCallingPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW, 3596 "showGlobalActions()")) { 3597 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 3598 } 3599 mPolicy.showGlobalActions(); 3600 } 3601 3602 @Override closeSystemDialogs(String reason)3603 public void closeSystemDialogs(String reason) { 3604 int callingPid = Binder.getCallingPid(); 3605 int callingUid = Binder.getCallingUid(); 3606 if (!mAtmService.checkCanCloseSystemDialogs(callingPid, callingUid, null)) { 3607 return; 3608 } 3609 synchronized (mGlobalLock) { 3610 mRoot.closeSystemDialogs(reason); 3611 } 3612 } 3613 3614 3615 @Override setAnimationScale(int which, float scale)3616 public void setAnimationScale(int which, float scale) { 3617 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 3618 "setAnimationScale()")) { 3619 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 3620 } 3621 3622 scale = fixScale(scale); 3623 switch (which) { 3624 case 0: mWindowAnimationScaleSetting = scale; break; 3625 case 1: mTransitionAnimationScaleSetting = scale; break; 3626 case 2: mAnimatorDurationScaleSetting = scale; break; 3627 } 3628 3629 // Persist setting 3630 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 3631 } 3632 3633 @Override setAnimationScales(float[] scales)3634 public void setAnimationScales(float[] scales) { 3635 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 3636 "setAnimationScale()")) { 3637 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 3638 } 3639 3640 if (scales != null) { 3641 if (scales.length >= 1) { 3642 mWindowAnimationScaleSetting = fixScale(scales[0]); 3643 } 3644 if (scales.length >= 2) { 3645 mTransitionAnimationScaleSetting = fixScale(scales[1]); 3646 } 3647 if (scales.length >= 3) { 3648 mAnimatorDurationScaleSetting = fixScale(scales[2]); 3649 dispatchNewAnimatorScaleLocked(null); 3650 } 3651 } 3652 3653 // Persist setting 3654 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 3655 } 3656 setAnimatorDurationScale(float scale)3657 private void setAnimatorDurationScale(float scale) { 3658 mAnimatorDurationScaleSetting = scale; 3659 ValueAnimator.setDurationScale(scale); 3660 } 3661 getWindowAnimationScaleLocked()3662 public float getWindowAnimationScaleLocked() { 3663 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; 3664 } 3665 getTransitionAnimationScaleLocked()3666 public float getTransitionAnimationScaleLocked() { 3667 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; 3668 } 3669 3670 @Override getAnimationScale(int which)3671 public float getAnimationScale(int which) { 3672 switch (which) { 3673 case 0: return mWindowAnimationScaleSetting; 3674 case 1: return mTransitionAnimationScaleSetting; 3675 case 2: return mAnimatorDurationScaleSetting; 3676 } 3677 return 0; 3678 } 3679 3680 @Override getAnimationScales()3681 public float[] getAnimationScales() { 3682 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting, 3683 mAnimatorDurationScaleSetting }; 3684 } 3685 3686 @Override getCurrentAnimatorScale()3687 public float getCurrentAnimatorScale() { 3688 synchronized (mGlobalLock) { 3689 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting; 3690 } 3691 } 3692 dispatchNewAnimatorScaleLocked(Session session)3693 void dispatchNewAnimatorScaleLocked(Session session) { 3694 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget(); 3695 } 3696 3697 @Override registerPointerEventListener(PointerEventListener listener, int displayId)3698 public void registerPointerEventListener(PointerEventListener listener, int displayId) { 3699 synchronized (mGlobalLock) { 3700 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 3701 if (displayContent != null) { 3702 displayContent.registerPointerEventListener(listener); 3703 } 3704 } 3705 } 3706 3707 @Override unregisterPointerEventListener(PointerEventListener listener, int displayId)3708 public void unregisterPointerEventListener(PointerEventListener listener, int displayId) { 3709 synchronized (mGlobalLock) { 3710 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 3711 if (displayContent != null) { 3712 displayContent.unregisterPointerEventListener(listener); 3713 } 3714 } 3715 } 3716 3717 // Called by window manager policy. Not exposed externally. 3718 @Override getLidState()3719 public int getLidState() { 3720 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 3721 InputManagerService.SW_LID); 3722 if (sw > 0) { 3723 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 3724 return LID_CLOSED; 3725 } else if (sw == 0) { 3726 // Switch state: AKEY_STATE_UP. 3727 return LID_OPEN; 3728 } else { 3729 // Switch state: AKEY_STATE_UNKNOWN. 3730 return LID_ABSENT; 3731 } 3732 } 3733 3734 // Called by window manager policy. Not exposed externally. 3735 @Override lockDeviceNow()3736 public void lockDeviceNow() { 3737 lockNow(null); 3738 } 3739 3740 // Called by window manager policy. Not exposed externally. 3741 @Override getCameraLensCoverState()3742 public int getCameraLensCoverState() { 3743 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 3744 InputManagerService.SW_CAMERA_LENS_COVER); 3745 if (sw > 0) { 3746 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 3747 return CAMERA_LENS_COVERED; 3748 } else if (sw == 0) { 3749 // Switch state: AKEY_STATE_UP. 3750 return CAMERA_LENS_UNCOVERED; 3751 } else { 3752 // Switch state: AKEY_STATE_UNKNOWN. 3753 return CAMERA_LENS_COVER_ABSENT; 3754 } 3755 } 3756 3757 // Called by window manager policy. Not exposed externally. 3758 @Override shutdown(boolean confirm)3759 public void shutdown(boolean confirm) { 3760 // Pass in the UI context, since ShutdownThread requires it (to show UI). 3761 ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(), 3762 PowerManager.SHUTDOWN_USER_REQUESTED, confirm); 3763 } 3764 3765 // Called by window manager policy. Not exposed externally. 3766 @Override reboot(boolean confirm)3767 public void reboot(boolean confirm) { 3768 // Pass in the UI context, since ShutdownThread requires it (to show UI). 3769 ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(), 3770 PowerManager.SHUTDOWN_USER_REQUESTED, confirm); 3771 } 3772 3773 // Called by window manager policy. Not exposed externally. 3774 @Override rebootSafeMode(boolean confirm)3775 public void rebootSafeMode(boolean confirm) { 3776 // Pass in the UI context, since ShutdownThread requires it (to show UI). 3777 ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(), 3778 confirm); 3779 } 3780 setCurrentUser(@serIdInt int newUserId)3781 public void setCurrentUser(@UserIdInt int newUserId) { 3782 synchronized (mGlobalLock) { 3783 final TransitionController controller = mAtmService.getTransitionController(); 3784 if (!controller.isCollecting() && controller.isShellTransitionsEnabled()) { 3785 controller.requestStartTransition(controller.createTransition(TRANSIT_OPEN), 3786 null /* trigger */, null /* remote */, null /* disp */); 3787 } 3788 mCurrentUserId = newUserId; 3789 mDisplayWindowSettingsProvider.setOverrideSettingsForUser(newUserId); 3790 mDisplayWindowSettingsProvider.removeStaleDisplaySettingsLocked(this, mRoot); 3791 mPolicy.setCurrentUserLw(newUserId); 3792 mKeyguardDisableHandler.setCurrentUser(newUserId); 3793 3794 // Hide windows that should not be seen by the new user. 3795 mRoot.switchUser(newUserId); 3796 mWindowPlacerLocked.performSurfacePlacement(); 3797 3798 // Notify whether the root docked task exists for the current user 3799 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3800 3801 // If the display is already prepared, update the density. 3802 // Otherwise, we'll update it when it's prepared. 3803 if (mDisplayReady) { 3804 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId); 3805 final int targetDensity = forcedDensity != 0 3806 ? forcedDensity : displayContent.getInitialDisplayDensity(); 3807 displayContent.setForcedDensity(targetDensity, UserHandle.USER_CURRENT); 3808 } 3809 } 3810 } 3811 3812 /* Called by WindowState */ isUserVisible(@serIdInt int userId)3813 boolean isUserVisible(@UserIdInt int userId) { 3814 return mUmInternal.isUserVisible(userId); 3815 } 3816 getUserAssignedToDisplay(int displayId)3817 @UserIdInt int getUserAssignedToDisplay(int displayId) { 3818 return mUmInternal.getUserAssignedToDisplay(displayId); 3819 } 3820 shouldPlacePrimaryHomeOnDisplay(int displayId)3821 boolean shouldPlacePrimaryHomeOnDisplay(int displayId) { 3822 int userId = mUmInternal.getUserAssignedToDisplay(displayId); 3823 return shouldPlacePrimaryHomeOnDisplay(displayId, userId); 3824 } 3825 shouldPlacePrimaryHomeOnDisplay(int displayId, int userId)3826 boolean shouldPlacePrimaryHomeOnDisplay(int displayId, int userId) { 3827 return mUmInternal.getMainDisplayAssignedToUser(userId) == displayId; 3828 } 3829 enableScreenAfterBoot()3830 public void enableScreenAfterBoot() { 3831 synchronized (mGlobalLock) { 3832 ProtoLog.i(WM_DEBUG_BOOT, "enableScreenAfterBoot: mDisplayEnabled=%b " 3833 + "mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. " 3834 + "%s", 3835 mDisplayEnabled, mForceDisplayEnabled, mShowingBootMessages, mSystemBooted, 3836 new RuntimeException("here").fillInStackTrace()); 3837 if (mSystemBooted) { 3838 return; 3839 } 3840 mSystemBooted = true; 3841 hideBootMessagesLocked(); 3842 // If the screen still doesn't come up after 30 seconds, give 3843 // up and turn it on. 3844 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000 * Build.HW_TIMEOUT_MULTIPLIER); 3845 } 3846 3847 mPolicy.systemBooted(); 3848 3849 performEnableScreen(); 3850 } 3851 3852 @Override enableScreenIfNeeded()3853 public void enableScreenIfNeeded() { 3854 synchronized (mGlobalLock) { 3855 enableScreenIfNeededLocked(); 3856 } 3857 } 3858 enableScreenIfNeededLocked()3859 void enableScreenIfNeededLocked() { 3860 ProtoLog.i(WM_DEBUG_BOOT, "enableScreenIfNeededLocked: mDisplayEnabled=%b " 3861 + "mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. " 3862 + "%s", 3863 mDisplayEnabled, mForceDisplayEnabled, mShowingBootMessages, mSystemBooted, 3864 new RuntimeException("here").fillInStackTrace()); 3865 if (mDisplayEnabled) { 3866 return; 3867 } 3868 if (!mSystemBooted && !mShowingBootMessages) { 3869 return; 3870 } 3871 mH.sendEmptyMessage(H.ENABLE_SCREEN); 3872 } 3873 performBootTimeout()3874 public void performBootTimeout() { 3875 synchronized (mGlobalLock) { 3876 if (mDisplayEnabled) { 3877 return; 3878 } 3879 ProtoLog.w(WM_ERROR, "***** BOOT TIMEOUT: forcing display enabled"); 3880 mForceDisplayEnabled = true; 3881 } 3882 performEnableScreen(); 3883 } 3884 3885 /** 3886 * Called when System UI has been started. 3887 */ onSystemUiStarted()3888 public void onSystemUiStarted() { 3889 mPolicy.onSystemUiStarted(); 3890 } 3891 performEnableScreen()3892 private void performEnableScreen() { 3893 synchronized (mGlobalLock) { 3894 ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: mDisplayEnabled=%b" 3895 + " mForceDisplayEnabled=%b" + " mShowingBootMessages=%b" 3896 + " mSystemBooted=%b. %s", mDisplayEnabled, 3897 mForceDisplayEnabled, mShowingBootMessages, mSystemBooted, 3898 new RuntimeException("here").fillInStackTrace()); 3899 if (mDisplayEnabled) { 3900 return; 3901 } 3902 if (!mSystemBooted && !mShowingBootMessages) { 3903 return; 3904 } 3905 3906 if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) { 3907 return; 3908 } 3909 3910 // Don't enable the screen until all existing windows have been drawn. 3911 if (!mForceDisplayEnabled) { 3912 if (mBootWaitForWindowsStartTime < 0) { 3913 // First time we will start waiting for all windows to be drawn. 3914 mBootWaitForWindowsStartTime = SystemClock.elapsedRealtime(); 3915 } 3916 for (int i = mRoot.getChildCount() - 1; i >= 0; i--) { 3917 if (mRoot.getChildAt(i).shouldWaitForSystemDecorWindowsOnBoot()) { 3918 return; 3919 } 3920 } 3921 long waitTime = SystemClock.elapsedRealtime() - mBootWaitForWindowsStartTime; 3922 mBootWaitForWindowsStartTime = -1; 3923 if (waitTime > 10) { 3924 ProtoLog.i(WM_DEBUG_BOOT, 3925 "performEnableScreen: Waited %dms for all windows to be drawn", 3926 waitTime); 3927 } 3928 } 3929 3930 if (!mBootAnimationStopped) { 3931 Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0); 3932 // stop boot animation 3933 // formerly we would just kill the process, but we now ask it to exit so it 3934 // can choose where to stop the animation. 3935 SystemProperties.set("service.bootanim.exit", "1"); 3936 mBootAnimationStopped = true; 3937 } 3938 3939 if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) { 3940 ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: Waiting for anim complete"); 3941 return; 3942 } 3943 3944 if (!SurfaceControl.bootFinished()) { 3945 ProtoLog.w(WM_ERROR, "performEnableScreen: bootFinished() failed."); 3946 return; 3947 } 3948 3949 EventLogTags.writeWmBootAnimationDone(SystemClock.uptimeMillis()); 3950 Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0); 3951 mDisplayEnabled = true; 3952 ProtoLog.i(WM_DEBUG_SCREEN_ON, "******************** ENABLING SCREEN!"); 3953 3954 // Enable input dispatch. 3955 mInputManagerCallback.setEventDispatchingLw(mEventDispatchingEnabled); 3956 } 3957 3958 try { 3959 mActivityManager.bootAnimationComplete(); 3960 } catch (RemoteException e) { 3961 } 3962 3963 mPolicy.enableScreenAfterBoot(); 3964 3965 // Make sure the last requested orientation has been applied. 3966 updateRotationUnchecked(false, false); 3967 3968 synchronized (mGlobalLock) { 3969 mAtmService.getTransitionController().mIsWaitingForDisplayEnabled = false; 3970 ProtoLog.v(WmProtoLogGroups.WM_DEBUG_WINDOW_TRANSITIONS, 3971 "Notified TransitionController that the display is ready."); 3972 } 3973 } 3974 checkBootAnimationCompleteLocked()3975 private boolean checkBootAnimationCompleteLocked() { 3976 if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) { 3977 mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED); 3978 mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED, 3979 BOOT_ANIMATION_POLL_INTERVAL); 3980 ProtoLog.i(WM_DEBUG_BOOT, "checkBootAnimationComplete: Waiting for anim complete"); 3981 return false; 3982 } 3983 ProtoLog.i(WM_DEBUG_BOOT, "checkBootAnimationComplete: Animation complete!"); 3984 return true; 3985 } 3986 showBootMessage(final CharSequence msg, final boolean always)3987 public void showBootMessage(final CharSequence msg, final boolean always) { 3988 boolean first = false; 3989 synchronized (mGlobalLock) { 3990 ProtoLog.i(WM_DEBUG_BOOT, "showBootMessage: msg=%s always=%b" 3991 + " mAllowBootMessages=%b mShowingBootMessages=%b" 3992 + " mSystemBooted=%b. %s", msg, always, mAllowBootMessages, 3993 mShowingBootMessages, mSystemBooted, 3994 new RuntimeException("here").fillInStackTrace()); 3995 if (!mAllowBootMessages) { 3996 return; 3997 } 3998 if (!mShowingBootMessages) { 3999 if (!always) { 4000 return; 4001 } 4002 first = true; 4003 } 4004 if (mSystemBooted) { 4005 return; 4006 } 4007 mShowingBootMessages = true; 4008 mPolicy.showBootMessage(msg, always); 4009 } 4010 if (first) { 4011 performEnableScreen(); 4012 } 4013 } 4014 hideBootMessagesLocked()4015 public void hideBootMessagesLocked() { 4016 ProtoLog.i(WM_DEBUG_BOOT, "hideBootMessagesLocked: mDisplayEnabled=%b" 4017 + " mForceDisplayEnabled=%b mShowingBootMessages=%b" 4018 + " mSystemBooted=%b. %s", mDisplayEnabled, mForceDisplayEnabled, 4019 mShowingBootMessages, mSystemBooted, 4020 new RuntimeException("here").fillInStackTrace()); 4021 if (mShowingBootMessages) { 4022 mShowingBootMessages = false; 4023 mPolicy.hideBootMessages(); 4024 } 4025 } 4026 4027 /** 4028 * Sets the touch mode state. 4029 * 4030 * If {@code com.android.internal.R.bool.config_perDisplayFocusEnabled} is set to true, then 4031 * only the display represented by the {@code displayId} parameter will be requested to switch 4032 * the touch mode state. Otherwise all displays that do not maintain their own focus and touch 4033 * mode will be requested to switch their touch mode state (disregarding {@code displayId} 4034 * parameter). 4035 * 4036 * To be able to change touch mode state, the caller must either own the focused window, or must 4037 * have the {@link android.Manifest.permission#MODIFY_TOUCH_MODE_STATE} permission. Instrumented 4038 * process, sourced with {@link android.Manifest.permission#MODIFY_TOUCH_MODE_STATE}, may switch 4039 * touch mode at any time. 4040 * 4041 * @param inTouch the touch mode to set 4042 * @param displayId the target display id 4043 */ 4044 @Override // Binder call setInTouchMode(boolean inTouch, int displayId)4045 public void setInTouchMode(boolean inTouch, int displayId) { 4046 synchronized (mGlobalLock) { 4047 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 4048 if (mPerDisplayFocusEnabled && (displayContent == null 4049 || displayContent.isInTouchMode() == inTouch)) { 4050 return; 4051 } 4052 final boolean displayHasOwnTouchMode = 4053 displayContent != null && displayContent.hasOwnFocus(); 4054 if (displayHasOwnTouchMode && displayContent.isInTouchMode() == inTouch) { 4055 return; 4056 } 4057 final int pid = Binder.getCallingPid(); 4058 final int uid = Binder.getCallingUid(); 4059 final boolean hasPermission = hasTouchModePermission(pid); 4060 final long token = Binder.clearCallingIdentity(); 4061 try { 4062 // If mPerDisplayFocusEnabled is set or the display maintains its own touch mode, 4063 // then just update the display pointed by displayId 4064 if (mPerDisplayFocusEnabled || displayHasOwnTouchMode) { 4065 if (mInputManager.setInTouchMode(inTouch, pid, uid, hasPermission, displayId)) { 4066 displayContent.setInTouchMode(inTouch); 4067 } 4068 } else { // Otherwise update all displays that do not maintain their own touch mode 4069 final int displayCount = mRoot.mChildren.size(); 4070 for (int i = 0; i < displayCount; ++i) { 4071 DisplayContent dc = mRoot.mChildren.get(i); 4072 if (dc.isInTouchMode() == inTouch || dc.hasOwnFocus()) { 4073 continue; 4074 } 4075 if (mInputManager.setInTouchMode(inTouch, pid, uid, hasPermission, 4076 dc.mDisplayId)) { 4077 dc.setInTouchMode(inTouch); 4078 } 4079 } 4080 } 4081 } finally { 4082 Binder.restoreCallingIdentity(token); 4083 } 4084 } 4085 } 4086 4087 /** 4088 * Sets the touch mode state forcibly on all displays (disregarding both the value of 4089 * {@code com.android.internal.R.bool.config_perDisplayFocusEnabled} and whether the display 4090 * maintains its own focus and touch mode). 4091 * 4092 * @param inTouch the touch mode to set 4093 */ 4094 @Override // Binder call setInTouchModeOnAllDisplays(boolean inTouch)4095 public void setInTouchModeOnAllDisplays(boolean inTouch) { 4096 final int pid = Binder.getCallingPid(); 4097 final int uid = Binder.getCallingUid(); 4098 final boolean hasPermission = hasTouchModePermission(pid); 4099 final long token = Binder.clearCallingIdentity(); 4100 try { 4101 synchronized (mGlobalLock) { 4102 for (int i = 0; i < mRoot.mChildren.size(); ++i) { 4103 DisplayContent dc = mRoot.mChildren.get(i); 4104 if (dc.isInTouchMode() != inTouch 4105 && mInputManager.setInTouchMode(inTouch, pid, uid, hasPermission, 4106 dc.mDisplayId)) { 4107 dc.setInTouchMode(inTouch); 4108 } 4109 } 4110 } 4111 } finally { 4112 Binder.restoreCallingIdentity(token); 4113 } 4114 } 4115 hasTouchModePermission(int pid)4116 private boolean hasTouchModePermission(int pid) { 4117 return mAtmService.instrumentationSourceHasPermission(pid, MODIFY_TOUCH_MODE_STATE) 4118 || checkCallingPermission(MODIFY_TOUCH_MODE_STATE, "setInTouchMode()", 4119 /* printlog= */ false); 4120 } 4121 4122 /** 4123 * Returns the touch mode state for the display id passed as argument. 4124 * 4125 * This method will return the default touch mode state (represented by 4126 * {@code com.android.internal.R.bool.config_defaultInTouchMode}) if the display passed as 4127 * argument is no longer registered in {@RootWindowContainer}). 4128 */ 4129 @Override // Binder call isInTouchMode(int displayId)4130 public boolean isInTouchMode(int displayId) { 4131 synchronized (mGlobalLock) { 4132 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 4133 if (displayContent == null) { 4134 return mContext.getResources().getBoolean(R.bool.config_defaultInTouchMode); 4135 } 4136 return displayContent.isInTouchMode(); 4137 } 4138 } 4139 showEmulatorDisplayOverlayIfNeeded()4140 public void showEmulatorDisplayOverlayIfNeeded() { 4141 if (mContext.getResources().getBoolean( 4142 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay) 4143 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false) 4144 && Build.IS_EMULATOR) { 4145 mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY)); 4146 } 4147 } 4148 showEmulatorDisplayOverlay()4149 public void showEmulatorDisplayOverlay() { 4150 synchronized (mGlobalLock) { 4151 4152 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> showEmulatorDisplayOverlay"); 4153 if (mEmulatorDisplayOverlay == null) { 4154 mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(mContext, 4155 getDefaultDisplayContentLocked(), 4156 mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER) 4157 * TYPE_LAYER_MULTIPLIER + 10, mTransaction); 4158 } 4159 mEmulatorDisplayOverlay.setVisibility(true, mTransaction); 4160 mTransaction.apply(); 4161 } 4162 } 4163 4164 // TODO: more accounting of which pid(s) turned it on, keep count, 4165 // only allow disables from pids which have count on, etc. 4166 @Override showStrictModeViolation(boolean on)4167 public void showStrictModeViolation(boolean on) { 4168 final int pid = Binder.getCallingPid(); 4169 if (on) { 4170 // Show the visualization, and enqueue a second message to tear it 4171 // down if we don't hear back from the app. 4172 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 1, pid)); 4173 mH.sendMessageDelayed(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid), 4174 DateUtils.SECOND_IN_MILLIS); 4175 } else { 4176 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid)); 4177 } 4178 } 4179 showStrictModeViolation(int arg, int pid)4180 private void showStrictModeViolation(int arg, int pid) { 4181 final boolean on = arg != 0; 4182 synchronized (mGlobalLock) { 4183 // Ignoring requests to enable the red border from clients which aren't on screen. 4184 // (e.g. Broadcast Receivers in the background..) 4185 if (on && !mRoot.canShowStrictModeViolation(pid)) { 4186 return; 4187 } 4188 4189 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM, ">>> showStrictModeViolation"); 4190 // TODO: Modify this to use the surface trace once it is not going baffling. 4191 // b/31532461 4192 // TODO(multi-display): support multiple displays 4193 if (mStrictModeFlash == null) { 4194 mStrictModeFlash = new StrictModeFlash(getDefaultDisplayContentLocked(), 4195 mTransaction); 4196 } 4197 mStrictModeFlash.setVisibility(on, mTransaction); 4198 mTransaction.apply(); 4199 } 4200 } 4201 4202 @Override setStrictModeVisualIndicatorPreference(String value)4203 public void setStrictModeVisualIndicatorPreference(String value) { 4204 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 4205 } 4206 4207 @Override screenshotWallpaper()4208 public Bitmap screenshotWallpaper() { 4209 if (!checkCallingPermission(READ_FRAME_BUFFER, "screenshotWallpaper()")) { 4210 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 4211 } 4212 try { 4213 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper"); 4214 synchronized (mGlobalLock) { 4215 // TODO(b/115486823) Screenshot at secondary displays if needed. 4216 final DisplayContent dc = mRoot.getDisplayContent(DEFAULT_DISPLAY); 4217 return dc.mWallpaperController.screenshotWallpaperLocked(); 4218 } 4219 } finally { 4220 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4221 } 4222 } 4223 4224 @Override mirrorWallpaperSurface(int displayId)4225 public SurfaceControl mirrorWallpaperSurface(int displayId) { 4226 synchronized (mGlobalLock) { 4227 final DisplayContent dc = mRoot.getDisplayContent(displayId); 4228 return dc.mWallpaperController.mirrorWallpaperSurface(); 4229 } 4230 } 4231 4232 @Nullable takeAssistScreenshot( @ullable ToBooleanFunction<WindowState> predicate)4233 private ScreenshotHardwareBuffer takeAssistScreenshot( 4234 @Nullable ToBooleanFunction<WindowState> predicate) { 4235 if (!checkCallingPermission(READ_FRAME_BUFFER, "requestAssistScreenshot()")) { 4236 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 4237 } 4238 4239 ScreenCapture.LayerCaptureArgs captureArgs; 4240 synchronized (mGlobalLock) { 4241 final DisplayContent displayContent = mRoot.getDisplayContent(DEFAULT_DISPLAY); 4242 if (displayContent == null) { 4243 if (DEBUG_SCREENSHOT) { 4244 Slog.i(TAG_WM, "Screenshot returning null. No Display for displayId=" 4245 + DEFAULT_DISPLAY); 4246 } 4247 captureArgs = null; 4248 } else { 4249 captureArgs = displayContent.getLayerCaptureArgs(predicate); 4250 } 4251 } 4252 4253 final ScreenshotHardwareBuffer screenshotBuffer; 4254 if (captureArgs != null) { 4255 ScreenCapture.SynchronousScreenCaptureListener syncScreenCapture = 4256 ScreenCapture.createSyncCaptureListener(); 4257 4258 ScreenCapture.captureLayers(captureArgs, syncScreenCapture); 4259 4260 screenshotBuffer = syncScreenCapture.getBuffer(); 4261 } else { 4262 screenshotBuffer = null; 4263 } 4264 4265 if (screenshotBuffer == null) { 4266 Slog.w(TAG_WM, "Failed to take screenshot"); 4267 } 4268 4269 return screenshotBuffer; 4270 } 4271 4272 /** 4273 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 4274 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 4275 * of the target image. 4276 */ 4277 @Override requestAssistScreenshot(final IAssistDataReceiver receiver)4278 public boolean requestAssistScreenshot(final IAssistDataReceiver receiver) { 4279 final ScreenshotHardwareBuffer shb = takeAssistScreenshot(/* predicate= */ null); 4280 final Bitmap bm = shb != null ? shb.asBitmap() : null; 4281 FgThread.getHandler().post(() -> { 4282 try { 4283 receiver.onHandleAssistScreenshot(bm); 4284 } catch (RemoteException e) { 4285 } 4286 }); 4287 4288 return true; 4289 } 4290 4291 /** 4292 * Generates and returns an up-to-date {@link Bitmap} for the specified taskId. 4293 * 4294 * @param taskId The task ID of the task for which a Bitmap is requested. 4295 * @param layerCaptureArgsBuilder A {@link ScreenCapture.LayerCaptureArgs.Builder} with 4296 * arguments for how to capture the Bitmap. The caller can 4297 * specify any arguments, but this method will ensure that the 4298 * specified task's SurfaceControl is used and the crop is set to 4299 * the bounds of that task. 4300 * @return The Bitmap, or null if no task with the specified ID can be found or the bitmap could 4301 * not be generated. 4302 */ 4303 @Nullable captureTaskBitmap(int taskId, @NonNull ScreenCapture.LayerCaptureArgs.Builder layerCaptureArgsBuilder)4304 public Bitmap captureTaskBitmap(int taskId, 4305 @NonNull ScreenCapture.LayerCaptureArgs.Builder layerCaptureArgsBuilder) { 4306 if (mTaskSnapshotController.shouldDisableSnapshots()) { 4307 return null; 4308 } 4309 4310 synchronized (mGlobalLock) { 4311 final Task task = mRoot.anyTaskForId(taskId); 4312 if (task == null) { 4313 return null; 4314 } 4315 4316 // The bounds returned by the task represent the task's position on the screen. However, 4317 // we need to specify a crop relative to the task's surface control. Therefore, shift 4318 // the task's bounds to 0,0 so that we have the correct size and position within the 4319 // task's surface control. 4320 task.getBounds(mTmpRect); 4321 mTmpRect.offsetTo(0, 0); 4322 4323 final SurfaceControl sc = task.getSurfaceControl(); 4324 final ScreenshotHardwareBuffer buffer = ScreenCapture.captureLayers( 4325 layerCaptureArgsBuilder.setLayer(sc).setSourceCrop(mTmpRect).build()); 4326 if (buffer == null) { 4327 Slog.w(TAG, "Could not get screenshot buffer for taskId: " + taskId); 4328 return null; 4329 } 4330 4331 return buffer.asBitmap(); 4332 } 4333 } 4334 4335 /** 4336 * In case a task write/delete operation was lost because the system crashed, this makes sure to 4337 * clean up the directory to remove obsolete files. 4338 * 4339 * @param persistentTaskIds A set of task ids that exist in our in-memory model. 4340 * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory 4341 * model. 4342 */ removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds)4343 public void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) { 4344 synchronized (mGlobalLock) { 4345 mTaskSnapshotController.removeObsoleteTaskFiles(persistentTaskIds, runningUserIds); 4346 } 4347 } 4348 4349 @Override setFixedToUserRotation(int displayId, int fixedToUserRotation)4350 public void setFixedToUserRotation(int displayId, int fixedToUserRotation) { 4351 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 4352 "setFixedToUserRotation()")) { 4353 throw new SecurityException("Requires SET_ORIENTATION permission"); 4354 } 4355 final long origId = Binder.clearCallingIdentity(); 4356 try { 4357 synchronized (mGlobalLock) { 4358 final DisplayContent display = mRoot.getDisplayContent(displayId); 4359 if (display == null) { 4360 Slog.w(TAG, "Trying to set fixed to user rotation for a missing display."); 4361 return; 4362 } 4363 display.getDisplayRotation().setFixedToUserRotation(fixedToUserRotation); 4364 } 4365 } finally { 4366 Binder.restoreCallingIdentity(origId); 4367 } 4368 } 4369 getFixedToUserRotation(int displayId)4370 int getFixedToUserRotation(int displayId) { 4371 synchronized (mGlobalLock) { 4372 final DisplayContent display = mRoot.getDisplayContent(displayId); 4373 if (display == null) { 4374 Slog.w(TAG, "Trying to get fixed to user rotation for a missing display."); 4375 return -1; 4376 } 4377 return display.getDisplayRotation().getFixedToUserRotationMode(); 4378 } 4379 } 4380 4381 @Override setIgnoreOrientationRequest(int displayId, boolean ignoreOrientationRequest)4382 public void setIgnoreOrientationRequest(int displayId, boolean ignoreOrientationRequest) { 4383 if (!checkCallingPermission( 4384 android.Manifest.permission.SET_ORIENTATION, "setIgnoreOrientationRequest()")) { 4385 throw new SecurityException("Requires SET_ORIENTATION permission"); 4386 } 4387 4388 final long origId = Binder.clearCallingIdentity(); 4389 try { 4390 synchronized (mGlobalLock) { 4391 final DisplayContent display = mRoot.getDisplayContent(displayId); 4392 if (display == null) { 4393 Slog.w(TAG, "Trying to setIgnoreOrientationRequest() for a missing display."); 4394 return; 4395 } 4396 display.setIgnoreOrientationRequest(ignoreOrientationRequest); 4397 } 4398 } finally { 4399 Binder.restoreCallingIdentity(origId); 4400 } 4401 } 4402 4403 @Override getIgnoreOrientationRequest(int displayId)4404 public boolean getIgnoreOrientationRequest(int displayId) { 4405 synchronized (mGlobalLock) { 4406 final DisplayContent display = mRoot.getDisplayContent(displayId); 4407 if (display == null) { 4408 Slog.w(TAG, "Trying to getIgnoreOrientationRequest() for a missing display."); 4409 return false; 4410 } 4411 return display.getIgnoreOrientationRequest(); 4412 } 4413 } 4414 4415 @Nullable resetIgnoreOrientationRequest(int displayId)4416 Boolean resetIgnoreOrientationRequest(int displayId) { 4417 synchronized (mGlobalLock) { 4418 final DisplayContent display = mRoot.getDisplayContent(displayId); 4419 if (display == null) { 4420 return null; 4421 } 4422 display.mHasSetIgnoreOrientationRequest = false; 4423 // Clear existing override settings. 4424 mDisplayWindowSettings.setIgnoreOrientationRequest(display, 4425 null /* ignoreOrientationRequest */); 4426 // Reload from settings in case there is built-in config. 4427 mDisplayWindowSettings.applyRotationSettingsToDisplayLocked(display); 4428 return display.getIgnoreOrientationRequest(); 4429 } 4430 } 4431 4432 /** 4433 * Controls whether ignore orientation request logic in {@link DisplayArea} is disabled 4434 * at runtime and how to optionally map some requested orientations to others. 4435 * 4436 * <p>Note: this assumes that {@link #mGlobalLock} is held by the caller. 4437 * 4438 * @param isIgnoreOrientationRequestDisabled when {@code true}, the system always ignores the 4439 * value of {@link DisplayArea#getIgnoreOrientationRequest} and app requested 4440 * orientation is respected. 4441 * @param fromOrientations The orientations we want to map to the correspondent orientations 4442 * in toOrientation. 4443 * @param toOrientations The orientations we map to the ones in fromOrientations at the same 4444 * index 4445 */ setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled, @Nullable int[] fromOrientations, @Nullable int[] toOrientations)4446 void setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled, 4447 @Nullable int[] fromOrientations, @Nullable int[] toOrientations) { 4448 mOrientationMapping.clear(); 4449 if (fromOrientations != null && toOrientations != null 4450 && fromOrientations.length == toOrientations.length) { 4451 for (int i = 0; i < fromOrientations.length; i++) { 4452 mOrientationMapping.put(fromOrientations[i], toOrientations[i]); 4453 } 4454 } 4455 if (isIgnoreOrientationRequestDisabled == mIsIgnoreOrientationRequestDisabled) { 4456 return; 4457 } 4458 mIsIgnoreOrientationRequestDisabled = isIgnoreOrientationRequestDisabled; 4459 for (int i = mRoot.getChildCount() - 1; i >= 0; i--) { 4460 mRoot.getChildAt(i).onIsIgnoreOrientationRequestDisabledChanged(); 4461 } 4462 } 4463 4464 /** 4465 * When {@link mIsIgnoreOrientationRequestDisabled} is {@value true} this method returns the 4466 * orientation to use in place of the one in input. It returns the same requestedOrientation in 4467 * input otherwise. 4468 * 4469 * @param requestedOrientation The orientation that can be mapped. 4470 * @return The orientation to use in place of requestedOrientation. 4471 */ mapOrientationRequest(int requestedOrientation)4472 int mapOrientationRequest(int requestedOrientation) { 4473 if (!mIsIgnoreOrientationRequestDisabled) { 4474 return requestedOrientation; 4475 } 4476 return mOrientationMapping.get(requestedOrientation, requestedOrientation); 4477 } 4478 4479 /** 4480 * Whether the system ignores the value of {@link DisplayArea#getIgnoreOrientationRequest} and 4481 * app requested orientation is respected. 4482 * 4483 * <p>Note: this assumes that {@link #mGlobalLock} is held by the caller. 4484 */ isIgnoreOrientationRequestDisabled()4485 boolean isIgnoreOrientationRequestDisabled() { 4486 return mIsIgnoreOrientationRequestDisabled 4487 || !mAppCompatConfiguration.isIgnoreOrientationRequestAllowed(); 4488 } 4489 4490 @Override freezeRotation(int rotation, String caller)4491 public void freezeRotation(int rotation, String caller) { 4492 freezeDisplayRotation(Display.DEFAULT_DISPLAY, rotation, caller); 4493 } 4494 4495 /** 4496 * Freeze rotation changes. (Enable "rotation lock".) 4497 * Persists across reboots. 4498 * @param displayId The ID of the display to freeze. 4499 * @param rotation The desired rotation to freeze to, or -1 to use the current rotation. 4500 */ 4501 @Override freezeDisplayRotation(int displayId, int rotation, String caller)4502 public void freezeDisplayRotation(int displayId, int rotation, String caller) { 4503 // TODO(multi-display): Track which display is rotated. 4504 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 4505 "freezeRotation()")) { 4506 throw new SecurityException("Requires SET_ORIENTATION permission"); 4507 } 4508 if (rotation < -1 || rotation > Surface.ROTATION_270) { 4509 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 4510 + "rotation constant."); 4511 } 4512 ProtoLog.v(WM_DEBUG_ORIENTATION, 4513 "freezeDisplayRotation: current rotation=%d, new rotation=%d, caller=%s", 4514 getDefaultDisplayRotation(), rotation, caller); 4515 4516 final long origId = Binder.clearCallingIdentity(); 4517 try { 4518 synchronized (mGlobalLock) { 4519 final DisplayContent display = mRoot.getDisplayContent(displayId); 4520 if (display == null) { 4521 Slog.w(TAG, "Trying to freeze rotation for a missing display."); 4522 return; 4523 } 4524 display.getDisplayRotation().freezeRotation(rotation, caller); 4525 } 4526 } finally { 4527 Binder.restoreCallingIdentity(origId); 4528 } 4529 4530 updateRotationUnchecked(false, false); 4531 } 4532 4533 @Override thawRotation(String caller)4534 public void thawRotation(String caller) { 4535 thawDisplayRotation(Display.DEFAULT_DISPLAY, caller); 4536 } 4537 4538 /** 4539 * Thaw rotation changes. (Disable "rotation lock".) 4540 * Persists across reboots. 4541 */ 4542 @Override thawDisplayRotation(int displayId, String caller)4543 public void thawDisplayRotation(int displayId, String caller) { 4544 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 4545 "thawRotation()")) { 4546 throw new SecurityException("Requires SET_ORIENTATION permission"); 4547 } 4548 4549 ProtoLog.v(WM_DEBUG_ORIENTATION, "thawRotation: mRotation=%d, caller=%s", 4550 getDefaultDisplayRotation(), caller); 4551 4552 final long origId = Binder.clearCallingIdentity(); 4553 try { 4554 synchronized (mGlobalLock) { 4555 final DisplayContent display = mRoot.getDisplayContent(displayId); 4556 if (display == null) { 4557 Slog.w(TAG, "Trying to thaw rotation for a missing display."); 4558 return; 4559 } 4560 display.getDisplayRotation().thawRotation(caller); 4561 } 4562 } finally { 4563 Binder.restoreCallingIdentity(origId); 4564 } 4565 4566 updateRotationUnchecked(false, false); 4567 } 4568 4569 @Override isRotationFrozen()4570 public boolean isRotationFrozen() { 4571 return isDisplayRotationFrozen(Display.DEFAULT_DISPLAY); 4572 } 4573 4574 @Override isDisplayRotationFrozen(int displayId)4575 public boolean isDisplayRotationFrozen(int displayId) { 4576 synchronized (mGlobalLock) { 4577 final DisplayContent display = mRoot.getDisplayContent(displayId); 4578 if (display == null) { 4579 Slog.w(TAG, "Trying to check if rotation is frozen on a missing display."); 4580 return false; 4581 } 4582 return display.getDisplayRotation().isRotationFrozen(); 4583 } 4584 } 4585 4586 @Override getDisplayUserRotation(int displayId)4587 public int getDisplayUserRotation(int displayId) { 4588 synchronized (mGlobalLock) { 4589 final DisplayContent display = mRoot.getDisplayContent(displayId); 4590 if (display == null) { 4591 Slog.w(TAG, "Trying to get user rotation of a missing display."); 4592 return -1; 4593 } 4594 return display.getDisplayRotation().getUserRotation(); 4595 } 4596 } 4597 4598 /** 4599 * Recalculate the current rotation. 4600 * 4601 * Called by the window manager policy whenever the state of the system changes 4602 * such that the current rotation might need to be updated, such as when the 4603 * device is docked or rotated into a new posture. 4604 */ 4605 @Override updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout)4606 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 4607 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 4608 } 4609 updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout)4610 private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 4611 ProtoLog.v(WM_DEBUG_ORIENTATION, "updateRotationUnchecked:" 4612 + " alwaysSendConfiguration=%b forceRelayout=%b", 4613 alwaysSendConfiguration, forceRelayout); 4614 4615 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation"); 4616 4617 final long origId = Binder.clearCallingIdentity(); 4618 4619 try { 4620 synchronized (mGlobalLock) { 4621 boolean layoutNeeded = false; 4622 final int displayCount = mRoot.mChildren.size(); 4623 for (int i = 0; i < displayCount; ++i) { 4624 final DisplayContent displayContent = mRoot.mChildren.get(i); 4625 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display"); 4626 final boolean rotationChanged = displayContent.updateRotationUnchecked(); 4627 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4628 4629 if (rotationChanged) { 4630 mAtmService.getTaskChangeNotificationController() 4631 .notifyOnActivityRotation(displayContent.mDisplayId); 4632 } 4633 4634 final boolean pendingRemoteDisplayChange = rotationChanged 4635 && (displayContent.mRemoteDisplayChangeController 4636 .isWaitingForRemoteDisplayChange() 4637 || displayContent.mTransitionController.isCollecting()); 4638 // Even if alwaysSend, we are waiting for a transition or remote to provide 4639 // updated configuration, so we can't update configuration yet. 4640 if (!pendingRemoteDisplayChange) { 4641 // The layout-needed flag will be set if there is a rotation change, so 4642 // only set it if the caller requests to force relayout. 4643 if (forceRelayout) { 4644 displayContent.setLayoutNeeded(); 4645 layoutNeeded = true; 4646 } 4647 if (rotationChanged || alwaysSendConfiguration) { 4648 displayContent.sendNewConfiguration(); 4649 } 4650 } 4651 } 4652 4653 if (layoutNeeded) { 4654 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, 4655 "updateRotation: performSurfacePlacement"); 4656 mWindowPlacerLocked.performSurfacePlacement(); 4657 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4658 } 4659 } 4660 } finally { 4661 Binder.restoreCallingIdentity(origId); 4662 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4663 } 4664 } 4665 4666 @Override getDefaultDisplayRotation()4667 public int getDefaultDisplayRotation() { 4668 synchronized (mGlobalLock) { 4669 return getDefaultDisplayContentLocked().getRotation(); 4670 } 4671 } 4672 4673 @Override setDisplayChangeWindowController(IDisplayChangeWindowController controller)4674 public void setDisplayChangeWindowController(IDisplayChangeWindowController controller) { 4675 mAtmService.enforceTaskPermission("setDisplayWindowRotationController"); 4676 try { 4677 synchronized (mGlobalLock) { 4678 if (mDisplayChangeController != null) { 4679 mDisplayChangeController.asBinder().unlinkToDeath( 4680 mDisplayChangeControllerDeath, 0); 4681 mDisplayChangeController = null; 4682 } 4683 controller.asBinder().linkToDeath(mDisplayChangeControllerDeath, 0); 4684 mDisplayChangeController = controller; 4685 } 4686 } catch (RemoteException e) { 4687 throw new RuntimeException("Unable to set rotation controller", e); 4688 } 4689 } 4690 4691 @EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS) 4692 @Override addShellRoot(int displayId, IWindow client, @WindowManager.ShellRootLayer int shellRootLayer)4693 public SurfaceControl addShellRoot(int displayId, IWindow client, 4694 @WindowManager.ShellRootLayer int shellRootLayer) { 4695 addShellRoot_enforcePermission(); 4696 final long origId = Binder.clearCallingIdentity(); 4697 try { 4698 synchronized (mGlobalLock) { 4699 final DisplayContent dc = mRoot.getDisplayContent(displayId); 4700 if (dc == null) { 4701 return null; 4702 } 4703 return dc.addShellRoot(client, shellRootLayer); 4704 } 4705 } finally { 4706 Binder.restoreCallingIdentity(origId); 4707 } 4708 } 4709 4710 @EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS) 4711 @Override setShellRootAccessibilityWindow(int displayId, @WindowManager.ShellRootLayer int shellRootLayer, IWindow target)4712 public void setShellRootAccessibilityWindow(int displayId, 4713 @WindowManager.ShellRootLayer int shellRootLayer, IWindow target) { 4714 setShellRootAccessibilityWindow_enforcePermission(); 4715 final long origId = Binder.clearCallingIdentity(); 4716 try { 4717 synchronized (mGlobalLock) { 4718 final DisplayContent dc = mRoot.getDisplayContent(displayId); 4719 if (dc == null) { 4720 return; 4721 } 4722 ShellRoot root = dc.mShellRoots.get(shellRootLayer); 4723 if (root == null) { 4724 return; 4725 } 4726 root.setAccessibilityWindow(target); 4727 } 4728 } finally { 4729 Binder.restoreCallingIdentity(origId); 4730 } 4731 } 4732 4733 @EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS) 4734 @Override setDisplayWindowInsetsController( int displayId, IDisplayWindowInsetsController insetsController)4735 public void setDisplayWindowInsetsController( 4736 int displayId, IDisplayWindowInsetsController insetsController) { 4737 setDisplayWindowInsetsController_enforcePermission(); 4738 final long origId = Binder.clearCallingIdentity(); 4739 try { 4740 synchronized (mGlobalLock) { 4741 final DisplayContent dc = mRoot.getDisplayContent(displayId); 4742 if (dc == null) { 4743 return; 4744 } 4745 dc.setRemoteInsetsController(insetsController); 4746 } 4747 } finally { 4748 Binder.restoreCallingIdentity(origId); 4749 } 4750 } 4751 4752 @EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS) 4753 @Override updateDisplayWindowRequestedVisibleTypes(int displayId, @InsetsType int visibleTypes, @InsetsType int mask, @Nullable ImeTracker.Token statsToken)4754 public void updateDisplayWindowRequestedVisibleTypes(int displayId, 4755 @InsetsType int visibleTypes, @InsetsType int mask, 4756 @Nullable ImeTracker.Token statsToken) { 4757 updateDisplayWindowRequestedVisibleTypes_enforcePermission(); 4758 final long origId = Binder.clearCallingIdentity(); 4759 try { 4760 synchronized (mGlobalLock) { 4761 final DisplayContent dc = mRoot.getDisplayContent(displayId); 4762 if (dc == null || dc.mRemoteInsetsControlTarget == null) { 4763 ImeTracker.forLogging().onFailed(statsToken, 4764 ImeTracker.PHASE_WM_UPDATE_DISPLAY_WINDOW_REQUESTED_VISIBLE_TYPES); 4765 return; 4766 } 4767 ImeTracker.forLogging().onProgress(statsToken, 4768 ImeTracker.PHASE_WM_UPDATE_DISPLAY_WINDOW_REQUESTED_VISIBLE_TYPES); 4769 final @InsetsType int changedTypes = 4770 dc.mRemoteInsetsControlTarget.updateRequestedVisibleTypes( 4771 visibleTypes, mask); 4772 // TODO(b/353463205) the statsToken shouldn't be null as it is used later in the 4773 // IME provider. Check if we have to create a new request here, if null. 4774 dc.getInsetsStateController().onRequestedVisibleTypesChanged( 4775 dc.mRemoteInsetsControlTarget, changedTypes, statsToken); 4776 } 4777 } finally { 4778 Binder.restoreCallingIdentity(origId); 4779 } 4780 } 4781 4782 @EnforcePermission(android.Manifest.permission.MANAGE_APP_TOKENS) 4783 @Override updateDisplayWindowAnimatingTypes(int displayId, @InsetsType int animatingTypes, @Nullable ImeTracker.Token statsToken)4784 public void updateDisplayWindowAnimatingTypes(int displayId, @InsetsType int animatingTypes, 4785 @Nullable ImeTracker.Token statsToken) { 4786 updateDisplayWindowAnimatingTypes_enforcePermission(); 4787 if (android.view.inputmethod.Flags.reportAnimatingInsetsTypes()) { 4788 final long origId = Binder.clearCallingIdentity(); 4789 try { 4790 synchronized (mGlobalLock) { 4791 final DisplayContent dc = mRoot.getDisplayContent(displayId); 4792 if (dc == null || dc.mRemoteInsetsControlTarget == null) { 4793 ImeTracker.forLogging().onFailed(statsToken, 4794 ImeTracker.PHASE_WM_UPDATE_DISPLAY_WINDOW_ANIMATING_TYPES); 4795 return; 4796 } 4797 ImeTracker.forLogging().onProgress(statsToken, 4798 ImeTracker.PHASE_WM_UPDATE_DISPLAY_WINDOW_ANIMATING_TYPES); 4799 dc.mRemoteInsetsControlTarget.setAnimatingTypes(animatingTypes, statsToken); 4800 } 4801 } finally { 4802 Binder.restoreCallingIdentity(origId); 4803 } 4804 } 4805 } 4806 4807 @Override watchRotation(IRotationWatcher watcher, int displayId)4808 public int watchRotation(IRotationWatcher watcher, int displayId) { 4809 final DisplayContent displayContent; 4810 synchronized (mGlobalLock) { 4811 displayContent = mRoot.getDisplayContent(displayId); 4812 if (displayContent == null) { 4813 throw new IllegalArgumentException("Trying to register rotation event " 4814 + "for invalid display: " + displayId); 4815 } 4816 mRotationWatcherController.registerDisplayRotationWatcher(watcher, displayId); 4817 return displayContent.getRotation(); 4818 } 4819 } 4820 4821 @Override removeRotationWatcher(IRotationWatcher watcher)4822 public void removeRotationWatcher(IRotationWatcher watcher) { 4823 synchronized (mGlobalLock) { 4824 mRotationWatcherController.removeRotationWatcher(watcher); 4825 } 4826 } 4827 4828 @Surface.Rotation 4829 @Override registerProposedRotationListener(IBinder contextToken, IRotationWatcher listener)4830 public int registerProposedRotationListener(IBinder contextToken, IRotationWatcher listener) { 4831 synchronized (mGlobalLock) { 4832 final WindowContainer<?> wc = 4833 mRotationWatcherController.getAssociatedWindowContainer(contextToken); 4834 if (wc == null) { 4835 Slog.w(TAG, "Register rotation listener from non-existing token, uid=" 4836 + Binder.getCallingUid()); 4837 return Surface.ROTATION_0; 4838 } 4839 mRotationWatcherController.registerProposedRotationListener(listener, contextToken); 4840 final WindowOrientationListener orientationListener = 4841 wc.mDisplayContent.getDisplayRotation().getOrientationListener(); 4842 if (orientationListener != null) { 4843 // It may be -1 if sensor is disabled. 4844 final int rotation = orientationListener.getProposedRotation(); 4845 if (rotation >= Surface.ROTATION_0) { 4846 return rotation; 4847 } 4848 } 4849 return wc.getWindowConfiguration().getRotation(); 4850 } 4851 } 4852 4853 @Override registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener, int displayId)4854 public boolean registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener, 4855 int displayId) { 4856 synchronized (mGlobalLock) { 4857 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 4858 if (displayContent == null) { 4859 throw new IllegalArgumentException("Trying to register visibility event " 4860 + "for invalid display: " + displayId); 4861 } 4862 mWallpaperVisibilityListeners.registerWallpaperVisibilityListener(listener, displayId); 4863 return displayContent.mWallpaperController.isWallpaperVisible(); 4864 } 4865 } 4866 4867 @Override unregisterWallpaperVisibilityListener(IWallpaperVisibilityListener listener, int displayId)4868 public void unregisterWallpaperVisibilityListener(IWallpaperVisibilityListener listener, 4869 int displayId) { 4870 synchronized (mGlobalLock) { 4871 mWallpaperVisibilityListeners 4872 .unregisterWallpaperVisibilityListener(listener, displayId); 4873 } 4874 } 4875 4876 @Override registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener, int displayId)4877 public void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener, 4878 int displayId) { 4879 synchronized (mGlobalLock) { 4880 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 4881 if (displayContent == null) { 4882 throw new IllegalArgumentException( 4883 "Trying to register system gesture exclusion event for invalid display: " 4884 + displayId); 4885 } 4886 displayContent.registerSystemGestureExclusionListener(listener); 4887 } 4888 } 4889 4890 @Override unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener, int displayId)4891 public void unregisterSystemGestureExclusionListener(ISystemGestureExclusionListener listener, 4892 int displayId) { 4893 synchronized (mGlobalLock) { 4894 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 4895 if (displayContent == null) { 4896 throw new IllegalArgumentException( 4897 "Trying to unregister system gesture exclusion event for invalid display: " 4898 + displayId); 4899 } 4900 displayContent.unregisterSystemGestureExclusionListener(listener); 4901 } 4902 } 4903 4904 @Override registerDecorViewGestureListener( IDecorViewGestureListener listener, int displayId)4905 public void registerDecorViewGestureListener( 4906 IDecorViewGestureListener listener, int displayId) { 4907 if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT, 4908 "registerDecorViewGestureListener()")) { 4909 throw new SecurityException("Requires MONITOR_INPUT permission"); 4910 } 4911 synchronized (mGlobalLock) { 4912 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 4913 if (displayContent == null) { 4914 throw new IllegalArgumentException( 4915 "Trying to register DecorView gesture event listener" 4916 + "for invalid display: " 4917 + displayId); 4918 } 4919 displayContent.registerDecorViewGestureListener(listener); 4920 } 4921 } 4922 4923 @Override unregisterDecorViewGestureListener( IDecorViewGestureListener listener, int displayId)4924 public void unregisterDecorViewGestureListener( 4925 IDecorViewGestureListener listener, int displayId) { 4926 if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT, 4927 "unregisterSystemGestureExclusionListener()")) { 4928 throw new SecurityException("Requires MONITOR_INPUT permission"); 4929 } 4930 synchronized (mGlobalLock) { 4931 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 4932 if (displayContent == null) { 4933 throw new IllegalArgumentException( 4934 "Trying to unregister DecorView gesture event listener" 4935 + "for invalid display: " 4936 + displayId); 4937 } 4938 displayContent.unregisterDecorViewGestureListener(listener); 4939 } 4940 } 4941 reportDecorViewGestureChanged(Session session, IWindow window, boolean intercepted)4942 void reportDecorViewGestureChanged(Session session, IWindow window, boolean intercepted) { 4943 synchronized (mGlobalLock) { 4944 final WindowState win = 4945 windowForClientLocked(session, window, false /* throwOnError */); 4946 if (win == null) { 4947 return; 4948 } 4949 win.getDisplayContent() 4950 .updateDecorViewGestureIntercepted(win.mToken.token, intercepted); 4951 } 4952 } 4953 reportSystemGestureExclusionChanged(Session session, IWindow window, List<Rect> exclusionRects)4954 void reportSystemGestureExclusionChanged(Session session, IWindow window, 4955 List<Rect> exclusionRects) { 4956 synchronized (mGlobalLock) { 4957 final WindowState win = windowForClientLocked(session, window, 4958 false /* throwOnError */); 4959 if (win == null) { 4960 Slog.i(TAG_WM, 4961 "reportSystemGestureExclusionChanged(): No window state for package:" 4962 + session.mPackageName); 4963 return; 4964 } 4965 if (win.setSystemGestureExclusion(exclusionRects)) { 4966 win.getDisplayContent().updateSystemGestureExclusion(); 4967 } 4968 } 4969 } 4970 reportKeepClearAreasChanged(Session session, IWindow window, List<Rect> restricted, List<Rect> unrestricted)4971 void reportKeepClearAreasChanged(Session session, IWindow window, 4972 List<Rect> restricted, List<Rect> unrestricted) { 4973 synchronized (mGlobalLock) { 4974 final WindowState win = windowForClientLocked(session, window, 4975 false /* throwOnError */); 4976 if (win == null) { 4977 Slog.i(TAG_WM, 4978 "reportKeepClearAreasChanged(): No window state for package:" 4979 + session.mPackageName); 4980 return; 4981 } 4982 if (win.setKeepClearAreas(restricted, unrestricted)) { 4983 win.getDisplayContent().updateKeepClearAreas(); 4984 } 4985 } 4986 } 4987 4988 @Override registerDisplayFoldListener(IDisplayFoldListener listener)4989 public void registerDisplayFoldListener(IDisplayFoldListener listener) { 4990 mPolicy.registerDisplayFoldListener(listener); 4991 } 4992 4993 @Override unregisterDisplayFoldListener(IDisplayFoldListener listener)4994 public void unregisterDisplayFoldListener(IDisplayFoldListener listener) { 4995 mPolicy.unregisterDisplayFoldListener(listener); 4996 } 4997 4998 /** 4999 * Overrides the folded area. 5000 * 5001 * @param area the overriding folded area or an empty {@code Rect} to clear the override. 5002 */ setOverrideFoldedArea(@onNull Rect area)5003 void setOverrideFoldedArea(@NonNull Rect area) { 5004 if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS) 5005 != PackageManager.PERMISSION_GRANTED) { 5006 throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS); 5007 } 5008 5009 final long origId = Binder.clearCallingIdentity(); 5010 try { 5011 synchronized (mGlobalLock) { 5012 mPolicy.setOverrideFoldedArea(area); 5013 } 5014 } finally { 5015 Binder.restoreCallingIdentity(origId); 5016 } 5017 } 5018 5019 /** 5020 * Get the display folded area. 5021 */ getFoldedArea()5022 @NonNull Rect getFoldedArea() { 5023 final long origId = Binder.clearCallingIdentity(); 5024 try { 5025 synchronized (mGlobalLock) { 5026 return mPolicy.getFoldedArea(); 5027 } 5028 } finally { 5029 Binder.restoreCallingIdentity(origId); 5030 } 5031 } 5032 5033 /** 5034 * Registers a hierarchy listener that gets callbacks when the hierarchy changes. The listener's 5035 * onDisplayAdded() will not be called for the displays returned. 5036 * 5037 * @return the displayIds for the existing displays 5038 */ 5039 @Override registerDisplayWindowListener(IDisplayWindowListener listener)5040 public int[] registerDisplayWindowListener(IDisplayWindowListener listener) { 5041 mAtmService.enforceTaskPermission("registerDisplayWindowListener"); 5042 final long ident = Binder.clearCallingIdentity(); 5043 try { 5044 return mDisplayNotificationController.registerListener(listener); 5045 } finally { 5046 Binder.restoreCallingIdentity(ident); 5047 } 5048 } 5049 5050 /** Unregister a hierarchy listener so that it stops receiving callbacks. */ 5051 @Override unregisterDisplayWindowListener(IDisplayWindowListener listener)5052 public void unregisterDisplayWindowListener(IDisplayWindowListener listener) { 5053 mAtmService.enforceTaskPermission("unregisterDisplayWindowListener"); 5054 mDisplayNotificationController.unregisterListener(listener); 5055 } 5056 5057 @Override getPreferredOptionsPanelGravity(int displayId)5058 public int getPreferredOptionsPanelGravity(int displayId) { 5059 synchronized (mGlobalLock) { 5060 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 5061 if (displayContent == null) { 5062 return Gravity.CENTER | Gravity.BOTTOM; 5063 } 5064 return displayContent.getPreferredOptionsPanelGravity(); 5065 } 5066 } 5067 5068 /** 5069 * Starts the view server on the specified port. 5070 * 5071 * @param port The port to listener to. 5072 * 5073 * @return True if the server was successfully started, false otherwise. 5074 * 5075 * @see com.android.server.wm.ViewServer 5076 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 5077 */ 5078 @Override startViewServer(int port)5079 public boolean startViewServer(int port) { 5080 if (isSystemSecure()) { 5081 return false; 5082 } 5083 5084 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 5085 return false; 5086 } 5087 5088 if (port < 1024) { 5089 return false; 5090 } 5091 5092 if (mViewServer != null) { 5093 if (!mViewServer.isRunning()) { 5094 try { 5095 return mViewServer.start(); 5096 } catch (IOException e) { 5097 ProtoLog.w(WM_ERROR, "View server did not start"); 5098 } 5099 } 5100 return false; 5101 } 5102 5103 try { 5104 mViewServer = new ViewServer(this, port); 5105 return mViewServer.start(); 5106 } catch (IOException e) { 5107 ProtoLog.w(WM_ERROR, "View server did not start"); 5108 } 5109 return false; 5110 } 5111 isSystemSecure()5112 private boolean isSystemSecure() { 5113 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 5114 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 5115 } 5116 5117 /** 5118 * Stops the view server if it exists. 5119 * 5120 * @return True if the server stopped, false if it wasn't started or 5121 * couldn't be stopped. 5122 * 5123 * @see com.android.server.wm.ViewServer 5124 */ 5125 @Override stopViewServer()5126 public boolean stopViewServer() { 5127 if (isSystemSecure()) { 5128 return false; 5129 } 5130 5131 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 5132 return false; 5133 } 5134 5135 if (mViewServer != null) { 5136 return mViewServer.stop(); 5137 } 5138 return false; 5139 } 5140 5141 /** 5142 * Indicates whether the view server is running. 5143 * 5144 * @return True if the server is running, false otherwise. 5145 * 5146 * @see com.android.server.wm.ViewServer 5147 */ 5148 @Override isViewServerRunning()5149 public boolean isViewServerRunning() { 5150 if (isSystemSecure()) { 5151 return false; 5152 } 5153 5154 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 5155 return false; 5156 } 5157 5158 return mViewServer != null && mViewServer.isRunning(); 5159 } 5160 5161 /** 5162 * Lists all available windows in the system. The listing is written in the specified Socket's 5163 * output stream with the following syntax: windowHashCodeInHexadecimal windowName 5164 * Each line of the output represents a different window. 5165 * 5166 * @param client The remote client to send the listing to. 5167 * @return false if an error occurred, true otherwise. 5168 */ viewServerListWindows(Socket client)5169 boolean viewServerListWindows(Socket client) { 5170 if (isSystemSecure()) { 5171 return false; 5172 } 5173 5174 boolean result = true; 5175 5176 final ArrayList<WindowState> windows = new ArrayList(); 5177 synchronized (mGlobalLock) { 5178 mRoot.forAllWindows(w -> { 5179 windows.add(w); 5180 }, false /* traverseTopToBottom */); 5181 } 5182 5183 BufferedWriter out = null; 5184 5185 // Any uncaught exception will crash the system process 5186 try { 5187 OutputStream clientStream = client.getOutputStream(); 5188 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 5189 5190 final int count = windows.size(); 5191 for (int i = 0; i < count; i++) { 5192 final WindowState w = windows.get(i); 5193 out.write(Integer.toHexString(System.identityHashCode(w))); 5194 out.write(' '); 5195 out.append(w.mAttrs.getTitle()); 5196 out.write('\n'); 5197 } 5198 5199 out.write("DONE.\n"); 5200 out.flush(); 5201 } catch (Exception e) { 5202 result = false; 5203 } finally { 5204 if (out != null) { 5205 try { 5206 out.close(); 5207 } catch (IOException e) { 5208 result = false; 5209 } 5210 } 5211 } 5212 5213 return result; 5214 } 5215 5216 // TODO(multidisplay): Extend to multiple displays. 5217 /** 5218 * Returns the focused window in the following format: 5219 * windowHashCodeInHexadecimal windowName 5220 * 5221 * @param client The remote client to send the listing to. 5222 * @return False if an error occurred, true otherwise. 5223 */ viewServerGetFocusedWindow(Socket client)5224 boolean viewServerGetFocusedWindow(Socket client) { 5225 if (isSystemSecure()) { 5226 return false; 5227 } 5228 5229 boolean result = true; 5230 5231 WindowState focusedWindow = getFocusedWindow(); 5232 5233 BufferedWriter out = null; 5234 5235 // Any uncaught exception will crash the system process 5236 try { 5237 OutputStream clientStream = client.getOutputStream(); 5238 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 5239 5240 if(focusedWindow != null) { 5241 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 5242 out.write(' '); 5243 out.append(focusedWindow.mAttrs.getTitle()); 5244 } 5245 out.write('\n'); 5246 out.flush(); 5247 } catch (Exception e) { 5248 result = false; 5249 } finally { 5250 if (out != null) { 5251 try { 5252 out.close(); 5253 } catch (IOException e) { 5254 result = false; 5255 } 5256 } 5257 } 5258 5259 return result; 5260 } 5261 5262 /** 5263 * Sends a command to a target window. The result of the command, if any, will be 5264 * written in the output stream of the specified socket. 5265 * 5266 * The parameters must follow this syntax: 5267 * windowHashcode extra 5268 * 5269 * Where XX is the length in characeters of the windowTitle. 5270 * 5271 * The first parameter is the target window. The window with the specified hashcode 5272 * will be the target. If no target can be found, nothing happens. The extra parameters 5273 * will be delivered to the target window and as parameters to the command itself. 5274 * 5275 * @param client The remote client to sent the result, if any, to. 5276 * @param command The command to execute. 5277 * @param parameters The command parameters. 5278 * 5279 * @return True if the command was successfully delivered, false otherwise. This does 5280 * not indicate whether the command itself was successful. 5281 */ viewServerWindowCommand(Socket client, String command, String parameters)5282 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 5283 if (isSystemSecure()) { 5284 return false; 5285 } 5286 5287 boolean success = true; 5288 Parcel data = null; 5289 Parcel reply = null; 5290 5291 BufferedWriter out = null; 5292 5293 // Any uncaught exception will crash the system process 5294 try { 5295 // Find the hashcode of the window 5296 int index = parameters.indexOf(' '); 5297 if (index == -1) { 5298 index = parameters.length(); 5299 } 5300 final String code = parameters.substring(0, index); 5301 int hashCode = (int) Long.parseLong(code, 16); 5302 5303 // Extract the command's parameter after the window description 5304 if (index < parameters.length()) { 5305 parameters = parameters.substring(index + 1); 5306 } else { 5307 parameters = ""; 5308 } 5309 5310 final WindowState window = findWindow(hashCode); 5311 if (window == null) { 5312 return false; 5313 } 5314 5315 data = Parcel.obtain(); 5316 data.writeInterfaceToken("android.view.IWindow"); 5317 data.writeString(command); 5318 data.writeString(parameters); 5319 data.writeInt(1); 5320 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 5321 5322 reply = Parcel.obtain(); 5323 5324 final IBinder binder = window.mClient.asBinder(); 5325 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 5326 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 5327 5328 reply.readException(); 5329 5330 if (!client.isOutputShutdown()) { 5331 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 5332 out.write("DONE\n"); 5333 out.flush(); 5334 } 5335 5336 } catch (Exception e) { 5337 ProtoLog.w(WM_ERROR, "Could not send command %s with parameters %s. %s", command, 5338 parameters, e); 5339 success = false; 5340 } finally { 5341 if (data != null) { 5342 data.recycle(); 5343 } 5344 if (reply != null) { 5345 reply.recycle(); 5346 } 5347 if (out != null) { 5348 try { 5349 out.close(); 5350 } catch (IOException e) { 5351 5352 } 5353 } 5354 } 5355 5356 return success; 5357 } 5358 addWindowChangeListener(WindowChangeListener listener)5359 void addWindowChangeListener(WindowChangeListener listener) { 5360 synchronized (mGlobalLock) { 5361 mWindowChangeListeners.add(listener); 5362 } 5363 } 5364 removeWindowChangeListener(WindowChangeListener listener)5365 void removeWindowChangeListener(WindowChangeListener listener) { 5366 synchronized (mGlobalLock) { 5367 mWindowChangeListeners.remove(listener); 5368 } 5369 } 5370 addWindowFocusChangeListener(WindowFocusChangeListener listener)5371 void addWindowFocusChangeListener(WindowFocusChangeListener listener) { 5372 synchronized (mGlobalLock) { 5373 mWindowFocusChangeListeners.add(listener); 5374 } 5375 } 5376 removeWindowFocusChangeListener(WindowFocusChangeListener listener)5377 void removeWindowFocusChangeListener(WindowFocusChangeListener listener) { 5378 synchronized (mGlobalLock) { 5379 mWindowFocusChangeListeners.remove(listener); 5380 } 5381 } 5382 notifyWindowRemovedListeners(IBinder client)5383 private void notifyWindowRemovedListeners(IBinder client) { 5384 OnWindowRemovedListener[] windowRemovedListeners; 5385 synchronized (mGlobalLock) { 5386 if (mOnWindowRemovedListeners.isEmpty()) { 5387 return; 5388 } 5389 windowRemovedListeners = new OnWindowRemovedListener[mOnWindowRemovedListeners.size()]; 5390 mOnWindowRemovedListeners.toArray(windowRemovedListeners); 5391 } 5392 mH.post(() -> { 5393 int size = windowRemovedListeners.length; 5394 for (int i = 0; i < size; i++) { 5395 windowRemovedListeners[i].onWindowRemoved(client); 5396 } 5397 }); 5398 } 5399 notifyWindowsChanged()5400 private void notifyWindowsChanged() { 5401 WindowChangeListener[] windowChangeListeners; 5402 synchronized (mGlobalLock) { 5403 if(mWindowChangeListeners.isEmpty()) { 5404 return; 5405 } 5406 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 5407 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 5408 } 5409 int N = windowChangeListeners.length; 5410 for(int i = 0; i < N; i++) { 5411 windowChangeListeners[i].windowsChanged(); 5412 } 5413 } 5414 notifyFocusChanged(IBinder focusedWindowToken)5415 private void notifyFocusChanged(IBinder focusedWindowToken) { 5416 WindowFocusChangeListener[] windowFocusChangeListeners; 5417 synchronized (mGlobalLock) { 5418 if(mWindowFocusChangeListeners.isEmpty()) { 5419 return; 5420 } 5421 windowFocusChangeListeners = 5422 new WindowFocusChangeListener[mWindowFocusChangeListeners.size()]; 5423 mWindowFocusChangeListeners.toArray(windowFocusChangeListeners); 5424 } 5425 int N = windowFocusChangeListeners.length; 5426 for(int i = 0; i < N; i++) { 5427 windowFocusChangeListeners[i].focusChanged(focusedWindowToken); 5428 } 5429 } 5430 findWindow(int hashCode)5431 private WindowState findWindow(int hashCode) { 5432 if (hashCode == -1) { 5433 // TODO(multidisplay): Extend to multiple displays. 5434 return getFocusedWindow(); 5435 } 5436 5437 synchronized (mGlobalLock) { 5438 return mRoot.getWindow((w) -> System.identityHashCode(w) == hashCode); 5439 } 5440 } 5441 computeNewConfiguration(int displayId)5442 public Configuration computeNewConfiguration(int displayId) { 5443 synchronized (mGlobalLock) { 5444 return computeNewConfigurationLocked(displayId); 5445 } 5446 } 5447 computeNewConfigurationLocked(int displayId)5448 private Configuration computeNewConfigurationLocked(int displayId) { 5449 if (!mDisplayReady) { 5450 return null; 5451 } 5452 final Configuration config = new Configuration(); 5453 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 5454 displayContent.computeScreenConfiguration(config); 5455 return config; 5456 } 5457 notifyHardKeyboardStatusChange()5458 void notifyHardKeyboardStatusChange() { 5459 final boolean available; 5460 final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener; 5461 synchronized (mGlobalLock) { 5462 listener = mHardKeyboardStatusChangeListener; 5463 available = mHardKeyboardAvailable; 5464 } 5465 if (listener != null) { 5466 listener.onHardKeyboardStatusChange(available); 5467 } 5468 } 5469 5470 // ------------------------------------------------------------- 5471 // Input Events and Focus Management 5472 // ------------------------------------------------------------- 5473 5474 final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this); 5475 private boolean mEventDispatchingEnabled; 5476 5477 @Override setEventDispatching(boolean enabled)5478 public void setEventDispatching(boolean enabled) { 5479 if (!checkCallingPermission(MANAGE_APP_TOKENS, "setEventDispatching()")) { 5480 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 5481 } 5482 5483 synchronized (mGlobalLock) { 5484 mEventDispatchingEnabled = enabled; 5485 if (mDisplayEnabled) { 5486 mInputManagerCallback.setEventDispatchingLw(enabled); 5487 } 5488 } 5489 } 5490 getFocusedWindow()5491 private WindowState getFocusedWindow() { 5492 synchronized (mGlobalLock) { 5493 return getFocusedWindowLocked(); 5494 } 5495 } 5496 getFocusedWindowLocked()5497 WindowState getFocusedWindowLocked() { 5498 // Return the focused window in the focused display. 5499 return mRoot.getTopFocusedDisplayContent().mCurrentFocus; 5500 } 5501 getImeFocusRootTaskLocked()5502 Task getImeFocusRootTaskLocked() { 5503 // Don't use mCurrentFocus.getStack() because it returns home stack for system windows. 5504 // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE 5505 // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved 5506 // to make room for IME, but the window is not the focused window that's taking input. 5507 // TODO (b/111080190): Consider the case of multiple IMEs on multi-display. 5508 final DisplayContent topFocusedDisplay = mRoot.getTopFocusedDisplayContent(); 5509 final ActivityRecord focusedApp = topFocusedDisplay.mFocusedApp; 5510 return (focusedApp != null && focusedApp.getTask() != null) 5511 ? focusedApp.getTask().getRootTask() : null; 5512 } 5513 detectSafeMode()5514 public boolean detectSafeMode() { 5515 if (!mInputManagerCallback.waitForInputDevicesReady( 5516 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 5517 ProtoLog.w(WM_ERROR, "Devices still not ready after waiting %d" 5518 + " milliseconds before attempting to detect safe mode.", 5519 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS); 5520 } 5521 5522 if (Settings.Global.getInt( 5523 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) { 5524 return false; 5525 } 5526 5527 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 5528 KeyEvent.KEYCODE_MENU); 5529 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 5530 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 5531 KeyEvent.KEYCODE_DPAD_CENTER); 5532 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 5533 InputManagerService.BTN_MOUSE); 5534 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 5535 KeyEvent.KEYCODE_VOLUME_DOWN); 5536 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 5537 || volumeDownState > 0; 5538 try { 5539 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0 5540 || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) { 5541 mSafeMode = true; 5542 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 5543 } 5544 } catch (IllegalArgumentException e) { 5545 } 5546 if (mSafeMode) { 5547 ProtoLog.i(WM_ERROR, "SAFE MODE ENABLED (menu=%d s=%d dpad=%d" 5548 + " trackball=%d)", menuState, sState, dpadState, trackballState); 5549 // May already be set if (for instance) this process has crashed 5550 if (SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) == 0) { 5551 SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1"); 5552 } 5553 } else { 5554 ProtoLog.i(WM_ERROR, "SAFE MODE not enabled"); 5555 } 5556 mPolicy.setSafeMode(mSafeMode); 5557 return mSafeMode; 5558 } 5559 displayReady()5560 public void displayReady() { 5561 synchronized (mGlobalLock) { 5562 if (mMaxUiWidth > 0) { 5563 mRoot.forAllDisplays(dc -> { 5564 if (dc.mDisplay.getType() == Display.TYPE_INTERNAL) { 5565 dc.setMaxUiWidth(mMaxUiWidth); 5566 } 5567 }); 5568 } 5569 applyForcedPropertiesForDefaultDisplay(); 5570 mAnimator.ready(); 5571 mDisplayReady = true; 5572 mHasWideColorGamutSupport = queryWideColorGamutSupport(); 5573 mHasHdrSupport = queryHdrSupport(); 5574 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 5575 PackageManager.FEATURE_TOUCHSCREEN); 5576 mIsFakeTouchDevice = mContext.getPackageManager().hasSystemFeature( 5577 PackageManager.FEATURE_FAKETOUCH); 5578 // Reconfigure all displays to make sure that the forced properties and 5579 // DisplayWindowSettings are applied. In addition, wide-color/hdr/isTouchDevice also 5580 // affect the Configuration. 5581 mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked); 5582 // Per-user display settings may leave outdated settings after user switches, especially 5583 // during reboots starting with the default user without setCurrentUser called. 5584 mDisplayWindowSettingsProvider.removeStaleDisplaySettingsLocked(this, mRoot); 5585 } 5586 } 5587 systemReady()5588 public void systemReady() { 5589 mSystemReady = true; 5590 mPolicy.systemReady(); 5591 mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady); 5592 mSnapshotController.systemReady(); 5593 UiThread.getHandler().post(mSettingsObserver::loadSettings); 5594 IVrManager vrManager = IVrManager.Stub.asInterface( 5595 ServiceManager.getService(Context.VR_SERVICE)); 5596 if (vrManager != null) { 5597 try { 5598 final boolean vrModeEnabled = vrManager.getVrModeState(); 5599 synchronized (mGlobalLock) { 5600 vrManager.registerListener(mVrStateCallbacks); 5601 if (vrModeEnabled) { 5602 mVrModeEnabled = vrModeEnabled; 5603 mVrStateCallbacks.onVrStateChanged(vrModeEnabled); 5604 } 5605 } 5606 } catch (RemoteException e) { 5607 // Ignore, we cannot do anything if we failed to register VR mode listener 5608 } 5609 } 5610 } 5611 5612 5613 // Keep logic in sync with SurfaceFlingerProperties.cpp 5614 // Consider exposing properties via ISurfaceComposer instead. queryWideColorGamutSupport()5615 private static boolean queryWideColorGamutSupport() { 5616 boolean defaultValue = false; 5617 Optional<Boolean> hasWideColorProp = SurfaceFlingerProperties.has_wide_color_display(); 5618 if (hasWideColorProp.isPresent()) { 5619 return hasWideColorProp.get(); 5620 } 5621 try { 5622 ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService(); 5623 OptionalBool hasWideColor = surfaceFlinger.hasWideColorDisplay(); 5624 if (hasWideColor != null) { 5625 return hasWideColor.value; 5626 } 5627 } catch (RemoteException e) { 5628 // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store 5629 } catch (NoSuchElementException e) { 5630 return defaultValue; 5631 } 5632 return false; 5633 } 5634 queryHdrSupport()5635 private static boolean queryHdrSupport() { 5636 boolean defaultValue = false; 5637 Optional<Boolean> hasHdrProp = SurfaceFlingerProperties.has_HDR_display(); 5638 if (hasHdrProp.isPresent()) { 5639 return hasHdrProp.get(); 5640 } 5641 try { 5642 ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService(); 5643 OptionalBool hasHdr = surfaceFlinger.hasHDRDisplay(); 5644 if (hasHdr != null) { 5645 return hasHdr.value; 5646 } 5647 } catch (RemoteException e) { 5648 // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store 5649 } catch (NoSuchElementException e) { 5650 return defaultValue; 5651 } 5652 return false; 5653 } 5654 5655 // Returns an input target which is mapped to the given input token. This can be a WindowState 5656 // or an embedded window. getInputTargetFromToken(IBinder inputToken)5657 @Nullable InputTarget getInputTargetFromToken(IBinder inputToken) { 5658 WindowState windowState = mInputToWindowMap.get(inputToken); 5659 if (windowState != null) { 5660 return windowState; 5661 } 5662 5663 EmbeddedWindowController.EmbeddedWindow embeddedWindow = 5664 mEmbeddedWindowController.get(inputToken); 5665 if (embeddedWindow != null) { 5666 return embeddedWindow; 5667 } 5668 5669 return null; 5670 } 5671 getInputTargetFromWindowTokenLocked(IBinder windowToken)5672 @Nullable InputTarget getInputTargetFromWindowTokenLocked(IBinder windowToken) { 5673 InputTarget window = mWindowMap.get(windowToken); 5674 if (window != null) { 5675 return window; 5676 } 5677 window = mEmbeddedWindowController.getByWindowToken(windowToken); 5678 return window; 5679 } 5680 reportFocusChanged(IBinder oldToken, IBinder newToken)5681 void reportFocusChanged(IBinder oldToken, IBinder newToken) { 5682 InputTarget lastTarget; 5683 InputTarget newTarget; 5684 synchronized (mGlobalLock) { 5685 lastTarget = getInputTargetFromToken(oldToken); 5686 newTarget = getInputTargetFromToken(newToken); 5687 if (newTarget == null && lastTarget == null) { 5688 Slog.v(TAG_WM, "Unknown focus tokens, dropping reportFocusChanged"); 5689 return; 5690 } 5691 mFocusedInputTarget = newTarget; 5692 5693 mAccessibilityController.onFocusChanged(lastTarget, newTarget); 5694 ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Focus changing: %s -> %s", lastTarget, newTarget); 5695 } 5696 5697 // Call WindowState focus change observers 5698 WindowState newFocusedWindow = newTarget != null ? newTarget.getWindowState() : null; 5699 if (newFocusedWindow != null && newFocusedWindow.mInputChannelToken == newToken) { 5700 mAnrController.onFocusChanged(newFocusedWindow); 5701 newFocusedWindow.reportFocusChangedSerialized(true); 5702 notifyFocusChanged(newTarget.getWindowToken()); 5703 } 5704 5705 WindowState lastFocusedWindow = lastTarget != null ? lastTarget.getWindowState() : null; 5706 if (lastFocusedWindow != null && lastFocusedWindow.mInputChannelToken == oldToken) { 5707 lastFocusedWindow.reportFocusChangedSerialized(false); 5708 } 5709 } 5710 5711 // ------------------------------------------------------------- 5712 // Async Handler 5713 // ------------------------------------------------------------- 5714 5715 final class H extends android.os.Handler { 5716 public static final int PERSIST_ANIMATION_SCALE = 14; 5717 public static final int ENABLE_SCREEN = 16; 5718 public static final int REPORT_WINDOWS_CHANGE = 19; 5719 5720 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 5721 public static final int BOOT_TIMEOUT = 23; 5722 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 5723 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 5724 5725 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 5726 5727 public static final int NEW_ANIMATOR_SCALE = 34; 5728 5729 public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36; 5730 5731 public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37; 5732 public static final int RESET_ANR_MESSAGE = 38; 5733 public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39; 5734 5735 public static final int UPDATE_MULTI_WINDOW_STACKS = 41; 5736 5737 public static final int UPDATE_ANIMATION_SCALE = 51; 5738 public static final int WINDOW_HIDE_TIMEOUT = 52; 5739 public static final int SET_HAS_OVERLAY_UI = 58; 5740 public static final int RECOMPUTE_FOCUS = 61; 5741 public static final int ON_POINTER_DOWN_OUTSIDE_FOCUS = 62; 5742 public static final int WINDOW_STATE_BLAST_SYNC_TIMEOUT = 64; 5743 public static final int REPARENT_TASK_TO_DEFAULT_DISPLAY = 65; 5744 public static final int INSETS_CHANGED = 66; 5745 5746 /** 5747 * Used to denote that an integer field in a message will not be used. 5748 */ 5749 public static final int UNUSED = 0; 5750 5751 @Override handleMessage(Message msg)5752 public void handleMessage(Message msg) { 5753 if (DEBUG_WINDOW_TRACE) { 5754 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what); 5755 } 5756 switch (msg.what) { 5757 case PERSIST_ANIMATION_SCALE: { 5758 Settings.Global.putFloat(mContext.getContentResolver(), 5759 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 5760 Settings.Global.putFloat(mContext.getContentResolver(), 5761 Settings.Global.TRANSITION_ANIMATION_SCALE, 5762 mTransitionAnimationScaleSetting); 5763 Settings.Global.putFloat(mContext.getContentResolver(), 5764 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 5765 break; 5766 } 5767 5768 case UPDATE_ANIMATION_SCALE: { 5769 @UpdateAnimationScaleMode 5770 final int mode = msg.arg1; 5771 switch (mode) { 5772 case WINDOW_ANIMATION_SCALE: { 5773 mWindowAnimationScaleSetting = getWindowAnimationScaleSetting(); 5774 break; 5775 } 5776 case TRANSITION_ANIMATION_SCALE: { 5777 mTransitionAnimationScaleSetting = 5778 getTransitionAnimationScaleSetting(); 5779 break; 5780 } 5781 case ANIMATION_DURATION_SCALE: { 5782 mAnimatorDurationScaleSetting = getAnimatorDurationScaleSetting(); 5783 dispatchNewAnimatorScaleLocked(null); 5784 break; 5785 } 5786 } 5787 break; 5788 } 5789 5790 case ENABLE_SCREEN: { 5791 performEnableScreen(); 5792 break; 5793 } 5794 5795 case REPORT_WINDOWS_CHANGE: { 5796 if (mWindowsChanged) { 5797 synchronized (mGlobalLock) { 5798 mWindowsChanged = false; 5799 } 5800 notifyWindowsChanged(); 5801 } 5802 break; 5803 } 5804 5805 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 5806 notifyHardKeyboardStatusChange(); 5807 break; 5808 } 5809 5810 case BOOT_TIMEOUT: { 5811 performBootTimeout(); 5812 break; 5813 } 5814 5815 case WAITING_FOR_DRAWN_TIMEOUT: { 5816 final Message callback; 5817 final WindowContainer<?> container = (WindowContainer<?>) msg.obj; 5818 synchronized (mGlobalLock) { 5819 ProtoLog.w(WM_ERROR, "Timeout waiting for drawn: undrawn=%s", 5820 container.mWaitingForDrawn); 5821 if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { 5822 for (int i = 0; i < container.mWaitingForDrawn.size(); i++) { 5823 traceEndWaitingForWindowDrawn(container.mWaitingForDrawn.get(i)); 5824 } 5825 } 5826 container.mWaitingForDrawn.clear(); 5827 callback = mWaitingForDrawnCallbacks.remove(container); 5828 } 5829 if (callback != null) { 5830 callback.sendToTarget(); 5831 } 5832 break; 5833 } 5834 5835 case SHOW_STRICT_MODE_VIOLATION: { 5836 showStrictModeViolation(msg.arg1, msg.arg2); 5837 break; 5838 } 5839 5840 case SHOW_EMULATOR_DISPLAY_OVERLAY: { 5841 showEmulatorDisplayOverlay(); 5842 break; 5843 } 5844 5845 case NOTIFY_ACTIVITY_DRAWN: { 5846 final ActivityRecord activity = (ActivityRecord) msg.obj; 5847 synchronized (mGlobalLock) { 5848 if (activity.isAttached()) { 5849 activity.getRootTask().notifyActivityDrawnLocked(activity); 5850 } 5851 } 5852 break; 5853 } 5854 case NEW_ANIMATOR_SCALE: { 5855 float scale = getCurrentAnimatorScale(); 5856 ValueAnimator.setDurationScale(scale); 5857 Session session = (Session)msg.obj; 5858 if (session != null) { 5859 try { 5860 session.mCallback.onAnimatorScaleChanged(scale); 5861 } catch (RemoteException e) { 5862 } 5863 } else { 5864 ArrayList<IWindowSessionCallback> callbacks 5865 = new ArrayList<IWindowSessionCallback>(); 5866 synchronized (mGlobalLock) { 5867 for (int i=0; i<mSessions.size(); i++) { 5868 callbacks.add(mSessions.valueAt(i).mCallback); 5869 } 5870 5871 } 5872 for (int i=0; i<callbacks.size(); i++) { 5873 try { 5874 callbacks.get(i).onAnimatorScaleChanged(scale); 5875 } catch (RemoteException e) { 5876 } 5877 } 5878 } 5879 break; 5880 } 5881 case CHECK_IF_BOOT_ANIMATION_FINISHED: { 5882 final boolean bootAnimationComplete; 5883 synchronized (mGlobalLock) { 5884 ProtoLog.i(WM_DEBUG_BOOT, "CHECK_IF_BOOT_ANIMATION_FINISHED:"); 5885 bootAnimationComplete = checkBootAnimationCompleteLocked(); 5886 } 5887 if (bootAnimationComplete) { 5888 performEnableScreen(); 5889 } 5890 break; 5891 } 5892 case RESET_ANR_MESSAGE: { 5893 synchronized (mGlobalLock) { 5894 mLastANRState = null; 5895 mAtmService.mLastANRState = null; 5896 } 5897 break; 5898 } 5899 case WALLPAPER_DRAW_PENDING_TIMEOUT: { 5900 synchronized (mGlobalLock) { 5901 final WallpaperController wallpaperController = 5902 (WallpaperController) msg.obj; 5903 if (wallpaperController != null 5904 && wallpaperController.processWallpaperDrawPendingTimeout()) { 5905 mWindowPlacerLocked.performSurfacePlacement(); 5906 } 5907 } 5908 break; 5909 } 5910 case UPDATE_MULTI_WINDOW_STACKS: { 5911 synchronized (mGlobalLock) { 5912 final DisplayContent displayContent = (DisplayContent) msg.obj; 5913 if (displayContent != null) { 5914 displayContent.adjustForImeIfNeeded(); 5915 } 5916 } 5917 break; 5918 } 5919 case WINDOW_HIDE_TIMEOUT: { 5920 final WindowState window = (WindowState) msg.obj; 5921 synchronized (mGlobalLock) { 5922 // TODO: This is all about fixing b/21693547 5923 // where partially initialized Toasts get stuck 5924 // around and keep the screen on. We'd like 5925 // to just remove the toast...but this can cause clients 5926 // who miss the timeout due to normal circumstances (e.g. 5927 // running under debugger) to crash (b/29105388). The windows will 5928 // eventually be removed when the client process finishes. 5929 // The best we can do for now is remove the FLAG_KEEP_SCREEN_ON 5930 // and prevent the symptoms of b/21693547. Since apps don't 5931 // support windows being removed under them we hide the window 5932 // and it will be removed when the app dies. 5933 window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON; 5934 window.hidePermanentlyLw(); 5935 window.setDisplayLayoutNeeded(); 5936 mWindowPlacerLocked.performSurfacePlacement(); 5937 } 5938 break; 5939 } 5940 case SET_HAS_OVERLAY_UI: { 5941 mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1); 5942 break; 5943 } 5944 case RECOMPUTE_FOCUS: { 5945 synchronized (mGlobalLock) { 5946 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 5947 true /* updateInputWindows */); 5948 } 5949 break; 5950 } 5951 case ON_POINTER_DOWN_OUTSIDE_FOCUS: { 5952 synchronized (mGlobalLock) { 5953 final IBinder touchedToken = (IBinder) msg.obj; 5954 onPointerDownOutsideFocusLocked(getInputTargetFromToken(touchedToken), 5955 true /* fromHandler */); 5956 } 5957 break; 5958 } 5959 case WINDOW_STATE_BLAST_SYNC_TIMEOUT: { 5960 synchronized (mGlobalLock) { 5961 final WindowState ws = (WindowState) msg.obj; 5962 Slog.i(TAG, "Blast sync timeout: " + ws); 5963 ws.immediatelyNotifyBlastSync(); 5964 } 5965 break; 5966 } 5967 case REPARENT_TASK_TO_DEFAULT_DISPLAY: { 5968 synchronized (mGlobalLock) { 5969 Task task = (Task) msg.obj; 5970 task.reparent(mRoot.getDefaultTaskDisplayArea(), true /* onTop */); 5971 // Resume focusable root task after reparenting to another display area. 5972 task.resumeNextFocusAfterReparent(); 5973 } 5974 break; 5975 } 5976 case INSETS_CHANGED: { 5977 synchronized (mGlobalLock) { 5978 if (mWindowsInsetsChanged > 0) { 5979 // We need to update resizing windows and dispatch the new insets state 5980 // to them. 5981 mWindowPlacerLocked.performSurfacePlacement(); 5982 } 5983 } 5984 break; 5985 } 5986 } 5987 if (DEBUG_WINDOW_TRACE) { 5988 Slog.v(TAG_WM, "handleMessage: exit"); 5989 } 5990 } 5991 5992 /** Remove the previous messages with the same 'what' and 'obj' then send the new one. */ sendNewMessageDelayed(int what, Object obj, long delayMillis)5993 void sendNewMessageDelayed(int what, Object obj, long delayMillis) { 5994 removeMessages(what, obj); 5995 sendMessageDelayed(obtainMessage(what, obj), delayMillis); 5996 } 5997 } 5998 5999 // ------------------------------------------------------------- 6000 // IWindowManager API 6001 // ------------------------------------------------------------- 6002 6003 @Override openSession(IWindowSessionCallback callback)6004 public IWindowSession openSession(IWindowSessionCallback callback) { 6005 return new Session(this, callback); 6006 } 6007 6008 @Override getInitialDisplaySize(int displayId, Point size)6009 public void getInitialDisplaySize(int displayId, Point size) { 6010 synchronized (mGlobalLock) { 6011 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6012 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 6013 size.x = displayContent.mInitialDisplayWidth; 6014 size.y = displayContent.mInitialDisplayHeight; 6015 } 6016 } 6017 } 6018 6019 @Override getBaseDisplaySize(int displayId, Point size)6020 public void getBaseDisplaySize(int displayId, Point size) { 6021 synchronized (mGlobalLock) { 6022 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6023 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 6024 size.x = displayContent.mBaseDisplayWidth; 6025 size.y = displayContent.mBaseDisplayHeight; 6026 } 6027 } 6028 } 6029 6030 @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 6031 @Override setForcedDisplaySize(int displayId, int width, int height)6032 public void setForcedDisplaySize(int displayId, int width, int height) { 6033 setForcedDisplaySize_enforcePermission(); 6034 6035 final long ident = Binder.clearCallingIdentity(); 6036 try { 6037 synchronized (mGlobalLock) { 6038 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6039 if (displayContent != null) { 6040 displayContent.setForcedSize(width, height); 6041 } 6042 } 6043 } finally { 6044 Binder.restoreCallingIdentity(ident); 6045 } 6046 } 6047 6048 @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 6049 @Override setForcedDisplayScalingMode(int displayId, int mode)6050 public void setForcedDisplayScalingMode(int displayId, int mode) { 6051 setForcedDisplayScalingMode_enforcePermission(); 6052 6053 final long ident = Binder.clearCallingIdentity(); 6054 try { 6055 synchronized (mGlobalLock) { 6056 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6057 if (displayContent != null) { 6058 displayContent.setForcedScalingMode(mode); 6059 } 6060 } 6061 } finally { 6062 Binder.restoreCallingIdentity(ident); 6063 } 6064 } 6065 setSandboxDisplayApis(int displayId, boolean sandboxDisplayApis)6066 void setSandboxDisplayApis(int displayId, boolean sandboxDisplayApis) { 6067 if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS) 6068 != PackageManager.PERMISSION_GRANTED) { 6069 throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS); 6070 } 6071 6072 final long ident = Binder.clearCallingIdentity(); 6073 try { 6074 synchronized (mGlobalLock) { 6075 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6076 if (displayContent != null) { 6077 displayContent.setSandboxDisplayApis(sandboxDisplayApis); 6078 } 6079 } 6080 } finally { 6081 Binder.restoreCallingIdentity(ident); 6082 } 6083 } 6084 6085 /** The global settings only apply to default display. */ applyForcedPropertiesForDefaultDisplay()6086 private boolean applyForcedPropertiesForDefaultDisplay() { 6087 boolean changed = false; 6088 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6089 // Display size. 6090 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 6091 Settings.Global.DISPLAY_SIZE_FORCED); 6092 if (sizeStr == null || sizeStr.length() == 0) { 6093 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 6094 } 6095 if (sizeStr != null && sizeStr.length() > 0) { 6096 final int pos = sizeStr.indexOf(','); 6097 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 6098 try { 6099 final Point size = displayContent.getValidForcedSize( 6100 Integer.parseInt(sizeStr.substring(0, pos)), 6101 Integer.parseInt(sizeStr.substring(pos + 1))); 6102 final int width = size.x; 6103 final int height = size.y; 6104 if (displayContent.mBaseDisplayWidth != width 6105 || displayContent.mBaseDisplayHeight != height) { 6106 ProtoLog.i(WM_ERROR, "FORCED DISPLAY SIZE: %dx%d", width, height); 6107 displayContent.updateBaseDisplayMetrics(width, height, 6108 displayContent.mBaseDisplayDensity, 6109 displayContent.mBaseDisplayPhysicalXDpi, 6110 displayContent.mBaseDisplayPhysicalYDpi); 6111 changed = true; 6112 } 6113 } catch (NumberFormatException ex) { 6114 } 6115 } 6116 } 6117 6118 // Display density. 6119 final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId); 6120 if (density != 0 && density != displayContent.mBaseDisplayDensity) { 6121 displayContent.mBaseDisplayDensity = density; 6122 changed = true; 6123 } 6124 6125 // Display scaling mode. 6126 int mode = Settings.Global.getInt(mContext.getContentResolver(), 6127 Settings.Global.DISPLAY_SCALING_FORCE, 0); 6128 if (displayContent.mDisplayScalingDisabled != (mode != 0)) { 6129 ProtoLog.i(WM_ERROR, "FORCED DISPLAY SCALING DISABLED"); 6130 displayContent.mDisplayScalingDisabled = true; 6131 changed = true; 6132 } 6133 return changed; 6134 } 6135 6136 @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 6137 @Override clearForcedDisplaySize(int displayId)6138 public void clearForcedDisplaySize(int displayId) { 6139 clearForcedDisplaySize_enforcePermission(); 6140 6141 final long ident = Binder.clearCallingIdentity(); 6142 try { 6143 synchronized (mGlobalLock) { 6144 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6145 if (displayContent != null) { 6146 displayContent.setForcedSize(displayContent.mInitialDisplayWidth, 6147 displayContent.mInitialDisplayHeight, 6148 displayContent.mInitialPhysicalXDpi, 6149 displayContent.mInitialPhysicalYDpi); 6150 } 6151 } 6152 } finally { 6153 Binder.restoreCallingIdentity(ident); 6154 } 6155 } 6156 6157 @Override getInitialDisplayDensity(int displayId)6158 public int getInitialDisplayDensity(int displayId) { 6159 synchronized (mGlobalLock) { 6160 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6161 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 6162 return displayContent.getInitialDisplayDensity(); 6163 } 6164 6165 DisplayInfo info = mDisplayManagerInternal.getDisplayInfo(displayId); 6166 if (info != null && info.hasAccess(Binder.getCallingUid())) { 6167 return info.logicalDensityDpi; 6168 } 6169 } 6170 return -1; 6171 } 6172 6173 @Override getBaseDisplayDensity(int displayId)6174 public int getBaseDisplayDensity(int displayId) { 6175 synchronized (mGlobalLock) { 6176 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6177 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 6178 return displayContent.mBaseDisplayDensity; 6179 } 6180 } 6181 return -1; 6182 } 6183 6184 /** 6185 * Return the display Id that has the given uniqueId. Unique ID is defined in 6186 * {@link DisplayInfo#uniqueId}. 6187 */ 6188 @Override getDisplayIdByUniqueId(String uniqueId)6189 public int getDisplayIdByUniqueId(String uniqueId) { 6190 synchronized (mGlobalLock) { 6191 final DisplayContent displayContent = mRoot.getDisplayContent(uniqueId); 6192 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 6193 return displayContent.mDisplayId; 6194 } 6195 } 6196 return -1; 6197 } 6198 6199 @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 6200 @Override setForcedDisplayDensityForUser(int displayId, int density, int userId)6201 public void setForcedDisplayDensityForUser(int displayId, int density, int userId) { 6202 setForcedDisplayDensityForUser_enforcePermission(); 6203 6204 final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 6205 Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser", 6206 null); 6207 final long ident = Binder.clearCallingIdentity(); 6208 try { 6209 synchronized (mGlobalLock) { 6210 setForcedDensityLockedInternal(displayId, density, targetUserId); 6211 } 6212 } finally { 6213 Binder.restoreCallingIdentity(ident); 6214 } 6215 } 6216 6217 @GuardedBy("mGlobalLock") setForcedDensityLockedInternal(final int displayId, final int density, @UserIdInt final int targetUserId)6218 private void setForcedDensityLockedInternal(final int displayId, final int density, 6219 @UserIdInt final int targetUserId) { 6220 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6221 if (displayContent != null) { 6222 displayContent.setForcedDensity(density, targetUserId); 6223 return; 6224 } 6225 6226 final DisplayInfo info = mDisplayManagerInternal.getDisplayInfo(displayId); 6227 if (info == null) { 6228 ProtoLog.e(WM_ERROR, "Failed to get information about logical display %d. " 6229 + "Skip setting forced display density.", displayId); 6230 return; 6231 } 6232 6233 mDisplayWindowSettings.setForcedDensity(info, density, targetUserId); 6234 } 6235 6236 @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 6237 @Override clearForcedDisplayDensityForUser(int displayId, int userId)6238 public void clearForcedDisplayDensityForUser(int displayId, int userId) { 6239 clearForcedDisplayDensityForUser_enforcePermission(); 6240 6241 final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 6242 Binder.getCallingUid(), userId, false, true, "clearForcedDisplayDensityForUser", 6243 null); 6244 final long ident = Binder.clearCallingIdentity(); 6245 try { 6246 synchronized (mGlobalLock) { 6247 // Clear forced display density ratio 6248 setForcedDisplayDensityRatioInternal(displayId, 0.0f, userId); 6249 6250 // Clear forced display density 6251 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6252 if (displayContent != null) { 6253 displayContent.setForcedDensity(displayContent.getInitialDisplayDensity(), 6254 callingUserId); 6255 return; 6256 } 6257 6258 final DisplayInfo info = mDisplayManagerInternal.getDisplayInfo(displayId); 6259 if (info == null) { 6260 ProtoLog.e(WM_ERROR, "Failed to get information about logical display %d. " 6261 + "Skip clearing forced display density.", displayId); 6262 return; 6263 } 6264 6265 mDisplayWindowSettings.setForcedDensity(info, info.logicalDensityDpi, 6266 userId); 6267 } 6268 } finally { 6269 Binder.restoreCallingIdentity(ident); 6270 } 6271 } 6272 6273 @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 6274 @Override setForcedDisplayDensityRatio(int displayId, float ratio, int userId)6275 public void setForcedDisplayDensityRatio(int displayId, float ratio, int userId) { 6276 setForcedDisplayDensityRatio_enforcePermission(); 6277 final long ident = Binder.clearCallingIdentity(); 6278 try { 6279 synchronized (mGlobalLock) { 6280 setForcedDisplayDensityRatioInternal(displayId, ratio, userId); 6281 } 6282 } finally { 6283 Binder.restoreCallingIdentity(ident); 6284 } 6285 } 6286 setForcedDisplayDensityRatioInternal( int displayId, float ratio, int userId)6287 private void setForcedDisplayDensityRatioInternal( 6288 int displayId, float ratio, int userId) { 6289 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6290 if (displayContent != null) { 6291 displayContent.setForcedDensityRatio(ratio, userId); 6292 return; 6293 } 6294 6295 final DisplayInfo info = mDisplayManagerInternal.getDisplayInfo(displayId); 6296 if (info == null) { 6297 ProtoLog.e(WM_ERROR, "Failed to get information about logical display %d. " 6298 + "Skip setting forced display density.", displayId); 6299 return; 6300 } 6301 mDisplayWindowSettings.setForcedDensityRatio(info, ratio); 6302 } 6303 6304 @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 6305 @Override setConfigurationChangeSettingsForUser( @onNull List<ConfigurationChangeSetting> settings, int userId)6306 public void setConfigurationChangeSettingsForUser( 6307 @NonNull List<ConfigurationChangeSetting> settings, int userId) { 6308 setConfigurationChangeSettingsForUser_enforcePermission(); 6309 if (!Flags.condenseConfigurationChangeForSimpleMode()) { 6310 throw new IllegalStateException( 6311 "setConfigurationChangeSettingsForUser shouldn't be called when " 6312 + "condenseConfigurationChangeForSimpleMode is disabled, " 6313 + "please enable the flag."); 6314 } 6315 6316 final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 6317 Binder.getCallingUid(), userId, false, true, 6318 "setConfigurationChangeSettingsForUser", 6319 null); 6320 final long ident = Binder.clearCallingIdentity(); 6321 try { 6322 synchronized (mGlobalLock) { 6323 mAtmService.deferWindowLayout(); 6324 try { 6325 // Apply the settings. 6326 for (int i = 0; i < settings.size(); i++) { 6327 settings.get(i).apply(callingUserId); 6328 } 6329 } finally { 6330 mAtmService.continueWindowLayout(); 6331 } 6332 } 6333 } finally { 6334 Binder.restoreCallingIdentity(ident); 6335 } 6336 } 6337 6338 /** 6339 * @param userId the ID of the user 6340 * @return the forced display density for the specified user, if set, or 6341 * {@code 0} if not set 6342 */ getForcedDisplayDensityForUserLocked(int userId)6343 private int getForcedDisplayDensityForUserLocked(int userId) { 6344 String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(), 6345 Settings.Secure.DISPLAY_DENSITY_FORCED, userId); 6346 if (densityStr == null || densityStr.length() == 0) { 6347 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 6348 } 6349 if (densityStr != null && densityStr.length() > 0) { 6350 try { 6351 return Integer.parseInt(densityStr); 6352 } catch (NumberFormatException ex) { 6353 } 6354 } 6355 return 0; 6356 } 6357 6358 @Override startWindowTrace()6359 public void startWindowTrace(){ 6360 mWindowTracing.startTrace(null /* printwriter */); 6361 } 6362 6363 @Override stopWindowTrace()6364 public void stopWindowTrace(){ 6365 mWindowTracing.stopTrace(null /* printwriter */); 6366 } 6367 6368 @Override saveWindowTraceToFile()6369 public void saveWindowTraceToFile() { 6370 mWindowTracing.saveForBugreport(null /* printwriter */); 6371 } 6372 6373 @Override isWindowTraceEnabled()6374 public boolean isWindowTraceEnabled() { 6375 return mWindowTracing.isEnabled(); 6376 } 6377 6378 @Override startTransitionTrace()6379 public void startTransitionTrace() { 6380 mTransitionTracer.startTrace(null /* printwriter */); 6381 } 6382 6383 @Override stopTransitionTrace()6384 public void stopTransitionTrace() { 6385 mTransitionTracer.stopTrace(null /* printwriter */); 6386 } 6387 6388 @Override isTransitionTraceEnabled()6389 public boolean isTransitionTraceEnabled() { 6390 return mTransitionTracer.isTracing(); 6391 } 6392 6393 @Override registerCrossWindowBlurEnabledListener( ICrossWindowBlurEnabledListener listener)6394 public boolean registerCrossWindowBlurEnabledListener( 6395 ICrossWindowBlurEnabledListener listener) { 6396 return mBlurController.registerCrossWindowBlurEnabledListener(listener); 6397 } 6398 6399 @Override unregisterCrossWindowBlurEnabledListener( ICrossWindowBlurEnabledListener listener)6400 public void unregisterCrossWindowBlurEnabledListener( 6401 ICrossWindowBlurEnabledListener listener) { 6402 mBlurController.unregisterCrossWindowBlurEnabledListener(listener); 6403 } 6404 6405 // ------------------------------------------------------------- 6406 // Internals 6407 // ------------------------------------------------------------- 6408 windowForClientLocked(Session session, IWindow client, boolean throwOnError)6409 final WindowState windowForClientLocked(Session session, IWindow client, boolean throwOnError) { 6410 return windowForClientLocked(session, client.asBinder(), throwOnError); 6411 } 6412 windowForClientLocked(Session session, IBinder client, boolean throwOnError)6413 final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) { 6414 WindowState win = mWindowMap.get(client); 6415 if (DEBUG) Slog.v(TAG_WM, "Looking up client " + client + ": " + win); 6416 if (win == null) { 6417 if (throwOnError) { 6418 throw new IllegalArgumentException( 6419 "Requested window " + client + " does not exist"); 6420 } 6421 ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session, 6422 Debug.getCallers(3)); 6423 return null; 6424 } 6425 if (session != null && win.mSession != session) { 6426 if (throwOnError) { 6427 throw new IllegalArgumentException("Requested window " + client + " is in session " 6428 + win.mSession + ", not " + session); 6429 } 6430 ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session, 6431 Debug.getCallers(3)); 6432 return null; 6433 } 6434 6435 return win; 6436 } 6437 checkDrawnWindowsLocked()6438 void checkDrawnWindowsLocked() { 6439 if (mWaitingForDrawnCallbacks.isEmpty()) { 6440 return; 6441 } 6442 for (int i = mWaitingForDrawnCallbacks.size() - 1; i >= 0; i--) { 6443 final WindowContainer<?> container = mWaitingForDrawnCallbacks.keyAt(i); 6444 for (int j = container.mWaitingForDrawn.size() - 1; j >= 0; j--) { 6445 final WindowState win = (WindowState) container.mWaitingForDrawn.get(j); 6446 ProtoLog.i(WM_DEBUG_SCREEN_ON, 6447 "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d", 6448 win, win.mRemoved, win.isVisible(), win.mHasSurface, 6449 win.mWinAnimator.mDrawState); 6450 if (win.mRemoved || !win.mHasSurface || !win.isVisibleByPolicy()) { 6451 // Window has been removed or hidden; no draw will now happen, so stop waiting. 6452 ProtoLog.w(WM_DEBUG_SCREEN_ON, "Aborted waiting for drawn: %s", win); 6453 container.mWaitingForDrawn.remove(win); 6454 if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { 6455 traceEndWaitingForWindowDrawn(win); 6456 } 6457 } else if (win.hasDrawn()) { 6458 // Window is now drawn (and shown). 6459 ProtoLog.d(WM_DEBUG_SCREEN_ON, "Window drawn win=%s", win); 6460 container.mWaitingForDrawn.remove(win); 6461 if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { 6462 traceEndWaitingForWindowDrawn(win); 6463 } 6464 } 6465 } 6466 if (container.mWaitingForDrawn.isEmpty()) { 6467 ProtoLog.d(WM_DEBUG_SCREEN_ON, "All windows drawn!"); 6468 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container); 6469 mWaitingForDrawnCallbacks.removeAt(i).sendToTarget(); 6470 } 6471 } 6472 } 6473 traceStartWaitingForWindowDrawn(WindowState window)6474 private void traceStartWaitingForWindowDrawn(WindowState window) { 6475 final String traceName = TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD + "#" 6476 + window.getWindowTag(); 6477 final String shortenedTraceName = traceName.substring(0, Math.min( 6478 TRACE_MAX_SECTION_NAME_LENGTH, traceName.length())); 6479 Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, shortenedTraceName, /* cookie= */ 0); 6480 } 6481 traceEndWaitingForWindowDrawn(WindowState window)6482 private void traceEndWaitingForWindowDrawn(WindowState window) { 6483 final String traceName = TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD + "#" 6484 + window.getWindowTag(); 6485 final String shortenedTraceName = traceName.substring(0, Math.min( 6486 TRACE_MAX_SECTION_NAME_LENGTH, traceName.length())); 6487 Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, shortenedTraceName, /* cookie= */ 0); 6488 } 6489 requestTraversal()6490 void requestTraversal() { 6491 mWindowPlacerLocked.requestTraversal(); 6492 } 6493 6494 /** Note that Locked in this case is on mLayoutToAnim */ scheduleAnimationLocked()6495 void scheduleAnimationLocked() { 6496 mAnimator.scheduleAnimation(); 6497 } 6498 updateFocusedWindowLocked(int mode, boolean updateInputWindows)6499 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 6500 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 6501 boolean changed = mRoot.updateFocusedWindowLocked(mode, updateInputWindows); 6502 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 6503 return changed; 6504 } 6505 getPropertyInt(String[] tokens, int index, int defUnits, int defDps, DisplayMetrics dm)6506 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 6507 DisplayMetrics dm) { 6508 if (index < tokens.length) { 6509 String str = tokens[index]; 6510 if (str != null && str.length() > 0) { 6511 try { 6512 int val = Integer.parseInt(str); 6513 return val; 6514 } catch (Exception e) { 6515 } 6516 } 6517 } 6518 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 6519 return defDps; 6520 } 6521 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 6522 return val; 6523 } 6524 createWatermark()6525 void createWatermark() { 6526 if (mWatermark != null) { 6527 return; 6528 } 6529 6530 File file = new File("/system/etc/setup.conf"); 6531 FileInputStream in = null; 6532 DataInputStream ind = null; 6533 try { 6534 in = new FileInputStream(file); 6535 ind = new DataInputStream(in); 6536 String line = ind.readLine(); 6537 if (line != null) { 6538 String[] toks = line.split("%"); 6539 if (toks != null && toks.length > 0) { 6540 // TODO(multi-display): Show watermarks on secondary displays. 6541 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6542 mWatermark = new Watermark(displayContent, displayContent.mRealDisplayMetrics, 6543 toks, mTransaction); 6544 mTransaction.apply(); 6545 } 6546 } 6547 } catch (FileNotFoundException e) { 6548 } catch (IOException e) { 6549 } finally { 6550 if (ind != null) { 6551 try { 6552 ind.close(); 6553 } catch (IOException e) { 6554 } 6555 } else if (in != null) { 6556 try { 6557 in.close(); 6558 } catch (IOException e) { 6559 } 6560 } 6561 } 6562 } 6563 6564 @Override setRecentsVisibility(boolean visible)6565 public void setRecentsVisibility(boolean visible) { 6566 if (!checkCallingPermission( 6567 android.Manifest.permission.STATUS_BAR, "setRecentsVisibility()")) { 6568 throw new SecurityException("Requires STATUS_BAR permission"); 6569 } 6570 synchronized (mGlobalLock) { 6571 mPolicy.setRecentsVisibilityLw(visible); 6572 } 6573 } 6574 6575 @Override hideTransientBars(int displayId)6576 public void hideTransientBars(int displayId) { 6577 if (!checkCallingPermission( 6578 android.Manifest.permission.STATUS_BAR, "hideTransientBars()")) { 6579 throw new SecurityException("Requires STATUS_BAR permission"); 6580 } 6581 6582 synchronized (mGlobalLock) { 6583 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6584 if (displayContent != null) { 6585 displayContent.getInsetsPolicy().hideTransient(); 6586 } else { 6587 Slog.w(TAG, "hideTransientBars with invalid displayId=" + displayId); 6588 } 6589 } 6590 } 6591 6592 @Override updateStaticPrivacyIndicatorBounds(int displayId, Rect[] staticBounds)6593 public void updateStaticPrivacyIndicatorBounds(int displayId, 6594 Rect[] staticBounds) { 6595 synchronized (mGlobalLock) { 6596 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 6597 if (displayContent != null) { 6598 displayContent.updatePrivacyIndicatorBounds(staticBounds); 6599 } else { 6600 Slog.w(TAG, "updateStaticPrivacyIndicatorBounds with invalid displayId=" 6601 + displayId); 6602 } 6603 } 6604 } 6605 6606 @EnforcePermission(android.Manifest.permission.STATUS_BAR) setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled)6607 public void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) { 6608 setNavBarVirtualKeyHapticFeedbackEnabled_enforcePermission(); 6609 6610 synchronized (mGlobalLock) { 6611 mPolicy.setNavBarVirtualKeyHapticFeedbackEnabledLw(enabled); 6612 } 6613 } 6614 6615 @Override createInputConsumer(IBinder token, String name, int displayId, InputChannel inputChannel)6616 public void createInputConsumer(IBinder token, String name, int displayId, 6617 InputChannel inputChannel) { 6618 if (!mAtmService.isCallerRecents(Binder.getCallingUid()) 6619 && mContext.checkCallingOrSelfPermission(INPUT_CONSUMER) != PERMISSION_GRANTED) { 6620 throw new SecurityException("createInputConsumer requires INPUT_CONSUMER permission"); 6621 } 6622 6623 synchronized (mGlobalLock) { 6624 DisplayContent display = mRoot.getDisplayContent(displayId); 6625 if (display != null) { 6626 display.getInputMonitor().createInputConsumer(token, name, inputChannel, 6627 Binder.getCallingPid(), Binder.getCallingUserHandle()); 6628 } 6629 } 6630 } 6631 6632 @Override destroyInputConsumer(IBinder token, int displayId)6633 public boolean destroyInputConsumer(IBinder token, int displayId) { 6634 if (!mAtmService.isCallerRecents(Binder.getCallingUid()) 6635 && mContext.checkCallingOrSelfPermission(INPUT_CONSUMER) != PERMISSION_GRANTED) { 6636 throw new SecurityException("destroyInputConsumer requires INPUT_CONSUMER permission"); 6637 } 6638 6639 synchronized (mGlobalLock) { 6640 DisplayContent display = mRoot.getDisplayContent(displayId); 6641 if (display != null) { 6642 return display.getInputMonitor().destroyInputConsumer(token); 6643 } 6644 return false; 6645 } 6646 } 6647 6648 @EnforcePermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) 6649 @Override getCurrentImeTouchRegion()6650 public Region getCurrentImeTouchRegion() { 6651 getCurrentImeTouchRegion_enforcePermission(); 6652 synchronized (mGlobalLock) { 6653 final Region r = new Region(); 6654 // TODO(b/111080190): this method is only return the recent focused IME touch region, 6655 // For Multi-Session IME, will need to add API for given display Id to 6656 // get the right IME touch region. 6657 for (int i = mRoot.mChildren.size() - 1; i >= 0; --i) { 6658 final DisplayContent displayContent = mRoot.mChildren.get(i); 6659 if (displayContent.mInputMethodWindow != null) { 6660 displayContent.mInputMethodWindow.getTouchableRegion(r); 6661 return r; 6662 } 6663 } 6664 return r; 6665 } 6666 } 6667 6668 @Override hasNavigationBar(int displayId)6669 public boolean hasNavigationBar(int displayId) { 6670 synchronized (mGlobalLock) { 6671 final DisplayContent dc = mRoot.getDisplayContent(displayId); 6672 if (dc == null) { 6673 return false; 6674 } 6675 return dc.getDisplayPolicy().hasNavigationBar(); 6676 } 6677 } 6678 6679 @Override lockNow(Bundle options)6680 public void lockNow(Bundle options) { 6681 mPolicy.lockNow(options); 6682 } 6683 showRecentApps()6684 public void showRecentApps() { 6685 mPolicy.showRecentApps(); 6686 } 6687 6688 @Override isSafeModeEnabled()6689 public boolean isSafeModeEnabled() { 6690 return mSafeMode; 6691 } 6692 6693 @Override clearWindowContentFrameStats(IBinder token)6694 public boolean clearWindowContentFrameStats(IBinder token) { 6695 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 6696 "clearWindowContentFrameStats()")) { 6697 throw new SecurityException("Requires FRAME_STATS permission"); 6698 } 6699 synchronized (mGlobalLock) { 6700 WindowState windowState = mWindowMap.get(token); 6701 if (windowState == null) { 6702 return false; 6703 } 6704 final SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 6705 if (surfaceControl == null) { 6706 return false; 6707 } 6708 return surfaceControl.clearContentFrameStats(); 6709 } 6710 } 6711 6712 @Override getWindowContentFrameStats(IBinder token)6713 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 6714 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 6715 "getWindowContentFrameStats()")) { 6716 throw new SecurityException("Requires FRAME_STATS permission"); 6717 } 6718 synchronized (mGlobalLock) { 6719 WindowState windowState = mWindowMap.get(token); 6720 if (windowState == null) { 6721 return null; 6722 } 6723 final SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 6724 if (surfaceControl == null) { 6725 return null; 6726 } 6727 if (mTempWindowRenderStats == null) { 6728 mTempWindowRenderStats = new WindowContentFrameStats(); 6729 } 6730 WindowContentFrameStats stats = mTempWindowRenderStats; 6731 if (!surfaceControl.getContentFrameStats(stats)) { 6732 return null; 6733 } 6734 return stats; 6735 } 6736 } 6737 dumpPolicyLocked(PrintWriter pw, String[] args)6738 private void dumpPolicyLocked(PrintWriter pw, String[] args) { 6739 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 6740 mPolicy.dump(" ", pw, args); 6741 } 6742 dumpAnimatorLocked(PrintWriter pw, boolean dumpAll)6743 private void dumpAnimatorLocked(PrintWriter pw, boolean dumpAll) { 6744 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 6745 mAnimator.dumpLocked(pw, " ", dumpAll); 6746 } 6747 dumpTokensLocked(PrintWriter pw, boolean dumpAll)6748 private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 6749 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 6750 mRoot.dumpTokens(pw, dumpAll); 6751 } 6752 6753 dumpHighRefreshRateBlacklist(PrintWriter pw)6754 private void dumpHighRefreshRateBlacklist(PrintWriter pw) { 6755 pw.println("WINDOW MANAGER HIGH REFRESH RATE BLACKLIST (dumpsys window refresh)"); 6756 mHighRefreshRateDenylist.dump(pw); 6757 } 6758 dumpTraceStatus(PrintWriter pw)6759 private void dumpTraceStatus(PrintWriter pw) { 6760 pw.println("WINDOW MANAGER TRACE (dumpsys window trace)"); 6761 pw.print(mWindowTracing.getStatus() + "\n"); 6762 } 6763 dumpLogStatus(PrintWriter pw)6764 private void dumpLogStatus(PrintWriter pw) { 6765 pw.println("WINDOW MANAGER LOGGING (dumpsys window logging)"); 6766 if (android.tracing.Flags.perfettoProtologTracing()) { 6767 pw.println("Deprecated legacy command. Use Perfetto commands instead."); 6768 return; 6769 } 6770 ((LegacyProtoLogImpl) ProtoLog.getSingleInstance()).getStatus(); 6771 } 6772 dumpSessionsLocked(PrintWriter pw)6773 private void dumpSessionsLocked(PrintWriter pw) { 6774 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 6775 for (int i=0; i<mSessions.size(); i++) { 6776 Session s = mSessions.valueAt(i); 6777 pw.print(" Session "); pw.print(s); pw.println(':'); 6778 s.dump(pw, " "); 6779 } 6780 } 6781 6782 /** 6783 * Write to a protocol buffer output stream. Protocol buffer message definition is at 6784 * {@link com.android.server.wm.WindowManagerServiceDumpProto}. 6785 * 6786 * @param proto Stream to write the WindowContainer object to. 6787 * @param logLevel Determines the amount of data to be written to the Protobuf. 6788 */ dumpDebugLocked(ProtoOutputStream proto, @WindowTracingLogLevel int logLevel)6789 void dumpDebugLocked(ProtoOutputStream proto, @WindowTracingLogLevel int logLevel) { 6790 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "dumpDebugLocked"); 6791 try { 6792 mPolicy.dumpDebug(proto, POLICY); 6793 mRoot.dumpDebug(proto, ROOT_WINDOW_CONTAINER, logLevel); 6794 final DisplayContent topFocusedDisplayContent = mRoot.getTopFocusedDisplayContent(); 6795 if (topFocusedDisplayContent.mCurrentFocus != null) { 6796 topFocusedDisplayContent.mCurrentFocus 6797 .writeIdentifierToProto(proto, FOCUSED_WINDOW); 6798 } 6799 if (topFocusedDisplayContent.mFocusedApp != null) { 6800 topFocusedDisplayContent.mFocusedApp.writeNameToProto(proto, FOCUSED_APP); 6801 } 6802 final WindowState imeWindow = mRoot.getCurrentInputMethodWindow(); 6803 if (imeWindow != null) { 6804 imeWindow.writeIdentifierToProto(proto, INPUT_METHOD_WINDOW); 6805 } 6806 proto.write(FOCUSED_DISPLAY_ID, topFocusedDisplayContent.getDisplayId()); 6807 proto.write(HARD_KEYBOARD_AVAILABLE, mHardKeyboardAvailable); 6808 6809 // This is always true for now since we still update the window frames at the server 6810 // side. Once we move the window layout to the client side, this can be false when we 6811 // are waiting for the frames. 6812 proto.write(WINDOW_FRAMES_VALID, true); 6813 6814 // Write the BackNavigationController's state into the protocol buffer 6815 mAtmService.mBackNavigationController.dumpDebug(proto, BACK_NAVIGATION); 6816 } finally { 6817 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 6818 } 6819 } 6820 dumpWindowsLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)6821 private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 6822 ArrayList<WindowState> windows) { 6823 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 6824 mRoot.dumpWindowsNoHeader(pw, dumpAll, windows); 6825 6826 if (!mHidingNonSystemOverlayWindows.isEmpty()) { 6827 pw.println(); 6828 pw.println(" Hiding System Alert Windows:"); 6829 for (int i = mHidingNonSystemOverlayWindows.size() - 1; i >= 0; i--) { 6830 final WindowState w = mHidingNonSystemOverlayWindows.get(i); 6831 pw.print(" #"); pw.print(i); pw.print(' '); 6832 pw.print(w); 6833 if (dumpAll) { 6834 pw.println(":"); 6835 w.dump(pw, " ", true); 6836 } else { 6837 pw.println(); 6838 } 6839 } 6840 } 6841 if (mForceRemoves != null && !mForceRemoves.isEmpty()) { 6842 pw.println(); 6843 pw.println(" Windows force removing:"); 6844 for (int i=mForceRemoves.size()-1; i>=0; i--) { 6845 WindowState w = mForceRemoves.get(i); 6846 pw.print(" Removing #"); pw.print(i); pw.print(' '); 6847 pw.print(w); 6848 if (dumpAll) { 6849 pw.println(":"); 6850 w.dump(pw, " ", true); 6851 } else { 6852 pw.println(); 6853 } 6854 } 6855 } 6856 if (!mDestroySurface.isEmpty()) { 6857 pw.println(); 6858 pw.println(" Windows waiting to destroy their surface:"); 6859 for (int i=mDestroySurface.size()-1; i>=0; i--) { 6860 WindowState w = mDestroySurface.get(i); 6861 if (windows == null || windows.contains(w)) { 6862 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 6863 pw.print(w); 6864 if (dumpAll) { 6865 pw.println(":"); 6866 w.dump(pw, " ", true); 6867 } else { 6868 pw.println(); 6869 } 6870 } 6871 } 6872 } 6873 if (!mResizingWindows.isEmpty()) { 6874 pw.println(); 6875 pw.println(" Windows waiting to resize:"); 6876 for (int i=mResizingWindows.size()-1; i>=0; i--) { 6877 WindowState w = mResizingWindows.get(i); 6878 if (windows == null || windows.contains(w)) { 6879 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 6880 pw.print(w); 6881 if (dumpAll) { 6882 pw.println(":"); 6883 w.dump(pw, " ", true); 6884 } else { 6885 pw.println(); 6886 } 6887 } 6888 } 6889 } 6890 if (!mWaitingForDrawnCallbacks.isEmpty()) { 6891 pw.println(); 6892 pw.println(" Clients waiting for these windows to be drawn:"); 6893 mWaitingForDrawnCallbacks.forEach((wc, callback) -> { 6894 pw.print(" WindowContainer "); 6895 pw.println(wc.getName()); 6896 for (int i = wc.mWaitingForDrawn.size() - 1; i >= 0; i--) { 6897 final WindowState win = (WindowState) wc.mWaitingForDrawn.get(i); 6898 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 6899 } 6900 }); 6901 6902 } 6903 pw.println(); 6904 pw.print(" mGlobalConfiguration="); pw.println(mRoot.getConfiguration()); 6905 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad); 6906 mRoot.dumpTopFocusedDisplayId(pw); 6907 mRoot.forAllDisplays(dc -> { 6908 final int displayId = dc.getDisplayId(); 6909 final InsetsControlTarget imeLayeringTarget = dc.getImeTarget(IME_TARGET_LAYERING); 6910 final InputTarget imeInputTarget = dc.getImeInputTarget(); 6911 final InsetsControlTarget imeControlTarget = dc.getImeTarget(IME_TARGET_CONTROL); 6912 if (imeLayeringTarget != null) { 6913 pw.print(" imeLayeringTarget in display# "); pw.print(displayId); 6914 pw.print(' '); pw.println(imeLayeringTarget); 6915 } 6916 if (imeInputTarget != null) { 6917 pw.print(" imeInputTarget in display# "); pw.print(displayId); 6918 pw.print(' '); pw.println(imeInputTarget); 6919 } 6920 if (imeControlTarget != null) { 6921 pw.print(" imeControlTarget in display# "); pw.print(displayId); 6922 pw.print(' '); pw.println(imeControlTarget); 6923 } 6924 pw.print(" Minimum task size of display#"); pw.print(displayId); 6925 pw.print(' '); pw.println(dc.mMinSizeOfResizeableTaskDp); 6926 }); 6927 pw.print(" mBlurEnabled="); pw.println(mBlurController.getBlurEnabled()); 6928 pw.print(" mDisableSecureWindows="); pw.println(mDisableSecureWindows); 6929 6930 mInputManagerCallback.dump(pw, " "); 6931 mSnapshotController.dump(pw, " "); 6932 6933 dumpAccessibilityController(pw, /* force= */ false); 6934 6935 if (dumpAll) { 6936 final WindowState imeWindow = mRoot.getCurrentInputMethodWindow(); 6937 if (imeWindow != null) { 6938 pw.print(" mInputMethodWindow="); pw.println(imeWindow); 6939 } 6940 mWindowPlacerLocked.dump(pw, " "); 6941 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 6942 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 6943 6944 mRoot.dumpLayoutNeededDisplayIds(pw); 6945 6946 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 6947 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked(); 6948 pw.print(" mRotation="); pw.println(defaultDisplayContent.getRotation()); 6949 pw.print(" mLastOrientation="); 6950 pw.println(defaultDisplayContent.getLastOrientation()); 6951 pw.print(" mWaitingForConfig="); 6952 pw.println(defaultDisplayContent.mWaitingForConfig); 6953 pw.print(" mWindowsInsetsChanged="); pw.println(mWindowsInsetsChanged); 6954 mRotationWatcherController.dump(pw); 6955 6956 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 6957 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 6958 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 6959 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 6960 } 6961 } 6962 dumpAccessibilityController(PrintWriter pw, boolean force)6963 private void dumpAccessibilityController(PrintWriter pw, boolean force) { 6964 boolean hasCallbacks = mAccessibilityController.hasCallbacks(); 6965 if (!hasCallbacks && !force) { 6966 return; 6967 } 6968 if (!hasCallbacks) { 6969 pw.println("AccessibilityController doesn't have callbacks, but printing it anways:"); 6970 } else { 6971 pw.println("AccessibilityController:"); 6972 } 6973 mAccessibilityController.dump(pw, " "); 6974 } 6975 dumpAccessibilityLocked(PrintWriter pw)6976 private void dumpAccessibilityLocked(PrintWriter pw) { 6977 dumpAccessibilityController(pw, /* force= */ true); 6978 } 6979 dumpWindows(PrintWriter pw, String name, boolean dumpAll)6980 private boolean dumpWindows(PrintWriter pw, String name, boolean dumpAll) { 6981 final ArrayList<WindowState> windows = new ArrayList(); 6982 if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) { 6983 final boolean appsOnly = name.contains("apps"); 6984 final boolean visibleOnly = name.contains("visible"); 6985 synchronized (mGlobalLock) { 6986 if (appsOnly) { 6987 mRoot.dumpDisplayContents(pw); 6988 } 6989 6990 mRoot.forAllWindows((w) -> { 6991 if ((!visibleOnly || w.isVisible()) 6992 && (!appsOnly || w.mActivityRecord != null)) { 6993 windows.add(w); 6994 } 6995 }, true /* traverseTopToBottom */); 6996 } 6997 } else { 6998 synchronized (mGlobalLock) { 6999 mRoot.getWindowsByName(windows, name); 7000 } 7001 } 7002 7003 if (windows.isEmpty()) { 7004 return false; 7005 } 7006 7007 synchronized (mGlobalLock) { 7008 dumpWindowsLocked(pw, dumpAll, windows); 7009 } 7010 return true; 7011 } 7012 dumpLastANRLocked(PrintWriter pw)7013 private void dumpLastANRLocked(PrintWriter pw) { 7014 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 7015 if (mLastANRState == null) { 7016 pw.println(" <no ANR has occurred since boot>"); 7017 } else { 7018 pw.println(mLastANRState); 7019 } 7020 } 7021 7022 /** 7023 * Saves information about the state of the window manager at 7024 * the time an ANR occurred before anything else in the system changes 7025 * in response. 7026 * 7027 * @param activity The application that ANR'd, may be null. 7028 * @param windowState The window that ANR'd, may be null. 7029 * @param reason The reason for the ANR, may be null. 7030 */ saveANRStateLocked(ActivityRecord activity, WindowState windowState, String reason)7031 void saveANRStateLocked(ActivityRecord activity, WindowState windowState, String reason) { 7032 StringWriter sw = new StringWriter(); 7033 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 7034 pw.println(" ANR time: " + DateFormat.getDateTimeInstance().format(new Date())); 7035 if (activity != null) { 7036 pw.println(" Application at fault: " + activity.stringName); 7037 } 7038 if (windowState != null) { 7039 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 7040 } 7041 if (reason != null) { 7042 pw.println(" Reason: " + reason); 7043 } 7044 pw.println(); 7045 final ArrayList<WindowState> relatedWindows = new ArrayList<>(); 7046 for (int i = mRoot.getChildCount() - 1; i >= 0; i--) { 7047 final DisplayContent dc = mRoot.getChildAt(i); 7048 final int displayId = dc.getDisplayId(); 7049 final WindowState currentFocus = dc.mCurrentFocus; 7050 final ActivityRecord focusedApp = dc.mFocusedApp; 7051 pw.println(" Display #" + displayId + " currentFocus=" + currentFocus 7052 + " focusedApp=" + focusedApp); 7053 if (!dc.mWinAddedSinceNullFocus.isEmpty()) { 7054 pw.println(" Windows added in display #" + displayId + " since null focus: " 7055 + dc.mWinAddedSinceNullFocus); 7056 } 7057 if (!dc.mWinRemovedSinceNullFocus.isEmpty()) { 7058 pw.println(" Windows removed in display #" + displayId + " since null focus: " 7059 + dc.mWinRemovedSinceNullFocus); 7060 } 7061 pw.println(" Tasks in top down Z order:"); 7062 dc.forAllTaskDisplayAreas(tda -> { 7063 tda.dump(pw, " ", false /* dumpAll */); 7064 }); 7065 dc.getInputMonitor().dump(pw, " "); 7066 pw.println(); 7067 dc.forAllWindows(w -> { 7068 if ((currentFocus != null && Objects.equals(w.mAttrs.packageName, 7069 currentFocus.mAttrs.packageName)) || (focusedApp != null 7070 && Objects.equals(w.mAttrs.packageName, focusedApp.packageName))) { 7071 relatedWindows.add(w); 7072 } 7073 }, true /* traverseTopToBottom */); 7074 } 7075 if (windowState != null && !relatedWindows.contains(windowState)) { 7076 relatedWindows.add(windowState); 7077 } 7078 mRoot.dumpWindowsNoHeader(pw, true /* dumpAll */, relatedWindows); 7079 pw.println(); 7080 pw.close(); 7081 mLastANRState = sw.toString(); 7082 7083 mH.removeMessages(H.RESET_ANR_MESSAGE); 7084 mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS); 7085 } 7086 7087 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)7088 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 7089 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 7090 PriorityDump.dump(mPriorityDumper, fd, pw, args); 7091 } 7092 7093 @NeverCompile // Avoid size overhead of debugging code. doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto)7094 private void doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto) { 7095 boolean dumpAll = false; 7096 7097 int opti = 0; 7098 while (opti < args.length) { 7099 String opt = args[opti]; 7100 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 7101 break; 7102 } 7103 opti++; 7104 if ("-a".equals(opt)) { 7105 dumpAll = true; 7106 } else if ("-h".equals(opt)) { 7107 pw.println("Window manager dump options:"); 7108 pw.println(" [-a] [-h] [cmd] ..."); 7109 pw.println(" cmd may be one of:"); 7110 pw.println(" l[astanr]: last ANR information"); 7111 pw.println(" p[policy]: policy state"); 7112 pw.println(" a[animator]: animator state"); 7113 pw.println(" s[essions]: active sessions"); 7114 pw.println(" surfaces: active surfaces (debugging enabled only)"); 7115 pw.println(" d[isplays]: active display contents"); 7116 pw.println(" t[okens]: token list"); 7117 pw.println(" w[indows]: window list"); 7118 pw.println(" a11y[accessibility]: accessibility-related state"); 7119 pw.println(" package-config: installed packages having app-specific config"); 7120 pw.println(" trace: print trace status and write Winscope trace to file"); 7121 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 7122 pw.println(" be a partial substring in a window name, a"); 7123 pw.println(" Window hex object identifier, or"); 7124 pw.println(" \"all\" for all windows, or"); 7125 pw.println(" \"visible\" for the visible windows."); 7126 pw.println(" \"visible-apps\" for the visible app windows."); 7127 pw.println(" -a: include all available server state."); 7128 pw.println(" --proto: output dump in protocol buffer format."); 7129 return; 7130 } else { 7131 pw.println("Unknown argument: " + opt + "; use -h for help"); 7132 } 7133 } 7134 7135 if (useProto) { 7136 final ProtoOutputStream proto = new ProtoOutputStream(fd); 7137 synchronized (mGlobalLock) { 7138 dumpDebugLocked(proto, WindowTracingLogLevel.ALL); 7139 } 7140 proto.flush(); 7141 return; 7142 } 7143 // Is the caller requesting to dump a particular piece of data? 7144 if (opti < args.length) { 7145 String cmd = args[opti]; 7146 opti++; 7147 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 7148 synchronized (mGlobalLock) { 7149 dumpLastANRLocked(pw); 7150 } 7151 return; 7152 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 7153 synchronized (mGlobalLock) { 7154 dumpPolicyLocked(pw, args); 7155 } 7156 return; 7157 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 7158 synchronized (mGlobalLock) { 7159 dumpAnimatorLocked(pw, true); 7160 } 7161 return; 7162 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 7163 synchronized (mGlobalLock) { 7164 dumpSessionsLocked(pw); 7165 } 7166 return; 7167 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 7168 synchronized (mGlobalLock) { 7169 mRoot.dumpDisplayContents(pw); 7170 } 7171 return; 7172 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 7173 synchronized (mGlobalLock) { 7174 dumpTokensLocked(pw, true); 7175 } 7176 return; 7177 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 7178 synchronized (mGlobalLock) { 7179 dumpWindowsLocked(pw, true, null); 7180 } 7181 return; 7182 } else if ("accessibility".equals(cmd) || "a11y".equals(cmd)) { 7183 synchronized (mGlobalLock) { 7184 dumpAccessibilityLocked(pw); 7185 } 7186 return; 7187 } else if ("all".equals(cmd)) { 7188 synchronized (mGlobalLock) { 7189 dumpWindowsLocked(pw, true, null); 7190 } 7191 return; 7192 } else if ("containers".equals(cmd)) { 7193 synchronized (mGlobalLock) { 7194 mRoot.dumpChildrenNames(pw, ""); 7195 pw.println(" "); 7196 mRoot.forAllWindows(w -> {pw.println(w);}, true /* traverseTopToBottom */); 7197 } 7198 return; 7199 } else if ("trace".equals(cmd)) { 7200 dumpTraceStatus(pw); 7201 return; 7202 } else if ("logging".equals(cmd)) { 7203 dumpLogStatus(pw); 7204 return; 7205 } else if ("refresh".equals(cmd)) { 7206 dumpHighRefreshRateBlacklist(pw); 7207 return; 7208 } else if ("constants".equals(cmd)) { 7209 mConstants.dump(pw); 7210 return; 7211 } else if ("package-config".equals(cmd)) { 7212 mAtmService.dumpInstalledPackagesConfig(pw); 7213 return; 7214 } else { 7215 // Dumping a single name? 7216 if (!dumpWindows(pw, cmd, dumpAll)) { 7217 pw.println("Bad window command, or no windows match: " + cmd); 7218 pw.println("Use -h for help."); 7219 } 7220 return; 7221 } 7222 } 7223 7224 synchronized (mGlobalLock) { 7225 pw.println(); 7226 final String separator = "---------------------------------------------------------" 7227 + "----------------------"; 7228 if (dumpAll) { 7229 pw.println(separator); 7230 } 7231 dumpLastANRLocked(pw); 7232 pw.println(); 7233 if (dumpAll) { 7234 pw.println(separator); 7235 } 7236 dumpPolicyLocked(pw, args); 7237 pw.println(); 7238 if (dumpAll) { 7239 pw.println(separator); 7240 } 7241 dumpAnimatorLocked(pw, dumpAll); 7242 pw.println(); 7243 if (dumpAll) { 7244 pw.println(separator); 7245 } 7246 dumpSessionsLocked(pw); 7247 pw.println(); 7248 if (dumpAll) { 7249 pw.println(separator); 7250 } 7251 if (dumpAll) { 7252 pw.println(separator); 7253 } 7254 mRoot.dumpDisplayContents(pw); 7255 pw.println(); 7256 if (dumpAll) { 7257 pw.println(separator); 7258 } 7259 dumpTokensLocked(pw, dumpAll); 7260 pw.println(); 7261 if (dumpAll) { 7262 pw.println(separator); 7263 } 7264 dumpWindowsLocked(pw, dumpAll, null); 7265 if (dumpAll) { 7266 pw.println(separator); 7267 } 7268 dumpTraceStatus(pw); 7269 if (dumpAll) { 7270 pw.println(separator); 7271 } 7272 dumpLogStatus(pw); 7273 if (dumpAll) { 7274 pw.println(separator); 7275 } 7276 dumpHighRefreshRateBlacklist(pw); 7277 if (dumpAll) { 7278 pw.println(separator); 7279 } 7280 mAtmService.dumpInstalledPackagesConfig(pw); 7281 if (dumpAll) { 7282 pw.println(separator); 7283 } 7284 mConstants.dump(pw); 7285 if (dumpAll) { 7286 pw.println(separator); 7287 } 7288 mSystemPerformanceHinter.dump(pw, ""); 7289 mTrustedPresentationListenerController.dump(pw); 7290 mSensitiveContentPackages.dump(pw); 7291 mScreenRecordingCallbackController.dump(pw); 7292 } 7293 } 7294 7295 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 7296 @Override monitor()7297 public void monitor() { 7298 synchronized (mGlobalLock) { } 7299 } 7300 7301 // There is an inherent assumption that this will never return null. 7302 // TODO(multi-display): Inspect all the call-points of this method to see if they make sense to 7303 // support non-default display. getDefaultDisplayContentLocked()7304 DisplayContent getDefaultDisplayContentLocked() { 7305 return mRoot.getDisplayContent(DEFAULT_DISPLAY); 7306 } 7307 7308 /** 7309 * Returns the main display content for the user passed as parameter. 7310 * 7311 * <p>Visible background users may have their own designated main display, distinct from the 7312 * system default display (DEFAULT_DISPLAY). Visible background users operate independently 7313 * with their own main displays. These secondary user main displays host the secondary home 7314 * activities. 7315 */ 7316 @Nullable getUserMainDisplayContentLocked(@serIdInt int userId)7317 DisplayContent getUserMainDisplayContentLocked(@UserIdInt int userId) { 7318 final int userMainDisplayId = mUmInternal.getMainDisplayAssignedToUser(userId); 7319 if (userMainDisplayId == -1) { 7320 return null; 7321 } 7322 return mRoot.getDisplayContent(userMainDisplayId); 7323 } 7324 onOverlayChanged()7325 public void onOverlayChanged() { 7326 // Post to display thread so it can get the latest display info. 7327 mH.post(() -> { 7328 synchronized (mGlobalLock) { 7329 mAtmService.deferWindowLayout(); 7330 mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().onOverlayChanged()); 7331 mAtmService.continueWindowLayout(); 7332 } 7333 }); 7334 } 7335 7336 @Override getWindowManagerLock()7337 public Object getWindowManagerLock() { 7338 return mGlobalLock; 7339 } 7340 7341 @Override getDockedStackSide()7342 public int getDockedStackSide() { 7343 return 0; 7344 } 7345 setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays)7346 void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) { 7347 synchronized (mGlobalLock) { 7348 mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays; 7349 mRoot.updateDisplayImePolicyCache(); 7350 } 7351 } 7352 7353 @VisibleForTesting setIsPc(boolean isPc)7354 void setIsPc(boolean isPc) { 7355 synchronized (mGlobalLock) { 7356 mIsPc = isPc; 7357 } 7358 } 7359 dipToPixel(int dip, DisplayMetrics displayMetrics)7360 static int dipToPixel(int dip, DisplayMetrics displayMetrics) { 7361 return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics); 7362 } 7363 registerPinnedTaskListener(int displayId, IPinnedTaskListener listener)7364 public void registerPinnedTaskListener(int displayId, IPinnedTaskListener listener) { 7365 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, 7366 "registerPinnedTaskListener()")) { 7367 return; 7368 } 7369 if (!mAtmService.mSupportsPictureInPicture) { 7370 return; 7371 } 7372 synchronized (mGlobalLock) { 7373 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 7374 displayContent.getPinnedTaskController().registerPinnedTaskListener(listener); 7375 } 7376 } 7377 7378 @Override getApplicationLaunchKeyboardShortcuts(int deviceId)7379 public KeyboardShortcutGroup getApplicationLaunchKeyboardShortcuts(int deviceId) { 7380 long token = Binder.clearCallingIdentity(); 7381 try { 7382 return mPolicy.getApplicationLaunchKeyboardShortcuts(deviceId); 7383 } finally { 7384 Binder.restoreCallingIdentity(token); 7385 } 7386 } 7387 7388 @Override requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId)7389 public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) { 7390 enforceRegisterWindowManagerListenersPermission("requestAppKeyboardShortcuts"); 7391 7392 WindowState focusedWindow = getFocusedWindow(); 7393 if (focusedWindow == null || focusedWindow.mClient == null) { 7394 notifyReceiverWithEmptyBundle(receiver); 7395 return; 7396 } 7397 try { 7398 focusedWindow.mClient.requestAppKeyboardShortcuts(receiver, deviceId); 7399 } catch (RemoteException e) { 7400 notifyReceiverWithEmptyBundle(receiver); 7401 } 7402 } 7403 7404 @Override requestImeKeyboardShortcuts(IResultReceiver receiver, int deviceId)7405 public void requestImeKeyboardShortcuts(IResultReceiver receiver, int deviceId) { 7406 enforceRegisterWindowManagerListenersPermission("requestImeKeyboardShortcuts"); 7407 7408 WindowState imeWindow = mRoot.getCurrentInputMethodWindow(); 7409 if (imeWindow == null || imeWindow.mClient == null) { 7410 notifyReceiverWithEmptyBundle(receiver); 7411 return; 7412 } 7413 try { 7414 imeWindow.mClient.requestAppKeyboardShortcuts(receiver, deviceId); 7415 } catch (RemoteException e) { 7416 notifyReceiverWithEmptyBundle(receiver); 7417 } 7418 } 7419 enforceRegisterWindowManagerListenersPermission(String message)7420 private void enforceRegisterWindowManagerListenersPermission(String message) { 7421 mContext.enforceCallingOrSelfPermission(REGISTER_WINDOW_MANAGER_LISTENERS, message); 7422 } 7423 notifyReceiverWithEmptyBundle(IResultReceiver receiver)7424 private static void notifyReceiverWithEmptyBundle(IResultReceiver receiver) { 7425 try { 7426 receiver.send(0, Bundle.EMPTY); 7427 } catch (RemoteException e) { 7428 ProtoLog.e(WM_ERROR, "unable to call receiver for empty keyboard shortcuts"); 7429 } 7430 } 7431 7432 @Override getStableInsets(int displayId, Rect outInsets)7433 public void getStableInsets(int displayId, Rect outInsets) throws RemoteException { 7434 synchronized (mGlobalLock) { 7435 getStableInsetsLocked(displayId, outInsets); 7436 } 7437 } 7438 7439 /** This is used when there's no app info available and shall return the system default.*/ getStableInsetsLocked(int displayId, Rect outInsets)7440 void getStableInsetsLocked(int displayId, Rect outInsets) { 7441 outInsets.setEmpty(); 7442 final DisplayContent dc = mRoot.getDisplayContent(displayId); 7443 if (dc != null) { 7444 final DisplayInfo di = dc.getDisplayInfo(); 7445 outInsets.set(dc.getDisplayPolicy().getDecorInsetsInfo( 7446 di.rotation, di.logicalWidth, di.logicalHeight).mConfigInsets); 7447 } 7448 } 7449 7450 /** 7451 * Update a tap exclude region in the window identified by the provided id. Touches down on this 7452 * region will not: 7453 * <ol> 7454 * <li>Switch focus to this window.</li> 7455 * <li>Move the display of this window to top.</li> 7456 * <li>Send the touch events to this window.</li> 7457 * </ol> 7458 * Passing an invalid region will remove the area from the exclude region of this window. 7459 */ updateTapExcludeRegion(IWindow client, Region region)7460 void updateTapExcludeRegion(IWindow client, Region region) { 7461 synchronized (mGlobalLock) { 7462 final WindowState callingWin = windowForClientLocked(null, client, false); 7463 if (callingWin == null) { 7464 ProtoLog.w(WM_ERROR, "Bad requesting window %s", client); 7465 return; 7466 } 7467 callingWin.updateTapExcludeRegion(region); 7468 } 7469 } 7470 7471 /** 7472 * Forwards a scroll capture request to the appropriate window, if available. 7473 * 7474 * @param displayId the display for the request 7475 * @param behindClient token for a window, used to filter the search to windows behind it 7476 * @param taskId specifies the id of a task the result must belong to or -1 to match any task 7477 * @param listener to receive the response 7478 */ requestScrollCapture(int displayId, @Nullable IBinder behindClient, int taskId, IScrollCaptureResponseListener listener)7479 public void requestScrollCapture(int displayId, @Nullable IBinder behindClient, int taskId, 7480 IScrollCaptureResponseListener listener) { 7481 if (!checkCallingPermission(READ_FRAME_BUFFER, "requestScrollCapture()")) { 7482 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 7483 } 7484 final long token = Binder.clearCallingIdentity(); 7485 try { 7486 ScrollCaptureResponse.Builder responseBuilder = new ScrollCaptureResponse.Builder(); 7487 synchronized (mGlobalLock) { 7488 DisplayContent dc = mRoot.getDisplayContent(displayId); 7489 if (dc == null) { 7490 ProtoLog.e(WM_ERROR, 7491 "Invalid displayId for requestScrollCapture: %d", displayId); 7492 responseBuilder.setDescription(String.format("bad displayId: %d", displayId)); 7493 listener.onScrollCaptureResponse(responseBuilder.build()); 7494 return; 7495 } 7496 WindowState topWindow = null; 7497 if (behindClient != null) { 7498 topWindow = windowForClientLocked(null, behindClient, /* throwOnError*/ false); 7499 } 7500 WindowState targetWindow = dc.findScrollCaptureTargetWindow(topWindow, taskId); 7501 if (targetWindow == null) { 7502 responseBuilder.setDescription("findScrollCaptureTargetWindow returned null"); 7503 listener.onScrollCaptureResponse(responseBuilder.build()); 7504 return; 7505 } 7506 try { 7507 // Forward to the window for handling, which will respond using the callback. 7508 targetWindow.mClient.requestScrollCapture(listener); 7509 } catch (RemoteException e) { 7510 ProtoLog.w(WM_ERROR, 7511 "requestScrollCapture: caught exception dispatching to window." 7512 + "token=%s", targetWindow.mClient.asBinder()); 7513 responseBuilder.setWindowTitle(targetWindow.getName()); 7514 responseBuilder.setPackageName(targetWindow.getOwningPackage()); 7515 responseBuilder.setDescription(String.format("caught exception: %s", e)); 7516 listener.onScrollCaptureResponse(responseBuilder.build()); 7517 } 7518 } 7519 } catch (RemoteException e) { 7520 ProtoLog.w(WM_ERROR, 7521 "requestScrollCapture: caught exception dispatching callback: %s", e); 7522 } finally { 7523 Binder.restoreCallingIdentity(token); 7524 } 7525 } 7526 7527 @Override getWindowingMode(int displayId)7528 public int getWindowingMode(int displayId) { 7529 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getWindowingMode()")) { 7530 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7531 } 7532 7533 synchronized (mGlobalLock) { 7534 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 7535 if (displayContent == null) { 7536 ProtoLog.w(WM_ERROR, 7537 "Attempted to get windowing mode of a display that does not exist: %d", 7538 displayId); 7539 return WindowConfiguration.WINDOWING_MODE_UNDEFINED; 7540 } 7541 return mDisplayWindowSettings.getWindowingModeLocked(displayContent); 7542 } 7543 } 7544 7545 @Override setWindowingMode(int displayId, int mode)7546 public void setWindowingMode(int displayId, int mode) { 7547 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setWindowingMode()")) { 7548 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7549 } 7550 7551 final long origId = Binder.clearCallingIdentity(); 7552 try { 7553 synchronized (mGlobalLock) { 7554 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null); 7555 if (displayContent == null) { 7556 ProtoLog.w(WM_ERROR, 7557 "Attempted to set windowing mode to a display that does not exist: %d", 7558 displayId); 7559 return; 7560 } 7561 7562 int lastWindowingMode = displayContent.getWindowingMode(); 7563 mDisplayWindowSettings.setWindowingModeLocked(displayContent, mode); 7564 7565 displayContent.reconfigureDisplayLocked(); 7566 7567 if (lastWindowingMode != displayContent.getWindowingMode()) { 7568 // reconfigure won't detect this change in isolation because the windowing mode 7569 // is already set on the display, so fire off a new config now. 7570 displayContent.sendNewConfiguration(); 7571 // Now that all configurations are updated, execute pending transitions. 7572 displayContent.executeAppTransition(); 7573 } 7574 } 7575 } finally { 7576 Binder.restoreCallingIdentity(origId); 7577 } 7578 } 7579 7580 @Override getRemoveContentMode(int displayId)7581 public @RemoveContentMode int getRemoveContentMode(int displayId) { 7582 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getRemoveContentMode()")) { 7583 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7584 } 7585 7586 synchronized (mGlobalLock) { 7587 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 7588 if (displayContent == null) { 7589 ProtoLog.w(WM_ERROR, 7590 "Attempted to get remove mode of a display that does not exist: %d", 7591 displayId); 7592 return REMOVE_CONTENT_MODE_UNDEFINED; 7593 } 7594 return displayContent.getRemoveContentMode(); 7595 } 7596 } 7597 7598 @Override setRemoveContentMode(int displayId, @RemoveContentMode int mode)7599 public void setRemoveContentMode(int displayId, @RemoveContentMode int mode) { 7600 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setRemoveContentMode()")) { 7601 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7602 } 7603 7604 final long origId = Binder.clearCallingIdentity(); 7605 try { 7606 synchronized (mGlobalLock) { 7607 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null); 7608 if (displayContent == null) { 7609 ProtoLog.w(WM_ERROR, 7610 "Attempted to set remove mode to a display that does not exist: %d", 7611 displayId); 7612 return; 7613 } 7614 7615 mDisplayWindowSettings.setRemoveContentModeLocked(displayContent, mode); 7616 displayContent.reconfigureDisplayLocked(); 7617 } 7618 } finally { 7619 Binder.restoreCallingIdentity(origId); 7620 } 7621 } 7622 7623 @Override shouldShowWithInsecureKeyguard(int displayId)7624 public boolean shouldShowWithInsecureKeyguard(int displayId) { 7625 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowWithInsecureKeyguard()")) { 7626 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7627 } 7628 7629 synchronized (mGlobalLock) { 7630 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 7631 if (displayContent == null) { 7632 ProtoLog.w(WM_ERROR, "Attempted to get flag of a display that does not exist: %d", 7633 displayId); 7634 return false; 7635 } 7636 return mDisplayWindowSettings.shouldShowWithInsecureKeyguardLocked(displayContent); 7637 } 7638 } 7639 7640 @Override setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow)7641 public void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow) { 7642 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, 7643 "setShouldShowWithInsecureKeyguard()")) { 7644 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7645 } 7646 final long origId = Binder.clearCallingIdentity(); 7647 try { 7648 synchronized (mGlobalLock) { 7649 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null); 7650 if (displayContent == null) { 7651 ProtoLog.w(WM_ERROR, "Attempted to set flag to a display that does not exist: " 7652 + "%d", displayId); 7653 return; 7654 } 7655 7656 mDisplayWindowSettings.setShouldShowWithInsecureKeyguardLocked(displayContent, 7657 shouldShow); 7658 7659 displayContent.reconfigureDisplayLocked(); 7660 } 7661 } finally { 7662 Binder.restoreCallingIdentity(origId); 7663 } 7664 } 7665 7666 @Override shouldShowSystemDecors(int displayId)7667 public boolean shouldShowSystemDecors(int displayId) { 7668 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowSystemDecors()")) { 7669 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7670 } 7671 7672 synchronized (mGlobalLock) { 7673 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 7674 if (displayContent == null) { 7675 ProtoLog.w(WM_ERROR, "Attempted to get system decors flag of a display that does " 7676 + "not exist: %d", displayId); 7677 return false; 7678 } 7679 return displayContent.isSystemDecorationsSupported(); 7680 } 7681 } 7682 7683 @Override isEligibleForDesktopMode(int displayId)7684 public boolean isEligibleForDesktopMode(int displayId) { 7685 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "isEligibleForDesktopMode()")) { 7686 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7687 } 7688 7689 synchronized (mGlobalLock) { 7690 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 7691 if (displayContent == null) { 7692 ProtoLog.e(WM_ERROR, "Attempted to check isEligibleForDesktopMode() " 7693 + "for a display that does not exist: %d", displayId); 7694 return false; 7695 } 7696 if (!displayContent.isSystemDecorationsSupported()) { 7697 return false; 7698 } 7699 return displayContent.isDefaultDisplay || displayContent.allowContentModeSwitch(); 7700 } 7701 } 7702 7703 @Override setShouldShowSystemDecors(int displayId, boolean shouldShow)7704 public void setShouldShowSystemDecors(int displayId, boolean shouldShow) { 7705 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setShouldShowSystemDecors()")) { 7706 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7707 } 7708 final long origId = Binder.clearCallingIdentity(); 7709 try { 7710 synchronized (mGlobalLock) { 7711 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null); 7712 if (displayContent == null) { 7713 ProtoLog.w(WM_ERROR, "Attempted to set system decors flag to a display that " 7714 + "does not exist: %d", displayId); 7715 return; 7716 } 7717 if (!displayContent.isTrusted()) { 7718 throw new SecurityException("Attempted to set system decors flag to an " 7719 + "untrusted virtual display: " + displayId); 7720 } 7721 7722 mDisplayWindowSettings.setShouldShowSystemDecorsLocked(displayContent, shouldShow); 7723 7724 displayContent.reconfigureDisplayLocked(); 7725 } 7726 } finally { 7727 Binder.restoreCallingIdentity(origId); 7728 } 7729 } 7730 7731 @Override getDisplayImePolicy(int displayId)7732 public @DisplayImePolicy int getDisplayImePolicy(int displayId) { 7733 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getDisplayImePolicy()")) { 7734 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7735 } 7736 final Map<Integer, Integer> displayImePolicyCache = mDisplayImePolicyCache; 7737 if (!displayImePolicyCache.containsKey(displayId)) { 7738 ProtoLog.w(WM_ERROR, 7739 "Attempted to get IME policy of a display that does not exist: %d", 7740 displayId); 7741 return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; 7742 } 7743 return displayImePolicyCache.get(displayId); 7744 } 7745 7746 @Override setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy)7747 public void setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy) { 7748 if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setDisplayImePolicy()")) { 7749 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 7750 } 7751 final long origId = Binder.clearCallingIdentity(); 7752 try { 7753 synchronized (mGlobalLock) { 7754 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null); 7755 if (displayContent == null) { 7756 ProtoLog.w(WM_ERROR, "Attempted to set IME policy to a display" 7757 + " that does not exist: %d", displayId); 7758 return; 7759 } 7760 if (!displayContent.isTrusted()) { 7761 throw new SecurityException("Attempted to set IME policy to an untrusted " 7762 + "virtual display: " + displayId); 7763 } 7764 7765 mDisplayWindowSettings.setDisplayImePolicy(displayContent, imePolicy); 7766 7767 displayContent.reconfigureDisplayLocked(); 7768 } 7769 } finally { 7770 Binder.restoreCallingIdentity(origId); 7771 } 7772 } 7773 7774 @Override onNotificationShadeExpanded(IBinder token, boolean expanded)7775 public void onNotificationShadeExpanded(IBinder token, boolean expanded) { 7776 synchronized (mGlobalLock) { 7777 final WindowState w = mWindowMap.get(token); 7778 if (w == null || w != w.mDisplayContent.getDisplayPolicy().getNotificationShade()) { 7779 return; 7780 } 7781 final WindowProcessController topApp = mAtmService.mTopApp; 7782 // Demotes the priority of top app if notification shade is expanded to occlude the app. 7783 // So the notification shade may have more capacity to draw and animate. 7784 final int demoteTopAppReasons = mAtmService.mDemoteTopAppReasons; 7785 if (expanded && mAtmService.mTopProcessState == ActivityManager.PROCESS_STATE_TOP 7786 && (demoteTopAppReasons & DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE) == 0) { 7787 mAtmService.mDemoteTopAppReasons = 7788 demoteTopAppReasons | DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE; 7789 Trace.instant(TRACE_TAG_WINDOW_MANAGER, "demote-top-for-ns"); 7790 if (topApp != null) { 7791 topApp.scheduleUpdateOomAdj(); 7792 } 7793 } else if (!expanded 7794 && (demoteTopAppReasons & DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE) != 0) { 7795 mAtmService.mDemoteTopAppReasons = 7796 demoteTopAppReasons & ~DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE; 7797 Trace.instant(TRACE_TAG_WINDOW_MANAGER, "cancel-demote-top-for-ns"); 7798 if (topApp != null) { 7799 topApp.scheduleUpdateOomAdj(); 7800 } 7801 } 7802 } 7803 } 7804 7805 @Override registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)7806 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver) 7807 throws RemoteException { 7808 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) { 7809 throw new SecurityException( 7810 "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission"); 7811 } 7812 mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver); 7813 } 7814 7815 private final class LocalService extends WindowManagerInternal { 7816 7817 @Override getAccessibilityController()7818 public AccessibilityControllerInternal getAccessibilityController() { 7819 return AccessibilityController.getAccessibilityControllerInternal( 7820 WindowManagerService.this); 7821 } 7822 7823 @Override clearSnapshotCache()7824 public void clearSnapshotCache() { 7825 synchronized (mGlobalLock) { 7826 mTaskSnapshotController.clearSnapshotCache(); 7827 } 7828 } 7829 7830 @Override requestTraversalFromDisplayManager()7831 public void requestTraversalFromDisplayManager() { 7832 synchronized (mGlobalLock) { 7833 requestTraversal(); 7834 } 7835 } 7836 7837 @Override onDisplayManagerReceivedDeviceState(int deviceState)7838 public void onDisplayManagerReceivedDeviceState(int deviceState) { 7839 mH.post(() -> { 7840 synchronized (mGlobalLock) { 7841 mRoot.onDisplayManagerReceivedDeviceState(deviceState); 7842 } 7843 }); 7844 } 7845 7846 @Override setMagnificationSpec(int displayId, MagnificationSpec spec)7847 public void setMagnificationSpec(int displayId, MagnificationSpec spec) { 7848 synchronized (mGlobalLock) { 7849 if (mAccessibilityController.hasCallbacks()) { 7850 mAccessibilityController.setMagnificationSpec(displayId, spec); 7851 } else { 7852 throw new IllegalStateException("Magnification callbacks not set!"); 7853 } 7854 } 7855 } 7856 7857 @Override setFullscreenMagnificationActivated(int displayId, boolean activated)7858 public void setFullscreenMagnificationActivated(int displayId, boolean activated) { 7859 synchronized (mGlobalLock) { 7860 if (mAccessibilityController.hasCallbacks()) { 7861 mAccessibilityController 7862 .setFullscreenMagnificationActivated(displayId, activated); 7863 } else { 7864 throw new IllegalStateException("Magnification callbacks not set!"); 7865 } 7866 } 7867 } 7868 7869 @Override getMagnificationRegion(int displayId, @NonNull Region magnificationRegion)7870 public void getMagnificationRegion(int displayId, @NonNull Region magnificationRegion) { 7871 synchronized (mGlobalLock) { 7872 if (mAccessibilityController.hasCallbacks()) { 7873 mAccessibilityController.getMagnificationRegion(displayId, magnificationRegion); 7874 } else { 7875 throw new IllegalStateException("Magnification callbacks not set!"); 7876 } 7877 } 7878 } 7879 7880 @Override setMagnificationCallbacks(int displayId, @Nullable MagnificationCallbacks callbacks)7881 public boolean setMagnificationCallbacks(int displayId, 7882 @Nullable MagnificationCallbacks callbacks) { 7883 synchronized (mGlobalLock) { 7884 return mAccessibilityController.setMagnificationCallbacks(displayId, callbacks); 7885 } 7886 } 7887 7888 @Override setWindowsForAccessibilityCallback(int displayId, WindowsForAccessibilityCallback callback)7889 public void setWindowsForAccessibilityCallback(int displayId, 7890 WindowsForAccessibilityCallback callback) { 7891 synchronized (mGlobalLock) { 7892 mAccessibilityController.setWindowsForAccessibilityCallback(displayId, callback); 7893 } 7894 } 7895 7896 @Override setInputFilter(IInputFilter filter)7897 public void setInputFilter(IInputFilter filter) { 7898 mInputManager.setInputFilter(filter); 7899 } 7900 7901 @Override getFocusedWindowToken()7902 public IBinder getFocusedWindowToken() { 7903 synchronized (mGlobalLock) { 7904 return mAccessibilityController.getFocusedWindowToken(); 7905 } 7906 } 7907 7908 // TODO (b/229837707): Delete this method after changing the solution. 7909 @Override getFocusedWindowTokenFromWindowStates()7910 public IBinder getFocusedWindowTokenFromWindowStates() { 7911 synchronized (mGlobalLock) { 7912 final WindowState windowState = getFocusedWindowLocked(); 7913 if (windowState != null) { 7914 return windowState.mClient.asBinder(); 7915 } 7916 return null; 7917 } 7918 } 7919 7920 @Override moveDisplayToTopIfAllowed(int displayId)7921 public void moveDisplayToTopIfAllowed(int displayId) { 7922 WindowManagerService.this.moveDisplayToTopIfAllowed(displayId); 7923 } 7924 7925 @Override requestWindowFocus(IBinder windowToken)7926 public void requestWindowFocus(IBinder windowToken) { 7927 synchronized (mGlobalLock) { 7928 final InputTarget inputTarget = 7929 WindowManagerService.this.getInputTargetFromWindowTokenLocked(windowToken); 7930 WindowManagerService.this.onPointerDownOutsideFocusLocked(inputTarget, 7931 false /* fromHandler */); 7932 } 7933 } 7934 7935 @Override isKeyguardLocked()7936 public boolean isKeyguardLocked() { 7937 return WindowManagerService.this.isKeyguardLocked(); 7938 } 7939 7940 @Override isKeyguardShowingAndNotOccluded()7941 public boolean isKeyguardShowingAndNotOccluded() { 7942 return WindowManagerService.this.isKeyguardShowingAndNotOccluded(); 7943 } 7944 7945 @Override isKeyguardSecure(@serIdInt int userId)7946 public boolean isKeyguardSecure(@UserIdInt int userId) { 7947 return mPolicy.isKeyguardSecure(userId); 7948 } 7949 7950 @Override showGlobalActions()7951 public void showGlobalActions() { 7952 WindowManagerService.this.showGlobalActions(); 7953 } 7954 7955 @Override getWindowFrame(IBinder token, Rect outBounds)7956 public void getWindowFrame(IBinder token, Rect outBounds) { 7957 synchronized (mGlobalLock) { 7958 WindowState windowState = mWindowMap.get(token); 7959 if (windowState != null) { 7960 outBounds.set(windowState.getFrame()); 7961 } else { 7962 outBounds.setEmpty(); 7963 } 7964 } 7965 } 7966 7967 @Override getWindowTransformationMatrixAndMagnificationSpec( IBinder token)7968 public Pair<Matrix, MagnificationSpec> getWindowTransformationMatrixAndMagnificationSpec( 7969 IBinder token) { 7970 return mAccessibilityController 7971 .getWindowTransformationMatrixAndMagnificationSpec(token); 7972 } 7973 7974 @Override waitForAllWindowsDrawn(Message message, long timeout, int displayId)7975 public void waitForAllWindowsDrawn(Message message, long timeout, int displayId) { 7976 Objects.requireNonNull(message.getTarget()); 7977 boolean allWindowsDrawn = false; 7978 synchronized (mGlobalLock) { 7979 allWindowsDrawn = waitForAllWindowsDrawnLocked(message, timeout, displayId); 7980 } 7981 if (allWindowsDrawn) { 7982 message.sendToTarget(); 7983 } 7984 } 7985 7986 /** Return {@code true} if all windows have been drawn. */ waitForAllWindowsDrawnLocked(Message message, long timeout, int displayId)7987 private boolean waitForAllWindowsDrawnLocked(Message message, long timeout, int displayId) { 7988 final WindowContainer<?> container = displayId == INVALID_DISPLAY 7989 ? mRoot : mRoot.getDisplayContent(displayId); 7990 if (container == null) { 7991 // The waiting container doesn't exist, no need to wait. Treat as drawn. 7992 return true; 7993 } 7994 if (displayId == INVALID_DISPLAY 7995 && mRoot.getDefaultDisplay().mDisplayUpdater.waitForTransition(message)) { 7996 // Use the ready-to-play of transition as the signal. 7997 return false; 7998 } 7999 container.waitForAllWindowsDrawn(); 8000 mWindowPlacerLocked.requestTraversal(); 8001 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container); 8002 if (container.mWaitingForDrawn.isEmpty()) { 8003 return true; 8004 } 8005 if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { 8006 for (int i = 0; i < container.mWaitingForDrawn.size(); i++) { 8007 traceStartWaitingForWindowDrawn(container.mWaitingForDrawn.get(i)); 8008 } 8009 } 8010 8011 mWaitingForDrawnCallbacks.put(container, message); 8012 mH.sendNewMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, container, timeout); 8013 checkDrawnWindowsLocked(); 8014 return false; 8015 } 8016 8017 @Override setForcedDisplaySize(int displayId, int width, int height)8018 public void setForcedDisplaySize(int displayId, int width, int height) { 8019 WindowManagerService.this.setForcedDisplaySize(displayId, width, height); 8020 } 8021 8022 @Override clearForcedDisplaySize(int displayId)8023 public void clearForcedDisplaySize(int displayId) { 8024 WindowManagerService.this.clearForcedDisplaySize(displayId); 8025 } 8026 8027 @Override addWindowToken(IBinder token, int type, int displayId, @Nullable Bundle options)8028 public void addWindowToken(IBinder token, int type, int displayId, 8029 @Nullable Bundle options) { 8030 WindowManagerService.this.addWindowToken(token, type, displayId, options); 8031 } 8032 8033 @Override removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit, int displayId)8034 public void removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit, 8035 int displayId) { 8036 WindowManagerService.this.removeWindowToken(binder, removeWindows, animateExit, 8037 displayId); 8038 } 8039 8040 @Override moveWindowTokenToDisplay(IBinder binder, int displayId)8041 public void moveWindowTokenToDisplay(IBinder binder, int displayId) { 8042 WindowManagerService.this.moveWindowTokenToDisplay(binder, displayId); 8043 } 8044 8045 // TODO(multi-display): currently only used by PWM to notify keyguard transitions as well 8046 // forwarding it to SystemUI for synchronizing status and navigation bar animations. 8047 @Override registerAppTransitionListener(AppTransitionListener listener)8048 public void registerAppTransitionListener(AppTransitionListener listener) { 8049 synchronized (mGlobalLock) { 8050 mAtmService.getTransitionController().registerLegacyListener(listener); 8051 } 8052 } 8053 8054 @Override registerTaskSystemBarsListener(TaskSystemBarsListener listener)8055 public void registerTaskSystemBarsListener(TaskSystemBarsListener listener) { 8056 synchronized (mGlobalLock) { 8057 mTaskSystemBarsListenerController.registerListener(listener); 8058 } 8059 } 8060 8061 @Override unregisterTaskSystemBarsListener(TaskSystemBarsListener listener)8062 public void unregisterTaskSystemBarsListener(TaskSystemBarsListener listener) { 8063 synchronized (mGlobalLock) { 8064 mTaskSystemBarsListenerController.unregisterListener(listener); 8065 } 8066 } 8067 8068 @Override reportPasswordChanged(int userId)8069 public void reportPasswordChanged(int userId) { 8070 mKeyguardDisableHandler.updateKeyguardEnabled(userId); 8071 } 8072 8073 @Override getInputMethodWindowVisibleHeight(int displayId)8074 public int getInputMethodWindowVisibleHeight(int displayId) { 8075 synchronized (mGlobalLock) { 8076 final DisplayContent dc = mRoot.getDisplayContent(displayId); 8077 return dc.getInputMethodWindowVisibleHeight(); 8078 } 8079 } 8080 8081 @Override setDismissImeOnBackKeyPressed(boolean dismissImeOnBackKeyPressed)8082 public void setDismissImeOnBackKeyPressed(boolean dismissImeOnBackKeyPressed) { 8083 mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed); 8084 } 8085 8086 @Override updateInputMethodTargetWindow(@onNull IBinder imeTargetWindowToken)8087 public void updateInputMethodTargetWindow(@NonNull IBinder imeTargetWindowToken) { 8088 // TODO (b/34628091): Use this method to address the window animation issue. 8089 if (DEBUG_INPUT_METHOD) { 8090 Slog.w(TAG_WM, "updateInputMethodTargetWindow:" 8091 + " imeTargetWindowToken=" + imeTargetWindowToken); 8092 } 8093 synchronized (mGlobalLock) { 8094 InputTarget imeTarget = 8095 getInputTargetFromWindowTokenLocked(imeTargetWindowToken); 8096 if (imeTarget != null) { 8097 imeTarget.getDisplayContent().updateImeInputAndControlTarget(imeTarget); 8098 8099 if (android.view.inputmethod.Flags.refactorInsetsController()) { 8100 // In case of a virtual display that may not show the IME, reset the 8101 // inputTarget of all other displays 8102 WindowState imeWindowState = imeTarget.getWindowState(); 8103 if (imeWindowState != null) { 8104 InsetsControlTarget fallback = 8105 imeTarget.getDisplayContent().getImeHostOrFallback( 8106 imeWindowState); 8107 if (imeWindowState != fallback) { 8108 // fallback should be the RemoteInsetsControlTarget of the 8109 // default display 8110 int currentDisplayId = imeTarget.getDisplayContent().getDisplayId(); 8111 mRoot.forAllDisplays(display -> { 8112 if (display.getDisplayId() != currentDisplayId) { 8113 display.setImeInputTarget(null); 8114 } 8115 }); 8116 } 8117 } 8118 } 8119 } 8120 } 8121 } 8122 8123 @Override isHardKeyboardAvailable()8124 public boolean isHardKeyboardAvailable() { 8125 synchronized (mGlobalLock) { 8126 return mHardKeyboardAvailable; 8127 } 8128 } 8129 8130 @Override setOnHardKeyboardStatusChangeListener( OnHardKeyboardStatusChangeListener listener)8131 public void setOnHardKeyboardStatusChangeListener( 8132 OnHardKeyboardStatusChangeListener listener) { 8133 synchronized (mGlobalLock) { 8134 mHardKeyboardStatusChangeListener = listener; 8135 } 8136 } 8137 8138 @Override setOnImeRequestedChangedListener( OnImeRequestedChangedListener listener)8139 public void setOnImeRequestedChangedListener( 8140 OnImeRequestedChangedListener listener) { 8141 synchronized (mGlobalLock) { 8142 mOnImeRequestedChangedListener = listener; 8143 } 8144 } 8145 8146 @Override computeWindowsForAccessibility(int displayId)8147 public void computeWindowsForAccessibility(int displayId) { 8148 mAccessibilityController.performComputeChangedWindowsNot(displayId, true); 8149 } 8150 8151 @Override setVr2dDisplayId(int vr2dDisplayId)8152 public void setVr2dDisplayId(int vr2dDisplayId) { 8153 if (DEBUG_DISPLAY) { 8154 Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId); 8155 } 8156 synchronized (mGlobalLock) { 8157 mVr2dDisplayId = vr2dDisplayId; 8158 } 8159 } 8160 8161 @Override registerDragDropControllerCallback(IDragDropCallback callback)8162 public void registerDragDropControllerCallback(IDragDropCallback callback) { 8163 mDragDropController.registerCallback(callback); 8164 } 8165 8166 @Override lockNow()8167 public void lockNow() { 8168 WindowManagerService.this.lockNow(null); 8169 } 8170 8171 @Override getWindowOwnerUserId(IBinder token)8172 public int getWindowOwnerUserId(IBinder token) { 8173 synchronized (mGlobalLock) { 8174 WindowState window = mWindowMap.get(token); 8175 if (window != null) { 8176 return window.mShowUserId; 8177 } 8178 return UserHandle.USER_NULL; 8179 } 8180 } 8181 8182 @Override setWallpaperShowWhenLocked(IBinder binder, boolean showWhenLocked)8183 public void setWallpaperShowWhenLocked(IBinder binder, boolean showWhenLocked) { 8184 synchronized (mGlobalLock) { 8185 final WindowToken token = mRoot.getWindowToken(binder); 8186 if (token == null || token.asWallpaperToken() == null) { 8187 ProtoLog.w(WM_ERROR, 8188 "setWallpaperShowWhenLocked: non-existent wallpaper token: %s", binder); 8189 return; 8190 } 8191 token.asWallpaperToken().setShowWhenLocked(showWhenLocked); 8192 } 8193 } 8194 8195 @Override setWallpaperCropHints(IBinder binder, SparseArray<Rect> cropHints)8196 public void setWallpaperCropHints(IBinder binder, SparseArray<Rect> cropHints) { 8197 synchronized (mGlobalLock) { 8198 final WindowToken token = mRoot.getWindowToken(binder); 8199 if (token == null || token.asWallpaperToken() == null) { 8200 ProtoLog.w(WM_ERROR, 8201 "setWallpaperCropHints: non-existent wallpaper token: %s", binder); 8202 return; 8203 } 8204 token.asWallpaperToken().setCropHints(cropHints); 8205 } 8206 } 8207 8208 @Override isUidFocused(int uid)8209 public boolean isUidFocused(int uid) { 8210 synchronized (mGlobalLock) { 8211 for (int i = mRoot.getChildCount() - 1; i >= 0; i--) { 8212 final DisplayContent displayContent = mRoot.getChildAt(i); 8213 if (displayContent.mCurrentFocus != null 8214 && uid == displayContent.mCurrentFocus.getOwningUid()) { 8215 return true; 8216 } 8217 } 8218 return false; 8219 } 8220 } 8221 8222 @Override hasInputMethodClientFocus(IBinder windowToken, int uid, int pid, int displayId)8223 public @ImeClientFocusResult int hasInputMethodClientFocus(IBinder windowToken, 8224 int uid, int pid, int displayId) { 8225 if (displayId == Display.INVALID_DISPLAY) { 8226 return ImeClientFocusResult.INVALID_DISPLAY_ID; 8227 } 8228 synchronized (mGlobalLock) { 8229 final DisplayContent displayContent = mRoot.getTopFocusedDisplayContent(); 8230 InputTarget target = getInputTargetFromWindowTokenLocked(windowToken); 8231 if (target == null) { 8232 return ImeClientFocusResult.NOT_IME_TARGET_WINDOW; 8233 } 8234 final int tokenDisplayId = target.getDisplayContent().getDisplayId(); 8235 if (tokenDisplayId != displayId) { 8236 Slog.e(TAG, "isInputMethodClientFocus: display ID mismatch." 8237 + " from client: " + displayId 8238 + " from window: " + tokenDisplayId); 8239 return ImeClientFocusResult.DISPLAY_ID_MISMATCH; 8240 } 8241 if (displayContent == null 8242 || displayContent.getDisplayId() != displayId 8243 || !displayContent.hasAccess(uid)) { 8244 return ImeClientFocusResult.INVALID_DISPLAY_ID; 8245 } 8246 8247 if (target.isInputMethodClientFocus(uid, pid)) { 8248 return ImeClientFocusResult.HAS_IME_FOCUS; 8249 } 8250 // Okay, how about this... what is the current focus? 8251 // It seems in some cases we may not have moved the IM 8252 // target window, such as when it was in a pop-up window, 8253 // so let's also look at the current focus. (An example: 8254 // go to Gmail, start searching so the keyboard goes up, 8255 // press home. Sometimes the IME won't go down.) 8256 // Would be nice to fix this more correctly, but it's 8257 // way at the end of a release, and this should be good enough. 8258 final WindowState currentFocus = displayContent.mCurrentFocus; 8259 if (currentFocus != null && currentFocus.mSession.mUid == uid 8260 && currentFocus.mSession.mPid == pid) { 8261 return currentFocus.canBeImeTarget() ? ImeClientFocusResult.HAS_IME_FOCUS 8262 : ImeClientFocusResult.NOT_IME_TARGET_WINDOW; 8263 } 8264 } 8265 return ImeClientFocusResult.NOT_IME_TARGET_WINDOW; 8266 } 8267 8268 @Override showImePostLayout(IBinder imeTargetWindowToken, @NonNull ImeTracker.Token statsToken)8269 public void showImePostLayout(IBinder imeTargetWindowToken, 8270 @NonNull ImeTracker.Token statsToken) { 8271 synchronized (mGlobalLock) { 8272 InputTarget imeTarget = getInputTargetFromWindowTokenLocked(imeTargetWindowToken); 8273 if (imeTarget == null) { 8274 ImeTracker.forLogging().onFailed(statsToken, 8275 ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET); 8276 return; 8277 } 8278 ImeTracker.forLogging().onProgress(statsToken, 8279 ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET); 8280 8281 final InsetsControlTarget controlTarget = imeTarget.getImeControlTarget(); 8282 imeTarget = controlTarget.getWindow(); 8283 // If InsetsControlTarget doesn't have a window, it's using remoteControlTarget 8284 // which is controlled by default display 8285 final DisplayContent dc = imeTarget != null 8286 ? imeTarget.getDisplayContent() : getDefaultDisplayContentLocked(); 8287 dc.getInsetsStateController().getImeSourceProvider() 8288 .scheduleShowImePostLayout(controlTarget, statsToken); 8289 } 8290 } 8291 8292 @Override hideIme(IBinder imeTargetWindowToken, int displayId, @NonNull ImeTracker.Token statsToken)8293 public void hideIme(IBinder imeTargetWindowToken, int displayId, 8294 @NonNull ImeTracker.Token statsToken) { 8295 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WMS.hideIme"); 8296 synchronized (mGlobalLock) { 8297 WindowState imeTarget = mWindowMap.get(imeTargetWindowToken); 8298 ProtoLog.d(WM_DEBUG_IME, "hideIme target: %s ", imeTarget); 8299 DisplayContent dc = mRoot.getDisplayContent(displayId); 8300 if (imeTarget != null) { 8301 imeTarget = imeTarget.getImeControlTarget().getWindow(); 8302 if (imeTarget != null) { 8303 dc = imeTarget.getDisplayContent(); 8304 } 8305 // If there was a pending IME show(), reset it as IME has been 8306 // requested to be hidden. 8307 dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout(); 8308 } 8309 if (dc != null && dc.getImeTarget(IME_TARGET_CONTROL) != null) { 8310 ImeTracker.forLogging().onProgress(statsToken, 8311 ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET); 8312 ProtoLog.d(WM_DEBUG_IME, "hideIme Control target: %s ", 8313 dc.getImeTarget(IME_TARGET_CONTROL)); 8314 dc.getImeTarget(IME_TARGET_CONTROL).hideInsets(WindowInsets.Type.ime(), 8315 true /* fromIme */, statsToken); 8316 } else { 8317 ImeTracker.forLogging().onFailed(statsToken, 8318 ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET); 8319 } 8320 if (dc != null) { 8321 dc.getInsetsStateController().getImeSourceProvider().setImeShowing(false); 8322 } 8323 } 8324 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 8325 } 8326 8327 @Override isUidAllowedOnDisplay(int displayId, int uid)8328 public boolean isUidAllowedOnDisplay(int displayId, int uid) { 8329 if (displayId == Display.DEFAULT_DISPLAY) { 8330 return true; 8331 } 8332 if (displayId == Display.INVALID_DISPLAY) { 8333 return false; 8334 } 8335 synchronized (mGlobalLock) { 8336 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 8337 return displayContent != null && displayContent.hasAccess(uid); 8338 } 8339 } 8340 8341 @Override getDisplayIdForWindow(IBinder windowToken)8342 public int getDisplayIdForWindow(IBinder windowToken) { 8343 synchronized (mGlobalLock) { 8344 final WindowState window = mWindowMap.get(windowToken); 8345 if (window != null) { 8346 return window.getDisplayContent().getDisplayId(); 8347 } 8348 return Display.INVALID_DISPLAY; 8349 } 8350 } 8351 8352 @Override getTopFocusedDisplayId()8353 public int getTopFocusedDisplayId() { 8354 synchronized (mGlobalLock) { 8355 return mRoot.getTopFocusedDisplayContent().getDisplayId(); 8356 } 8357 } 8358 8359 @Override getTopFocusedDisplayUiContext()8360 public Context getTopFocusedDisplayUiContext() { 8361 synchronized (mGlobalLock) { 8362 return mRoot.getTopFocusedDisplayContent().getDisplayUiContext(); 8363 } 8364 } 8365 8366 @Override setNonDefaultDisplayRotation(int displayId, @Surface.Rotation int rotation, @NonNull String caller)8367 public void setNonDefaultDisplayRotation(int displayId, @Surface.Rotation int rotation, 8368 @NonNull String caller) { 8369 if (displayId == Display.DEFAULT_DISPLAY || displayId == Display.INVALID_DISPLAY) { 8370 Slog.w(TAG, "Cannot set rotation for display with id: " + displayId); 8371 return; 8372 } 8373 synchronized (mGlobalLock) { 8374 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 8375 if (displayContent == null) { 8376 Slog.w(TAG, "Cannot set rotation for display " + displayId 8377 + " due to missing DisplayContent"); 8378 return; 8379 } 8380 displayContent.getDisplayRotation().setUserRotation( 8381 displayContent.getDisplayRotation().getUserRotationMode(), rotation, 8382 caller); 8383 } 8384 } 8385 8386 @Override setHomeSupportedOnDisplay(String displayUniqueId, int displayType, boolean supported)8387 public void setHomeSupportedOnDisplay(String displayUniqueId, int displayType, 8388 boolean supported) { 8389 final long origId = Binder.clearCallingIdentity(); 8390 try { 8391 synchronized (mGlobalLock) { 8392 mDisplayWindowSettings.setHomeSupportedOnDisplayLocked( 8393 displayUniqueId, displayType, supported); 8394 } 8395 } finally { 8396 Binder.restoreCallingIdentity(origId); 8397 } 8398 } 8399 8400 @Override isHomeSupportedOnDisplay(int displayId)8401 public boolean isHomeSupportedOnDisplay(int displayId) { 8402 synchronized (mGlobalLock) { 8403 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 8404 if (displayContent == null) { 8405 ProtoLog.w(WM_ERROR, "Attempted to get home support flag of a display that " 8406 + "does not exist: %d", displayId); 8407 return false; 8408 } 8409 return displayContent.isHomeSupported(); 8410 } 8411 } 8412 8413 @Override setIgnoreActivitySizeRestrictionsOnDisplay(@onNull String displayUniqueId, int displayType, boolean enabled)8414 public void setIgnoreActivitySizeRestrictionsOnDisplay(@NonNull String displayUniqueId, 8415 int displayType, boolean enabled) { 8416 final long origId = Binder.clearCallingIdentity(); 8417 try { 8418 synchronized (mGlobalLock) { 8419 mDisplayWindowSettings.setIgnoreActivitySizeRestrictionsOnDisplayLocked( 8420 displayUniqueId, displayType, enabled); 8421 } 8422 } finally { 8423 Binder.restoreCallingIdentity(origId); 8424 } 8425 } 8426 8427 @Override clearDisplaySettings(String displayUniqueId, int displayType)8428 public void clearDisplaySettings(String displayUniqueId, int displayType) { 8429 final long origId = Binder.clearCallingIdentity(); 8430 try { 8431 synchronized (mGlobalLock) { 8432 mDisplayWindowSettings.clearDisplaySettings(displayUniqueId, displayType); 8433 } 8434 } finally { 8435 Binder.restoreCallingIdentity(origId); 8436 } 8437 } 8438 8439 @Override getDisplayImePolicy(int displayId)8440 public @DisplayImePolicy int getDisplayImePolicy(int displayId) { 8441 return WindowManagerService.this.getDisplayImePolicy(displayId); 8442 } 8443 8444 @Override addRefreshRateRangeForPackage(@onNull String packageName, float minRefreshRate, float maxRefreshRate)8445 public void addRefreshRateRangeForPackage(@NonNull String packageName, 8446 float minRefreshRate, float maxRefreshRate) { 8447 synchronized (mGlobalLock) { 8448 mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().getRefreshRatePolicy() 8449 .addRefreshRateRangeForPackage( 8450 packageName, minRefreshRate, maxRefreshRate)); 8451 } 8452 } 8453 8454 @Override removeRefreshRateRangeForPackage(@onNull String packageName)8455 public void removeRefreshRateRangeForPackage(@NonNull String packageName) { 8456 synchronized (mGlobalLock) { 8457 mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().getRefreshRatePolicy() 8458 .removeRefreshRateRangeForPackage(packageName)); 8459 } 8460 } 8461 8462 @Override isTouchOrFaketouchDevice()8463 public boolean isTouchOrFaketouchDevice() { 8464 synchronized (mGlobalLock) { 8465 if (mIsTouchDevice && !mIsFakeTouchDevice) { 8466 throw new IllegalStateException( 8467 "touchscreen supported device must report faketouch."); 8468 } 8469 return mIsFakeTouchDevice; 8470 } 8471 } 8472 8473 @Override getKeyInterceptionInfoFromToken(IBinder inputToken)8474 public @Nullable KeyInterceptionInfo getKeyInterceptionInfoFromToken(IBinder inputToken) { 8475 return mKeyInterceptionInfoForToken.get(inputToken); 8476 } 8477 8478 @Override setAccessibilityIdToSurfaceMetadata( IBinder windowToken, int accessibilityWindowId)8479 public void setAccessibilityIdToSurfaceMetadata( 8480 IBinder windowToken, int accessibilityWindowId) { 8481 synchronized (mGlobalLock) { 8482 final WindowState state = mWindowMap.get(windowToken); 8483 if (state == null) { 8484 Slog.w(TAG, "Cannot find window which accessibility connection is added to"); 8485 return; 8486 } 8487 mTransaction.setMetadata(state.mSurfaceControl, 8488 SurfaceControl.METADATA_ACCESSIBILITY_ID, accessibilityWindowId).apply(); 8489 } 8490 } 8491 8492 @Override getWindowName(@onNull IBinder binder)8493 public String getWindowName(@NonNull IBinder binder) { 8494 synchronized (mGlobalLock) { 8495 final WindowState w = mWindowMap.get(binder); 8496 return w != null ? w.getName() : null; 8497 } 8498 } 8499 8500 @Override onToggleImeRequested(boolean show, IBinder focusedToken, IBinder requestToken, int displayId)8501 public ImeTargetInfo onToggleImeRequested(boolean show, IBinder focusedToken, 8502 IBinder requestToken, int displayId) { 8503 final String focusedWindowName; 8504 final String requestWindowName; 8505 final String imeControlTargetName; 8506 final String imeLayerTargetName; 8507 final String imeSurfaceParentName; 8508 synchronized (mGlobalLock) { 8509 final WindowState focusedWin = mWindowMap.get(focusedToken); 8510 focusedWindowName = focusedWin != null ? focusedWin.getName() : "null"; 8511 final WindowState requestWin = mWindowMap.get(requestToken); 8512 requestWindowName = requestWin != null ? requestWin.getName() : "null"; 8513 final DisplayContent dc = mRoot.getDisplayContent(displayId); 8514 if (dc != null) { 8515 final InsetsControlTarget controlTarget = dc.getImeTarget(IME_TARGET_CONTROL); 8516 if (controlTarget != null) { 8517 final WindowState w = InsetsControlTarget.asWindowOrNull(controlTarget); 8518 imeControlTargetName = w != null ? w.getName() : controlTarget.toString(); 8519 } else { 8520 imeControlTargetName = "null"; 8521 } 8522 final InsetsControlTarget target = dc.getImeTarget(IME_TARGET_LAYERING); 8523 imeLayerTargetName = target != null ? target.getWindow().getName() : "null"; 8524 final SurfaceControl imeParent = dc.mInputMethodSurfaceParent; 8525 imeSurfaceParentName = imeParent != null ? imeParent.toString() : "null"; 8526 if (show) { 8527 dc.onShowImeRequested(); 8528 } 8529 } else { 8530 imeControlTargetName = imeLayerTargetName = imeSurfaceParentName = "no-display"; 8531 } 8532 } 8533 return new ImeTargetInfo(focusedWindowName, requestWindowName, imeControlTargetName, 8534 imeLayerTargetName, imeSurfaceParentName); 8535 } 8536 8537 @Override shouldRestoreImeVisibility(IBinder imeTargetWindowToken)8538 public boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) { 8539 return WindowManagerService.this.shouldRestoreImeVisibility(imeTargetWindowToken); 8540 } 8541 8542 @Override addTrustedTaskOverlay(int taskId, SurfaceControlViewHost.SurfacePackage overlay)8543 public void addTrustedTaskOverlay(int taskId, 8544 SurfaceControlViewHost.SurfacePackage overlay) { 8545 if (overlay == null) { 8546 throw new IllegalArgumentException("Invalid overlay passed in for task=" + taskId); 8547 } 8548 synchronized (mGlobalLock) { 8549 if (overlay.getSurfaceControl() == null 8550 || !overlay.getSurfaceControl().isValid()) { 8551 throw new IllegalArgumentException( 8552 "Invalid overlay surfacecontrol passed in for task=" + taskId); 8553 } 8554 final Task task = mRoot.getRootTask(taskId); 8555 if (task == null) { 8556 throw new IllegalArgumentException("no task with taskId" + taskId); 8557 } 8558 task.addTrustedOverlay(overlay, task.getTopVisibleAppMainWindow()); 8559 } 8560 } 8561 8562 @Override removeTrustedTaskOverlay(int taskId, SurfaceControlViewHost.SurfacePackage overlay)8563 public void removeTrustedTaskOverlay(int taskId, 8564 SurfaceControlViewHost.SurfacePackage overlay) { 8565 if (overlay == null) { 8566 throw new IllegalArgumentException("Invalid overlay passed in for task=" + taskId); 8567 } 8568 synchronized (mGlobalLock) { 8569 if (overlay.getSurfaceControl() == null 8570 || !overlay.getSurfaceControl().isValid()) { 8571 throw new IllegalArgumentException( 8572 "Invalid overlay surfacecontrol passed in for task=" + taskId); 8573 } 8574 final Task task = mRoot.getRootTask(taskId); 8575 if (task == null) { 8576 throw new IllegalArgumentException("no task with taskId" + taskId); 8577 } 8578 task.removeTrustedOverlay(overlay); 8579 } 8580 } 8581 8582 @Override getHandwritingSurfaceForDisplay(int displayId)8583 public SurfaceControl getHandwritingSurfaceForDisplay(int displayId) { 8584 synchronized (mGlobalLock) { 8585 final DisplayContent dc = mRoot.getDisplayContent(displayId); 8586 if (dc == null) { 8587 Slog.e(TAG, "Failed to create a handwriting surface on display: " 8588 + displayId + " - DisplayContent not found."); 8589 return null; 8590 } 8591 final SurfaceControl inputOverlay = dc.getInputOverlayLayer(); 8592 if (inputOverlay == null) { 8593 Slog.e(TAG, "Failed to create a gesture monitor on display: " + displayId 8594 + " - Input overlay layer is not initialized."); 8595 return null; 8596 } 8597 // TODO(b/210039666): Use a method like add/removeDisplayOverlay if available. 8598 return makeSurfaceBuilder() 8599 .setContainerLayer() 8600 .setName("IME Handwriting Surface") 8601 .setCallsite("getHandwritingSurfaceForDisplay") 8602 .setParent(inputOverlay) 8603 .build(); 8604 } 8605 } 8606 8607 @Override isPointInsideWindow(@onNull IBinder windowToken, int displayId, float displayX, float displayY)8608 public boolean isPointInsideWindow(@NonNull IBinder windowToken, int displayId, 8609 float displayX, float displayY) { 8610 synchronized (mGlobalLock) { 8611 final WindowState w = mWindowMap.get(windowToken); 8612 if (w == null || w.getDisplayId() != displayId) { 8613 return false; 8614 } 8615 8616 return w.getBounds().contains((int) displayX, (int) displayY); 8617 } 8618 } 8619 8620 @Override setContentRecordingSession( @ullable ContentRecordingSession incomingSession)8621 public boolean setContentRecordingSession( 8622 @Nullable ContentRecordingSession incomingSession) { 8623 synchronized (mGlobalLock) { 8624 // Allow the controller to handle teardown of a non-task session. 8625 if (incomingSession == null 8626 || incomingSession.getContentToRecord() != RECORD_CONTENT_TASK) { 8627 mContentRecordingController.setContentRecordingSessionLocked(incomingSession, 8628 WindowManagerService.this); 8629 return true; 8630 } 8631 // For a task session, find the activity identified by the launch cookie. 8632 final WindowContainerInfo wci = 8633 getTaskWindowContainerInfoForRecordingSession(incomingSession); 8634 if (wci == null) { 8635 Slog.w(TAG, "Handling a new recording session; unable to find the " 8636 + "WindowContainerToken"); 8637 return false; 8638 } 8639 // Replace the launch cookie in the session details with the task's 8640 // WindowContainerToken. 8641 incomingSession.setTokenToRecord(wci.getToken().asBinder()); 8642 // Also replace the UNKNOWN target UID with the actual UID. 8643 incomingSession.setTargetUid(wci.getUid()); 8644 mContentRecordingController.setContentRecordingSessionLocked(incomingSession, 8645 WindowManagerService.this); 8646 return true; 8647 } 8648 } 8649 8650 @Override getA11yOverlayLayer(int displayId)8651 public SurfaceControl getA11yOverlayLayer(int displayId) { 8652 synchronized (mGlobalLock) { 8653 DisplayContent dc = mRoot.getDisplayContent(displayId); 8654 if (dc != null) { 8655 return dc.getA11yOverlayLayer(); 8656 } 8657 } 8658 return null; 8659 } 8660 8661 @Override captureDisplay(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs, ScreenCapture.ScreenCaptureListener listener)8662 public void captureDisplay(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs, 8663 ScreenCapture.ScreenCaptureListener listener) { 8664 WindowManagerService.this.captureDisplay(displayId, captureArgs, listener); 8665 } 8666 8667 @Override hasNavigationBar(int displayId)8668 public boolean hasNavigationBar(int displayId) { 8669 return WindowManagerService.this.hasNavigationBar(displayId); 8670 } 8671 8672 @Override setOrientationRequestPolicy(boolean respected, int[] fromOrientations, int[] toOrientations)8673 public void setOrientationRequestPolicy(boolean respected, 8674 int[] fromOrientations, int[] toOrientations) { 8675 synchronized (mGlobalLock) { 8676 WindowManagerService.this.setOrientationRequestPolicy(respected, 8677 fromOrientations, toOrientations); 8678 } 8679 } 8680 8681 @Override getTargetWindowTokenFromInputToken(IBinder inputToken)8682 public @Nullable IBinder getTargetWindowTokenFromInputToken(IBinder inputToken) { 8683 InputTarget inputTarget = WindowManagerService.this.getInputTargetFromToken(inputToken); 8684 return inputTarget == null ? null : inputTarget.getWindowToken(); 8685 } 8686 8687 @Override setBlockScreenCaptureForAppsSessionId(long sessionId)8688 public void setBlockScreenCaptureForAppsSessionId(long sessionId) { 8689 synchronized (mGlobalLock) { 8690 if (sensitiveContentMetricsBugfix() 8691 && mSensitiveContentProtectionSessionId != sessionId) { 8692 mSensitiveContentProtectionSessionId = sessionId; 8693 } 8694 } 8695 } 8696 8697 @Override addBlockScreenCaptureForApps(ArraySet<PackageInfo> packageInfos)8698 public void addBlockScreenCaptureForApps(ArraySet<PackageInfo> packageInfos) { 8699 synchronized (mGlobalLock) { 8700 boolean modified = 8701 mSensitiveContentPackages.addBlockScreenCaptureForApps(packageInfos); 8702 if (modified) { 8703 WindowManagerService.this.refreshScreenCaptureDisabled(); 8704 if (sensitiveContentImprovements()) { 8705 // TODO(b/331842561): Combine this traversal with the one inside 8706 // refreshScreenCaptureDisabled above. 8707 mRoot.forAllWindows((w) -> { 8708 if (w.isVisible()) { 8709 WindowManagerService.this.showToastIfBlockingScreenCapture(w); 8710 } else if (sensitiveContentRecentsScreenshotBugfix() 8711 && shouldInvalidateSnapshot(w)) { 8712 final Task task = w.getTask(); 8713 // preventing from showing up in starting window. 8714 mTaskSnapshotController.removeAndDeleteSnapshot( 8715 task.mTaskId, task.mUserId); 8716 // Refresh TaskThumbnailCache 8717 task.onSnapshotInvalidated(); 8718 } 8719 }, /* traverseTopToBottom= */ true); 8720 } 8721 } 8722 } 8723 } 8724 shouldInvalidateSnapshot(WindowState w)8725 private boolean shouldInvalidateSnapshot(WindowState w) { 8726 return w.getTask() != null 8727 && mSensitiveContentPackages.shouldBlockScreenCaptureForApp( 8728 w.getOwningPackage(), w.getOwningUid(), w.getWindowToken()); 8729 } 8730 8731 @Override removeBlockScreenCaptureForApps(ArraySet<PackageInfo> packageInfos)8732 public void removeBlockScreenCaptureForApps(ArraySet<PackageInfo> packageInfos) { 8733 synchronized (mGlobalLock) { 8734 boolean modified = 8735 mSensitiveContentPackages.removeBlockScreenCaptureForApps(packageInfos); 8736 if (modified) { 8737 WindowManagerService.this.refreshScreenCaptureDisabled(); 8738 } 8739 if (sensitiveContentImprovements()) { 8740 for (int i = 0; i < packageInfos.size(); i++) { 8741 int uid = packageInfos.valueAt(i).getUid(); 8742 if (mCaptureBlockedToastShownUids.contains(uid)) { 8743 mCaptureBlockedToastShownUids.remove( 8744 mCaptureBlockedToastShownUids.indexOf(uid)); 8745 } 8746 } 8747 } 8748 } 8749 } 8750 8751 @Override clearBlockedApps()8752 public void clearBlockedApps() { 8753 synchronized (mGlobalLock) { 8754 boolean modified = mSensitiveContentPackages.clearBlockedApps(); 8755 if (modified) { 8756 WindowManagerService.this.refreshScreenCaptureDisabled(); 8757 } 8758 if (sensitiveContentImprovements()) { 8759 mCaptureBlockedToastShownUids.clear(); 8760 } 8761 } 8762 } 8763 8764 @Override registerWindowFocusChangeListener(WindowFocusChangeListener listener)8765 public void registerWindowFocusChangeListener(WindowFocusChangeListener listener) { 8766 WindowManagerService.this.addWindowFocusChangeListener(listener); 8767 } 8768 8769 @Override unregisterWindowFocusChangeListener(WindowFocusChangeListener listener)8770 public void unregisterWindowFocusChangeListener(WindowFocusChangeListener listener) { 8771 WindowManagerService.this.removeWindowFocusChangeListener(listener); 8772 } 8773 8774 @Override registerOnWindowRemovedListener(OnWindowRemovedListener listener)8775 public void registerOnWindowRemovedListener(OnWindowRemovedListener listener) { 8776 synchronized (mGlobalLock) { 8777 mOnWindowRemovedListeners.add(listener); 8778 } 8779 } 8780 8781 @Override unregisterOnWindowRemovedListener(OnWindowRemovedListener listener)8782 public void unregisterOnWindowRemovedListener(OnWindowRemovedListener listener) { 8783 synchronized (mGlobalLock) { 8784 mOnWindowRemovedListeners.remove(listener); 8785 } 8786 } 8787 8788 @Override moveFocusToAdjacentEmbeddedActivityIfNeeded()8789 public boolean moveFocusToAdjacentEmbeddedActivityIfNeeded() { 8790 synchronized (mGlobalLock) { 8791 final WindowState focusedWindow = getFocusedWindow(); 8792 if (focusedWindow == null) { 8793 return false; 8794 } 8795 8796 if (moveFocusToAdjacentEmbeddedWindow(focusedWindow)) { 8797 // Sync the input transactions to ensure the input focus updates as well. 8798 syncInputTransactions(false); 8799 return true; 8800 } 8801 8802 return false; 8803 } 8804 } 8805 8806 @Override takeAssistScreenshot()8807 public ScreenshotHardwareBuffer takeAssistScreenshot() { 8808 // WMS.takeAssistScreenshot takes care of the locking. 8809 return WindowManagerService.this.takeAssistScreenshot(/* predicate */ null); 8810 } 8811 8812 @Override takeContextualSearchScreenshot(int uid)8813 public ScreenshotHardwareBuffer takeContextualSearchScreenshot(int uid) { 8814 // WMS.takeAssistScreenshot takes care of the locking. 8815 return WindowManagerService.this.takeAssistScreenshot(win -> { 8816 switch (win.getWindowType()) { 8817 case LayoutParams.TYPE_STATUS_BAR: 8818 case LayoutParams.TYPE_NAVIGATION_BAR: 8819 case LayoutParams.TYPE_NAVIGATION_BAR_PANEL: 8820 case LayoutParams.TYPE_POINTER: 8821 return false; 8822 case LayoutParams.TYPE_APPLICATION_OVERLAY: 8823 return uid != win.getOwningUid(); 8824 default: 8825 return true; 8826 } 8827 }); 8828 } 8829 } 8830 8831 private final class ImeTargetVisibilityPolicyImpl extends ImeTargetVisibilityPolicy { 8832 8833 @Override 8834 public boolean showImeScreenshot(@NonNull IBinder imeTarget, int displayId) { 8835 synchronized (mGlobalLock) { 8836 final WindowState imeTargetWindow = mWindowMap.get(imeTarget); 8837 if (imeTargetWindow == null) { 8838 return false; 8839 } 8840 final DisplayContent dc = mRoot.getDisplayContent(displayId); 8841 if (dc == null) { 8842 Slog.w(TAG, "Invalid displayId:" + displayId + ", fail to show ime screenshot"); 8843 return false; 8844 } 8845 8846 dc.showImeScreenshot(imeTargetWindow); 8847 return true; 8848 } 8849 } 8850 @Override 8851 public boolean removeImeScreenshot(int displayId) { 8852 synchronized (mGlobalLock) { 8853 final DisplayContent dc = mRoot.getDisplayContent(displayId); 8854 if (dc == null) { 8855 Slog.w(TAG, "Invalid displayId:" + displayId 8856 + ", fail to remove ime screenshot"); 8857 return false; 8858 } 8859 dc.removeImeSurfaceImmediately(); 8860 } 8861 return true; 8862 } 8863 } 8864 8865 /** Called to inform window manager if non-Vr UI shoul be disabled or not. */ 8866 public void disableNonVrUi(boolean disable) { 8867 synchronized (mGlobalLock) { 8868 // Allow alert window notifications to be shown if non-vr UI is enabled. 8869 final boolean showAlertWindowNotifications = !disable; 8870 if (showAlertWindowNotifications == mShowAlertWindowNotifications) { 8871 return; 8872 } 8873 mShowAlertWindowNotifications = showAlertWindowNotifications; 8874 8875 for (int i = mSessions.size() - 1; i >= 0; --i) { 8876 final Session s = mSessions.valueAt(i); 8877 s.setShowingAlertWindowNotificationAllowed(mShowAlertWindowNotifications); 8878 } 8879 } 8880 } 8881 8882 boolean hasWideColorGamutSupport() { 8883 return mHasWideColorGamutSupport && 8884 SystemProperties.getInt("persist.sys.sf.native_mode", 0) != 1; 8885 } 8886 8887 boolean hasHdrSupport() { 8888 return mHasHdrSupport && hasWideColorGamutSupport(); 8889 } 8890 8891 void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) { 8892 final boolean effective = (surfaceShown && win.hideNonSystemOverlayWindowsWhenVisible()); 8893 if (effective == mHidingNonSystemOverlayWindows.contains(win)) { 8894 return; 8895 } 8896 8897 if (effective) { 8898 mHidingNonSystemOverlayWindows.add(win); 8899 } else { 8900 mHidingNonSystemOverlayWindows.remove(win); 8901 } 8902 8903 final boolean changed; 8904 if (Flags.fixHideOverlayApi()) { 8905 final int uid = win.getOwningUid(); 8906 final int numUIDsPreUpdate = mHidingNonSystemOverlayWindowsCountPerUid.size(); 8907 final int newCount = mHidingNonSystemOverlayWindowsCountPerUid.getOrDefault(uid, 0) 8908 + (effective ? +1 : -1); 8909 if (newCount <= 0) { 8910 mHidingNonSystemOverlayWindowsCountPerUid.remove(uid); 8911 } else { 8912 mHidingNonSystemOverlayWindowsCountPerUid.put(uid, newCount); 8913 } 8914 final int numUIDsPostUpdate = mHidingNonSystemOverlayWindowsCountPerUid.size(); 8915 // The visibility of SAWs needs to be refreshed when the number of uids that 8916 // request hiding SAWs changes between "0", "1", or "2+". 8917 changed = (numUIDsPostUpdate != numUIDsPreUpdate) 8918 && (numUIDsPostUpdate <= 1 || numUIDsPreUpdate <= 1); 8919 } else { 8920 // The visibility of SAWs needs to be refreshed when the number of windows that 8921 // request hiding SAWs changes between "0" or "1+". 8922 changed = (effective && mHidingNonSystemOverlayWindows.size() == 1) 8923 || (!effective && mHidingNonSystemOverlayWindows.isEmpty()); 8924 } 8925 8926 if (changed) { 8927 mRoot.forAllWindows((w) -> { 8928 w.setForceHideNonSystemOverlayWindowIfNeeded(shouldHideNonSystemOverlayWindow(w)); 8929 }, false /* traverseTopToBottom */); 8930 } 8931 } 8932 8933 /** Called from Accessibility Controller to apply magnification spec */ 8934 public void applyMagnificationSpecLocked(int displayId, MagnificationSpec spec) { 8935 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 8936 if (displayContent != null) { 8937 displayContent.applyMagnificationSpec(spec); 8938 } 8939 } 8940 8941 SurfaceControl.Builder makeSurfaceBuilder() { 8942 return mSurfaceControlFactory.get(); 8943 } 8944 8945 @Override 8946 public void syncInputTransactions(boolean waitForAnimations) { 8947 final long token = Binder.clearCallingIdentity(); 8948 try { 8949 if (waitForAnimations) { 8950 waitForAnimationsToComplete(); 8951 } 8952 8953 // Collect all input transactions from all displays to make sure we could sync all input 8954 // windows at same time. 8955 final SurfaceControl.Transaction t = mTransactionFactory.get(); 8956 synchronized (mGlobalLock) { 8957 mWindowPlacerLocked.performSurfacePlacementIfScheduled(); 8958 mRoot.forAllDisplays(displayContent -> 8959 displayContent.getInputMonitor().updateInputWindowsImmediately(t)); 8960 } 8961 8962 CountDownLatch countDownLatch = new CountDownLatch(1); 8963 t.addWindowInfosReportedListener(countDownLatch::countDown).apply(); 8964 countDownLatch.await(SYNC_INPUT_TRANSACTIONS_TIMEOUT_MS, TimeUnit.MILLISECONDS); 8965 } catch (InterruptedException exception) { 8966 Slog.e(TAG_WM, "Exception thrown while waiting for window infos to be reported", 8967 exception); 8968 } finally { 8969 Binder.restoreCallingIdentity(token); 8970 } 8971 } 8972 8973 /** 8974 * Wait until all container animations and surface operations behalf of WindowManagerService 8975 * complete. 8976 */ 8977 private void waitForAnimationsToComplete() { 8978 synchronized (mGlobalLock) { 8979 long timeoutRemaining = ANIMATION_COMPLETED_TIMEOUT_MS; 8980 // This could prevent if there is no container animation, we still have to apply the 8981 // pending transaction and exit waiting. 8982 mAnimator.mNotifyWhenNoAnimation = true; 8983 boolean animateStarting = false; 8984 while (timeoutRemaining > 0) { 8985 // Waiting until all starting windows has finished animating. 8986 animateStarting = !mAtmService.getTransitionController().isShellTransitionsEnabled() 8987 && mRoot.forAllActivities(ActivityRecord::hasStartingWindow); 8988 boolean isAnimating = mAnimator.isAnimationScheduled() 8989 || mRoot.isAnimating(TRANSITION | CHILDREN, ANIMATION_TYPE_ALL) 8990 || animateStarting; 8991 if (!isAnimating) { 8992 // isAnimating is a legacy transition query and will be removed, so also add 8993 // a check for whether this is in a shell-transition when not using legacy. 8994 if (!mAtmService.getTransitionController().inTransition()) { 8995 break; 8996 } 8997 } 8998 long startTime = System.currentTimeMillis(); 8999 try { 9000 mGlobalLock.wait(timeoutRemaining); 9001 } catch (InterruptedException e) { 9002 } 9003 timeoutRemaining -= (System.currentTimeMillis() - startTime); 9004 } 9005 mAnimator.mNotifyWhenNoAnimation = false; 9006 9007 WindowContainer animatingContainer; 9008 animatingContainer = mRoot.getAnimatingContainer(TRANSITION | CHILDREN, 9009 ANIMATION_TYPE_ALL); 9010 if (mAnimator.isAnimationScheduled() || animatingContainer != null || animateStarting) { 9011 Slog.w(TAG, "Timed out waiting for animations to complete," 9012 + " animatingContainer=" + animatingContainer 9013 + " animationType=" + SurfaceAnimator.animationTypeToString( 9014 animatingContainer != null 9015 ? animatingContainer.mSurfaceAnimator.getAnimationType() 9016 : SurfaceAnimator.ANIMATION_TYPE_NONE) 9017 + " animateStarting=" + animateStarting); 9018 } 9019 } 9020 } 9021 9022 void onAnimationFinished() { 9023 synchronized (mGlobalLock) { 9024 mGlobalLock.notifyAll(); 9025 } 9026 } 9027 9028 void clearPointerDownOutsideFocusRunnable() { 9029 if (mPointerDownOutsideFocusRunnable == null) return; 9030 9031 mH.removeCallbacks(mPointerDownOutsideFocusRunnable); 9032 mPointerDownOutsideFocusRunnable = null; 9033 } 9034 9035 private void onPointerDownOutsideFocusLocked(InputTarget t, boolean fromHandler) { 9036 if (t == null || !t.receiveFocusFromTapOutside()) { 9037 // If the window that received the input event cannot receive keys, don't move the 9038 // display it's on to the top since that window won't be able to get focus anyway. 9039 return; 9040 } 9041 9042 final ActivityRecord touchedApp = t.getActivityRecord(); 9043 if (touchedApp != null && touchedApp.getTask() != null) { 9044 final ActivityRecord top = touchedApp.getTask().topRunningActivity(); 9045 if (top != null && top != touchedApp && top.getTaskFragment().getBounds().contains( 9046 touchedApp.getTaskFragment().getBounds())) { 9047 // This is a special case where the pointer-down-outside focus on an Activity that's 9048 // entirely occluded by the task top running activity, this is possible if the 9049 // pointer-down-outside-focus event is delayed (after new activity started on top). 9050 // In that case, drop the event to prevent changing focus to a background activity. 9051 Slog.w(TAG, "onPointerDownOutsideFocusLocked, drop event because " + touchedApp 9052 + " is occluded and should not be focused."); 9053 return; 9054 } 9055 } 9056 9057 if (mDeviceStateCallback.isInRearDisplayOuterDefaultState()) { 9058 final Display[] rearDisplays = mDisplayManager 9059 .getDisplays(DisplayManager.DISPLAY_CATEGORY_REAR); 9060 if (rearDisplays.length > 0 && rearDisplays[0].getDisplayId() == t.getDisplayId()) { 9061 // Do not change display focus to the inner display if we're in this mode. Note that 9062 // in this mode, the inner display is configured as a rear display. 9063 Slog.w(TAG, "Ignoring focus change because device is in RDM."); 9064 return; 9065 } 9066 } 9067 9068 clearPointerDownOutsideFocusRunnable(); 9069 9070 final InputTarget focusedInputTarget = mFocusedInputTarget; 9071 if (shouldDelayTouchOutside(t)) { 9072 mPointerDownOutsideFocusRunnable = 9073 () -> handlePointerDownOutsideFocus(t, focusedInputTarget); 9074 mH.postDelayed(mPointerDownOutsideFocusRunnable, POINTER_DOWN_OUTSIDE_FOCUS_TIMEOUT_MS); 9075 } else if (!fromHandler) { 9076 // Still post the runnable to handler thread in case there is already a runnable 9077 // in execution, but still waiting to hold the wm lock. 9078 mPointerDownOutsideFocusRunnable = 9079 () -> handlePointerDownOutsideFocus(t, focusedInputTarget); 9080 mH.post(mPointerDownOutsideFocusRunnable); 9081 } else { 9082 handlePointerDownOutsideFocus(t, focusedInputTarget); 9083 } 9084 } 9085 9086 private boolean shouldDelayTouchOutside(InputTarget t) { 9087 final ActivityRecord activity = t.getActivityRecord(); 9088 final Task task = activity != null ? activity.getTask() : null; 9089 9090 final boolean isInputTargetNotFocused = 9091 mFocusedInputTarget != t && mFocusedInputTarget != null; 9092 final boolean isTouchOnFocusedDisplay = mFocusedInputTarget != null 9093 && t.getDisplayId() == mFocusedInputTarget.getDisplayId(); 9094 if (!(isInputTargetNotFocused && isTouchOnFocusedDisplay)) { 9095 return false; 9096 } 9097 9098 // For embedded activity that is showing side-by-side with another activity, delay 9099 // handling the touch-outside event to prevent focus rapid changes back-n-forth. 9100 final boolean shouldDelayTouchForEmbeddedActivity = activity != null 9101 && activity.isEmbedded() 9102 && activity.getTaskFragment().hasAdjacentTaskFragment(); 9103 9104 // For cases when there are multiple freeform windows where non-top windows are blocking 9105 // the gesture zones, delay handling the touch-outside event to prevent refocusing the 9106 // the non-top windows during the gesture. 9107 final boolean shouldDelayTouchForFreeform = 9108 task != null && task.getWindowingMode() == WINDOWING_MODE_FREEFORM; 9109 9110 // If non of the above cases are true, handle the touch-outside event directly. 9111 return shouldDelayTouchForEmbeddedActivity || shouldDelayTouchForFreeform; 9112 } 9113 9114 private void handlePointerDownOutsideFocus(InputTarget t, InputTarget focusedInputTarget) { 9115 synchronized (mGlobalLock) { 9116 final WindowState w = t.getWindowState(); 9117 // Skip if the mFocusedInputTarget is already changed or the touched Activity is no 9118 // longer visible. This is possible if the pointer-down-outside-focus event is 9119 // delayed to be handled. 9120 if (mFocusedInputTarget != focusedInputTarget || (w != null 9121 && w.getActivityRecord() != null 9122 && !w.getActivityRecord().isVisibleRequested())) { 9123 ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, 9124 "Skip onPointerDownOutsideFocusLocked due to input target changed %s", t); 9125 return; 9126 } 9127 if (mPointerDownOutsideFocusRunnable != null 9128 && mH.hasCallbacks(mPointerDownOutsideFocusRunnable)) { 9129 // Skip if there's another pending pointer-down-outside-focus event. 9130 return; 9131 } 9132 clearPointerDownOutsideFocusRunnable(); 9133 9134 if (w != null) { 9135 final Task task = w.getTask(); 9136 if (task != null && w.mTransitionController.isTransientHide(task)) { 9137 // Don't disturb transient animation by accident touch. 9138 return; 9139 } 9140 } 9141 9142 ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s", t); 9143 if (mFocusedInputTarget != t && mFocusedInputTarget != null) { 9144 mFocusedInputTarget.handleTapOutsideFocusOutsideSelf(); 9145 } 9146 // Trigger Activity#onUserLeaveHint() if the order change of task pauses any activities. 9147 mAtmService.mTaskSupervisor.mUserLeaving = true; 9148 t.handleTapOutsideFocusInsideSelf(); 9149 mAtmService.mTaskSupervisor.mUserLeaving = false; 9150 } 9151 } 9152 9153 @VisibleForTesting 9154 void handleTaskFocusChange(Task task, ActivityRecord touchedActivity) { 9155 if (task == null) { 9156 return; 9157 } 9158 9159 // We ignore root home task since we don't want root home task to move to front when 9160 // touched. Specifically, in freeform we don't want tapping on home to cause the freeform 9161 // apps to go behind home. See b/117376413 9162 if (task.isActivityTypeHome()) { 9163 // Only ignore root home task if the requested focus home Task is in the same 9164 // TaskDisplayArea as the current focus Task. 9165 TaskDisplayArea homeTda = task.getDisplayArea(); 9166 WindowState curFocusedWindow = getFocusedWindow(); 9167 if (curFocusedWindow != null && homeTda != null 9168 && curFocusedWindow.isDescendantOf(homeTda)) { 9169 return; 9170 } 9171 } 9172 9173 mAtmService.setFocusedTask(task.mTaskId, touchedActivity); 9174 } 9175 9176 @VisibleForTesting 9177 static class WindowContainerInfo { 9178 private final int mUid; 9179 @NonNull private final WindowContainerToken mToken; 9180 9181 private WindowContainerInfo(int uid, @NonNull WindowContainerToken token) { 9182 this.mUid = uid; 9183 this.mToken = token; 9184 } 9185 9186 public int getUid() { 9187 return mUid; 9188 } 9189 9190 @NonNull 9191 public WindowContainerToken getToken() { 9192 return mToken; 9193 } 9194 } 9195 9196 /** 9197 * Retrieve the {@link WindowContainerInfo} of the task that was launched for MediaProjection. 9198 * 9199 * @param session the {@link ContentRecordingSession} containing the launch cookie and/or 9200 * task id of the Task started for capture. 9201 * @return a token representing the task containing the activity started with the given launch 9202 * cookie, or {@code null} if the token couldn't be found. 9203 */ 9204 @VisibleForTesting 9205 @Nullable 9206 WindowContainerInfo getTaskWindowContainerInfoForRecordingSession( 9207 @NonNull ContentRecordingSession session) { 9208 WindowContainerToken taskWindowContainerToken = null; 9209 ActivityRecord targetActivity = null; 9210 Task targetTask = null; 9211 9212 // First attempt to find the launched task by looking for the launched activity with the 9213 // matching launch cookie. 9214 if (session.getTokenToRecord() != null) { 9215 IBinder launchCookie = session.getTokenToRecord(); 9216 targetActivity = mRoot.getActivity(activity -> activity.mLaunchCookie == launchCookie); 9217 if (targetActivity == null) { 9218 Slog.w(TAG, "Unable to find the activity for this launch cookie"); 9219 } else { 9220 if (targetActivity.getTask() == null) { 9221 Slog.w(TAG, "Unable to find the task for this launch cookie"); 9222 } else { 9223 targetTask = targetActivity.getTask(); 9224 taskWindowContainerToken = targetTask.mRemoteToken.toWindowContainerToken(); 9225 } 9226 } 9227 } 9228 9229 // In the case we can't find an activity with a matching launch cookie, it could be due to 9230 // the launched activity being closed, but the launched task is still open, so now attempt 9231 // to look for the task directly. 9232 if (taskWindowContainerToken == null && session.getTaskId() != -1) { 9233 int targetTaskId = session.getTaskId(); 9234 targetTask = mRoot.getTask(task -> task.isTaskId(targetTaskId)); 9235 if (targetTask == null) { 9236 Slog.w(TAG, "Unable to find the task for this projection"); 9237 } else { 9238 taskWindowContainerToken = targetTask.mRemoteToken.toWindowContainerToken(); 9239 } 9240 } 9241 9242 // If we were unable to find the launched task in either fashion, then something must have 9243 // wrong (i.e. the task was closed before capture started). 9244 if (taskWindowContainerToken == null) { 9245 Slog.w(TAG, "Unable to find the WindowContainerToken for ContentRecordingSession"); 9246 return null; 9247 } 9248 return new WindowContainerInfo(targetTask.effectiveUid, taskWindowContainerToken); 9249 } 9250 9251 /** 9252 * You need ALLOW_SLIPPERY_TOUCHES permission to be able to set FLAG_SLIPPERY. 9253 */ 9254 private int sanitizeFlagSlippery(int flags, String windowName, int callingUid, int callingPid) { 9255 if ((flags & FLAG_SLIPPERY) == 0) { 9256 return flags; 9257 } 9258 final int permissionResult = mContext.checkPermission( 9259 android.Manifest.permission.ALLOW_SLIPPERY_TOUCHES, callingPid, callingUid); 9260 if (permissionResult != PackageManager.PERMISSION_GRANTED) { 9261 Slog.w(TAG, "Removing FLAG_SLIPPERY from '" + windowName 9262 + "' because it doesn't have ALLOW_SLIPPERY_TOUCHES permission"); 9263 return flags & ~FLAG_SLIPPERY; 9264 } 9265 return flags; 9266 } 9267 9268 /** 9269 * Ensure the caller has the right permissions to be able to set the requested input features. 9270 */ 9271 private int sanitizeInputFeatures(int inputFeatures, String windowName, int callingUid, 9272 int callingPid, boolean isTrustedOverlay) { 9273 // You need MONITOR_INPUT permission to be able to set INPUT_FEATURE_SPY. 9274 if ((inputFeatures & INPUT_FEATURE_SPY) != 0) { 9275 final int permissionResult = mContext.checkPermission( 9276 permission.MONITOR_INPUT, callingPid, callingUid); 9277 if (permissionResult != PackageManager.PERMISSION_GRANTED) { 9278 throw new IllegalArgumentException( 9279 "Cannot use INPUT_FEATURE_SPY from '" + windowName 9280 + "' because it doesn't the have MONITOR_INPUT permission"); 9281 } 9282 } 9283 9284 // You can only use INPUT_FEATURE_SENSITIVE_FOR_PRIVACY on a trusted overlay. 9285 if ((inputFeatures & INPUT_FEATURE_SENSITIVE_FOR_PRIVACY) != 0 && !isTrustedOverlay) { 9286 Slog.w(TAG, "Removing INPUT_FEATURE_SENSITIVE_FOR_PRIVACY from '" + windowName 9287 + "' because it isn't a trusted overlay"); 9288 return inputFeatures & ~INPUT_FEATURE_SENSITIVE_FOR_PRIVACY; 9289 } 9290 return inputFeatures; 9291 } 9292 9293 /** 9294 * Assigns an InputChannel to a SurfaceControl and configures it to receive 9295 * touch input according to it's on-screen geometry. 9296 * 9297 * Used by WindowlessWindowManager to enable input on SurfaceControl embedded 9298 * views. 9299 */ 9300 void grantInputChannel(Session session, int callingUid, int callingPid, int displayId, 9301 SurfaceControl surface, IBinder clientToken, 9302 @Nullable InputTransferToken hostInputTransferToken, int flags, int privateFlags, 9303 int inputFeatures, int type, IBinder windowToken, InputTransferToken inputTransferToken, 9304 String inputHandleName, InputChannel outInputChannel) { 9305 final int sanitizedType = sanitizeWindowType(session, displayId, windowToken, type); 9306 final InputApplicationHandle applicationHandle; 9307 final String name; 9308 Objects.requireNonNull(outInputChannel); 9309 Objects.requireNonNull(inputTransferToken); 9310 9311 synchronized (mGlobalLock) { 9312 WindowState hostWindowState = hostInputTransferToken != null 9313 ? mInputToWindowMap.get(hostInputTransferToken.getToken()) : null; 9314 EmbeddedWindowController.EmbeddedWindow win = 9315 new EmbeddedWindowController.EmbeddedWindow(session, this, clientToken, 9316 hostWindowState, callingUid, callingPid, sanitizedType, displayId, 9317 inputTransferToken, inputHandleName, (flags & FLAG_NOT_FOCUSABLE) == 0); 9318 win.openInputChannel(outInputChannel); 9319 mEmbeddedWindowController.add(outInputChannel.getToken(), win); 9320 applicationHandle = win.getApplicationHandle(); 9321 name = win.toString(); 9322 } 9323 9324 updateInputChannel(outInputChannel.getToken(), callingUid, callingPid, displayId, surface, 9325 name, applicationHandle, flags, privateFlags, inputFeatures, sanitizedType, 9326 null /* region */, clientToken); 9327 } 9328 9329 @Override 9330 public boolean transferTouchGesture(@NonNull InputTransferToken transferFromToken, 9331 @NonNull InputTransferToken transferToToken) { 9332 Objects.requireNonNull(transferFromToken); 9333 Objects.requireNonNull(transferToToken); 9334 9335 final int callingUid = Binder.getCallingUid(); 9336 final long identity = Binder.clearCallingIdentity(); 9337 boolean didTransfer; 9338 try { 9339 synchronized (mGlobalLock) { 9340 // If the transferToToken exists in the input to window map, it means the request 9341 // is to transfer from embedded to host. Otherwise, the transferToToken 9342 // represents an embedded window so transfer from host to embedded. 9343 WindowState windowStateTo = mInputToWindowMap.get(transferToToken.getToken()); 9344 if (windowStateTo != null) { 9345 didTransfer = mEmbeddedWindowController.transferToHost(callingUid, 9346 transferFromToken, 9347 windowStateTo); 9348 } else { 9349 WindowState windowStateFrom = mInputToWindowMap.get( 9350 transferFromToken.getToken()); 9351 didTransfer = mEmbeddedWindowController.transferToEmbedded(callingUid, 9352 windowStateFrom, 9353 transferToToken); 9354 } 9355 } 9356 } finally { 9357 Binder.restoreCallingIdentity(identity); 9358 } 9359 return didTransfer; 9360 } 9361 9362 private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid, 9363 int displayId, SurfaceControl surface, String name, 9364 InputApplicationHandle applicationHandle, int flags, 9365 int privateFlags, int inputFeatures, int type, Region region, IBinder clientToken) { 9366 final InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId); 9367 h.token = channelToken; 9368 h.setWindowToken(clientToken); 9369 h.name = name; 9370 9371 final boolean isTrustedOverlay = (privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0; 9372 flags = sanitizeFlagSlippery(flags, name, callingUid, callingPid); 9373 inputFeatures = sanitizeInputFeatures(inputFeatures, name, callingUid, callingPid, 9374 isTrustedOverlay); 9375 9376 final int sanitizedLpFlags = 9377 (flags & (FLAG_NOT_TOUCHABLE | FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE 9378 | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH)) 9379 | LayoutParams.FLAG_NOT_TOUCH_MODAL; 9380 h.layoutParamsType = type; 9381 h.layoutParamsFlags = sanitizedLpFlags; 9382 9383 // Do not allow any input features to be set without sanitizing them first. 9384 h.inputConfig = InputConfigAdapter.getInputConfigFromWindowParams( 9385 type, sanitizedLpFlags, inputFeatures); 9386 9387 9388 if ((flags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0) { 9389 h.inputConfig |= InputConfig.NOT_FOCUSABLE; 9390 } 9391 9392 h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 9393 h.ownerUid = callingUid; 9394 h.ownerPid = callingPid; 9395 9396 if (region == null) { 9397 h.replaceTouchableRegionWithCrop(null); 9398 } else { 9399 h.touchableRegion.set(region); 9400 h.replaceTouchableRegionWithCrop = false; 9401 9402 // Task managers may need to receive input events around task layers to resize tasks. 9403 final int permissionResult = mContext.checkPermission( 9404 permission.MANAGE_ACTIVITY_TASKS, callingPid, callingUid); 9405 if (permissionResult != PackageManager.PERMISSION_GRANTED) { 9406 h.setTouchableRegionCrop(surface); 9407 } 9408 } 9409 9410 final SurfaceControl.Transaction t = mTransactionFactory.get(); 9411 // Check private trusted overlay flag to set trustedOverlay field of input window handle. 9412 h.setTrustedOverlay(t, surface, isTrustedOverlay); 9413 t.setInputWindowInfo(surface, h); 9414 t.apply(); 9415 t.close(); 9416 surface.release(); 9417 } 9418 9419 /** 9420 * Updates the flags on an existing surface's input channel. This assumes the surface provided 9421 * is the one associated with the provided input-channel. If this isn't the case, behavior 9422 * is undefined. 9423 */ 9424 void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface, 9425 int flags, int privateFlags, int inputFeatures, Region region) { 9426 final InputApplicationHandle applicationHandle; 9427 final String name; 9428 final EmbeddedWindowController.EmbeddedWindow win; 9429 synchronized (mGlobalLock) { 9430 win = mEmbeddedWindowController.get(channelToken); 9431 if (win == null) { 9432 Slog.e(TAG, "Couldn't find window for provided channelToken."); 9433 return; 9434 } 9435 name = win.toString(); 9436 applicationHandle = win.getApplicationHandle(); 9437 win.setIsFocusable((flags & FLAG_NOT_FOCUSABLE) == 0); 9438 } 9439 9440 updateInputChannel(channelToken, win.mOwnerUid, win.mOwnerPid, displayId, surface, name, 9441 applicationHandle, flags, privateFlags, inputFeatures, win.mWindowType, region, 9442 win.mClient); 9443 } 9444 9445 /** 9446 * Returns the Activity that has the most recently created window in the adjacent activities 9447 * if any. 9448 */ 9449 @NonNull 9450 ActivityRecord getMostRecentActivityInAdjacent(@NonNull ActivityRecord focusedActivity) { 9451 final TaskFragment taskFragment = focusedActivity.getTaskFragment(); 9452 if (taskFragment == null) { 9453 // Return if activity no attached. 9454 return focusedActivity; 9455 } 9456 9457 if (!focusedActivity.isEmbedded()) { 9458 // Return if the focused activity is not embedded. 9459 return focusedActivity; 9460 } 9461 9462 if (!taskFragment.hasAdjacentTaskFragment()) { 9463 return focusedActivity; 9464 } 9465 9466 // Find the adjacent activity with more recently active window. 9467 final ActivityRecord[] mostRecentActiveActivity = { focusedActivity }; 9468 final long[] mostRecentActiveTime = { focusedActivity.getLastWindowCreateTime() }; 9469 taskFragment.forOtherAdjacentTaskFragments(adjacentTaskFragment -> { 9470 final ActivityRecord adjacentTopActivity = adjacentTaskFragment.topRunningActivity(); 9471 if (adjacentTopActivity != null) { 9472 final long lastWindowCreateTime = adjacentTopActivity.getLastWindowCreateTime(); 9473 if (lastWindowCreateTime > mostRecentActiveTime[0]) { 9474 mostRecentActiveTime[0] = lastWindowCreateTime; 9475 mostRecentActiveActivity[0] = adjacentTopActivity; 9476 } 9477 } 9478 }); 9479 return mostRecentActiveActivity[0]; 9480 } 9481 9482 @NonNull 9483 WindowState getMostRecentUsedEmbeddedWindowForBack(@NonNull WindowState focusedWindow) { 9484 final ActivityRecord focusedActivity = focusedWindow.getActivityRecord(); 9485 if (focusedActivity == null) { 9486 // Not an Activity. 9487 return focusedWindow; 9488 } 9489 9490 final ActivityRecord mostRecentActivityInAdjacent = getMostRecentActivityInAdjacent( 9491 focusedActivity); 9492 if (mostRecentActivityInAdjacent == focusedActivity) { 9493 // Already be the most recent window. 9494 return focusedWindow; 9495 } 9496 9497 // Looks for a candidate focused window on the adjacent Activity for the back event. 9498 final WindowState candidate = 9499 mostRecentActivityInAdjacent.getDisplayContent().findFocusedWindow( 9500 mostRecentActivityInAdjacent); 9501 return candidate != null ? candidate : focusedWindow; 9502 } 9503 9504 /** 9505 * Move focus to the adjacent embedded activity if the adjacent activity is more recently 9506 * created or has a window more recently added. 9507 * <p> 9508 * Returns {@code true} if the focused window is changed. Otherwise, returns {@code false}. 9509 */ 9510 boolean moveFocusToAdjacentEmbeddedWindow(@NonNull WindowState focusedWindow) { 9511 final ActivityRecord activity = focusedWindow.getActivityRecord(); 9512 if (activity == null) { 9513 return false; 9514 } 9515 9516 final ActivityRecord mostRecentActivityInAdjacent = getMostRecentActivityInAdjacent( 9517 activity); 9518 9519 moveFocusToActivity(mostRecentActivityInAdjacent); 9520 return !focusedWindow.isFocused(); 9521 } 9522 9523 boolean moveFocusToAdjacentWindow(@NonNull WindowState fromWin, @FocusDirection int direction) { 9524 if (!fromWin.isFocused()) { 9525 return false; 9526 } 9527 final TaskFragment fromFragment = fromWin.getTaskFragment(); 9528 if (fromFragment == null || fromFragment.asTask() != null) { 9529 // Don't move the focus to another task. 9530 return false; 9531 } 9532 if (!fromFragment.hasAdjacentTaskFragment()) { 9533 // No adjacent window. 9534 return false; 9535 } 9536 if (fromFragment.getAdjacentTaskFragments().size() > 2) { 9537 throw new IllegalStateException("Not yet support 3+ adjacent for non-Task TFs"); 9538 } 9539 final TaskFragment[] tmpAdjacent = new TaskFragment[1]; 9540 fromFragment.forOtherAdjacentTaskFragments(adjacentTF -> { 9541 tmpAdjacent[0] = adjacentTF; 9542 return true; 9543 }); 9544 final TaskFragment adjacentFragment = tmpAdjacent[0]; 9545 if (adjacentFragment.isIsolatedNav()) { 9546 // Don't move the focus if the adjacent TF is isolated navigation. 9547 return false; 9548 } 9549 final Rect fromBounds = fromFragment.getBounds(); 9550 final Rect adjacentBounds = adjacentFragment.getBounds(); 9551 switch (direction) { 9552 case View.FOCUS_LEFT: 9553 if (adjacentBounds.left >= fromBounds.left) { 9554 return false; 9555 } 9556 break; 9557 case View.FOCUS_UP: 9558 if (adjacentBounds.top >= fromBounds.top) { 9559 return false; 9560 } 9561 break; 9562 case View.FOCUS_RIGHT: 9563 if (adjacentBounds.right <= fromBounds.right) { 9564 return false; 9565 } 9566 break; 9567 case View.FOCUS_DOWN: 9568 if (adjacentBounds.bottom <= fromBounds.bottom) { 9569 return false; 9570 } 9571 break; 9572 case View.FOCUS_BACKWARD: 9573 case View.FOCUS_FORWARD: 9574 // These are not absolute directions. Skip checking the bounds. 9575 break; 9576 default: 9577 return false; 9578 } 9579 final ActivityRecord topRunningActivity = adjacentFragment.topRunningActivity( 9580 true /* focusableOnly */); 9581 if (topRunningActivity == null) { 9582 return false; 9583 } 9584 moveFocusToActivity(topRunningActivity); 9585 return !fromWin.isFocused(); 9586 } 9587 9588 @VisibleForTesting 9589 void moveFocusToActivity(@NonNull ActivityRecord activity) { 9590 moveDisplayToTopInternal(activity.getDisplayId()); 9591 handleTaskFocusChange(activity.getTask(), activity); 9592 } 9593 9594 /** Return whether layer tracing is enabled */ 9595 public boolean isLayerTracing() { 9596 if (!checkCallingPermission( 9597 android.Manifest.permission.DUMP, "isLayerTracing()")) { 9598 throw new SecurityException("Requires DUMP permission"); 9599 } 9600 9601 final long token = Binder.clearCallingIdentity(); 9602 try { 9603 Parcel data = null; 9604 Parcel reply = null; 9605 try { 9606 IBinder sf = ServiceManager.getService("SurfaceFlinger"); 9607 if (sf != null) { 9608 reply = Parcel.obtain(); 9609 data = Parcel.obtain(); 9610 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 9611 sf.transact(/* LAYER_TRACE_STATUS_CODE */ 1026, data, reply, 0 /* flags */); 9612 return reply.readBoolean(); 9613 } 9614 } catch (RemoteException e) { 9615 Slog.e(TAG, "Failed to get layer tracing"); 9616 } finally { 9617 if (data != null) { 9618 data.recycle(); 9619 } 9620 if (reply != null) { 9621 reply.recycle(); 9622 } 9623 } 9624 } finally { 9625 Binder.restoreCallingIdentity(token); 9626 } 9627 return false; 9628 } 9629 9630 /** Enable or disable layer tracing */ 9631 public void setLayerTracing(boolean enabled) { 9632 if (!checkCallingPermission( 9633 android.Manifest.permission.DUMP, "setLayerTracing()")) { 9634 throw new SecurityException("Requires DUMP permission"); 9635 } 9636 9637 final long token = Binder.clearCallingIdentity(); 9638 try { 9639 Parcel data = null; 9640 try { 9641 IBinder sf = ServiceManager.getService("SurfaceFlinger"); 9642 if (sf != null) { 9643 data = Parcel.obtain(); 9644 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 9645 data.writeInt(enabled ? 1 : 0); 9646 sf.transact(/* LAYER_TRACE_CONTROL_CODE */ 1025, data, null, 0 /* flags */); 9647 } 9648 } catch (RemoteException e) { 9649 Slog.e(TAG, "Failed to set layer tracing"); 9650 } finally { 9651 if (data != null) { 9652 data.recycle(); 9653 } 9654 } 9655 } finally { 9656 Binder.restoreCallingIdentity(token); 9657 } 9658 } 9659 9660 /** Set layer tracing flags. */ 9661 public void setLayerTracingFlags(int flags) { 9662 if (!checkCallingPermission( 9663 android.Manifest.permission.DUMP, "setLayerTracingFlags")) { 9664 throw new SecurityException("Requires DUMP permission"); 9665 } 9666 9667 final long token = Binder.clearCallingIdentity(); 9668 try { 9669 Parcel data = null; 9670 try { 9671 IBinder sf = ServiceManager.getService("SurfaceFlinger"); 9672 if (sf != null) { 9673 data = Parcel.obtain(); 9674 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 9675 data.writeInt(flags); 9676 sf.transact(1033 /* LAYER_TRACE_FLAGS_CODE */, data, null, 0 /* flags */); 9677 } 9678 } catch (RemoteException e) { 9679 Slog.e(TAG, "Failed to set layer tracing flags"); 9680 } finally { 9681 if (data != null) { 9682 data.recycle(); 9683 } 9684 } 9685 } finally { 9686 Binder.restoreCallingIdentity(token); 9687 } 9688 } 9689 9690 /** 9691 * Toggle active transaction tracing. 9692 * Setting to true increases the buffer size for active debugging. 9693 * Setting to false resets the buffer size and dumps the trace to file. 9694 */ 9695 public void setActiveTransactionTracing(boolean active) { 9696 if (!checkCallingPermission( 9697 android.Manifest.permission.DUMP, "setActiveTransactionTracing()")) { 9698 throw new SecurityException("Requires DUMP permission"); 9699 } 9700 9701 final long token = Binder.clearCallingIdentity(); 9702 try { 9703 Parcel data = null; 9704 try { 9705 IBinder sf = ServiceManager.getService("SurfaceFlinger"); 9706 if (sf != null) { 9707 data = Parcel.obtain(); 9708 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 9709 data.writeInt(active ? 1 : 0); 9710 sf.transact(/* TRANSACTION_TRACE_CONTROL_CODE */ 1041, data, 9711 null, 0 /* flags */); 9712 } 9713 } catch (RemoteException e) { 9714 Slog.e(TAG, "Failed to set transaction tracing"); 9715 } finally { 9716 if (data != null) { 9717 data.recycle(); 9718 } 9719 } 9720 } finally { 9721 Binder.restoreCallingIdentity(token); 9722 } 9723 } 9724 9725 @Override 9726 public boolean mirrorDisplay(int displayId, SurfaceControl outSurfaceControl) { 9727 if (!checkCallingPermission(READ_FRAME_BUFFER, "mirrorDisplay()")) { 9728 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 9729 } 9730 9731 final SurfaceControl displaySc; 9732 synchronized (mGlobalLock) { 9733 DisplayContent displayContent = mRoot.getDisplayContent(displayId); 9734 if (displayContent == null) { 9735 Slog.e(TAG, "Invalid displayId " + displayId + " for mirrorDisplay"); 9736 return false; 9737 } 9738 9739 displaySc = displayContent.getWindowingLayer(); 9740 } 9741 9742 final SurfaceControl mirror = SurfaceControl.mirrorSurface(displaySc); 9743 outSurfaceControl.copyFrom(mirror, "WMS.mirrorDisplay"); 9744 mirror.release(); 9745 return true; 9746 } 9747 9748 @Override 9749 public boolean getWindowInsets(int displayId, IBinder token, InsetsState outInsetsState) { 9750 final long origId = Binder.clearCallingIdentity(); 9751 try { 9752 synchronized (mGlobalLock) { 9753 final DisplayContent dc = getDisplayContentOrCreate(displayId, token); 9754 if (dc == null) { 9755 throw new WindowManager.InvalidDisplayException("Display#" + displayId 9756 + "could not be found!"); 9757 } 9758 final WindowToken winToken = dc.getWindowToken(token); 9759 dc.getInsetsPolicy().getInsetsForWindowMetrics(winToken, outInsetsState); 9760 return dc.getDisplayPolicy().areSystemBarsForcedConsumedLw(); 9761 } 9762 } finally { 9763 Binder.restoreCallingIdentity(origId); 9764 } 9765 } 9766 9767 @Override 9768 public List<DisplayInfo> getPossibleDisplayInfo(int displayId) { 9769 final int callingUid = Binder.getCallingUid(); 9770 final long origId = Binder.clearCallingIdentity(); 9771 try { 9772 synchronized (mGlobalLock) { 9773 if (!mAtmService.isCallerRecents(callingUid) 9774 && (!multiCrop() || callingUid != SYSTEM_UID)) { 9775 Slog.e(TAG, "Unable to verify uid for getPossibleDisplayInfo" 9776 + " on uid " + callingUid); 9777 return new ArrayList<>(); 9778 } 9779 9780 // Retrieve the DisplayInfo across all possible display layouts. 9781 return mPossibleDisplayInfoMapper.getPossibleDisplayInfos(displayId); 9782 } 9783 } finally { 9784 Binder.restoreCallingIdentity(origId); 9785 } 9786 } 9787 9788 List<DisplayInfo> getPossibleDisplayInfoLocked(int displayId) { 9789 // Retrieve the DisplayInfo for all possible rotations across all possible display 9790 // layouts. 9791 return mPossibleDisplayInfoMapper.getPossibleDisplayInfos(displayId); 9792 } 9793 9794 void grantEmbeddedWindowFocus(Session session, InputTransferToken inputTransferToken, 9795 boolean grantFocus) { 9796 synchronized (mGlobalLock) { 9797 final EmbeddedWindowController.EmbeddedWindow embeddedWindow = 9798 mEmbeddedWindowController.getByInputTransferToken(inputTransferToken); 9799 if (embeddedWindow == null) { 9800 Slog.e(TAG, "Embedded window not found"); 9801 return; 9802 } 9803 if (embeddedWindow.mSession != session) { 9804 Slog.e(TAG, "Window not in session:" + session); 9805 return; 9806 } 9807 IBinder inputToken = embeddedWindow.getInputChannelToken(); 9808 if (inputToken == null) { 9809 Slog.e(TAG, "Focus token found but input channel token not found"); 9810 return; 9811 } 9812 SurfaceControl.Transaction t = mTransactionFactory.get(); 9813 final int displayId = embeddedWindow.mDisplayId; 9814 if (grantFocus) { 9815 t.setFocusedWindow(inputToken, embeddedWindow.toString(), displayId).apply(); 9816 EventLog.writeEvent(LOGTAG_INPUT_FOCUS, 9817 "Focus request " + embeddedWindow, "reason=grantEmbeddedWindowFocus(true)"); 9818 } else { 9819 // Search for a new focus target 9820 DisplayContent displayContent = mRoot.getDisplayContent(displayId); 9821 WindowState newFocusTarget = displayContent == null 9822 ? null : displayContent.findFocusedWindow(); 9823 if (newFocusTarget == null) { 9824 t.setFocusedWindow(null, null, displayId).apply(); 9825 ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s" 9826 + " dropped focus so setting focus to null since no candidate" 9827 + " was found", 9828 embeddedWindow); 9829 return; 9830 } 9831 t.setFocusedWindow(newFocusTarget.mInputChannelToken, newFocusTarget.getName(), 9832 displayId).apply(); 9833 9834 EventLog.writeEvent(LOGTAG_INPUT_FOCUS, 9835 "Focus request " + newFocusTarget, 9836 "reason=grantEmbeddedWindowFocus(false)"); 9837 } 9838 ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s grantFocus=%s", 9839 embeddedWindow, grantFocus); 9840 } 9841 } 9842 9843 void grantEmbeddedWindowFocus(Session session, IWindow callingWindow, 9844 InputTransferToken inputTransferToken, boolean grantFocus) { 9845 synchronized (mGlobalLock) { 9846 final WindowState hostWindow = 9847 windowForClientLocked(session, callingWindow, false /* throwOnError*/); 9848 if (hostWindow == null) { 9849 Slog.e(TAG, "Host window not found"); 9850 return; 9851 } 9852 if (hostWindow.mInputChannelToken == null) { 9853 Slog.e(TAG, "Host window does not have an input channel"); 9854 return; 9855 } 9856 final EmbeddedWindowController.EmbeddedWindow embeddedWindow = 9857 mEmbeddedWindowController.getByInputTransferToken(inputTransferToken); 9858 if (embeddedWindow == null) { 9859 Slog.e(TAG, "Embedded window not found"); 9860 return; 9861 } 9862 if (embeddedWindow.mHostWindowState != hostWindow) { 9863 Slog.e(TAG, "Embedded window does not belong to the host"); 9864 return; 9865 } 9866 if (grantFocus) { 9867 hostWindow.mInputWindowHandle.setFocusTransferTarget( 9868 embeddedWindow.getInputChannelToken()); 9869 EventLog.writeEvent(LOGTAG_INPUT_FOCUS, 9870 "Transfer focus request " + embeddedWindow, 9871 "reason=grantEmbeddedWindowFocus(true)"); 9872 } else { 9873 hostWindow.mInputWindowHandle.setFocusTransferTarget(null); 9874 EventLog.writeEvent(LOGTAG_INPUT_FOCUS, 9875 "Transfer focus request " + hostWindow, 9876 "reason=grantEmbeddedWindowFocus(false)"); 9877 } 9878 DisplayContent dc = mRoot.getDisplayContent(hostWindow.getDisplayId()); 9879 if (dc != null) { 9880 dc.getInputMonitor().updateInputWindowsLw(true); 9881 } 9882 9883 ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s grantFocus=%s", 9884 embeddedWindow, grantFocus); 9885 } 9886 } 9887 9888 @Override 9889 public void holdLock(IBinder token, int durationMs) { 9890 mTestUtilityService.verifyHoldLockToken(token); 9891 9892 synchronized (mGlobalLock) { 9893 SystemClock.sleep(durationMs); 9894 } 9895 } 9896 9897 @Override 9898 public String[] getSupportedDisplayHashAlgorithms() { 9899 return mDisplayHashController.getSupportedHashAlgorithms(); 9900 } 9901 9902 @Override 9903 public VerifiedDisplayHash verifyDisplayHash(DisplayHash displayHash) { 9904 return mDisplayHashController.verifyDisplayHash(displayHash); 9905 } 9906 9907 @Override 9908 public void setDisplayHashThrottlingEnabled(boolean enable) { 9909 if (!checkCallingPermission(READ_FRAME_BUFFER, "setDisplayHashThrottle()")) { 9910 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 9911 } 9912 mDisplayHashController.setDisplayHashThrottlingEnabled(enable); 9913 } 9914 9915 @Override 9916 public boolean isTaskSnapshotSupported() { 9917 synchronized (mGlobalLock) { 9918 return !mTaskSnapshotController.shouldDisableSnapshots(); 9919 } 9920 } 9921 9922 void generateDisplayHash(Session session, IWindow window, Rect boundsInWindow, 9923 String hashAlgorithm, RemoteCallback callback) { 9924 final SurfaceControl displaySurfaceControl; 9925 final Rect boundsInDisplay = new Rect(boundsInWindow); 9926 synchronized (mGlobalLock) { 9927 final WindowState win = windowForClientLocked(session, window, false); 9928 if (win == null) { 9929 Slog.w(TAG, "Failed to generate DisplayHash. Invalid window"); 9930 mDisplayHashController.sendDisplayHashError(callback, 9931 DISPLAY_HASH_ERROR_MISSING_WINDOW); 9932 return; 9933 } 9934 9935 if (win.mActivityRecord == null || !win.mActivityRecord.isState( 9936 ActivityRecord.State.RESUMED)) { 9937 mDisplayHashController.sendDisplayHashError(callback, 9938 DISPLAY_HASH_ERROR_MISSING_WINDOW); 9939 return; 9940 } 9941 9942 DisplayContent displayContent = win.getDisplayContent(); 9943 if (displayContent == null) { 9944 Slog.w(TAG, "Failed to generate DisplayHash. Window is not on a display"); 9945 mDisplayHashController.sendDisplayHashError(callback, 9946 DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN); 9947 return; 9948 } 9949 9950 displaySurfaceControl = displayContent.getSurfaceControl(); 9951 mDisplayHashController.calculateDisplayHashBoundsLocked(win, boundsInWindow, 9952 boundsInDisplay); 9953 9954 if (boundsInDisplay.isEmpty()) { 9955 Slog.w(TAG, "Failed to generate DisplayHash. Bounds are not on screen"); 9956 mDisplayHashController.sendDisplayHashError(callback, 9957 DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN); 9958 return; 9959 } 9960 } 9961 9962 // A screenshot of the entire display is taken rather than just the window. This is 9963 // because if we take a screenshot of the window, it will not include content that might 9964 // be covering it with the same uid. We want to make sure we include content that's 9965 // covering to ensure we get as close as possible to what the user sees 9966 final int uid = session.mUid; 9967 ScreenCapture.LayerCaptureArgs.Builder args = 9968 new ScreenCapture.LayerCaptureArgs.Builder(displaySurfaceControl) 9969 .setUid(uid) 9970 .setSourceCrop(boundsInDisplay); 9971 9972 mDisplayHashController.generateDisplayHash(args, boundsInWindow, hashAlgorithm, uid, 9973 callback); 9974 } 9975 9976 boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) { 9977 final Task imeTargetWindowTask; 9978 synchronized (mGlobalLock) { 9979 final WindowState imeTargetWindow = mWindowMap.get(imeTargetWindowToken); 9980 if (imeTargetWindow == null) { 9981 return false; 9982 } 9983 imeTargetWindowTask = imeTargetWindow.getTask(); 9984 if (imeTargetWindowTask == null) { 9985 return false; 9986 } 9987 if (imeTargetWindow.mActivityRecord != null 9988 && imeTargetWindow.mActivityRecord.mLastImeShown) { 9989 return true; 9990 } 9991 final TaskSnapshot snapshot = mTaskSnapshotController.getSnapshot( 9992 imeTargetWindowTask.mTaskId, false /* isLowResolution */); 9993 return snapshot != null && snapshot.hasImeSurface(); 9994 } 9995 } 9996 9997 @Override 9998 public int getImeDisplayId() { 9999 // TODO(b/189805422): Add a toast to notify users that IMS may get extra 10000 // onConfigurationChanged callback when perDisplayFocus is enabled. 10001 // Enabling perDisplayFocus means that we track focus on each display, so we don't have 10002 // the "top focus" display and getTopFocusedDisplayContent returns the default display 10003 // as the fallback. It leads to InputMethodService receives an extra onConfiguration 10004 // callback when InputMethodService move from a secondary display to another display 10005 // with the same display metrics because InputMethodService will always associate with 10006 // the ImeContainer on the default display in onCreate and receive a configuration update 10007 // to match default display ImeContainer and then receive another configuration update 10008 // from attachToWindowToken. 10009 synchronized (mGlobalLock) { 10010 final DisplayContent dc = mRoot.getTopFocusedDisplayContent(); 10011 return dc.getImePolicy() == DISPLAY_IME_POLICY_LOCAL ? dc.getDisplayId() 10012 : DEFAULT_DISPLAY; 10013 } 10014 } 10015 10016 @Override 10017 public void setTaskSnapshotEnabled(boolean enabled) { 10018 mTaskSnapshotController.setSnapshotEnabled(enabled); 10019 } 10020 10021 @Override 10022 @RequiresPermission(Manifest.permission.ACCESS_FPS_COUNTER) 10023 public void registerTaskFpsCallback(@IntRange(from = 0) int taskId, 10024 ITaskFpsCallback callback) { 10025 if (mContext.checkCallingOrSelfPermission(Manifest.permission.ACCESS_FPS_COUNTER) 10026 != PackageManager.PERMISSION_GRANTED) { 10027 final int pid = Binder.getCallingPid(); 10028 throw new SecurityException("Access denied to process: " + pid 10029 + ", must have permission " + Manifest.permission.ACCESS_FPS_COUNTER); 10030 } 10031 synchronized (mGlobalLock) { 10032 if (mRoot.anyTaskForId(taskId) == null) { 10033 throw new IllegalArgumentException("no task with taskId: " + taskId); 10034 } 10035 } 10036 10037 mTaskFpsCallbackController.registerListener(taskId, callback); 10038 } 10039 10040 @Override 10041 @RequiresPermission(Manifest.permission.ACCESS_FPS_COUNTER) 10042 public void unregisterTaskFpsCallback(ITaskFpsCallback callback) { 10043 if (mContext.checkCallingOrSelfPermission(Manifest.permission.ACCESS_FPS_COUNTER) 10044 != PackageManager.PERMISSION_GRANTED) { 10045 final int pid = Binder.getCallingPid(); 10046 throw new SecurityException("Access denied to process: " + pid 10047 + ", must have permission " + Manifest.permission.ACCESS_FPS_COUNTER); 10048 } 10049 10050 mTaskFpsCallbackController.unregisterListener(callback); 10051 } 10052 10053 @Override 10054 public Bitmap snapshotTaskForRecents(int taskId) { 10055 if (!checkCallingPermission(READ_FRAME_BUFFER, "snapshotTaskForRecents()")) { 10056 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 10057 } 10058 10059 TaskSnapshot taskSnapshot; 10060 final long token = Binder.clearCallingIdentity(); 10061 try { 10062 final Supplier<TaskSnapshot> supplier; 10063 synchronized (mGlobalLock) { 10064 Task task = mRoot.anyTaskForId(taskId, MATCH_ATTACHED_TASK_OR_RECENT_TASKS); 10065 if (task == null) { 10066 throw new IllegalArgumentException( 10067 "Failed to find matching task for taskId=" + taskId); 10068 } 10069 supplier = mTaskSnapshotController.captureSnapshot(task, true /* allowAppTheme */); 10070 } 10071 taskSnapshot = supplier != null ? supplier.get() : null; 10072 } finally { 10073 Binder.restoreCallingIdentity(token); 10074 } 10075 10076 if (taskSnapshot == null || taskSnapshot.getHardwareBuffer() == null) { 10077 return null; 10078 } 10079 return Bitmap.wrapHardwareBuffer(taskSnapshot.getHardwareBuffer(), 10080 taskSnapshot.getColorSpace()); 10081 } 10082 10083 @Override 10084 public void setRecentsAppBehindSystemBars(boolean behindSystemBars) { 10085 if (!checkCallingPermission(START_TASKS_FROM_RECENTS, "setRecentsAppBehindSystemBars()")) { 10086 throw new SecurityException("Requires START_TASKS_FROM_RECENTS permission"); 10087 } 10088 final long token = Binder.clearCallingIdentity(); 10089 try { 10090 synchronized (mGlobalLock) { 10091 final Task recentsApp = mRoot.getTask(task -> task.isActivityTypeHomeOrRecents() 10092 && task.getTopVisibleActivity() != null); 10093 if (recentsApp != null) { 10094 recentsApp.getTask().setCanAffectSystemUiFlags(behindSystemBars); 10095 mWindowPlacerLocked.requestTraversal(); 10096 } 10097 InputMethodManagerInternal.get().maybeFinishStylusHandwriting(); 10098 } 10099 } finally { 10100 Binder.restoreCallingIdentity(token); 10101 } 10102 } 10103 10104 /** 10105 * Gets the background color of the letterbox. Considered invalid if the background has 10106 * multiple colors {@link #isLetterboxBackgroundMultiColored} 10107 */ 10108 @Override 10109 public int getLetterboxBackgroundColorInArgb() { 10110 return mAppCompatConfiguration.getLetterboxBackgroundColor().toArgb(); 10111 } 10112 10113 /** 10114 * Whether the outer area of the letterbox has multiple colors (e.g. blurred background). 10115 */ 10116 @Override 10117 public boolean isLetterboxBackgroundMultiColored() { 10118 @AppCompatConfiguration.LetterboxBackgroundType int letterboxBackgroundType = 10119 mAppCompatConfiguration.getLetterboxBackgroundType(); 10120 switch (letterboxBackgroundType) { 10121 case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING: 10122 case LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND: 10123 case LETTERBOX_BACKGROUND_WALLPAPER: 10124 return true; 10125 case LETTERBOX_BACKGROUND_SOLID_COLOR: 10126 return false; 10127 default: 10128 throw new AssertionError( 10129 "Unexpected letterbox background type: " + letterboxBackgroundType); 10130 } 10131 } 10132 10133 @Override 10134 public void captureDisplay(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs, 10135 ScreenCapture.ScreenCaptureListener listener) { 10136 Slog.d(TAG, "captureDisplay"); 10137 if (!checkCallingPermission(READ_FRAME_BUFFER, "captureDisplay()")) { 10138 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 10139 } 10140 10141 ScreenCapture.LayerCaptureArgs layerCaptureArgs = getCaptureArgs(displayId, captureArgs); 10142 ScreenCapture.captureLayers(layerCaptureArgs, listener); 10143 10144 if (Binder.getCallingUid() != SYSTEM_UID) { 10145 // Release the SurfaceControl objects only if the caller is not in system server as no 10146 // parcelling occurs in this case. 10147 layerCaptureArgs.release(); 10148 } 10149 } 10150 10151 @VisibleForTesting 10152 ScreenCapture.LayerCaptureArgs getCaptureArgs(int displayId, 10153 @Nullable ScreenCapture.CaptureArgs captureArgs) { 10154 final SurfaceControl displaySurfaceControl; 10155 synchronized (mGlobalLock) { 10156 DisplayContent displayContent = mRoot.getDisplayContent(displayId); 10157 if (displayContent == null) { 10158 throw new IllegalArgumentException("Trying to screenshot and invalid display: " 10159 + displayId); 10160 } 10161 10162 displaySurfaceControl = displayContent.getSurfaceControl(); 10163 10164 if (captureArgs == null) { 10165 captureArgs = new ScreenCapture.CaptureArgs.Builder<>() 10166 .build(); 10167 } 10168 10169 if (captureArgs.mSourceCrop.isEmpty()) { 10170 displayContent.getBounds(mTmpRect); 10171 mTmpRect.offsetTo(0, 0); 10172 } else { 10173 mTmpRect.set(captureArgs.mSourceCrop); 10174 } 10175 } 10176 10177 return new ScreenCapture.LayerCaptureArgs.Builder(displaySurfaceControl, captureArgs) 10178 .setSourceCrop(mTmpRect) 10179 .build(); 10180 } 10181 10182 @Override 10183 public boolean isGlobalKey(int keyCode) { 10184 return mPolicy.isGlobalKey(keyCode); 10185 } 10186 10187 private int sanitizeWindowType(Session session, int displayId, IBinder windowToken, int type) { 10188 // Determine whether this window type is valid for this process. 10189 final boolean isTypeValid; 10190 if (type == TYPE_ACCESSIBILITY_OVERLAY && windowToken != null) { 10191 // Only accessibility services can add accessibility overlays. 10192 // Accessibility services will have a WindowToken with type 10193 // TYPE_ACCESSIBILITY_OVERLAY. 10194 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 10195 final WindowToken token = displayContent.getWindowToken(windowToken); 10196 if (token == null) { 10197 isTypeValid = false; 10198 } else if (type == token.getWindowType()) { 10199 isTypeValid = true; 10200 } else { 10201 isTypeValid = false; 10202 } 10203 } else if (!session.mCanAddInternalSystemWindow && type != 0) { 10204 Slog.w( 10205 TAG_WM, 10206 "Requires INTERNAL_SYSTEM_WINDOW permission if assign type to" 10207 + " input. New type will be 0."); 10208 isTypeValid = false; 10209 } else { 10210 isTypeValid = true; 10211 } 10212 10213 if (!isTypeValid) { 10214 return 0; 10215 } 10216 return type; 10217 } 10218 @Override 10219 public boolean addToSurfaceSyncGroup(IBinder syncGroupToken, boolean parentSyncGroupMerge, 10220 @Nullable ISurfaceSyncGroupCompletedListener completedListener, 10221 AddToSurfaceSyncGroupResult outAddToSyncGroupResult) { 10222 return mSurfaceSyncGroupController.addToSyncGroup(syncGroupToken, parentSyncGroupMerge, 10223 completedListener, outAddToSyncGroupResult); 10224 } 10225 10226 @Override 10227 public void markSurfaceSyncGroupReady(IBinder syncGroupToken) { 10228 mSurfaceSyncGroupController.markSyncGroupReady(syncGroupToken); 10229 } 10230 10231 10232 /** 10233 * Must be called when a screenshot is taken via hardware chord. 10234 * 10235 * Notifies all registered visible activities that have registered for screencapture callback, 10236 * Returns a list of visible apps component names. 10237 */ 10238 @Override 10239 public List<ComponentName> notifyScreenshotListeners(int displayId) { 10240 // make sure caller is SysUI. 10241 if (!checkCallingPermission(STATUS_BAR_SERVICE, 10242 "notifyScreenshotListeners()")) { 10243 throw new SecurityException("Requires STATUS_BAR_SERVICE permission"); 10244 } 10245 synchronized (mGlobalLock) { 10246 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 10247 if (displayContent == null) { 10248 return new ArrayList<>(); 10249 } 10250 ArraySet<ComponentName> notifiedApps = new ArraySet<>(); 10251 displayContent.forAllActivities( 10252 (ar) -> { 10253 if (!notifiedApps.contains(ar.mActivityComponent) && ar.isVisible() 10254 && ar.isRegisteredForScreenCaptureCallback()) { 10255 ar.reportScreenCaptured(); 10256 notifiedApps.add(ar.mActivityComponent); 10257 } 10258 }, 10259 true /* traverseTopToBottom */); 10260 return List.copyOf(notifiedApps); 10261 } 10262 } 10263 10264 /** 10265 * Returns whether the given UID is the owner of a virtual device, which the given display 10266 * belongs to. 10267 */ 10268 @Override 10269 public boolean isCallerVirtualDeviceOwner(int displayId, int callingUid) { 10270 if (!android.companion.virtualdevice.flags.Flags.statusBarAndInsets()) { 10271 return false; 10272 } 10273 final long identity = Binder.clearCallingIdentity(); 10274 try { 10275 return mAtmService.mTaskSupervisor.isDeviceOwnerUid(displayId, callingUid); 10276 } finally { 10277 Binder.restoreCallingIdentity(identity); 10278 } 10279 } 10280 10281 /** 10282 * Returns whether the display with the given ID is trusted. 10283 */ 10284 @Override 10285 public boolean isDisplayTrusted(int displayId) { 10286 final long identity = Binder.clearCallingIdentity(); 10287 try { 10288 synchronized (mGlobalLock) { 10289 DisplayContent dc = mRoot.getDisplayContent(displayId); 10290 return dc != null && dc.isTrusted(); 10291 } 10292 } finally { 10293 Binder.restoreCallingIdentity(identity); 10294 } 10295 } 10296 10297 @RequiresPermission(ACCESS_SURFACE_FLINGER) 10298 @Override 10299 public boolean replaceContentOnDisplay(int displayId, SurfaceControl sc) { 10300 if (!checkCallingPermission(ACCESS_SURFACE_FLINGER, 10301 "replaceDisplayContent()")) { 10302 throw new SecurityException("Requires ACCESS_SURFACE_FLINGER permission"); 10303 } 10304 10305 final long origId = Binder.clearCallingIdentity(); 10306 try { 10307 synchronized (mGlobalLock) { 10308 DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId); 10309 if (dc == null) { 10310 return false; 10311 } 10312 dc.replaceContent(sc); 10313 return true; 10314 } 10315 } finally { 10316 Binder.restoreCallingIdentity(origId); 10317 } 10318 } 10319 10320 /** 10321 * Resets the spatial ordering of recents for testing purposes. 10322 */ 10323 void resetFreezeRecentTaskListReordering() { 10324 if (!checkCallingPermission(permission.MANAGE_ACTIVITY_TASKS, 10325 "resetFreezeRecentTaskListReordering()")) { 10326 throw new SecurityException("Requires MANAGE_ACTIVITY_TASKS permission"); 10327 } 10328 mAtmService.getRecentTasks().resetFreezeTaskListReorderingOnTimeout(); 10329 } 10330 10331 @Override 10332 public void registerTrustedPresentationListener(IBinder window, 10333 ITrustedPresentationListener listener, 10334 TrustedPresentationThresholds thresholds, int id) { 10335 mTrustedPresentationListenerController.registerListener(window, listener, thresholds, id); 10336 } 10337 10338 @Override 10339 public void unregisterTrustedPresentationListener(ITrustedPresentationListener listener, 10340 int id) { 10341 mTrustedPresentationListenerController.unregisterListener(listener, id); 10342 } 10343 10344 @EnforcePermission(android.Manifest.permission.DETECT_SCREEN_RECORDING) 10345 @Override 10346 public boolean registerScreenRecordingCallback(IScreenRecordingCallback callback) { 10347 registerScreenRecordingCallback_enforcePermission(); 10348 return mScreenRecordingCallbackController.register(callback); 10349 } 10350 10351 @EnforcePermission(android.Manifest.permission.DETECT_SCREEN_RECORDING) 10352 @Override 10353 public void unregisterScreenRecordingCallback(IScreenRecordingCallback callback) { 10354 unregisterScreenRecordingCallback_enforcePermission(); 10355 mScreenRecordingCallbackController.unregister(callback); 10356 } 10357 10358 void onProcessActivityVisibilityChanged(int uid, boolean visible) { 10359 mScreenRecordingCallbackController.onProcessActivityVisibilityChanged(uid, visible); 10360 } 10361 10362 /** 10363 * Sets the listener to be called back when a cross-window drag and drop operation happens. 10364 */ 10365 @Override 10366 public void setGlobalDragListener(IGlobalDragListener listener) throws RemoteException { 10367 mAtmService.enforceTaskPermission("setUnhandledDragListener"); 10368 synchronized (mGlobalLock) { 10369 mDragDropController.setGlobalDragListener(listener); 10370 } 10371 } 10372 10373 boolean getDisableSecureWindows() { 10374 return mDisableSecureWindows; 10375 } 10376 10377 /** 10378 * Called to notify WMS that the specified window has become visible. This shows a Toast if the 10379 * window is deemed to hold sensitive content. 10380 */ 10381 private void onWindowVisible(@NonNull WindowState w) { 10382 showToastIfBlockingScreenCapture(w); 10383 } 10384 10385 /** 10386 * Shows a Toast if the specified window is 10387 * {@link LocalService#addBlockScreenCaptureForApps(ArraySet) blocked} from screen capture based 10388 * on sensitive content protections. 10389 */ 10390 private void showToastIfBlockingScreenCapture(@NonNull WindowState w) { 10391 int uid = w.getOwningUid(); 10392 if (mCaptureBlockedToastShownUids.contains(uid)) { 10393 return; 10394 } 10395 if (mSensitiveContentPackages.shouldBlockScreenCaptureForApp(w.getOwningPackage(), uid, 10396 w.getWindowToken())) { 10397 mCaptureBlockedToastShownUids.add(uid); 10398 mH.post(() -> { 10399 Toast.makeText(mContext, Looper.getMainLooper(), 10400 mContext.getString(R.string.screen_not_shared_sensitive_content), 10401 Toast.LENGTH_LONG) 10402 .show(); 10403 }); 10404 // If blocked due to notification protection (null window token) log protection applied 10405 if (sensitiveContentMetricsBugfix() 10406 && mSensitiveContentPackages 10407 .shouldBlockScreenCaptureForApp(w.getOwningPackage(), uid, null)) { 10408 FrameworkStatsLog.write( 10409 SENSITIVE_NOTIFICATION_APP_PROTECTION_APPLIED, 10410 mSensitiveContentProtectionSessionId, 10411 uid); 10412 } 10413 } 10414 } 10415 10416 private static boolean getShellTransitEnabled() { 10417 return true; 10418 } 10419 10420 /** 10421 * Dump ViewRootImpl for visible non-activity windows. 10422 */ 10423 private void dumpVisibleWindowClients(FileDescriptor fd, PrintWriter pw, long timeout) { 10424 final ArrayList<WindowState> systemWindows = new ArrayList<>(); 10425 synchronized (mGlobalLock) { 10426 mRoot.forAllWindows(w -> { 10427 if (!w.isActivityWindow() && w.isVisibleNow()) { 10428 systemWindows.add(w); 10429 } 10430 }, false /* traverseTopToBottom */); 10431 } 10432 10433 systemWindows.forEach(w -> { 10434 pw.println("---------------------------------"); 10435 pw.println(w.toString()); 10436 pw.flush(); 10437 try (TransferPipe tp = new TransferPipe()) { 10438 w.mClient.dumpWindow(tp.getWriteFd()); 10439 tp.go(fd, timeout); 10440 } catch (IOException e) { 10441 pw.println("Failure while dumping the window: " + e); 10442 } catch (RemoteException e) { 10443 pw.println("Got a RemoteException while dumping the window"); 10444 } 10445 }); 10446 } 10447 10448 private final class ConfigurationChangeSettingInternalImpl implements 10449 ConfigurationChangeSetting.ConfigurationChangeSettingInternal { 10450 @NonNull 10451 @Override 10452 public ConfigurationChangeSetting createImplFromParcel( 10453 @ConfigurationChangeSetting.SettingType int settingType, @NonNull Parcel in) { 10454 switch (settingType) { 10455 case ConfigurationChangeSetting.SETTING_TYPE_DISPLAY_DENSITY: 10456 return new DensitySettingImpl(in); 10457 case ConfigurationChangeSetting.SETTING_TYPE_FONT_SCALE: 10458 return new FontScaleSettingImpl(in); 10459 default: 10460 throw new IllegalArgumentException("Unknown setting type " + settingType); 10461 } 10462 } 10463 10464 private final class DensitySettingImpl extends ConfigurationChangeSetting.DensitySetting { 10465 private DensitySettingImpl(Parcel in) { 10466 super(in); 10467 } 10468 10469 @Override 10470 @GuardedBy("mGlobalLock") 10471 public void apply(@UserIdInt int userId) { 10472 setForcedDensityLockedInternal(mDisplayId, mDensity, userId); 10473 } 10474 } 10475 10476 private final class FontScaleSettingImpl extends 10477 ConfigurationChangeSetting.FontScaleSetting { 10478 private FontScaleSettingImpl(Parcel in) { 10479 super(in); 10480 } 10481 10482 @Override 10483 @GuardedBy("mGlobalLock") 10484 public void apply(@UserIdInt int userId) { 10485 Settings.System.putFloat(mContext.getContentResolver(), 10486 Settings.System.FONT_SCALE, mFontScaleFactor); 10487 mAtmService.updateFontScaleIfNeeded(userId); 10488 } 10489 } 10490 } 10491 } 10492