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