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