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