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