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