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.MANAGE_APP_TOKENS; 20 import static android.Manifest.permission.READ_FRAME_BUFFER; 21 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS; 22 import static android.Manifest.permission.RESTRICTED_VR_ACCESS; 23 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; 24 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; 25 import static android.app.StatusBarManager.DISABLE_MASK; 26 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED; 27 import static android.content.Intent.ACTION_USER_REMOVED; 28 import static android.content.Intent.EXTRA_USER_HANDLE; 29 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 30 import static android.os.Process.ROOT_UID; 31 import static android.os.Process.SHELL_UID; 32 import static android.os.Process.SYSTEM_UID; 33 import static android.os.Process.myPid; 34 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 35 import static android.os.UserHandle.USER_NULL; 36 import static android.view.Display.DEFAULT_DISPLAY; 37 import static android.view.Display.INVALID_DISPLAY; 38 import static android.view.WindowManager.DOCKED_INVALID; 39 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; 40 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 41 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 42 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; 43 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 44 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 45 import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 46 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 47 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 48 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 49 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 50 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 51 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; 52 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 53 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 54 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 55 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 56 import static android.view.WindowManager.LayoutParams.TYPE_DRAG; 57 import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 58 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 59 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 60 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 61 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; 62 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; 63 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; 64 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 65 import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 66 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; 67 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 68 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY; 69 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; 70 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 71 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 72 import static com.android.server.LockGuard.INDEX_WINDOW; 73 import static com.android.server.LockGuard.installLock; 74 import static com.android.server.wm.AppTransition.TRANSIT_UNSET; 75 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END; 76 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START; 77 import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED; 78 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 79 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 80 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 81 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 82 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; 83 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION; 84 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 85 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG; 86 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 87 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 88 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 89 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON; 90 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 91 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 92 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; 93 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON; 94 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW; 95 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; 96 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 97 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 98 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT; 99 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; 100 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 101 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 102 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 103 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS; 104 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON; 105 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 106 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 107 108 import android.Manifest; 109 import android.Manifest.permission; 110 import android.animation.AnimationHandler; 111 import android.animation.ValueAnimator; 112 import android.annotation.IntDef; 113 import android.annotation.NonNull; 114 import android.annotation.Nullable; 115 import android.app.ActivityManager; 116 import android.app.ActivityManager.TaskSnapshot; 117 import android.app.ActivityManagerInternal; 118 import android.app.ActivityThread; 119 import android.app.AppOpsManager; 120 import android.app.IActivityManager; 121 import android.content.BroadcastReceiver; 122 import android.content.ContentResolver; 123 import android.content.Context; 124 import android.content.Intent; 125 import android.content.IntentFilter; 126 import android.content.pm.ApplicationInfo; 127 import android.content.pm.PackageManager; 128 import android.content.res.Configuration; 129 import android.database.ContentObserver; 130 import android.graphics.Bitmap; 131 import android.graphics.GraphicBuffer; 132 import android.graphics.Matrix; 133 import android.graphics.PixelFormat; 134 import android.graphics.Point; 135 import android.graphics.Rect; 136 import android.graphics.RectF; 137 import android.graphics.Region; 138 import android.hardware.configstore.V1_0.ISurfaceFlingerConfigs; 139 import android.hardware.configstore.V1_0.OptionalBool; 140 import android.hardware.display.DisplayManager; 141 import android.hardware.display.DisplayManagerInternal; 142 import android.hardware.input.InputManager; 143 import android.net.Uri; 144 import android.os.Binder; 145 import android.os.Build; 146 import android.os.Bundle; 147 import android.os.Debug; 148 import android.os.Handler; 149 import android.os.IBinder; 150 import android.os.IRemoteCallback; 151 import android.os.Looper; 152 import android.os.Message; 153 import android.os.Parcel; 154 import android.os.ParcelFileDescriptor; 155 import android.os.PowerManager; 156 import android.os.PowerManagerInternal; 157 import android.os.PowerSaveState; 158 import android.os.RemoteException; 159 import android.os.ServiceManager; 160 import android.os.StrictMode; 161 import android.os.SystemClock; 162 import android.os.SystemProperties; 163 import android.os.SystemService; 164 import android.os.Trace; 165 import android.os.UserHandle; 166 import android.os.WorkSource; 167 import android.provider.Settings; 168 import android.text.format.DateUtils; 169 import android.util.ArraySet; 170 import android.util.DisplayMetrics; 171 import android.util.EventLog; 172 import android.util.Log; 173 import android.util.MergedConfiguration; 174 import android.util.Pair; 175 import android.util.Slog; 176 import android.util.SparseArray; 177 import android.util.SparseIntArray; 178 import android.util.TimeUtils; 179 import android.util.TypedValue; 180 import android.view.AppTransitionAnimationSpec; 181 import android.view.Display; 182 import android.view.DisplayInfo; 183 import android.view.Gravity; 184 import android.view.IAppTransitionAnimationSpecsFuture; 185 import android.view.IDockedStackListener; 186 import android.view.IInputFilter; 187 import android.view.IOnKeyguardExitResult; 188 import android.view.IPinnedStackListener; 189 import android.view.IRotationWatcher; 190 import android.view.IWallpaperVisibilityListener; 191 import android.view.IWindow; 192 import android.view.IWindowId; 193 import android.view.IWindowManager; 194 import android.view.IWindowSession; 195 import android.view.IWindowSessionCallback; 196 import android.view.InputChannel; 197 import android.view.InputDevice; 198 import android.view.InputEvent; 199 import android.view.InputEventReceiver; 200 import android.view.KeyEvent; 201 import android.view.MagnificationSpec; 202 import android.view.MotionEvent; 203 import android.view.PointerIcon; 204 import android.view.Surface; 205 import android.view.Surface.OutOfResourcesException; 206 import android.view.SurfaceControl; 207 import android.view.SurfaceSession; 208 import android.view.View; 209 import android.view.WindowContentFrameStats; 210 import android.view.WindowManager; 211 import android.view.WindowManager.LayoutParams; 212 import android.view.WindowManagerGlobal; 213 import android.view.WindowManagerInternal; 214 import android.view.WindowManagerPolicy; 215 import android.view.WindowManagerPolicy.PointerEventListener; 216 import android.view.WindowManagerPolicy.ScreenOffListener; 217 import android.view.animation.Animation; 218 import android.view.inputmethod.InputMethodManagerInternal; 219 220 import com.android.internal.R; 221 import com.android.internal.app.IAssistScreenshotReceiver; 222 import com.android.internal.graphics.SfVsyncFrameCallbackProvider; 223 import com.android.internal.os.IResultReceiver; 224 import com.android.internal.policy.IKeyguardDismissCallback; 225 import com.android.internal.policy.IShortcutService; 226 import com.android.internal.util.DumpUtils; 227 import com.android.internal.util.FastPrintWriter; 228 import com.android.internal.view.IInputContext; 229 import com.android.internal.view.IInputMethodClient; 230 import com.android.internal.view.IInputMethodManager; 231 import com.android.internal.view.WindowManagerPolicyThread; 232 import com.android.server.AnimationThread; 233 import com.android.server.DisplayThread; 234 import com.android.server.EventLogTags; 235 import com.android.server.FgThread; 236 import com.android.server.LocalServices; 237 import com.android.server.UiThread; 238 import com.android.server.Watchdog; 239 import com.android.server.input.InputManagerService; 240 import com.android.server.power.BatterySaverPolicy.ServiceType; 241 import com.android.server.power.ShutdownThread; 242 243 import java.io.BufferedWriter; 244 import java.io.DataInputStream; 245 import java.io.File; 246 import java.io.FileDescriptor; 247 import java.io.FileInputStream; 248 import java.io.FileNotFoundException; 249 import java.io.IOException; 250 import java.io.OutputStream; 251 import java.io.OutputStreamWriter; 252 import java.io.PrintWriter; 253 import java.io.StringWriter; 254 import java.lang.annotation.Retention; 255 import java.lang.annotation.RetentionPolicy; 256 import java.net.Socket; 257 import java.text.DateFormat; 258 import java.util.ArrayList; 259 import java.util.Date; 260 import java.util.List; 261 /** {@hide} */ 262 public class WindowManagerService extends IWindowManager.Stub 263 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { 264 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM; 265 266 static final int LAYOUT_REPEAT_THRESHOLD = 4; 267 268 static final boolean PROFILE_ORIENTATION = false; 269 static final boolean localLOGV = DEBUG; 270 271 /** How much to multiply the policy's type layer, to reserve room 272 * for multiple windows of the same type and Z-ordering adjustment 273 * with TYPE_LAYER_OFFSET. */ 274 static final int TYPE_LAYER_MULTIPLIER = 10000; 275 276 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above 277 * or below others in the same layer. */ 278 static final int TYPE_LAYER_OFFSET = 1000; 279 280 /** How much to increment the layer for each window, to reserve room 281 * for effect surfaces between them. 282 */ 283 static final int WINDOW_LAYER_MULTIPLIER = 5; 284 285 /** 286 * Dim surface layer is immediately below target window. 287 */ 288 static final int LAYER_OFFSET_DIM = 1; 289 290 /** 291 * Animation thumbnail is as far as possible below the window above 292 * the thumbnail (or in other words as far as possible above the window 293 * below it). 294 */ 295 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1; 296 297 /** The maximum length we will accept for a loaded animation duration: 298 * this is 10 seconds. 299 */ 300 static final int MAX_ANIMATION_DURATION = 10 * 1000; 301 302 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 303 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 304 305 /** Amount of time (in milliseconds) to delay before declaring a seamless rotation timeout. */ 306 static final int SEAMLESS_ROTATION_TIMEOUT_DURATION = 2000; 307 308 /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */ 309 static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000; 310 311 /** Amount of time to allow a last ANR message to exist before freeing the memory. */ 312 static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours 313 /** 314 * If true, the window manager will do its own custom freezing and general 315 * management of the screen during rotation. 316 */ 317 static final boolean CUSTOM_SCREEN_ROTATION = true; 318 319 // Maximum number of milliseconds to wait for input devices to be enumerated before 320 // proceding with safe mode detection. 321 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 322 323 // Default input dispatching timeout in nanoseconds. 324 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; 325 326 // Poll interval in milliseconds for watching boot animation finished. 327 private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; 328 329 // The name of the boot animation service in init.rc. 330 private static final String BOOT_ANIMATION_SERVICE = "bootanim"; 331 332 static final int UPDATE_FOCUS_NORMAL = 0; 333 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 334 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 335 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 336 337 private static final String SYSTEM_SECURE = "ro.secure"; 338 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 339 340 private static final String DENSITY_OVERRIDE = "ro.config.density_override"; 341 private static final String SIZE_OVERRIDE = "ro.config.size_override"; 342 343 private static final int MAX_SCREENSHOT_RETRIES = 3; 344 345 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular"; 346 347 // Used to indicate that if there is already a transition set, it should be preserved when 348 // trying to apply a new one. 349 private static final boolean ALWAYS_KEEP_CURRENT = true; 350 351 private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f; 352 353 // Enums for animation scale update types. 354 @Retention(RetentionPolicy.SOURCE) 355 @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE}) 356 private @interface UpdateAnimationScaleMode {}; 357 private static final int WINDOW_ANIMATION_SCALE = 0; 358 private static final int TRANSITION_ANIMATION_SCALE = 1; 359 private static final int ANIMATION_DURATION_SCALE = 2; 360 361 final private KeyguardDisableHandler mKeyguardDisableHandler; 362 boolean mKeyguardGoingAway; 363 // VR Vr2d Display Id. 364 int mVr2dDisplayId = INVALID_DISPLAY; 365 366 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 367 @Override 368 public void onReceive(Context context, Intent intent) { 369 switch (intent.getAction()) { 370 case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED: 371 mKeyguardDisableHandler.sendEmptyMessage(KEYGUARD_POLICY_CHANGED); 372 break; 373 case ACTION_USER_REMOVED: 374 final int userId = intent.getIntExtra(EXTRA_USER_HANDLE, USER_NULL); 375 if (userId != USER_NULL) { 376 synchronized (mWindowMap) { 377 mScreenCaptureDisabled.remove(userId); 378 } 379 } 380 break; 381 } 382 } 383 }; 384 final WindowSurfacePlacer mWindowPlacerLocked; 385 386 /** 387 * Current user when multi-user is enabled. Don't show windows of 388 * non-current user. Also see mCurrentProfileIds. 389 */ 390 int mCurrentUserId; 391 /** 392 * Users that are profiles of the current user. These are also allowed to show windows 393 * on the current user. 394 */ 395 int[] mCurrentProfileIds = new int[] {}; 396 397 final Context mContext; 398 399 final boolean mHaveInputMethods; 400 401 final boolean mHasPermanentDpad; 402 final long mDrawLockTimeoutMillis; 403 final boolean mAllowAnimationsInLowPowerMode; 404 405 final boolean mAllowBootMessages; 406 407 final boolean mLimitedAlphaCompositing; 408 final int mMaxUiWidth; 409 410 final WindowManagerPolicy mPolicy; 411 412 final IActivityManager mActivityManager; 413 final ActivityManagerInternal mAmInternal; 414 415 final AppOpsManager mAppOps; 416 417 final DisplaySettings mDisplaySettings; 418 419 /** If the system should display notifications for apps displaying an alert window. */ 420 boolean mShowAlertWindowNotifications = true; 421 422 /** 423 * All currently active sessions with clients. 424 */ 425 final ArraySet<Session> mSessions = new ArraySet<>(); 426 427 /** 428 * Mapping from an IWindow IBinder to the server's Window object. 429 * This is also used as the lock for all of our state. 430 * NOTE: Never call into methods that lock ActivityManagerService while holding this object. 431 */ 432 final WindowHashMap mWindowMap = new WindowHashMap(); 433 434 /** 435 * List of window tokens that have finished starting their application, 436 * and now need to have the policy remove their windows. 437 */ 438 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>(); 439 440 /** 441 * List of window tokens that have finished drawing their own windows and 442 * no longer need to show any saved surfaces. Windows that's still showing 443 * saved surfaces will be cleaned up after next animation pass. 444 */ 445 final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>(); 446 447 /** 448 * List of app window tokens that are waiting for replacing windows. If the 449 * replacement doesn't come in time the stale windows needs to be disposed of. 450 */ 451 final ArrayList<AppWindowToken> mWindowReplacementTimeouts = new ArrayList<>(); 452 453 /** 454 * Windows that are being resized. Used so we can tell the client about 455 * the resize after closing the transaction in which we resized the 456 * underlying surface. 457 */ 458 final ArrayList<WindowState> mResizingWindows = new ArrayList<>(); 459 460 /** 461 * Windows whose animations have ended and now must be removed. 462 */ 463 final ArrayList<WindowState> mPendingRemove = new ArrayList<>(); 464 465 /** 466 * Used when processing mPendingRemove to avoid working on the original array. 467 */ 468 WindowState[] mPendingRemoveTmp = new WindowState[20]; 469 470 /** 471 * Windows whose surface should be destroyed. 472 */ 473 final ArrayList<WindowState> mDestroySurface = new ArrayList<>(); 474 475 /** 476 * Windows with a preserved surface waiting to be destroyed. These windows 477 * are going through a surface change. We keep the old surface around until 478 * the first frame on the new surface finishes drawing. 479 */ 480 final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>(); 481 482 /** 483 * Windows that have lost input focus and are waiting for the new 484 * focus window to be displayed before they are told about this. 485 */ 486 ArrayList<WindowState> mLosingFocus = new ArrayList<>(); 487 488 /** 489 * This is set when we have run out of memory, and will either be an empty 490 * list or contain windows that need to be force removed. 491 */ 492 final ArrayList<WindowState> mForceRemoves = new ArrayList<>(); 493 494 /** 495 * Windows that clients are waiting to have drawn. 496 */ 497 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>(); 498 /** 499 * And the callback to make when they've all been drawn. 500 */ 501 Runnable mWaitingForDrawnCallback; 502 503 /** List of window currently causing non-system overlay windows to be hidden. */ 504 private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>(); 505 506 /** 507 * Stores for each user whether screencapture is disabled 508 * This array is essentially a cache for all userId for 509 * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled} 510 */ 511 private SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>(); 512 513 IInputMethodManager mInputMethodManager; 514 515 AccessibilityController mAccessibilityController; 516 517 final SurfaceSession mFxSession; 518 Watermark mWatermark; 519 StrictModeFlash mStrictModeFlash; 520 CircularDisplayMask mCircularDisplayMask; 521 EmulatorDisplayOverlay mEmulatorDisplayOverlay; 522 523 final float[] mTmpFloats = new float[9]; 524 final Rect mTmpRect = new Rect(); 525 final Rect mTmpRect2 = new Rect(); 526 final Rect mTmpRect3 = new Rect(); 527 final RectF mTmpRectF = new RectF(); 528 529 final Matrix mTmpTransform = new Matrix(); 530 531 boolean mDisplayReady; 532 boolean mSafeMode; 533 boolean mDisplayEnabled = false; 534 boolean mSystemBooted = false; 535 boolean mForceDisplayEnabled = false; 536 boolean mShowingBootMessages = false; 537 boolean mBootAnimationStopped = false; 538 539 // Following variables are for debugging screen wakelock only. 540 WindowState mLastWakeLockHoldingWindow = null; 541 WindowState mLastWakeLockObscuringWindow = null; 542 543 /** Dump of the windows and app tokens at the time of the last ANR. Cleared after 544 * LAST_ANR_LIFETIME_DURATION_MSECS */ 545 String mLastANRState; 546 547 // The root of the device window hierarchy. 548 RootWindowContainer mRoot; 549 550 int mDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; 551 Rect mDockedStackCreateBounds; 552 553 private final SparseIntArray mTmpTaskIds = new SparseIntArray(); 554 555 boolean mForceResizableTasks = false; 556 boolean mSupportsPictureInPicture = false; 557 getDragLayerLocked()558 int getDragLayerLocked() { 559 return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 560 } 561 562 class RotationWatcher { 563 final IRotationWatcher mWatcher; 564 final IBinder.DeathRecipient mDeathRecipient; 565 final int mDisplayId; RotationWatcher(IRotationWatcher watcher, IBinder.DeathRecipient deathRecipient, int displayId)566 RotationWatcher(IRotationWatcher watcher, IBinder.DeathRecipient deathRecipient, 567 int displayId) { 568 mWatcher = watcher; 569 mDeathRecipient = deathRecipient; 570 mDisplayId = displayId; 571 } 572 } 573 574 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>(); 575 int mDeferredRotationPauseCount; 576 final WallpaperVisibilityListeners mWallpaperVisibilityListeners = 577 new WallpaperVisibilityListeners(); 578 579 int mSystemDecorLayer = 0; 580 final Rect mScreenRect = new Rect(); 581 582 boolean mDisplayFrozen = false; 583 long mDisplayFreezeTime = 0; 584 int mLastDisplayFreezeDuration = 0; 585 Object mLastFinishedFreezeSource = null; 586 boolean mWaitingForConfig = false; 587 boolean mSwitchingUser = false; 588 589 final static int WINDOWS_FREEZING_SCREENS_NONE = 0; 590 final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1; 591 final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2; 592 int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE; 593 594 boolean mClientFreezingScreen = false; 595 int mAppsFreezingScreen = 0; 596 597 int mLayoutSeq = 0; 598 599 // Last systemUiVisibility we received from status bar. 600 int mLastStatusBarVisibility = 0; 601 // Last systemUiVisibility we dispatched to windows. 602 int mLastDispatchedSystemUiVisibility = 0; 603 604 // State while inside of layoutAndPlaceSurfacesLocked(). 605 boolean mFocusMayChange; 606 607 // This is held as long as we have the screen frozen, to give us time to 608 // perform a rotation animation when turning off shows the lock screen which 609 // changes the orientation. 610 private final PowerManager.WakeLock mScreenFrozenLock; 611 612 final AppTransition mAppTransition; 613 boolean mSkipAppTransitionAnimation = false; 614 615 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>(); 616 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>(); 617 618 final UnknownAppVisibilityController mUnknownAppVisibilityController = 619 new UnknownAppVisibilityController(this); 620 final TaskSnapshotController mTaskSnapshotController; 621 622 boolean mIsTouchDevice; 623 624 final H mH = new H(); 625 626 /** 627 * Handler for things to run that have direct impact on an animation, i.e. animation tick, 628 * layout, starting window creation, whereas {@link H} runs things that are still important, but 629 * not as critical. 630 */ 631 final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper()); 632 633 WindowState mCurrentFocus = null; 634 WindowState mLastFocus = null; 635 636 /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */ 637 private final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>(); 638 /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */ 639 private final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>(); 640 641 /** This just indicates the window the input method is on top of, not 642 * necessarily the window its input is going to. */ 643 WindowState mInputMethodTarget = null; 644 645 /** If true hold off on modifying the animation layer of mInputMethodTarget */ 646 boolean mInputMethodTargetWaitingAnim; 647 648 WindowState mInputMethodWindow = null; 649 650 boolean mHardKeyboardAvailable; 651 WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 652 SettingsObserver mSettingsObserver; 653 654 // A count of the windows which are 'seamlessly rotated', e.g. a surface 655 // at an old orientation is being transformed. We freeze orientation updates 656 // while any windows are seamlessly rotated, so we need to track when this 657 // hits zero so we can apply deferred orientation updates. 658 int mSeamlessRotationCount = 0; 659 660 private final class SettingsObserver extends ContentObserver { 661 private final Uri mDisplayInversionEnabledUri = 662 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 663 private final Uri mWindowAnimationScaleUri = 664 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE); 665 private final Uri mTransitionAnimationScaleUri = 666 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE); 667 private final Uri mAnimationDurationScaleUri = 668 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE); 669 SettingsObserver()670 public SettingsObserver() { 671 super(new Handler()); 672 ContentResolver resolver = mContext.getContentResolver(); 673 resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this, 674 UserHandle.USER_ALL); 675 resolver.registerContentObserver(mWindowAnimationScaleUri, false, this, 676 UserHandle.USER_ALL); 677 resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this, 678 UserHandle.USER_ALL); 679 resolver.registerContentObserver(mAnimationDurationScaleUri, false, this, 680 UserHandle.USER_ALL); 681 } 682 683 @Override onChange(boolean selfChange, Uri uri)684 public void onChange(boolean selfChange, Uri uri) { 685 if (uri == null) { 686 return; 687 } 688 689 if (mDisplayInversionEnabledUri.equals(uri)) { 690 updateCircularDisplayMaskIfNeeded(); 691 } else { 692 @UpdateAnimationScaleMode 693 final int mode; 694 if (mWindowAnimationScaleUri.equals(uri)) { 695 mode = WINDOW_ANIMATION_SCALE; 696 } else if (mTransitionAnimationScaleUri.equals(uri)) { 697 mode = TRANSITION_ANIMATION_SCALE; 698 } else if (mAnimationDurationScaleUri.equals(uri)) { 699 mode = ANIMATION_DURATION_SCALE; 700 } else { 701 // Ignoring unrecognized content changes 702 return; 703 } 704 Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0); 705 mH.sendMessage(m); 706 } 707 } 708 } 709 710 boolean mAnimateWallpaperWithTarget; 711 712 // TODO: Move to RootWindowContainer 713 AppWindowToken mFocusedApp = null; 714 715 PowerManager mPowerManager; 716 PowerManagerInternal mPowerManagerInternal; 717 718 private float mWindowAnimationScaleSetting = 1.0f; 719 private float mTransitionAnimationScaleSetting = 1.0f; 720 private float mAnimatorDurationScaleSetting = 1.0f; 721 private boolean mAnimationsDisabled = false; 722 723 final InputManagerService mInputManager; 724 final DisplayManagerInternal mDisplayManagerInternal; 725 final DisplayManager mDisplayManager; 726 private final Display[] mDisplays; 727 728 // Indicates whether this device supports wide color gamut rendering 729 private boolean mHasWideColorGamutSupport; 730 731 // Who is holding the screen on. 732 private Session mHoldingScreenOn; 733 private PowerManager.WakeLock mHoldingScreenWakeLock; 734 735 boolean mTurnOnScreen; 736 737 // Whether or not a layout can cause a wake up when theater mode is enabled. 738 boolean mAllowTheaterModeWakeFromLayout; 739 740 TaskPositioner mTaskPositioner; 741 DragState mDragState = null; 742 743 // For frozen screen animations. 744 private int mExitAnimId, mEnterAnimId; 745 746 // The display that the rotation animation is applying to. 747 private int mFrozenDisplayId; 748 749 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 750 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 751 int mTransactionSequence; 752 753 final WindowAnimator mAnimator; 754 755 final BoundsAnimationController mBoundsAnimationController; 756 757 private final PointerEventDispatcher mPointerEventDispatcher; 758 759 private WindowContentFrameStats mTempWindowRenderStats; 760 761 final class DragInputEventReceiver extends InputEventReceiver { 762 // Set, if stylus button was down at the start of the drag. 763 private boolean mStylusButtonDownAtStart; 764 // Indicates the first event to check for button state. 765 private boolean mIsStartEvent = true; 766 // Set to true to ignore input events after the drag gesture is complete but the drag events 767 // are still being dispatched. 768 private boolean mMuteInput = false; 769 DragInputEventReceiver(InputChannel inputChannel, Looper looper)770 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { 771 super(inputChannel, looper); 772 } 773 774 @Override onInputEvent(InputEvent event, int displayId)775 public void onInputEvent(InputEvent event, int displayId) { 776 boolean handled = false; 777 try { 778 if (mDragState == null) { 779 // The drag has ended but the clean-up message has not been processed by 780 // window manager. Drop events that occur after this until window manager 781 // has a chance to clean-up the input handle. 782 handled = true; 783 return; 784 } 785 if (event instanceof MotionEvent 786 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 787 && !mMuteInput) { 788 final MotionEvent motionEvent = (MotionEvent)event; 789 boolean endDrag = false; 790 final float newX = motionEvent.getRawX(); 791 final float newY = motionEvent.getRawY(); 792 final boolean isStylusButtonDown = 793 (motionEvent.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0; 794 795 if (mIsStartEvent) { 796 if (isStylusButtonDown) { 797 // First event and the button was down, check for the button being 798 // lifted in the future, if that happens we'll drop the item. 799 mStylusButtonDownAtStart = true; 800 } 801 mIsStartEvent = false; 802 } 803 804 switch (motionEvent.getAction()) { 805 case MotionEvent.ACTION_DOWN: { 806 if (DEBUG_DRAG) { 807 Slog.w(TAG_WM, "Unexpected ACTION_DOWN in drag layer"); 808 } 809 } break; 810 811 case MotionEvent.ACTION_MOVE: { 812 if (mStylusButtonDownAtStart && !isStylusButtonDown) { 813 if (DEBUG_DRAG) Slog.d(TAG_WM, "Button no longer pressed; dropping at " 814 + newX + "," + newY); 815 mMuteInput = true; 816 synchronized (mWindowMap) { 817 endDrag = mDragState.notifyDropLw(newX, newY); 818 } 819 } else { 820 synchronized (mWindowMap) { 821 // move the surface and tell the involved window(s) where we are 822 mDragState.notifyMoveLw(newX, newY); 823 } 824 } 825 } break; 826 827 case MotionEvent.ACTION_UP: { 828 if (DEBUG_DRAG) Slog.d(TAG_WM, "Got UP on move channel; dropping at " 829 + newX + "," + newY); 830 mMuteInput = true; 831 synchronized (mWindowMap) { 832 endDrag = mDragState.notifyDropLw(newX, newY); 833 } 834 } break; 835 836 case MotionEvent.ACTION_CANCEL: { 837 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!"); 838 mMuteInput = true; 839 endDrag = true; 840 } break; 841 } 842 843 if (endDrag) { 844 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state"); 845 // tell all the windows that the drag has ended 846 synchronized (mWindowMap) { 847 // endDragLw will post back to looper to dispose the receiver 848 // since we still need the receiver for the last finishInputEvent. 849 mDragState.endDragLw(); 850 } 851 mStylusButtonDownAtStart = false; 852 mIsStartEvent = true; 853 } 854 855 handled = true; 856 } 857 } catch (Exception e) { 858 Slog.e(TAG_WM, "Exception caught by drag handleMotion", e); 859 } finally { 860 finishInputEvent(event, handled); 861 } 862 } 863 } 864 865 /** 866 * Whether the UI is currently running in touch mode (not showing 867 * navigational focus because the user is directly pressing the screen). 868 */ 869 boolean mInTouchMode; 870 871 private ViewServer mViewServer; 872 final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>(); 873 boolean mWindowsChanged = false; 874 875 public interface WindowChangeListener { windowsChanged()876 public void windowsChanged(); focusChanged()877 public void focusChanged(); 878 } 879 880 final Configuration mTempConfiguration = new Configuration(); 881 882 // If true, only the core apps and services are being launched because the device 883 // is in a special boot mode, such as being encrypted or waiting for a decryption password. 884 // For example, when this flag is true, there will be no wallpaper service. 885 final boolean mOnlyCore; 886 887 // List of clients without a transtiton animation that we notify once we are done transitioning 888 // since they won't be notified through the app window animator. 889 final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>(); 890 891 static WindowManagerThreadPriorityBooster sThreadPriorityBooster = 892 new WindowManagerThreadPriorityBooster(); 893 boostPriorityForLockedSection()894 static void boostPriorityForLockedSection() { 895 sThreadPriorityBooster.boost(); 896 } 897 resetPriorityAfterLockedSection()898 static void resetPriorityAfterLockedSection() { 899 sThreadPriorityBooster.reset(); 900 } 901 openSurfaceTransaction()902 void openSurfaceTransaction() { 903 try { 904 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction"); 905 synchronized (mWindowMap) { 906 if (mRoot.mSurfaceTraceEnabled) { 907 mRoot.mRemoteEventTrace.openSurfaceTransaction(); 908 } 909 SurfaceControl.openTransaction(); 910 } 911 } finally { 912 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 913 } 914 } 915 916 /** 917 * Closes a surface transaction. 918 */ closeSurfaceTransaction()919 void closeSurfaceTransaction() { 920 try { 921 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction"); 922 synchronized (mWindowMap) { 923 if (mRoot.mSurfaceTraceEnabled) { 924 mRoot.mRemoteEventTrace.closeSurfaceTransaction(); 925 } 926 SurfaceControl.closeTransaction(); 927 } 928 } finally { 929 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 930 } 931 } 932 933 /** 934 * Executes an empty animation transaction without holding the WM lock to simulate 935 * back-pressure. See {@link WindowAnimator#animate} why this is needed. 936 */ executeEmptyAnimationTransaction()937 void executeEmptyAnimationTransaction() { 938 try { 939 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction"); 940 synchronized (mWindowMap) { 941 if (mRoot.mSurfaceTraceEnabled) { 942 mRoot.mRemoteEventTrace.openSurfaceTransaction(); 943 } 944 SurfaceControl.openTransaction(); 945 SurfaceControl.setAnimationTransaction(); 946 if (mRoot.mSurfaceTraceEnabled) { 947 mRoot.mRemoteEventTrace.closeSurfaceTransaction(); 948 } 949 } 950 } finally { 951 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 952 } 953 try { 954 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction"); 955 SurfaceControl.closeTransaction(); 956 } finally { 957 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 958 } 959 } 960 961 /** Listener to notify activity manager about app transitions. */ 962 final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier 963 = new WindowManagerInternal.AppTransitionListener() { 964 965 @Override 966 public void onAppTransitionCancelledLocked(int transit) { 967 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_CANCELLED); 968 } 969 970 @Override 971 public void onAppTransitionFinishedLocked(IBinder token) { 972 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_FINISHED); 973 final AppWindowToken atoken = mRoot.getAppWindowToken(token); 974 if (atoken == null) { 975 return; 976 } 977 if (atoken.mLaunchTaskBehind) { 978 try { 979 mActivityManager.notifyLaunchTaskBehindComplete(atoken.token); 980 } catch (RemoteException e) { 981 } 982 atoken.mLaunchTaskBehind = false; 983 } else { 984 atoken.updateReportedVisibilityLocked(); 985 if (atoken.mEnteringAnimation) { 986 atoken.mEnteringAnimation = false; 987 try { 988 mActivityManager.notifyEnterAnimationComplete(atoken.token); 989 } catch (RemoteException e) { 990 } 991 } 992 } 993 } 994 }; 995 996 final ArrayList<AppFreezeListener> mAppFreezeListeners = new ArrayList<>(); 997 998 interface AppFreezeListener { onAppFreezeTimeout()999 void onAppFreezeTimeout(); 1000 } 1001 1002 private static WindowManagerService sInstance; getInstance()1003 static WindowManagerService getInstance() { 1004 return sInstance; 1005 } 1006 main(final Context context, final InputManagerService im, final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy)1007 public static WindowManagerService main(final Context context, final InputManagerService im, 1008 final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore, 1009 WindowManagerPolicy policy) { 1010 DisplayThread.getHandler().runWithScissors(() -> 1011 sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs, 1012 onlyCore, policy), 0); 1013 return sInstance; 1014 } 1015 initPolicy()1016 private void initPolicy() { 1017 UiThread.getHandler().runWithScissors(new Runnable() { 1018 @Override 1019 public void run() { 1020 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 1021 1022 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); 1023 } 1024 }, 0); 1025 } 1026 WindowManagerService(Context context, InputManagerService inputManager, boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy)1027 private WindowManagerService(Context context, InputManagerService inputManager, 1028 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore, 1029 WindowManagerPolicy policy) { 1030 installLock(this, INDEX_WINDOW); 1031 mRoot = new RootWindowContainer(this); 1032 mContext = context; 1033 mHaveInputMethods = haveInputMethods; 1034 mAllowBootMessages = showBootMsgs; 1035 mOnlyCore = onlyCore; 1036 mLimitedAlphaCompositing = context.getResources().getBoolean( 1037 com.android.internal.R.bool.config_sf_limitedAlpha); 1038 mHasPermanentDpad = context.getResources().getBoolean( 1039 com.android.internal.R.bool.config_hasPermanentDpad); 1040 mInTouchMode = context.getResources().getBoolean( 1041 com.android.internal.R.bool.config_defaultInTouchMode); 1042 mDrawLockTimeoutMillis = context.getResources().getInteger( 1043 com.android.internal.R.integer.config_drawLockTimeoutMillis); 1044 mAllowAnimationsInLowPowerMode = context.getResources().getBoolean( 1045 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode); 1046 mMaxUiWidth = context.getResources().getInteger( 1047 com.android.internal.R.integer.config_maxUiWidth); 1048 mInputManager = inputManager; // Must be before createDisplayContentLocked. 1049 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 1050 mDisplaySettings = new DisplaySettings(); 1051 mDisplaySettings.readSettingsLocked(); 1052 1053 mWindowPlacerLocked = new WindowSurfacePlacer(this); 1054 mPolicy = policy; 1055 mTaskSnapshotController = new TaskSnapshotController(this); 1056 1057 LocalServices.addService(WindowManagerPolicy.class, mPolicy); 1058 1059 if(mInputManager != null) { 1060 final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM); 1061 mPointerEventDispatcher = inputChannel != null 1062 ? new PointerEventDispatcher(inputChannel) : null; 1063 } else { 1064 mPointerEventDispatcher = null; 1065 } 1066 1067 mFxSession = new SurfaceSession(); 1068 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 1069 mDisplays = mDisplayManager.getDisplays(); 1070 for (Display display : mDisplays) { 1071 createDisplayContentLocked(display); 1072 } 1073 1074 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 1075 1076 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 1077 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 1078 1079 if (mPowerManagerInternal != null) { 1080 mPowerManagerInternal.registerLowPowerModeObserver( 1081 new PowerManagerInternal.LowPowerModeListener() { 1082 @Override 1083 public int getServiceType() { 1084 return ServiceType.ANIMATION; 1085 } 1086 1087 @Override 1088 public void onLowPowerModeChanged(PowerSaveState result) { 1089 synchronized (mWindowMap) { 1090 final boolean enabled = result.batterySaverEnabled; 1091 if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) { 1092 mAnimationsDisabled = enabled; 1093 dispatchNewAnimatorScaleLocked(null); 1094 } 1095 } 1096 } 1097 }); 1098 mAnimationsDisabled = mPowerManagerInternal 1099 .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled; 1100 } 1101 mScreenFrozenLock = mPowerManager.newWakeLock( 1102 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 1103 mScreenFrozenLock.setReferenceCounted(false); 1104 1105 mAppTransition = new AppTransition(context, this); 1106 mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier); 1107 1108 final AnimationHandler animationHandler = new AnimationHandler(); 1109 animationHandler.setProvider(new SfVsyncFrameCallbackProvider()); 1110 mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition, 1111 AnimationThread.getHandler(), animationHandler); 1112 1113 mActivityManager = ActivityManager.getService(); 1114 mAmInternal = LocalServices.getService(ActivityManagerInternal.class); 1115 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 1116 AppOpsManager.OnOpChangedInternalListener opListener = 1117 new AppOpsManager.OnOpChangedInternalListener() { 1118 @Override public void onOpChanged(int op, String packageName) { 1119 updateAppOpsState(); 1120 } 1121 }; 1122 mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener); 1123 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener); 1124 1125 // Get persisted window scale setting 1126 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 1127 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 1128 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 1129 Settings.Global.TRANSITION_ANIMATION_SCALE, 1130 context.getResources().getFloat( 1131 R.dimen.config_appTransitionAnimationDurationScaleDefault)); 1132 1133 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 1134 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 1135 1136 IntentFilter filter = new IntentFilter(); 1137 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 1138 filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 1139 // Listen to user removal broadcasts so that we can remove the user-specific data. 1140 filter.addAction(Intent.ACTION_USER_REMOVED); 1141 mContext.registerReceiver(mBroadcastReceiver, filter); 1142 1143 mSettingsObserver = new SettingsObserver(); 1144 1145 mHoldingScreenWakeLock = mPowerManager.newWakeLock( 1146 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM); 1147 mHoldingScreenWakeLock.setReferenceCounted(false); 1148 1149 mAnimator = new WindowAnimator(this); 1150 1151 mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean( 1152 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout); 1153 1154 1155 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 1156 initPolicy(); 1157 1158 // Add ourself to the Watchdog monitors. 1159 Watchdog.getInstance().addMonitor(this); 1160 1161 openSurfaceTransaction(); 1162 try { 1163 createWatermarkInTransaction(); 1164 } finally { 1165 closeSurfaceTransaction(); 1166 } 1167 1168 showEmulatorDisplayOverlayIfNeeded(); 1169 } 1170 getInputMonitor()1171 public InputMonitor getInputMonitor() { 1172 return mInputMonitor; 1173 } 1174 1175 @Override onTransact(int code, Parcel data, Parcel reply, int flags)1176 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 1177 throws RemoteException { 1178 try { 1179 return super.onTransact(code, data, reply, flags); 1180 } catch (RuntimeException e) { 1181 // The window manager only throws security exceptions, so let's 1182 // log all others. 1183 if (!(e instanceof SecurityException)) { 1184 Slog.wtf(TAG_WM, "Window Manager Crash", e); 1185 } 1186 throw e; 1187 } 1188 } 1189 excludeWindowTypeFromTapOutTask(int windowType)1190 static boolean excludeWindowTypeFromTapOutTask(int windowType) { 1191 switch (windowType) { 1192 case TYPE_STATUS_BAR: 1193 case TYPE_NAVIGATION_BAR: 1194 case TYPE_INPUT_METHOD_DIALOG: 1195 return true; 1196 } 1197 return false; 1198 } 1199 addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel)1200 public int addWindow(Session session, IWindow client, int seq, 1201 WindowManager.LayoutParams attrs, int viewVisibility, int displayId, 1202 Rect outContentInsets, Rect outStableInsets, Rect outOutsets, 1203 InputChannel outInputChannel) { 1204 int[] appOp = new int[1]; 1205 int res = mPolicy.checkAddPermission(attrs, appOp); 1206 if (res != WindowManagerGlobal.ADD_OKAY) { 1207 return res; 1208 } 1209 1210 boolean reportNewConfig = false; 1211 WindowState parentWindow = null; 1212 long origId; 1213 final int callingUid = Binder.getCallingUid(); 1214 final int type = attrs.type; 1215 1216 synchronized(mWindowMap) { 1217 if (!mDisplayReady) { 1218 throw new IllegalStateException("Display has not been initialialized"); 1219 } 1220 1221 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 1222 if (displayContent == null) { 1223 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: " 1224 + displayId + ". Aborting."); 1225 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1226 } 1227 if (!displayContent.hasAccess(session.mUid) 1228 && !mDisplayManagerInternal.isUidPresentOnDisplay(session.mUid, displayId)) { 1229 Slog.w(TAG_WM, "Attempted to add window to a display for which the application " 1230 + "does not have access: " + displayId + ". Aborting."); 1231 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1232 } 1233 1234 if (mWindowMap.containsKey(client.asBinder())) { 1235 Slog.w(TAG_WM, "Window " + client + " is already added"); 1236 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 1237 } 1238 1239 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 1240 parentWindow = windowForClientLocked(null, attrs.token, false); 1241 if (parentWindow == null) { 1242 Slog.w(TAG_WM, "Attempted to add window with token that is not a window: " 1243 + attrs.token + ". Aborting."); 1244 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 1245 } 1246 if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW 1247 && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) { 1248 Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: " 1249 + attrs.token + ". Aborting."); 1250 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 1251 } 1252 } 1253 1254 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) { 1255 Slog.w(TAG_WM, "Attempted to add private presentation window to a non-private display. Aborting."); 1256 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 1257 } 1258 1259 if (type == TYPE_PRESENTATION && !displayContent.getDisplay().isPublicPresentation()) { 1260 Slog.w(TAG_WM, 1261 "Attempted to add presentation window to a non-suitable display. " 1262 + "Aborting."); 1263 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1264 } 1265 1266 AppWindowToken atoken = null; 1267 final boolean hasParent = parentWindow != null; 1268 // Use existing parent window token for child windows since they go in the same token 1269 // as there parent window so we can apply the same policy on them. 1270 WindowToken token = displayContent.getWindowToken( 1271 hasParent ? parentWindow.mAttrs.token : attrs.token); 1272 // If this is a child window, we want to apply the same type checking rules as the 1273 // parent window type. 1274 final int rootType = hasParent ? parentWindow.mAttrs.type : type; 1275 1276 boolean addToastWindowRequiresToken = false; 1277 1278 if (token == null) { 1279 if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) { 1280 Slog.w(TAG_WM, "Attempted to add application window with unknown token " 1281 + attrs.token + ". Aborting."); 1282 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1283 } 1284 if (rootType == TYPE_INPUT_METHOD) { 1285 Slog.w(TAG_WM, "Attempted to add input method window with unknown token " 1286 + attrs.token + ". Aborting."); 1287 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1288 } 1289 if (rootType == TYPE_VOICE_INTERACTION) { 1290 Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token " 1291 + attrs.token + ". Aborting."); 1292 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1293 } 1294 if (rootType == TYPE_WALLPAPER) { 1295 Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token " 1296 + attrs.token + ". Aborting."); 1297 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1298 } 1299 if (rootType == TYPE_DREAM) { 1300 Slog.w(TAG_WM, "Attempted to add Dream window with unknown token " 1301 + attrs.token + ". Aborting."); 1302 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1303 } 1304 if (rootType == TYPE_QS_DIALOG) { 1305 Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token " 1306 + attrs.token + ". Aborting."); 1307 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1308 } 1309 if (rootType == TYPE_ACCESSIBILITY_OVERLAY) { 1310 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token " 1311 + attrs.token + ". Aborting."); 1312 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1313 } 1314 if (type == TYPE_TOAST) { 1315 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows. 1316 if (doesAddToastWindowRequireToken(attrs.packageName, callingUid, 1317 parentWindow)) { 1318 Slog.w(TAG_WM, "Attempted to add a toast window with unknown token " 1319 + attrs.token + ". Aborting."); 1320 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1321 } 1322 } 1323 final IBinder binder = attrs.token != null ? attrs.token : client.asBinder(); 1324 token = new WindowToken(this, binder, type, false, displayContent, 1325 session.mCanAddInternalSystemWindow); 1326 } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) { 1327 atoken = token.asAppWindowToken(); 1328 if (atoken == null) { 1329 Slog.w(TAG_WM, "Attempted to add window with non-application token " 1330 + token + ". Aborting."); 1331 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 1332 } else if (atoken.removed) { 1333 Slog.w(TAG_WM, "Attempted to add window with exiting application token " 1334 + token + ". Aborting."); 1335 return WindowManagerGlobal.ADD_APP_EXITING; 1336 } 1337 } else if (rootType == TYPE_INPUT_METHOD) { 1338 if (token.windowType != TYPE_INPUT_METHOD) { 1339 Slog.w(TAG_WM, "Attempted to add input method window with bad token " 1340 + attrs.token + ". Aborting."); 1341 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1342 } 1343 } else if (rootType == TYPE_VOICE_INTERACTION) { 1344 if (token.windowType != TYPE_VOICE_INTERACTION) { 1345 Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token " 1346 + attrs.token + ". Aborting."); 1347 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1348 } 1349 } else if (rootType == TYPE_WALLPAPER) { 1350 if (token.windowType != TYPE_WALLPAPER) { 1351 Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token " 1352 + attrs.token + ". Aborting."); 1353 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1354 } 1355 } else if (rootType == TYPE_DREAM) { 1356 if (token.windowType != TYPE_DREAM) { 1357 Slog.w(TAG_WM, "Attempted to add Dream window with bad token " 1358 + attrs.token + ". Aborting."); 1359 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1360 } 1361 } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) { 1362 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) { 1363 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token " 1364 + attrs.token + ". Aborting."); 1365 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1366 } 1367 } else if (type == TYPE_TOAST) { 1368 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows. 1369 addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName, 1370 callingUid, parentWindow); 1371 if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) { 1372 Slog.w(TAG_WM, "Attempted to add a toast window with bad token " 1373 + attrs.token + ". Aborting."); 1374 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1375 } 1376 } else if (type == TYPE_QS_DIALOG) { 1377 if (token.windowType != TYPE_QS_DIALOG) { 1378 Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token " 1379 + attrs.token + ". Aborting."); 1380 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1381 } 1382 } else if (token.asAppWindowToken() != null) { 1383 Slog.w(TAG_WM, "Non-null appWindowToken for system window of rootType=" + rootType); 1384 // It is not valid to use an app token with other system types; we will 1385 // instead make a new token for it (as if null had been passed in for the token). 1386 attrs.token = null; 1387 token = new WindowToken(this, client.asBinder(), type, false, displayContent, 1388 session.mCanAddInternalSystemWindow); 1389 } 1390 1391 final WindowState win = new WindowState(this, session, client, token, parentWindow, 1392 appOp[0], seq, attrs, viewVisibility, session.mUid, 1393 session.mCanAddInternalSystemWindow); 1394 if (win.mDeathRecipient == null) { 1395 // Client has apparently died, so there is no reason to 1396 // continue. 1397 Slog.w(TAG_WM, "Adding window client " + client.asBinder() 1398 + " that is dead, aborting."); 1399 return WindowManagerGlobal.ADD_APP_EXITING; 1400 } 1401 1402 if (win.getDisplayContent() == null) { 1403 Slog.w(TAG_WM, "Adding window to Display that has been removed."); 1404 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1405 } 1406 1407 mPolicy.adjustWindowParamsLw(win.mAttrs); 1408 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 1409 1410 res = mPolicy.prepareAddWindowLw(win, attrs); 1411 if (res != WindowManagerGlobal.ADD_OKAY) { 1412 return res; 1413 } 1414 1415 final boolean openInputChannels = (outInputChannel != null 1416 && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0); 1417 if (openInputChannels) { 1418 win.openInputChannel(outInputChannel); 1419 } 1420 1421 // If adding a toast requires a token for this app we always schedule hiding 1422 // toast windows to make sure they don't stick around longer then necessary. 1423 // We hide instead of remove such windows as apps aren't prepared to handle 1424 // windows being removed under them. 1425 // 1426 // If the app is older it can add toasts without a token and hence overlay 1427 // other apps. To be maximally compatible with these apps we will hide the 1428 // window after the toast timeout only if the focused window is from another 1429 // UID, otherwise we allow unlimited duration. When a UID looses focus we 1430 // schedule hiding all of its toast windows. 1431 if (type == TYPE_TOAST) { 1432 if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) { 1433 Slog.w(TAG_WM, "Adding more than one toast window for UID at a time."); 1434 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 1435 } 1436 // Make sure this happens before we moved focus as one can make the 1437 // toast focusable to force it not being hidden after the timeout. 1438 // Focusable toasts are always timed out to prevent a focused app to 1439 // show a focusable toasts while it has focus which will be kept on 1440 // the screen after the activity goes away. 1441 if (addToastWindowRequiresToken 1442 || (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0 1443 || mCurrentFocus == null 1444 || mCurrentFocus.mOwnerUid != callingUid) { 1445 mH.sendMessageDelayed( 1446 mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win), 1447 win.mAttrs.hideTimeoutMilliseconds); 1448 } 1449 } 1450 1451 // From now on, no exceptions or errors allowed! 1452 1453 res = WindowManagerGlobal.ADD_OKAY; 1454 if (mCurrentFocus == null) { 1455 mWinAddedSinceNullFocus.add(win); 1456 } 1457 1458 if (excludeWindowTypeFromTapOutTask(type)) { 1459 displayContent.mTapExcludedWindows.add(win); 1460 } 1461 1462 origId = Binder.clearCallingIdentity(); 1463 1464 win.attach(); 1465 mWindowMap.put(client.asBinder(), win); 1466 if (win.mAppOp != AppOpsManager.OP_NONE) { 1467 int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), 1468 win.getOwningPackage()); 1469 if ((startOpResult != AppOpsManager.MODE_ALLOWED) && 1470 (startOpResult != AppOpsManager.MODE_DEFAULT)) { 1471 win.setAppOpVisibilityLw(false); 1472 } 1473 } 1474 1475 final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty(); 1476 win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows); 1477 1478 final AppWindowToken aToken = token.asAppWindowToken(); 1479 if (type == TYPE_APPLICATION_STARTING && aToken != null) { 1480 aToken.startingWindow = win; 1481 if (DEBUG_STARTING_WINDOW) Slog.v (TAG_WM, "addWindow: " + aToken 1482 + " startingWindow=" + win); 1483 } 1484 1485 boolean imMayMove = true; 1486 1487 win.mToken.addWindow(win); 1488 if (type == TYPE_INPUT_METHOD) { 1489 win.mGivenInsetsPending = true; 1490 setInputMethodWindowLocked(win); 1491 imMayMove = false; 1492 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 1493 displayContent.computeImeTarget(true /* updateImeTarget */); 1494 imMayMove = false; 1495 } else { 1496 if (type == TYPE_WALLPAPER) { 1497 displayContent.mWallpaperController.clearLastWallpaperTimeoutTime(); 1498 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1499 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 1500 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1501 } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) { 1502 // If there is currently a wallpaper being shown, and 1503 // the base layer of the new window is below the current 1504 // layer of the target window, then adjust the wallpaper. 1505 // This is to avoid a new window being placed between the 1506 // wallpaper and its target. 1507 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1508 } 1509 } 1510 1511 // If the window is being added to a stack that's currently adjusted for IME, 1512 // make sure to apply the same adjust to this new window. 1513 win.applyAdjustForImeIfNeeded(); 1514 1515 if (type == TYPE_DOCK_DIVIDER) { 1516 mRoot.getDisplayContent(displayId).getDockedDividerController().setWindow(win); 1517 } 1518 1519 final WindowStateAnimator winAnimator = win.mWinAnimator; 1520 winAnimator.mEnterAnimationPending = true; 1521 winAnimator.mEnteringAnimation = true; 1522 // Check if we need to prepare a transition for replacing window first. 1523 if (atoken != null && atoken.isVisible() 1524 && !prepareWindowReplacementTransition(atoken)) { 1525 // If not, check if need to set up a dummy transition during display freeze 1526 // so that the unfreeze wait for the apps to draw. This might be needed if 1527 // the app is relaunching. 1528 prepareNoneTransitionForRelaunching(atoken); 1529 } 1530 1531 if (displayContent.isDefaultDisplay) { 1532 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 1533 final Rect taskBounds; 1534 if (atoken != null && atoken.getTask() != null) { 1535 taskBounds = mTmpRect; 1536 atoken.getTask().getBounds(mTmpRect); 1537 } else { 1538 taskBounds = null; 1539 } 1540 if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, displayInfo.rotation, 1541 displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets, 1542 outStableInsets, outOutsets)) { 1543 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR; 1544 } 1545 } else { 1546 outContentInsets.setEmpty(); 1547 outStableInsets.setEmpty(); 1548 } 1549 1550 if (mInTouchMode) { 1551 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 1552 } 1553 if (win.mAppToken == null || !win.mAppToken.isClientHidden()) { 1554 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 1555 } 1556 1557 mInputMonitor.setUpdateInputWindowsNeededLw(); 1558 1559 boolean focusChanged = false; 1560 if (win.canReceiveKeys()) { 1561 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 1562 false /*updateInputWindows*/); 1563 if (focusChanged) { 1564 imMayMove = false; 1565 } 1566 } 1567 1568 if (imMayMove) { 1569 displayContent.computeImeTarget(true /* updateImeTarget */); 1570 } 1571 1572 // Don't do layout here, the window must call 1573 // relayout to be displayed, so we'll do it there. 1574 displayContent.assignWindowLayers(false /* setLayoutNeeded */); 1575 1576 if (focusChanged) { 1577 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/); 1578 } 1579 mInputMonitor.updateInputWindowsLw(false /*force*/); 1580 1581 if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client " 1582 + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5)); 1583 1584 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false, displayId)) { 1585 reportNewConfig = true; 1586 } 1587 } 1588 1589 if (reportNewConfig) { 1590 sendNewConfiguration(displayId); 1591 } 1592 1593 Binder.restoreCallingIdentity(origId); 1594 1595 return res; 1596 } 1597 doesAddToastWindowRequireToken(String packageName, int callingUid, WindowState attachedWindow)1598 private boolean doesAddToastWindowRequireToken(String packageName, int callingUid, 1599 WindowState attachedWindow) { 1600 // Try using the target SDK of the root window 1601 if (attachedWindow != null) { 1602 return attachedWindow.mAppToken != null 1603 && attachedWindow.mAppToken.mTargetSdk >= Build.VERSION_CODES.O; 1604 } else { 1605 // Otherwise, look at the package 1606 try { 1607 ApplicationInfo appInfo = mContext.getPackageManager() 1608 .getApplicationInfoAsUser(packageName, 0, 1609 UserHandle.getUserId(callingUid)); 1610 if (appInfo.uid != callingUid) { 1611 throw new SecurityException("Package " + packageName + " not in UID " 1612 + callingUid); 1613 } 1614 if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O) { 1615 return true; 1616 } 1617 } catch (PackageManager.NameNotFoundException e) { 1618 /* ignore */ 1619 } 1620 } 1621 return false; 1622 } 1623 1624 /** 1625 * Returns true if we're done setting up any transitions. 1626 */ prepareWindowReplacementTransition(AppWindowToken atoken)1627 private boolean prepareWindowReplacementTransition(AppWindowToken atoken) { 1628 atoken.clearAllDrawn(); 1629 final WindowState replacedWindow = atoken.getReplacingWindow(); 1630 if (replacedWindow == null) { 1631 // We expect to already receive a request to remove the old window. If it did not 1632 // happen, let's just simply add a window. 1633 return false; 1634 } 1635 // We use the visible frame, because we want the animation to morph the window from what 1636 // was visible to the user to the final destination of the new window. 1637 Rect frame = replacedWindow.mVisibleFrame; 1638 // We treat this as if this activity was opening, so we can trigger the app transition 1639 // animation and piggy-back on existing transition animation infrastructure. 1640 mOpeningApps.add(atoken); 1641 prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT); 1642 mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top, 1643 frame.width(), frame.height()); 1644 executeAppTransition(); 1645 return true; 1646 } 1647 prepareNoneTransitionForRelaunching(AppWindowToken atoken)1648 private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) { 1649 // Set up a none-transition and add the app to opening apps, so that the display 1650 // unfreeze wait for the apps to be drawn. 1651 // Note that if the display unfroze already because app unfreeze timed out, 1652 // we don't set up the transition anymore and just let it go. 1653 if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) { 1654 mOpeningApps.add(atoken); 1655 prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT); 1656 executeAppTransition(); 1657 } 1658 } 1659 1660 /** 1661 * Returns whether screen capture is disabled for all windows of a specific user. 1662 */ isScreenCaptureDisabledLocked(int userId)1663 boolean isScreenCaptureDisabledLocked(int userId) { 1664 Boolean disabled = mScreenCaptureDisabled.get(userId); 1665 if (disabled == null) { 1666 return false; 1667 } 1668 return disabled; 1669 } 1670 isSecureLocked(WindowState w)1671 boolean isSecureLocked(WindowState w) { 1672 if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) { 1673 return true; 1674 } 1675 if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) { 1676 return true; 1677 } 1678 return false; 1679 } 1680 1681 @Override enableSurfaceTrace(ParcelFileDescriptor pfd)1682 public void enableSurfaceTrace(ParcelFileDescriptor pfd) { 1683 final int callingUid = Binder.getCallingUid(); 1684 if (callingUid != SHELL_UID && callingUid != ROOT_UID) { 1685 throw new SecurityException("Only shell can call enableSurfaceTrace"); 1686 } 1687 1688 synchronized (mWindowMap) { 1689 mRoot.enableSurfaceTrace(pfd); 1690 } 1691 } 1692 1693 @Override disableSurfaceTrace()1694 public void disableSurfaceTrace() { 1695 final int callingUid = Binder.getCallingUid(); 1696 if (callingUid != SHELL_UID && callingUid != ROOT_UID && 1697 callingUid != SYSTEM_UID) { 1698 throw new SecurityException("Only shell can call disableSurfaceTrace"); 1699 } 1700 synchronized (mWindowMap) { 1701 mRoot.disableSurfaceTrace(); 1702 } 1703 } 1704 1705 /** 1706 * Set mScreenCaptureDisabled for specific user 1707 */ 1708 @Override setScreenCaptureDisabled(int userId, boolean disabled)1709 public void setScreenCaptureDisabled(int userId, boolean disabled) { 1710 int callingUid = Binder.getCallingUid(); 1711 if (callingUid != SYSTEM_UID) { 1712 throw new SecurityException("Only system can call setScreenCaptureDisabled."); 1713 } 1714 1715 synchronized(mWindowMap) { 1716 mScreenCaptureDisabled.put(userId, disabled); 1717 // Update secure surface for all windows belonging to this user. 1718 mRoot.setSecureSurfaceState(userId, disabled); 1719 } 1720 } 1721 removeWindow(Session session, IWindow client)1722 void removeWindow(Session session, IWindow client) { 1723 synchronized(mWindowMap) { 1724 WindowState win = windowForClientLocked(session, client, false); 1725 if (win == null) { 1726 return; 1727 } 1728 win.removeIfPossible(); 1729 } 1730 } 1731 1732 /** 1733 * Performs some centralized bookkeeping clean-up on the window that is being removed. 1734 * NOTE: Should only be called from {@link WindowState#removeImmediately()} 1735 * TODO: Maybe better handled with a method {@link WindowContainer#removeChild} if we can 1736 * figure-out a good way to have all parents of a WindowState doing the same thing without 1737 * forgetting to add the wiring when a new parent of WindowState is added. 1738 */ postWindowRemoveCleanupLocked(WindowState win)1739 void postWindowRemoveCleanupLocked(WindowState win) { 1740 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "postWindowRemoveCleanupLocked: " + win); 1741 mWindowMap.remove(win.mClient.asBinder()); 1742 if (win.mAppOp != AppOpsManager.OP_NONE) { 1743 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); 1744 } 1745 1746 if (mCurrentFocus == null) { 1747 mWinRemovedSinceNullFocus.add(win); 1748 } 1749 mPendingRemove.remove(win); 1750 mResizingWindows.remove(win); 1751 updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */); 1752 mWindowsChanged = true; 1753 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win); 1754 1755 if (mInputMethodWindow == win) { 1756 setInputMethodWindowLocked(null); 1757 } 1758 1759 final WindowToken token = win.mToken; 1760 final AppWindowToken atoken = win.mAppToken; 1761 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token); 1762 // Window will already be removed from token before this post clean-up method is called. 1763 if (token.isEmpty()) { 1764 if (!token.mPersistOnEmpty) { 1765 token.removeImmediately(); 1766 } else if (atoken != null) { 1767 // TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after 1768 // re-factor. 1769 atoken.firstWindowDrawn = false; 1770 atoken.clearAllDrawn(); 1771 final TaskStack stack = atoken.getStack(); 1772 if (stack != null) { 1773 stack.mExitingAppTokens.remove(atoken); 1774 } 1775 } 1776 } 1777 1778 if (atoken != null) { 1779 atoken.postWindowRemoveStartingWindowCleanup(win); 1780 } 1781 1782 final DisplayContent dc = win.getDisplayContent(); 1783 if (win.mAttrs.type == TYPE_WALLPAPER) { 1784 dc.mWallpaperController.clearLastWallpaperTimeoutTime(); 1785 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1786 } else if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 1787 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1788 } 1789 1790 if (dc != null && !mWindowPlacerLocked.isInLayout()) { 1791 dc.assignWindowLayers(true /* setLayoutNeeded */); 1792 mWindowPlacerLocked.performSurfacePlacement(); 1793 if (win.mAppToken != null) { 1794 win.mAppToken.updateReportedVisibilityLocked(); 1795 } 1796 } 1797 1798 mInputMonitor.updateInputWindowsLw(true /*force*/); 1799 } 1800 setInputMethodWindowLocked(WindowState win)1801 void setInputMethodWindowLocked(WindowState win) { 1802 mInputMethodWindow = win; 1803 final DisplayContent dc = win != null 1804 ? win.getDisplayContent() : getDefaultDisplayContentLocked(); 1805 dc.computeImeTarget(true /* updateImeTarget */); 1806 } 1807 updateAppOpsState()1808 private void updateAppOpsState() { 1809 synchronized(mWindowMap) { 1810 mRoot.updateAppOpsState(); 1811 } 1812 } 1813 logSurface(WindowState w, String msg, boolean withStackTrace)1814 static void logSurface(WindowState w, String msg, boolean withStackTrace) { 1815 String str = " SURFACE " + msg + ": " + w; 1816 if (withStackTrace) { 1817 logWithStack(TAG, str); 1818 } else { 1819 Slog.i(TAG_WM, str); 1820 } 1821 } 1822 logSurface(SurfaceControl s, String title, String msg)1823 static void logSurface(SurfaceControl s, String title, String msg) { 1824 String str = " SURFACE " + s + ": " + msg + " / " + title; 1825 Slog.i(TAG_WM, str); 1826 } 1827 logWithStack(String tag, String s)1828 static void logWithStack(String tag, String s) { 1829 RuntimeException e = null; 1830 if (SHOW_STACK_CRAWLS) { 1831 e = new RuntimeException(); 1832 e.fillInStackTrace(); 1833 } 1834 Slog.i(tag, s, e); 1835 } 1836 setTransparentRegionWindow(Session session, IWindow client, Region region)1837 void setTransparentRegionWindow(Session session, IWindow client, Region region) { 1838 long origId = Binder.clearCallingIdentity(); 1839 try { 1840 synchronized (mWindowMap) { 1841 WindowState w = windowForClientLocked(session, client, false); 1842 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1843 "transparentRegionHint=" + region, false); 1844 1845 if ((w != null) && w.mHasSurface) { 1846 w.mWinAnimator.setTransparentRegionHintLocked(region); 1847 } 1848 } 1849 } finally { 1850 Binder.restoreCallingIdentity(origId); 1851 } 1852 } 1853 setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableRegion)1854 void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets, 1855 Rect visibleInsets, Region touchableRegion) { 1856 long origId = Binder.clearCallingIdentity(); 1857 try { 1858 synchronized (mWindowMap) { 1859 WindowState w = windowForClientLocked(session, client, false); 1860 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w 1861 + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets 1862 + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets 1863 + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion 1864 + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets); 1865 if (w != null) { 1866 w.mGivenInsetsPending = false; 1867 w.mGivenContentInsets.set(contentInsets); 1868 w.mGivenVisibleInsets.set(visibleInsets); 1869 w.mGivenTouchableRegion.set(touchableRegion); 1870 w.mTouchableInsets = touchableInsets; 1871 if (w.mGlobalScale != 1) { 1872 w.mGivenContentInsets.scale(w.mGlobalScale); 1873 w.mGivenVisibleInsets.scale(w.mGlobalScale); 1874 w.mGivenTouchableRegion.scale(w.mGlobalScale); 1875 } 1876 w.setDisplayLayoutNeeded(); 1877 mWindowPlacerLocked.performSurfacePlacement(); 1878 } 1879 } 1880 } finally { 1881 Binder.restoreCallingIdentity(origId); 1882 } 1883 } 1884 getWindowDisplayFrame(Session session, IWindow client, Rect outDisplayFrame)1885 public void getWindowDisplayFrame(Session session, IWindow client, 1886 Rect outDisplayFrame) { 1887 synchronized(mWindowMap) { 1888 WindowState win = windowForClientLocked(session, client, false); 1889 if (win == null) { 1890 outDisplayFrame.setEmpty(); 1891 return; 1892 } 1893 outDisplayFrame.set(win.mDisplayFrame); 1894 } 1895 } 1896 onRectangleOnScreenRequested(IBinder token, Rect rectangle)1897 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 1898 synchronized (mWindowMap) { 1899 if (mAccessibilityController != null) { 1900 WindowState window = mWindowMap.get(token); 1901 //TODO (multidisplay): Magnification is supported only for the default display. 1902 if (window != null && window.getDisplayId() == DEFAULT_DISPLAY) { 1903 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle); 1904 } 1905 } 1906 } 1907 } 1908 getWindowId(IBinder token)1909 public IWindowId getWindowId(IBinder token) { 1910 synchronized (mWindowMap) { 1911 WindowState window = mWindowMap.get(token); 1912 return window != null ? window.mWindowId : null; 1913 } 1914 } 1915 pokeDrawLock(Session session, IBinder token)1916 public void pokeDrawLock(Session session, IBinder token) { 1917 synchronized (mWindowMap) { 1918 WindowState window = windowForClientLocked(session, token, false); 1919 if (window != null) { 1920 window.pokeDrawLockLw(mDrawLockTimeoutMillis); 1921 } 1922 } 1923 } 1924 relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame, MergedConfiguration mergedConfiguration, Surface outSurface)1925 public int relayoutWindow(Session session, IWindow client, int seq, 1926 WindowManager.LayoutParams attrs, int requestedWidth, 1927 int requestedHeight, int viewVisibility, int flags, 1928 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, 1929 Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame, 1930 MergedConfiguration mergedConfiguration, Surface outSurface) { 1931 int result = 0; 1932 boolean configChanged; 1933 boolean hasStatusBarPermission = 1934 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 1935 == PackageManager.PERMISSION_GRANTED; 1936 1937 long origId = Binder.clearCallingIdentity(); 1938 final int displayId; 1939 synchronized(mWindowMap) { 1940 WindowState win = windowForClientLocked(session, client, false); 1941 if (win == null) { 1942 return 0; 1943 } 1944 displayId = win.getDisplayId(); 1945 1946 WindowStateAnimator winAnimator = win.mWinAnimator; 1947 if (viewVisibility != View.GONE) { 1948 win.setRequestedSize(requestedWidth, requestedHeight); 1949 } 1950 1951 int attrChanges = 0; 1952 int flagChanges = 0; 1953 if (attrs != null) { 1954 mPolicy.adjustWindowParamsLw(attrs); 1955 // if they don't have the permission, mask out the status bar bits 1956 if (seq == win.mSeq) { 1957 int systemUiVisibility = attrs.systemUiVisibility 1958 | attrs.subtreeSystemUiVisibility; 1959 if ((systemUiVisibility & DISABLE_MASK) != 0) { 1960 if (!hasStatusBarPermission) { 1961 systemUiVisibility &= ~DISABLE_MASK; 1962 } 1963 } 1964 win.mSystemUiVisibility = systemUiVisibility; 1965 } 1966 if (win.mAttrs.type != attrs.type) { 1967 throw new IllegalArgumentException( 1968 "Window type can not be changed after the window is added."); 1969 } 1970 1971 // Odd choice but less odd than embedding in copyFrom() 1972 if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY) 1973 != 0) { 1974 attrs.x = win.mAttrs.x; 1975 attrs.y = win.mAttrs.y; 1976 attrs.width = win.mAttrs.width; 1977 attrs.height = win.mAttrs.height; 1978 } 1979 1980 flagChanges = win.mAttrs.flags ^= attrs.flags; 1981 attrChanges = win.mAttrs.copyFrom(attrs); 1982 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED 1983 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) { 1984 win.mLayoutNeeded = true; 1985 } 1986 if (win.mAppToken != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0 1987 || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) { 1988 win.mAppToken.checkKeyguardFlagsChanged(); 1989 } 1990 if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0) 1991 && (mAccessibilityController != null) 1992 && (win.getDisplayId() == DEFAULT_DISPLAY)) { 1993 // No move or resize, but the controller checks for title changes as well 1994 mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 1995 } 1996 1997 if ((flagChanges & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) { 1998 updateNonSystemOverlayWindowsVisibilityIfNeeded( 1999 win, win.mWinAnimator.getShown()); 2000 } 2001 } 2002 2003 if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility 2004 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs); 2005 winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0; 2006 win.mEnforceSizeCompat = 2007 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0; 2008 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { 2009 winAnimator.mAlpha = attrs.alpha; 2010 } 2011 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight); 2012 2013 if (win.mAttrs.surfaceInsets.left != 0 2014 || win.mAttrs.surfaceInsets.top != 0 2015 || win.mAttrs.surfaceInsets.right != 0 2016 || win.mAttrs.surfaceInsets.bottom != 0) { 2017 winAnimator.setOpaqueLocked(false); 2018 } 2019 2020 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0; 2021 final boolean isDefaultDisplay = win.isDefaultDisplay(); 2022 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility 2023 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0) 2024 || (!win.mRelayoutCalled)); 2025 2026 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility 2027 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0; 2028 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0; 2029 if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) { 2030 winAnimator.mSurfaceController.setSecure(isSecureLocked(win)); 2031 } 2032 2033 win.mRelayoutCalled = true; 2034 win.mInRelayout = true; 2035 2036 final int oldVisibility = win.mViewVisibility; 2037 win.mViewVisibility = viewVisibility; 2038 if (DEBUG_SCREEN_ON) { 2039 RuntimeException stack = new RuntimeException(); 2040 stack.fillInStackTrace(); 2041 Slog.i(TAG_WM, "Relayout " + win + ": oldVis=" + oldVisibility 2042 + " newVis=" + viewVisibility, stack); 2043 } 2044 2045 // We should only relayout if the view is visible, it is a starting window, or the 2046 // associated appToken is not hidden. 2047 final boolean shouldRelayout = viewVisibility == View.VISIBLE && 2048 (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING 2049 || !win.mAppToken.isClientHidden()); 2050 2051 if (shouldRelayout) { 2052 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1"); 2053 2054 // We are about to create a surface, but we didn't run a layout yet. So better run 2055 // a layout now that we already know the right size, as a resize call will make the 2056 // surface transaction blocking until next vsync and slow us down. 2057 // TODO: Ideally we'd create the surface after running layout a bit further down, 2058 // but moving this seems to be too risky at this point in the release. 2059 if (win.mLayoutSeq == -1) { 2060 win.setDisplayLayoutNeeded(); 2061 mWindowPlacerLocked.performSurfacePlacement(true); 2062 } 2063 result = win.relayoutVisibleWindow(result, attrChanges, oldVisibility); 2064 2065 try { 2066 result = createSurfaceControl(outSurface, result, win, winAnimator); 2067 } catch (Exception e) { 2068 mInputMonitor.updateInputWindowsLw(true /*force*/); 2069 2070 Slog.w(TAG_WM, "Exception thrown when creating surface for client " 2071 + client + " (" + win.mAttrs.getTitle() + ")", 2072 e); 2073 Binder.restoreCallingIdentity(origId); 2074 return 0; 2075 } 2076 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { 2077 focusMayChange = isDefaultDisplay; 2078 } 2079 if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) { 2080 setInputMethodWindowLocked(win); 2081 imMayMove = true; 2082 } 2083 win.adjustStartingWindowFlags(); 2084 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2085 } else { 2086 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_2"); 2087 2088 winAnimator.mEnterAnimationPending = false; 2089 winAnimator.mEnteringAnimation = false; 2090 final boolean usingSavedSurfaceBeforeVisible = 2091 oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface(); 2092 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 2093 if (winAnimator.hasSurface() && !win.mAnimatingExit 2094 && usingSavedSurfaceBeforeVisible) { 2095 Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win); 2096 } 2097 } 2098 2099 if (winAnimator.hasSurface() && !win.mAnimatingExit 2100 && !usingSavedSurfaceBeforeVisible) { 2101 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win 2102 + ": mAnimatingExit=" + win.mAnimatingExit); 2103 // If we are not currently running the exit animation, we 2104 // need to see about starting one. 2105 // We don't want to animate visibility of windows which are pending 2106 // replacement. In the case of activity relaunch child windows 2107 // could request visibility changes as they are detached from the main 2108 // application window during the tear down process. If we satisfied 2109 // these visibility changes though, we would cause a visual glitch 2110 // hiding the window before it's replacement was available. 2111 // So we just do nothing on our side. 2112 if (!win.mWillReplaceWindow) { 2113 focusMayChange = tryStartExitingAnimation( 2114 win, winAnimator, isDefaultDisplay, focusMayChange); 2115 } 2116 result |= RELAYOUT_RES_SURFACE_CHANGED; 2117 } 2118 if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) { 2119 // We already told the client to go invisible, but the message may not be 2120 // handled yet, or it might want to draw a last frame. If we already have a 2121 // surface, let the client use that, but don't create new surface at this point. 2122 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface"); 2123 winAnimator.mSurfaceController.getSurface(outSurface); 2124 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2125 } else { 2126 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win); 2127 2128 try { 2129 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_" 2130 + win.mAttrs.getTitle()); 2131 outSurface.release(); 2132 } finally { 2133 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2134 } 2135 } 2136 2137 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2138 } 2139 2140 if (focusMayChange) { 2141 //System.out.println("Focus may change: " + win.mAttrs.getTitle()); 2142 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 2143 false /*updateInputWindows*/)) { 2144 imMayMove = false; 2145 } 2146 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus); 2147 } 2148 2149 // updateFocusedWindowLocked() already assigned layers so we only need to 2150 // reassign them at this point if the IM window state gets shuffled 2151 boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0; 2152 final DisplayContent dc = win.getDisplayContent(); 2153 if (imMayMove) { 2154 dc.computeImeTarget(true /* updateImeTarget */); 2155 if (toBeDisplayed) { 2156 // Little hack here -- we -should- be able to rely on the function to return 2157 // true if the IME has moved and needs its layer recomputed. However, if the IME 2158 // was hidden and isn't actually moved in the list, its layer may be out of data 2159 // so we make sure to recompute it. 2160 dc.assignWindowLayers(false /* setLayoutNeeded */); 2161 } 2162 } 2163 2164 if (wallpaperMayMove) { 2165 win.getDisplayContent().pendingLayoutChanges |= 2166 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2167 } 2168 2169 if (win.mAppToken != null) { 2170 mUnknownAppVisibilityController.notifyRelayouted(win.mAppToken); 2171 } 2172 2173 win.setDisplayLayoutNeeded(); 2174 win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; 2175 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, 2176 "relayoutWindow: updateOrientationFromAppTokens"); 2177 configChanged = updateOrientationFromAppTokensLocked(false, displayId); 2178 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2179 2180 // We may be deferring layout passes at the moment, but since the client is interested 2181 // in the new out values right now we need to force a layout. 2182 mWindowPlacerLocked.performSurfacePlacement(true /* force */); 2183 if (toBeDisplayed && win.mIsWallpaper) { 2184 DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo(); 2185 dc.mWallpaperController.updateWallpaperOffset( 2186 win, displayInfo.logicalWidth, displayInfo.logicalHeight, false); 2187 } 2188 if (win.mAppToken != null) { 2189 win.mAppToken.updateReportedVisibilityLocked(); 2190 } 2191 if (winAnimator.mReportSurfaceResized) { 2192 winAnimator.mReportSurfaceResized = false; 2193 result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED; 2194 } 2195 if (mPolicy.isNavBarForcedShownLw(win)) { 2196 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR; 2197 } 2198 if (!win.isGoneForLayoutLw()) { 2199 win.mResizedWhileGone = false; 2200 } 2201 2202 // We must always send the latest {@link MergedConfiguration}, regardless of whether we 2203 // have already reported it. The client might not have processed the previous value yet 2204 // and needs process it before handling the corresponding window frame. the variable 2205 // {@code mergedConfiguration} is an out parameter that will be passed back to the 2206 // client over IPC and checked there. 2207 // Note: in the cases where the window is tied to an activity, we should not send a 2208 // configuration update when the window has requested to be hidden. Doing so can lead 2209 // to the client erroneously accepting a configuration that would have otherwise caused 2210 // an activity restart. We instead hand back the last reported 2211 // {@link MergedConfiguration}. 2212 if (shouldRelayout) { 2213 win.getMergedConfiguration(mergedConfiguration); 2214 } else { 2215 win.getLastReportedMergedConfiguration(mergedConfiguration); 2216 } 2217 2218 win.setLastReportedMergedConfiguration(mergedConfiguration); 2219 2220 outFrame.set(win.mCompatFrame); 2221 outOverscanInsets.set(win.mOverscanInsets); 2222 outContentInsets.set(win.mContentInsets); 2223 win.mLastRelayoutContentInsets.set(win.mContentInsets); 2224 outVisibleInsets.set(win.mVisibleInsets); 2225 outStableInsets.set(win.mStableInsets); 2226 outOutsets.set(win.mOutsets); 2227 outBackdropFrame.set(win.getBackdropFrame(win.mFrame)); 2228 if (localLOGV) Slog.v( 2229 TAG_WM, "Relayout given client " + client.asBinder() 2230 + ", requestedWidth=" + requestedWidth 2231 + ", requestedHeight=" + requestedHeight 2232 + ", viewVisibility=" + viewVisibility 2233 + "\nRelayout returning frame=" + outFrame 2234 + ", surface=" + outSurface); 2235 2236 if (localLOGV || DEBUG_FOCUS) Slog.v( 2237 TAG_WM, "Relayout of " + win + ": focusMayChange=" + focusMayChange); 2238 2239 result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0; 2240 2241 mInputMonitor.updateInputWindowsLw(true /*force*/); 2242 2243 if (DEBUG_LAYOUT) { 2244 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString()); 2245 } 2246 win.mInRelayout = false; 2247 } 2248 2249 if (configChanged) { 2250 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: sendNewConfiguration"); 2251 sendNewConfiguration(displayId); 2252 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2253 } 2254 Binder.restoreCallingIdentity(origId); 2255 return result; 2256 } 2257 tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator, boolean isDefaultDisplay, boolean focusMayChange)2258 private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator, 2259 boolean isDefaultDisplay, boolean focusMayChange) { 2260 // Try starting an animation; if there isn't one, we 2261 // can destroy the surface right away. 2262 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2263 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2264 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2265 } 2266 if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) { 2267 focusMayChange = isDefaultDisplay; 2268 win.mAnimatingExit = true; 2269 win.mWinAnimator.mAnimating = true; 2270 } else if (win.mWinAnimator.isAnimationSet()) { 2271 // Currently in a hide animation... turn this into 2272 // an exit. 2273 win.mAnimatingExit = true; 2274 win.mWinAnimator.mAnimating = true; 2275 } else if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) { 2276 // If the wallpaper is currently behind this 2277 // window, we need to change both of them inside 2278 // of a transaction to avoid artifacts. 2279 win.mAnimatingExit = true; 2280 win.mWinAnimator.mAnimating = true; 2281 } else { 2282 if (mInputMethodWindow == win) { 2283 setInputMethodWindowLocked(null); 2284 } 2285 boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : false; 2286 // We set mDestroying=true so AppWindowToken#notifyAppStopped in-to destroy surfaces 2287 // will later actually destroy the surface if we do not do so here. Normally we leave 2288 // this to the exit animation. 2289 win.mDestroying = true; 2290 win.destroySurface(false, stopped); 2291 } 2292 // TODO(multidisplay): Magnification is supported only for the default display. 2293 if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) { 2294 mAccessibilityController.onWindowTransitionLocked(win, transit); 2295 } 2296 2297 // When we start the exit animation we take the Surface from the client 2298 // so it will stop perturbing it. We need to likewise takeaway the SurfaceFlinger 2299 // side child surfaces, so they will remain preserved in their current state 2300 // (rather than be cleaned up immediately by the app code). 2301 SurfaceControl.openTransaction(); 2302 winAnimator.detachChildren(); 2303 SurfaceControl.closeTransaction(); 2304 2305 return focusMayChange; 2306 } 2307 createSurfaceControl(Surface outSurface, int result, WindowState win, WindowStateAnimator winAnimator)2308 private int createSurfaceControl(Surface outSurface, int result, WindowState win, 2309 WindowStateAnimator winAnimator) { 2310 if (!win.mHasSurface) { 2311 result |= RELAYOUT_RES_SURFACE_CHANGED; 2312 } 2313 2314 WindowSurfaceController surfaceController; 2315 try { 2316 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl"); 2317 surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid); 2318 } finally { 2319 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2320 } 2321 if (surfaceController != null) { 2322 surfaceController.getSurface(outSurface); 2323 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " OUT SURFACE " + outSurface + ": copied"); 2324 } else { 2325 // For some reason there isn't a surface. Clear the 2326 // caller's object so they see the same state. 2327 Slog.w(TAG_WM, "Failed to create surface control for " + win); 2328 outSurface.release(); 2329 } 2330 2331 return result; 2332 } 2333 outOfMemoryWindow(Session session, IWindow client)2334 public boolean outOfMemoryWindow(Session session, IWindow client) { 2335 final long origId = Binder.clearCallingIdentity(); 2336 2337 try { 2338 synchronized (mWindowMap) { 2339 WindowState win = windowForClientLocked(session, client, false); 2340 if (win == null) { 2341 return false; 2342 } 2343 return mRoot.reclaimSomeSurfaceMemory(win.mWinAnimator, "from-client", false); 2344 } 2345 } finally { 2346 Binder.restoreCallingIdentity(origId); 2347 } 2348 } 2349 finishDrawingWindow(Session session, IWindow client)2350 void finishDrawingWindow(Session session, IWindow client) { 2351 final long origId = Binder.clearCallingIdentity(); 2352 try { 2353 synchronized (mWindowMap) { 2354 WindowState win = windowForClientLocked(session, client, false); 2355 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState=" 2356 + (win != null ? win.mWinAnimator.drawStateToString() : "null")); 2357 if (win != null && win.mWinAnimator.finishDrawingLocked()) { 2358 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 2359 win.getDisplayContent().pendingLayoutChanges |= 2360 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2361 } 2362 win.setDisplayLayoutNeeded(); 2363 mWindowPlacerLocked.requestTraversal(); 2364 } 2365 } 2366 } finally { 2367 Binder.restoreCallingIdentity(origId); 2368 } 2369 } 2370 applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction)2371 boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp, 2372 int transit, boolean enter, boolean isVoiceInteraction) { 2373 // Only apply an animation if the display isn't frozen. If it is 2374 // frozen, there is no reason to animate and it can cause strange 2375 // artifacts when we unfreeze the display if some different animation 2376 // is running. 2377 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked"); 2378 if (atoken.okToAnimate()) { 2379 final DisplayContent displayContent = atoken.getTask().getDisplayContent(); 2380 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2381 final int width = displayInfo.appWidth; 2382 final int height = displayInfo.appHeight; 2383 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM, 2384 "applyAnimation: atoken=" + atoken); 2385 2386 // Determine the visible rect to calculate the thumbnail clip 2387 final WindowState win = atoken.findMainWindow(); 2388 final Rect frame = new Rect(0, 0, width, height); 2389 final Rect displayFrame = new Rect(0, 0, 2390 displayInfo.logicalWidth, displayInfo.logicalHeight); 2391 final Rect insets = new Rect(); 2392 final Rect stableInsets = new Rect(); 2393 Rect surfaceInsets = null; 2394 final boolean freeform = win != null && win.inFreeformWorkspace(); 2395 if (win != null) { 2396 // Containing frame will usually cover the whole screen, including dialog windows. 2397 // For freeform workspace windows it will not cover the whole screen and it also 2398 // won't exactly match the final freeform window frame (e.g. when overlapping with 2399 // the status bar). In that case we need to use the final frame. 2400 if (freeform) { 2401 frame.set(win.mFrame); 2402 } else { 2403 frame.set(win.mContainingFrame); 2404 } 2405 surfaceInsets = win.getAttrs().surfaceInsets; 2406 insets.set(win.mContentInsets); 2407 stableInsets.set(win.mStableInsets); 2408 } 2409 2410 if (atoken.mLaunchTaskBehind) { 2411 // Differentiate the two animations. This one which is briefly on the screen 2412 // gets the !enter animation, and the other activity which remains on the 2413 // screen gets the enter animation. Both appear in the mOpeningApps set. 2414 enter = false; 2415 } 2416 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition." 2417 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter 2418 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets); 2419 final Configuration displayConfig = displayContent.getConfiguration(); 2420 Animation a = mAppTransition.loadAnimation(lp, transit, enter, displayConfig.uiMode, 2421 displayConfig.orientation, frame, displayFrame, insets, surfaceInsets, 2422 stableInsets, isVoiceInteraction, freeform, atoken.getTask().mTaskId); 2423 if (a != null) { 2424 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken); 2425 final int containingWidth = frame.width(); 2426 final int containingHeight = frame.height(); 2427 atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight, width, 2428 height, mAppTransition.canSkipFirstFrame(), 2429 mAppTransition.getAppStackClipMode(), 2430 transit, mAppTransition.getTransitFlags()); 2431 } 2432 } else { 2433 atoken.mAppAnimator.clearAnimation(); 2434 } 2435 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2436 2437 return atoken.mAppAnimator.animation != null; 2438 } 2439 checkCallingPermission(String permission, String func)2440 boolean checkCallingPermission(String permission, String func) { 2441 // Quick check: if the calling permission is me, it's all okay. 2442 if (Binder.getCallingPid() == myPid()) { 2443 return true; 2444 } 2445 2446 if (mContext.checkCallingPermission(permission) 2447 == PackageManager.PERMISSION_GRANTED) { 2448 return true; 2449 } 2450 final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid() 2451 + ", uid=" + Binder.getCallingUid() + " requires " + permission; 2452 Slog.w(TAG_WM, msg); 2453 return false; 2454 } 2455 2456 @Override addWindowToken(IBinder binder, int type, int displayId)2457 public void addWindowToken(IBinder binder, int type, int displayId) { 2458 if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) { 2459 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 2460 } 2461 2462 synchronized(mWindowMap) { 2463 final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId); 2464 WindowToken token = dc.getWindowToken(binder); 2465 if (token != null) { 2466 Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder 2467 + " for already created window token: " + token 2468 + " displayId=" + displayId); 2469 return; 2470 } 2471 if (type == TYPE_WALLPAPER) { 2472 new WallpaperWindowToken(this, binder, true, dc, 2473 true /* ownerCanManageAppTokens */); 2474 } else { 2475 new WindowToken(this, binder, type, true, dc, true /* ownerCanManageAppTokens */); 2476 } 2477 } 2478 } 2479 2480 @Override removeWindowToken(IBinder binder, int displayId)2481 public void removeWindowToken(IBinder binder, int displayId) { 2482 if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) { 2483 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 2484 } 2485 2486 final long origId = Binder.clearCallingIdentity(); 2487 try { 2488 synchronized (mWindowMap) { 2489 final DisplayContent dc = mRoot.getDisplayContent(displayId); 2490 if (dc == null) { 2491 Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder 2492 + " for non-exiting displayId=" + displayId); 2493 return; 2494 } 2495 2496 final WindowToken token = dc.removeWindowToken(binder); 2497 if (token == null) { 2498 Slog.w(TAG_WM, 2499 "removeWindowToken: Attempted to remove non-existing token: " + binder); 2500 return; 2501 } 2502 2503 mInputMonitor.updateInputWindowsLw(true /*force*/); 2504 } 2505 } finally { 2506 Binder.restoreCallingIdentity(origId); 2507 } 2508 } 2509 2510 @Override updateOrientationFromAppTokens(Configuration currentConfig, IBinder freezeThisOneIfNeeded, int displayId)2511 public Configuration updateOrientationFromAppTokens(Configuration currentConfig, 2512 IBinder freezeThisOneIfNeeded, int displayId) { 2513 if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) { 2514 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 2515 } 2516 2517 final Configuration config; 2518 final long ident = Binder.clearCallingIdentity(); 2519 try { 2520 synchronized(mWindowMap) { 2521 config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded, 2522 displayId); 2523 } 2524 } finally { 2525 Binder.restoreCallingIdentity(ident); 2526 } 2527 2528 return config; 2529 } 2530 updateOrientationFromAppTokensLocked(Configuration currentConfig, IBinder freezeThisOneIfNeeded, int displayId)2531 private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig, 2532 IBinder freezeThisOneIfNeeded, int displayId) { 2533 if (!mDisplayReady) { 2534 return null; 2535 } 2536 Configuration config = null; 2537 2538 if (updateOrientationFromAppTokensLocked(false, displayId)) { 2539 // If we changed the orientation but mOrientationChangeComplete is already true, 2540 // we used seamless rotation, and we don't need to freeze the screen. 2541 if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) { 2542 final AppWindowToken atoken = mRoot.getAppWindowToken(freezeThisOneIfNeeded); 2543 if (atoken != null) { 2544 atoken.startFreezingScreen(); 2545 } 2546 } 2547 config = computeNewConfigurationLocked(displayId); 2548 2549 } else if (currentConfig != null) { 2550 // No obvious action we need to take, but if our current state mismatches the activity 2551 // manager's, update it, disregarding font scale, which should remain set to the value 2552 // of the previous configuration. 2553 // Here we're calling Configuration#unset() instead of setToDefaults() because we need 2554 // to keep override configs clear of non-empty values (e.g. fontSize). 2555 mTempConfiguration.unset(); 2556 mTempConfiguration.updateFrom(currentConfig); 2557 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 2558 displayContent.computeScreenConfiguration(mTempConfiguration); 2559 if (currentConfig.diff(mTempConfiguration) != 0) { 2560 mWaitingForConfig = true; 2561 displayContent.setLayoutNeeded(); 2562 int anim[] = new int[2]; 2563 if (displayContent.isDimming()) { 2564 anim[0] = anim[1] = 0; 2565 } else { 2566 mPolicy.selectRotationAnimationLw(anim); 2567 } 2568 startFreezingDisplayLocked(false, anim[0], anim[1], displayContent); 2569 config = new Configuration(mTempConfiguration); 2570 } 2571 } 2572 2573 return config; 2574 } 2575 2576 /** 2577 * Determine the new desired orientation of the display, returning a non-null new Configuration 2578 * if it has changed from the current orientation. IF TRUE IS RETURNED SOMEONE MUST CALL 2579 * {@link #setNewDisplayOverrideConfiguration(Configuration, int)} TO TELL THE WINDOW MANAGER IT 2580 * CAN UNFREEZE THE SCREEN. This will typically be done for you if you call 2581 * {@link #sendNewConfiguration(int)}. 2582 * 2583 * The orientation is computed from non-application windows first. If none of the 2584 * non-application windows specify orientation, the orientation is computed from application 2585 * tokens. 2586 * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int) 2587 */ updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId)2588 boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) { 2589 long ident = Binder.clearCallingIdentity(); 2590 try { 2591 final DisplayContent dc = mRoot.getDisplayContent(displayId); 2592 final int req = dc.getOrientation(); 2593 if (req != dc.getLastOrientation()) { 2594 dc.setLastOrientation(req); 2595 //send a message to Policy indicating orientation change to take 2596 //action like disabling/enabling sensors etc., 2597 // TODO(multi-display): Implement policy for secondary displays. 2598 if (dc.isDefaultDisplay) { 2599 mPolicy.setCurrentOrientationLw(req); 2600 } 2601 if (dc.updateRotationUnchecked(inTransaction)) { 2602 // changed 2603 return true; 2604 } 2605 } 2606 2607 return false; 2608 } finally { 2609 Binder.restoreCallingIdentity(ident); 2610 } 2611 } 2612 2613 // If this is true we have updated our desired orientation, but not yet 2614 // changed the real orientation our applied our screen rotation animation. 2615 // For example, because a previous screen rotation was in progress. rotationNeedsUpdateLocked()2616 boolean rotationNeedsUpdateLocked() { 2617 // TODO(multi-display): Check for updates on all displays. Need to have per-display policy 2618 // to implement WindowManagerPolicy#rotationForOrientationLw() correctly. 2619 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked(); 2620 final int lastOrientation = defaultDisplayContent.getLastOrientation(); 2621 final int oldRotation = defaultDisplayContent.getRotation(); 2622 final boolean oldAltOrientation = defaultDisplayContent.getAltOrientation(); 2623 2624 final int rotation = mPolicy.rotationForOrientationLw(lastOrientation, 2625 oldRotation); 2626 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 2627 lastOrientation, rotation); 2628 if (oldRotation == rotation && oldAltOrientation == altOrientation) { 2629 return false; 2630 } 2631 return true; 2632 } 2633 2634 @Override setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId)2635 public int[] setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId) { 2636 if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewDisplayOverrideConfiguration()")) { 2637 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 2638 } 2639 2640 synchronized(mWindowMap) { 2641 if (mWaitingForConfig) { 2642 mWaitingForConfig = false; 2643 mLastFinishedFreezeSource = "new-config"; 2644 } 2645 return mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, displayId); 2646 } 2647 } 2648 setFocusTaskRegionLocked(AppWindowToken previousFocus)2649 void setFocusTaskRegionLocked(AppWindowToken previousFocus) { 2650 final Task focusedTask = mFocusedApp != null ? mFocusedApp.getTask() : null; 2651 final Task previousTask = previousFocus != null ? previousFocus.getTask() : null; 2652 final DisplayContent focusedDisplayContent = 2653 focusedTask != null ? focusedTask.getDisplayContent() : null; 2654 final DisplayContent previousDisplayContent = 2655 previousTask != null ? previousTask.getDisplayContent() : null; 2656 if (previousDisplayContent != null && previousDisplayContent != focusedDisplayContent) { 2657 previousDisplayContent.setTouchExcludeRegion(null); 2658 } 2659 if (focusedDisplayContent != null) { 2660 focusedDisplayContent.setTouchExcludeRegion(focusedTask); 2661 } 2662 } 2663 2664 @Override setFocusedApp(IBinder token, boolean moveFocusNow)2665 public void setFocusedApp(IBinder token, boolean moveFocusNow) { 2666 if (!checkCallingPermission(MANAGE_APP_TOKENS, "setFocusedApp()")) { 2667 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 2668 } 2669 2670 synchronized(mWindowMap) { 2671 final AppWindowToken newFocus; 2672 if (token == null) { 2673 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, was " + mFocusedApp); 2674 newFocus = null; 2675 } else { 2676 newFocus = mRoot.getAppWindowToken(token); 2677 if (newFocus == null) { 2678 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token); 2679 } 2680 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus 2681 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow); 2682 } 2683 2684 final boolean changed = mFocusedApp != newFocus; 2685 if (changed) { 2686 AppWindowToken prev = mFocusedApp; 2687 mFocusedApp = newFocus; 2688 mInputMonitor.setFocusedAppLw(newFocus); 2689 setFocusTaskRegionLocked(prev); 2690 } 2691 2692 if (moveFocusNow && changed) { 2693 final long origId = Binder.clearCallingIdentity(); 2694 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2695 Binder.restoreCallingIdentity(origId); 2696 } 2697 } 2698 } 2699 2700 @Override prepareAppTransition(int transit, boolean alwaysKeepCurrent)2701 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { 2702 prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */); 2703 } 2704 2705 /** 2706 * @param transit What kind of transition is happening. Use one of the constants 2707 * AppTransition.TRANSIT_*. 2708 * @param alwaysKeepCurrent If true and a transition is already set, new transition will NOT 2709 * be set. 2710 * @param flags Additional flags for the app transition, Use a combination of the constants 2711 * AppTransition.TRANSIT_FLAG_*. 2712 * @param forceOverride Always override the transit, not matter what was set previously. 2713 */ prepareAppTransition(int transit, boolean alwaysKeepCurrent, int flags, boolean forceOverride)2714 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent, int flags, 2715 boolean forceOverride) { 2716 if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) { 2717 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 2718 } 2719 synchronized(mWindowMap) { 2720 boolean prepared = mAppTransition.prepareAppTransitionLocked(transit, alwaysKeepCurrent, 2721 flags, forceOverride); 2722 // TODO (multidisplay): associate app transitions with displays 2723 final DisplayContent dc = mRoot.getDisplayContent(DEFAULT_DISPLAY); 2724 if (prepared && dc != null && dc.okToAnimate()) { 2725 mSkipAppTransitionAnimation = false; 2726 } 2727 } 2728 } 2729 2730 @Override getPendingAppTransition()2731 public int getPendingAppTransition() { 2732 return mAppTransition.getAppTransition(); 2733 } 2734 2735 @Override overridePendingAppTransition(String packageName, int enterAnim, int exitAnim, IRemoteCallback startedCallback)2736 public void overridePendingAppTransition(String packageName, 2737 int enterAnim, int exitAnim, IRemoteCallback startedCallback) { 2738 synchronized(mWindowMap) { 2739 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim, 2740 startedCallback); 2741 } 2742 } 2743 2744 @Override overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, int startHeight)2745 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 2746 int startHeight) { 2747 synchronized(mWindowMap) { 2748 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth, 2749 startHeight); 2750 } 2751 } 2752 2753 @Override overridePendingAppTransitionClipReveal(int startX, int startY, int startWidth, int startHeight)2754 public void overridePendingAppTransitionClipReveal(int startX, int startY, 2755 int startWidth, int startHeight) { 2756 synchronized(mWindowMap) { 2757 mAppTransition.overridePendingAppTransitionClipReveal(startX, startY, startWidth, 2758 startHeight); 2759 } 2760 } 2761 2762 @Override overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp)2763 public void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX, 2764 int startY, IRemoteCallback startedCallback, boolean scaleUp) { 2765 synchronized(mWindowMap) { 2766 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY, 2767 startedCallback, scaleUp); 2768 } 2769 } 2770 2771 @Override overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp)2772 public void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX, 2773 int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, 2774 boolean scaleUp) { 2775 synchronized(mWindowMap) { 2776 mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX, startY, 2777 targetWidth, targetHeight, startedCallback, scaleUp); 2778 } 2779 } 2780 2781 @Override overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs, IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback, boolean scaleUp)2782 public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs, 2783 IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback, 2784 boolean scaleUp) { 2785 synchronized (mWindowMap) { 2786 mAppTransition.overridePendingAppTransitionMultiThumb(specs, onAnimationStartedCallback, 2787 onAnimationFinishedCallback, scaleUp); 2788 prolongAnimationsFromSpecs(specs, scaleUp); 2789 2790 } 2791 } 2792 prolongAnimationsFromSpecs(@onNull AppTransitionAnimationSpec[] specs, boolean scaleUp)2793 void prolongAnimationsFromSpecs(@NonNull AppTransitionAnimationSpec[] specs, boolean scaleUp) { 2794 // This is used by freeform <-> recents windows transition. We need to synchronize 2795 // the animation with the appearance of the content of recents, so we will make 2796 // animation stay on the first or last frame a little longer. 2797 mTmpTaskIds.clear(); 2798 for (int i = specs.length - 1; i >= 0; i--) { 2799 mTmpTaskIds.put(specs[i].taskId, 0); 2800 } 2801 for (final WindowState win : mWindowMap.values()) { 2802 final Task task = win.getTask(); 2803 if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1 2804 && task.inFreeformWorkspace()) { 2805 final AppWindowToken appToken = win.mAppToken; 2806 if (appToken != null && appToken.mAppAnimator != null) { 2807 appToken.mAppAnimator.startProlongAnimation(scaleUp ? 2808 PROLONG_ANIMATION_AT_START : PROLONG_ANIMATION_AT_END); 2809 } 2810 } 2811 } 2812 } 2813 2814 @Override overridePendingAppTransitionInPlace(String packageName, int anim)2815 public void overridePendingAppTransitionInPlace(String packageName, int anim) { 2816 synchronized(mWindowMap) { 2817 mAppTransition.overrideInPlaceAppTransition(packageName, anim); 2818 } 2819 } 2820 2821 @Override overridePendingAppTransitionMultiThumbFuture( IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback, boolean scaleUp)2822 public void overridePendingAppTransitionMultiThumbFuture( 2823 IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback, 2824 boolean scaleUp) { 2825 synchronized(mWindowMap) { 2826 mAppTransition.overridePendingAppTransitionMultiThumbFuture(specsFuture, callback, 2827 scaleUp); 2828 } 2829 } 2830 2831 @Override endProlongedAnimations()2832 public void endProlongedAnimations() { 2833 synchronized (mWindowMap) { 2834 for (final WindowState win : mWindowMap.values()) { 2835 final AppWindowToken appToken = win.mAppToken; 2836 if (appToken != null && appToken.mAppAnimator != null) { 2837 appToken.mAppAnimator.endProlongedAnimation(); 2838 } 2839 } 2840 mAppTransition.notifyProlongedAnimationsEnded(); 2841 } 2842 } 2843 2844 @Override executeAppTransition()2845 public void executeAppTransition() { 2846 if (!checkCallingPermission(MANAGE_APP_TOKENS, "executeAppTransition()")) { 2847 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 2848 } 2849 2850 synchronized(mWindowMap) { 2851 if (DEBUG_APP_TRANSITIONS) Slog.w(TAG_WM, "Execute app transition: " + mAppTransition 2852 + " Callers=" + Debug.getCallers(5)); 2853 if (mAppTransition.isTransitionSet()) { 2854 mAppTransition.setReady(); 2855 final long origId = Binder.clearCallingIdentity(); 2856 try { 2857 mWindowPlacerLocked.performSurfacePlacement(); 2858 } finally { 2859 Binder.restoreCallingIdentity(origId); 2860 } 2861 } 2862 } 2863 } 2864 setAppFullscreen(IBinder token, boolean toOpaque)2865 public void setAppFullscreen(IBinder token, boolean toOpaque) { 2866 synchronized (mWindowMap) { 2867 final AppWindowToken atoken = mRoot.getAppWindowToken(token); 2868 if (atoken != null) { 2869 atoken.setFillsParent(toOpaque); 2870 setWindowOpaqueLocked(token, toOpaque); 2871 mWindowPlacerLocked.requestTraversal(); 2872 } 2873 } 2874 } 2875 setWindowOpaque(IBinder token, boolean isOpaque)2876 public void setWindowOpaque(IBinder token, boolean isOpaque) { 2877 synchronized (mWindowMap) { 2878 setWindowOpaqueLocked(token, isOpaque); 2879 } 2880 } 2881 setWindowOpaqueLocked(IBinder token, boolean isOpaque)2882 private void setWindowOpaqueLocked(IBinder token, boolean isOpaque) { 2883 final AppWindowToken wtoken = mRoot.getAppWindowToken(token); 2884 if (wtoken != null) { 2885 final WindowState win = wtoken.findMainWindow(); 2886 if (win != null) { 2887 win.mWinAnimator.setOpaqueLocked(isOpaque); 2888 } 2889 } 2890 } 2891 updateTokenInPlaceLocked(AppWindowToken wtoken, int transit)2892 void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) { 2893 if (transit != TRANSIT_UNSET) { 2894 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 2895 wtoken.mAppAnimator.setNullAnimation(); 2896 } 2897 applyAnimationLocked(wtoken, null, transit, false, false); 2898 } 2899 } 2900 setDockedStackCreateState(int mode, Rect bounds)2901 public void setDockedStackCreateState(int mode, Rect bounds) { 2902 synchronized (mWindowMap) { 2903 setDockedStackCreateStateLocked(mode, bounds); 2904 } 2905 } 2906 setDockedStackCreateStateLocked(int mode, Rect bounds)2907 void setDockedStackCreateStateLocked(int mode, Rect bounds) { 2908 mDockedStackCreateMode = mode; 2909 mDockedStackCreateBounds = bounds; 2910 } 2911 isValidPictureInPictureAspectRatio(int displayId, float aspectRatio)2912 public boolean isValidPictureInPictureAspectRatio(int displayId, float aspectRatio) { 2913 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 2914 return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio( 2915 aspectRatio); 2916 } 2917 2918 @Override getStackBounds(int stackId, Rect bounds)2919 public void getStackBounds(int stackId, Rect bounds) { 2920 synchronized (mWindowMap) { 2921 final TaskStack stack = mRoot.getStackById(stackId); 2922 if (stack != null) { 2923 stack.getBounds(bounds); 2924 return; 2925 } 2926 bounds.setEmpty(); 2927 } 2928 } 2929 2930 @Override notifyShowingDreamChanged()2931 public void notifyShowingDreamChanged() { 2932 notifyKeyguardFlagsChanged(null /* callback */); 2933 } 2934 2935 @Override getInputMethodWindowLw()2936 public WindowManagerPolicy.WindowState getInputMethodWindowLw() { 2937 return mInputMethodWindow; 2938 } 2939 2940 @Override notifyKeyguardTrustedChanged()2941 public void notifyKeyguardTrustedChanged() { 2942 mH.sendEmptyMessage(H.NOTIFY_KEYGUARD_TRUSTED_CHANGED); 2943 } 2944 2945 @Override onKeyguardShowingAndNotOccludedChanged()2946 public void onKeyguardShowingAndNotOccludedChanged() { 2947 mH.sendEmptyMessage(H.RECOMPUTE_FOCUS); 2948 } 2949 2950 @Override screenTurningOff(ScreenOffListener listener)2951 public void screenTurningOff(ScreenOffListener listener) { 2952 mTaskSnapshotController.screenTurningOff(listener); 2953 } 2954 2955 /** 2956 * Starts deferring layout passes. Useful when doing multiple changes but to optimize 2957 * performance, only one layout pass should be done. This can be called multiple times, and 2958 * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout} 2959 */ deferSurfaceLayout()2960 public void deferSurfaceLayout() { 2961 synchronized (mWindowMap) { 2962 mWindowPlacerLocked.deferLayout(); 2963 } 2964 } 2965 2966 /** 2967 * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()} 2968 */ continueSurfaceLayout()2969 public void continueSurfaceLayout() { 2970 synchronized (mWindowMap) { 2971 mWindowPlacerLocked.continueLayout(); 2972 } 2973 } 2974 2975 /** 2976 * @return true if the activity contains windows that have 2977 * {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set 2978 */ containsShowWhenLockedWindow(IBinder token)2979 public boolean containsShowWhenLockedWindow(IBinder token) { 2980 synchronized (mWindowMap) { 2981 final AppWindowToken wtoken = mRoot.getAppWindowToken(token); 2982 return wtoken != null && wtoken.containsShowWhenLockedWindow(); 2983 } 2984 } 2985 2986 /** 2987 * @return true if the activity contains windows that have 2988 * {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set 2989 */ containsDismissKeyguardWindow(IBinder token)2990 public boolean containsDismissKeyguardWindow(IBinder token) { 2991 synchronized (mWindowMap) { 2992 final AppWindowToken wtoken = mRoot.getAppWindowToken(token); 2993 return wtoken != null && wtoken.containsDismissKeyguardWindow(); 2994 } 2995 } 2996 2997 /** 2998 * Notifies activity manager that some Keyguard flags have changed and that it needs to 2999 * reevaluate the visibilities of the activities. 3000 * @param callback Runnable to be called when activity manager is done reevaluating visibilities 3001 */ notifyKeyguardFlagsChanged(@ullable Runnable callback)3002 void notifyKeyguardFlagsChanged(@Nullable Runnable callback) { 3003 final Runnable wrappedCallback = callback != null 3004 ? () -> { synchronized (mWindowMap) { callback.run(); } } 3005 : null; 3006 mH.obtainMessage(H.NOTIFY_KEYGUARD_FLAGS_CHANGED, wrappedCallback).sendToTarget(); 3007 } 3008 isKeyguardTrusted()3009 public boolean isKeyguardTrusted() { 3010 synchronized (mWindowMap) { 3011 return mPolicy.isKeyguardTrustedLw(); 3012 } 3013 } 3014 setKeyguardGoingAway(boolean keyguardGoingAway)3015 public void setKeyguardGoingAway(boolean keyguardGoingAway) { 3016 synchronized (mWindowMap) { 3017 mKeyguardGoingAway = keyguardGoingAway; 3018 } 3019 } 3020 3021 // ------------------------------------------------------------- 3022 // Misc IWindowSession methods 3023 // ------------------------------------------------------------- 3024 3025 @Override startFreezingScreen(int exitAnim, int enterAnim)3026 public void startFreezingScreen(int exitAnim, int enterAnim) { 3027 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 3028 "startFreezingScreen()")) { 3029 throw new SecurityException("Requires FREEZE_SCREEN permission"); 3030 } 3031 3032 synchronized(mWindowMap) { 3033 if (!mClientFreezingScreen) { 3034 mClientFreezingScreen = true; 3035 final long origId = Binder.clearCallingIdentity(); 3036 try { 3037 startFreezingDisplayLocked(false, exitAnim, enterAnim); 3038 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 3039 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 3040 } finally { 3041 Binder.restoreCallingIdentity(origId); 3042 } 3043 } 3044 } 3045 } 3046 3047 @Override stopFreezingScreen()3048 public void stopFreezingScreen() { 3049 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 3050 "stopFreezingScreen()")) { 3051 throw new SecurityException("Requires FREEZE_SCREEN permission"); 3052 } 3053 3054 synchronized(mWindowMap) { 3055 if (mClientFreezingScreen) { 3056 mClientFreezingScreen = false; 3057 mLastFinishedFreezeSource = "client"; 3058 final long origId = Binder.clearCallingIdentity(); 3059 try { 3060 stopFreezingDisplayLocked(); 3061 } finally { 3062 Binder.restoreCallingIdentity(origId); 3063 } 3064 } 3065 } 3066 } 3067 3068 @Override disableKeyguard(IBinder token, String tag)3069 public void disableKeyguard(IBinder token, String tag) { 3070 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 3071 != PackageManager.PERMISSION_GRANTED) { 3072 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 3073 } 3074 // If this isn't coming from the system then don't allow disabling the lockscreen 3075 // to bypass security. 3076 if (Binder.getCallingUid() != SYSTEM_UID && isKeyguardSecure()) { 3077 Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard"); 3078 return; 3079 } 3080 3081 // If this isn't coming from the current profiles, ignore it. 3082 if (!isCurrentProfileLocked(UserHandle.getCallingUserId())) { 3083 Log.d(TAG_WM, "non-current profiles, ignore disableKeyguard"); 3084 return; 3085 } 3086 3087 if (token == null) { 3088 throw new IllegalArgumentException("token == null"); 3089 } 3090 3091 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 3092 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 3093 } 3094 3095 @Override reenableKeyguard(IBinder token)3096 public void reenableKeyguard(IBinder token) { 3097 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 3098 != PackageManager.PERMISSION_GRANTED) { 3099 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 3100 } 3101 3102 if (token == null) { 3103 throw new IllegalArgumentException("token == null"); 3104 } 3105 3106 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 3107 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 3108 } 3109 3110 /** 3111 * @see android.app.KeyguardManager#exitKeyguardSecurely 3112 */ 3113 @Override exitKeyguardSecurely(final IOnKeyguardExitResult callback)3114 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 3115 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 3116 != PackageManager.PERMISSION_GRANTED) { 3117 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 3118 } 3119 3120 if (callback == null) { 3121 throw new IllegalArgumentException("callback == null"); 3122 } 3123 3124 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 3125 @Override 3126 public void onKeyguardExitResult(boolean success) { 3127 try { 3128 callback.onKeyguardExitResult(success); 3129 } catch (RemoteException e) { 3130 // Client has died, we don't care. 3131 } 3132 } 3133 }); 3134 } 3135 3136 @Override inKeyguardRestrictedInputMode()3137 public boolean inKeyguardRestrictedInputMode() { 3138 return mPolicy.inKeyguardRestrictedKeyInputMode(); 3139 } 3140 3141 @Override isKeyguardLocked()3142 public boolean isKeyguardLocked() { 3143 return mPolicy.isKeyguardLocked(); 3144 } 3145 isKeyguardShowingAndNotOccluded()3146 public boolean isKeyguardShowingAndNotOccluded() { 3147 return mPolicy.isKeyguardShowingAndNotOccluded(); 3148 } 3149 3150 @Override isKeyguardSecure()3151 public boolean isKeyguardSecure() { 3152 int userId = UserHandle.getCallingUserId(); 3153 long origId = Binder.clearCallingIdentity(); 3154 try { 3155 return mPolicy.isKeyguardSecure(userId); 3156 } finally { 3157 Binder.restoreCallingIdentity(origId); 3158 } 3159 } 3160 isShowingDream()3161 public boolean isShowingDream() { 3162 synchronized (mWindowMap) { 3163 return mPolicy.isShowingDreamLw(); 3164 } 3165 } 3166 3167 @Override dismissKeyguard(IKeyguardDismissCallback callback)3168 public void dismissKeyguard(IKeyguardDismissCallback callback) { 3169 checkCallingPermission(permission.CONTROL_KEYGUARD, "dismissKeyguard"); 3170 synchronized(mWindowMap) { 3171 mPolicy.dismissKeyguardLw(callback); 3172 } 3173 } 3174 onKeyguardOccludedChanged(boolean occluded)3175 public void onKeyguardOccludedChanged(boolean occluded) { 3176 synchronized (mWindowMap) { 3177 mPolicy.onKeyguardOccludedChangedLw(occluded); 3178 } 3179 } 3180 3181 @Override setSwitchingUser(boolean switching)3182 public void setSwitchingUser(boolean switching) { 3183 if (!checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, 3184 "setSwitchingUser()")) { 3185 throw new SecurityException("Requires INTERACT_ACROSS_USERS_FULL permission"); 3186 } 3187 mPolicy.setSwitchingUser(switching); 3188 synchronized (mWindowMap) { 3189 mSwitchingUser = switching; 3190 } 3191 } 3192 showGlobalActions()3193 void showGlobalActions() { 3194 mPolicy.showGlobalActions(); 3195 } 3196 3197 @Override closeSystemDialogs(String reason)3198 public void closeSystemDialogs(String reason) { 3199 synchronized(mWindowMap) { 3200 mRoot.closeSystemDialogs(reason); 3201 } 3202 } 3203 fixScale(float scale)3204 static float fixScale(float scale) { 3205 if (scale < 0) scale = 0; 3206 else if (scale > 20) scale = 20; 3207 return Math.abs(scale); 3208 } 3209 3210 @Override setAnimationScale(int which, float scale)3211 public void setAnimationScale(int which, float scale) { 3212 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 3213 "setAnimationScale()")) { 3214 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 3215 } 3216 3217 scale = fixScale(scale); 3218 switch (which) { 3219 case 0: mWindowAnimationScaleSetting = scale; break; 3220 case 1: mTransitionAnimationScaleSetting = scale; break; 3221 case 2: mAnimatorDurationScaleSetting = scale; break; 3222 } 3223 3224 // Persist setting 3225 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 3226 } 3227 3228 @Override setAnimationScales(float[] scales)3229 public void setAnimationScales(float[] scales) { 3230 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 3231 "setAnimationScale()")) { 3232 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 3233 } 3234 3235 if (scales != null) { 3236 if (scales.length >= 1) { 3237 mWindowAnimationScaleSetting = fixScale(scales[0]); 3238 } 3239 if (scales.length >= 2) { 3240 mTransitionAnimationScaleSetting = fixScale(scales[1]); 3241 } 3242 if (scales.length >= 3) { 3243 mAnimatorDurationScaleSetting = fixScale(scales[2]); 3244 dispatchNewAnimatorScaleLocked(null); 3245 } 3246 } 3247 3248 // Persist setting 3249 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 3250 } 3251 setAnimatorDurationScale(float scale)3252 private void setAnimatorDurationScale(float scale) { 3253 mAnimatorDurationScaleSetting = scale; 3254 ValueAnimator.setDurationScale(scale); 3255 } 3256 getWindowAnimationScaleLocked()3257 public float getWindowAnimationScaleLocked() { 3258 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; 3259 } 3260 getTransitionAnimationScaleLocked()3261 public float getTransitionAnimationScaleLocked() { 3262 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; 3263 } 3264 3265 @Override getAnimationScale(int which)3266 public float getAnimationScale(int which) { 3267 switch (which) { 3268 case 0: return mWindowAnimationScaleSetting; 3269 case 1: return mTransitionAnimationScaleSetting; 3270 case 2: return mAnimatorDurationScaleSetting; 3271 } 3272 return 0; 3273 } 3274 3275 @Override getAnimationScales()3276 public float[] getAnimationScales() { 3277 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting, 3278 mAnimatorDurationScaleSetting }; 3279 } 3280 3281 @Override getCurrentAnimatorScale()3282 public float getCurrentAnimatorScale() { 3283 synchronized(mWindowMap) { 3284 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting; 3285 } 3286 } 3287 dispatchNewAnimatorScaleLocked(Session session)3288 void dispatchNewAnimatorScaleLocked(Session session) { 3289 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget(); 3290 } 3291 3292 @Override registerPointerEventListener(PointerEventListener listener)3293 public void registerPointerEventListener(PointerEventListener listener) { 3294 mPointerEventDispatcher.registerInputEventListener(listener); 3295 } 3296 3297 @Override unregisterPointerEventListener(PointerEventListener listener)3298 public void unregisterPointerEventListener(PointerEventListener listener) { 3299 mPointerEventDispatcher.unregisterInputEventListener(listener); 3300 } 3301 3302 /** Check if the service is set to dispatch pointer events. */ canDispatchPointerEvents()3303 boolean canDispatchPointerEvents() { 3304 return mPointerEventDispatcher != null; 3305 } 3306 3307 // Called by window manager policy. Not exposed externally. 3308 @Override getLidState()3309 public int getLidState() { 3310 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 3311 InputManagerService.SW_LID); 3312 if (sw > 0) { 3313 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 3314 return LID_CLOSED; 3315 } else if (sw == 0) { 3316 // Switch state: AKEY_STATE_UP. 3317 return LID_OPEN; 3318 } else { 3319 // Switch state: AKEY_STATE_UNKNOWN. 3320 return LID_ABSENT; 3321 } 3322 } 3323 3324 // Called by window manager policy. Not exposed externally. 3325 @Override lockDeviceNow()3326 public void lockDeviceNow() { 3327 lockNow(null); 3328 } 3329 3330 // Called by window manager policy. Not exposed externally. 3331 @Override getCameraLensCoverState()3332 public int getCameraLensCoverState() { 3333 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 3334 InputManagerService.SW_CAMERA_LENS_COVER); 3335 if (sw > 0) { 3336 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 3337 return CAMERA_LENS_COVERED; 3338 } else if (sw == 0) { 3339 // Switch state: AKEY_STATE_UP. 3340 return CAMERA_LENS_UNCOVERED; 3341 } else { 3342 // Switch state: AKEY_STATE_UNKNOWN. 3343 return CAMERA_LENS_COVER_ABSENT; 3344 } 3345 } 3346 3347 // Called by window manager policy. Not exposed externally. 3348 @Override switchInputMethod(boolean forwardDirection)3349 public void switchInputMethod(boolean forwardDirection) { 3350 final InputMethodManagerInternal inputMethodManagerInternal = 3351 LocalServices.getService(InputMethodManagerInternal.class); 3352 if (inputMethodManagerInternal != null) { 3353 inputMethodManagerInternal.switchInputMethod(forwardDirection); 3354 } 3355 } 3356 3357 // Called by window manager policy. Not exposed externally. 3358 @Override shutdown(boolean confirm)3359 public void shutdown(boolean confirm) { 3360 // Pass in the UI context, since ShutdownThread requires it (to show UI). 3361 ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(), 3362 PowerManager.SHUTDOWN_USER_REQUESTED, confirm); 3363 } 3364 3365 // Called by window manager policy. Not exposed externally. 3366 @Override reboot(boolean confirm)3367 public void reboot(boolean confirm) { 3368 // Pass in the UI context, since ShutdownThread requires it (to show UI). 3369 ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(), 3370 PowerManager.SHUTDOWN_USER_REQUESTED, confirm); 3371 } 3372 3373 // Called by window manager policy. Not exposed externally. 3374 @Override rebootSafeMode(boolean confirm)3375 public void rebootSafeMode(boolean confirm) { 3376 // Pass in the UI context, since ShutdownThread requires it (to show UI). 3377 ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(), 3378 confirm); 3379 } 3380 setCurrentProfileIds(final int[] currentProfileIds)3381 public void setCurrentProfileIds(final int[] currentProfileIds) { 3382 synchronized (mWindowMap) { 3383 mCurrentProfileIds = currentProfileIds; 3384 } 3385 } 3386 setCurrentUser(final int newUserId, final int[] currentProfileIds)3387 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) { 3388 synchronized (mWindowMap) { 3389 mCurrentUserId = newUserId; 3390 mCurrentProfileIds = currentProfileIds; 3391 mAppTransition.setCurrentUser(newUserId); 3392 mPolicy.setCurrentUserLw(newUserId); 3393 3394 // If keyguard was disabled, re-enable it 3395 // TODO: Keep track of keyguardEnabled state per user and use here... 3396 // e.g. enabled = mKeyguardDisableHandler.getEnabledStateForUser(newUserId); 3397 mPolicy.enableKeyguard(true); 3398 3399 // Hide windows that should not be seen by the new user. 3400 mRoot.switchUser(); 3401 mWindowPlacerLocked.performSurfacePlacement(); 3402 3403 // Notify whether the docked stack exists for the current user 3404 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3405 final TaskStack stack = displayContent.getDockedStackIgnoringVisibility(); 3406 displayContent.mDividerControllerLocked.notifyDockedStackExistsChanged( 3407 stack != null && stack.hasTaskForUser(newUserId)); 3408 3409 // If the display is already prepared, update the density. 3410 // Otherwise, we'll update it when it's prepared. 3411 if (mDisplayReady) { 3412 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId); 3413 final int targetDensity = forcedDensity != 0 ? forcedDensity 3414 : displayContent.mInitialDisplayDensity; 3415 setForcedDisplayDensityLocked(displayContent, targetDensity); 3416 } 3417 } 3418 } 3419 3420 /* Called by WindowState */ isCurrentProfileLocked(int userId)3421 boolean isCurrentProfileLocked(int userId) { 3422 if (userId == mCurrentUserId) return true; 3423 for (int i = 0; i < mCurrentProfileIds.length; i++) { 3424 if (mCurrentProfileIds[i] == userId) return true; 3425 } 3426 return false; 3427 } 3428 enableScreenAfterBoot()3429 public void enableScreenAfterBoot() { 3430 synchronized(mWindowMap) { 3431 if (DEBUG_BOOT) { 3432 RuntimeException here = new RuntimeException("here"); 3433 here.fillInStackTrace(); 3434 Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 3435 + " mForceDisplayEnabled=" + mForceDisplayEnabled 3436 + " mShowingBootMessages=" + mShowingBootMessages 3437 + " mSystemBooted=" + mSystemBooted, here); 3438 } 3439 if (mSystemBooted) { 3440 return; 3441 } 3442 mSystemBooted = true; 3443 hideBootMessagesLocked(); 3444 // If the screen still doesn't come up after 30 seconds, give 3445 // up and turn it on. 3446 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000); 3447 } 3448 3449 mPolicy.systemBooted(); 3450 3451 performEnableScreen(); 3452 } 3453 3454 @Override enableScreenIfNeeded()3455 public void enableScreenIfNeeded() { 3456 synchronized (mWindowMap) { 3457 enableScreenIfNeededLocked(); 3458 } 3459 } 3460 enableScreenIfNeededLocked()3461 void enableScreenIfNeededLocked() { 3462 if (DEBUG_BOOT) { 3463 RuntimeException here = new RuntimeException("here"); 3464 here.fillInStackTrace(); 3465 Slog.i(TAG_WM, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 3466 + " mForceDisplayEnabled=" + mForceDisplayEnabled 3467 + " mShowingBootMessages=" + mShowingBootMessages 3468 + " mSystemBooted=" + mSystemBooted, here); 3469 } 3470 if (mDisplayEnabled) { 3471 return; 3472 } 3473 if (!mSystemBooted && !mShowingBootMessages) { 3474 return; 3475 } 3476 mH.sendEmptyMessage(H.ENABLE_SCREEN); 3477 } 3478 performBootTimeout()3479 public void performBootTimeout() { 3480 synchronized(mWindowMap) { 3481 if (mDisplayEnabled) { 3482 return; 3483 } 3484 Slog.w(TAG_WM, "***** BOOT TIMEOUT: forcing display enabled"); 3485 mForceDisplayEnabled = true; 3486 } 3487 performEnableScreen(); 3488 } 3489 3490 /** 3491 * Called when System UI has been started. 3492 */ onSystemUiStarted()3493 public void onSystemUiStarted() { 3494 mPolicy.onSystemUiStarted(); 3495 } 3496 performEnableScreen()3497 private void performEnableScreen() { 3498 synchronized(mWindowMap) { 3499 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 3500 + " mForceDisplayEnabled=" + mForceDisplayEnabled 3501 + " mShowingBootMessages=" + mShowingBootMessages 3502 + " mSystemBooted=" + mSystemBooted 3503 + " mOnlyCore=" + mOnlyCore, 3504 new RuntimeException("here").fillInStackTrace()); 3505 if (mDisplayEnabled) { 3506 return; 3507 } 3508 if (!mSystemBooted && !mShowingBootMessages) { 3509 return; 3510 } 3511 3512 if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) { 3513 return; 3514 } 3515 3516 // Don't enable the screen until all existing windows have been drawn. 3517 if (!mForceDisplayEnabled 3518 // TODO(multidisplay): Expand to all displays? 3519 && getDefaultDisplayContentLocked().checkWaitingForWindows()) { 3520 return; 3521 } 3522 3523 if (!mBootAnimationStopped) { 3524 Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0); 3525 // stop boot animation 3526 // formerly we would just kill the process, but we now ask it to exit so it 3527 // can choose where to stop the animation. 3528 SystemProperties.set("service.bootanim.exit", "1"); 3529 mBootAnimationStopped = true; 3530 } 3531 3532 if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) { 3533 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete"); 3534 return; 3535 } 3536 3537 try { 3538 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 3539 if (surfaceFlinger != null) { 3540 Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 3541 Parcel data = Parcel.obtain(); 3542 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 3543 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 3544 data, null, 0); 3545 data.recycle(); 3546 } 3547 } catch (RemoteException ex) { 3548 Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!"); 3549 } 3550 3551 EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis()); 3552 Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0); 3553 mDisplayEnabled = true; 3554 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!"); 3555 3556 // Enable input dispatch. 3557 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 3558 } 3559 3560 try { 3561 mActivityManager.bootAnimationComplete(); 3562 } catch (RemoteException e) { 3563 } 3564 3565 mPolicy.enableScreenAfterBoot(); 3566 3567 // Make sure the last requested orientation has been applied. 3568 updateRotationUnchecked(false, false); 3569 } 3570 checkBootAnimationCompleteLocked()3571 private boolean checkBootAnimationCompleteLocked() { 3572 if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) { 3573 mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED); 3574 mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED, 3575 BOOT_ANIMATION_POLL_INTERVAL); 3576 if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Waiting for anim complete"); 3577 return false; 3578 } 3579 if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Animation complete!"); 3580 return true; 3581 } 3582 showBootMessage(final CharSequence msg, final boolean always)3583 public void showBootMessage(final CharSequence msg, final boolean always) { 3584 boolean first = false; 3585 synchronized(mWindowMap) { 3586 if (DEBUG_BOOT) { 3587 RuntimeException here = new RuntimeException("here"); 3588 here.fillInStackTrace(); 3589 Slog.i(TAG_WM, "showBootMessage: msg=" + msg + " always=" + always 3590 + " mAllowBootMessages=" + mAllowBootMessages 3591 + " mShowingBootMessages=" + mShowingBootMessages 3592 + " mSystemBooted=" + mSystemBooted, here); 3593 } 3594 if (!mAllowBootMessages) { 3595 return; 3596 } 3597 if (!mShowingBootMessages) { 3598 if (!always) { 3599 return; 3600 } 3601 first = true; 3602 } 3603 if (mSystemBooted) { 3604 return; 3605 } 3606 mShowingBootMessages = true; 3607 mPolicy.showBootMessage(msg, always); 3608 } 3609 if (first) { 3610 performEnableScreen(); 3611 } 3612 } 3613 hideBootMessagesLocked()3614 public void hideBootMessagesLocked() { 3615 if (DEBUG_BOOT) { 3616 RuntimeException here = new RuntimeException("here"); 3617 here.fillInStackTrace(); 3618 Slog.i(TAG_WM, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 3619 + " mForceDisplayEnabled=" + mForceDisplayEnabled 3620 + " mShowingBootMessages=" + mShowingBootMessages 3621 + " mSystemBooted=" + mSystemBooted, here); 3622 } 3623 if (mShowingBootMessages) { 3624 mShowingBootMessages = false; 3625 mPolicy.hideBootMessages(); 3626 } 3627 } 3628 3629 @Override setInTouchMode(boolean mode)3630 public void setInTouchMode(boolean mode) { 3631 synchronized(mWindowMap) { 3632 mInTouchMode = mode; 3633 } 3634 } 3635 updateCircularDisplayMaskIfNeeded()3636 private void updateCircularDisplayMaskIfNeeded() { 3637 if (mContext.getResources().getConfiguration().isScreenRound() 3638 && mContext.getResources().getBoolean( 3639 com.android.internal.R.bool.config_windowShowCircularMask)) { 3640 final int currentUserId; 3641 synchronized(mWindowMap) { 3642 currentUserId = mCurrentUserId; 3643 } 3644 // Device configuration calls for a circular display mask, but we only enable the mask 3645 // if the accessibility color inversion feature is disabled, as the inverted mask 3646 // causes artifacts. 3647 int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(), 3648 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, currentUserId); 3649 int showMask = (inversionState == 1) ? 0 : 1; 3650 Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK); 3651 m.arg1 = showMask; 3652 mH.sendMessage(m); 3653 } 3654 } 3655 showEmulatorDisplayOverlayIfNeeded()3656 public void showEmulatorDisplayOverlayIfNeeded() { 3657 if (mContext.getResources().getBoolean( 3658 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay) 3659 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false) 3660 && Build.IS_EMULATOR) { 3661 mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY)); 3662 } 3663 } 3664 showCircularMask(boolean visible)3665 public void showCircularMask(boolean visible) { 3666 synchronized(mWindowMap) { 3667 3668 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, 3669 ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")"); 3670 openSurfaceTransaction(); 3671 try { 3672 if (visible) { 3673 // TODO(multi-display): support multiple displays 3674 if (mCircularDisplayMask == null) { 3675 int screenOffset = mContext.getResources().getInteger( 3676 com.android.internal.R.integer.config_windowOutsetBottom); 3677 int maskThickness = mContext.getResources().getDimensionPixelSize( 3678 com.android.internal.R.dimen.circular_display_mask_thickness); 3679 3680 mCircularDisplayMask = new CircularDisplayMask( 3681 getDefaultDisplayContentLocked().getDisplay(), 3682 mFxSession, 3683 mPolicy.getWindowLayerFromTypeLw( 3684 WindowManager.LayoutParams.TYPE_POINTER) 3685 * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness); 3686 } 3687 mCircularDisplayMask.setVisibility(true); 3688 } else if (mCircularDisplayMask != null) { 3689 mCircularDisplayMask.setVisibility(false); 3690 mCircularDisplayMask = null; 3691 } 3692 } finally { 3693 closeSurfaceTransaction(); 3694 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, 3695 "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")"); 3696 } 3697 } 3698 } 3699 showEmulatorDisplayOverlay()3700 public void showEmulatorDisplayOverlay() { 3701 synchronized(mWindowMap) { 3702 3703 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, 3704 ">>> OPEN TRANSACTION showEmulatorDisplayOverlay"); 3705 openSurfaceTransaction(); 3706 try { 3707 if (mEmulatorDisplayOverlay == null) { 3708 mEmulatorDisplayOverlay = new EmulatorDisplayOverlay( 3709 mContext, 3710 getDefaultDisplayContentLocked().getDisplay(), 3711 mFxSession, 3712 mPolicy.getWindowLayerFromTypeLw( 3713 WindowManager.LayoutParams.TYPE_POINTER) 3714 * TYPE_LAYER_MULTIPLIER + 10); 3715 } 3716 mEmulatorDisplayOverlay.setVisibility(true); 3717 } finally { 3718 closeSurfaceTransaction(); 3719 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, 3720 "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay"); 3721 } 3722 } 3723 } 3724 3725 // TODO: more accounting of which pid(s) turned it on, keep count, 3726 // only allow disables from pids which have count on, etc. 3727 @Override showStrictModeViolation(boolean on)3728 public void showStrictModeViolation(boolean on) { 3729 final int pid = Binder.getCallingPid(); 3730 if (on) { 3731 // Show the visualization, and enqueue a second message to tear it 3732 // down if we don't hear back from the app. 3733 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 1, pid)); 3734 mH.sendMessageDelayed(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid), 3735 DateUtils.SECOND_IN_MILLIS); 3736 } else { 3737 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid)); 3738 } 3739 } 3740 showStrictModeViolation(int arg, int pid)3741 private void showStrictModeViolation(int arg, int pid) { 3742 final boolean on = arg != 0; 3743 synchronized(mWindowMap) { 3744 // Ignoring requests to enable the red border from clients which aren't on screen. 3745 // (e.g. Broadcast Receivers in the background..) 3746 if (on && !mRoot.canShowStrictModeViolation(pid)) { 3747 return; 3748 } 3749 3750 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM, 3751 ">>> OPEN TRANSACTION showStrictModeViolation"); 3752 // TODO: Modify this to use the surface trace once it is not going crazy. 3753 // b/31532461 3754 SurfaceControl.openTransaction(); 3755 try { 3756 // TODO(multi-display): support multiple displays 3757 if (mStrictModeFlash == null) { 3758 mStrictModeFlash = new StrictModeFlash( 3759 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 3760 } 3761 mStrictModeFlash.setVisibility(on); 3762 } finally { 3763 SurfaceControl.closeTransaction(); 3764 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM, 3765 "<<< CLOSE TRANSACTION showStrictModeViolation"); 3766 } 3767 } 3768 } 3769 3770 @Override setStrictModeVisualIndicatorPreference(String value)3771 public void setStrictModeVisualIndicatorPreference(String value) { 3772 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 3773 } 3774 3775 @Override screenshotWallpaper()3776 public Bitmap screenshotWallpaper() { 3777 if (!checkCallingPermission(READ_FRAME_BUFFER, 3778 "screenshotWallpaper()")) { 3779 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 3780 } 3781 try { 3782 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper"); 3783 return screenshotApplications(null /* appToken */, DEFAULT_DISPLAY, -1 /* width */, 3784 -1 /* height */, true /* includeFullDisplay */, 1f /* frameScale */, 3785 Bitmap.Config.ARGB_8888, true /* wallpaperOnly */, false /* includeDecor */); 3786 } finally { 3787 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 3788 } 3789 } 3790 3791 /** 3792 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 3793 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 3794 * of the target image. 3795 */ 3796 @Override requestAssistScreenshot(final IAssistScreenshotReceiver receiver)3797 public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) { 3798 if (!checkCallingPermission(READ_FRAME_BUFFER, 3799 "requestAssistScreenshot()")) { 3800 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 3801 } 3802 3803 FgThread.getHandler().post(() -> { 3804 Bitmap bm = screenshotApplications(null /* appToken */, DEFAULT_DISPLAY, 3805 -1 /* width */, -1 /* height */, true /* includeFullDisplay */, 3806 1f /* frameScale */, Bitmap.Config.ARGB_8888, false /* wallpaperOnly */, 3807 false /* includeDecor */); 3808 try { 3809 receiver.send(bm); 3810 } catch (RemoteException e) { 3811 } 3812 }); 3813 3814 return true; 3815 } 3816 getTaskSnapshot(int taskId, int userId, boolean reducedResolution)3817 public TaskSnapshot getTaskSnapshot(int taskId, int userId, boolean reducedResolution) { 3818 return mTaskSnapshotController.getSnapshot(taskId, userId, true /* restoreFromDisk */, 3819 reducedResolution); 3820 } 3821 3822 /** 3823 * In case a task write/delete operation was lost because the system crashed, this makes sure to 3824 * clean up the directory to remove obsolete files. 3825 * 3826 * @param persistentTaskIds A set of task ids that exist in our in-memory model. 3827 * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory 3828 * model. 3829 */ removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds)3830 public void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) { 3831 synchronized (mWindowMap) { 3832 mTaskSnapshotController.removeObsoleteTaskFiles(persistentTaskIds, runningUserIds); 3833 } 3834 } 3835 3836 /** 3837 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 3838 * In portrait mode, it grabs the full screenshot. 3839 * 3840 * @param displayId the Display to take a screenshot of. 3841 * @param width the width of the target bitmap 3842 * @param height the height of the target bitmap 3843 * @param includeFullDisplay true if the screen should not be cropped before capture 3844 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1 3845 * @param config of the output bitmap 3846 * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot 3847 * @param includeDecor whether to include window decors, like the status or navigation bar 3848 * background of the window 3849 */ screenshotApplications(IBinder appToken, int displayId, int width, int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config, boolean wallpaperOnly, boolean includeDecor)3850 private Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 3851 int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config, 3852 boolean wallpaperOnly, boolean includeDecor) { 3853 final DisplayContent displayContent; 3854 synchronized(mWindowMap) { 3855 displayContent = mRoot.getDisplayContentOrCreate(displayId); 3856 if (displayContent == null) { 3857 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 3858 + ": returning null. No Display for displayId=" + displayId); 3859 return null; 3860 } 3861 } 3862 return displayContent.screenshotApplications(appToken, width, height, 3863 includeFullDisplay, frameScale, config, wallpaperOnly, includeDecor); 3864 } 3865 3866 /** 3867 * Freeze rotation changes. (Enable "rotation lock".) 3868 * Persists across reboots. 3869 * @param rotation The desired rotation to freeze to, or -1 to use the 3870 * current rotation. 3871 */ 3872 @Override freezeRotation(int rotation)3873 public void freezeRotation(int rotation) { 3874 // TODO(multi-display): Track which display is rotated. 3875 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 3876 "freezeRotation()")) { 3877 throw new SecurityException("Requires SET_ORIENTATION permission"); 3878 } 3879 if (rotation < -1 || rotation > Surface.ROTATION_270) { 3880 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 3881 + "rotation constant."); 3882 } 3883 3884 final int defaultDisplayRotation = getDefaultDisplayRotation(); 3885 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation=" 3886 + defaultDisplayRotation); 3887 3888 long origId = Binder.clearCallingIdentity(); 3889 try { 3890 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 3891 rotation == -1 ? defaultDisplayRotation : rotation); 3892 } finally { 3893 Binder.restoreCallingIdentity(origId); 3894 } 3895 3896 updateRotationUnchecked(false, false); 3897 } 3898 3899 /** 3900 * Thaw rotation changes. (Disable "rotation lock".) 3901 * Persists across reboots. 3902 */ 3903 @Override thawRotation()3904 public void thawRotation() { 3905 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 3906 "thawRotation()")) { 3907 throw new SecurityException("Requires SET_ORIENTATION permission"); 3908 } 3909 3910 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation=" 3911 + getDefaultDisplayRotation()); 3912 3913 long origId = Binder.clearCallingIdentity(); 3914 try { 3915 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 3916 777); // rot not used 3917 } finally { 3918 Binder.restoreCallingIdentity(origId); 3919 } 3920 3921 updateRotationUnchecked(false, false); 3922 } 3923 3924 /** 3925 * Recalculate the current rotation. 3926 * 3927 * Called by the window manager policy whenever the state of the system changes 3928 * such that the current rotation might need to be updated, such as when the 3929 * device is docked or rotated into a new posture. 3930 */ 3931 @Override updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout)3932 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 3933 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 3934 } 3935 3936 /** 3937 * Temporarily pauses rotation changes until resumed. 3938 * 3939 * This can be used to prevent rotation changes from occurring while the user is 3940 * performing certain operations, such as drag and drop. 3941 * 3942 * This call nests and must be matched by an equal number of calls to 3943 * {@link #resumeRotationLocked}. 3944 */ pauseRotationLocked()3945 void pauseRotationLocked() { 3946 mDeferredRotationPauseCount += 1; 3947 } 3948 3949 /** 3950 * Resumes normal rotation changes after being paused. 3951 */ resumeRotationLocked()3952 void resumeRotationLocked() { 3953 if (mDeferredRotationPauseCount > 0) { 3954 mDeferredRotationPauseCount -= 1; 3955 if (mDeferredRotationPauseCount == 0) { 3956 // TODO(multi-display): Update rotation for different displays separately. 3957 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3958 final boolean changed = displayContent.updateRotationUnchecked( 3959 false /* inTransaction */); 3960 if (changed) { 3961 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId()) 3962 .sendToTarget(); 3963 } 3964 } 3965 } 3966 } 3967 updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout)3968 private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 3969 if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked:" 3970 + " alwaysSendConfiguration=" + alwaysSendConfiguration 3971 + " forceRelayout=" + forceRelayout); 3972 3973 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation"); 3974 3975 long origId = Binder.clearCallingIdentity(); 3976 3977 try { 3978 // TODO(multi-display): Update rotation for different displays separately. 3979 final boolean rotationChanged; 3980 final int displayId; 3981 synchronized (mWindowMap) { 3982 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3983 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display"); 3984 rotationChanged = displayContent.updateRotationUnchecked( 3985 false /* inTransaction */); 3986 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 3987 if (!rotationChanged || forceRelayout) { 3988 displayContent.setLayoutNeeded(); 3989 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, 3990 "updateRotation: performSurfacePlacement"); 3991 mWindowPlacerLocked.performSurfacePlacement(); 3992 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 3993 } 3994 displayId = displayContent.getDisplayId(); 3995 } 3996 3997 if (rotationChanged || alwaysSendConfiguration) { 3998 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: sendNewConfiguration"); 3999 sendNewConfiguration(displayId); 4000 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4001 } 4002 } finally { 4003 Binder.restoreCallingIdentity(origId); 4004 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 4005 } 4006 } 4007 4008 @Override getDefaultDisplayRotation()4009 public int getDefaultDisplayRotation() { 4010 synchronized (mWindowMap) { 4011 return getDefaultDisplayContentLocked().getRotation(); 4012 } 4013 } 4014 4015 @Override isRotationFrozen()4016 public boolean isRotationFrozen() { 4017 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 4018 } 4019 4020 @Override watchRotation(IRotationWatcher watcher, int displayId)4021 public int watchRotation(IRotationWatcher watcher, int displayId) { 4022 final IBinder watcherBinder = watcher.asBinder(); 4023 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 4024 @Override 4025 public void binderDied() { 4026 synchronized (mWindowMap) { 4027 for (int i=0; i<mRotationWatchers.size(); i++) { 4028 if (watcherBinder == mRotationWatchers.get(i).mWatcher.asBinder()) { 4029 RotationWatcher removed = mRotationWatchers.remove(i); 4030 IBinder binder = removed.mWatcher.asBinder(); 4031 if (binder != null) { 4032 binder.unlinkToDeath(this, 0); 4033 } 4034 i--; 4035 } 4036 } 4037 } 4038 } 4039 }; 4040 4041 synchronized (mWindowMap) { 4042 try { 4043 watcher.asBinder().linkToDeath(dr, 0); 4044 mRotationWatchers.add(new RotationWatcher(watcher, dr, displayId)); 4045 } catch (RemoteException e) { 4046 // Client died, no cleanup needed. 4047 } 4048 4049 return getDefaultDisplayRotation(); 4050 } 4051 } 4052 4053 @Override removeRotationWatcher(IRotationWatcher watcher)4054 public void removeRotationWatcher(IRotationWatcher watcher) { 4055 final IBinder watcherBinder = watcher.asBinder(); 4056 synchronized (mWindowMap) { 4057 for (int i=0; i<mRotationWatchers.size(); i++) { 4058 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 4059 if (watcherBinder == rotationWatcher.mWatcher.asBinder()) { 4060 RotationWatcher removed = mRotationWatchers.remove(i); 4061 IBinder binder = removed.mWatcher.asBinder(); 4062 if (binder != null) { 4063 binder.unlinkToDeath(removed.mDeathRecipient, 0); 4064 } 4065 i--; 4066 } 4067 } 4068 } 4069 } 4070 4071 @Override registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener, int displayId)4072 public boolean registerWallpaperVisibilityListener(IWallpaperVisibilityListener listener, 4073 int displayId) { 4074 synchronized (mWindowMap) { 4075 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 4076 if (displayContent == null) { 4077 throw new IllegalArgumentException("Trying to register visibility event " 4078 + "for invalid display: " + displayId); 4079 } 4080 mWallpaperVisibilityListeners.registerWallpaperVisibilityListener(listener, displayId); 4081 return displayContent.mWallpaperController.isWallpaperVisible(); 4082 } 4083 } 4084 4085 @Override unregisterWallpaperVisibilityListener(IWallpaperVisibilityListener listener, int displayId)4086 public void unregisterWallpaperVisibilityListener(IWallpaperVisibilityListener listener, 4087 int displayId) { 4088 synchronized (mWindowMap) { 4089 mWallpaperVisibilityListeners 4090 .unregisterWallpaperVisibilityListener(listener, displayId); 4091 } 4092 } 4093 4094 /** 4095 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 4096 * theme attribute) on devices that feature a physical options menu key attempt to position 4097 * their menu panel window along the edge of the screen nearest the physical menu key. 4098 * This lowers the travel distance between invoking the menu panel and selecting 4099 * a menu option. 4100 * 4101 * This method helps control where that menu is placed. Its current implementation makes 4102 * assumptions about the menu key and its relationship to the screen based on whether 4103 * the device's natural orientation is portrait (width < height) or landscape. 4104 * 4105 * The menu key is assumed to be located along the bottom edge of natural-portrait 4106 * devices and along the right edge of natural-landscape devices. If these assumptions 4107 * do not hold for the target device, this method should be changed to reflect that. 4108 * 4109 * @return A {@link Gravity} value for placing the options menu window 4110 */ 4111 @Override getPreferredOptionsPanelGravity()4112 public int getPreferredOptionsPanelGravity() { 4113 synchronized (mWindowMap) { 4114 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 4115 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 4116 final int rotation = displayContent.getRotation(); 4117 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 4118 // On devices with a natural orientation of portrait 4119 switch (rotation) { 4120 default: 4121 case Surface.ROTATION_0: 4122 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 4123 case Surface.ROTATION_90: 4124 return Gravity.RIGHT | Gravity.BOTTOM; 4125 case Surface.ROTATION_180: 4126 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 4127 case Surface.ROTATION_270: 4128 return Gravity.START | Gravity.BOTTOM; 4129 } 4130 } 4131 4132 // On devices with a natural orientation of landscape 4133 switch (rotation) { 4134 default: 4135 case Surface.ROTATION_0: 4136 return Gravity.RIGHT | Gravity.BOTTOM; 4137 case Surface.ROTATION_90: 4138 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 4139 case Surface.ROTATION_180: 4140 return Gravity.START | Gravity.BOTTOM; 4141 case Surface.ROTATION_270: 4142 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 4143 } 4144 } 4145 } 4146 4147 /** 4148 * Starts the view server on the specified port. 4149 * 4150 * @param port The port to listener to. 4151 * 4152 * @return True if the server was successfully started, false otherwise. 4153 * 4154 * @see com.android.server.wm.ViewServer 4155 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 4156 */ 4157 @Override startViewServer(int port)4158 public boolean startViewServer(int port) { 4159 if (isSystemSecure()) { 4160 return false; 4161 } 4162 4163 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 4164 return false; 4165 } 4166 4167 if (port < 1024) { 4168 return false; 4169 } 4170 4171 if (mViewServer != null) { 4172 if (!mViewServer.isRunning()) { 4173 try { 4174 return mViewServer.start(); 4175 } catch (IOException e) { 4176 Slog.w(TAG_WM, "View server did not start"); 4177 } 4178 } 4179 return false; 4180 } 4181 4182 try { 4183 mViewServer = new ViewServer(this, port); 4184 return mViewServer.start(); 4185 } catch (IOException e) { 4186 Slog.w(TAG_WM, "View server did not start"); 4187 } 4188 return false; 4189 } 4190 isSystemSecure()4191 private boolean isSystemSecure() { 4192 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 4193 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 4194 } 4195 4196 /** 4197 * Stops the view server if it exists. 4198 * 4199 * @return True if the server stopped, false if it wasn't started or 4200 * couldn't be stopped. 4201 * 4202 * @see com.android.server.wm.ViewServer 4203 */ 4204 @Override stopViewServer()4205 public boolean stopViewServer() { 4206 if (isSystemSecure()) { 4207 return false; 4208 } 4209 4210 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 4211 return false; 4212 } 4213 4214 if (mViewServer != null) { 4215 return mViewServer.stop(); 4216 } 4217 return false; 4218 } 4219 4220 /** 4221 * Indicates whether the view server is running. 4222 * 4223 * @return True if the server is running, false otherwise. 4224 * 4225 * @see com.android.server.wm.ViewServer 4226 */ 4227 @Override isViewServerRunning()4228 public boolean isViewServerRunning() { 4229 if (isSystemSecure()) { 4230 return false; 4231 } 4232 4233 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 4234 return false; 4235 } 4236 4237 return mViewServer != null && mViewServer.isRunning(); 4238 } 4239 4240 /** 4241 * Lists all available windows in the system. The listing is written in the specified Socket's 4242 * output stream with the following syntax: windowHashCodeInHexadecimal windowName 4243 * Each line of the output represents a different window. 4244 * 4245 * @param client The remote client to send the listing to. 4246 * @return false if an error occurred, true otherwise. 4247 */ viewServerListWindows(Socket client)4248 boolean viewServerListWindows(Socket client) { 4249 if (isSystemSecure()) { 4250 return false; 4251 } 4252 4253 boolean result = true; 4254 4255 final ArrayList<WindowState> windows = new ArrayList(); 4256 synchronized (mWindowMap) { 4257 mRoot.forAllWindows(w -> { 4258 windows.add(w); 4259 }, false /* traverseTopToBottom */); 4260 } 4261 4262 BufferedWriter out = null; 4263 4264 // Any uncaught exception will crash the system process 4265 try { 4266 OutputStream clientStream = client.getOutputStream(); 4267 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 4268 4269 final int count = windows.size(); 4270 for (int i = 0; i < count; i++) { 4271 final WindowState w = windows.get(i); 4272 out.write(Integer.toHexString(System.identityHashCode(w))); 4273 out.write(' '); 4274 out.append(w.mAttrs.getTitle()); 4275 out.write('\n'); 4276 } 4277 4278 out.write("DONE.\n"); 4279 out.flush(); 4280 } catch (Exception e) { 4281 result = false; 4282 } finally { 4283 if (out != null) { 4284 try { 4285 out.close(); 4286 } catch (IOException e) { 4287 result = false; 4288 } 4289 } 4290 } 4291 4292 return result; 4293 } 4294 4295 // TODO(multidisplay): Extend to multiple displays. 4296 /** 4297 * Returns the focused window in the following format: 4298 * windowHashCodeInHexadecimal windowName 4299 * 4300 * @param client The remote client to send the listing to. 4301 * @return False if an error occurred, true otherwise. 4302 */ viewServerGetFocusedWindow(Socket client)4303 boolean viewServerGetFocusedWindow(Socket client) { 4304 if (isSystemSecure()) { 4305 return false; 4306 } 4307 4308 boolean result = true; 4309 4310 WindowState focusedWindow = getFocusedWindow(); 4311 4312 BufferedWriter out = null; 4313 4314 // Any uncaught exception will crash the system process 4315 try { 4316 OutputStream clientStream = client.getOutputStream(); 4317 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 4318 4319 if(focusedWindow != null) { 4320 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 4321 out.write(' '); 4322 out.append(focusedWindow.mAttrs.getTitle()); 4323 } 4324 out.write('\n'); 4325 out.flush(); 4326 } catch (Exception e) { 4327 result = false; 4328 } finally { 4329 if (out != null) { 4330 try { 4331 out.close(); 4332 } catch (IOException e) { 4333 result = false; 4334 } 4335 } 4336 } 4337 4338 return result; 4339 } 4340 4341 /** 4342 * Sends a command to a target window. The result of the command, if any, will be 4343 * written in the output stream of the specified socket. 4344 * 4345 * The parameters must follow this syntax: 4346 * windowHashcode extra 4347 * 4348 * Where XX is the length in characeters of the windowTitle. 4349 * 4350 * The first parameter is the target window. The window with the specified hashcode 4351 * will be the target. If no target can be found, nothing happens. The extra parameters 4352 * will be delivered to the target window and as parameters to the command itself. 4353 * 4354 * @param client The remote client to sent the result, if any, to. 4355 * @param command The command to execute. 4356 * @param parameters The command parameters. 4357 * 4358 * @return True if the command was successfully delivered, false otherwise. This does 4359 * not indicate whether the command itself was successful. 4360 */ viewServerWindowCommand(Socket client, String command, String parameters)4361 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 4362 if (isSystemSecure()) { 4363 return false; 4364 } 4365 4366 boolean success = true; 4367 Parcel data = null; 4368 Parcel reply = null; 4369 4370 BufferedWriter out = null; 4371 4372 // Any uncaught exception will crash the system process 4373 try { 4374 // Find the hashcode of the window 4375 int index = parameters.indexOf(' '); 4376 if (index == -1) { 4377 index = parameters.length(); 4378 } 4379 final String code = parameters.substring(0, index); 4380 int hashCode = (int) Long.parseLong(code, 16); 4381 4382 // Extract the command's parameter after the window description 4383 if (index < parameters.length()) { 4384 parameters = parameters.substring(index + 1); 4385 } else { 4386 parameters = ""; 4387 } 4388 4389 final WindowState window = findWindow(hashCode); 4390 if (window == null) { 4391 return false; 4392 } 4393 4394 data = Parcel.obtain(); 4395 data.writeInterfaceToken("android.view.IWindow"); 4396 data.writeString(command); 4397 data.writeString(parameters); 4398 data.writeInt(1); 4399 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 4400 4401 reply = Parcel.obtain(); 4402 4403 final IBinder binder = window.mClient.asBinder(); 4404 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 4405 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 4406 4407 reply.readException(); 4408 4409 if (!client.isOutputShutdown()) { 4410 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 4411 out.write("DONE\n"); 4412 out.flush(); 4413 } 4414 4415 } catch (Exception e) { 4416 Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e); 4417 success = false; 4418 } finally { 4419 if (data != null) { 4420 data.recycle(); 4421 } 4422 if (reply != null) { 4423 reply.recycle(); 4424 } 4425 if (out != null) { 4426 try { 4427 out.close(); 4428 } catch (IOException e) { 4429 4430 } 4431 } 4432 } 4433 4434 return success; 4435 } 4436 addWindowChangeListener(WindowChangeListener listener)4437 public void addWindowChangeListener(WindowChangeListener listener) { 4438 synchronized(mWindowMap) { 4439 mWindowChangeListeners.add(listener); 4440 } 4441 } 4442 removeWindowChangeListener(WindowChangeListener listener)4443 public void removeWindowChangeListener(WindowChangeListener listener) { 4444 synchronized(mWindowMap) { 4445 mWindowChangeListeners.remove(listener); 4446 } 4447 } 4448 notifyWindowsChanged()4449 private void notifyWindowsChanged() { 4450 WindowChangeListener[] windowChangeListeners; 4451 synchronized(mWindowMap) { 4452 if(mWindowChangeListeners.isEmpty()) { 4453 return; 4454 } 4455 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 4456 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 4457 } 4458 int N = windowChangeListeners.length; 4459 for(int i = 0; i < N; i++) { 4460 windowChangeListeners[i].windowsChanged(); 4461 } 4462 } 4463 notifyFocusChanged()4464 private void notifyFocusChanged() { 4465 WindowChangeListener[] windowChangeListeners; 4466 synchronized(mWindowMap) { 4467 if(mWindowChangeListeners.isEmpty()) { 4468 return; 4469 } 4470 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 4471 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 4472 } 4473 int N = windowChangeListeners.length; 4474 for(int i = 0; i < N; i++) { 4475 windowChangeListeners[i].focusChanged(); 4476 } 4477 } 4478 findWindow(int hashCode)4479 private WindowState findWindow(int hashCode) { 4480 if (hashCode == -1) { 4481 // TODO(multidisplay): Extend to multiple displays. 4482 return getFocusedWindow(); 4483 } 4484 4485 synchronized (mWindowMap) { 4486 return mRoot.getWindow((w) -> System.identityHashCode(w) == hashCode); 4487 } 4488 } 4489 4490 /** 4491 * Instruct the Activity Manager to fetch and update the current display's configuration and 4492 * broadcast them to config-changed listeners if appropriate. 4493 * NOTE: Can't be called with the window manager lock held since it call into activity manager. 4494 */ sendNewConfiguration(int displayId)4495 void sendNewConfiguration(int displayId) { 4496 try { 4497 final boolean configUpdated = mActivityManager.updateDisplayOverrideConfiguration( 4498 null /* values */, displayId); 4499 if (!configUpdated) { 4500 // Something changed (E.g. device rotation), but no configuration update is needed. 4501 // E.g. changing device rotation by 180 degrees. Go ahead and perform surface 4502 // placement to unfreeze the display since we froze it when the rotation was updated 4503 // in DisplayContent#updateRotationUnchecked. 4504 synchronized (mWindowMap) { 4505 if (mWaitingForConfig) { 4506 mWaitingForConfig = false; 4507 mLastFinishedFreezeSource = "config-unchanged"; 4508 final DisplayContent dc = mRoot.getDisplayContent(displayId); 4509 if (dc != null) { 4510 dc.setLayoutNeeded(); 4511 } 4512 mWindowPlacerLocked.performSurfacePlacement(); 4513 } 4514 } 4515 } 4516 } catch (RemoteException e) { 4517 } 4518 } 4519 computeNewConfiguration(int displayId)4520 public Configuration computeNewConfiguration(int displayId) { 4521 synchronized (mWindowMap) { 4522 return computeNewConfigurationLocked(displayId); 4523 } 4524 } 4525 computeNewConfigurationLocked(int displayId)4526 private Configuration computeNewConfigurationLocked(int displayId) { 4527 if (!mDisplayReady) { 4528 return null; 4529 } 4530 final Configuration config = new Configuration(); 4531 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 4532 displayContent.computeScreenConfiguration(config); 4533 return config; 4534 } 4535 notifyHardKeyboardStatusChange()4536 void notifyHardKeyboardStatusChange() { 4537 final boolean available; 4538 final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener; 4539 synchronized (mWindowMap) { 4540 listener = mHardKeyboardStatusChangeListener; 4541 available = mHardKeyboardAvailable; 4542 } 4543 if (listener != null) { 4544 listener.onHardKeyboardStatusChange(available); 4545 } 4546 } 4547 startMovingTask(IWindow window, float startX, float startY)4548 boolean startMovingTask(IWindow window, float startX, float startY) { 4549 WindowState win = null; 4550 synchronized (mWindowMap) { 4551 win = windowForClientLocked(null, window, false); 4552 // win shouldn't be null here, pass it down to startPositioningLocked 4553 // to get warning if it's null. 4554 if (!startPositioningLocked( 4555 win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) { 4556 return false; 4557 } 4558 } 4559 try { 4560 mActivityManager.setFocusedTask(win.getTask().mTaskId); 4561 } catch(RemoteException e) {} 4562 return true; 4563 } 4564 handleTapOutsideTask(DisplayContent displayContent, int x, int y)4565 private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) { 4566 int taskId = -1; 4567 synchronized (mWindowMap) { 4568 final Task task = displayContent.findTaskForResizePoint(x, y); 4569 if (task != null) { 4570 if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/, 4571 task.preserveOrientationOnResize(), x, y)) { 4572 return; 4573 } 4574 taskId = task.mTaskId; 4575 } else { 4576 taskId = displayContent.taskIdFromPoint(x, y); 4577 } 4578 } 4579 if (taskId >= 0) { 4580 try { 4581 mActivityManager.setFocusedTask(taskId); 4582 } catch(RemoteException e) {} 4583 } 4584 } 4585 startPositioningLocked(WindowState win, boolean resize, boolean preserveOrientation, float startX, float startY)4586 private boolean startPositioningLocked(WindowState win, boolean resize, 4587 boolean preserveOrientation, float startX, float startY) { 4588 if (DEBUG_TASK_POSITIONING) 4589 Slog.d(TAG_WM, "startPositioningLocked: " 4590 + "win=" + win + ", resize=" + resize + ", preserveOrientation=" 4591 + preserveOrientation + ", {" + startX + ", " + startY + "}"); 4592 4593 if (win == null || win.getAppToken() == null) { 4594 Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win); 4595 return false; 4596 } 4597 if (win.mInputChannel == null) { 4598 Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, " 4599 + " probably being removed"); 4600 return false; 4601 } 4602 4603 final DisplayContent displayContent = win.getDisplayContent(); 4604 if (displayContent == null) { 4605 Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win); 4606 return false; 4607 } 4608 4609 Display display = displayContent.getDisplay(); 4610 mTaskPositioner = new TaskPositioner(this); 4611 mTaskPositioner.register(display); 4612 mInputMonitor.updateInputWindowsLw(true /*force*/); 4613 4614 // We need to grab the touch focus so that the touch events during the 4615 // resizing/scrolling are not sent to the app. 'win' is the main window 4616 // of the app, it may not have focus since there might be other windows 4617 // on top (eg. a dialog window). 4618 WindowState transferFocusFromWin = win; 4619 if (mCurrentFocus != null && mCurrentFocus != win 4620 && mCurrentFocus.mAppToken == win.mAppToken) { 4621 transferFocusFromWin = mCurrentFocus; 4622 } 4623 if (!mInputManager.transferTouchFocus( 4624 transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) { 4625 Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus"); 4626 mTaskPositioner.unregister(); 4627 mTaskPositioner = null; 4628 mInputMonitor.updateInputWindowsLw(true /*force*/); 4629 return false; 4630 } 4631 4632 mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY); 4633 return true; 4634 } 4635 finishPositioning()4636 private void finishPositioning() { 4637 if (DEBUG_TASK_POSITIONING) { 4638 Slog.d(TAG_WM, "finishPositioning"); 4639 } 4640 synchronized (mWindowMap) { 4641 if (mTaskPositioner != null) { 4642 mTaskPositioner.unregister(); 4643 mTaskPositioner = null; 4644 mInputMonitor.updateInputWindowsLw(true /*force*/); 4645 } 4646 } 4647 } 4648 4649 // ------------------------------------------------------------- 4650 // Drag and drop 4651 // ------------------------------------------------------------- 4652 prepareDragSurface(IWindow window, SurfaceSession session, int flags, int width, int height, Surface outSurface)4653 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 4654 int flags, int width, int height, Surface outSurface) { 4655 if (DEBUG_DRAG) { 4656 Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height 4657 + " flags=" + Integer.toHexString(flags) + " win=" + window 4658 + " asbinder=" + window.asBinder()); 4659 } 4660 4661 final int callerPid = Binder.getCallingPid(); 4662 final int callerUid = Binder.getCallingUid(); 4663 final long origId = Binder.clearCallingIdentity(); 4664 IBinder token = null; 4665 4666 try { 4667 synchronized (mWindowMap) { 4668 try { 4669 if (mDragState == null) { 4670 // TODO(multi-display): support other displays 4671 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 4672 final Display display = displayContent.getDisplay(); 4673 4674 SurfaceControl surface = new SurfaceControl(session, "drag surface", 4675 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 4676 surface.setLayerStack(display.getLayerStack()); 4677 float alpha = 1; 4678 if ((flags & View.DRAG_FLAG_OPAQUE) == 0) { 4679 alpha = DRAG_SHADOW_ALPHA_TRANSPARENT; 4680 } 4681 surface.setAlpha(alpha); 4682 4683 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG " 4684 + surface + ": CREATE"); 4685 outSurface.copyFrom(surface); 4686 final IBinder winBinder = window.asBinder(); 4687 token = new Binder(); 4688 mDragState = new DragState(this, token, surface, flags, winBinder); 4689 mDragState.mPid = callerPid; 4690 mDragState.mUid = callerUid; 4691 mDragState.mOriginalAlpha = alpha; 4692 token = mDragState.mToken = new Binder(); 4693 4694 // 5 second timeout for this window to actually begin the drag 4695 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 4696 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 4697 mH.sendMessageDelayed(msg, 5000); 4698 } else { 4699 Slog.w(TAG_WM, "Drag already in progress"); 4700 } 4701 } catch (OutOfResourcesException e) { 4702 Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e); 4703 if (mDragState != null) { 4704 mDragState.reset(); 4705 mDragState = null; 4706 } 4707 } 4708 } 4709 } finally { 4710 Binder.restoreCallingIdentity(origId); 4711 } 4712 4713 return token; 4714 } 4715 4716 // ------------------------------------------------------------- 4717 // Input Events and Focus Management 4718 // ------------------------------------------------------------- 4719 4720 final InputMonitor mInputMonitor = new InputMonitor(this); 4721 private boolean mEventDispatchingEnabled; 4722 4723 @Override setEventDispatching(boolean enabled)4724 public void setEventDispatching(boolean enabled) { 4725 if (!checkCallingPermission(MANAGE_APP_TOKENS, "setEventDispatching()")) { 4726 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4727 } 4728 4729 synchronized (mWindowMap) { 4730 mEventDispatchingEnabled = enabled; 4731 if (mDisplayEnabled) { 4732 mInputMonitor.setEventDispatchingLw(enabled); 4733 } 4734 } 4735 } 4736 getFocusedWindow()4737 private WindowState getFocusedWindow() { 4738 synchronized (mWindowMap) { 4739 return getFocusedWindowLocked(); 4740 } 4741 } 4742 getFocusedWindowLocked()4743 private WindowState getFocusedWindowLocked() { 4744 return mCurrentFocus; 4745 } 4746 getImeFocusStackLocked()4747 TaskStack getImeFocusStackLocked() { 4748 // Don't use mCurrentFocus.getStack() because it returns home stack for system windows. 4749 // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE 4750 // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved 4751 // to make room for IME, but the window is not the focused window that's taking input. 4752 return (mFocusedApp != null && mFocusedApp.getTask() != null) ? 4753 mFocusedApp.getTask().mStack : null; 4754 } 4755 detectSafeMode()4756 public boolean detectSafeMode() { 4757 if (!mInputMonitor.waitForInputDevicesReady( 4758 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 4759 Slog.w(TAG_WM, "Devices still not ready after waiting " 4760 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 4761 + " milliseconds before attempting to detect safe mode."); 4762 } 4763 4764 if (Settings.Global.getInt( 4765 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) { 4766 return false; 4767 } 4768 4769 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 4770 KeyEvent.KEYCODE_MENU); 4771 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 4772 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 4773 KeyEvent.KEYCODE_DPAD_CENTER); 4774 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 4775 InputManagerService.BTN_MOUSE); 4776 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 4777 KeyEvent.KEYCODE_VOLUME_DOWN); 4778 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 4779 || volumeDownState > 0; 4780 try { 4781 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0 4782 || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) { 4783 mSafeMode = true; 4784 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 4785 } 4786 } catch (IllegalArgumentException e) { 4787 } 4788 if (mSafeMode) { 4789 Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 4790 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 4791 SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1"); 4792 } else { 4793 Log.i(TAG_WM, "SAFE MODE not enabled"); 4794 } 4795 mPolicy.setSafeMode(mSafeMode); 4796 return mSafeMode; 4797 } 4798 displayReady()4799 public void displayReady() { 4800 for (Display display : mDisplays) { 4801 displayReady(display.getDisplayId()); 4802 } 4803 4804 synchronized(mWindowMap) { 4805 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 4806 if (mMaxUiWidth > 0) { 4807 displayContent.setMaxUiWidth(mMaxUiWidth); 4808 } 4809 readForcedDisplayPropertiesLocked(displayContent); 4810 mDisplayReady = true; 4811 } 4812 4813 try { 4814 mActivityManager.updateConfiguration(null); 4815 } catch (RemoteException e) { 4816 } 4817 4818 synchronized(mWindowMap) { 4819 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 4820 PackageManager.FEATURE_TOUCHSCREEN); 4821 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 4822 } 4823 4824 try { 4825 mActivityManager.updateConfiguration(null); 4826 } catch (RemoteException e) { 4827 } 4828 4829 updateCircularDisplayMaskIfNeeded(); 4830 } 4831 displayReady(int displayId)4832 private void displayReady(int displayId) { 4833 synchronized(mWindowMap) { 4834 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 4835 if (displayContent != null) { 4836 mAnimator.addDisplayLocked(displayId); 4837 displayContent.initializeDisplayBaseInfo(); 4838 } 4839 } 4840 } 4841 systemReady()4842 public void systemReady() { 4843 mPolicy.systemReady(); 4844 mTaskSnapshotController.systemReady(); 4845 mHasWideColorGamutSupport = queryWideColorGamutSupport(); 4846 } 4847 queryWideColorGamutSupport()4848 private static boolean queryWideColorGamutSupport() { 4849 try { 4850 ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService(); 4851 OptionalBool hasWideColor = surfaceFlinger.hasWideColorDisplay(); 4852 if (hasWideColor != null) { 4853 return hasWideColor.value; 4854 } 4855 } catch (RemoteException e) { 4856 // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store 4857 } 4858 return false; 4859 } 4860 4861 // ------------------------------------------------------------- 4862 // Async Handler 4863 // ------------------------------------------------------------- 4864 4865 final class H extends android.os.Handler { 4866 public static final int REPORT_FOCUS_CHANGE = 2; 4867 public static final int REPORT_LOSING_FOCUS = 3; 4868 public static final int WINDOW_FREEZE_TIMEOUT = 11; 4869 4870 public static final int APP_TRANSITION_TIMEOUT = 13; 4871 public static final int PERSIST_ANIMATION_SCALE = 14; 4872 public static final int FORCE_GC = 15; 4873 public static final int ENABLE_SCREEN = 16; 4874 public static final int APP_FREEZE_TIMEOUT = 17; 4875 public static final int SEND_NEW_CONFIGURATION = 18; 4876 public static final int REPORT_WINDOWS_CHANGE = 19; 4877 public static final int DRAG_START_TIMEOUT = 20; 4878 public static final int DRAG_END_TIMEOUT = 21; 4879 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 4880 public static final int BOOT_TIMEOUT = 23; 4881 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 4882 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 4883 public static final int DO_ANIMATION_CALLBACK = 26; 4884 4885 public static final int CLIENT_FREEZE_TIMEOUT = 30; 4886 public static final int TAP_OUTSIDE_TASK = 31; 4887 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 4888 4889 public static final int ALL_WINDOWS_DRAWN = 33; 4890 4891 public static final int NEW_ANIMATOR_SCALE = 34; 4892 4893 public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35; 4894 public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36; 4895 4896 public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37; 4897 public static final int RESET_ANR_MESSAGE = 38; 4898 public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39; 4899 4900 public static final int FINISH_TASK_POSITIONING = 40; 4901 4902 public static final int UPDATE_DOCKED_STACK_DIVIDER = 41; 4903 4904 public static final int TEAR_DOWN_DRAG_AND_DROP_INPUT = 44; 4905 4906 public static final int WINDOW_REPLACEMENT_TIMEOUT = 46; 4907 4908 public static final int NOTIFY_APP_TRANSITION_STARTING = 47; 4909 public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48; 4910 public static final int NOTIFY_APP_TRANSITION_FINISHED = 49; 4911 public static final int UPDATE_ANIMATION_SCALE = 51; 4912 public static final int WINDOW_HIDE_TIMEOUT = 52; 4913 public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53; 4914 public static final int SEAMLESS_ROTATION_TIMEOUT = 54; 4915 public static final int RESTORE_POINTER_ICON = 55; 4916 public static final int NOTIFY_KEYGUARD_FLAGS_CHANGED = 56; 4917 public static final int NOTIFY_KEYGUARD_TRUSTED_CHANGED = 57; 4918 public static final int SET_HAS_OVERLAY_UI = 58; 4919 public static final int RECOMPUTE_FOCUS = 61; 4920 4921 /** 4922 * Used to denote that an integer field in a message will not be used. 4923 */ 4924 public static final int UNUSED = 0; 4925 4926 @Override handleMessage(Message msg)4927 public void handleMessage(Message msg) { 4928 if (DEBUG_WINDOW_TRACE) { 4929 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what); 4930 } 4931 switch (msg.what) { 4932 case REPORT_FOCUS_CHANGE: { 4933 WindowState lastFocus; 4934 WindowState newFocus; 4935 4936 AccessibilityController accessibilityController = null; 4937 4938 synchronized(mWindowMap) { 4939 // TODO(multidisplay): Accessibility supported only of default desiplay. 4940 if (mAccessibilityController != null && getDefaultDisplayContentLocked() 4941 .getDisplayId() == DEFAULT_DISPLAY) { 4942 accessibilityController = mAccessibilityController; 4943 } 4944 4945 lastFocus = mLastFocus; 4946 newFocus = mCurrentFocus; 4947 if (lastFocus == newFocus) { 4948 // Focus is not changing, so nothing to do. 4949 return; 4950 } 4951 mLastFocus = newFocus; 4952 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus + 4953 " to " + newFocus); 4954 if (newFocus != null && lastFocus != null 4955 && !newFocus.isDisplayedLw()) { 4956 //Slog.i(TAG_WM, "Delaying loss of focus..."); 4957 mLosingFocus.add(lastFocus); 4958 lastFocus = null; 4959 } 4960 } 4961 4962 // First notify the accessibility manager for the change so it has 4963 // the windows before the newly focused one starts firing eventgs. 4964 if (accessibilityController != null) { 4965 accessibilityController.onWindowFocusChangedNotLocked(); 4966 } 4967 4968 //System.out.println("Changing focus from " + lastFocus 4969 // + " to " + newFocus); 4970 if (newFocus != null) { 4971 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus); 4972 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 4973 notifyFocusChanged(); 4974 } 4975 4976 if (lastFocus != null) { 4977 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus); 4978 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 4979 } 4980 } break; 4981 4982 case REPORT_LOSING_FOCUS: { 4983 ArrayList<WindowState> losers; 4984 4985 synchronized(mWindowMap) { 4986 losers = mLosingFocus; 4987 mLosingFocus = new ArrayList<WindowState>(); 4988 } 4989 4990 final int N = losers.size(); 4991 for (int i=0; i<N; i++) { 4992 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " + 4993 losers.get(i)); 4994 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 4995 } 4996 } break; 4997 4998 case WINDOW_FREEZE_TIMEOUT: { 4999 // TODO(multidisplay): Can non-default displays rotate? 5000 synchronized (mWindowMap) { 5001 getDefaultDisplayContentLocked().onWindowFreezeTimeout(); 5002 } 5003 break; 5004 } 5005 5006 case APP_TRANSITION_TIMEOUT: { 5007 synchronized (mWindowMap) { 5008 if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty() 5009 || !mClosingApps.isEmpty()) { 5010 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT." 5011 + " isTransitionSet()=" + mAppTransition.isTransitionSet() 5012 + " mOpeningApps.size()=" + mOpeningApps.size() 5013 + " mClosingApps.size()=" + mClosingApps.size()); 5014 mAppTransition.setTimeout(); 5015 mWindowPlacerLocked.performSurfacePlacement(); 5016 } 5017 } 5018 break; 5019 } 5020 5021 case PERSIST_ANIMATION_SCALE: { 5022 Settings.Global.putFloat(mContext.getContentResolver(), 5023 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 5024 Settings.Global.putFloat(mContext.getContentResolver(), 5025 Settings.Global.TRANSITION_ANIMATION_SCALE, 5026 mTransitionAnimationScaleSetting); 5027 Settings.Global.putFloat(mContext.getContentResolver(), 5028 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 5029 break; 5030 } 5031 5032 case UPDATE_ANIMATION_SCALE: { 5033 @UpdateAnimationScaleMode 5034 final int mode = msg.arg1; 5035 switch (mode) { 5036 case WINDOW_ANIMATION_SCALE: { 5037 mWindowAnimationScaleSetting = Settings.Global.getFloat( 5038 mContext.getContentResolver(), 5039 Settings.Global.WINDOW_ANIMATION_SCALE, 5040 mWindowAnimationScaleSetting); 5041 break; 5042 } 5043 case TRANSITION_ANIMATION_SCALE: { 5044 mTransitionAnimationScaleSetting = Settings.Global.getFloat( 5045 mContext.getContentResolver(), 5046 Settings.Global.TRANSITION_ANIMATION_SCALE, 5047 mTransitionAnimationScaleSetting); 5048 break; 5049 } 5050 case ANIMATION_DURATION_SCALE: { 5051 mAnimatorDurationScaleSetting = Settings.Global.getFloat( 5052 mContext.getContentResolver(), 5053 Settings.Global.ANIMATOR_DURATION_SCALE, 5054 mAnimatorDurationScaleSetting); 5055 dispatchNewAnimatorScaleLocked(null); 5056 break; 5057 } 5058 } 5059 break; 5060 } 5061 5062 case FORCE_GC: { 5063 synchronized (mWindowMap) { 5064 // Since we're holding both mWindowMap and mAnimator we don't need to 5065 // hold mAnimator.mLayoutToAnim. 5066 if (mAnimator.isAnimating() || mAnimator.isAnimationScheduled()) { 5067 // If we are animating, don't do the gc now but 5068 // delay a bit so we don't interrupt the animation. 5069 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 5070 return; 5071 } 5072 // If we are currently rotating the display, it will 5073 // schedule a new message when done. 5074 if (mDisplayFrozen) { 5075 return; 5076 } 5077 } 5078 Runtime.getRuntime().gc(); 5079 break; 5080 } 5081 5082 case ENABLE_SCREEN: { 5083 performEnableScreen(); 5084 break; 5085 } 5086 5087 case APP_FREEZE_TIMEOUT: { 5088 synchronized (mWindowMap) { 5089 Slog.w(TAG_WM, "App freeze timeout expired."); 5090 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 5091 for (int i = mAppFreezeListeners.size() - 1; i >=0 ; --i) { 5092 mAppFreezeListeners.get(i).onAppFreezeTimeout(); 5093 } 5094 } 5095 break; 5096 } 5097 5098 case CLIENT_FREEZE_TIMEOUT: { 5099 synchronized (mWindowMap) { 5100 if (mClientFreezingScreen) { 5101 mClientFreezingScreen = false; 5102 mLastFinishedFreezeSource = "client-timeout"; 5103 stopFreezingDisplayLocked(); 5104 } 5105 } 5106 break; 5107 } 5108 5109 case SEND_NEW_CONFIGURATION: { 5110 removeMessages(SEND_NEW_CONFIGURATION, msg.obj); 5111 final int displayId = (Integer) msg.obj; 5112 if (mRoot.getDisplayContent(displayId) != null) { 5113 sendNewConfiguration(displayId); 5114 } else { 5115 // Message could come after display has already been removed. 5116 if (DEBUG_CONFIGURATION) { 5117 Slog.w(TAG, "Trying to send configuration to non-existing displayId=" 5118 + displayId); 5119 } 5120 } 5121 break; 5122 } 5123 5124 case REPORT_WINDOWS_CHANGE: { 5125 if (mWindowsChanged) { 5126 synchronized (mWindowMap) { 5127 mWindowsChanged = false; 5128 } 5129 notifyWindowsChanged(); 5130 } 5131 break; 5132 } 5133 5134 case DRAG_START_TIMEOUT: { 5135 IBinder win = (IBinder)msg.obj; 5136 if (DEBUG_DRAG) { 5137 Slog.w(TAG_WM, "Timeout starting drag by win " + win); 5138 } 5139 synchronized (mWindowMap) { 5140 // !!! TODO: ANR the app that has failed to start the drag in time 5141 if (mDragState != null) { 5142 mDragState.unregister(); 5143 mDragState.reset(); 5144 mDragState = null; 5145 } 5146 } 5147 break; 5148 } 5149 5150 case DRAG_END_TIMEOUT: { 5151 IBinder win = (IBinder)msg.obj; 5152 if (DEBUG_DRAG) { 5153 Slog.w(TAG_WM, "Timeout ending drag to win " + win); 5154 } 5155 synchronized (mWindowMap) { 5156 // !!! TODO: ANR the drag-receiving app 5157 if (mDragState != null) { 5158 mDragState.mDragResult = false; 5159 mDragState.endDragLw(); 5160 } 5161 } 5162 break; 5163 } 5164 5165 case TEAR_DOWN_DRAG_AND_DROP_INPUT: { 5166 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ending; tearing down input channel"); 5167 DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj; 5168 if (interceptor != null) { 5169 synchronized (mWindowMap) { 5170 interceptor.tearDown(); 5171 } 5172 } 5173 } 5174 break; 5175 5176 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 5177 notifyHardKeyboardStatusChange(); 5178 break; 5179 } 5180 5181 case BOOT_TIMEOUT: { 5182 performBootTimeout(); 5183 break; 5184 } 5185 5186 case WAITING_FOR_DRAWN_TIMEOUT: { 5187 Runnable callback = null; 5188 synchronized (mWindowMap) { 5189 Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 5190 mWaitingForDrawn.clear(); 5191 callback = mWaitingForDrawnCallback; 5192 mWaitingForDrawnCallback = null; 5193 } 5194 if (callback != null) { 5195 callback.run(); 5196 } 5197 break; 5198 } 5199 5200 case SHOW_STRICT_MODE_VIOLATION: { 5201 showStrictModeViolation(msg.arg1, msg.arg2); 5202 break; 5203 } 5204 5205 case SHOW_CIRCULAR_DISPLAY_MASK: { 5206 showCircularMask(msg.arg1 == 1); 5207 break; 5208 } 5209 5210 case SHOW_EMULATOR_DISPLAY_OVERLAY: { 5211 showEmulatorDisplayOverlay(); 5212 break; 5213 } 5214 5215 case DO_ANIMATION_CALLBACK: { 5216 try { 5217 ((IRemoteCallback)msg.obj).sendResult(null); 5218 } catch (RemoteException e) { 5219 } 5220 break; 5221 } 5222 5223 case TAP_OUTSIDE_TASK: { 5224 handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2); 5225 } 5226 break; 5227 5228 case FINISH_TASK_POSITIONING: { 5229 finishPositioning(); 5230 } 5231 break; 5232 5233 case NOTIFY_ACTIVITY_DRAWN: 5234 try { 5235 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 5236 } catch (RemoteException e) { 5237 } 5238 break; 5239 case ALL_WINDOWS_DRAWN: { 5240 Runnable callback; 5241 synchronized (mWindowMap) { 5242 callback = mWaitingForDrawnCallback; 5243 mWaitingForDrawnCallback = null; 5244 } 5245 if (callback != null) { 5246 callback.run(); 5247 } 5248 break; 5249 } 5250 case NEW_ANIMATOR_SCALE: { 5251 float scale = getCurrentAnimatorScale(); 5252 ValueAnimator.setDurationScale(scale); 5253 Session session = (Session)msg.obj; 5254 if (session != null) { 5255 try { 5256 session.mCallback.onAnimatorScaleChanged(scale); 5257 } catch (RemoteException e) { 5258 } 5259 } else { 5260 ArrayList<IWindowSessionCallback> callbacks 5261 = new ArrayList<IWindowSessionCallback>(); 5262 synchronized (mWindowMap) { 5263 for (int i=0; i<mSessions.size(); i++) { 5264 callbacks.add(mSessions.valueAt(i).mCallback); 5265 } 5266 5267 } 5268 for (int i=0; i<callbacks.size(); i++) { 5269 try { 5270 callbacks.get(i).onAnimatorScaleChanged(scale); 5271 } catch (RemoteException e) { 5272 } 5273 } 5274 } 5275 } 5276 break; 5277 case CHECK_IF_BOOT_ANIMATION_FINISHED: { 5278 final boolean bootAnimationComplete; 5279 synchronized (mWindowMap) { 5280 if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:"); 5281 bootAnimationComplete = checkBootAnimationCompleteLocked(); 5282 } 5283 if (bootAnimationComplete) { 5284 performEnableScreen(); 5285 } 5286 } 5287 break; 5288 case RESET_ANR_MESSAGE: { 5289 synchronized (mWindowMap) { 5290 mLastANRState = null; 5291 } 5292 mAmInternal.clearSavedANRState(); 5293 } 5294 break; 5295 case WALLPAPER_DRAW_PENDING_TIMEOUT: { 5296 synchronized (mWindowMap) { 5297 if (mRoot.mWallpaperController.processWallpaperDrawPendingTimeout()) { 5298 mWindowPlacerLocked.performSurfacePlacement(); 5299 } 5300 } 5301 } 5302 break; 5303 case UPDATE_DOCKED_STACK_DIVIDER: { 5304 synchronized (mWindowMap) { 5305 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 5306 displayContent.getDockedDividerController().reevaluateVisibility(false); 5307 displayContent.adjustForImeIfNeeded(); 5308 } 5309 } 5310 break; 5311 case WINDOW_REPLACEMENT_TIMEOUT: { 5312 synchronized (mWindowMap) { 5313 for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) { 5314 final AppWindowToken token = mWindowReplacementTimeouts.get(i); 5315 token.onWindowReplacementTimeout(); 5316 } 5317 mWindowReplacementTimeouts.clear(); 5318 } 5319 } 5320 break; 5321 case NOTIFY_APP_TRANSITION_STARTING: { 5322 mAmInternal.notifyAppTransitionStarting((SparseIntArray) msg.obj, 5323 msg.getWhen()); 5324 } 5325 break; 5326 case NOTIFY_APP_TRANSITION_CANCELLED: { 5327 mAmInternal.notifyAppTransitionCancelled(); 5328 } 5329 break; 5330 case NOTIFY_APP_TRANSITION_FINISHED: { 5331 mAmInternal.notifyAppTransitionFinished(); 5332 } 5333 break; 5334 case WINDOW_HIDE_TIMEOUT: { 5335 final WindowState window = (WindowState) msg.obj; 5336 synchronized(mWindowMap) { 5337 // TODO: This is all about fixing b/21693547 5338 // where partially initialized Toasts get stuck 5339 // around and keep the screen on. We'd like 5340 // to just remove the toast...but this can cause clients 5341 // who miss the timeout due to normal circumstances (e.g. 5342 // running under debugger) to crash (b/29105388). The windows will 5343 // eventually be removed when the client process finishes. 5344 // The best we can do for now is remove the FLAG_KEEP_SCREEN_ON 5345 // and prevent the symptoms of b/21693547. Since apps don't 5346 // support windows being removed under them we hide the window 5347 // and it will be removed when the app dies. 5348 window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON; 5349 window.hidePermanentlyLw(); 5350 window.setDisplayLayoutNeeded(); 5351 mWindowPlacerLocked.performSurfacePlacement(); 5352 } 5353 } 5354 break; 5355 case NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED: { 5356 mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1); 5357 } 5358 break; 5359 case RESTORE_POINTER_ICON: { 5360 synchronized (mWindowMap) { 5361 restorePointerIconLocked((DisplayContent)msg.obj, msg.arg1, msg.arg2); 5362 } 5363 } 5364 break; 5365 case SEAMLESS_ROTATION_TIMEOUT: { 5366 // Rotation only supported on primary display. 5367 // TODO(multi-display) 5368 synchronized(mWindowMap) { 5369 final DisplayContent dc = getDefaultDisplayContentLocked(); 5370 dc.onSeamlessRotationTimeout(); 5371 } 5372 } 5373 break; 5374 case NOTIFY_KEYGUARD_FLAGS_CHANGED: { 5375 mAmInternal.notifyKeyguardFlagsChanged((Runnable) msg.obj); 5376 } 5377 break; 5378 case NOTIFY_KEYGUARD_TRUSTED_CHANGED: { 5379 mAmInternal.notifyKeyguardTrustedChanged(); 5380 } 5381 break; 5382 case SET_HAS_OVERLAY_UI: { 5383 mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1); 5384 } 5385 break; 5386 case RECOMPUTE_FOCUS: { 5387 synchronized (mWindowMap) { 5388 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 5389 true /* updateInputWindows */); 5390 } 5391 } 5392 break; 5393 } 5394 if (DEBUG_WINDOW_TRACE) { 5395 Slog.v(TAG_WM, "handleMessage: exit"); 5396 } 5397 } 5398 } 5399 destroyPreservedSurfaceLocked()5400 void destroyPreservedSurfaceLocked() { 5401 for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) { 5402 final WindowState w = mDestroyPreservedSurface.get(i); 5403 w.mWinAnimator.destroyPreservedSurfaceLocked(); 5404 } 5405 mDestroyPreservedSurface.clear(); 5406 } 5407 stopUsingSavedSurfaceLocked()5408 void stopUsingSavedSurfaceLocked() { 5409 for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) { 5410 final AppWindowToken wtoken = mFinishedEarlyAnim.get(i); 5411 wtoken.stopUsingSavedSurfaceLocked(); 5412 } 5413 mFinishedEarlyAnim.clear(); 5414 } 5415 5416 // ------------------------------------------------------------- 5417 // IWindowManager API 5418 // ------------------------------------------------------------- 5419 5420 @Override openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext)5421 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 5422 IInputContext inputContext) { 5423 if (client == null) throw new IllegalArgumentException("null client"); 5424 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 5425 Session session = new Session(this, callback, client, inputContext); 5426 return session; 5427 } 5428 5429 @Override inputMethodClientHasFocus(IInputMethodClient client)5430 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 5431 synchronized (mWindowMap) { 5432 // TODO: multi-display 5433 if (getDefaultDisplayContentLocked().inputMethodClientHasFocus(client)) { 5434 return true; 5435 } 5436 5437 // Okay, how about this... what is the current focus? 5438 // It seems in some cases we may not have moved the IM 5439 // target window, such as when it was in a pop-up window, 5440 // so let's also look at the current focus. (An example: 5441 // go to Gmail, start searching so the keyboard goes up, 5442 // press home. Sometimes the IME won't go down.) 5443 // Would be nice to fix this more correctly, but it's 5444 // way at the end of a release, and this should be good enough. 5445 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 5446 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 5447 return true; 5448 } 5449 } 5450 return false; 5451 } 5452 5453 @Override getInitialDisplaySize(int displayId, Point size)5454 public void getInitialDisplaySize(int displayId, Point size) { 5455 synchronized (mWindowMap) { 5456 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 5457 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 5458 size.x = displayContent.mInitialDisplayWidth; 5459 size.y = displayContent.mInitialDisplayHeight; 5460 } 5461 } 5462 } 5463 5464 @Override getBaseDisplaySize(int displayId, Point size)5465 public void getBaseDisplaySize(int displayId, Point size) { 5466 synchronized (mWindowMap) { 5467 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 5468 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 5469 size.x = displayContent.mBaseDisplayWidth; 5470 size.y = displayContent.mBaseDisplayHeight; 5471 } 5472 } 5473 } 5474 5475 @Override setForcedDisplaySize(int displayId, int width, int height)5476 public void setForcedDisplaySize(int displayId, int width, int height) { 5477 if (mContext.checkCallingOrSelfPermission( 5478 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 5479 PackageManager.PERMISSION_GRANTED) { 5480 throw new SecurityException("Must hold permission " + 5481 android.Manifest.permission.WRITE_SECURE_SETTINGS); 5482 } 5483 if (displayId != DEFAULT_DISPLAY) { 5484 throw new IllegalArgumentException("Can only set the default display"); 5485 } 5486 final long ident = Binder.clearCallingIdentity(); 5487 try { 5488 synchronized(mWindowMap) { 5489 // Set some sort of reasonable bounds on the size of the display that we 5490 // will try to emulate. 5491 final int MIN_WIDTH = 200; 5492 final int MIN_HEIGHT = 200; 5493 final int MAX_SCALE = 2; 5494 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 5495 if (displayContent != null) { 5496 width = Math.min(Math.max(width, MIN_WIDTH), 5497 displayContent.mInitialDisplayWidth * MAX_SCALE); 5498 height = Math.min(Math.max(height, MIN_HEIGHT), 5499 displayContent.mInitialDisplayHeight * MAX_SCALE); 5500 setForcedDisplaySizeLocked(displayContent, width, height); 5501 Settings.Global.putString(mContext.getContentResolver(), 5502 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 5503 } 5504 } 5505 } finally { 5506 Binder.restoreCallingIdentity(ident); 5507 } 5508 } 5509 5510 @Override setForcedDisplayScalingMode(int displayId, int mode)5511 public void setForcedDisplayScalingMode(int displayId, int mode) { 5512 if (mContext.checkCallingOrSelfPermission( 5513 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 5514 PackageManager.PERMISSION_GRANTED) { 5515 throw new SecurityException("Must hold permission " + 5516 android.Manifest.permission.WRITE_SECURE_SETTINGS); 5517 } 5518 if (displayId != DEFAULT_DISPLAY) { 5519 throw new IllegalArgumentException("Can only set the default display"); 5520 } 5521 final long ident = Binder.clearCallingIdentity(); 5522 try { 5523 synchronized(mWindowMap) { 5524 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 5525 if (displayContent != null) { 5526 if (mode < 0 || mode > 1) { 5527 mode = 0; 5528 } 5529 setForcedDisplayScalingModeLocked(displayContent, mode); 5530 Settings.Global.putInt(mContext.getContentResolver(), 5531 Settings.Global.DISPLAY_SCALING_FORCE, mode); 5532 } 5533 } 5534 } finally { 5535 Binder.restoreCallingIdentity(ident); 5536 } 5537 } 5538 setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode)5539 private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) { 5540 Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off")); 5541 displayContent.mDisplayScalingDisabled = (mode != 0); 5542 reconfigureDisplayLocked(displayContent); 5543 } 5544 readForcedDisplayPropertiesLocked(final DisplayContent displayContent)5545 private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) { 5546 // Display size. 5547 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 5548 Settings.Global.DISPLAY_SIZE_FORCED); 5549 if (sizeStr == null || sizeStr.length() == 0) { 5550 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 5551 } 5552 if (sizeStr != null && sizeStr.length() > 0) { 5553 final int pos = sizeStr.indexOf(','); 5554 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 5555 int width, height; 5556 try { 5557 width = Integer.parseInt(sizeStr.substring(0, pos)); 5558 height = Integer.parseInt(sizeStr.substring(pos+1)); 5559 if (displayContent.mBaseDisplayWidth != width 5560 || displayContent.mBaseDisplayHeight != height) { 5561 Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height); 5562 displayContent.updateBaseDisplayMetrics(width, height, 5563 displayContent.mBaseDisplayDensity); 5564 } 5565 } catch (NumberFormatException ex) { 5566 } 5567 } 5568 } 5569 5570 // Display density. 5571 final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId); 5572 if (density != 0) { 5573 displayContent.mBaseDisplayDensity = density; 5574 } 5575 5576 // Display scaling mode. 5577 int mode = Settings.Global.getInt(mContext.getContentResolver(), 5578 Settings.Global.DISPLAY_SCALING_FORCE, 0); 5579 if (mode != 0) { 5580 Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED"); 5581 displayContent.mDisplayScalingDisabled = true; 5582 } 5583 } 5584 5585 // displayContent must not be null setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height)5586 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 5587 Slog.i(TAG_WM, "Using new display size: " + width + "x" + height); 5588 displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity); 5589 reconfigureDisplayLocked(displayContent); 5590 } 5591 5592 @Override clearForcedDisplaySize(int displayId)5593 public void clearForcedDisplaySize(int displayId) { 5594 if (mContext.checkCallingOrSelfPermission( 5595 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 5596 PackageManager.PERMISSION_GRANTED) { 5597 throw new SecurityException("Must hold permission " + 5598 android.Manifest.permission.WRITE_SECURE_SETTINGS); 5599 } 5600 if (displayId != DEFAULT_DISPLAY) { 5601 throw new IllegalArgumentException("Can only set the default display"); 5602 } 5603 final long ident = Binder.clearCallingIdentity(); 5604 try { 5605 synchronized(mWindowMap) { 5606 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 5607 if (displayContent != null) { 5608 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 5609 displayContent.mInitialDisplayHeight); 5610 Settings.Global.putString(mContext.getContentResolver(), 5611 Settings.Global.DISPLAY_SIZE_FORCED, ""); 5612 } 5613 } 5614 } finally { 5615 Binder.restoreCallingIdentity(ident); 5616 } 5617 } 5618 5619 @Override getInitialDisplayDensity(int displayId)5620 public int getInitialDisplayDensity(int displayId) { 5621 synchronized (mWindowMap) { 5622 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 5623 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 5624 return displayContent.mInitialDisplayDensity; 5625 } 5626 } 5627 return -1; 5628 } 5629 5630 @Override getBaseDisplayDensity(int displayId)5631 public int getBaseDisplayDensity(int displayId) { 5632 synchronized (mWindowMap) { 5633 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 5634 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 5635 return displayContent.mBaseDisplayDensity; 5636 } 5637 } 5638 return -1; 5639 } 5640 5641 @Override setForcedDisplayDensityForUser(int displayId, int density, int userId)5642 public void setForcedDisplayDensityForUser(int displayId, int density, int userId) { 5643 if (mContext.checkCallingOrSelfPermission( 5644 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 5645 PackageManager.PERMISSION_GRANTED) { 5646 throw new SecurityException("Must hold permission " + 5647 android.Manifest.permission.WRITE_SECURE_SETTINGS); 5648 } 5649 if (displayId != DEFAULT_DISPLAY) { 5650 throw new IllegalArgumentException("Can only set the default display"); 5651 } 5652 5653 final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 5654 Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser", 5655 null); 5656 final long ident = Binder.clearCallingIdentity(); 5657 try { 5658 synchronized(mWindowMap) { 5659 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 5660 if (displayContent != null && mCurrentUserId == targetUserId) { 5661 setForcedDisplayDensityLocked(displayContent, density); 5662 } 5663 Settings.Secure.putStringForUser(mContext.getContentResolver(), 5664 Settings.Secure.DISPLAY_DENSITY_FORCED, 5665 Integer.toString(density), targetUserId); 5666 } 5667 } finally { 5668 Binder.restoreCallingIdentity(ident); 5669 } 5670 } 5671 5672 @Override clearForcedDisplayDensityForUser(int displayId, int userId)5673 public void clearForcedDisplayDensityForUser(int displayId, int userId) { 5674 if (mContext.checkCallingOrSelfPermission( 5675 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 5676 PackageManager.PERMISSION_GRANTED) { 5677 throw new SecurityException("Must hold permission " + 5678 android.Manifest.permission.WRITE_SECURE_SETTINGS); 5679 } 5680 if (displayId != DEFAULT_DISPLAY) { 5681 throw new IllegalArgumentException("Can only set the default display"); 5682 } 5683 5684 final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 5685 Binder.getCallingUid(), userId, false, true, "clearForcedDisplayDensityForUser", 5686 null); 5687 final long ident = Binder.clearCallingIdentity(); 5688 try { 5689 synchronized(mWindowMap) { 5690 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 5691 if (displayContent != null && mCurrentUserId == callingUserId) { 5692 setForcedDisplayDensityLocked(displayContent, 5693 displayContent.mInitialDisplayDensity); 5694 } 5695 Settings.Secure.putStringForUser(mContext.getContentResolver(), 5696 Settings.Secure.DISPLAY_DENSITY_FORCED, "", callingUserId); 5697 } 5698 } finally { 5699 Binder.restoreCallingIdentity(ident); 5700 } 5701 } 5702 5703 /** 5704 * @param userId the ID of the user 5705 * @return the forced display density for the specified user, if set, or 5706 * {@code 0} if not set 5707 */ getForcedDisplayDensityForUserLocked(int userId)5708 private int getForcedDisplayDensityForUserLocked(int userId) { 5709 String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(), 5710 Settings.Secure.DISPLAY_DENSITY_FORCED, userId); 5711 if (densityStr == null || densityStr.length() == 0) { 5712 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 5713 } 5714 if (densityStr != null && densityStr.length() > 0) { 5715 try { 5716 return Integer.parseInt(densityStr); 5717 } catch (NumberFormatException ex) { 5718 } 5719 } 5720 return 0; 5721 } 5722 5723 /** 5724 * Forces the given display to the use the specified density. 5725 * 5726 * @param displayContent the display to modify 5727 * @param density the density in DPI to use 5728 */ setForcedDisplayDensityLocked(@onNull DisplayContent displayContent, int density)5729 private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent, 5730 int density) { 5731 displayContent.mBaseDisplayDensity = density; 5732 reconfigureDisplayLocked(displayContent); 5733 } 5734 reconfigureDisplayLocked(@onNull DisplayContent displayContent)5735 void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) { 5736 if (!mDisplayReady) { 5737 return; 5738 } 5739 configureDisplayPolicyLocked(displayContent); 5740 displayContent.setLayoutNeeded(); 5741 5742 final int displayId = displayContent.getDisplayId(); 5743 boolean configChanged = updateOrientationFromAppTokensLocked(false /* inTransaction */, 5744 displayId); 5745 final Configuration currentDisplayConfig = displayContent.getConfiguration(); 5746 mTempConfiguration.setTo(currentDisplayConfig); 5747 displayContent.computeScreenConfiguration(mTempConfiguration); 5748 configChanged |= currentDisplayConfig.diff(mTempConfiguration) != 0; 5749 5750 if (configChanged) { 5751 mWaitingForConfig = true; 5752 startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */, 5753 0 /* enterAnim */, displayContent); 5754 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget(); 5755 } 5756 5757 mWindowPlacerLocked.performSurfacePlacement(); 5758 } 5759 configureDisplayPolicyLocked(DisplayContent displayContent)5760 void configureDisplayPolicyLocked(DisplayContent displayContent) { 5761 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 5762 displayContent.mBaseDisplayWidth, 5763 displayContent.mBaseDisplayHeight, 5764 displayContent.mBaseDisplayDensity); 5765 5766 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5767 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 5768 displayInfo.overscanLeft, displayInfo.overscanTop, 5769 displayInfo.overscanRight, displayInfo.overscanBottom); 5770 } 5771 5772 /** 5773 * Get an array with display ids ordered by focus priority - last items should be given 5774 * focus first. Sparse array just maps position to displayId. 5775 */ 5776 // TODO: Maintain display list in focus order in ActivityManager and remove this call. getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder)5777 public void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) { 5778 synchronized(mWindowMap) { 5779 mRoot.getDisplaysInFocusOrder(displaysInFocusOrder); 5780 } 5781 } 5782 5783 @Override setOverscan(int displayId, int left, int top, int right, int bottom)5784 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 5785 if (mContext.checkCallingOrSelfPermission( 5786 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 5787 PackageManager.PERMISSION_GRANTED) { 5788 throw new SecurityException("Must hold permission " + 5789 android.Manifest.permission.WRITE_SECURE_SETTINGS); 5790 } 5791 final long ident = Binder.clearCallingIdentity(); 5792 try { 5793 synchronized(mWindowMap) { 5794 DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 5795 if (displayContent != null) { 5796 setOverscanLocked(displayContent, left, top, right, bottom); 5797 } 5798 } 5799 } finally { 5800 Binder.restoreCallingIdentity(ident); 5801 } 5802 } 5803 setOverscanLocked(DisplayContent displayContent, int left, int top, int right, int bottom)5804 private void setOverscanLocked(DisplayContent displayContent, 5805 int left, int top, int right, int bottom) { 5806 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5807 displayInfo.overscanLeft = left; 5808 displayInfo.overscanTop = top; 5809 displayInfo.overscanRight = right; 5810 displayInfo.overscanBottom = bottom; 5811 5812 mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top, 5813 right, bottom); 5814 mDisplaySettings.writeSettingsLocked(); 5815 5816 reconfigureDisplayLocked(displayContent); 5817 } 5818 5819 // ------------------------------------------------------------- 5820 // Internals 5821 // ------------------------------------------------------------- 5822 windowForClientLocked(Session session, IWindow client, boolean throwOnError)5823 final WindowState windowForClientLocked(Session session, IWindow client, boolean throwOnError) { 5824 return windowForClientLocked(session, client.asBinder(), throwOnError); 5825 } 5826 windowForClientLocked(Session session, IBinder client, boolean throwOnError)5827 final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) { 5828 WindowState win = mWindowMap.get(client); 5829 if (localLOGV) Slog.v(TAG_WM, "Looking up client " + client + ": " + win); 5830 if (win == null) { 5831 if (throwOnError) { 5832 throw new IllegalArgumentException( 5833 "Requested window " + client + " does not exist"); 5834 } 5835 Slog.w(TAG_WM, "Failed looking up window callers=" + Debug.getCallers(3)); 5836 return null; 5837 } 5838 if (session != null && win.mSession != session) { 5839 if (throwOnError) { 5840 throw new IllegalArgumentException("Requested window " + client + " is in session " 5841 + win.mSession + ", not " + session); 5842 } 5843 Slog.w(TAG_WM, "Failed looking up window callers=" + Debug.getCallers(3)); 5844 return null; 5845 } 5846 5847 return win; 5848 } 5849 makeWindowFreezingScreenIfNeededLocked(WindowState w)5850 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 5851 // If the screen is currently frozen or off, then keep 5852 // it frozen/off until this window draws at its new 5853 // orientation. 5854 if (!w.mToken.okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { 5855 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w); 5856 w.setOrientationChanging(true); 5857 w.mLastFreezeDuration = 0; 5858 mRoot.mOrientationChangeComplete = false; 5859 if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) { 5860 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; 5861 // XXX should probably keep timeout from 5862 // when we first froze the display. 5863 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 5864 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 5865 WINDOW_FREEZE_TIMEOUT_DURATION); 5866 } 5867 } 5868 } 5869 5870 /** 5871 * @return bitmap indicating if another pass through layout must be made. 5872 */ handleAnimatingStoppedAndTransitionLocked()5873 int handleAnimatingStoppedAndTransitionLocked() { 5874 int changes = 0; 5875 5876 mAppTransition.setIdle(); 5877 5878 for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) { 5879 final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i); 5880 mAppTransition.notifyAppTransitionFinishedLocked(token); 5881 } 5882 mNoAnimationNotifyOnTransitionFinished.clear(); 5883 5884 // TODO: multi-display. 5885 final DisplayContent dc = getDefaultDisplayContentLocked(); 5886 5887 dc.mWallpaperController.hideDeferredWallpapersIfNeeded(); 5888 5889 dc.onAppTransitionDone(); 5890 5891 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5892 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM, 5893 "Wallpaper layer changed: assigning layers + relayout"); 5894 dc.computeImeTarget(true /* updateImeTarget */); 5895 mRoot.mWallpaperMayChange = true; 5896 // Since the window list has been rebuilt, focus might have to be recomputed since the 5897 // actual order of windows might have changed again. 5898 mFocusMayChange = true; 5899 5900 return changes; 5901 } 5902 checkDrawnWindowsLocked()5903 void checkDrawnWindowsLocked() { 5904 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 5905 return; 5906 } 5907 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 5908 WindowState win = mWaitingForDrawn.get(j); 5909 if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win + 5910 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 5911 " mHasSurface=" + win.mHasSurface + 5912 " drawState=" + win.mWinAnimator.mDrawState); 5913 if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) { 5914 // Window has been removed or hidden; no draw will now happen, so stop waiting. 5915 if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win); 5916 mWaitingForDrawn.remove(win); 5917 } else if (win.hasDrawnLw()) { 5918 // Window is now drawn (and shown). 5919 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win); 5920 mWaitingForDrawn.remove(win); 5921 } 5922 } 5923 if (mWaitingForDrawn.isEmpty()) { 5924 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!"); 5925 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 5926 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 5927 } 5928 } 5929 setHoldScreenLocked(final Session newHoldScreen)5930 void setHoldScreenLocked(final Session newHoldScreen) { 5931 final boolean hold = newHoldScreen != null; 5932 5933 if (hold && mHoldingScreenOn != newHoldScreen) { 5934 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 5935 } 5936 mHoldingScreenOn = newHoldScreen; 5937 5938 final boolean state = mHoldingScreenWakeLock.isHeld(); 5939 if (hold != state) { 5940 if (hold) { 5941 if (DEBUG_KEEP_SCREEN_ON) { 5942 Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to " 5943 + mRoot.mHoldScreenWindow); 5944 } 5945 mLastWakeLockHoldingWindow = mRoot.mHoldScreenWindow; 5946 mLastWakeLockObscuringWindow = null; 5947 mHoldingScreenWakeLock.acquire(); 5948 mPolicy.keepScreenOnStartedLw(); 5949 } else { 5950 if (DEBUG_KEEP_SCREEN_ON) { 5951 Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by " 5952 + mRoot.mObscuringWindow); 5953 } 5954 mLastWakeLockHoldingWindow = null; 5955 mLastWakeLockObscuringWindow = mRoot.mObscuringWindow; 5956 mPolicy.keepScreenOnStoppedLw(); 5957 mHoldingScreenWakeLock.release(); 5958 } 5959 } 5960 } 5961 requestTraversal()5962 void requestTraversal() { 5963 synchronized (mWindowMap) { 5964 mWindowPlacerLocked.requestTraversal(); 5965 } 5966 } 5967 5968 /** Note that Locked in this case is on mLayoutToAnim */ scheduleAnimationLocked()5969 void scheduleAnimationLocked() { 5970 mAnimator.scheduleAnimation(); 5971 } 5972 5973 // TODO: Move to DisplayContent updateFocusedWindowLocked(int mode, boolean updateInputWindows)5974 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 5975 WindowState newFocus = mRoot.computeFocusedWindow(); 5976 if (mCurrentFocus != newFocus) { 5977 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 5978 // This check makes sure that we don't already have the focus 5979 // change message pending. 5980 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 5981 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 5982 // TODO(multidisplay): Focused windows on default display only. 5983 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 5984 boolean imWindowChanged = false; 5985 if (mInputMethodWindow != null) { 5986 final WindowState prevTarget = mInputMethodTarget; 5987 final WindowState newTarget = 5988 displayContent.computeImeTarget(true /* updateImeTarget*/); 5989 5990 imWindowChanged = prevTarget != newTarget; 5991 5992 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 5993 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) { 5994 final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer; 5995 displayContent.assignWindowLayers(false /* setLayoutNeeded */); 5996 imWindowChanged |= 5997 prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer; 5998 } 5999 } 6000 6001 if (imWindowChanged) { 6002 mWindowsChanged = true; 6003 displayContent.setLayoutNeeded(); 6004 newFocus = mRoot.computeFocusedWindow(); 6005 } 6006 6007 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " + 6008 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 6009 final WindowState oldFocus = mCurrentFocus; 6010 mCurrentFocus = newFocus; 6011 mLosingFocus.remove(newFocus); 6012 6013 if (mCurrentFocus != null) { 6014 mWinAddedSinceNullFocus.clear(); 6015 mWinRemovedSinceNullFocus.clear(); 6016 } 6017 6018 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 6019 6020 if (imWindowChanged && oldFocus != mInputMethodWindow) { 6021 // Focus of the input method window changed. Perform layout if needed. 6022 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 6023 displayContent.performLayout(true /*initial*/, updateInputWindows); 6024 focusChanged &= ~FINISH_LAYOUT_REDO_LAYOUT; 6025 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 6026 // Client will do the layout, but we need to assign layers 6027 // for handleNewWindowLocked() below. 6028 displayContent.assignWindowLayers(false /* setLayoutNeeded */); 6029 } 6030 } 6031 6032 if ((focusChanged & FINISH_LAYOUT_REDO_LAYOUT) != 0) { 6033 // The change in focus caused us to need to do a layout. Okay. 6034 displayContent.setLayoutNeeded(); 6035 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 6036 displayContent.performLayout(true /*initial*/, updateInputWindows); 6037 } 6038 } 6039 6040 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 6041 // If we defer assigning layers, then the caller is responsible for 6042 // doing this part. 6043 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 6044 } 6045 6046 displayContent.adjustForImeIfNeeded(); 6047 6048 // We may need to schedule some toast windows to be removed. The toasts for an app that 6049 // does not have input focus are removed within a timeout to prevent apps to redress 6050 // other apps' UI. 6051 displayContent.scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus); 6052 6053 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 6054 return true; 6055 } 6056 return false; 6057 } 6058 startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim)6059 void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 6060 startFreezingDisplayLocked(inTransaction, exitAnim, enterAnim, 6061 getDefaultDisplayContentLocked()); 6062 } 6063 startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim, DisplayContent displayContent)6064 void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim, 6065 DisplayContent displayContent) { 6066 if (mDisplayFrozen) { 6067 return; 6068 } 6069 6070 if (!displayContent.isReady() || !mPolicy.isScreenOn() || !displayContent.okToAnimate()) { 6071 // No need to freeze the screen before the display is ready, if the screen is off, 6072 // or we can't currently animate. 6073 return; 6074 } 6075 6076 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 6077 "startFreezingDisplayLocked: inTransaction=" + inTransaction 6078 + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim 6079 + " called by " + Debug.getCallers(8)); 6080 mScreenFrozenLock.acquire(); 6081 6082 mDisplayFrozen = true; 6083 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 6084 mLastFinishedFreezeSource = null; 6085 6086 // {@link mDisplayFrozen} prevents us from freezing on multiple displays at the same time. 6087 // As a result, we only track the display that has initially froze the screen. 6088 mFrozenDisplayId = displayContent.getDisplayId(); 6089 6090 mInputMonitor.freezeInputDispatchingLw(); 6091 6092 // Clear the last input window -- that is just used for 6093 // clean transitions between IMEs, and if we are freezing 6094 // the screen then the whole world is changing behind the scenes. 6095 mPolicy.setLastInputMethodWindowLw(null, null); 6096 6097 if (mAppTransition.isTransitionSet()) { 6098 mAppTransition.freeze(); 6099 } 6100 6101 if (PROFILE_ORIENTATION) { 6102 File file = new File("/data/system/frozen"); 6103 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 6104 } 6105 6106 // TODO(multidisplay): rotation on non-default displays 6107 if (CUSTOM_SCREEN_ROTATION && displayContent.isDefaultDisplay) { 6108 mExitAnimId = exitAnim; 6109 mEnterAnimId = enterAnim; 6110 ScreenRotationAnimation screenRotationAnimation = 6111 mAnimator.getScreenRotationAnimationLocked(mFrozenDisplayId); 6112 if (screenRotationAnimation != null) { 6113 screenRotationAnimation.kill(); 6114 } 6115 6116 // Check whether the current screen contains any secure content. 6117 boolean isSecure = displayContent.hasSecureWindowOnScreen(); 6118 6119 displayContent.updateDisplayInfo(); 6120 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 6121 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure, 6122 this); 6123 mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId, 6124 screenRotationAnimation); 6125 } 6126 } 6127 stopFreezingDisplayLocked()6128 void stopFreezingDisplayLocked() { 6129 if (!mDisplayFrozen) { 6130 return; 6131 } 6132 6133 if (mWaitingForConfig || mAppsFreezingScreen > 0 6134 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE 6135 || mClientFreezingScreen || !mOpeningApps.isEmpty()) { 6136 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 6137 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 6138 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 6139 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 6140 + ", mClientFreezingScreen=" + mClientFreezingScreen 6141 + ", mOpeningApps.size()=" + mOpeningApps.size()); 6142 return; 6143 } 6144 6145 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 6146 "stopFreezingDisplayLocked: Unfreezing now"); 6147 6148 final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId); 6149 6150 // We must make a local copy of the displayId as it can be potentially overwritten later on 6151 // in this method. For example, {@link startFreezingDisplayLocked} may be called as a result 6152 // of update rotation, but we reference the frozen display after that call in this method. 6153 final int displayId = mFrozenDisplayId; 6154 mFrozenDisplayId = INVALID_DISPLAY; 6155 mDisplayFrozen = false; 6156 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 6157 StringBuilder sb = new StringBuilder(128); 6158 sb.append("Screen frozen for "); 6159 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 6160 if (mLastFinishedFreezeSource != null) { 6161 sb.append(" due to "); 6162 sb.append(mLastFinishedFreezeSource); 6163 } 6164 Slog.i(TAG_WM, sb.toString()); 6165 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 6166 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 6167 if (PROFILE_ORIENTATION) { 6168 Debug.stopMethodTracing(); 6169 } 6170 6171 boolean updateRotation = false; 6172 6173 ScreenRotationAnimation screenRotationAnimation = 6174 mAnimator.getScreenRotationAnimationLocked(displayId); 6175 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6176 && screenRotationAnimation.hasScreenshot()) { 6177 if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation"); 6178 // TODO(multidisplay): rotation on main screen only. 6179 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6180 // Get rotation animation again, with new top window 6181 boolean isDimming = displayContent.isDimming(); 6182 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 6183 mExitAnimId = mEnterAnimId = 0; 6184 } 6185 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 6186 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 6187 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 6188 scheduleAnimationLocked(); 6189 } else { 6190 screenRotationAnimation.kill(); 6191 mAnimator.setScreenRotationAnimationLocked(displayId, null); 6192 updateRotation = true; 6193 } 6194 } else { 6195 if (screenRotationAnimation != null) { 6196 screenRotationAnimation.kill(); 6197 mAnimator.setScreenRotationAnimationLocked(displayId, null); 6198 } 6199 updateRotation = true; 6200 } 6201 6202 mInputMonitor.thawInputDispatchingLw(); 6203 6204 boolean configChanged; 6205 6206 // While the display is frozen we don't re-compute the orientation 6207 // to avoid inconsistent states. However, something interesting 6208 // could have actually changed during that time so re-evaluate it 6209 // now to catch that. 6210 configChanged = updateOrientationFromAppTokensLocked(false, displayId); 6211 6212 // A little kludge: a lot could have happened while the 6213 // display was frozen, so now that we are coming back we 6214 // do a gc so that any remote references the system 6215 // processes holds on others can be released if they are 6216 // no longer needed. 6217 mH.removeMessages(H.FORCE_GC); 6218 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 6219 6220 mScreenFrozenLock.release(); 6221 6222 if (updateRotation) { 6223 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation"); 6224 configChanged |= displayContent.updateRotationUnchecked( 6225 false /* inTransaction */); 6226 } 6227 6228 if (configChanged) { 6229 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget(); 6230 } 6231 } 6232 getPropertyInt(String[] tokens, int index, int defUnits, int defDps, DisplayMetrics dm)6233 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 6234 DisplayMetrics dm) { 6235 if (index < tokens.length) { 6236 String str = tokens[index]; 6237 if (str != null && str.length() > 0) { 6238 try { 6239 int val = Integer.parseInt(str); 6240 return val; 6241 } catch (Exception e) { 6242 } 6243 } 6244 } 6245 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 6246 return defDps; 6247 } 6248 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 6249 return val; 6250 } 6251 createWatermarkInTransaction()6252 void createWatermarkInTransaction() { 6253 if (mWatermark != null) { 6254 return; 6255 } 6256 6257 File file = new File("/system/etc/setup.conf"); 6258 FileInputStream in = null; 6259 DataInputStream ind = null; 6260 try { 6261 in = new FileInputStream(file); 6262 ind = new DataInputStream(in); 6263 String line = ind.readLine(); 6264 if (line != null) { 6265 String[] toks = line.split("%"); 6266 if (toks != null && toks.length > 0) { 6267 // TODO(multi-display): Show watermarks on secondary displays. 6268 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6269 mWatermark = new Watermark(displayContent.getDisplay(), 6270 displayContent.mRealDisplayMetrics, mFxSession, toks); 6271 } 6272 } 6273 } catch (FileNotFoundException e) { 6274 } catch (IOException e) { 6275 } finally { 6276 if (ind != null) { 6277 try { 6278 ind.close(); 6279 } catch (IOException e) { 6280 } 6281 } else if (in != null) { 6282 try { 6283 in.close(); 6284 } catch (IOException e) { 6285 } 6286 } 6287 } 6288 } 6289 6290 @Override setRecentsVisibility(boolean visible)6291 public void setRecentsVisibility(boolean visible) { 6292 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 6293 != PackageManager.PERMISSION_GRANTED) { 6294 throw new SecurityException("Caller does not hold permission " 6295 + android.Manifest.permission.STATUS_BAR); 6296 } 6297 6298 synchronized (mWindowMap) { 6299 mPolicy.setRecentsVisibilityLw(visible); 6300 } 6301 } 6302 6303 @Override setPipVisibility(boolean visible)6304 public void setPipVisibility(boolean visible) { 6305 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 6306 != PackageManager.PERMISSION_GRANTED) { 6307 throw new SecurityException("Caller does not hold permission " 6308 + android.Manifest.permission.STATUS_BAR); 6309 } 6310 6311 synchronized (mWindowMap) { 6312 mPolicy.setPipVisibilityLw(visible); 6313 } 6314 } 6315 6316 @Override statusBarVisibilityChanged(int visibility)6317 public void statusBarVisibilityChanged(int visibility) { 6318 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 6319 != PackageManager.PERMISSION_GRANTED) { 6320 throw new SecurityException("Caller does not hold permission " 6321 + android.Manifest.permission.STATUS_BAR); 6322 } 6323 6324 synchronized (mWindowMap) { 6325 mLastStatusBarVisibility = visibility; 6326 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 6327 updateStatusBarVisibilityLocked(visibility); 6328 } 6329 } 6330 6331 // TODO(multidisplay): StatusBar on multiple screens? updateStatusBarVisibilityLocked(int visibility)6332 private boolean updateStatusBarVisibilityLocked(int visibility) { 6333 if (mLastDispatchedSystemUiVisibility == visibility) { 6334 return false; 6335 } 6336 final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility) 6337 // We are only interested in differences of one of the 6338 // clearable flags... 6339 & View.SYSTEM_UI_CLEARABLE_FLAGS 6340 // ...if it has actually been cleared. 6341 & ~visibility; 6342 6343 mLastDispatchedSystemUiVisibility = visibility; 6344 mInputManager.setSystemUiVisibility(visibility); 6345 getDefaultDisplayContentLocked().updateSystemUiVisibility(visibility, globalDiff); 6346 return true; 6347 } 6348 6349 @Override reevaluateStatusBarVisibility()6350 public void reevaluateStatusBarVisibility() { 6351 synchronized (mWindowMap) { 6352 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 6353 if (updateStatusBarVisibilityLocked(visibility)) { 6354 mWindowPlacerLocked.requestTraversal(); 6355 } 6356 } 6357 } 6358 6359 /** 6360 * Used by ActivityManager to determine where to position an app with aspect ratio shorter then 6361 * the screen is. 6362 * @see WindowManagerPolicy#getNavBarPosition() 6363 */ getNavBarPosition()6364 public int getNavBarPosition() { 6365 synchronized (mWindowMap) { 6366 // Perform layout if it was scheduled before to make sure that we get correct nav bar 6367 // position when doing rotations. 6368 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked(); 6369 defaultDisplayContent.performLayout(false /* initial */, 6370 false /* updateInputWindows */); 6371 return mPolicy.getNavBarPosition(); 6372 } 6373 } 6374 6375 @Override createInputConsumer(Looper looper, String name, InputEventReceiver.Factory inputEventReceiverFactory)6376 public WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name, 6377 InputEventReceiver.Factory inputEventReceiverFactory) { 6378 synchronized (mWindowMap) { 6379 return mInputMonitor.createInputConsumer(looper, name, inputEventReceiverFactory); 6380 } 6381 } 6382 6383 @Override createInputConsumer(String name, InputChannel inputChannel)6384 public void createInputConsumer(String name, InputChannel inputChannel) { 6385 synchronized (mWindowMap) { 6386 mInputMonitor.createInputConsumer(name, inputChannel); 6387 } 6388 } 6389 6390 @Override destroyInputConsumer(String name)6391 public boolean destroyInputConsumer(String name) { 6392 synchronized (mWindowMap) { 6393 return mInputMonitor.destroyInputConsumer(name); 6394 } 6395 } 6396 6397 @Override getCurrentImeTouchRegion()6398 public Region getCurrentImeTouchRegion() { 6399 if (mContext.checkCallingOrSelfPermission(RESTRICTED_VR_ACCESS) != PERMISSION_GRANTED) { 6400 throw new SecurityException("getCurrentImeTouchRegion is restricted to VR services"); 6401 } 6402 synchronized (mWindowMap) { 6403 final Region r = new Region(); 6404 if (mInputMethodWindow != null) { 6405 mInputMethodWindow.getTouchableRegion(r); 6406 } 6407 return r; 6408 } 6409 } 6410 6411 @Override hasNavigationBar()6412 public boolean hasNavigationBar() { 6413 return mPolicy.hasNavigationBar(); 6414 } 6415 6416 @Override lockNow(Bundle options)6417 public void lockNow(Bundle options) { 6418 mPolicy.lockNow(options); 6419 } 6420 showRecentApps(boolean fromHome)6421 public void showRecentApps(boolean fromHome) { 6422 mPolicy.showRecentApps(fromHome); 6423 } 6424 6425 @Override isSafeModeEnabled()6426 public boolean isSafeModeEnabled() { 6427 return mSafeMode; 6428 } 6429 6430 @Override clearWindowContentFrameStats(IBinder token)6431 public boolean clearWindowContentFrameStats(IBinder token) { 6432 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 6433 "clearWindowContentFrameStats()")) { 6434 throw new SecurityException("Requires FRAME_STATS permission"); 6435 } 6436 synchronized (mWindowMap) { 6437 WindowState windowState = mWindowMap.get(token); 6438 if (windowState == null) { 6439 return false; 6440 } 6441 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController; 6442 if (surfaceController == null) { 6443 return false; 6444 } 6445 return surfaceController.clearWindowContentFrameStats(); 6446 } 6447 } 6448 6449 @Override getWindowContentFrameStats(IBinder token)6450 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 6451 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 6452 "getWindowContentFrameStats()")) { 6453 throw new SecurityException("Requires FRAME_STATS permission"); 6454 } 6455 synchronized (mWindowMap) { 6456 WindowState windowState = mWindowMap.get(token); 6457 if (windowState == null) { 6458 return null; 6459 } 6460 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController; 6461 if (surfaceController == null) { 6462 return null; 6463 } 6464 if (mTempWindowRenderStats == null) { 6465 mTempWindowRenderStats = new WindowContentFrameStats(); 6466 } 6467 WindowContentFrameStats stats = mTempWindowRenderStats; 6468 if (!surfaceController.getWindowContentFrameStats(stats)) { 6469 return null; 6470 } 6471 return stats; 6472 } 6473 } 6474 notifyAppRelaunching(IBinder token)6475 public void notifyAppRelaunching(IBinder token) { 6476 synchronized (mWindowMap) { 6477 final AppWindowToken appWindow = mRoot.getAppWindowToken(token); 6478 if (appWindow != null) { 6479 appWindow.startRelaunching(); 6480 } 6481 } 6482 } 6483 notifyAppRelaunchingFinished(IBinder token)6484 public void notifyAppRelaunchingFinished(IBinder token) { 6485 synchronized (mWindowMap) { 6486 final AppWindowToken appWindow = mRoot.getAppWindowToken(token); 6487 if (appWindow != null) { 6488 appWindow.finishRelaunching(); 6489 } 6490 } 6491 } 6492 notifyAppRelaunchesCleared(IBinder token)6493 public void notifyAppRelaunchesCleared(IBinder token) { 6494 synchronized (mWindowMap) { 6495 final AppWindowToken appWindow = mRoot.getAppWindowToken(token); 6496 if (appWindow != null) { 6497 appWindow.clearRelaunching(); 6498 } 6499 } 6500 } 6501 notifyAppResumedFinished(IBinder token)6502 public void notifyAppResumedFinished(IBinder token) { 6503 synchronized (mWindowMap) { 6504 final AppWindowToken appWindow = mRoot.getAppWindowToken(token); 6505 if (appWindow != null) { 6506 mUnknownAppVisibilityController.notifyAppResumedFinished(appWindow); 6507 } 6508 } 6509 } 6510 6511 /** 6512 * Called when a task has been removed from the recent tasks list. 6513 * <p> 6514 * Note: This doesn't go through {@link TaskWindowContainerController} yet as the window 6515 * container may not exist when this happens. 6516 */ notifyTaskRemovedFromRecents(int taskId, int userId)6517 public void notifyTaskRemovedFromRecents(int taskId, int userId) { 6518 synchronized (mWindowMap) { 6519 mTaskSnapshotController.notifyTaskRemovedFromRecents(taskId, userId); 6520 } 6521 } 6522 6523 @Override getDockedDividerInsetsLw()6524 public int getDockedDividerInsetsLw() { 6525 return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets(); 6526 } 6527 dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll)6528 private void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 6529 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 6530 mPolicy.dump(" ", pw, args); 6531 } 6532 dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll)6533 private void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 6534 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 6535 mAnimator.dumpLocked(pw, " ", dumpAll); 6536 } 6537 dumpTokensLocked(PrintWriter pw, boolean dumpAll)6538 private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 6539 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 6540 mRoot.dumpTokens(pw, dumpAll); 6541 if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) { 6542 pw.println(); 6543 if (mOpeningApps.size() > 0) { 6544 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 6545 } 6546 if (mClosingApps.size() > 0) { 6547 pw.print(" mClosingApps="); pw.println(mClosingApps); 6548 } 6549 } 6550 } 6551 dumpSessionsLocked(PrintWriter pw, boolean dumpAll)6552 private void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 6553 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 6554 for (int i=0; i<mSessions.size(); i++) { 6555 Session s = mSessions.valueAt(i); 6556 pw.print(" Session "); pw.print(s); pw.println(':'); 6557 s.dump(pw, " "); 6558 } 6559 } 6560 dumpWindowsLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)6561 private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 6562 ArrayList<WindowState> windows) { 6563 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 6564 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 6565 } 6566 dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)6567 private void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 6568 ArrayList<WindowState> windows) { 6569 mRoot.dumpWindowsNoHeader(pw, dumpAll, windows); 6570 6571 if (!mHidingNonSystemOverlayWindows.isEmpty()) { 6572 pw.println(); 6573 pw.println(" Hiding System Alert Windows:"); 6574 for (int i = mHidingNonSystemOverlayWindows.size() - 1; i >= 0; i--) { 6575 final WindowState w = mHidingNonSystemOverlayWindows.get(i); 6576 pw.print(" #"); pw.print(i); pw.print(' '); 6577 pw.print(w); 6578 if (dumpAll) { 6579 pw.println(":"); 6580 w.dump(pw, " ", true); 6581 } else { 6582 pw.println(); 6583 } 6584 } 6585 } 6586 if (mPendingRemove.size() > 0) { 6587 pw.println(); 6588 pw.println(" Remove pending for:"); 6589 for (int i=mPendingRemove.size()-1; i>=0; i--) { 6590 WindowState w = mPendingRemove.get(i); 6591 if (windows == null || windows.contains(w)) { 6592 pw.print(" Remove #"); pw.print(i); pw.print(' '); 6593 pw.print(w); 6594 if (dumpAll) { 6595 pw.println(":"); 6596 w.dump(pw, " ", true); 6597 } else { 6598 pw.println(); 6599 } 6600 } 6601 } 6602 } 6603 if (mForceRemoves != null && mForceRemoves.size() > 0) { 6604 pw.println(); 6605 pw.println(" Windows force removing:"); 6606 for (int i=mForceRemoves.size()-1; i>=0; i--) { 6607 WindowState w = mForceRemoves.get(i); 6608 pw.print(" Removing #"); pw.print(i); pw.print(' '); 6609 pw.print(w); 6610 if (dumpAll) { 6611 pw.println(":"); 6612 w.dump(pw, " ", true); 6613 } else { 6614 pw.println(); 6615 } 6616 } 6617 } 6618 if (mDestroySurface.size() > 0) { 6619 pw.println(); 6620 pw.println(" Windows waiting to destroy their surface:"); 6621 for (int i=mDestroySurface.size()-1; i>=0; i--) { 6622 WindowState w = mDestroySurface.get(i); 6623 if (windows == null || windows.contains(w)) { 6624 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 6625 pw.print(w); 6626 if (dumpAll) { 6627 pw.println(":"); 6628 w.dump(pw, " ", true); 6629 } else { 6630 pw.println(); 6631 } 6632 } 6633 } 6634 } 6635 if (mLosingFocus.size() > 0) { 6636 pw.println(); 6637 pw.println(" Windows losing focus:"); 6638 for (int i=mLosingFocus.size()-1; i>=0; i--) { 6639 WindowState w = mLosingFocus.get(i); 6640 if (windows == null || windows.contains(w)) { 6641 pw.print(" Losing #"); pw.print(i); pw.print(' '); 6642 pw.print(w); 6643 if (dumpAll) { 6644 pw.println(":"); 6645 w.dump(pw, " ", true); 6646 } else { 6647 pw.println(); 6648 } 6649 } 6650 } 6651 } 6652 if (mResizingWindows.size() > 0) { 6653 pw.println(); 6654 pw.println(" Windows waiting to resize:"); 6655 for (int i=mResizingWindows.size()-1; i>=0; i--) { 6656 WindowState w = mResizingWindows.get(i); 6657 if (windows == null || windows.contains(w)) { 6658 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 6659 pw.print(w); 6660 if (dumpAll) { 6661 pw.println(":"); 6662 w.dump(pw, " ", true); 6663 } else { 6664 pw.println(); 6665 } 6666 } 6667 } 6668 } 6669 if (mWaitingForDrawn.size() > 0) { 6670 pw.println(); 6671 pw.println(" Clients waiting for these windows to be drawn:"); 6672 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 6673 WindowState win = mWaitingForDrawn.get(i); 6674 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 6675 } 6676 } 6677 pw.println(); 6678 pw.print(" mGlobalConfiguration="); pw.println(mRoot.getConfiguration()); 6679 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad); 6680 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 6681 if (mLastFocus != mCurrentFocus) { 6682 pw.print(" mLastFocus="); pw.println(mLastFocus); 6683 } 6684 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 6685 if (mInputMethodTarget != null) { 6686 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 6687 } 6688 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 6689 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 6690 pw.print(" mLastDisplayFreezeDuration="); 6691 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 6692 if ( mLastFinishedFreezeSource != null) { 6693 pw.print(" due to "); 6694 pw.print(mLastFinishedFreezeSource); 6695 } 6696 pw.println(); 6697 pw.print(" mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow); 6698 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow); 6699 pw.println(); 6700 6701 mInputMonitor.dump(pw, " "); 6702 mUnknownAppVisibilityController.dump(pw, " "); 6703 mTaskSnapshotController.dump(pw, " "); 6704 6705 if (dumpAll) { 6706 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 6707 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 6708 if (mLastStatusBarVisibility != 0) { 6709 pw.print(" mLastStatusBarVisibility=0x"); 6710 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 6711 } 6712 if (mInputMethodWindow != null) { 6713 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 6714 } 6715 mWindowPlacerLocked.dump(pw, " "); 6716 mRoot.mWallpaperController.dump(pw, " "); 6717 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 6718 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 6719 6720 mRoot.dumpLayoutNeededDisplayIds(pw); 6721 6722 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 6723 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 6724 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 6725 pw.print(" client="); pw.print(mClientFreezingScreen); 6726 pw.print(" apps="); pw.print(mAppsFreezingScreen); 6727 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 6728 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked(); 6729 pw.print(" mRotation="); pw.print(defaultDisplayContent.getRotation()); 6730 pw.print(" mAltOrientation="); 6731 pw.println(defaultDisplayContent.getAltOrientation()); 6732 pw.print(" mLastWindowForcedOrientation="); 6733 pw.print(defaultDisplayContent.getLastWindowForcedOrientation()); 6734 pw.print(" mLastOrientation="); 6735 pw.println(defaultDisplayContent.getLastOrientation()); 6736 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 6737 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 6738 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 6739 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 6740 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 6741 pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation); 6742 pw.println(" mLayoutToAnim:"); 6743 mAppTransition.dump(pw, " "); 6744 } 6745 } 6746 dumpWindows(PrintWriter pw, String name, String[] args, int opti, boolean dumpAll)6747 private boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti, 6748 boolean dumpAll) { 6749 final ArrayList<WindowState> windows = new ArrayList(); 6750 if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) { 6751 final boolean appsOnly = name.contains("apps"); 6752 final boolean visibleOnly = name.contains("visible"); 6753 synchronized(mWindowMap) { 6754 if (appsOnly) { 6755 mRoot.dumpDisplayContents(pw); 6756 } 6757 6758 mRoot.forAllWindows((w) -> { 6759 if ((!visibleOnly || w.mWinAnimator.getShown()) 6760 && (!appsOnly || w.mAppToken != null)) { 6761 windows.add(w); 6762 } 6763 }, true /* traverseTopToBottom */); 6764 } 6765 } else { 6766 synchronized(mWindowMap) { 6767 mRoot.getWindowsByName(windows, name); 6768 } 6769 } 6770 6771 if (windows.size() <= 0) { 6772 return false; 6773 } 6774 6775 synchronized(mWindowMap) { 6776 dumpWindowsLocked(pw, dumpAll, windows); 6777 } 6778 return true; 6779 } 6780 dumpLastANRLocked(PrintWriter pw)6781 private void dumpLastANRLocked(PrintWriter pw) { 6782 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 6783 if (mLastANRState == null) { 6784 pw.println(" <no ANR has occurred since boot>"); 6785 } else { 6786 pw.println(mLastANRState); 6787 } 6788 } 6789 6790 /** 6791 * Saves information about the state of the window manager at 6792 * the time an ANR occurred before anything else in the system changes 6793 * in response. 6794 * 6795 * @param appWindowToken The application that ANR'd, may be null. 6796 * @param windowState The window that ANR'd, may be null. 6797 * @param reason The reason for the ANR, may be null. 6798 */ saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason)6799 void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason) { 6800 StringWriter sw = new StringWriter(); 6801 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 6802 pw.println(" ANR time: " + DateFormat.getDateTimeInstance().format(new Date())); 6803 if (appWindowToken != null) { 6804 pw.println(" Application at fault: " + appWindowToken.stringName); 6805 } 6806 if (windowState != null) { 6807 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 6808 } 6809 if (reason != null) { 6810 pw.println(" Reason: " + reason); 6811 } 6812 if (!mWinAddedSinceNullFocus.isEmpty()) { 6813 pw.println(" Windows added since null focus: " + mWinAddedSinceNullFocus); 6814 } 6815 if (!mWinRemovedSinceNullFocus.isEmpty()) { 6816 pw.println(" Windows removed since null focus: " + mWinRemovedSinceNullFocus); 6817 } 6818 pw.println(); 6819 dumpWindowsNoHeaderLocked(pw, true, null); 6820 pw.println(); 6821 pw.println("Last ANR continued"); 6822 mRoot.dumpDisplayContents(pw); 6823 pw.close(); 6824 mLastANRState = sw.toString(); 6825 6826 mH.removeMessages(H.RESET_ANR_MESSAGE); 6827 mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS); 6828 } 6829 6830 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)6831 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 6832 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 6833 6834 boolean dumpAll = false; 6835 6836 int opti = 0; 6837 while (opti < args.length) { 6838 String opt = args[opti]; 6839 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 6840 break; 6841 } 6842 opti++; 6843 if ("-a".equals(opt)) { 6844 dumpAll = true; 6845 } else if ("-h".equals(opt)) { 6846 pw.println("Window manager dump options:"); 6847 pw.println(" [-a] [-h] [cmd] ..."); 6848 pw.println(" cmd may be one of:"); 6849 pw.println(" l[astanr]: last ANR information"); 6850 pw.println(" p[policy]: policy state"); 6851 pw.println(" a[animator]: animator state"); 6852 pw.println(" s[essions]: active sessions"); 6853 pw.println(" surfaces: active surfaces (debugging enabled only)"); 6854 pw.println(" d[isplays]: active display contents"); 6855 pw.println(" t[okens]: token list"); 6856 pw.println(" w[indows]: window list"); 6857 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 6858 pw.println(" be a partial substring in a window name, a"); 6859 pw.println(" Window hex object identifier, or"); 6860 pw.println(" \"all\" for all windows, or"); 6861 pw.println(" \"visible\" for the visible windows."); 6862 pw.println(" \"visible-apps\" for the visible app windows."); 6863 pw.println(" -a: include all available server state."); 6864 return; 6865 } else { 6866 pw.println("Unknown argument: " + opt + "; use -h for help"); 6867 } 6868 } 6869 6870 // Is the caller requesting to dump a particular piece of data? 6871 if (opti < args.length) { 6872 String cmd = args[opti]; 6873 opti++; 6874 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 6875 synchronized(mWindowMap) { 6876 dumpLastANRLocked(pw); 6877 } 6878 return; 6879 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 6880 synchronized(mWindowMap) { 6881 dumpPolicyLocked(pw, args, true); 6882 } 6883 return; 6884 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 6885 synchronized(mWindowMap) { 6886 dumpAnimatorLocked(pw, args, true); 6887 } 6888 return; 6889 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 6890 synchronized(mWindowMap) { 6891 dumpSessionsLocked(pw, true); 6892 } 6893 return; 6894 } else if ("surfaces".equals(cmd)) { 6895 synchronized(mWindowMap) { 6896 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null); 6897 } 6898 return; 6899 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 6900 synchronized(mWindowMap) { 6901 mRoot.dumpDisplayContents(pw); 6902 } 6903 return; 6904 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 6905 synchronized(mWindowMap) { 6906 dumpTokensLocked(pw, true); 6907 } 6908 return; 6909 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 6910 synchronized(mWindowMap) { 6911 dumpWindowsLocked(pw, true, null); 6912 } 6913 return; 6914 } else if ("all".equals(cmd) || "a".equals(cmd)) { 6915 synchronized(mWindowMap) { 6916 dumpWindowsLocked(pw, true, null); 6917 } 6918 return; 6919 } else if ("containers".equals(cmd)) { 6920 synchronized(mWindowMap) { 6921 StringBuilder output = new StringBuilder(); 6922 mRoot.dumpChildrenNames(output, " "); 6923 pw.println(output.toString()); 6924 pw.println(" "); 6925 mRoot.forAllWindows(w -> {pw.println(w);}, true /* traverseTopToBottom */); 6926 } 6927 return; 6928 } else { 6929 // Dumping a single name? 6930 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 6931 pw.println("Bad window command, or no windows match: " + cmd); 6932 pw.println("Use -h for help."); 6933 } 6934 return; 6935 } 6936 } 6937 6938 synchronized(mWindowMap) { 6939 pw.println(); 6940 if (dumpAll) { 6941 pw.println("-------------------------------------------------------------------------------"); 6942 } 6943 dumpLastANRLocked(pw); 6944 pw.println(); 6945 if (dumpAll) { 6946 pw.println("-------------------------------------------------------------------------------"); 6947 } 6948 dumpPolicyLocked(pw, args, dumpAll); 6949 pw.println(); 6950 if (dumpAll) { 6951 pw.println("-------------------------------------------------------------------------------"); 6952 } 6953 dumpAnimatorLocked(pw, args, dumpAll); 6954 pw.println(); 6955 if (dumpAll) { 6956 pw.println("-------------------------------------------------------------------------------"); 6957 } 6958 dumpSessionsLocked(pw, dumpAll); 6959 pw.println(); 6960 if (dumpAll) { 6961 pw.println("-------------------------------------------------------------------------------"); 6962 } 6963 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ? 6964 "-------------------------------------------------------------------------------" 6965 : null); 6966 pw.println(); 6967 if (dumpAll) { 6968 pw.println("-------------------------------------------------------------------------------"); 6969 } 6970 mRoot.dumpDisplayContents(pw); 6971 pw.println(); 6972 if (dumpAll) { 6973 pw.println("-------------------------------------------------------------------------------"); 6974 } 6975 dumpTokensLocked(pw, dumpAll); 6976 pw.println(); 6977 if (dumpAll) { 6978 pw.println("-------------------------------------------------------------------------------"); 6979 } 6980 dumpWindowsLocked(pw, dumpAll, null); 6981 } 6982 } 6983 6984 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 6985 @Override monitor()6986 public void monitor() { 6987 synchronized (mWindowMap) { } 6988 } 6989 6990 // TODO: All the display method below should probably be moved into the RootWindowContainer... createDisplayContentLocked(final Display display)6991 private void createDisplayContentLocked(final Display display) { 6992 if (display == null) { 6993 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 6994 } 6995 mRoot.getDisplayContentOrCreate(display.getDisplayId()); 6996 } 6997 6998 // There is an inherent assumption that this will never return null. 6999 // TODO(multi-display): Inspect all the call-points of this method to see if they make sense to 7000 // support non-default display. getDefaultDisplayContentLocked()7001 DisplayContent getDefaultDisplayContentLocked() { 7002 return mRoot.getDisplayContentOrCreate(DEFAULT_DISPLAY); 7003 } 7004 onDisplayAdded(int displayId)7005 public void onDisplayAdded(int displayId) { 7006 synchronized (mWindowMap) { 7007 final Display display = mDisplayManager.getDisplay(displayId); 7008 if (display != null) { 7009 createDisplayContentLocked(display); 7010 displayReady(displayId); 7011 } 7012 mWindowPlacerLocked.requestTraversal(); 7013 } 7014 } 7015 onDisplayRemoved(int displayId)7016 public void onDisplayRemoved(int displayId) { 7017 synchronized (mWindowMap) { 7018 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 7019 if (displayContent != null) { 7020 displayContent.removeIfPossible(); 7021 } 7022 mAnimator.removeDisplayLocked(displayId); 7023 mWindowPlacerLocked.requestTraversal(); 7024 } 7025 } 7026 onDisplayChanged(int displayId)7027 public void onDisplayChanged(int displayId) { 7028 synchronized (mWindowMap) { 7029 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 7030 if (displayContent != null) { 7031 displayContent.updateDisplayInfo(); 7032 } 7033 mWindowPlacerLocked.requestTraversal(); 7034 } 7035 } 7036 7037 @Override getWindowManagerLock()7038 public Object getWindowManagerLock() { 7039 return mWindowMap; 7040 } 7041 7042 /** 7043 * Hint to a token that its activity will relaunch, which will trigger removal and addition of 7044 * a window. 7045 * @param token Application token for which the activity will be relaunched. 7046 */ setWillReplaceWindow(IBinder token, boolean animate)7047 public void setWillReplaceWindow(IBinder token, boolean animate) { 7048 synchronized (mWindowMap) { 7049 final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token); 7050 if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) { 7051 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token " 7052 + token); 7053 return; 7054 } 7055 appWindowToken.setWillReplaceWindows(animate); 7056 } 7057 } 7058 7059 /** 7060 * Hint to a token that its windows will be replaced across activity relaunch. 7061 * The windows would otherwise be removed shortly following this as the 7062 * activity is torn down. 7063 * @param token Application token for which the activity will be relaunched. 7064 * @param childrenOnly Whether to mark only child windows for replacement 7065 * (for the case where main windows are being preserved/ 7066 * reused rather than replaced). 7067 * 7068 */ 7069 // TODO: The s at the end of the method name is the only difference with the name of the method 7070 // above. We should combine them or find better names. setWillReplaceWindows(IBinder token, boolean childrenOnly)7071 void setWillReplaceWindows(IBinder token, boolean childrenOnly) { 7072 synchronized (mWindowMap) { 7073 final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token); 7074 if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) { 7075 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token " 7076 + token); 7077 return; 7078 } 7079 7080 if (childrenOnly) { 7081 appWindowToken.setWillReplaceChildWindows(); 7082 } else { 7083 appWindowToken.setWillReplaceWindows(false /* animate */); 7084 } 7085 7086 scheduleClearWillReplaceWindows(token, true /* replacing */); 7087 } 7088 } 7089 7090 /** 7091 * If we're replacing the window, schedule a timer to clear the replaced window 7092 * after a timeout, in case the replacing window is not coming. 7093 * 7094 * If we're not replacing the window, clear the replace window settings of the app. 7095 * 7096 * @param token Application token for the activity whose window might be replaced. 7097 * @param replacing Whether the window is being replaced or not. 7098 */ scheduleClearWillReplaceWindows(IBinder token, boolean replacing)7099 public void scheduleClearWillReplaceWindows(IBinder token, boolean replacing) { 7100 synchronized (mWindowMap) { 7101 final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token); 7102 if (appWindowToken == null) { 7103 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token " 7104 + token); 7105 return; 7106 } 7107 if (replacing) { 7108 scheduleWindowReplacementTimeouts(appWindowToken); 7109 } else { 7110 appWindowToken.clearWillReplaceWindows(); 7111 } 7112 } 7113 } 7114 scheduleWindowReplacementTimeouts(AppWindowToken appWindowToken)7115 void scheduleWindowReplacementTimeouts(AppWindowToken appWindowToken) { 7116 if (!mWindowReplacementTimeouts.contains(appWindowToken)) { 7117 mWindowReplacementTimeouts.add(appWindowToken); 7118 } 7119 mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT); 7120 mH.sendEmptyMessageDelayed( 7121 H.WINDOW_REPLACEMENT_TIMEOUT, WINDOW_REPLACEMENT_TIMEOUT_DURATION); 7122 } 7123 7124 @Override getDockedStackSide()7125 public int getDockedStackSide() { 7126 synchronized (mWindowMap) { 7127 final TaskStack dockedStack = getDefaultDisplayContentLocked() 7128 .getDockedStackIgnoringVisibility(); 7129 return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(); 7130 } 7131 } 7132 7133 @Override setDockedStackResizing(boolean resizing)7134 public void setDockedStackResizing(boolean resizing) { 7135 synchronized (mWindowMap) { 7136 getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing); 7137 requestTraversal(); 7138 } 7139 } 7140 7141 @Override setDockedStackDividerTouchRegion(Rect touchRegion)7142 public void setDockedStackDividerTouchRegion(Rect touchRegion) { 7143 synchronized (mWindowMap) { 7144 getDefaultDisplayContentLocked().getDockedDividerController() 7145 .setTouchRegion(touchRegion); 7146 setFocusTaskRegionLocked(null); 7147 } 7148 } 7149 7150 @Override setResizeDimLayer(boolean visible, int targetStackId, float alpha)7151 public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) { 7152 synchronized (mWindowMap) { 7153 getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer( 7154 visible, targetStackId, alpha); 7155 } 7156 } 7157 setForceResizableTasks(boolean forceResizableTasks)7158 public void setForceResizableTasks(boolean forceResizableTasks) { 7159 synchronized (mWindowMap) { 7160 mForceResizableTasks = forceResizableTasks; 7161 } 7162 } 7163 setSupportsPictureInPicture(boolean supportsPictureInPicture)7164 public void setSupportsPictureInPicture(boolean supportsPictureInPicture) { 7165 synchronized (mWindowMap) { 7166 mSupportsPictureInPicture = supportsPictureInPicture; 7167 } 7168 } 7169 dipToPixel(int dip, DisplayMetrics displayMetrics)7170 static int dipToPixel(int dip, DisplayMetrics displayMetrics) { 7171 return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics); 7172 } 7173 7174 @Override registerDockedStackListener(IDockedStackListener listener)7175 public void registerDockedStackListener(IDockedStackListener listener) { 7176 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, 7177 "registerDockedStackListener()")) { 7178 return; 7179 } 7180 synchronized (mWindowMap) { 7181 // TODO(multi-display): The listener is registered on the default display only. 7182 getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener( 7183 listener); 7184 } 7185 } 7186 7187 @Override registerPinnedStackListener(int displayId, IPinnedStackListener listener)7188 public void registerPinnedStackListener(int displayId, IPinnedStackListener listener) { 7189 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, 7190 "registerPinnedStackListener()")) { 7191 return; 7192 } 7193 if (!mSupportsPictureInPicture) { 7194 return; 7195 } 7196 synchronized (mWindowMap) { 7197 final DisplayContent displayContent = mRoot.getDisplayContent(displayId); 7198 displayContent.getPinnedStackController().registerPinnedStackListener(listener); 7199 } 7200 } 7201 7202 @Override requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId)7203 public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) { 7204 try { 7205 WindowState focusedWindow = getFocusedWindow(); 7206 if (focusedWindow != null && focusedWindow.mClient != null) { 7207 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId); 7208 } 7209 } catch (RemoteException e) { 7210 } 7211 } 7212 7213 @Override getStableInsets(int displayId, Rect outInsets)7214 public void getStableInsets(int displayId, Rect outInsets) throws RemoteException { 7215 synchronized (mWindowMap) { 7216 getStableInsetsLocked(displayId, outInsets); 7217 } 7218 } 7219 getStableInsetsLocked(int displayId, Rect outInsets)7220 void getStableInsetsLocked(int displayId, Rect outInsets) { 7221 outInsets.setEmpty(); 7222 final DisplayContent dc = mRoot.getDisplayContent(displayId); 7223 if (dc != null) { 7224 final DisplayInfo di = dc.getDisplayInfo(); 7225 mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets); 7226 } 7227 } 7228 intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds)7229 void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) { 7230 mTmpRect3.set(display); 7231 mTmpRect3.inset(insets); 7232 inOutBounds.intersect(mTmpRect3); 7233 } 7234 7235 MousePositionTracker mMousePositionTracker = new MousePositionTracker(); 7236 7237 private static class MousePositionTracker implements PointerEventListener { 7238 private boolean mLatestEventWasMouse; 7239 private float mLatestMouseX; 7240 private float mLatestMouseY; 7241 updatePosition(float x, float y)7242 void updatePosition(float x, float y) { 7243 synchronized (this) { 7244 mLatestEventWasMouse = true; 7245 mLatestMouseX = x; 7246 mLatestMouseY = y; 7247 } 7248 } 7249 7250 @Override onPointerEvent(MotionEvent motionEvent)7251 public void onPointerEvent(MotionEvent motionEvent) { 7252 if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) { 7253 updatePosition(motionEvent.getRawX(), motionEvent.getRawY()); 7254 } else { 7255 synchronized (this) { 7256 mLatestEventWasMouse = false; 7257 } 7258 } 7259 } 7260 }; 7261 updatePointerIcon(IWindow client)7262 void updatePointerIcon(IWindow client) { 7263 float mouseX, mouseY; 7264 7265 synchronized(mMousePositionTracker) { 7266 if (!mMousePositionTracker.mLatestEventWasMouse) { 7267 return; 7268 } 7269 mouseX = mMousePositionTracker.mLatestMouseX; 7270 mouseY = mMousePositionTracker.mLatestMouseY; 7271 } 7272 7273 synchronized (mWindowMap) { 7274 if (mDragState != null) { 7275 // Drag cursor overrides the app cursor. 7276 return; 7277 } 7278 WindowState callingWin = windowForClientLocked(null, client, false); 7279 if (callingWin == null) { 7280 Slog.w(TAG_WM, "Bad requesting window " + client); 7281 return; 7282 } 7283 final DisplayContent displayContent = callingWin.getDisplayContent(); 7284 if (displayContent == null) { 7285 return; 7286 } 7287 WindowState windowUnderPointer = 7288 displayContent.getTouchableWinAtPointLocked(mouseX, mouseY); 7289 if (windowUnderPointer != callingWin) { 7290 return; 7291 } 7292 try { 7293 windowUnderPointer.mClient.updatePointerIcon( 7294 windowUnderPointer.translateToWindowX(mouseX), 7295 windowUnderPointer.translateToWindowY(mouseY)); 7296 } catch (RemoteException e) { 7297 Slog.w(TAG_WM, "unable to update pointer icon"); 7298 } 7299 } 7300 } 7301 restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY)7302 void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) { 7303 // Mouse position tracker has not been getting updates while dragging, update it now. 7304 mMousePositionTracker.updatePosition(latestX, latestY); 7305 7306 WindowState windowUnderPointer = 7307 displayContent.getTouchableWinAtPointLocked(latestX, latestY); 7308 if (windowUnderPointer != null) { 7309 try { 7310 windowUnderPointer.mClient.updatePointerIcon( 7311 windowUnderPointer.translateToWindowX(latestX), 7312 windowUnderPointer.translateToWindowY(latestY)); 7313 } catch (RemoteException e) { 7314 Slog.w(TAG_WM, "unable to restore pointer icon"); 7315 } 7316 } else { 7317 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT); 7318 } 7319 } 7320 7321 @Override registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)7322 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver) 7323 throws RemoteException { 7324 if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) { 7325 throw new SecurityException( 7326 "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission"); 7327 } 7328 mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver); 7329 } 7330 markForSeamlessRotation(WindowState w, boolean seamlesslyRotated)7331 void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) { 7332 if (seamlesslyRotated == w.mSeamlesslyRotated) { 7333 return; 7334 } 7335 w.mSeamlesslyRotated = seamlesslyRotated; 7336 if (seamlesslyRotated) { 7337 mSeamlessRotationCount++; 7338 } else { 7339 mSeamlessRotationCount--; 7340 } 7341 if (mSeamlessRotationCount == 0) { 7342 if (DEBUG_ORIENTATION) { 7343 Slog.i(TAG, "Performing post-rotate rotation after seamless rotation"); 7344 } 7345 final DisplayContent displayContent = w.getDisplayContent(); 7346 if (displayContent.updateRotationUnchecked(false /* inTransaction */)) { 7347 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId()) 7348 .sendToTarget(); 7349 } 7350 } 7351 } 7352 7353 private final class LocalService extends WindowManagerInternal { 7354 @Override requestTraversalFromDisplayManager()7355 public void requestTraversalFromDisplayManager() { 7356 requestTraversal(); 7357 } 7358 7359 @Override setMagnificationSpec(MagnificationSpec spec)7360 public void setMagnificationSpec(MagnificationSpec spec) { 7361 synchronized (mWindowMap) { 7362 if (mAccessibilityController != null) { 7363 mAccessibilityController.setMagnificationSpecLocked(spec); 7364 } else { 7365 throw new IllegalStateException("Magnification callbacks not set!"); 7366 } 7367 } 7368 if (Binder.getCallingPid() != myPid()) { 7369 spec.recycle(); 7370 } 7371 } 7372 7373 @Override setForceShowMagnifiableBounds(boolean show)7374 public void setForceShowMagnifiableBounds(boolean show) { 7375 synchronized (mWindowMap) { 7376 if (mAccessibilityController != null) { 7377 mAccessibilityController.setForceShowMagnifiableBoundsLocked(show); 7378 } else { 7379 throw new IllegalStateException("Magnification callbacks not set!"); 7380 } 7381 } 7382 } 7383 7384 @Override getMagnificationRegion(@onNull Region magnificationRegion)7385 public void getMagnificationRegion(@NonNull Region magnificationRegion) { 7386 synchronized (mWindowMap) { 7387 if (mAccessibilityController != null) { 7388 mAccessibilityController.getMagnificationRegionLocked(magnificationRegion); 7389 } else { 7390 throw new IllegalStateException("Magnification callbacks not set!"); 7391 } 7392 } 7393 } 7394 7395 @Override getCompatibleMagnificationSpecForWindow(IBinder windowToken)7396 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 7397 synchronized (mWindowMap) { 7398 WindowState windowState = mWindowMap.get(windowToken); 7399 if (windowState == null) { 7400 return null; 7401 } 7402 MagnificationSpec spec = null; 7403 if (mAccessibilityController != null) { 7404 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 7405 } 7406 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 7407 return null; 7408 } 7409 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 7410 spec.scale *= windowState.mGlobalScale; 7411 return spec; 7412 } 7413 } 7414 7415 @Override setMagnificationCallbacks(@ullable MagnificationCallbacks callbacks)7416 public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) { 7417 synchronized (mWindowMap) { 7418 if (mAccessibilityController == null) { 7419 mAccessibilityController = new AccessibilityController( 7420 WindowManagerService.this); 7421 } 7422 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 7423 if (!mAccessibilityController.hasCallbacksLocked()) { 7424 mAccessibilityController = null; 7425 } 7426 } 7427 } 7428 7429 @Override setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback)7430 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 7431 synchronized (mWindowMap) { 7432 if (mAccessibilityController == null) { 7433 mAccessibilityController = new AccessibilityController( 7434 WindowManagerService.this); 7435 } 7436 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 7437 if (!mAccessibilityController.hasCallbacksLocked()) { 7438 mAccessibilityController = null; 7439 } 7440 } 7441 } 7442 7443 @Override setInputFilter(IInputFilter filter)7444 public void setInputFilter(IInputFilter filter) { 7445 mInputManager.setInputFilter(filter); 7446 } 7447 7448 @Override getFocusedWindowToken()7449 public IBinder getFocusedWindowToken() { 7450 synchronized (mWindowMap) { 7451 WindowState windowState = getFocusedWindowLocked(); 7452 if (windowState != null) { 7453 return windowState.mClient.asBinder(); 7454 } 7455 return null; 7456 } 7457 } 7458 7459 @Override isKeyguardLocked()7460 public boolean isKeyguardLocked() { 7461 return WindowManagerService.this.isKeyguardLocked(); 7462 } 7463 7464 @Override isKeyguardShowingAndNotOccluded()7465 public boolean isKeyguardShowingAndNotOccluded() { 7466 return WindowManagerService.this.isKeyguardShowingAndNotOccluded(); 7467 } 7468 7469 @Override showGlobalActions()7470 public void showGlobalActions() { 7471 WindowManagerService.this.showGlobalActions(); 7472 } 7473 7474 @Override getWindowFrame(IBinder token, Rect outBounds)7475 public void getWindowFrame(IBinder token, Rect outBounds) { 7476 synchronized (mWindowMap) { 7477 WindowState windowState = mWindowMap.get(token); 7478 if (windowState != null) { 7479 outBounds.set(windowState.mFrame); 7480 } else { 7481 outBounds.setEmpty(); 7482 } 7483 } 7484 } 7485 7486 @Override waitForAllWindowsDrawn(Runnable callback, long timeout)7487 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 7488 boolean allWindowsDrawn = false; 7489 synchronized (mWindowMap) { 7490 mWaitingForDrawnCallback = callback; 7491 getDefaultDisplayContentLocked().waitForAllWindowsDrawn(); 7492 mWindowPlacerLocked.requestTraversal(); 7493 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 7494 if (mWaitingForDrawn.isEmpty()) { 7495 allWindowsDrawn = true; 7496 } else { 7497 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 7498 checkDrawnWindowsLocked(); 7499 } 7500 } 7501 if (allWindowsDrawn) { 7502 callback.run(); 7503 } 7504 } 7505 7506 @Override addWindowToken(IBinder token, int type, int displayId)7507 public void addWindowToken(IBinder token, int type, int displayId) { 7508 WindowManagerService.this.addWindowToken(token, type, displayId); 7509 } 7510 7511 @Override removeWindowToken(IBinder binder, boolean removeWindows, int displayId)7512 public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) { 7513 synchronized(mWindowMap) { 7514 if (removeWindows) { 7515 final DisplayContent dc = mRoot.getDisplayContent(displayId); 7516 if (dc == null) { 7517 Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder 7518 + " for non-exiting displayId=" + displayId); 7519 return; 7520 } 7521 7522 final WindowToken token = dc.removeWindowToken(binder); 7523 if (token == null) { 7524 Slog.w(TAG_WM, "removeWindowToken: Attempted to remove non-existing token: " 7525 + binder); 7526 return; 7527 } 7528 7529 token.removeAllWindowsIfPossible(); 7530 } 7531 WindowManagerService.this.removeWindowToken(binder, displayId); 7532 } 7533 } 7534 7535 @Override registerAppTransitionListener(AppTransitionListener listener)7536 public void registerAppTransitionListener(AppTransitionListener listener) { 7537 synchronized (mWindowMap) { 7538 mAppTransition.registerListenerLocked(listener); 7539 } 7540 } 7541 7542 @Override getInputMethodWindowVisibleHeight()7543 public int getInputMethodWindowVisibleHeight() { 7544 synchronized (mWindowMap) { 7545 return mPolicy.getInputMethodWindowVisibleHeightLw(); 7546 } 7547 } 7548 7549 @Override saveLastInputMethodWindowForTransition()7550 public void saveLastInputMethodWindowForTransition() { 7551 synchronized (mWindowMap) { 7552 if (mInputMethodWindow != null) { 7553 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 7554 } 7555 } 7556 } 7557 7558 @Override clearLastInputMethodWindowForTransition()7559 public void clearLastInputMethodWindowForTransition() { 7560 synchronized (mWindowMap) { 7561 mPolicy.setLastInputMethodWindowLw(null, null); 7562 } 7563 } 7564 7565 @Override updateInputMethodWindowStatus(@onNull IBinder imeToken, boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed, @Nullable IBinder targetWindowToken)7566 public void updateInputMethodWindowStatus(@NonNull IBinder imeToken, 7567 boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed, 7568 @Nullable IBinder targetWindowToken) { 7569 // TODO (b/34628091): Use this method to address the window animation issue. 7570 if (DEBUG_INPUT_METHOD) { 7571 Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken 7572 + " dismissImeOnBackKeyPressed=" + dismissImeOnBackKeyPressed 7573 + " imeWindowVisible=" + imeWindowVisible 7574 + " targetWindowToken=" + targetWindowToken); 7575 } 7576 mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed); 7577 } 7578 7579 @Override isHardKeyboardAvailable()7580 public boolean isHardKeyboardAvailable() { 7581 synchronized (mWindowMap) { 7582 return mHardKeyboardAvailable; 7583 } 7584 } 7585 7586 @Override setOnHardKeyboardStatusChangeListener( OnHardKeyboardStatusChangeListener listener)7587 public void setOnHardKeyboardStatusChangeListener( 7588 OnHardKeyboardStatusChangeListener listener) { 7589 synchronized (mWindowMap) { 7590 mHardKeyboardStatusChangeListener = listener; 7591 } 7592 } 7593 7594 @Override isStackVisible(int stackId)7595 public boolean isStackVisible(int stackId) { 7596 synchronized (mWindowMap) { 7597 final DisplayContent dc = getDefaultDisplayContentLocked(); 7598 return dc.isStackVisible(stackId); 7599 } 7600 } 7601 7602 @Override isDockedDividerResizing()7603 public boolean isDockedDividerResizing() { 7604 synchronized (mWindowMap) { 7605 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing(); 7606 } 7607 } 7608 7609 @Override computeWindowsForAccessibility()7610 public void computeWindowsForAccessibility() { 7611 final AccessibilityController accessibilityController; 7612 synchronized (mWindowMap) { 7613 accessibilityController = mAccessibilityController; 7614 } 7615 if (accessibilityController != null) { 7616 accessibilityController.performComputeChangedWindowsNotLocked(); 7617 } 7618 } 7619 7620 @Override setVr2dDisplayId(int vr2dDisplayId)7621 public void setVr2dDisplayId(int vr2dDisplayId) { 7622 if (DEBUG_DISPLAY) { 7623 Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId); 7624 } 7625 synchronized (WindowManagerService.this) { 7626 mVr2dDisplayId = vr2dDisplayId; 7627 } 7628 } 7629 } 7630 registerAppFreezeListener(AppFreezeListener listener)7631 void registerAppFreezeListener(AppFreezeListener listener) { 7632 if (!mAppFreezeListeners.contains(listener)) { 7633 mAppFreezeListeners.add(listener); 7634 } 7635 } 7636 unregisterAppFreezeListener(AppFreezeListener listener)7637 void unregisterAppFreezeListener(AppFreezeListener listener) { 7638 mAppFreezeListeners.remove(listener); 7639 } 7640 7641 /** 7642 * WARNING: This interrupts surface updates, be careful! Don't 7643 * execute within the transaction for longer than you would 7644 * execute on an animation thread. 7645 * WARNING: This holds the WindowManager lock, so if exec will acquire 7646 * the ActivityManager lock, you should hold it BEFORE calling this 7647 * otherwise there is a risk of deadlock if another thread holding the AM 7648 * lock waits on the WM lock. 7649 * WARNING: This method contains locks known to the State of California 7650 * to cause Deadlocks and other conditions. 7651 * 7652 * Begins a surface transaction with which the AM can batch operations. 7653 * All Surface updates performed by the WindowManager following this 7654 * will not appear on screen until after the call to 7655 * closeSurfaceTransaction. 7656 * 7657 * ActivityManager can use this to ensure multiple 'commands' will all 7658 * be reflected in a single frame. For example when reparenting a window 7659 * which was previously hidden due to it's parent properties, we may 7660 * need to ensure it is hidden in the same frame that the properties 7661 * from the new parent are inherited, otherwise it could be revealed 7662 * mistakenly. 7663 * 7664 * TODO(b/36393204): We can investigate totally replacing #deferSurfaceLayout 7665 * with something like this but it seems that some existing cases of 7666 * deferSurfaceLayout may be a little too broad, in particular the total 7667 * enclosure of startActivityUnchecked which could run for quite some time. 7668 */ inSurfaceTransaction(Runnable exec)7669 public void inSurfaceTransaction(Runnable exec) { 7670 // We hold the WindowManger lock to ensure relayoutWindow 7671 // does not return while a Surface transaction is opening. 7672 // The client depends on us to have resized the surface 7673 // by that point (b/36462635) 7674 7675 synchronized (mWindowMap) { 7676 SurfaceControl.openTransaction(); 7677 try { 7678 exec.run(); 7679 } finally { 7680 SurfaceControl.closeTransaction(); 7681 } 7682 } 7683 } 7684 7685 /** Called to inform window manager if non-Vr UI shoul be disabled or not. */ disableNonVrUi(boolean disable)7686 public void disableNonVrUi(boolean disable) { 7687 synchronized (mWindowMap) { 7688 // Allow alert window notifications to be shown if non-vr UI is enabled. 7689 final boolean showAlertWindowNotifications = !disable; 7690 if (showAlertWindowNotifications == mShowAlertWindowNotifications) { 7691 return; 7692 } 7693 mShowAlertWindowNotifications = showAlertWindowNotifications; 7694 7695 for (int i = mSessions.size() - 1; i >= 0; --i) { 7696 final Session s = mSessions.valueAt(i); 7697 s.setShowingAlertWindowNotificationAllowed(mShowAlertWindowNotifications); 7698 } 7699 } 7700 } 7701 hasWideColorGamutSupport()7702 boolean hasWideColorGamutSupport() { 7703 return mHasWideColorGamutSupport && 7704 !SystemProperties.getBoolean("persist.sys.sf.native_mode", false); 7705 } 7706 updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown)7707 void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) { 7708 if (!win.hideNonSystemOverlayWindowsWhenVisible() 7709 && !mHidingNonSystemOverlayWindows.contains(win)) { 7710 return; 7711 } 7712 final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty(); 7713 if (surfaceShown) { 7714 if (!mHidingNonSystemOverlayWindows.contains(win)) { 7715 mHidingNonSystemOverlayWindows.add(win); 7716 } 7717 } else { 7718 mHidingNonSystemOverlayWindows.remove(win); 7719 } 7720 7721 final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty(); 7722 7723 if (systemAlertWindowsHidden == hideSystemAlertWindows) { 7724 return; 7725 } 7726 7727 mRoot.forAllWindows((w) -> { 7728 w.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows); 7729 }, false /* traverseTopToBottom */); 7730 } 7731 } 7732