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 android.Manifest; 20 import android.animation.ValueAnimator; 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.app.ActivityManager; 25 import android.app.ActivityManagerInternal; 26 import android.app.ActivityManagerNative; 27 import android.app.AppOpsManager; 28 import android.app.IActivityManager; 29 import android.app.Notification; 30 import android.app.NotificationManager; 31 import android.app.PendingIntent; 32 import android.app.admin.DevicePolicyManager; 33 import android.content.BroadcastReceiver; 34 import android.content.ContentResolver; 35 import android.content.Context; 36 import android.content.Intent; 37 import android.content.IntentFilter; 38 import android.content.pm.ActivityInfo; 39 import android.content.pm.ApplicationInfo; 40 import android.content.pm.PackageManager; 41 import android.content.res.CompatibilityInfo; 42 import android.content.res.Configuration; 43 import android.database.ContentObserver; 44 import android.graphics.Bitmap; 45 import android.graphics.PixelFormat; 46 import android.graphics.Matrix; 47 import android.graphics.Point; 48 import android.graphics.Rect; 49 import android.graphics.RectF; 50 import android.graphics.Region; 51 import android.hardware.display.DisplayManager; 52 import android.hardware.display.DisplayManagerInternal; 53 import android.hardware.input.InputManager; 54 import android.net.Uri; 55 import android.os.Binder; 56 import android.os.Build; 57 import android.os.Bundle; 58 import android.os.Debug; 59 import android.os.Handler; 60 import android.os.IBinder; 61 import android.os.IRemoteCallback; 62 import android.os.Looper; 63 import android.os.Message; 64 import android.os.Parcel; 65 import android.os.ParcelFileDescriptor; 66 import android.os.PowerManager; 67 import android.os.PowerManagerInternal; 68 import android.os.Process; 69 import android.os.RemoteException; 70 import android.os.ServiceManager; 71 import android.os.StrictMode; 72 import android.os.SystemClock; 73 import android.os.SystemProperties; 74 import android.os.SystemService; 75 import android.os.Trace; 76 import android.os.UserHandle; 77 import android.os.WorkSource; 78 import android.provider.Settings; 79 import android.util.ArraySet; 80 import android.util.DisplayMetrics; 81 import android.util.EventLog; 82 import android.util.Log; 83 import android.util.Pair; 84 import android.util.Slog; 85 import android.util.SparseArray; 86 import android.util.SparseIntArray; 87 import android.util.TimeUtils; 88 import android.util.TypedValue; 89 import android.view.AppTransitionAnimationSpec; 90 import android.view.Choreographer; 91 import android.view.Display; 92 import android.view.DisplayInfo; 93 import android.view.Gravity; 94 import android.view.PointerIcon; 95 import android.view.IAppTransitionAnimationSpecsFuture; 96 import android.view.IApplicationToken; 97 import android.view.IDockedStackListener; 98 import android.view.IInputFilter; 99 import android.view.IOnKeyguardExitResult; 100 import android.view.IRotationWatcher; 101 import android.view.IWindow; 102 import android.view.IWindowId; 103 import android.view.IWindowManager; 104 import android.view.IWindowSession; 105 import android.view.IWindowSessionCallback; 106 import android.view.InputChannel; 107 import android.view.InputDevice; 108 import android.view.InputEvent; 109 import android.view.InputEventReceiver; 110 import android.view.KeyEvent; 111 import android.view.MagnificationSpec; 112 import android.view.MotionEvent; 113 import android.view.Surface; 114 import android.view.Surface.OutOfResourcesException; 115 import android.view.SurfaceControl; 116 import android.view.SurfaceSession; 117 import android.view.View; 118 import android.view.WindowContentFrameStats; 119 import android.view.WindowManager; 120 import android.view.WindowManager.LayoutParams; 121 import android.view.WindowManagerGlobal; 122 import android.view.WindowManagerInternal; 123 import android.view.WindowManagerPolicy; 124 import android.view.WindowManagerPolicy.PointerEventListener; 125 import android.view.animation.Animation; 126 import android.view.inputmethod.InputMethodManagerInternal; 127 128 import com.android.internal.R; 129 import com.android.internal.app.IAssistScreenshotReceiver; 130 import com.android.internal.os.IResultReceiver; 131 import com.android.internal.policy.IShortcutService; 132 import com.android.internal.util.ArrayUtils; 133 import com.android.internal.util.FastPrintWriter; 134 import com.android.internal.view.IInputContext; 135 import com.android.internal.view.IInputMethodClient; 136 import com.android.internal.view.IInputMethodManager; 137 import com.android.internal.view.WindowManagerPolicyThread; 138 import com.android.server.AttributeCache; 139 import com.android.server.DisplayThread; 140 import com.android.server.EventLogTags; 141 import com.android.server.FgThread; 142 import com.android.server.LocalServices; 143 import com.android.server.UiThread; 144 import com.android.server.Watchdog; 145 import com.android.server.input.InputManagerService; 146 import com.android.server.policy.PhoneWindowManager; 147 import com.android.server.power.ShutdownThread; 148 149 import java.io.BufferedWriter; 150 import java.io.DataInputStream; 151 import java.io.File; 152 import java.io.FileDescriptor; 153 import java.io.FileInputStream; 154 import java.io.FileNotFoundException; 155 import java.io.IOException; 156 import java.io.OutputStream; 157 import java.io.OutputStreamWriter; 158 import java.io.PrintWriter; 159 import java.io.StringWriter; 160 import java.lang.annotation.Retention; 161 import java.lang.annotation.RetentionPolicy; 162 import java.net.Socket; 163 import java.text.DateFormat; 164 import java.util.ArrayList; 165 import java.util.Arrays; 166 import java.util.Date; 167 import java.util.HashMap; 168 import java.util.Iterator; 169 import java.util.List; 170 171 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; 172 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 173 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 174 import static android.app.ActivityManager.StackId.PINNED_STACK_ID; 175 import static android.app.StatusBarManager.DISABLE_MASK; 176 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 177 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 178 import static android.view.WindowManager.DOCKED_BOTTOM; 179 import static android.view.WindowManager.DOCKED_INVALID; 180 import static android.view.WindowManager.DOCKED_TOP; 181 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; 182 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 183 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 184 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 185 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 186 import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 187 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 188 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 189 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 190 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 191 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; 192 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 193 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 194 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 195 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 196 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; 197 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 198 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 199 import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 200 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 201 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 202 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 203 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; 204 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; 205 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 206 import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 207 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; 208 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 209 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY; 210 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; 211 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 212 import static android.view.WindowManagerPolicy.TRANSIT_EXIT; 213 import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 214 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END; 215 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START; 216 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; 217 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; 218 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; 219 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 220 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 221 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_ORIENTATION; 222 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 223 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; 224 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION; 225 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 226 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG; 227 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 228 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 229 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 230 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD; 231 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON; 232 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 233 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 234 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE; 235 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; 236 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON; 237 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; 238 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW; 239 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE; 240 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; 241 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT; 242 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 243 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 244 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT; 245 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; 246 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 247 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 248 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC; 249 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 250 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSACTIONS; 251 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON; 252 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 253 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 254 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; 255 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; 256 257 /** {@hide} */ 258 public class WindowManagerService extends IWindowManager.Stub 259 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { 260 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM; 261 262 static final int LAYOUT_REPEAT_THRESHOLD = 4; 263 264 static final boolean PROFILE_ORIENTATION = false; 265 static final boolean localLOGV = DEBUG; 266 267 /** How much to multiply the policy's type layer, to reserve room 268 * for multiple windows of the same type and Z-ordering adjustment 269 * with TYPE_LAYER_OFFSET. */ 270 static final int TYPE_LAYER_MULTIPLIER = 10000; 271 272 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above 273 * or below others in the same layer. */ 274 static final int TYPE_LAYER_OFFSET = 1000; 275 276 /** How much to increment the layer for each window, to reserve room 277 * for effect surfaces between them. 278 */ 279 static final int WINDOW_LAYER_MULTIPLIER = 5; 280 281 /** 282 * Dim surface layer is immediately below target window. 283 */ 284 static final int LAYER_OFFSET_DIM = 1; 285 286 /** 287 * Animation thumbnail is as far as possible below the window above 288 * the thumbnail (or in other words as far as possible above the window 289 * below it). 290 */ 291 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1; 292 293 /** The maximum length we will accept for a loaded animation duration: 294 * this is 10 seconds. 295 */ 296 static final int MAX_ANIMATION_DURATION = 10 * 1000; 297 298 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 299 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 300 301 /** Amount of time (in milliseconds) to delay before declaring a seamless rotation timeout. */ 302 static final int SEAMLESS_ROTATION_TIMEOUT_DURATION = 2000; 303 304 /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */ 305 static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000; 306 307 /** Amount of time to allow a last ANR message to exist before freeing the memory. */ 308 static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours 309 /** 310 * If true, the window manager will do its own custom freezing and general 311 * management of the screen during rotation. 312 */ 313 static final boolean CUSTOM_SCREEN_ROTATION = true; 314 315 // Maximum number of milliseconds to wait for input devices to be enumerated before 316 // proceding with safe mode detection. 317 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 318 319 // Default input dispatching timeout in nanoseconds. 320 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; 321 322 // Poll interval in milliseconds for watching boot animation finished. 323 private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; 324 325 // The name of the boot animation service in init.rc. 326 private static final String BOOT_ANIMATION_SERVICE = "bootanim"; 327 328 static final int UPDATE_FOCUS_NORMAL = 0; 329 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 330 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 331 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 332 333 private static final String SYSTEM_SECURE = "ro.secure"; 334 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 335 336 private static final String DENSITY_OVERRIDE = "ro.config.density_override"; 337 private static final String SIZE_OVERRIDE = "ro.config.size_override"; 338 339 private static final int MAX_SCREENSHOT_RETRIES = 3; 340 341 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular"; 342 343 // Used to indicate that if there is already a transition set, it should be preserved when 344 // trying to apply a new one. 345 private static final boolean ALWAYS_KEEP_CURRENT = true; 346 347 private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f; 348 349 private static final String PROPERTY_BUILD_DATE_UTC = "ro.build.date.utc"; 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 361 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 362 @Override 363 public void onReceive(Context context, Intent intent) { 364 final String action = intent.getAction(); 365 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) { 366 mKeyguardDisableHandler.sendEmptyMessage( 367 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED); 368 } 369 } 370 }; 371 final WindowSurfacePlacer mWindowPlacerLocked; 372 373 /** 374 * Current user when multi-user is enabled. Don't show windows of 375 * non-current user. Also see mCurrentProfileIds. 376 */ 377 int mCurrentUserId; 378 /** 379 * Users that are profiles of the current user. These are also allowed to show windows 380 * on the current user. 381 */ 382 int[] mCurrentProfileIds = new int[] {}; 383 384 final Context mContext; 385 386 final boolean mHaveInputMethods; 387 388 final boolean mHasPermanentDpad; 389 final long mDrawLockTimeoutMillis; 390 final boolean mAllowAnimationsInLowPowerMode; 391 392 final boolean mAllowBootMessages; 393 394 final boolean mLimitedAlphaCompositing; 395 396 final WindowManagerPolicy mPolicy = new PhoneWindowManager(); 397 398 final IActivityManager mActivityManager; 399 final ActivityManagerInternal mAmInternal; 400 401 final AppOpsManager mAppOps; 402 403 final DisplaySettings mDisplaySettings; 404 405 /** 406 * All currently active sessions with clients. 407 */ 408 final ArraySet<Session> mSessions = new ArraySet<>(); 409 410 /** 411 * Mapping from an IWindow IBinder to the server's Window object. 412 * This is also used as the lock for all of our state. 413 * NOTE: Never call into methods that lock ActivityManagerService while holding this object. 414 */ 415 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>(); 416 417 /** 418 * Mapping from a token IBinder to a WindowToken object. 419 */ 420 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<>(); 421 422 /** 423 * List of window tokens that have finished starting their application, 424 * and now need to have the policy remove their windows. 425 */ 426 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>(); 427 428 /** 429 * List of window tokens that have finished drawing their own windows and 430 * no longer need to show any saved surfaces. Windows that's still showing 431 * saved surfaces will be cleaned up after next animation pass. 432 */ 433 final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>(); 434 435 /** 436 * List of app window tokens that are waiting for replacing windows. If the 437 * replacement doesn't come in time the stale windows needs to be disposed of. 438 */ 439 final ArrayList<AppWindowToken> mReplacingWindowTimeouts = new ArrayList<>(); 440 441 /** 442 * The input consumer added to the window manager which consumes input events to windows below 443 * it. 444 */ 445 InputConsumerImpl mInputConsumer; 446 447 /** 448 * The input consumer added to the window manager before all wallpaper windows. 449 */ 450 InputConsumerImpl mWallpaperInputConsumer; 451 452 /** 453 * Windows that are being resized. Used so we can tell the client about 454 * the resize after closing the transaction in which we resized the 455 * underlying surface. 456 */ 457 final ArrayList<WindowState> mResizingWindows = new ArrayList<>(); 458 459 /** 460 * Windows whose animations have ended and now must be removed. 461 */ 462 final ArrayList<WindowState> mPendingRemove = new ArrayList<>(); 463 464 /** 465 * Used when processing mPendingRemove to avoid working on the original array. 466 */ 467 WindowState[] mPendingRemoveTmp = new WindowState[20]; 468 469 /** 470 * Windows whose surface should be destroyed. 471 */ 472 final ArrayList<WindowState> mDestroySurface = new ArrayList<>(); 473 474 /** 475 * Windows with a preserved surface waiting to be destroyed. These windows 476 * are going through a surface change. We keep the old surface around until 477 * the first frame on the new surface finishes drawing. 478 */ 479 final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>(); 480 481 /** 482 * Windows that have lost input focus and are waiting for the new 483 * focus window to be displayed before they are told about this. 484 */ 485 ArrayList<WindowState> mLosingFocus = new ArrayList<>(); 486 487 /** 488 * This is set when we have run out of memory, and will either be an empty 489 * list or contain windows that need to be force removed. 490 */ 491 final ArrayList<WindowState> mForceRemoves = new ArrayList<>(); 492 493 /** 494 * Windows that clients are waiting to have drawn. 495 */ 496 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>(); 497 /** 498 * And the callback to make when they've all been drawn. 499 */ 500 Runnable mWaitingForDrawnCallback; 501 502 /** 503 * Used when rebuilding window list to keep track of windows that have 504 * been removed. 505 */ 506 WindowState[] mRebuildTmp = new WindowState[20]; 507 508 /** 509 * Stores for each user whether screencapture is disabled 510 * This array is essentially a cache for all userId for 511 * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled} 512 */ 513 SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>(); 514 515 IInputMethodManager mInputMethodManager; 516 517 AccessibilityController mAccessibilityController; 518 519 final SurfaceSession mFxSession; 520 Watermark mWatermark; 521 StrictModeFlash mStrictModeFlash; 522 CircularDisplayMask mCircularDisplayMask; 523 EmulatorDisplayOverlay mEmulatorDisplayOverlay; 524 525 final float[] mTmpFloats = new float[9]; 526 final Rect mTmpRect = new Rect(); 527 final Rect mTmpRect2 = new Rect(); 528 final Rect mTmpRect3 = new Rect(); 529 final RectF mTmpRectF = new RectF(); 530 531 final Matrix mTmpTransform = new Matrix(); 532 533 boolean mDisplayReady; 534 boolean mSafeMode; 535 boolean mDisplayEnabled = false; 536 boolean mSystemBooted = false; 537 boolean mForceDisplayEnabled = false; 538 boolean mShowingBootMessages = false; 539 boolean mBootAnimationStopped = false; 540 541 // Following variables are for debugging screen wakelock only. 542 WindowState mLastWakeLockHoldingWindow = null; 543 WindowState mLastWakeLockObscuringWindow = null; 544 545 /** Dump of the windows and app tokens at the time of the last ANR. Cleared after 546 * LAST_ANR_LIFETIME_DURATION_MSECS */ 547 String mLastANRState; 548 549 /** All DisplayContents in the world, kept here */ 550 SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2); 551 552 int mRotation = 0; 553 int mLastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 554 boolean mAltOrientation = false; 555 556 private boolean mKeyguardWaitingForActivityDrawn; 557 558 int mDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; 559 Rect mDockedStackCreateBounds; 560 561 private final SparseIntArray mTmpTaskIds = new SparseIntArray(); 562 563 private final ArrayList<Integer> mChangedStackList = new ArrayList(); 564 565 boolean mForceResizableTasks = false; 566 getDragLayerLocked()567 int getDragLayerLocked() { 568 return mPolicy.windowTypeToLayerLw(LayoutParams.TYPE_DRAG) * TYPE_LAYER_MULTIPLIER 569 + TYPE_LAYER_OFFSET; 570 } 571 572 class RotationWatcher { 573 IRotationWatcher watcher; 574 IBinder.DeathRecipient deathRecipient; RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d)575 RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) { 576 watcher = w; 577 deathRecipient = d; 578 } 579 } 580 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>(); 581 int mDeferredRotationPauseCount; 582 583 int mSystemDecorLayer = 0; 584 final Rect mScreenRect = new Rect(); 585 586 boolean mDisplayFrozen = false; 587 long mDisplayFreezeTime = 0; 588 int mLastDisplayFreezeDuration = 0; 589 Object mLastFinishedFreezeSource = null; 590 boolean mWaitingForConfig = false; 591 592 final static int WINDOWS_FREEZING_SCREENS_NONE = 0; 593 final static int WINDOWS_FREEZING_SCREENS_ACTIVE = 1; 594 final static int WINDOWS_FREEZING_SCREENS_TIMEOUT = 2; 595 int mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE; 596 597 boolean mClientFreezingScreen = false; 598 int mAppsFreezingScreen = 0; 599 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 600 int mLastKeyguardForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 601 602 int mLayoutSeq = 0; 603 604 // Last systemUiVisibility we received from status bar. 605 int mLastStatusBarVisibility = 0; 606 // Last systemUiVisibility we dispatched to windows. 607 int mLastDispatchedSystemUiVisibility = 0; 608 609 // State while inside of layoutAndPlaceSurfacesLocked(). 610 boolean mFocusMayChange; 611 612 Configuration mCurConfiguration = new Configuration(); 613 614 // This is held as long as we have the screen frozen, to give us time to 615 // perform a rotation animation when turning off shows the lock screen which 616 // changes the orientation. 617 private final PowerManager.WakeLock mScreenFrozenLock; 618 619 final AppTransition mAppTransition; 620 boolean mSkipAppTransitionAnimation = false; 621 622 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>(); 623 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>(); 624 625 boolean mIsTouchDevice; 626 627 final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 628 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 629 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 630 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 631 632 final H mH = new H(); 633 634 final Choreographer mChoreographer = Choreographer.getInstance(); 635 636 WindowState mCurrentFocus = null; 637 WindowState mLastFocus = null; 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 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<>(); 648 649 /** Temporary list for comparison. Always clear this after use so we don't end up with 650 * orphaned windows references */ 651 final ArrayList<WindowState> mTmpWindows = new ArrayList<>(); 652 653 boolean mHardKeyboardAvailable; 654 WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 655 SettingsObserver mSettingsObserver; 656 657 // A count of the windows which are 'seamlessly rotated', e.g. a surface 658 // at an old orientation is being transformed. We freeze orientation updates 659 // while any windows are seamlessly rotated, so we need to track when this 660 // hits zero so we can apply deferred orientation updates. 661 int mSeamlessRotationCount = 0; 662 663 private final class SettingsObserver extends ContentObserver { 664 private final Uri mDisplayInversionEnabledUri = 665 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 666 private final Uri mWindowAnimationScaleUri = 667 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE); 668 private final Uri mTransitionAnimationScaleUri = 669 Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE); 670 private final Uri mAnimationDurationScaleUri = 671 Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE); 672 SettingsObserver()673 public SettingsObserver() { 674 super(new Handler()); 675 ContentResolver resolver = mContext.getContentResolver(); 676 resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this, 677 UserHandle.USER_ALL); 678 resolver.registerContentObserver(mWindowAnimationScaleUri, false, this, 679 UserHandle.USER_ALL); 680 resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this, 681 UserHandle.USER_ALL); 682 resolver.registerContentObserver(mAnimationDurationScaleUri, false, this, 683 UserHandle.USER_ALL); 684 } 685 686 @Override onChange(boolean selfChange, Uri uri)687 public void onChange(boolean selfChange, Uri uri) { 688 if (uri == null) { 689 return; 690 } 691 692 if (mDisplayInversionEnabledUri.equals(uri)) { 693 updateCircularDisplayMaskIfNeeded(); 694 } else { 695 @UpdateAnimationScaleMode 696 final int mode; 697 if (mWindowAnimationScaleUri.equals(uri)) { 698 mode = WINDOW_ANIMATION_SCALE; 699 } else if (mTransitionAnimationScaleUri.equals(uri)) { 700 mode = TRANSITION_ANIMATION_SCALE; 701 } else if (mAnimationDurationScaleUri.equals(uri)) { 702 mode = ANIMATION_DURATION_SCALE; 703 } else { 704 // Ignoring unrecognized content changes 705 return; 706 } 707 Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0); 708 mH.sendMessage(m); 709 } 710 } 711 } 712 713 WallpaperController mWallpaperControllerLocked; 714 715 final WindowLayersController mLayersController; 716 717 boolean mAnimateWallpaperWithTarget; 718 719 AppWindowToken mFocusedApp = null; 720 721 PowerManager mPowerManager; 722 PowerManagerInternal mPowerManagerInternal; 723 724 float mWindowAnimationScaleSetting = 1.0f; 725 float mTransitionAnimationScaleSetting = 1.0f; 726 float mAnimatorDurationScaleSetting = 1.0f; 727 boolean mAnimationsDisabled = false; 728 729 final InputManagerService mInputManager; 730 final DisplayManagerInternal mDisplayManagerInternal; 731 final DisplayManager mDisplayManager; 732 final Display[] mDisplays; 733 734 // Who is holding the screen on. 735 Session mHoldingScreenOn; 736 PowerManager.WakeLock mHoldingScreenWakeLock; 737 738 boolean mTurnOnScreen; 739 740 // Whether or not a layout can cause a wake up when theater mode is enabled. 741 boolean mAllowTheaterModeWakeFromLayout; 742 743 TaskPositioner mTaskPositioner; 744 DragState mDragState = null; 745 746 // For frozen screen animations. 747 int mExitAnimId, mEnterAnimId; 748 749 boolean mAnimationScheduled; 750 751 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 752 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 753 int mTransactionSequence; 754 755 final WindowAnimator mAnimator; 756 757 private final BoundsAnimationController mBoundsAnimationController; 758 759 SparseArray<Task> mTaskIdToTask = new SparseArray<>(); 760 761 /** All of the TaskStacks in the window manager, unordered. For an ordered list call 762 * DisplayContent.getStacks(). */ 763 SparseArray<TaskStack> mStackIdToStack = new SparseArray<>(); 764 765 private final PointerEventDispatcher mPointerEventDispatcher; 766 767 private WindowContentFrameStats mTempWindowRenderStats; 768 769 final class DragInputEventReceiver extends InputEventReceiver { 770 // Set, if stylus button was down at the start of the drag. 771 private boolean mStylusButtonDownAtStart; 772 // Indicates the first event to check for button state. 773 private boolean mIsStartEvent = true; 774 DragInputEventReceiver(InputChannel inputChannel, Looper looper)775 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { 776 super(inputChannel, looper); 777 } 778 779 @Override onInputEvent(InputEvent event)780 public void onInputEvent(InputEvent event) { 781 boolean handled = false; 782 try { 783 if (event instanceof MotionEvent 784 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 785 && mDragState != null) { 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 synchronized (mWindowMap) { 814 endDrag = mDragState.notifyDropLw(newX, newY); 815 } 816 } else { 817 synchronized (mWindowMap) { 818 // move the surface and tell the involved window(s) where we are 819 mDragState.notifyMoveLw(newX, newY); 820 } 821 } 822 } break; 823 824 case MotionEvent.ACTION_UP: { 825 if (DEBUG_DRAG) Slog.d(TAG_WM, "Got UP on move channel; dropping at " 826 + newX + "," + newY); 827 synchronized (mWindowMap) { 828 endDrag = mDragState.notifyDropLw(newX, newY); 829 } 830 } break; 831 832 case MotionEvent.ACTION_CANCEL: { 833 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!"); 834 endDrag = true; 835 } break; 836 } 837 838 if (endDrag) { 839 if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state"); 840 // tell all the windows that the drag has ended 841 synchronized (mWindowMap) { 842 mDragState.endDragLw(); 843 } 844 mStylusButtonDownAtStart = false; 845 mIsStartEvent = true; 846 } 847 848 handled = true; 849 } 850 } catch (Exception e) { 851 Slog.e(TAG_WM, "Exception caught by drag handleMotion", e); 852 } finally { 853 finishInputEvent(event, handled); 854 } 855 } 856 } 857 858 /** 859 * Whether the UI is currently running in touch mode (not showing 860 * navigational focus because the user is directly pressing the screen). 861 */ 862 boolean mInTouchMode; 863 864 private ViewServer mViewServer; 865 final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>(); 866 boolean mWindowsChanged = false; 867 868 public interface WindowChangeListener { windowsChanged()869 public void windowsChanged(); focusChanged()870 public void focusChanged(); 871 } 872 873 final Configuration mTempConfiguration = new Configuration(); 874 875 // The desired scaling factor for compatible apps. 876 float mCompatibleScreenScale; 877 878 // If true, only the core apps and services are being launched because the device 879 // is in a special boot mode, such as being encrypted or waiting for a decryption password. 880 // For example, when this flag is true, there will be no wallpaper service. 881 final boolean mOnlyCore; 882 883 // List of clients without a transtiton animation that we notify once we are done transitioning 884 // since they won't be notified through the app window animator. 885 final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>(); 886 887 // List of displays to reconfigure after configuration changes. 888 // Some of the information reported for a display is dependent on resources to do the right 889 // calculations. For example, {@link DisplayInfo#smallestNominalAppWidth} and company are 890 // dependent on the height and width of the status and nav bar which change depending on the 891 // current configuration. 892 private final DisplayContentList mReconfigureOnConfigurationChanged = new DisplayContentList(); 893 894 /** Listener to notify activity manager about app transitions. */ 895 private final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier 896 = new WindowManagerInternal.AppTransitionListener() { 897 898 @Override 899 public void onAppTransitionCancelledLocked() { 900 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_CANCELLED); 901 } 902 903 @Override 904 public void onAppTransitionFinishedLocked(IBinder token) { 905 mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_FINISHED); 906 AppWindowToken atoken = findAppWindowToken(token); 907 if (atoken == null) { 908 return; 909 } 910 if (atoken.mLaunchTaskBehind) { 911 try { 912 mActivityManager.notifyLaunchTaskBehindComplete(atoken.token); 913 } catch (RemoteException e) { 914 } 915 atoken.mLaunchTaskBehind = false; 916 } else { 917 atoken.updateReportedVisibilityLocked(); 918 if (atoken.mEnteringAnimation) { 919 atoken.mEnteringAnimation = false; 920 try { 921 mActivityManager.notifyEnterAnimationComplete(atoken.token); 922 } catch (RemoteException e) { 923 } 924 } 925 } 926 } 927 }; 928 main(final Context context, final InputManagerService im, final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore)929 public static WindowManagerService main(final Context context, 930 final InputManagerService im, 931 final boolean haveInputMethods, final boolean showBootMsgs, 932 final boolean onlyCore) { 933 final WindowManagerService[] holder = new WindowManagerService[1]; 934 DisplayThread.getHandler().runWithScissors(new Runnable() { 935 @Override 936 public void run() { 937 holder[0] = new WindowManagerService(context, im, 938 haveInputMethods, showBootMsgs, onlyCore); 939 } 940 }, 0); 941 return holder[0]; 942 } 943 initPolicy()944 private void initPolicy() { 945 UiThread.getHandler().runWithScissors(new Runnable() { 946 @Override 947 public void run() { 948 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 949 950 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); 951 } 952 }, 0); 953 } 954 WindowManagerService(Context context, InputManagerService inputManager, boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore)955 private WindowManagerService(Context context, InputManagerService inputManager, 956 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { 957 mContext = context; 958 mHaveInputMethods = haveInputMethods; 959 mAllowBootMessages = showBootMsgs; 960 mOnlyCore = onlyCore; 961 mLimitedAlphaCompositing = context.getResources().getBoolean( 962 com.android.internal.R.bool.config_sf_limitedAlpha); 963 mHasPermanentDpad = context.getResources().getBoolean( 964 com.android.internal.R.bool.config_hasPermanentDpad); 965 mInTouchMode = context.getResources().getBoolean( 966 com.android.internal.R.bool.config_defaultInTouchMode); 967 mDrawLockTimeoutMillis = context.getResources().getInteger( 968 com.android.internal.R.integer.config_drawLockTimeoutMillis); 969 mAllowAnimationsInLowPowerMode = context.getResources().getBoolean( 970 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode); 971 mInputManager = inputManager; // Must be before createDisplayContentLocked. 972 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 973 mDisplaySettings = new DisplaySettings(); 974 mDisplaySettings.readSettingsLocked(); 975 976 mWallpaperControllerLocked = new WallpaperController(this); 977 mWindowPlacerLocked = new WindowSurfacePlacer(this); 978 mLayersController = new WindowLayersController(this); 979 980 LocalServices.addService(WindowManagerPolicy.class, mPolicy); 981 982 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG_WM)); 983 984 mFxSession = new SurfaceSession(); 985 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 986 mDisplays = mDisplayManager.getDisplays(); 987 for (Display display : mDisplays) { 988 createDisplayContentLocked(display); 989 } 990 991 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 992 993 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 994 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 995 mPowerManagerInternal.registerLowPowerModeObserver( 996 new PowerManagerInternal.LowPowerModeListener() { 997 @Override 998 public void onLowPowerModeChanged(boolean enabled) { 999 synchronized (mWindowMap) { 1000 if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) { 1001 mAnimationsDisabled = enabled; 1002 dispatchNewAnimatorScaleLocked(null); 1003 } 1004 } 1005 } 1006 }); 1007 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled(); 1008 mScreenFrozenLock = mPowerManager.newWakeLock( 1009 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 1010 mScreenFrozenLock.setReferenceCounted(false); 1011 1012 mAppTransition = new AppTransition(context, this); 1013 mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier); 1014 1015 mBoundsAnimationController = 1016 new BoundsAnimationController(mAppTransition, UiThread.getHandler()); 1017 1018 mActivityManager = ActivityManagerNative.getDefault(); 1019 mAmInternal = LocalServices.getService(ActivityManagerInternal.class); 1020 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 1021 AppOpsManager.OnOpChangedInternalListener opListener = 1022 new AppOpsManager.OnOpChangedInternalListener() { 1023 @Override public void onOpChanged(int op, String packageName) { 1024 updateAppOpsState(); 1025 } 1026 }; 1027 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener); 1028 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener); 1029 1030 // Get persisted window scale setting 1031 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 1032 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 1033 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 1034 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting); 1035 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 1036 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 1037 1038 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 1039 IntentFilter filter = new IntentFilter(); 1040 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 1041 mContext.registerReceiver(mBroadcastReceiver, filter); 1042 1043 mSettingsObserver = new SettingsObserver(); 1044 1045 mHoldingScreenWakeLock = mPowerManager.newWakeLock( 1046 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM); 1047 mHoldingScreenWakeLock.setReferenceCounted(false); 1048 1049 mAnimator = new WindowAnimator(this); 1050 1051 mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean( 1052 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout); 1053 1054 1055 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 1056 initPolicy(); 1057 1058 // Add ourself to the Watchdog monitors. 1059 Watchdog.getInstance().addMonitor(this); 1060 1061 SurfaceControl.openTransaction(); 1062 try { 1063 createWatermarkInTransaction(); 1064 } finally { 1065 SurfaceControl.closeTransaction(); 1066 } 1067 1068 showEmulatorDisplayOverlayIfNeeded(); 1069 } 1070 getInputMonitor()1071 public InputMonitor getInputMonitor() { 1072 return mInputMonitor; 1073 } 1074 1075 @Override onTransact(int code, Parcel data, Parcel reply, int flags)1076 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 1077 throws RemoteException { 1078 try { 1079 return super.onTransact(code, data, reply, flags); 1080 } catch (RuntimeException e) { 1081 // The window manager only throws security exceptions, so let's 1082 // log all others. 1083 if (!(e instanceof SecurityException)) { 1084 Slog.wtf(TAG_WM, "Window Manager Crash", e); 1085 } 1086 throw e; 1087 } 1088 } 1089 placeWindowAfter(WindowState pos, WindowState window)1090 private void placeWindowAfter(WindowState pos, WindowState window) { 1091 final WindowList windows = pos.getWindowList(); 1092 final int i = windows.indexOf(pos); 1093 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1094 TAG_WM, "Adding window " + window + " at " 1095 + (i+1) + " of " + windows.size() + " (after " + pos + ")"); 1096 windows.add(i+1, window); 1097 mWindowsChanged = true; 1098 } 1099 placeWindowBefore(WindowState pos, WindowState window)1100 private void placeWindowBefore(WindowState pos, WindowState window) { 1101 final WindowList windows = pos.getWindowList(); 1102 int i = windows.indexOf(pos); 1103 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1104 TAG_WM, "Adding window " + window + " at " 1105 + i + " of " + windows.size() + " (before " + pos + ")"); 1106 if (i < 0) { 1107 Slog.w(TAG_WM, "placeWindowBefore: Unable to find " + pos + " in " + windows); 1108 i = 0; 1109 } 1110 windows.add(i, window); 1111 mWindowsChanged = true; 1112 } 1113 1114 //This method finds out the index of a window that has the same app token as 1115 //win. used for z ordering the windows in mWindows findIdxBasedOnAppTokens(WindowState win)1116 private int findIdxBasedOnAppTokens(WindowState win) { 1117 WindowList windows = win.getWindowList(); 1118 for(int j = windows.size() - 1; j >= 0; j--) { 1119 WindowState wentry = windows.get(j); 1120 if(wentry.mAppToken == win.mAppToken) { 1121 return j; 1122 } 1123 } 1124 return -1; 1125 } 1126 1127 /** 1128 * Return the list of Windows from the passed token on the given Display. 1129 * @param token The token with all the windows. 1130 * @param displayContent The display we are interested in. 1131 * @return List of windows from token that are on displayContent. 1132 */ getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent)1133 private WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) { 1134 final WindowList windowList = new WindowList(); 1135 final int count = token.windows.size(); 1136 for (int i = 0; i < count; i++) { 1137 final WindowState win = token.windows.get(i); 1138 if (win.getDisplayContent() == displayContent) { 1139 windowList.add(win); 1140 } 1141 } 1142 return windowList; 1143 } 1144 1145 /** 1146 * Recursive search through a WindowList and all of its windows' children. 1147 * @param targetWin The window to search for. 1148 * @param windows The list to search. 1149 * @return The index of win in windows or of the window that is an ancestor of win. 1150 */ indexOfWinInWindowList(WindowState targetWin, WindowList windows)1151 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) { 1152 for (int i = windows.size() - 1; i >= 0; i--) { 1153 final WindowState w = windows.get(i); 1154 if (w == targetWin) { 1155 return i; 1156 } 1157 if (!w.mChildWindows.isEmpty()) { 1158 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) { 1159 return i; 1160 } 1161 } 1162 } 1163 return -1; 1164 } 1165 addAppWindowToListLocked(final WindowState win)1166 private int addAppWindowToListLocked(final WindowState win) { 1167 final DisplayContent displayContent = win.getDisplayContent(); 1168 if (displayContent == null) { 1169 // It doesn't matter this display is going away. 1170 return 0; 1171 } 1172 final IWindow client = win.mClient; 1173 final WindowToken token = win.mToken; 1174 1175 final WindowList windows = displayContent.getWindowList(); 1176 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1177 int tokenWindowsPos = 0; 1178 if (!tokenWindowList.isEmpty()) { 1179 return addAppWindowToTokenListLocked(win, token, windows, tokenWindowList); 1180 } 1181 1182 // No windows from this token on this display 1183 if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window " + client.asBinder() 1184 + " (token=" + token + ")"); 1185 // Figure out where the window should go, based on the 1186 // order of applications. 1187 WindowState pos = null; 1188 1189 final ArrayList<Task> tasks = displayContent.getTasks(); 1190 int taskNdx; 1191 int tokenNdx = -1; 1192 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1193 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1194 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 1195 final AppWindowToken t = tokens.get(tokenNdx); 1196 if (t == token) { 1197 --tokenNdx; 1198 if (tokenNdx < 0) { 1199 --taskNdx; 1200 if (taskNdx >= 0) { 1201 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1; 1202 } 1203 } 1204 break; 1205 } 1206 1207 // We haven't reached the token yet; if this token 1208 // is not going to the bottom and has windows on this display, we can 1209 // use it as an anchor for when we do reach the token. 1210 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1211 if (!t.sendingToBottom && tokenWindowList.size() > 0) { 1212 pos = tokenWindowList.get(0); 1213 } 1214 } 1215 if (tokenNdx >= 0) { 1216 // early exit 1217 break; 1218 } 1219 } 1220 1221 // We now know the index into the apps. If we found 1222 // an app window above, that gives us the position; else 1223 // we need to look some more. 1224 if (pos != null) { 1225 // Move behind any windows attached to this one. 1226 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1227 if (atoken != null) { 1228 tokenWindowList = 1229 getTokenWindowsOnDisplay(atoken, displayContent); 1230 final int NC = tokenWindowList.size(); 1231 if (NC > 0) { 1232 WindowState bottom = tokenWindowList.get(0); 1233 if (bottom.mSubLayer < 0) { 1234 pos = bottom; 1235 } 1236 } 1237 } 1238 placeWindowBefore(pos, win); 1239 return tokenWindowsPos; 1240 } 1241 1242 // Continue looking down until we find the first 1243 // token that has windows on this display. 1244 for ( ; taskNdx >= 0; --taskNdx) { 1245 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1246 for ( ; tokenNdx >= 0; --tokenNdx) { 1247 final AppWindowToken t = tokens.get(tokenNdx); 1248 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1249 final int NW = tokenWindowList.size(); 1250 if (NW > 0) { 1251 pos = tokenWindowList.get(NW-1); 1252 break; 1253 } 1254 } 1255 if (tokenNdx >= 0) { 1256 // found 1257 break; 1258 } 1259 } 1260 1261 if (pos != null) { 1262 // Move in front of any windows attached to this 1263 // one. 1264 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1265 if (atoken != null) { 1266 final int NC = atoken.windows.size(); 1267 if (NC > 0) { 1268 WindowState top = atoken.windows.get(NC-1); 1269 if (top.mSubLayer >= 0) { 1270 pos = top; 1271 } 1272 } 1273 } 1274 placeWindowAfter(pos, win); 1275 return tokenWindowsPos; 1276 } 1277 1278 // Just search for the start of this layer. 1279 final int myLayer = win.mBaseLayer; 1280 int i; 1281 for (i = windows.size() - 1; i >= 0; --i) { 1282 WindowState w = windows.get(i); 1283 // Dock divider shares the base layer with application windows, but we want to always 1284 // keep it above the application windows. The sharing of the base layer is intended 1285 // for window animations, which need to be above the dock divider for the duration 1286 // of the animation. 1287 if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) { 1288 break; 1289 } 1290 } 1291 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1292 "Based on layer: Adding window " + win + " at " + (i + 1) + " of " 1293 + windows.size()); 1294 windows.add(i + 1, win); 1295 mWindowsChanged = true; 1296 return tokenWindowsPos; 1297 } 1298 addAppWindowToTokenListLocked(WindowState win, WindowToken token, WindowList windows, WindowList tokenWindowList)1299 private int addAppWindowToTokenListLocked(WindowState win, WindowToken token, 1300 WindowList windows, WindowList tokenWindowList) { 1301 int tokenWindowsPos; 1302 // If this application has existing windows, we 1303 // simply place the new window on top of them... but 1304 // keep the starting window on top. 1305 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 1306 // Base windows go behind everything else. 1307 WindowState lowestWindow = tokenWindowList.get(0); 1308 placeWindowBefore(lowestWindow, win); 1309 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows); 1310 } else { 1311 AppWindowToken atoken = win.mAppToken; 1312 final int windowListPos = tokenWindowList.size(); 1313 WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 1314 if (atoken != null && lastWindow == atoken.startingWindow) { 1315 placeWindowBefore(lastWindow, win); 1316 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows); 1317 } else { 1318 int newIdx = findIdxBasedOnAppTokens(win); 1319 //there is a window above this one associated with the same 1320 //apptoken note that the window could be a floating window 1321 //that was created later or a window at the top of the list of 1322 //windows associated with this token. 1323 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1324 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " 1325 + windows.size()); 1326 windows.add(newIdx + 1, win); 1327 if (newIdx < 0) { 1328 // No window from token found on win's display. 1329 tokenWindowsPos = 0; 1330 } else { 1331 tokenWindowsPos = indexOfWinInWindowList( 1332 windows.get(newIdx), token.windows) + 1; 1333 } 1334 mWindowsChanged = true; 1335 } 1336 } 1337 return tokenWindowsPos; 1338 } 1339 addFreeWindowToListLocked(final WindowState win)1340 private void addFreeWindowToListLocked(final WindowState win) { 1341 final WindowList windows = win.getWindowList(); 1342 1343 // Figure out where window should go, based on layer. 1344 final int myLayer = win.mBaseLayer; 1345 int i; 1346 for (i = windows.size() - 1; i >= 0; i--) { 1347 final WindowState otherWin = windows.get(i); 1348 if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= myLayer) { 1349 // Wallpaper wanders through the window list, for example to position itself 1350 // directly behind keyguard. Because of this it will break the ordering based on 1351 // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and 1352 // we don't want the new window to appear above them. An example of this is adding 1353 // of the docked stack divider. Consider a scenario with the following ordering (top 1354 // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider 1355 // to land below the assist preview, so the dock divider must ignore the wallpaper, 1356 // with which it shares the base layer. 1357 break; 1358 } 1359 } 1360 i++; 1361 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1362 "Free window: Adding window " + win + " at " + i + " of " + windows.size()); 1363 windows.add(i, win); 1364 mWindowsChanged = true; 1365 } 1366 addAttachedWindowToListLocked(final WindowState win, boolean addToToken)1367 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) { 1368 final WindowToken token = win.mToken; 1369 final DisplayContent displayContent = win.getDisplayContent(); 1370 if (displayContent == null) { 1371 return; 1372 } 1373 final WindowState attached = win.mAttachedWindow; 1374 1375 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1376 1377 // Figure out this window's ordering relative to the window 1378 // it is attached to. 1379 final int NA = tokenWindowList.size(); 1380 final int sublayer = win.mSubLayer; 1381 int largestSublayer = Integer.MIN_VALUE; 1382 WindowState windowWithLargestSublayer = null; 1383 int i; 1384 for (i = 0; i < NA; i++) { 1385 WindowState w = tokenWindowList.get(i); 1386 final int wSublayer = w.mSubLayer; 1387 if (wSublayer >= largestSublayer) { 1388 largestSublayer = wSublayer; 1389 windowWithLargestSublayer = w; 1390 } 1391 if (sublayer < 0) { 1392 // For negative sublayers, we go below all windows 1393 // in the same sublayer. 1394 if (wSublayer >= sublayer) { 1395 if (addToToken) { 1396 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token); 1397 token.windows.add(i, win); 1398 } 1399 placeWindowBefore(wSublayer >= 0 ? attached : w, win); 1400 break; 1401 } 1402 } else { 1403 // For positive sublayers, we go above all windows 1404 // in the same sublayer. 1405 if (wSublayer > sublayer) { 1406 if (addToToken) { 1407 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token); 1408 token.windows.add(i, win); 1409 } 1410 placeWindowBefore(w, win); 1411 break; 1412 } 1413 } 1414 } 1415 if (i >= NA) { 1416 if (addToToken) { 1417 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token); 1418 token.windows.add(win); 1419 } 1420 if (sublayer < 0) { 1421 placeWindowBefore(attached, win); 1422 } else { 1423 placeWindowAfter(largestSublayer >= 0 1424 ? windowWithLargestSublayer 1425 : attached, 1426 win); 1427 } 1428 } 1429 } 1430 addWindowToListInOrderLocked(final WindowState win, boolean addToToken)1431 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) { 1432 if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindowToListInOrderLocked: win=" + win + 1433 " Callers=" + Debug.getCallers(4)); 1434 if (win.mAttachedWindow == null) { 1435 final WindowToken token = win.mToken; 1436 int tokenWindowsPos = 0; 1437 if (token.appWindowToken != null) { 1438 tokenWindowsPos = addAppWindowToListLocked(win); 1439 } else { 1440 addFreeWindowToListLocked(win); 1441 } 1442 if (addToToken) { 1443 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + token); 1444 token.windows.add(tokenWindowsPos, win); 1445 } 1446 } else { 1447 addAttachedWindowToListLocked(win, addToToken); 1448 } 1449 1450 final AppWindowToken appToken = win.mAppToken; 1451 if (appToken != null) { 1452 if (addToToken) { 1453 appToken.addWindow(win); 1454 } 1455 } 1456 } 1457 canBeImeTarget(WindowState w)1458 static boolean canBeImeTarget(WindowState w) { 1459 final int fl = w.mAttrs.flags 1460 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1461 final int type = w.mAttrs.type; 1462 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) 1463 || type == TYPE_APPLICATION_STARTING) { 1464 if (DEBUG_INPUT_METHOD) { 1465 Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1466 if (!w.isVisibleOrAdding()) { 1467 Slog.i(TAG_WM, " mSurfaceController=" + w.mWinAnimator.mSurfaceController 1468 + " relayoutCalled=" + w.mRelayoutCalled 1469 + " viewVis=" + w.mViewVisibility 1470 + " policyVis=" + w.mPolicyVisibility 1471 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1472 + " attachHid=" + w.mAttachedHidden 1473 + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying); 1474 if (w.mAppToken != null) { 1475 Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1476 } 1477 } 1478 } 1479 return w.isVisibleOrAdding(); 1480 } 1481 return false; 1482 } 1483 1484 /** 1485 * Dig through the WindowStates and find the one that the Input Method will target. 1486 * @param willMove 1487 * @return The index+1 in mWindows of the discovered target. 1488 */ findDesiredInputMethodWindowIndexLocked(boolean willMove)1489 int findDesiredInputMethodWindowIndexLocked(boolean willMove) { 1490 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1491 // same display. Or even when the current IME/target are not on the same screen as the next 1492 // IME/target. For now only look for input windows on the main screen. 1493 WindowList windows = getDefaultWindowListLocked(); 1494 WindowState w = null; 1495 int i; 1496 for (i = windows.size() - 1; i >= 0; --i) { 1497 WindowState win = windows.get(i); 1498 1499 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i 1500 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1501 if (canBeImeTarget(win)) { 1502 w = win; 1503 //Slog.i(TAG_WM, "Putting input method here!"); 1504 1505 // Yet more tricksyness! If this window is a "starting" 1506 // window, we do actually want to be on top of it, but 1507 // it is not -really- where input will go. So if the caller 1508 // is not actually looking to move the IME, look down below 1509 // for a real window to target... 1510 if (!willMove 1511 && w.mAttrs.type == TYPE_APPLICATION_STARTING 1512 && i > 0) { 1513 WindowState wb = windows.get(i-1); 1514 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1515 i--; 1516 w = wb; 1517 } 1518 } 1519 break; 1520 } 1521 } 1522 1523 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1524 1525 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w); 1526 1527 // Now, a special case -- if the last target's window is in the 1528 // process of exiting, and is above the new target, keep on the 1529 // last target to avoid flicker. Consider for example a Dialog with 1530 // the IME shown: when the Dialog is dismissed, we want to keep 1531 // the IME above it until it is completely gone so it doesn't drop 1532 // behind the dialog or its full-screen scrim. 1533 final WindowState curTarget = mInputMethodTarget; 1534 if (curTarget != null 1535 && curTarget.isDisplayedLw() 1536 && curTarget.isClosing() 1537 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1538 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing"); 1539 return windows.indexOf(curTarget) + 1; 1540 } 1541 1542 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" 1543 + w + " willMove=" + willMove); 1544 1545 if (willMove && w != null) { 1546 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1547 if (token != null) { 1548 1549 // Now some fun for dealing with window animations that 1550 // modify the Z order. We need to look at all windows below 1551 // the current target that are in this app, finding the highest 1552 // visible one in layering. 1553 WindowState highestTarget = null; 1554 int highestPos = 0; 1555 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1556 WindowList curWindows = curTarget.getWindowList(); 1557 int pos = curWindows.indexOf(curTarget); 1558 while (pos >= 0) { 1559 WindowState win = curWindows.get(pos); 1560 if (win.mAppToken != token) { 1561 break; 1562 } 1563 if (!win.mRemoved) { 1564 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1565 highestTarget.mWinAnimator.mAnimLayer) { 1566 highestTarget = win; 1567 highestPos = pos; 1568 } 1569 } 1570 pos--; 1571 } 1572 } 1573 1574 if (highestTarget != null) { 1575 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, mAppTransition + " " + highestTarget 1576 + " animating=" + highestTarget.mWinAnimator.isAnimationSet() 1577 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1578 + " new layer=" + w.mWinAnimator.mAnimLayer); 1579 1580 if (mAppTransition.isTransitionSet()) { 1581 // If we are currently setting up for an animation, 1582 // hold everything until we can find out what will happen. 1583 mInputMethodTargetWaitingAnim = true; 1584 mInputMethodTarget = highestTarget; 1585 return highestPos + 1; 1586 } else if (highestTarget.mWinAnimator.isAnimationSet() && 1587 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1588 // If the window we are currently targeting is involved 1589 // with an animation, and it is on top of the next target 1590 // we will be over, then hold off on moving until 1591 // that is done. 1592 mInputMethodTargetWaitingAnim = true; 1593 mInputMethodTarget = highestTarget; 1594 return highestPos + 1; 1595 } 1596 } 1597 } 1598 } 1599 1600 //Slog.i(TAG_WM, "Placing input method @" + (i+1)); 1601 if (w != null) { 1602 if (willMove) { 1603 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to " 1604 + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 1605 mInputMethodTarget = w; 1606 mInputMethodTargetWaitingAnim = false; 1607 if (w.mAppToken != null) { 1608 mLayersController.setInputMethodAnimLayerAdjustment( 1609 w.mAppToken.mAppAnimator.animLayerAdjustment); 1610 } else { 1611 mLayersController.setInputMethodAnimLayerAdjustment(0); 1612 } 1613 } 1614 1615 // If the docked divider is visible, we still need to go through this whole 1616 // excercise to find the appropriate input method target (used for animations 1617 // and dialog adjustments), but for purposes of Z ordering we simply wish to 1618 // place it above the docked divider. Unless it is already above the divider. 1619 WindowState dockedDivider = w.mDisplayContent.mDividerControllerLocked.getWindow(); 1620 if (dockedDivider != null && dockedDivider.isVisibleLw()) { 1621 int dividerIndex = windows.indexOf(dockedDivider); 1622 if (dividerIndex > 0 && dividerIndex > i) { 1623 return dividerIndex + 1; 1624 } 1625 } 1626 return i+1; 1627 } 1628 if (willMove) { 1629 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to null." 1630 + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 1631 mInputMethodTarget = null; 1632 mLayersController.setInputMethodAnimLayerAdjustment(0); 1633 } 1634 return -1; 1635 } 1636 addInputMethodWindowToListLocked(WindowState win)1637 void addInputMethodWindowToListLocked(WindowState win) { 1638 int pos = findDesiredInputMethodWindowIndexLocked(true); 1639 if (pos >= 0) { 1640 win.mTargetAppToken = mInputMethodTarget.mAppToken; 1641 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1642 TAG_WM, "Adding input method window " + win + " at " + pos); 1643 // TODO(multidisplay): IMEs are only supported on the default display. 1644 getDefaultWindowListLocked().add(pos, win); 1645 mWindowsChanged = true; 1646 moveInputMethodDialogsLocked(pos + 1); 1647 return; 1648 } 1649 win.mTargetAppToken = null; 1650 addWindowToListInOrderLocked(win, true); 1651 moveInputMethodDialogsLocked(pos); 1652 } 1653 tmpRemoveWindowLocked(int interestingPos, WindowState win)1654 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { 1655 WindowList windows = win.getWindowList(); 1656 int wpos = windows.indexOf(win); 1657 if (wpos >= 0) { 1658 if (wpos < interestingPos) interestingPos--; 1659 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + win); 1660 windows.remove(wpos); 1661 mWindowsChanged = true; 1662 int NC = win.mChildWindows.size(); 1663 while (NC > 0) { 1664 NC--; 1665 WindowState cw = win.mChildWindows.get(NC); 1666 int cpos = windows.indexOf(cw); 1667 if (cpos >= 0) { 1668 if (cpos < interestingPos) interestingPos--; 1669 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing child at " 1670 + cpos + ": " + cw); 1671 windows.remove(cpos); 1672 } 1673 } 1674 } 1675 return interestingPos; 1676 } 1677 reAddWindowToListInOrderLocked(WindowState win)1678 private void reAddWindowToListInOrderLocked(WindowState win) { 1679 addWindowToListInOrderLocked(win, false); 1680 // This is a hack to get all of the child windows added as well 1681 // at the right position. Child windows should be rare and 1682 // this case should be rare, so it shouldn't be that big a deal. 1683 WindowList windows = win.getWindowList(); 1684 int wpos = windows.indexOf(win); 1685 if (wpos >= 0) { 1686 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win); 1687 windows.remove(wpos); 1688 mWindowsChanged = true; 1689 reAddWindowLocked(wpos, win); 1690 } 1691 } 1692 logWindowList(final WindowList windows, String prefix)1693 void logWindowList(final WindowList windows, String prefix) { 1694 int N = windows.size(); 1695 while (N > 0) { 1696 N--; 1697 Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N)); 1698 } 1699 } 1700 moveInputMethodDialogsLocked(int pos)1701 void moveInputMethodDialogsLocked(int pos) { 1702 ArrayList<WindowState> dialogs = mInputMethodDialogs; 1703 1704 // TODO(multidisplay): IMEs are only supported on the default display. 1705 WindowList windows = getDefaultWindowListLocked(); 1706 final int N = dialogs.size(); 1707 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos); 1708 for (int i=0; i<N; i++) { 1709 pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); 1710 } 1711 if (DEBUG_INPUT_METHOD) { 1712 Slog.v(TAG_WM, "Window list w/pos=" + pos); 1713 logWindowList(windows, " "); 1714 } 1715 1716 if (pos >= 0) { 1717 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; 1718 // Skip windows owned by the input method. 1719 if (mInputMethodWindow != null) { 1720 while (pos < windows.size()) { 1721 WindowState wp = windows.get(pos); 1722 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) { 1723 pos++; 1724 continue; 1725 } 1726 break; 1727 } 1728 } 1729 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos); 1730 for (int i=0; i<N; i++) { 1731 WindowState win = dialogs.get(i); 1732 win.mTargetAppToken = targetAppToken; 1733 pos = reAddWindowLocked(pos, win); 1734 } 1735 if (DEBUG_INPUT_METHOD) { 1736 Slog.v(TAG_WM, "Final window list:"); 1737 logWindowList(windows, " "); 1738 } 1739 return; 1740 } 1741 for (int i=0; i<N; i++) { 1742 WindowState win = dialogs.get(i); 1743 win.mTargetAppToken = null; 1744 reAddWindowToListInOrderLocked(win); 1745 if (DEBUG_INPUT_METHOD) { 1746 Slog.v(TAG_WM, "No IM target, final list:"); 1747 logWindowList(windows, " "); 1748 } 1749 } 1750 } 1751 moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers)1752 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { 1753 final WindowState imWin = mInputMethodWindow; 1754 final int DN = mInputMethodDialogs.size(); 1755 if (imWin == null && DN == 0) { 1756 return false; 1757 } 1758 1759 // TODO(multidisplay): IMEs are only supported on the default display. 1760 WindowList windows = getDefaultWindowListLocked(); 1761 1762 int imPos = findDesiredInputMethodWindowIndexLocked(true); 1763 if (imPos >= 0) { 1764 // In this case, the input method windows are to be placed 1765 // immediately above the window they are targeting. 1766 1767 // First check to see if the input method windows are already 1768 // located here, and contiguous. 1769 final int N = windows.size(); 1770 WindowState firstImWin = imPos < N 1771 ? windows.get(imPos) : null; 1772 1773 // Figure out the actual input method window that should be 1774 // at the bottom of their stack. 1775 WindowState baseImWin = imWin != null 1776 ? imWin : mInputMethodDialogs.get(0); 1777 if (baseImWin.mChildWindows.size() > 0) { 1778 WindowState cw = baseImWin.mChildWindows.get(0); 1779 if (cw.mSubLayer < 0) baseImWin = cw; 1780 } 1781 1782 if (firstImWin == baseImWin) { 1783 // The windows haven't moved... but are they still contiguous? 1784 // First find the top IM window. 1785 int pos = imPos+1; 1786 while (pos < N) { 1787 if (!(windows.get(pos)).mIsImWindow) { 1788 break; 1789 } 1790 pos++; 1791 } 1792 pos++; 1793 // Now there should be no more input method windows above. 1794 while (pos < N) { 1795 if ((windows.get(pos)).mIsImWindow) { 1796 break; 1797 } 1798 pos++; 1799 } 1800 if (pos >= N) { 1801 // Z order is good. 1802 // The IM target window may be changed, so update the mTargetAppToken. 1803 if (imWin != null) { 1804 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1805 } 1806 return false; 1807 } 1808 } 1809 1810 if (imWin != null) { 1811 if (DEBUG_INPUT_METHOD) { 1812 Slog.v(TAG_WM, "Moving IM from " + imPos); 1813 logWindowList(windows, " "); 1814 } 1815 imPos = tmpRemoveWindowLocked(imPos, imWin); 1816 if (DEBUG_INPUT_METHOD) { 1817 Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":"); 1818 logWindowList(windows, " "); 1819 } 1820 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1821 reAddWindowLocked(imPos, imWin); 1822 if (DEBUG_INPUT_METHOD) { 1823 Slog.v(TAG_WM, "List after moving IM to " + imPos + ":"); 1824 logWindowList(windows, " "); 1825 } 1826 if (DN > 0) moveInputMethodDialogsLocked(imPos+1); 1827 } else { 1828 moveInputMethodDialogsLocked(imPos); 1829 } 1830 1831 } else { 1832 // In this case, the input method windows go in a fixed layer, 1833 // because they aren't currently associated with a focus window. 1834 1835 if (imWin != null) { 1836 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos); 1837 tmpRemoveWindowLocked(0, imWin); 1838 imWin.mTargetAppToken = null; 1839 reAddWindowToListInOrderLocked(imWin); 1840 if (DEBUG_INPUT_METHOD) { 1841 Slog.v(TAG_WM, "List with no IM target:"); 1842 logWindowList(windows, " "); 1843 } 1844 if (DN > 0) moveInputMethodDialogsLocked(-1); 1845 } else { 1846 moveInputMethodDialogsLocked(-1); 1847 } 1848 1849 } 1850 1851 if (needAssignLayers) { 1852 mLayersController.assignLayersLocked(windows); 1853 } 1854 1855 return true; 1856 } 1857 excludeWindowTypeFromTapOutTask(int windowType)1858 private static boolean excludeWindowTypeFromTapOutTask(int windowType) { 1859 switch (windowType) { 1860 case TYPE_STATUS_BAR: 1861 case TYPE_NAVIGATION_BAR: 1862 case TYPE_INPUT_METHOD_DIALOG: 1863 return true; 1864 } 1865 return false; 1866 } 1867 addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel)1868 public int addWindow(Session session, IWindow client, int seq, 1869 WindowManager.LayoutParams attrs, int viewVisibility, int displayId, 1870 Rect outContentInsets, Rect outStableInsets, Rect outOutsets, 1871 InputChannel outInputChannel) { 1872 int[] appOp = new int[1]; 1873 int res = mPolicy.checkAddPermission(attrs, appOp); 1874 if (res != WindowManagerGlobal.ADD_OKAY) { 1875 return res; 1876 } 1877 1878 boolean reportNewConfig = false; 1879 WindowState attachedWindow = null; 1880 long origId; 1881 final int callingUid = Binder.getCallingUid(); 1882 final int type = attrs.type; 1883 1884 synchronized(mWindowMap) { 1885 if (!mDisplayReady) { 1886 throw new IllegalStateException("Display has not been initialialized"); 1887 } 1888 1889 final DisplayContent displayContent = getDisplayContentLocked(displayId); 1890 if (displayContent == null) { 1891 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: " 1892 + displayId + ". Aborting."); 1893 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1894 } 1895 if (!displayContent.hasAccess(session.mUid)) { 1896 Slog.w(TAG_WM, "Attempted to add window to a display for which the application " 1897 + "does not have access: " + displayId + ". Aborting."); 1898 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 1899 } 1900 1901 if (mWindowMap.containsKey(client.asBinder())) { 1902 Slog.w(TAG_WM, "Window " + client + " is already added"); 1903 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 1904 } 1905 1906 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 1907 attachedWindow = windowForClientLocked(null, attrs.token, false); 1908 if (attachedWindow == null) { 1909 Slog.w(TAG_WM, "Attempted to add window with token that is not a window: " 1910 + attrs.token + ". Aborting."); 1911 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 1912 } 1913 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW 1914 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { 1915 Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: " 1916 + attrs.token + ". Aborting."); 1917 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 1918 } 1919 } 1920 1921 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) { 1922 Slog.w(TAG_WM, "Attempted to add private presentation window to a non-private display. Aborting."); 1923 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 1924 } 1925 1926 boolean addToken = false; 1927 WindowToken token = mTokenMap.get(attrs.token); 1928 AppWindowToken atoken = null; 1929 boolean addToastWindowRequiresToken = false; 1930 1931 if (token == null) { 1932 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 1933 Slog.w(TAG_WM, "Attempted to add application window with unknown token " 1934 + attrs.token + ". Aborting."); 1935 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1936 } 1937 if (type == TYPE_INPUT_METHOD) { 1938 Slog.w(TAG_WM, "Attempted to add input method window with unknown token " 1939 + attrs.token + ". Aborting."); 1940 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1941 } 1942 if (type == TYPE_VOICE_INTERACTION) { 1943 Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token " 1944 + attrs.token + ". Aborting."); 1945 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1946 } 1947 if (type == TYPE_WALLPAPER) { 1948 Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token " 1949 + attrs.token + ". Aborting."); 1950 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1951 } 1952 if (type == TYPE_DREAM) { 1953 Slog.w(TAG_WM, "Attempted to add Dream window with unknown token " 1954 + attrs.token + ". Aborting."); 1955 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1956 } 1957 if (type == TYPE_QS_DIALOG) { 1958 Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token " 1959 + attrs.token + ". Aborting."); 1960 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1961 } 1962 if (type == TYPE_ACCESSIBILITY_OVERLAY) { 1963 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token " 1964 + attrs.token + ". Aborting."); 1965 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1966 } 1967 if (type == TYPE_TOAST) { 1968 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows. 1969 if (doesAddToastWindowRequireToken(attrs.packageName, callingUid, 1970 attachedWindow)) { 1971 Slog.w(TAG_WM, "Attempted to add a toast window with unknown token " 1972 + attrs.token + ". Aborting."); 1973 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 1974 } 1975 } 1976 token = new WindowToken(this, attrs.token, -1, false); 1977 addToken = true; 1978 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 1979 atoken = token.appWindowToken; 1980 if (atoken == null) { 1981 Slog.w(TAG_WM, "Attempted to add window with non-application token " 1982 + token + ". Aborting."); 1983 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 1984 } else if (atoken.removed) { 1985 Slog.w(TAG_WM, "Attempted to add window with exiting application token " 1986 + token + ". Aborting."); 1987 return WindowManagerGlobal.ADD_APP_EXITING; 1988 } 1989 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { 1990 // No need for this guy! 1991 if (DEBUG_STARTING_WINDOW || localLOGV) Slog.v( 1992 TAG_WM, "**** NO NEED TO START: " + attrs.getTitle()); 1993 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; 1994 } 1995 } else if (type == TYPE_INPUT_METHOD) { 1996 if (token.windowType != TYPE_INPUT_METHOD) { 1997 Slog.w(TAG_WM, "Attempted to add input method window with bad token " 1998 + attrs.token + ". Aborting."); 1999 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2000 } 2001 } else if (type == TYPE_VOICE_INTERACTION) { 2002 if (token.windowType != TYPE_VOICE_INTERACTION) { 2003 Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token " 2004 + attrs.token + ". Aborting."); 2005 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2006 } 2007 } else if (type == TYPE_WALLPAPER) { 2008 if (token.windowType != TYPE_WALLPAPER) { 2009 Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token " 2010 + attrs.token + ". Aborting."); 2011 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2012 } 2013 } else if (type == TYPE_DREAM) { 2014 if (token.windowType != TYPE_DREAM) { 2015 Slog.w(TAG_WM, "Attempted to add Dream window with bad token " 2016 + attrs.token + ". Aborting."); 2017 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2018 } 2019 } else if (type == TYPE_ACCESSIBILITY_OVERLAY) { 2020 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) { 2021 Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token " 2022 + attrs.token + ". Aborting."); 2023 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2024 } 2025 } else if (type == TYPE_TOAST) { 2026 // Apps targeting SDK above N MR1 cannot arbitrary add toast windows. 2027 addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName, 2028 callingUid, attachedWindow); 2029 if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) { 2030 Slog.w(TAG_WM, "Attempted to add a toast window with bad token " 2031 + attrs.token + ". Aborting."); 2032 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2033 } 2034 } else if (type == TYPE_QS_DIALOG) { 2035 if (token.windowType != TYPE_QS_DIALOG) { 2036 Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token " 2037 + attrs.token + ". Aborting."); 2038 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2039 } 2040 } else if (token.appWindowToken != null) { 2041 Slog.w(TAG_WM, "Non-null appWindowToken for system window of type=" + type); 2042 // It is not valid to use an app token with other system types; we will 2043 // instead make a new token for it (as if null had been passed in for the token). 2044 attrs.token = null; 2045 token = new WindowToken(this, null, -1, false); 2046 addToken = true; 2047 } 2048 2049 WindowState win = new WindowState(this, session, client, token, 2050 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent); 2051 if (win.mDeathRecipient == null) { 2052 // Client has apparently died, so there is no reason to 2053 // continue. 2054 Slog.w(TAG_WM, "Adding window client " + client.asBinder() 2055 + " that is dead, aborting."); 2056 return WindowManagerGlobal.ADD_APP_EXITING; 2057 } 2058 2059 if (win.getDisplayContent() == null) { 2060 Slog.w(TAG_WM, "Adding window to Display that has been removed."); 2061 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2062 } 2063 2064 mPolicy.adjustWindowParamsLw(win.mAttrs); 2065 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 2066 2067 res = mPolicy.prepareAddWindowLw(win, attrs); 2068 if (res != WindowManagerGlobal.ADD_OKAY) { 2069 return res; 2070 } 2071 2072 final boolean openInputChannels = (outInputChannel != null 2073 && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0); 2074 if (openInputChannels) { 2075 win.openInputChannel(outInputChannel); 2076 } 2077 2078 // If adding a toast requires a token for this app we always schedule hiding 2079 // toast windows to make sure they don't stick around longer then necessary. 2080 // We hide instead of remove such windows as apps aren't prepared to handle 2081 // windows being removed under them. 2082 // 2083 // If the app is older it can add toasts without a token and hence overlay 2084 // other apps. To be maximally compatible with these apps we will hide the 2085 // window after the toast timeout only if the focused window is from another 2086 // UID, otherwise we allow unlimited duration. When a UID looses focus we 2087 // schedule hiding all of its toast windows. 2088 if (type == TYPE_TOAST) { 2089 if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) { 2090 Slog.w(TAG_WM, "Adding more than one toast window for UID at a time."); 2091 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 2092 } 2093 // Make sure this happens before we moved focus as one can make the 2094 // toast focusable to force it not being hidden after the timeout. 2095 // Focusable toasts are always timed out to prevent a focused app to 2096 // show a focusable toasts while it has focus which will be kept on 2097 // the screen after the activity goes away. 2098 if (addToastWindowRequiresToken 2099 || (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0 2100 || mCurrentFocus == null 2101 || mCurrentFocus.mOwnerUid != callingUid) { 2102 mH.sendMessageDelayed( 2103 mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win), 2104 win.mAttrs.hideTimeoutMilliseconds); 2105 } 2106 } 2107 2108 // From now on, no exceptions or errors allowed! 2109 2110 res = WindowManagerGlobal.ADD_OKAY; 2111 2112 if (excludeWindowTypeFromTapOutTask(type)) { 2113 displayContent.mTapExcludedWindows.add(win); 2114 } 2115 2116 origId = Binder.clearCallingIdentity(); 2117 2118 if (addToken) { 2119 mTokenMap.put(attrs.token, token); 2120 } 2121 win.attach(); 2122 mWindowMap.put(client.asBinder(), win); 2123 if (win.mAppOp != AppOpsManager.OP_NONE) { 2124 int startOpResult = mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), 2125 win.getOwningPackage()); 2126 if ((startOpResult != AppOpsManager.MODE_ALLOWED) && 2127 (startOpResult != AppOpsManager.MODE_DEFAULT)) { 2128 win.setAppOpVisibilityLw(false); 2129 } 2130 } 2131 2132 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { 2133 token.appWindowToken.startingWindow = win; 2134 if (DEBUG_STARTING_WINDOW) Slog.v (TAG_WM, "addWindow: " + token.appWindowToken 2135 + " startingWindow=" + win); 2136 } 2137 2138 boolean imMayMove = true; 2139 2140 if (type == TYPE_INPUT_METHOD) { 2141 win.mGivenInsetsPending = true; 2142 mInputMethodWindow = win; 2143 addInputMethodWindowToListLocked(win); 2144 imMayMove = false; 2145 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 2146 mInputMethodDialogs.add(win); 2147 addWindowToListInOrderLocked(win, true); 2148 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); 2149 imMayMove = false; 2150 } else { 2151 addWindowToListInOrderLocked(win, true); 2152 if (type == TYPE_WALLPAPER) { 2153 mWallpaperControllerLocked.clearLastWallpaperTimeoutTime(); 2154 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2155 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2156 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2157 } else if (mWallpaperControllerLocked.isBelowWallpaperTarget(win)) { 2158 // If there is currently a wallpaper being shown, and 2159 // the base layer of the new window is below the current 2160 // layer of the target window, then adjust the wallpaper. 2161 // This is to avoid a new window being placed between the 2162 // wallpaper and its target. 2163 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2164 } 2165 } 2166 2167 // If the window is being added to a task that's docked but non-resizeable, 2168 // we need to update this new window's scroll position when it's added. 2169 win.applyScrollIfNeeded(); 2170 2171 // If the window is being added to a stack that's currently adjusted for IME, 2172 // make sure to apply the same adjust to this new window. 2173 win.applyAdjustForImeIfNeeded(); 2174 2175 if (type == TYPE_DOCK_DIVIDER) { 2176 getDefaultDisplayContentLocked().getDockedDividerController().setWindow(win); 2177 } 2178 2179 final WindowStateAnimator winAnimator = win.mWinAnimator; 2180 winAnimator.mEnterAnimationPending = true; 2181 winAnimator.mEnteringAnimation = true; 2182 // Check if we need to prepare a transition for replacing window first. 2183 if (atoken != null && !prepareWindowReplacementTransition(atoken)) { 2184 // If not, check if need to set up a dummy transition during display freeze 2185 // so that the unfreeze wait for the apps to draw. This might be needed if 2186 // the app is relaunching. 2187 prepareNoneTransitionForRelaunching(atoken); 2188 } 2189 2190 if (displayContent.isDefaultDisplay) { 2191 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2192 final Rect taskBounds; 2193 if (atoken != null && atoken.mTask != null) { 2194 taskBounds = mTmpRect; 2195 atoken.mTask.getBounds(mTmpRect); 2196 } else { 2197 taskBounds = null; 2198 } 2199 if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, mRotation, 2200 displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets, 2201 outStableInsets, outOutsets)) { 2202 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR; 2203 } 2204 } else { 2205 outContentInsets.setEmpty(); 2206 outStableInsets.setEmpty(); 2207 } 2208 2209 if (mInTouchMode) { 2210 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2211 } 2212 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2213 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2214 } 2215 2216 mInputMonitor.setUpdateInputWindowsNeededLw(); 2217 2218 boolean focusChanged = false; 2219 if (win.canReceiveKeys()) { 2220 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2221 false /*updateInputWindows*/); 2222 if (focusChanged) { 2223 imMayMove = false; 2224 } 2225 } 2226 2227 if (imMayMove) { 2228 moveInputMethodWindowsIfNeededLocked(false); 2229 } 2230 2231 mLayersController.assignLayersLocked(displayContent.getWindowList()); 2232 // Don't do layout here, the window must call 2233 // relayout to be displayed, so we'll do it there. 2234 2235 if (focusChanged) { 2236 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/); 2237 } 2238 mInputMonitor.updateInputWindowsLw(false /*force*/); 2239 2240 if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client " 2241 + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5)); 2242 2243 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2244 reportNewConfig = true; 2245 } 2246 } 2247 2248 if (reportNewConfig) { 2249 sendNewConfiguration(); 2250 } 2251 2252 Binder.restoreCallingIdentity(origId); 2253 2254 return res; 2255 } 2256 doesAddToastWindowRequireToken(String packageName, int callingUid, WindowState attachedWindow)2257 private boolean doesAddToastWindowRequireToken(String packageName, int callingUid, 2258 WindowState attachedWindow) { 2259 // Try using the target SDK of the root window 2260 if (attachedWindow != null) { 2261 return attachedWindow.mAppToken != null 2262 && attachedWindow.mAppToken.targetSdk > Build.VERSION_CODES.N_MR1; 2263 } else { 2264 // Otherwise, look at the package 2265 try { 2266 ApplicationInfo appInfo = mContext.getPackageManager() 2267 .getApplicationInfoAsUser(packageName, 0, 2268 UserHandle.getUserId(callingUid)); 2269 if (appInfo.uid != callingUid) { 2270 throw new SecurityException("Package " + packageName + " not in UID " 2271 + callingUid); 2272 } 2273 if (appInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) { 2274 return true; 2275 } 2276 } catch (PackageManager.NameNotFoundException e) { 2277 /* ignore */ 2278 } 2279 } 2280 return false; 2281 } 2282 2283 /** 2284 * Returns true if we're done setting up any transitions. 2285 */ prepareWindowReplacementTransition(AppWindowToken atoken)2286 private boolean prepareWindowReplacementTransition(AppWindowToken atoken) { 2287 atoken.clearAllDrawn(); 2288 WindowState replacedWindow = null; 2289 for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) { 2290 WindowState candidate = atoken.windows.get(i); 2291 if (candidate.mAnimatingExit && candidate.mWillReplaceWindow 2292 && candidate.mAnimateReplacingWindow) { 2293 replacedWindow = candidate; 2294 } 2295 } 2296 if (replacedWindow == null) { 2297 // We expect to already receive a request to remove the old window. If it did not 2298 // happen, let's just simply add a window. 2299 return false; 2300 } 2301 // We use the visible frame, because we want the animation to morph the window from what 2302 // was visible to the user to the final destination of the new window. 2303 Rect frame = replacedWindow.mVisibleFrame; 2304 // We treat this as if this activity was opening, so we can trigger the app transition 2305 // animation and piggy-back on existing transition animation infrastructure. 2306 mOpeningApps.add(atoken); 2307 prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT); 2308 mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top, 2309 frame.width(), frame.height()); 2310 executeAppTransition(); 2311 return true; 2312 } 2313 prepareNoneTransitionForRelaunching(AppWindowToken atoken)2314 private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) { 2315 // Set up a none-transition and add the app to opening apps, so that the display 2316 // unfreeze wait for the apps to be drawn. 2317 // Note that if the display unfroze already because app unfreeze timed out, 2318 // we don't set up the transition anymore and just let it go. 2319 if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) { 2320 mOpeningApps.add(atoken); 2321 prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT); 2322 executeAppTransition(); 2323 } 2324 } 2325 2326 /** 2327 * Returns whether screen capture is disabled for all windows of a specific user. 2328 */ isScreenCaptureDisabledLocked(int userId)2329 boolean isScreenCaptureDisabledLocked(int userId) { 2330 Boolean disabled = mScreenCaptureDisabled.get(userId); 2331 if (disabled == null) { 2332 return false; 2333 } 2334 return disabled; 2335 } 2336 isSecureLocked(WindowState w)2337 boolean isSecureLocked(WindowState w) { 2338 if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) { 2339 return true; 2340 } 2341 if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) { 2342 return true; 2343 } 2344 return false; 2345 } 2346 2347 /** 2348 * Set mScreenCaptureDisabled for specific user 2349 */ 2350 @Override setScreenCaptureDisabled(int userId, boolean disabled)2351 public void setScreenCaptureDisabled(int userId, boolean disabled) { 2352 int callingUid = Binder.getCallingUid(); 2353 if (callingUid != Process.SYSTEM_UID) { 2354 throw new SecurityException("Only system can call setScreenCaptureDisabled."); 2355 } 2356 2357 synchronized(mWindowMap) { 2358 mScreenCaptureDisabled.put(userId, disabled); 2359 // Update secure surface for all windows belonging to this user. 2360 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 2361 WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 2362 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 2363 final WindowState win = windows.get(winNdx); 2364 if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) { 2365 win.mWinAnimator.setSecureLocked(disabled); 2366 } 2367 } 2368 } 2369 } 2370 } 2371 setupWindowForRemoveOnExit(WindowState win)2372 private void setupWindowForRemoveOnExit(WindowState win) { 2373 win.mRemoveOnExit = true; 2374 win.setDisplayLayoutNeeded(); 2375 // Request a focus update as this window's input channel is already gone. Otherwise 2376 // we could have no focused window in input manager. 2377 final boolean focusChanged = updateFocusedWindowLocked( 2378 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 2379 mWindowPlacerLocked.performSurfacePlacement(); 2380 if (focusChanged) { 2381 mInputMonitor.updateInputWindowsLw(false /*force*/); 2382 } 2383 } 2384 removeWindow(Session session, IWindow client)2385 public void removeWindow(Session session, IWindow client) { 2386 synchronized(mWindowMap) { 2387 WindowState win = windowForClientLocked(session, client, false); 2388 if (win == null) { 2389 return; 2390 } 2391 removeWindowLocked(win); 2392 } 2393 } 2394 removeWindowLocked(WindowState win)2395 void removeWindowLocked(WindowState win) { 2396 removeWindowLocked(win, false); 2397 } 2398 removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow)2399 void removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow) { 2400 win.mWindowRemovalAllowed = true; 2401 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 2402 "removeWindowLocked: " + win + " callers=" + Debug.getCallers(4)); 2403 2404 final boolean startingWindow = win.mAttrs.type == TYPE_APPLICATION_STARTING; 2405 if (startingWindow) { 2406 if (DEBUG_STARTING_WINDOW) Slog.d(TAG_WM, "Starting window removed " + win); 2407 } 2408 2409 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win == mCurrentFocus) Slog.v( 2410 TAG_WM, "Remove " + win + " client=" 2411 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) 2412 + ", surfaceController=" + win.mWinAnimator.mSurfaceController + " Callers=" 2413 + Debug.getCallers(4)); 2414 2415 final long origId = Binder.clearCallingIdentity(); 2416 2417 win.disposeInputChannel(); 2418 2419 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, 2420 "Remove " + win + ": mSurfaceController=" + win.mWinAnimator.mSurfaceController 2421 + " mAnimatingExit=" + win.mAnimatingExit 2422 + " mRemoveOnExit=" + win.mRemoveOnExit 2423 + " mHasSurface=" + win.mHasSurface 2424 + " surfaceShowing=" + win.mWinAnimator.getShown() 2425 + " isAnimationSet=" + win.mWinAnimator.isAnimationSet() 2426 + " app-animation=" 2427 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2428 + " mWillReplaceWindow=" + win.mWillReplaceWindow 2429 + " inPendingTransaction=" 2430 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2431 + " mDisplayFrozen=" + mDisplayFrozen 2432 + " callers=" + Debug.getCallers(6)); 2433 // Visibility of the removed window. Will be used later to update orientation later on. 2434 boolean wasVisible = false; 2435 // First, see if we need to run an animation. If we do, we have to hold off on removing the 2436 // window until the animation is done. If the display is frozen, just remove immediately, 2437 // since the animation wouldn't be seen. 2438 if (win.mHasSurface && okToDisplay()) { 2439 final AppWindowToken appToken = win.mAppToken; 2440 if (win.mWillReplaceWindow) { 2441 // This window is going to be replaced. We need to keep it around until the new one 2442 // gets added, then we will get rid of this one. 2443 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Preserving " + win + " until the new one is " 2444 + "added"); 2445 // TODO: We are overloading mAnimatingExit flag to prevent the window state from 2446 // been removed. We probably need another flag to indicate that window removal 2447 // should be deffered vs. overloading the flag that says we are playing an exit 2448 // animation. 2449 win.mAnimatingExit = true; 2450 win.mReplacingRemoveRequested = true; 2451 Binder.restoreCallingIdentity(origId); 2452 return; 2453 } 2454 2455 if (win.isAnimatingWithSavedSurface() && !appToken.allDrawnExcludingSaved) { 2456 // We started enter animation early with a saved surface, now the app asks to remove 2457 // this window. If we remove it now and the app is not yet drawn, we'll show a 2458 // flicker. Delay the removal now until it's really drawn. 2459 if (DEBUG_ADD_REMOVE) { 2460 Slog.d(TAG_WM, "removeWindowLocked: delay removal of " + win 2461 + " due to early animation"); 2462 } 2463 // Do not set mAnimatingExit to true here, it will cause the surface to be hidden 2464 // immediately after the enter animation is done. If the app is not yet drawn then 2465 // it will show up as a flicker. 2466 setupWindowForRemoveOnExit(win); 2467 Binder.restoreCallingIdentity(origId); 2468 return; 2469 } 2470 // If we are not currently running the exit animation, we need to see about starting one 2471 wasVisible = win.isWinVisibleLw(); 2472 2473 if (keepVisibleDeadWindow) { 2474 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2475 "Not removing " + win + " because app died while it's visible"); 2476 2477 win.mAppDied = true; 2478 win.setDisplayLayoutNeeded(); 2479 mWindowPlacerLocked.performSurfacePlacement(); 2480 2481 // Set up a replacement input channel since the app is now dead. 2482 // We need to catch tapping on the dead window to restart the app. 2483 win.openInputChannel(null); 2484 mInputMonitor.updateInputWindowsLw(true /*force*/); 2485 2486 Binder.restoreCallingIdentity(origId); 2487 return; 2488 } 2489 2490 final WindowStateAnimator winAnimator = win.mWinAnimator; 2491 if (wasVisible) { 2492 final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE; 2493 2494 // Try starting an animation. 2495 if (winAnimator.applyAnimationLocked(transit, false)) { 2496 win.mAnimatingExit = true; 2497 } 2498 //TODO (multidisplay): Magnification is supported only for the default display. 2499 if (mAccessibilityController != null 2500 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2501 mAccessibilityController.onWindowTransitionLocked(win, transit); 2502 } 2503 } 2504 final boolean isAnimating = 2505 winAnimator.isAnimationSet() && !winAnimator.isDummyAnimation(); 2506 final boolean lastWindowIsStartingWindow = startingWindow && appToken != null 2507 && appToken.allAppWindows.size() == 1; 2508 // We delay the removal of a window if it has a showing surface that can be used to run 2509 // exit animation and it is marked as exiting. 2510 // Also, If isn't the an animating starting window that is the last window in the app. 2511 // We allow the removal of the non-animating starting window now as there is no 2512 // additional window or animation that will trigger its removal. 2513 if (winAnimator.getShown() && win.mAnimatingExit 2514 && (!lastWindowIsStartingWindow || isAnimating)) { 2515 // The exit animation is running or should run... wait for it! 2516 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2517 "Not removing " + win + " due to exit animation "); 2518 setupWindowForRemoveOnExit(win); 2519 if (appToken != null) { 2520 appToken.updateReportedVisibilityLocked(); 2521 } 2522 Binder.restoreCallingIdentity(origId); 2523 return; 2524 } 2525 } 2526 2527 removeWindowInnerLocked(win); 2528 // Removing a visible window will effect the computed orientation 2529 // So just update orientation if needed. 2530 if (wasVisible && updateOrientationFromAppTokensLocked(false)) { 2531 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2532 } 2533 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2534 Binder.restoreCallingIdentity(origId); 2535 } 2536 removeWindowInnerLocked(WindowState win)2537 void removeWindowInnerLocked(WindowState win) { 2538 if (win.mRemoved) { 2539 // Nothing to do. 2540 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2541 "removeWindowInnerLocked: " + win + " Already removed..."); 2542 return; 2543 } 2544 2545 for (int i = win.mChildWindows.size() - 1; i >= 0; i--) { 2546 WindowState cwin = win.mChildWindows.get(i); 2547 Slog.w(TAG_WM, "Force-removing child win " + cwin + " from container " + win); 2548 removeWindowInnerLocked(cwin); 2549 } 2550 2551 win.mRemoved = true; 2552 2553 if (mInputMethodTarget == win) { 2554 moveInputMethodWindowsIfNeededLocked(false); 2555 } 2556 2557 if (false) { 2558 RuntimeException e = new RuntimeException("here"); 2559 e.fillInStackTrace(); 2560 Slog.w(TAG_WM, "Removing window " + win, e); 2561 } 2562 2563 final int type = win.mAttrs.type; 2564 if (excludeWindowTypeFromTapOutTask(type)) { 2565 final DisplayContent displaycontent = win.getDisplayContent(); 2566 displaycontent.mTapExcludedWindows.remove(win); 2567 } 2568 mPolicy.removeWindowLw(win); 2569 win.removeLocked(); 2570 2571 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "removeWindowInnerLocked: " + win); 2572 mWindowMap.remove(win.mClient.asBinder()); 2573 if (win.mAppOp != AppOpsManager.OP_NONE) { 2574 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); 2575 } 2576 2577 mPendingRemove.remove(win); 2578 mResizingWindows.remove(win); 2579 mWindowsChanged = true; 2580 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win); 2581 2582 if (mInputMethodWindow == win) { 2583 mInputMethodWindow = null; 2584 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { 2585 mInputMethodDialogs.remove(win); 2586 } 2587 2588 final WindowToken token = win.mToken; 2589 final AppWindowToken atoken = win.mAppToken; 2590 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token); 2591 token.windows.remove(win); 2592 if (atoken != null) { 2593 atoken.allAppWindows.remove(win); 2594 } 2595 if (localLOGV) Slog.v( 2596 TAG_WM, "**** Removing window " + win + ": count=" 2597 + token.windows.size()); 2598 if (token.windows.size() == 0) { 2599 if (!token.explicit) { 2600 mTokenMap.remove(token.token); 2601 } else if (atoken != null) { 2602 atoken.firstWindowDrawn = false; 2603 atoken.clearAllDrawn(); 2604 } 2605 } 2606 2607 if (atoken != null) { 2608 if (atoken.startingWindow == win) { 2609 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win); 2610 scheduleRemoveStartingWindowLocked(atoken); 2611 } else 2612 if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) { 2613 // If this is the last window and we had requested a starting 2614 // transition window, well there is no point now. 2615 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingWindow"); 2616 atoken.startingData = null; 2617 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) { 2618 // If this is the last window except for a starting transition 2619 // window, we need to get rid of the starting transition. 2620 scheduleRemoveStartingWindowLocked(atoken); 2621 } 2622 } 2623 2624 if (type == TYPE_WALLPAPER) { 2625 mWallpaperControllerLocked.clearLastWallpaperTimeoutTime(); 2626 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2627 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2628 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2629 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2630 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2631 } 2632 2633 final WindowList windows = win.getWindowList(); 2634 if (windows != null) { 2635 windows.remove(win); 2636 if (!mWindowPlacerLocked.isInLayout()) { 2637 mLayersController.assignLayersLocked(windows); 2638 win.setDisplayLayoutNeeded(); 2639 mWindowPlacerLocked.performSurfacePlacement(); 2640 if (win.mAppToken != null) { 2641 win.mAppToken.updateReportedVisibilityLocked(); 2642 } 2643 } 2644 } 2645 2646 mInputMonitor.updateInputWindowsLw(true /*force*/); 2647 } 2648 updateAppOpsState()2649 public void updateAppOpsState() { 2650 synchronized(mWindowMap) { 2651 final int numDisplays = mDisplayContents.size(); 2652 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 2653 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 2654 final int numWindows = windows.size(); 2655 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 2656 final WindowState win = windows.get(winNdx); 2657 if (win.mAppOp != AppOpsManager.OP_NONE) { 2658 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(), 2659 win.getOwningPackage()); 2660 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED || 2661 mode == AppOpsManager.MODE_DEFAULT); 2662 } 2663 } 2664 } 2665 } 2666 } 2667 logSurface(WindowState w, String msg, boolean withStackTrace)2668 static void logSurface(WindowState w, String msg, boolean withStackTrace) { 2669 String str = " SURFACE " + msg + ": " + w; 2670 if (withStackTrace) { 2671 logWithStack(TAG, str); 2672 } else { 2673 Slog.i(TAG_WM, str); 2674 } 2675 } 2676 logSurface(SurfaceControl s, String title, String msg)2677 static void logSurface(SurfaceControl s, String title, String msg) { 2678 String str = " SURFACE " + s + ": " + msg + " / " + title; 2679 Slog.i(TAG_WM, str); 2680 } 2681 logWithStack(String tag, String s)2682 static void logWithStack(String tag, String s) { 2683 RuntimeException e = null; 2684 if (SHOW_STACK_CRAWLS) { 2685 e = new RuntimeException(); 2686 e.fillInStackTrace(); 2687 } 2688 Slog.i(tag, s, e); 2689 } 2690 setTransparentRegionWindow(Session session, IWindow client, Region region)2691 void setTransparentRegionWindow(Session session, IWindow client, Region region) { 2692 long origId = Binder.clearCallingIdentity(); 2693 try { 2694 synchronized (mWindowMap) { 2695 WindowState w = windowForClientLocked(session, client, false); 2696 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 2697 "transparentRegionHint=" + region, false); 2698 2699 if ((w != null) && w.mHasSurface) { 2700 w.mWinAnimator.setTransparentRegionHintLocked(region); 2701 } 2702 } 2703 } finally { 2704 Binder.restoreCallingIdentity(origId); 2705 } 2706 } 2707 setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableRegion)2708 void setInsetsWindow(Session session, IWindow client, int touchableInsets, Rect contentInsets, 2709 Rect visibleInsets, Region touchableRegion) { 2710 long origId = Binder.clearCallingIdentity(); 2711 try { 2712 synchronized (mWindowMap) { 2713 WindowState w = windowForClientLocked(session, client, false); 2714 if (DEBUG_LAYOUT) Slog.d(TAG, "setInsetsWindow " + w 2715 + ", contentInsets=" + w.mGivenContentInsets + " -> " + contentInsets 2716 + ", visibleInsets=" + w.mGivenVisibleInsets + " -> " + visibleInsets 2717 + ", touchableRegion=" + w.mGivenTouchableRegion + " -> " + touchableRegion 2718 + ", touchableInsets " + w.mTouchableInsets + " -> " + touchableInsets); 2719 if (w != null) { 2720 w.mGivenInsetsPending = false; 2721 w.mGivenContentInsets.set(contentInsets); 2722 w.mGivenVisibleInsets.set(visibleInsets); 2723 w.mGivenTouchableRegion.set(touchableRegion); 2724 w.mTouchableInsets = touchableInsets; 2725 if (w.mGlobalScale != 1) { 2726 w.mGivenContentInsets.scale(w.mGlobalScale); 2727 w.mGivenVisibleInsets.scale(w.mGlobalScale); 2728 w.mGivenTouchableRegion.scale(w.mGlobalScale); 2729 } 2730 w.setDisplayLayoutNeeded(); 2731 mWindowPlacerLocked.performSurfacePlacement(); 2732 } 2733 } 2734 } finally { 2735 Binder.restoreCallingIdentity(origId); 2736 } 2737 } 2738 getWindowDisplayFrame(Session session, IWindow client, Rect outDisplayFrame)2739 public void getWindowDisplayFrame(Session session, IWindow client, 2740 Rect outDisplayFrame) { 2741 synchronized(mWindowMap) { 2742 WindowState win = windowForClientLocked(session, client, false); 2743 if (win == null) { 2744 outDisplayFrame.setEmpty(); 2745 return; 2746 } 2747 outDisplayFrame.set(win.mDisplayFrame); 2748 } 2749 } 2750 onRectangleOnScreenRequested(IBinder token, Rect rectangle)2751 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 2752 synchronized (mWindowMap) { 2753 if (mAccessibilityController != null) { 2754 WindowState window = mWindowMap.get(token); 2755 //TODO (multidisplay): Magnification is supported only for the default display. 2756 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 2757 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle); 2758 } 2759 } 2760 } 2761 } 2762 getWindowId(IBinder token)2763 public IWindowId getWindowId(IBinder token) { 2764 synchronized (mWindowMap) { 2765 WindowState window = mWindowMap.get(token); 2766 return window != null ? window.mWindowId : null; 2767 } 2768 } 2769 pokeDrawLock(Session session, IBinder token)2770 public void pokeDrawLock(Session session, IBinder token) { 2771 synchronized (mWindowMap) { 2772 WindowState window = windowForClientLocked(session, token, false); 2773 if (window != null) { 2774 window.pokeDrawLockLw(mDrawLockTimeoutMillis); 2775 } 2776 } 2777 } 2778 repositionChild(Session session, IWindow client, int left, int top, int right, int bottom, long frameNumber, Rect outFrame)2779 void repositionChild(Session session, IWindow client, 2780 int left, int top, int right, int bottom, 2781 long frameNumber, Rect outFrame) { 2782 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild"); 2783 long origId = Binder.clearCallingIdentity(); 2784 2785 try { 2786 synchronized(mWindowMap) { 2787 WindowState win = windowForClientLocked(session, client, false); 2788 if (win == null) { 2789 return; 2790 } 2791 if (win.mAttachedWindow == null) { 2792 throw new IllegalArgumentException( 2793 "repositionChild called but window is not" 2794 + "attached to a parent win=" + win); 2795 } 2796 2797 win.mAttrs.x = left; 2798 win.mAttrs.y = top; 2799 win.mAttrs.width = right - left; 2800 win.mAttrs.height = bottom - top; 2801 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight); 2802 2803 if (win.mHasSurface) { 2804 if (SHOW_TRANSACTIONS) { 2805 Slog.i(TAG_WM, ">>> OPEN TRANSACTION repositionChild"); 2806 } 2807 2808 SurfaceControl.openTransaction(); 2809 2810 try { 2811 2812 win.applyGravityAndUpdateFrame(win.mContainingFrame, win.mDisplayFrame); 2813 win.mWinAnimator.computeShownFrameLocked(); 2814 2815 win.mWinAnimator.setSurfaceBoundariesLocked(false); 2816 2817 if (frameNumber > 0) { 2818 win.mWinAnimator.deferTransactionUntilParentFrame(frameNumber); 2819 } 2820 2821 } finally { 2822 SurfaceControl.closeTransaction(); 2823 if (SHOW_TRANSACTIONS) { 2824 Slog.i(TAG_WM, "<<< CLOSE TRANSACTION repositionChild"); 2825 } 2826 } 2827 } 2828 2829 outFrame = win.mCompatFrame; 2830 } 2831 } finally { 2832 Binder.restoreCallingIdentity(origId); 2833 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 2834 } 2835 } 2836 relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame, Configuration outConfig, Surface outSurface)2837 public int relayoutWindow(Session session, IWindow client, int seq, 2838 WindowManager.LayoutParams attrs, int requestedWidth, 2839 int requestedHeight, int viewVisibility, int flags, 2840 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, 2841 Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame, 2842 Configuration outConfig, Surface outSurface) { 2843 int result = 0; 2844 boolean configChanged; 2845 boolean hasStatusBarPermission = 2846 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 2847 == PackageManager.PERMISSION_GRANTED; 2848 2849 long origId = Binder.clearCallingIdentity(); 2850 synchronized(mWindowMap) { 2851 WindowState win = windowForClientLocked(session, client, false); 2852 if (win == null) { 2853 return 0; 2854 } 2855 2856 WindowStateAnimator winAnimator = win.mWinAnimator; 2857 if (viewVisibility != View.GONE) { 2858 win.setRequestedSize(requestedWidth, requestedHeight); 2859 } 2860 2861 int attrChanges = 0; 2862 int flagChanges = 0; 2863 if (attrs != null) { 2864 mPolicy.adjustWindowParamsLw(attrs); 2865 // if they don't have the permission, mask out the status bar bits 2866 if (seq == win.mSeq) { 2867 int systemUiVisibility = attrs.systemUiVisibility 2868 | attrs.subtreeSystemUiVisibility; 2869 if ((systemUiVisibility & DISABLE_MASK) != 0) { 2870 if (!hasStatusBarPermission) { 2871 systemUiVisibility &= ~DISABLE_MASK; 2872 } 2873 } 2874 win.mSystemUiVisibility = systemUiVisibility; 2875 } 2876 if (win.mAttrs.type != attrs.type) { 2877 throw new IllegalArgumentException( 2878 "Window type can not be changed after the window is added."); 2879 } 2880 2881 // Odd choice but less odd than embedding in copyFrom() 2882 if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY) 2883 != 0) { 2884 attrs.x = win.mAttrs.x; 2885 attrs.y = win.mAttrs.y; 2886 attrs.width = win.mAttrs.width; 2887 attrs.height = win.mAttrs.height; 2888 } 2889 2890 flagChanges = win.mAttrs.flags ^= attrs.flags; 2891 attrChanges = win.mAttrs.copyFrom(attrs); 2892 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED 2893 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) { 2894 win.mLayoutNeeded = true; 2895 } 2896 } 2897 2898 if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility 2899 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs); 2900 winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0; 2901 win.mEnforceSizeCompat = 2902 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0; 2903 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { 2904 winAnimator.mAlpha = attrs.alpha; 2905 } 2906 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight); 2907 2908 if (win.mAttrs.surfaceInsets.left != 0 2909 || win.mAttrs.surfaceInsets.top != 0 2910 || win.mAttrs.surfaceInsets.right != 0 2911 || win.mAttrs.surfaceInsets.bottom != 0) { 2912 winAnimator.setOpaqueLocked(false); 2913 } 2914 2915 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0; 2916 final boolean isDefaultDisplay = win.isDefaultDisplay(); 2917 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility 2918 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0) 2919 || (!win.mRelayoutCalled)); 2920 2921 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility 2922 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0; 2923 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0; 2924 if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) { 2925 winAnimator.mSurfaceController.setSecure(isSecureLocked(win)); 2926 } 2927 2928 win.mRelayoutCalled = true; 2929 win.mInRelayout = true; 2930 2931 final int oldVisibility = win.mViewVisibility; 2932 win.mViewVisibility = viewVisibility; 2933 if (DEBUG_SCREEN_ON) { 2934 RuntimeException stack = new RuntimeException(); 2935 stack.fillInStackTrace(); 2936 Slog.i(TAG_WM, "Relayout " + win + ": oldVis=" + oldVisibility 2937 + " newVis=" + viewVisibility, stack); 2938 } 2939 if (viewVisibility == View.VISIBLE && 2940 (win.mAppToken == null || !win.mAppToken.clientHidden)) { 2941 result = relayoutVisibleWindow(outConfig, result, win, winAnimator, attrChanges, 2942 oldVisibility); 2943 try { 2944 result = createSurfaceControl(outSurface, result, win, winAnimator); 2945 } catch (Exception e) { 2946 mInputMonitor.updateInputWindowsLw(true /*force*/); 2947 2948 Slog.w(TAG_WM, "Exception thrown when creating surface for client " 2949 + client + " (" + win.mAttrs.getTitle() + ")", 2950 e); 2951 Binder.restoreCallingIdentity(origId); 2952 return 0; 2953 } 2954 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { 2955 focusMayChange = isDefaultDisplay; 2956 } 2957 if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) { 2958 mInputMethodWindow = win; 2959 imMayMove = true; 2960 } 2961 win.adjustStartingWindowFlags(); 2962 } else { 2963 winAnimator.mEnterAnimationPending = false; 2964 winAnimator.mEnteringAnimation = false; 2965 final boolean usingSavedSurfaceBeforeVisible = 2966 oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface(); 2967 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 2968 if (winAnimator.hasSurface() && !win.mAnimatingExit 2969 && usingSavedSurfaceBeforeVisible) { 2970 Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win); 2971 } 2972 } 2973 2974 if (winAnimator.hasSurface() && !win.mAnimatingExit 2975 && !usingSavedSurfaceBeforeVisible) { 2976 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win 2977 + ": mAnimatingExit=" + win.mAnimatingExit); 2978 // If we are not currently running the exit animation, we 2979 // need to see about starting one. 2980 // We don't want to animate visibility of windows which are pending 2981 // replacement. In the case of activity relaunch child windows 2982 // could request visibility changes as they are detached from the main 2983 // application window during the tear down process. If we satisfied 2984 // these visibility changes though, we would cause a visual glitch 2985 // hiding the window before it's replacement was available. 2986 // So we just do nothing on our side. 2987 if (!win.mWillReplaceWindow) { 2988 focusMayChange = tryStartExitingAnimation( 2989 win, winAnimator, isDefaultDisplay, focusMayChange); 2990 } 2991 result |= RELAYOUT_RES_SURFACE_CHANGED; 2992 } 2993 if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) { 2994 // We already told the client to go invisible, but the message may not be 2995 // handled yet, or it might want to draw a last frame. If we already have a 2996 // surface, let the client use that, but don't create new surface at this point. 2997 winAnimator.mSurfaceController.getSurface(outSurface); 2998 } else { 2999 if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win); 3000 3001 try { 3002 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_" 3003 + win.mAttrs.getTitle()); 3004 outSurface.release(); 3005 } finally { 3006 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 3007 } 3008 } 3009 } 3010 3011 if (focusMayChange) { 3012 //System.out.println("Focus may change: " + win.mAttrs.getTitle()); 3013 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 3014 false /*updateInputWindows*/)) { 3015 imMayMove = false; 3016 } 3017 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus); 3018 } 3019 3020 // updateFocusedWindowLocked() already assigned layers so we only need to 3021 // reassign them at this point if the IM window state gets shuffled 3022 boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0; 3023 if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) { 3024 // Little hack here -- we -should- be able to rely on the 3025 // function to return true if the IME has moved and needs 3026 // its layer recomputed. However, if the IME was hidden 3027 // and isn't actually moved in the list, its layer may be 3028 // out of data so we make sure to recompute it. 3029 mLayersController.assignLayersLocked(win.getWindowList()); 3030 } 3031 3032 if (wallpaperMayMove) { 3033 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3034 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3035 } 3036 3037 win.setDisplayLayoutNeeded(); 3038 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; 3039 configChanged = updateOrientationFromAppTokensLocked(false); 3040 mWindowPlacerLocked.performSurfacePlacement(); 3041 if (toBeDisplayed && win.mIsWallpaper) { 3042 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3043 mWallpaperControllerLocked.updateWallpaperOffset( 3044 win, displayInfo.logicalWidth, displayInfo.logicalHeight, false); 3045 } 3046 if (win.mAppToken != null) { 3047 win.mAppToken.updateReportedVisibilityLocked(); 3048 } 3049 if (winAnimator.mReportSurfaceResized) { 3050 winAnimator.mReportSurfaceResized = false; 3051 result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED; 3052 } 3053 if (mPolicy.isNavBarForcedShownLw(win)) { 3054 result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR; 3055 } 3056 if (!win.isGoneForLayoutLw()) { 3057 win.mResizedWhileGone = false; 3058 } 3059 outFrame.set(win.mCompatFrame); 3060 outOverscanInsets.set(win.mOverscanInsets); 3061 outContentInsets.set(win.mContentInsets); 3062 outVisibleInsets.set(win.mVisibleInsets); 3063 outStableInsets.set(win.mStableInsets); 3064 outOutsets.set(win.mOutsets); 3065 outBackdropFrame.set(win.getBackdropFrame(win.mFrame)); 3066 if (localLOGV) Slog.v( 3067 TAG_WM, "Relayout given client " + client.asBinder() 3068 + ", requestedWidth=" + requestedWidth 3069 + ", requestedHeight=" + requestedHeight 3070 + ", viewVisibility=" + viewVisibility 3071 + "\nRelayout returning frame=" + outFrame 3072 + ", surface=" + outSurface); 3073 3074 if (localLOGV || DEBUG_FOCUS) Slog.v( 3075 TAG_WM, "Relayout of " + win + ": focusMayChange=" + focusMayChange); 3076 3077 result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0; 3078 3079 mInputMonitor.updateInputWindowsLw(true /*force*/); 3080 3081 if (DEBUG_LAYOUT) { 3082 Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString()); 3083 } 3084 win.mInRelayout = false; 3085 } 3086 3087 if (configChanged) { 3088 sendNewConfiguration(); 3089 } 3090 Binder.restoreCallingIdentity(origId); 3091 return result; 3092 } 3093 tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator, boolean isDefaultDisplay, boolean focusMayChange)3094 private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator, 3095 boolean isDefaultDisplay, boolean focusMayChange) { 3096 // Try starting an animation; if there isn't one, we 3097 // can destroy the surface right away. 3098 int transit = WindowManagerPolicy.TRANSIT_EXIT; 3099 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 3100 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 3101 } 3102 if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) { 3103 focusMayChange = isDefaultDisplay; 3104 win.mAnimatingExit = true; 3105 win.mWinAnimator.mAnimating = true; 3106 } else if (win.mWinAnimator.isAnimationSet()) { 3107 // Currently in a hide animation... turn this into 3108 // an exit. 3109 win.mAnimatingExit = true; 3110 win.mWinAnimator.mAnimating = true; 3111 } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) { 3112 // If the wallpaper is currently behind this 3113 // window, we need to change both of them inside 3114 // of a transaction to avoid artifacts. 3115 win.mAnimatingExit = true; 3116 win.mWinAnimator.mAnimating = true; 3117 } else { 3118 if (mInputMethodWindow == win) { 3119 mInputMethodWindow = null; 3120 } 3121 win.destroyOrSaveSurface(); 3122 } 3123 //TODO (multidisplay): Magnification is supported only for the default 3124 if (mAccessibilityController != null 3125 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 3126 mAccessibilityController.onWindowTransitionLocked(win, transit); 3127 } 3128 return focusMayChange; 3129 } 3130 createSurfaceControl(Surface outSurface, int result, WindowState win, WindowStateAnimator winAnimator)3131 private int createSurfaceControl(Surface outSurface, int result, WindowState win, 3132 WindowStateAnimator winAnimator) { 3133 if (!win.mHasSurface) { 3134 result |= RELAYOUT_RES_SURFACE_CHANGED; 3135 } 3136 WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked(); 3137 if (surfaceController != null) { 3138 surfaceController.getSurface(outSurface); 3139 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " OUT SURFACE " + outSurface + ": copied"); 3140 } else { 3141 // For some reason there isn't a surface. Clear the 3142 // caller's object so they see the same state. 3143 Slog.w(TAG_WM, "Failed to create surface control for " + win); 3144 outSurface.release(); 3145 } 3146 return result; 3147 } 3148 relayoutVisibleWindow(Configuration outConfig, int result, WindowState win, WindowStateAnimator winAnimator, int attrChanges, int oldVisibility)3149 private int relayoutVisibleWindow(Configuration outConfig, int result, WindowState win, 3150 WindowStateAnimator winAnimator, int attrChanges, int oldVisibility) { 3151 result |= !win.isVisibleLw() ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0; 3152 if (win.mAnimatingExit) { 3153 Slog.d(TAG, "relayoutVisibleWindow: " + win + " mAnimatingExit=true, mRemoveOnExit=" 3154 + win.mRemoveOnExit + ", mDestroying=" + win.mDestroying); 3155 3156 winAnimator.cancelExitAnimationForNextAnimationLocked(); 3157 win.mAnimatingExit = false; 3158 } 3159 if (win.mDestroying) { 3160 win.mDestroying = false; 3161 mDestroySurface.remove(win); 3162 } 3163 if (oldVisibility == View.GONE) { 3164 winAnimator.mEnterAnimationPending = true; 3165 } 3166 3167 win.mLastVisibleLayoutRotation = mRotation; 3168 3169 winAnimator.mEnteringAnimation = true; 3170 if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { 3171 win.prepareWindowToDisplayDuringRelayout(outConfig); 3172 } 3173 if ((attrChanges & LayoutParams.FORMAT_CHANGED) != 0) { 3174 // If the format can't be changed in place, preserve the old surface until the app draws 3175 // on the new one. This prevents blinking when we change elevation of freeform and 3176 // pinned windows. 3177 if (!winAnimator.tryChangeFormatInPlaceLocked()) { 3178 winAnimator.preserveSurfaceLocked(); 3179 result |= RELAYOUT_RES_SURFACE_CHANGED 3180 | WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; 3181 } 3182 } 3183 3184 // If we're starting a drag-resize, we'll be changing the surface size as well as 3185 // notifying the client to render to with an offset from the surface's top-left. 3186 if (win.isDragResizeChanged() || win.isResizedWhileNotDragResizing()) { 3187 win.setDragResizing(); 3188 win.setResizedWhileNotDragResizing(false); 3189 // We can only change top level windows to the full-screen surface when 3190 // resizing (as we only have one full-screen surface). So there is no need 3191 // to preserve and destroy windows which are attached to another, they 3192 // will keep their surface and its size may change over time. 3193 if (win.mHasSurface && win.mAttachedWindow == null) { 3194 winAnimator.preserveSurfaceLocked(); 3195 result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; 3196 } 3197 } 3198 final boolean freeformResizing = win.isDragResizing() 3199 && win.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM; 3200 final boolean dockedResizing = win.isDragResizing() 3201 && win.getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER; 3202 result |= freeformResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0; 3203 result |= dockedResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0; 3204 if (win.isAnimatingWithSavedSurface()) { 3205 // If we're animating with a saved surface now, request client to report draw. 3206 // We still need to know when the real thing is drawn. 3207 result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; 3208 } 3209 return result; 3210 } 3211 performDeferredDestroyWindow(Session session, IWindow client)3212 public void performDeferredDestroyWindow(Session session, IWindow client) { 3213 long origId = Binder.clearCallingIdentity(); 3214 3215 try { 3216 synchronized (mWindowMap) { 3217 WindowState win = windowForClientLocked(session, client, false); 3218 if (win == null || win.mWillReplaceWindow) { 3219 return; 3220 } 3221 3222 win.mWinAnimator.destroyDeferredSurfaceLocked(); 3223 } 3224 } finally { 3225 Binder.restoreCallingIdentity(origId); 3226 } 3227 } 3228 outOfMemoryWindow(Session session, IWindow client)3229 public boolean outOfMemoryWindow(Session session, IWindow client) { 3230 long origId = Binder.clearCallingIdentity(); 3231 3232 try { 3233 synchronized (mWindowMap) { 3234 WindowState win = windowForClientLocked(session, client, false); 3235 if (win == null) { 3236 return false; 3237 } 3238 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false); 3239 } 3240 } finally { 3241 Binder.restoreCallingIdentity(origId); 3242 } 3243 } 3244 finishDrawingWindow(Session session, IWindow client)3245 public void finishDrawingWindow(Session session, IWindow client) { 3246 final long origId = Binder.clearCallingIdentity(); 3247 try { 3248 synchronized (mWindowMap) { 3249 WindowState win = windowForClientLocked(session, client, false); 3250 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState=" 3251 + (win != null ? win.mWinAnimator.drawStateToString() : "null")); 3252 if (win != null && win.mWinAnimator.finishDrawingLocked()) { 3253 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 3254 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3255 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3256 } 3257 win.setDisplayLayoutNeeded(); 3258 mWindowPlacerLocked.requestTraversal(); 3259 } 3260 } 3261 } finally { 3262 Binder.restoreCallingIdentity(origId); 3263 } 3264 } 3265 applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction)3266 private boolean applyAnimationLocked(AppWindowToken atoken, WindowManager.LayoutParams lp, 3267 int transit, boolean enter, boolean isVoiceInteraction) { 3268 // Only apply an animation if the display isn't frozen. If it is 3269 // frozen, there is no reason to animate and it can cause strange 3270 // artifacts when we unfreeze the display if some different animation 3271 // is running. 3272 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked"); 3273 if (okToDisplay()) { 3274 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3275 final int width = displayInfo.appWidth; 3276 final int height = displayInfo.appHeight; 3277 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM, 3278 "applyAnimation: atoken=" + atoken); 3279 3280 // Determine the visible rect to calculate the thumbnail clip 3281 final WindowState win = atoken.findMainWindow(); 3282 final Rect frame = new Rect(0, 0, width, height); 3283 final Rect displayFrame = new Rect(0, 0, 3284 displayInfo.logicalWidth, displayInfo.logicalHeight); 3285 final Rect insets = new Rect(); 3286 Rect surfaceInsets = null; 3287 final boolean freeform = win != null && win.inFreeformWorkspace(); 3288 if (win != null) { 3289 // Containing frame will usually cover the whole screen, including dialog windows. 3290 // For freeform workspace windows it will not cover the whole screen and it also 3291 // won't exactly match the final freeform window frame (e.g. when overlapping with 3292 // the status bar). In that case we need to use the final frame. 3293 if (freeform) { 3294 frame.set(win.mFrame); 3295 } else { 3296 frame.set(win.mContainingFrame); 3297 } 3298 surfaceInsets = win.getAttrs().surfaceInsets; 3299 insets.set(win.mContentInsets); 3300 } 3301 3302 if (atoken.mLaunchTaskBehind) { 3303 // Differentiate the two animations. This one which is briefly on the screen 3304 // gets the !enter animation, and the other activity which remains on the 3305 // screen gets the enter animation. Both appear in the mOpeningApps set. 3306 enter = false; 3307 } 3308 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition." 3309 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter 3310 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets); 3311 Animation a = mAppTransition.loadAnimation(lp, transit, enter, mCurConfiguration.uiMode, 3312 mCurConfiguration.orientation, frame, displayFrame, insets, surfaceInsets, 3313 isVoiceInteraction, freeform, atoken.mTask.mTaskId); 3314 if (a != null) { 3315 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken); 3316 final int containingWidth = frame.width(); 3317 final int containingHeight = frame.height(); 3318 atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight, 3319 mAppTransition.canSkipFirstFrame(), mAppTransition.getAppStackClipMode()); 3320 } 3321 } else { 3322 atoken.mAppAnimator.clearAnimation(); 3323 } 3324 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 3325 3326 return atoken.mAppAnimator.animation != null; 3327 } 3328 3329 // ------------------------------------------------------------- 3330 // Application Window Tokens 3331 // ------------------------------------------------------------- 3332 validateAppTokens(int stackId, List<TaskGroup> tasks)3333 public void validateAppTokens(int stackId, List<TaskGroup> tasks) { 3334 synchronized (mWindowMap) { 3335 int t = tasks.size() - 1; 3336 if (t < 0) { 3337 Slog.w(TAG_WM, "validateAppTokens: empty task list"); 3338 return; 3339 } 3340 3341 TaskGroup task = tasks.get(0); 3342 int taskId = task.taskId; 3343 Task targetTask = mTaskIdToTask.get(taskId); 3344 DisplayContent displayContent = targetTask.getDisplayContent(); 3345 if (displayContent == null) { 3346 Slog.w(TAG_WM, "validateAppTokens: no Display for taskId=" + taskId); 3347 return; 3348 } 3349 3350 final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks(); 3351 int taskNdx; 3352 for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) { 3353 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens; 3354 task = tasks.get(t); 3355 List<IApplicationToken> tokens = task.tokens; 3356 3357 DisplayContent lastDisplayContent = displayContent; 3358 displayContent = mTaskIdToTask.get(taskId).getDisplayContent(); 3359 if (displayContent != lastDisplayContent) { 3360 Slog.w(TAG_WM, "validateAppTokens: displayContent changed in TaskGroup list!"); 3361 return; 3362 } 3363 3364 int tokenNdx; 3365 int v; 3366 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1; 3367 tokenNdx >= 0 && v >= 0; ) { 3368 final AppWindowToken atoken = localTokens.get(tokenNdx); 3369 if (atoken.removed) { 3370 --tokenNdx; 3371 continue; 3372 } 3373 if (tokens.get(v) != atoken.token) { 3374 break; 3375 } 3376 --tokenNdx; 3377 v--; 3378 } 3379 3380 if (tokenNdx >= 0 || v >= 0) { 3381 break; 3382 } 3383 } 3384 3385 if (taskNdx >= 0 || t >= 0) { 3386 Slog.w(TAG_WM, "validateAppTokens: Mismatch! ActivityManager=" + tasks); 3387 Slog.w(TAG_WM, "validateAppTokens: Mismatch! WindowManager=" + localTasks); 3388 Slog.w(TAG_WM, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4)); 3389 } 3390 } 3391 } 3392 validateStackOrder(Integer[] remoteStackIds)3393 public void validateStackOrder(Integer[] remoteStackIds) { 3394 // TODO: 3395 } 3396 checkCallingPermission(String permission, String func)3397 private boolean checkCallingPermission(String permission, String func) { 3398 // Quick check: if the calling permission is me, it's all okay. 3399 if (Binder.getCallingPid() == Process.myPid()) { 3400 return true; 3401 } 3402 3403 if (mContext.checkCallingPermission(permission) 3404 == PackageManager.PERMISSION_GRANTED) { 3405 return true; 3406 } 3407 String msg = "Permission Denial: " + func + " from pid=" 3408 + Binder.getCallingPid() 3409 + ", uid=" + Binder.getCallingUid() 3410 + " requires " + permission; 3411 Slog.w(TAG_WM, msg); 3412 return false; 3413 } 3414 okToDisplay()3415 boolean okToDisplay() { 3416 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn(); 3417 } 3418 findAppWindowToken(IBinder token)3419 AppWindowToken findAppWindowToken(IBinder token) { 3420 WindowToken wtoken = mTokenMap.get(token); 3421 if (wtoken == null) { 3422 return null; 3423 } 3424 return wtoken.appWindowToken; 3425 } 3426 3427 @Override addWindowToken(IBinder token, int type)3428 public void addWindowToken(IBinder token, int type) { 3429 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3430 "addWindowToken()")) { 3431 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3432 } 3433 3434 synchronized(mWindowMap) { 3435 WindowToken wtoken = mTokenMap.get(token); 3436 if (wtoken != null) { 3437 Slog.w(TAG_WM, "Attempted to add existing input method token: " + token); 3438 return; 3439 } 3440 wtoken = new WindowToken(this, token, type, true); 3441 mTokenMap.put(token, wtoken); 3442 if (type == TYPE_WALLPAPER) { 3443 mWallpaperControllerLocked.addWallpaperToken(wtoken); 3444 } 3445 } 3446 } 3447 3448 @Override removeWindowToken(IBinder token)3449 public void removeWindowToken(IBinder token) { 3450 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3451 "removeWindowToken()")) { 3452 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3453 } 3454 3455 final long origId = Binder.clearCallingIdentity(); 3456 synchronized(mWindowMap) { 3457 DisplayContent displayContent = null; 3458 WindowToken wtoken = mTokenMap.remove(token); 3459 if (wtoken != null) { 3460 boolean delayed = false; 3461 if (!wtoken.hidden) { 3462 final int N = wtoken.windows.size(); 3463 boolean changed = false; 3464 3465 for (int i=0; i<N; i++) { 3466 WindowState win = wtoken.windows.get(i); 3467 displayContent = win.getDisplayContent(); 3468 3469 if (win.mWinAnimator.isAnimationSet()) { 3470 delayed = true; 3471 } 3472 3473 if (win.isVisibleNow()) { 3474 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, 3475 false); 3476 //TODO (multidisplay): Magnification is supported only for the default 3477 if (mAccessibilityController != null && win.isDefaultDisplay()) { 3478 mAccessibilityController.onWindowTransitionLocked(win, 3479 WindowManagerPolicy.TRANSIT_EXIT); 3480 } 3481 changed = true; 3482 if (displayContent != null) { 3483 displayContent.layoutNeeded = true; 3484 } 3485 } 3486 } 3487 3488 wtoken.hidden = true; 3489 3490 if (changed) { 3491 mWindowPlacerLocked.performSurfacePlacement(); 3492 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 3493 false /*updateInputWindows*/); 3494 } 3495 3496 if (delayed && displayContent != null) { 3497 displayContent.mExitingTokens.add(wtoken); 3498 } else if (wtoken.windowType == TYPE_WALLPAPER) { 3499 mWallpaperControllerLocked.removeWallpaperToken(wtoken); 3500 } 3501 } else if (wtoken.windowType == TYPE_WALLPAPER) { 3502 mWallpaperControllerLocked.removeWallpaperToken(wtoken); 3503 } 3504 3505 mInputMonitor.updateInputWindowsLw(true /*force*/); 3506 } else { 3507 Slog.w(TAG_WM, "Attempted to remove non-existing token: " + token); 3508 } 3509 } 3510 Binder.restoreCallingIdentity(origId); 3511 } 3512 createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken, Rect bounds, Configuration config)3513 private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken, 3514 Rect bounds, Configuration config) { 3515 if (DEBUG_STACK) Slog.i(TAG_WM, "createTaskLocked: taskId=" + taskId + " stackId=" + stackId 3516 + " atoken=" + atoken + " bounds=" + bounds); 3517 final TaskStack stack = mStackIdToStack.get(stackId); 3518 if (stack == null) { 3519 throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); 3520 } 3521 EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId); 3522 Task task = new Task(taskId, stack, userId, this, bounds, config); 3523 mTaskIdToTask.put(taskId, task); 3524 stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */, atoken.showForAllUsers); 3525 return task; 3526 } 3527 3528 @Override addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId, int configChanges, boolean voiceInteraction, boolean launchTaskBehind, Rect taskBounds, Configuration config, int taskResizeMode, boolean alwaysFocusable, boolean homeTask, int targetSdkVersion, int rotationAnimationHint)3529 public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, 3530 int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId, 3531 int configChanges, boolean voiceInteraction, boolean launchTaskBehind, 3532 Rect taskBounds, Configuration config, int taskResizeMode, boolean alwaysFocusable, 3533 boolean homeTask, int targetSdkVersion, int rotationAnimationHint) { 3534 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3535 "addAppToken()")) { 3536 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3537 } 3538 3539 // Get the dispatching timeout here while we are not holding any locks so that it 3540 // can be cached by the AppWindowToken. The timeout value is used later by the 3541 // input dispatcher in code that does hold locks. If we did not cache the value 3542 // here we would run the chance of introducing a deadlock between the window manager 3543 // (which holds locks while updating the input dispatcher state) and the activity manager 3544 // (which holds locks while querying the application token). 3545 long inputDispatchingTimeoutNanos; 3546 try { 3547 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; 3548 } catch (RemoteException ex) { 3549 Slog.w(TAG_WM, "Could not get dispatching timeout.", ex); 3550 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 3551 } 3552 3553 synchronized(mWindowMap) { 3554 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3555 if (atoken != null) { 3556 Slog.w(TAG_WM, "Attempted to add existing app token: " + token); 3557 return; 3558 } 3559 atoken = new AppWindowToken(this, token, voiceInteraction); 3560 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; 3561 atoken.appFullscreen = fullscreen; 3562 atoken.showForAllUsers = showForAllUsers; 3563 atoken.targetSdk = targetSdkVersion; 3564 atoken.requestedOrientation = requestedOrientation; 3565 atoken.layoutConfigChanges = (configChanges & 3566 (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0; 3567 atoken.mLaunchTaskBehind = launchTaskBehind; 3568 atoken.mAlwaysFocusable = alwaysFocusable; 3569 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken 3570 + " to stack=" + stackId + " task=" + taskId + " at " + addPos); 3571 atoken.mRotationAnimationHint = rotationAnimationHint; 3572 3573 Task task = mTaskIdToTask.get(taskId); 3574 if (task == null) { 3575 task = createTaskLocked(taskId, stackId, userId, atoken, taskBounds, config); 3576 } 3577 task.addAppToken(addPos, atoken, taskResizeMode, homeTask); 3578 3579 mTokenMap.put(token.asBinder(), atoken); 3580 3581 // Application tokens start out hidden. 3582 atoken.hidden = true; 3583 atoken.hiddenRequested = true; 3584 } 3585 } 3586 3587 @Override setAppTask(IBinder token, int taskId, int stackId, Rect taskBounds, Configuration config, int taskResizeMode, boolean homeTask)3588 public void setAppTask(IBinder token, int taskId, int stackId, Rect taskBounds, 3589 Configuration config, int taskResizeMode, boolean homeTask) { 3590 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3591 "setAppTask()")) { 3592 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3593 } 3594 3595 synchronized(mWindowMap) { 3596 final AppWindowToken atoken = findAppWindowToken(token); 3597 if (atoken == null) { 3598 Slog.w(TAG_WM, "Attempted to set task id of non-existing app token: " + token); 3599 return; 3600 } 3601 final Task oldTask = atoken.mTask; 3602 oldTask.removeAppToken(atoken); 3603 3604 Task newTask = mTaskIdToTask.get(taskId); 3605 if (newTask == null) { 3606 newTask = createTaskLocked( 3607 taskId, stackId, oldTask.mUserId, atoken, taskBounds, config); 3608 } 3609 newTask.addAppToken(Integer.MAX_VALUE /* at top */, atoken, taskResizeMode, homeTask); 3610 } 3611 } 3612 getOrientationLocked()3613 public int getOrientationLocked() { 3614 if (mDisplayFrozen) { 3615 if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) { 3616 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3617 "Display is frozen, return " + mLastWindowForcedOrientation); 3618 // If the display is frozen, some activities may be in the middle 3619 // of restarting, and thus have removed their old window. If the 3620 // window has the flag to hide the lock screen, then the lock screen 3621 // can re-appear and inflict its own orientation on us. Keep the 3622 // orientation stable until this all settles down. 3623 return mLastWindowForcedOrientation; 3624 } else if (mPolicy.isKeyguardLocked()) { 3625 // Use the last orientation the while the display is frozen with the 3626 // keyguard locked. This could be the keyguard forced orientation or 3627 // from a SHOW_WHEN_LOCKED window. We don't want to check the show when 3628 // locked window directly though as things aren't stable while 3629 // the display is frozen, for example the window could be momentarily unavailable 3630 // due to activity relaunch. 3631 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, " 3632 + "return " + mLastOrientation); 3633 return mLastOrientation; 3634 } 3635 } else { 3636 // TODO(multidisplay): Change to the correct display. 3637 final WindowList windows = getDefaultWindowListLocked(); 3638 for (int pos = windows.size() - 1; pos >= 0; --pos) { 3639 WindowState win = windows.get(pos); 3640 if (win.mAppToken != null) { 3641 // We hit an application window. so the orientation will be determined by the 3642 // app window. No point in continuing further. 3643 break; 3644 } 3645 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) { 3646 continue; 3647 } 3648 int req = win.mAttrs.screenOrientation; 3649 if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) { 3650 continue; 3651 } 3652 3653 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req); 3654 if (mPolicy.isKeyguardHostWindow(win.mAttrs)) { 3655 mLastKeyguardForcedOrientation = req; 3656 } 3657 return (mLastWindowForcedOrientation = req); 3658 } 3659 mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 3660 3661 if (mPolicy.isKeyguardLocked()) { 3662 // The screen is locked and no top system window is requesting an orientation. 3663 // Return either the orientation of the show-when-locked app (if there is any) or 3664 // the orientation of the keyguard. No point in searching from the rest of apps. 3665 WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw(); 3666 AppWindowToken appShowWhenLocked = winShowWhenLocked == null ? 3667 null : winShowWhenLocked.mAppToken; 3668 if (appShowWhenLocked != null) { 3669 int req = appShowWhenLocked.requestedOrientation; 3670 if (req == SCREEN_ORIENTATION_BEHIND) { 3671 req = mLastKeyguardForcedOrientation; 3672 } 3673 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Done at " + appShowWhenLocked 3674 + " -- show when locked, return " + req); 3675 return req; 3676 } 3677 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3678 "No one is requesting an orientation when the screen is locked"); 3679 return mLastKeyguardForcedOrientation; 3680 } 3681 } 3682 3683 // Top system windows are not requesting an orientation. Start searching from apps. 3684 return getAppSpecifiedOrientation(); 3685 } 3686 getAppSpecifiedOrientation()3687 private int getAppSpecifiedOrientation() { 3688 int lastOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 3689 boolean findingBehind = false; 3690 boolean lastFullscreen = false; 3691 DisplayContent displayContent = getDefaultDisplayContentLocked(); 3692 final ArrayList<Task> tasks = displayContent.getTasks(); 3693 final boolean inMultiWindow = isStackVisibleLocked(DOCKED_STACK_ID) 3694 || isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID); 3695 final boolean dockMinimized = 3696 getDefaultDisplayContentLocked().mDividerControllerLocked.isMinimizedDock(); 3697 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 3698 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 3699 final int firstToken = tokens.size() - 1; 3700 for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) { 3701 final AppWindowToken atoken = tokens.get(tokenNdx); 3702 3703 if (DEBUG_APP_ORIENTATION) Slog.v(TAG_WM, "Checking app orientation: " + atoken); 3704 3705 // if we're about to tear down this window and not seek for 3706 // the behind activity, don't use it for orientation 3707 if (!findingBehind && !atoken.hidden && atoken.hiddenRequested) { 3708 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3709 "Skipping " + atoken + " -- going to hide"); 3710 continue; 3711 } 3712 3713 if (tokenNdx == firstToken) { 3714 // If we have hit a new Task, and the bottom of the previous group didn't 3715 // explicitly say to use the orientation behind it, and the last app was 3716 // full screen, then we'll stick with the user's orientation. 3717 if (lastOrientation != SCREEN_ORIENTATION_BEHIND && lastFullscreen) { 3718 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Done at " + atoken 3719 + " -- end of group, return " + lastOrientation); 3720 return lastOrientation; 3721 } 3722 } 3723 3724 // We ignore any hidden applications on the top. 3725 if (atoken.hiddenRequested) { 3726 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3727 "Skipping " + atoken + " -- hidden on top"); 3728 continue; 3729 } 3730 3731 // No app except the home app may specify the screen orientation in multi-window, 3732 // and only if the docked stack is minimized to avoid weirdness when home task 3733 // temporarily gets moved to the front. 3734 if (inMultiWindow && (!atoken.mTask.isHomeTask() || !dockMinimized)) { 3735 continue; 3736 } 3737 3738 if (tokenNdx == 0) { 3739 // Last token in this task. 3740 lastOrientation = atoken.requestedOrientation; 3741 } 3742 3743 int or = atoken.requestedOrientation; 3744 // If this application is fullscreen, and didn't explicitly say 3745 // to use the orientation behind it, then just take whatever 3746 // orientation it has and ignores whatever is under it. 3747 lastFullscreen = atoken.appFullscreen; 3748 if (lastFullscreen && or != SCREEN_ORIENTATION_BEHIND) { 3749 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3750 "Done at " + atoken + " -- full screen, return " + or); 3751 return or; 3752 } 3753 // If this application has requested an explicit orientation, then use it. 3754 if (or != SCREEN_ORIENTATION_UNSPECIFIED && or != SCREEN_ORIENTATION_BEHIND) { 3755 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3756 "Done at " + atoken + " -- explicitly set, return " + or); 3757 return or; 3758 } 3759 findingBehind |= (or == SCREEN_ORIENTATION_BEHIND); 3760 } 3761 } 3762 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3763 "No app is requesting an orientation, return " + mLastOrientation); 3764 // The next app has not been requested to be visible, so we keep the current orientation 3765 // to prevent freezing/unfreezing the display too early unless we are in multi-window, in 3766 // which we don't let the app customize the orientation unless it was the home task that 3767 // is handled above. 3768 return inMultiWindow ? SCREEN_ORIENTATION_UNSPECIFIED : mLastOrientation; 3769 } 3770 3771 @Override updateOrientationFromAppTokens( Configuration currentConfig, IBinder freezeThisOneIfNeeded)3772 public Configuration updateOrientationFromAppTokens( 3773 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3774 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3775 "updateOrientationFromAppTokens()")) { 3776 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3777 } 3778 3779 Configuration config = null; 3780 long ident = Binder.clearCallingIdentity(); 3781 3782 synchronized(mWindowMap) { 3783 config = updateOrientationFromAppTokensLocked(currentConfig, 3784 freezeThisOneIfNeeded); 3785 } 3786 3787 Binder.restoreCallingIdentity(ident); 3788 return config; 3789 } 3790 updateOrientationFromAppTokensLocked( Configuration currentConfig, IBinder freezeThisOneIfNeeded)3791 private Configuration updateOrientationFromAppTokensLocked( 3792 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3793 if (!mDisplayReady) { 3794 return null; 3795 } 3796 Configuration config = null; 3797 3798 if (updateOrientationFromAppTokensLocked(false)) { 3799 // If we changed the orientation but mOrientationChangeComplete is 3800 // already true, we used seamless rotation, and we don't need 3801 // to freeze the screen. 3802 if (freezeThisOneIfNeeded != null && 3803 !mWindowPlacerLocked.mOrientationChangeComplete) { 3804 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded); 3805 if (atoken != null) { 3806 startAppFreezingScreenLocked(atoken); 3807 } 3808 } 3809 config = computeNewConfigurationLocked(); 3810 3811 } else if (currentConfig != null) { 3812 // No obvious action we need to take, but if our current 3813 // state mismatches the activity manager's, update it, 3814 // disregarding font scale, which should remain set to 3815 // the value of the previous configuration. 3816 mTempConfiguration.setToDefaults(); 3817 mTempConfiguration.updateFrom(currentConfig); 3818 computeScreenConfigurationLocked(mTempConfiguration); 3819 if (currentConfig.diff(mTempConfiguration) != 0) { 3820 mWaitingForConfig = true; 3821 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3822 displayContent.layoutNeeded = true; 3823 int anim[] = new int[2]; 3824 if (displayContent.isDimming()) { 3825 anim[0] = anim[1] = 0; 3826 } else { 3827 mPolicy.selectRotationAnimationLw(anim); 3828 } 3829 startFreezingDisplayLocked(false, anim[0], anim[1]); 3830 config = new Configuration(mTempConfiguration); 3831 } 3832 } 3833 3834 return config; 3835 } 3836 3837 /* 3838 * Determine the new desired orientation of the display, returning 3839 * a non-null new Configuration if it has changed from the current 3840 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL 3841 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE 3842 * SCREEN. This will typically be done for you if you call 3843 * sendNewConfiguration(). 3844 * 3845 * The orientation is computed from non-application windows first. If none of 3846 * the non-application windows specify orientation, the orientation is computed from 3847 * application tokens. 3848 * @see android.view.IWindowManager#updateOrientationFromAppTokens( 3849 * android.os.IBinder) 3850 */ updateOrientationFromAppTokensLocked(boolean inTransaction)3851 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) { 3852 long ident = Binder.clearCallingIdentity(); 3853 try { 3854 int req = getOrientationLocked(); 3855 if (req != mLastOrientation) { 3856 mLastOrientation = req; 3857 //send a message to Policy indicating orientation change to take 3858 //action like disabling/enabling sensors etc., 3859 mPolicy.setCurrentOrientationLw(req); 3860 if (updateRotationUncheckedLocked(inTransaction)) { 3861 // changed 3862 return true; 3863 } 3864 } 3865 3866 return false; 3867 } finally { 3868 Binder.restoreCallingIdentity(ident); 3869 } 3870 } 3871 3872 // If this is true we have updated our desired orientation, but not yet 3873 // changed the real orientation our applied our screen rotation animation. 3874 // For example, because a previous screen rotation was in progress. rotationNeedsUpdateLocked()3875 boolean rotationNeedsUpdateLocked() { 3876 int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation); 3877 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 3878 mLastOrientation, rotation); 3879 if (mRotation == rotation && mAltOrientation == altOrientation) { 3880 return false; 3881 } 3882 return true; 3883 } 3884 3885 @Override setNewConfiguration(Configuration config)3886 public int[] setNewConfiguration(Configuration config) { 3887 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3888 "setNewConfiguration()")) { 3889 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3890 } 3891 3892 synchronized(mWindowMap) { 3893 if (mWaitingForConfig) { 3894 mWaitingForConfig = false; 3895 mLastFinishedFreezeSource = "new-config"; 3896 } 3897 boolean configChanged = mCurConfiguration.diff(config) != 0; 3898 if (!configChanged) { 3899 return null; 3900 } 3901 prepareFreezingAllTaskBounds(); 3902 mCurConfiguration = new Configuration(config); 3903 return onConfigurationChanged(); 3904 } 3905 } 3906 3907 @Override getBoundsForNewConfiguration(int stackId)3908 public Rect getBoundsForNewConfiguration(int stackId) { 3909 synchronized(mWindowMap) { 3910 final TaskStack stack = mStackIdToStack.get(stackId); 3911 final Rect outBounds = new Rect(); 3912 stack.getBoundsForNewConfiguration(outBounds); 3913 return outBounds; 3914 } 3915 } 3916 prepareFreezingAllTaskBounds()3917 private void prepareFreezingAllTaskBounds() { 3918 for (int i = mDisplayContents.size() - 1; i >= 0; i--) { 3919 ArrayList<TaskStack> stacks = mDisplayContents.valueAt(i).getStacks(); 3920 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 3921 final TaskStack stack = stacks.get(stackNdx); 3922 stack.prepareFreezingTaskBounds(); 3923 } 3924 } 3925 3926 } onConfigurationChanged()3927 private int[] onConfigurationChanged() { 3928 mPolicy.onConfigurationChanged(); 3929 3930 final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked(); 3931 if (!mReconfigureOnConfigurationChanged.contains(defaultDisplayContent)) { 3932 // The default display size information is heavily dependent on the resources in the 3933 // current configuration, so we need to reconfigure it everytime the configuration 3934 // changes. See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... 3935 mReconfigureOnConfigurationChanged.add(defaultDisplayContent); 3936 } 3937 for (int i = mReconfigureOnConfigurationChanged.size() - 1; i >= 0; i--) { 3938 reconfigureDisplayLocked(mReconfigureOnConfigurationChanged.remove(i)); 3939 } 3940 3941 defaultDisplayContent.getDockedDividerController().onConfigurationChanged(); 3942 mChangedStackList.clear(); 3943 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) { 3944 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 3945 if (stack.onConfigurationChanged()) { 3946 mChangedStackList.add(stack.mStackId); 3947 } 3948 } 3949 return mChangedStackList.isEmpty() ? 3950 null : ArrayUtils.convertToIntArray(mChangedStackList); 3951 } 3952 3953 @Override setAppOrientation(IApplicationToken token, int requestedOrientation)3954 public void setAppOrientation(IApplicationToken token, int requestedOrientation) { 3955 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3956 "setAppOrientation()")) { 3957 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3958 } 3959 3960 synchronized(mWindowMap) { 3961 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3962 if (atoken == null) { 3963 Slog.w(TAG_WM, "Attempted to set orientation of non-existing app token: " + token); 3964 return; 3965 } 3966 3967 atoken.requestedOrientation = requestedOrientation; 3968 } 3969 } 3970 3971 @Override getAppOrientation(IApplicationToken token)3972 public int getAppOrientation(IApplicationToken token) { 3973 synchronized(mWindowMap) { 3974 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 3975 if (wtoken == null) { 3976 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3977 } 3978 3979 return wtoken.requestedOrientation; 3980 } 3981 } 3982 setFocusTaskRegionLocked()3983 void setFocusTaskRegionLocked() { 3984 if (mFocusedApp != null) { 3985 final Task task = mFocusedApp.mTask; 3986 final DisplayContent displayContent = task.getDisplayContent(); 3987 if (displayContent != null) { 3988 displayContent.setTouchExcludeRegion(task); 3989 } 3990 } 3991 } 3992 3993 @Override setFocusedApp(IBinder token, boolean moveFocusNow)3994 public void setFocusedApp(IBinder token, boolean moveFocusNow) { 3995 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3996 "setFocusedApp()")) { 3997 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3998 } 3999 4000 synchronized(mWindowMap) { 4001 final AppWindowToken newFocus; 4002 if (token == null) { 4003 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, was " + mFocusedApp); 4004 newFocus = null; 4005 } else { 4006 newFocus = findAppWindowToken(token); 4007 if (newFocus == null) { 4008 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token); 4009 } 4010 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus 4011 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow); 4012 } 4013 4014 final boolean changed = mFocusedApp != newFocus; 4015 if (changed) { 4016 mFocusedApp = newFocus; 4017 mInputMonitor.setFocusedAppLw(newFocus); 4018 setFocusTaskRegionLocked(); 4019 } 4020 4021 if (moveFocusNow && changed) { 4022 final long origId = Binder.clearCallingIdentity(); 4023 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4024 Binder.restoreCallingIdentity(origId); 4025 } 4026 } 4027 } 4028 4029 /** 4030 * @param transit What kind of transition is happening. Use one of the constants 4031 * AppTransition.TRANSIT_*. 4032 * @param alwaysKeepCurrent If true and a transition is already set, new transition will NOT 4033 * be set. 4034 */ 4035 @Override prepareAppTransition(int transit, boolean alwaysKeepCurrent)4036 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { 4037 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4038 "prepareAppTransition()")) { 4039 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4040 } 4041 synchronized(mWindowMap) { 4042 boolean prepared = mAppTransition.prepareAppTransitionLocked( 4043 transit, alwaysKeepCurrent); 4044 if (prepared && okToDisplay()) { 4045 mSkipAppTransitionAnimation = false; 4046 } 4047 } 4048 } 4049 4050 @Override getPendingAppTransition()4051 public int getPendingAppTransition() { 4052 return mAppTransition.getAppTransition(); 4053 } 4054 4055 @Override overridePendingAppTransition(String packageName, int enterAnim, int exitAnim, IRemoteCallback startedCallback)4056 public void overridePendingAppTransition(String packageName, 4057 int enterAnim, int exitAnim, IRemoteCallback startedCallback) { 4058 synchronized(mWindowMap) { 4059 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim, 4060 startedCallback); 4061 } 4062 } 4063 4064 @Override overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, int startHeight)4065 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 4066 int startHeight) { 4067 synchronized(mWindowMap) { 4068 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth, 4069 startHeight); 4070 } 4071 } 4072 4073 @Override overridePendingAppTransitionClipReveal(int startX, int startY, int startWidth, int startHeight)4074 public void overridePendingAppTransitionClipReveal(int startX, int startY, 4075 int startWidth, int startHeight) { 4076 synchronized(mWindowMap) { 4077 mAppTransition.overridePendingAppTransitionClipReveal(startX, startY, startWidth, 4078 startHeight); 4079 } 4080 } 4081 4082 @Override overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp)4083 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, 4084 int startY, IRemoteCallback startedCallback, boolean scaleUp) { 4085 synchronized(mWindowMap) { 4086 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY, 4087 startedCallback, scaleUp); 4088 } 4089 } 4090 4091 @Override overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp)4092 public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, 4093 int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, 4094 boolean scaleUp) { 4095 synchronized(mWindowMap) { 4096 mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX, startY, 4097 targetWidth, targetHeight, startedCallback, scaleUp); 4098 } 4099 } 4100 4101 @Override overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs, IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback, boolean scaleUp)4102 public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs, 4103 IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback, 4104 boolean scaleUp) { 4105 synchronized (mWindowMap) { 4106 mAppTransition.overridePendingAppTransitionMultiThumb(specs, onAnimationStartedCallback, 4107 onAnimationFinishedCallback, scaleUp); 4108 prolongAnimationsFromSpecs(specs, scaleUp); 4109 4110 } 4111 } 4112 prolongAnimationsFromSpecs(@onNull AppTransitionAnimationSpec[] specs, boolean scaleUp)4113 void prolongAnimationsFromSpecs(@NonNull AppTransitionAnimationSpec[] specs, boolean scaleUp) { 4114 // This is used by freeform <-> recents windows transition. We need to synchronize 4115 // the animation with the appearance of the content of recents, so we will make 4116 // animation stay on the first or last frame a little longer. 4117 mTmpTaskIds.clear(); 4118 for (int i = specs.length - 1; i >= 0; i--) { 4119 mTmpTaskIds.put(specs[i].taskId, 0); 4120 } 4121 for (final WindowState win : mWindowMap.values()) { 4122 final Task task = win.getTask(); 4123 if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1 4124 && task.inFreeformWorkspace()) { 4125 final AppWindowToken appToken = win.mAppToken; 4126 if (appToken != null && appToken.mAppAnimator != null) { 4127 appToken.mAppAnimator.startProlongAnimation(scaleUp ? 4128 PROLONG_ANIMATION_AT_START : PROLONG_ANIMATION_AT_END); 4129 } 4130 } 4131 } 4132 } 4133 4134 @Override overridePendingAppTransitionInPlace(String packageName, int anim)4135 public void overridePendingAppTransitionInPlace(String packageName, int anim) { 4136 synchronized(mWindowMap) { 4137 mAppTransition.overrideInPlaceAppTransition(packageName, anim); 4138 } 4139 } 4140 4141 @Override overridePendingAppTransitionMultiThumbFuture( IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback, boolean scaleUp)4142 public void overridePendingAppTransitionMultiThumbFuture( 4143 IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback, 4144 boolean scaleUp) { 4145 synchronized(mWindowMap) { 4146 mAppTransition.overridePendingAppTransitionMultiThumbFuture(specsFuture, callback, 4147 scaleUp); 4148 } 4149 } 4150 4151 @Override endProlongedAnimations()4152 public void endProlongedAnimations() { 4153 synchronized (mWindowMap) { 4154 for (final WindowState win : mWindowMap.values()) { 4155 final AppWindowToken appToken = win.mAppToken; 4156 if (appToken != null && appToken.mAppAnimator != null) { 4157 appToken.mAppAnimator.endProlongedAnimation(); 4158 } 4159 } 4160 mAppTransition.notifyProlongedAnimationsEnded(); 4161 } 4162 } 4163 4164 @Override executeAppTransition()4165 public void executeAppTransition() { 4166 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4167 "executeAppTransition()")) { 4168 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4169 } 4170 4171 synchronized(mWindowMap) { 4172 if (DEBUG_APP_TRANSITIONS) Slog.w(TAG_WM, "Execute app transition: " + mAppTransition 4173 + " Callers=" + Debug.getCallers(5)); 4174 if (mAppTransition.isTransitionSet()) { 4175 mAppTransition.setReady(); 4176 final long origId = Binder.clearCallingIdentity(); 4177 try { 4178 mWindowPlacerLocked.performSurfacePlacement(); 4179 } finally { 4180 Binder.restoreCallingIdentity(origId); 4181 } 4182 } 4183 } 4184 } 4185 4186 @Override setAppStartingWindow(IBinder token, String pkg, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded)4187 public boolean setAppStartingWindow(IBinder token, String pkg, 4188 int theme, CompatibilityInfo compatInfo, 4189 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, 4190 int windowFlags, IBinder transferFrom, boolean createIfNeeded) { 4191 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4192 "setAppStartingWindow()")) { 4193 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4194 } 4195 4196 synchronized(mWindowMap) { 4197 if (DEBUG_STARTING_WINDOW) Slog.v( 4198 TAG_WM, "setAppStartingWindow: token=" + token + " pkg=" + pkg 4199 + " transferFrom=" + transferFrom); 4200 4201 AppWindowToken wtoken = findAppWindowToken(token); 4202 if (wtoken == null) { 4203 Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + token); 4204 return false; 4205 } 4206 4207 // If the display is frozen, we won't do anything until the 4208 // actual window is displayed so there is no reason to put in 4209 // the starting window. 4210 if (!okToDisplay()) { 4211 return false; 4212 } 4213 4214 if (wtoken.startingData != null) { 4215 return false; 4216 } 4217 4218 // If this is a translucent window, then don't 4219 // show a starting window -- the current effect (a full-screen 4220 // opaque starting window that fades away to the real contents 4221 // when it is ready) does not work for this. 4222 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Checking theme of starting window: 0x" 4223 + Integer.toHexString(theme)); 4224 if (theme != 0) { 4225 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 4226 com.android.internal.R.styleable.Window, mCurrentUserId); 4227 if (ent == null) { 4228 // Whoops! App doesn't exist. Um. Okay. We'll just 4229 // pretend like we didn't see that. 4230 return false; 4231 } 4232 final boolean windowIsTranslucent = ent.array.getBoolean( 4233 com.android.internal.R.styleable.Window_windowIsTranslucent, false); 4234 final boolean windowIsFloating = ent.array.getBoolean( 4235 com.android.internal.R.styleable.Window_windowIsFloating, false); 4236 final boolean windowShowWallpaper = ent.array.getBoolean( 4237 com.android.internal.R.styleable.Window_windowShowWallpaper, false); 4238 final boolean windowDisableStarting = ent.array.getBoolean( 4239 com.android.internal.R.styleable.Window_windowDisablePreview, false); 4240 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Translucent=" + windowIsTranslucent 4241 + " Floating=" + windowIsFloating 4242 + " ShowWallpaper=" + windowShowWallpaper); 4243 if (windowIsTranslucent) { 4244 return false; 4245 } 4246 if (windowIsFloating || windowDisableStarting) { 4247 return false; 4248 } 4249 if (windowShowWallpaper) { 4250 if (mWallpaperControllerLocked.getWallpaperTarget() == null) { 4251 // If this theme is requesting a wallpaper, and the wallpaper 4252 // is not currently visible, then this effectively serves as 4253 // an opaque window and our starting window transition animation 4254 // can still work. We just need to make sure the starting window 4255 // is also showing the wallpaper. 4256 windowFlags |= FLAG_SHOW_WALLPAPER; 4257 } else { 4258 return false; 4259 } 4260 } 4261 } 4262 4263 if (transferStartingWindow(transferFrom, wtoken)) { 4264 return true; 4265 } 4266 4267 // There is no existing starting window, and the caller doesn't 4268 // want us to create one, so that's it! 4269 if (!createIfNeeded) { 4270 return false; 4271 } 4272 4273 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData"); 4274 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, 4275 labelRes, icon, logo, windowFlags); 4276 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4277 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4278 // want to process the message ASAP, before any other queued 4279 // messages. 4280 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING"); 4281 mH.sendMessageAtFrontOfQueue(m); 4282 } 4283 return true; 4284 } 4285 transferStartingWindow(IBinder transferFrom, AppWindowToken wtoken)4286 private boolean transferStartingWindow(IBinder transferFrom, AppWindowToken wtoken) { 4287 if (transferFrom == null) { 4288 return false; 4289 } 4290 AppWindowToken ttoken = findAppWindowToken(transferFrom); 4291 if (ttoken == null) { 4292 return false; 4293 } 4294 WindowState startingWindow = ttoken.startingWindow; 4295 if (startingWindow != null && ttoken.startingView != null) { 4296 // In this case, the starting icon has already been displayed, so start 4297 // letting windows get shown immediately without any more transitions. 4298 mSkipAppTransitionAnimation = true; 4299 4300 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, 4301 "Moving existing starting " + startingWindow + " from " + ttoken 4302 + " to " + wtoken); 4303 final long origId = Binder.clearCallingIdentity(); 4304 4305 // Transfer the starting window over to the new token. 4306 wtoken.startingData = ttoken.startingData; 4307 wtoken.startingView = ttoken.startingView; 4308 wtoken.startingDisplayed = ttoken.startingDisplayed; 4309 ttoken.startingDisplayed = false; 4310 wtoken.startingWindow = startingWindow; 4311 wtoken.reportedVisible = ttoken.reportedVisible; 4312 ttoken.startingData = null; 4313 ttoken.startingView = null; 4314 ttoken.startingWindow = null; 4315 ttoken.startingMoved = true; 4316 startingWindow.mToken = wtoken; 4317 startingWindow.mRootToken = wtoken; 4318 startingWindow.mAppToken = wtoken; 4319 4320 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { 4321 Slog.v(TAG_WM, "Removing starting window: " + startingWindow); 4322 } 4323 startingWindow.getWindowList().remove(startingWindow); 4324 mWindowsChanged = true; 4325 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 4326 "Removing starting " + startingWindow + " from " + ttoken); 4327 ttoken.windows.remove(startingWindow); 4328 ttoken.allAppWindows.remove(startingWindow); 4329 addWindowToListInOrderLocked(startingWindow, true); 4330 4331 // Propagate other interesting state between the 4332 // tokens. If the old token is displayed, we should 4333 // immediately force the new one to be displayed. If 4334 // it is animating, we need to move that animation to 4335 // the new one. 4336 if (ttoken.allDrawn) { 4337 wtoken.allDrawn = true; 4338 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn; 4339 } 4340 if (ttoken.firstWindowDrawn) { 4341 wtoken.firstWindowDrawn = true; 4342 } 4343 if (!ttoken.hidden) { 4344 wtoken.hidden = false; 4345 wtoken.hiddenRequested = false; 4346 } 4347 if (wtoken.clientHidden != ttoken.clientHidden) { 4348 wtoken.clientHidden = ttoken.clientHidden; 4349 wtoken.sendAppVisibilityToClients(); 4350 } 4351 ttoken.mAppAnimator.transferCurrentAnimation( 4352 wtoken.mAppAnimator, startingWindow.mWinAnimator); 4353 4354 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4355 true /*updateInputWindows*/); 4356 getDefaultDisplayContentLocked().layoutNeeded = true; 4357 mWindowPlacerLocked.performSurfacePlacement(); 4358 Binder.restoreCallingIdentity(origId); 4359 return true; 4360 } else if (ttoken.startingData != null) { 4361 // The previous app was getting ready to show a 4362 // starting window, but hasn't yet done so. Steal it! 4363 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving pending starting from " + ttoken 4364 + " to " + wtoken); 4365 wtoken.startingData = ttoken.startingData; 4366 ttoken.startingData = null; 4367 ttoken.startingMoved = true; 4368 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4369 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4370 // want to process the message ASAP, before any other queued 4371 // messages. 4372 mH.sendMessageAtFrontOfQueue(m); 4373 return true; 4374 } 4375 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4376 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4377 if (tAppAnimator.thumbnail != null) { 4378 // The old token is animating with a thumbnail, transfer that to the new token. 4379 if (wAppAnimator.thumbnail != null) { 4380 wAppAnimator.thumbnail.destroy(); 4381 } 4382 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 4383 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 4384 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 4385 tAppAnimator.thumbnail = null; 4386 } 4387 return false; 4388 } 4389 removeAppStartingWindow(IBinder token)4390 public void removeAppStartingWindow(IBinder token) { 4391 synchronized (mWindowMap) { 4392 final AppWindowToken wtoken = mTokenMap.get(token).appWindowToken; 4393 scheduleRemoveStartingWindowLocked(wtoken); 4394 } 4395 } 4396 setAppFullscreen(IBinder token, boolean toOpaque)4397 public void setAppFullscreen(IBinder token, boolean toOpaque) { 4398 synchronized (mWindowMap) { 4399 AppWindowToken atoken = findAppWindowToken(token); 4400 if (atoken != null) { 4401 atoken.appFullscreen = toOpaque; 4402 setWindowOpaqueLocked(token, toOpaque); 4403 mWindowPlacerLocked.requestTraversal(); 4404 } 4405 } 4406 } 4407 setWindowOpaque(IBinder token, boolean isOpaque)4408 public void setWindowOpaque(IBinder token, boolean isOpaque) { 4409 synchronized (mWindowMap) { 4410 setWindowOpaqueLocked(token, isOpaque); 4411 } 4412 } 4413 setWindowOpaqueLocked(IBinder token, boolean isOpaque)4414 public void setWindowOpaqueLocked(IBinder token, boolean isOpaque) { 4415 AppWindowToken wtoken = findAppWindowToken(token); 4416 if (wtoken != null) { 4417 WindowState win = wtoken.findMainWindow(); 4418 if (win != null) { 4419 win.mWinAnimator.setOpaqueLocked(isOpaque); 4420 } 4421 } 4422 } 4423 setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction)4424 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4425 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { 4426 boolean delayed = false; 4427 4428 if (wtoken.clientHidden == visible) { 4429 wtoken.clientHidden = !visible; 4430 wtoken.sendAppVisibilityToClients(); 4431 } 4432 4433 // Allow for state changes and animation to be applied if: 4434 // * token is transitioning visibility state 4435 // * or the token was marked as hidden and is exiting before we had a chance to play the 4436 // transition animation 4437 // * or this is an opening app and windows are being replaced. 4438 boolean visibilityChanged = false; 4439 if (wtoken.hidden == visible || (wtoken.hidden && wtoken.mIsExiting) || 4440 (visible && wtoken.waitingForReplacement())) { 4441 boolean changed = false; 4442 if (DEBUG_APP_TRANSITIONS) Slog.v( 4443 TAG_WM, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4444 + " performLayout=" + performLayout); 4445 4446 boolean runningAppAnimation = false; 4447 4448 if (transit != AppTransition.TRANSIT_UNSET) { 4449 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4450 wtoken.mAppAnimator.setNullAnimation(); 4451 } 4452 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) { 4453 delayed = runningAppAnimation = true; 4454 } 4455 WindowState window = wtoken.findMainWindow(); 4456 //TODO (multidisplay): Magnification is supported only for the default display. 4457 if (window != null && mAccessibilityController != null 4458 && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 4459 mAccessibilityController.onAppWindowTransitionLocked(window, transit); 4460 } 4461 changed = true; 4462 } 4463 4464 final int windowsCount = wtoken.allAppWindows.size(); 4465 for (int i = 0; i < windowsCount; i++) { 4466 WindowState win = wtoken.allAppWindows.get(i); 4467 if (win == wtoken.startingWindow) { 4468 // Starting window that's exiting will be removed when the animation 4469 // finishes. Mark all relevant flags for that finishExit will proceed 4470 // all the way to actually remove it. 4471 if (!visible && win.isVisibleNow() && wtoken.mAppAnimator.isAnimating()) { 4472 win.mAnimatingExit = true; 4473 win.mRemoveOnExit = true; 4474 win.mWindowRemovalAllowed = true; 4475 } 4476 continue; 4477 } 4478 4479 //Slog.i(TAG_WM, "Window " + win + ": vis=" + win.isVisible()); 4480 //win.dump(" "); 4481 if (visible) { 4482 if (!win.isVisibleNow()) { 4483 if (!runningAppAnimation) { 4484 win.mWinAnimator.applyAnimationLocked( 4485 WindowManagerPolicy.TRANSIT_ENTER, true); 4486 //TODO (multidisplay): Magnification is supported only for the default 4487 if (mAccessibilityController != null 4488 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4489 mAccessibilityController.onWindowTransitionLocked(win, 4490 WindowManagerPolicy.TRANSIT_ENTER); 4491 } 4492 } 4493 changed = true; 4494 win.setDisplayLayoutNeeded(); 4495 } 4496 } else if (win.isVisibleNow()) { 4497 if (!runningAppAnimation) { 4498 win.mWinAnimator.applyAnimationLocked( 4499 WindowManagerPolicy.TRANSIT_EXIT, false); 4500 //TODO (multidisplay): Magnification is supported only for the default 4501 if (mAccessibilityController != null 4502 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4503 mAccessibilityController.onWindowTransitionLocked(win, 4504 WindowManagerPolicy.TRANSIT_EXIT); 4505 } 4506 } 4507 changed = true; 4508 win.setDisplayLayoutNeeded(); 4509 } 4510 } 4511 4512 wtoken.hidden = wtoken.hiddenRequested = !visible; 4513 visibilityChanged = true; 4514 if (!visible) { 4515 unsetAppFreezingScreenLocked(wtoken, true, true); 4516 } else { 4517 // If we are being set visible, and the starting window is 4518 // not yet displayed, then make sure it doesn't get displayed. 4519 WindowState swin = wtoken.startingWindow; 4520 if (swin != null && !swin.isDrawnLw()) { 4521 swin.mPolicyVisibility = false; 4522 swin.mPolicyVisibilityAfterAnim = false; 4523 } 4524 } 4525 4526 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setTokenVisibilityLocked: " + wtoken 4527 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4528 + wtoken.hiddenRequested); 4529 4530 if (changed) { 4531 mInputMonitor.setUpdateInputWindowsNeededLw(); 4532 if (performLayout) { 4533 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4534 false /*updateInputWindows*/); 4535 mWindowPlacerLocked.performSurfacePlacement(); 4536 } 4537 mInputMonitor.updateInputWindowsLw(false /*force*/); 4538 } 4539 } 4540 4541 if (wtoken.mAppAnimator.animation != null) { 4542 delayed = true; 4543 } 4544 4545 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4546 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimationSet()) { 4547 delayed = true; 4548 } 4549 } 4550 4551 if (visibilityChanged) { 4552 if (visible && !delayed) { 4553 // The token was made immediately visible, there will be no entrance animation. 4554 // We need to inform the client the enter animation was finished. 4555 wtoken.mEnteringAnimation = true; 4556 mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(wtoken.token); 4557 } 4558 4559 if (!mClosingApps.contains(wtoken) && !mOpeningApps.contains(wtoken)) { 4560 // The token is not closing nor opening, so even if there is an animation set, that 4561 // doesn't mean that it goes through the normal app transition cycle so we have 4562 // to inform the docked controller about visibility change. 4563 getDefaultDisplayContentLocked().getDockedDividerController() 4564 .notifyAppVisibilityChanged(); 4565 } 4566 } 4567 4568 return delayed; 4569 } 4570 updateTokenInPlaceLocked(AppWindowToken wtoken, int transit)4571 void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) { 4572 if (transit != AppTransition.TRANSIT_UNSET) { 4573 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4574 wtoken.mAppAnimator.setNullAnimation(); 4575 } 4576 applyAnimationLocked(wtoken, null, transit, false, false); 4577 } 4578 } 4579 4580 @Override notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface)4581 public void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface) { 4582 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4583 "notifyAppResumed()")) { 4584 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4585 } 4586 4587 synchronized(mWindowMap) { 4588 final AppWindowToken wtoken; 4589 wtoken = findAppWindowToken(token); 4590 if (wtoken == null) { 4591 Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + token); 4592 return; 4593 } 4594 wtoken.notifyAppResumed(wasStopped, allowSavedSurface); 4595 } 4596 } 4597 4598 @Override notifyAppStopped(IBinder token)4599 public void notifyAppStopped(IBinder token) { 4600 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4601 "notifyAppStopped()")) { 4602 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4603 } 4604 4605 synchronized(mWindowMap) { 4606 final AppWindowToken wtoken; 4607 wtoken = findAppWindowToken(token); 4608 if (wtoken == null) { 4609 Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: " + token); 4610 return; 4611 } 4612 wtoken.notifyAppStopped(); 4613 } 4614 } 4615 4616 @Override setAppVisibility(IBinder token, boolean visible)4617 public void setAppVisibility(IBinder token, boolean visible) { 4618 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4619 "setAppVisibility()")) { 4620 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4621 } 4622 4623 AppWindowToken wtoken; 4624 4625 synchronized(mWindowMap) { 4626 wtoken = findAppWindowToken(token); 4627 if (wtoken == null) { 4628 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token); 4629 return; 4630 } 4631 4632 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility(" + 4633 token + ", visible=" + visible + "): " + mAppTransition + 4634 " hidden=" + wtoken.hidden + " hiddenRequested=" + 4635 wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6)); 4636 4637 mOpeningApps.remove(wtoken); 4638 mClosingApps.remove(wtoken); 4639 wtoken.waitingToShow = false; 4640 wtoken.hiddenRequested = !visible; 4641 4642 if (!visible) { 4643 // If the app is dead while it was visible, we kept its dead window on screen. 4644 // Now that the app is going invisible, we can remove it. It will be restarted 4645 // if made visible again. 4646 wtoken.removeAllDeadWindows(); 4647 wtoken.setVisibleBeforeClientHidden(); 4648 } else if (visible) { 4649 if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) { 4650 // Add the app mOpeningApps if transition is unset but ready. This means 4651 // we're doing a screen freeze, and the unfreeze will wait for all opening 4652 // apps to be ready. 4653 mOpeningApps.add(wtoken); 4654 } 4655 wtoken.startingMoved = false; 4656 // If the token is currently hidden (should be the common case), or has been 4657 // stopped, then we need to set up to wait for its windows to be ready. 4658 if (wtoken.hidden || wtoken.mAppStopped) { 4659 wtoken.clearAllDrawn(); 4660 4661 // If the app was already visible, don't reset the waitingToShow state. 4662 if (wtoken.hidden) { 4663 wtoken.waitingToShow = true; 4664 } 4665 4666 if (wtoken.clientHidden) { 4667 // In the case where we are making an app visible 4668 // but holding off for a transition, we still need 4669 // to tell the client to make its windows visible so 4670 // they get drawn. Otherwise, we will wait on 4671 // performing the transition until all windows have 4672 // been drawn, they never will be, and we are sad. 4673 wtoken.clientHidden = false; 4674 wtoken.sendAppVisibilityToClients(); 4675 } 4676 } 4677 wtoken.requestUpdateWallpaperIfNeeded(); 4678 4679 if (DEBUG_ADD_REMOVE) Slog.v( 4680 TAG_WM, "No longer Stopped: " + wtoken); 4681 wtoken.mAppStopped = false; 4682 } 4683 4684 // If we are preparing an app transition, then delay changing 4685 // the visibility of this token until we execute that transition. 4686 if (okToDisplay() && mAppTransition.isTransitionSet()) { 4687 // A dummy animation is a placeholder animation which informs others that an 4688 // animation is going on (in this case an application transition). If the animation 4689 // was transferred from another application/animator, no dummy animator should be 4690 // created since an animation is already in progress. 4691 if (wtoken.mAppAnimator.usingTransferredAnimation 4692 && wtoken.mAppAnimator.animation == null) { 4693 Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken 4694 + ", using null transfered animation!"); 4695 } 4696 if (!wtoken.mAppAnimator.usingTransferredAnimation && 4697 (!wtoken.startingDisplayed || mSkipAppTransitionAnimation)) { 4698 if (DEBUG_APP_TRANSITIONS) Slog.v( 4699 TAG_WM, "Setting dummy animation on: " + wtoken); 4700 wtoken.mAppAnimator.setDummyAnimation(); 4701 } 4702 wtoken.inPendingTransaction = true; 4703 if (visible) { 4704 mOpeningApps.add(wtoken); 4705 wtoken.mEnteringAnimation = true; 4706 } else { 4707 mClosingApps.add(wtoken); 4708 wtoken.mEnteringAnimation = false; 4709 } 4710 if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) { 4711 // We're launchingBehind, add the launching activity to mOpeningApps. 4712 final WindowState win = 4713 findFocusedWindowLocked(getDefaultDisplayContentLocked()); 4714 if (win != null) { 4715 final AppWindowToken focusedToken = win.mAppToken; 4716 if (focusedToken != null) { 4717 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, " + 4718 " adding " + focusedToken + " to mOpeningApps"); 4719 // Force animation to be loaded. 4720 focusedToken.hidden = true; 4721 mOpeningApps.add(focusedToken); 4722 } 4723 } 4724 } 4725 return; 4726 } 4727 4728 final long origId = Binder.clearCallingIdentity(); 4729 wtoken.inPendingTransaction = false; 4730 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET, 4731 true, wtoken.voiceInteraction); 4732 wtoken.updateReportedVisibilityLocked(); 4733 Binder.restoreCallingIdentity(origId); 4734 } 4735 } 4736 unsetAppFreezingScreenLocked(AppWindowToken wtoken, boolean unfreezeSurfaceNow, boolean force)4737 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4738 boolean unfreezeSurfaceNow, boolean force) { 4739 if (wtoken.mAppAnimator.freezingScreen) { 4740 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + wtoken 4741 + " force=" + force); 4742 final int N = wtoken.allAppWindows.size(); 4743 boolean unfrozeWindows = false; 4744 for (int i=0; i<N; i++) { 4745 WindowState w = wtoken.allAppWindows.get(i); 4746 if (w.mAppFreezing) { 4747 w.mAppFreezing = false; 4748 if (w.mHasSurface && !w.mOrientationChanging 4749 && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { 4750 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + w); 4751 w.mOrientationChanging = true; 4752 mWindowPlacerLocked.mOrientationChangeComplete = false; 4753 } 4754 w.mLastFreezeDuration = 0; 4755 unfrozeWindows = true; 4756 w.setDisplayLayoutNeeded(); 4757 } 4758 } 4759 if (force || unfrozeWindows) { 4760 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + wtoken); 4761 wtoken.mAppAnimator.freezingScreen = false; 4762 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime() 4763 - mDisplayFreezeTime); 4764 mAppsFreezingScreen--; 4765 mLastFinishedFreezeSource = wtoken; 4766 } 4767 if (unfreezeSurfaceNow) { 4768 if (unfrozeWindows) { 4769 mWindowPlacerLocked.performSurfacePlacement(); 4770 } 4771 stopFreezingDisplayLocked(); 4772 } 4773 } 4774 } 4775 startAppFreezingScreenLocked(AppWindowToken wtoken)4776 private void startAppFreezingScreenLocked(AppWindowToken wtoken) { 4777 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + wtoken.appToken + ": hidden=" 4778 + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4779 if (!wtoken.hiddenRequested) { 4780 if (!wtoken.mAppAnimator.freezingScreen) { 4781 wtoken.mAppAnimator.freezingScreen = true; 4782 wtoken.mAppAnimator.lastFreezeDuration = 0; 4783 mAppsFreezingScreen++; 4784 if (mAppsFreezingScreen == 1) { 4785 startFreezingDisplayLocked(false, 0, 0); 4786 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4787 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000); 4788 } 4789 } 4790 final int N = wtoken.allAppWindows.size(); 4791 for (int i=0; i<N; i++) { 4792 WindowState w = wtoken.allAppWindows.get(i); 4793 w.mAppFreezing = true; 4794 } 4795 } 4796 } 4797 4798 @Override startAppFreezingScreen(IBinder token, int configChanges)4799 public void startAppFreezingScreen(IBinder token, int configChanges) { 4800 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4801 "setAppFreezingScreen()")) { 4802 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4803 } 4804 4805 synchronized(mWindowMap) { 4806 if (configChanges == 0 && okToDisplay()) { 4807 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + token); 4808 return; 4809 } 4810 4811 AppWindowToken wtoken = findAppWindowToken(token); 4812 if (wtoken == null || wtoken.appToken == null) { 4813 Slog.w(TAG_WM, "Attempted to freeze screen with non-existing app token: " + wtoken); 4814 return; 4815 } 4816 final long origId = Binder.clearCallingIdentity(); 4817 startAppFreezingScreenLocked(wtoken); 4818 Binder.restoreCallingIdentity(origId); 4819 } 4820 } 4821 4822 @Override stopAppFreezingScreen(IBinder token, boolean force)4823 public void stopAppFreezingScreen(IBinder token, boolean force) { 4824 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4825 "setAppFreezingScreen()")) { 4826 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4827 } 4828 4829 synchronized(mWindowMap) { 4830 AppWindowToken wtoken = findAppWindowToken(token); 4831 if (wtoken == null || wtoken.appToken == null) { 4832 return; 4833 } 4834 final long origId = Binder.clearCallingIdentity(); 4835 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + token 4836 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4837 unsetAppFreezingScreenLocked(wtoken, true, force); 4838 Binder.restoreCallingIdentity(origId); 4839 } 4840 } 4841 4842 @Override removeAppToken(IBinder token)4843 public void removeAppToken(IBinder token) { 4844 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4845 "removeAppToken()")) { 4846 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4847 } 4848 4849 AppWindowToken wtoken = null; 4850 AppWindowToken startingToken = null; 4851 boolean delayed = false; 4852 4853 final long origId = Binder.clearCallingIdentity(); 4854 synchronized(mWindowMap) { 4855 WindowToken basewtoken = mTokenMap.remove(token); 4856 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4857 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + wtoken); 4858 delayed = setTokenVisibilityLocked(wtoken, null, false, 4859 AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction); 4860 wtoken.inPendingTransaction = false; 4861 mOpeningApps.remove(wtoken); 4862 wtoken.waitingToShow = false; 4863 if (mClosingApps.contains(wtoken)) { 4864 delayed = true; 4865 } else if (mAppTransition.isTransitionSet()) { 4866 mClosingApps.add(wtoken); 4867 delayed = true; 4868 } 4869 if (DEBUG_APP_TRANSITIONS) Slog.v( 4870 TAG_WM, "Removing app " + wtoken + " delayed=" + delayed 4871 + " animation=" + wtoken.mAppAnimator.animation 4872 + " animating=" + wtoken.mAppAnimator.animating); 4873 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: " 4874 + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); 4875 final TaskStack stack = wtoken.mTask.mStack; 4876 if (delayed && !wtoken.allAppWindows.isEmpty()) { 4877 // set the token aside because it has an active animation to be finished 4878 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, 4879 "removeAppToken make exiting: " + wtoken); 4880 stack.mExitingAppTokens.add(wtoken); 4881 wtoken.mIsExiting = true; 4882 } else { 4883 // Make sure there is no animation running on this token, 4884 // so any windows associated with it will be removed as 4885 // soon as their animations are complete 4886 wtoken.mAppAnimator.clearAnimation(); 4887 wtoken.mAppAnimator.animating = false; 4888 wtoken.removeAppFromTaskLocked(); 4889 } 4890 4891 wtoken.removed = true; 4892 if (wtoken.startingData != null) { 4893 startingToken = wtoken; 4894 } 4895 unsetAppFreezingScreenLocked(wtoken, true, true); 4896 if (mFocusedApp == wtoken) { 4897 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + wtoken); 4898 mFocusedApp = null; 4899 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4900 mInputMonitor.setFocusedAppLw(null); 4901 } 4902 } else { 4903 Slog.w(TAG_WM, "Attempted to remove non-existing app token: " + token); 4904 } 4905 4906 if (!delayed && wtoken != null) { 4907 wtoken.updateReportedVisibilityLocked(); 4908 } 4909 4910 // Will only remove if startingToken non null. 4911 scheduleRemoveStartingWindowLocked(startingToken); 4912 } 4913 Binder.restoreCallingIdentity(origId); 4914 4915 } 4916 scheduleRemoveStartingWindowLocked(AppWindowToken wtoken)4917 void scheduleRemoveStartingWindowLocked(AppWindowToken wtoken) { 4918 if (wtoken == null) { 4919 return; 4920 } 4921 if (mH.hasMessages(H.REMOVE_STARTING, wtoken)) { 4922 // Already scheduled. 4923 return; 4924 } 4925 4926 if (wtoken.startingWindow == null) { 4927 if (wtoken.startingData != null) { 4928 // Starting window has not been added yet, but it is scheduled to be added. 4929 // Go ahead and cancel the request. 4930 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, 4931 "Clearing startingData for token=" + wtoken); 4932 wtoken.startingData = null; 4933 } 4934 return; 4935 } 4936 4937 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1) + 4938 ": Schedule remove starting " + wtoken + (wtoken != null ? 4939 " startingWindow=" + wtoken.startingWindow : "")); 4940 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken); 4941 mH.sendMessage(m); 4942 } 4943 dumpAppTokensLocked()4944 void dumpAppTokensLocked() { 4945 final int numStacks = mStackIdToStack.size(); 4946 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 4947 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 4948 Slog.v(TAG_WM, " Stack #" + stack.mStackId + " tasks from bottom to top:"); 4949 final ArrayList<Task> tasks = stack.getTasks(); 4950 final int numTasks = tasks.size(); 4951 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4952 final Task task = tasks.get(taskNdx); 4953 Slog.v(TAG_WM, " Task #" + task.mTaskId + " activities from bottom to top:"); 4954 AppTokenList tokens = task.mAppTokens; 4955 final int numTokens = tokens.size(); 4956 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4957 Slog.v(TAG_WM, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token); 4958 } 4959 } 4960 } 4961 } 4962 dumpWindowsLocked()4963 void dumpWindowsLocked() { 4964 final int numDisplays = mDisplayContents.size(); 4965 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4966 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4967 Slog.v(TAG_WM, " Display #" + displayContent.getDisplayId()); 4968 final WindowList windows = displayContent.getWindowList(); 4969 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4970 Slog.v(TAG_WM, " #" + winNdx + ": " + windows.get(winNdx)); 4971 } 4972 } 4973 } 4974 reAddWindowLocked(int index, WindowState win)4975 private final int reAddWindowLocked(int index, WindowState win) { 4976 final WindowList windows = win.getWindowList(); 4977 // Adding child windows relies on mChildWindows being ordered by mSubLayer. 4978 final int NCW = win.mChildWindows.size(); 4979 boolean winAdded = false; 4980 for (int j=0; j<NCW; j++) { 4981 WindowState cwin = win.mChildWindows.get(j); 4982 if (!winAdded && cwin.mSubLayer >= 0) { 4983 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding child window at " 4984 + index + ": " + cwin); 4985 win.mRebuilding = false; 4986 windows.add(index, win); 4987 index++; 4988 winAdded = true; 4989 } 4990 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at " 4991 + index + ": " + cwin); 4992 cwin.mRebuilding = false; 4993 windows.add(index, cwin); 4994 index++; 4995 } 4996 if (!winAdded) { 4997 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at " 4998 + index + ": " + win); 4999 win.mRebuilding = false; 5000 windows.add(index, win); 5001 index++; 5002 } 5003 mWindowsChanged = true; 5004 return index; 5005 } 5006 reAddAppWindowsLocked(final DisplayContent displayContent, int index, WindowToken token)5007 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index, 5008 WindowToken token) { 5009 final int NW = token.windows.size(); 5010 for (int i=0; i<NW; i++) { 5011 final WindowState win = token.windows.get(i); 5012 final DisplayContent winDisplayContent = win.getDisplayContent(); 5013 if (winDisplayContent == displayContent || winDisplayContent == null) { 5014 win.mDisplayContent = displayContent; 5015 index = reAddWindowLocked(index, win); 5016 } 5017 } 5018 return index; 5019 } 5020 5021 moveStackWindowsLocked(DisplayContent displayContent)5022 void moveStackWindowsLocked(DisplayContent displayContent) { 5023 final WindowList windows = displayContent.getWindowList(); 5024 mTmpWindows.addAll(windows); 5025 5026 rebuildAppWindowListLocked(displayContent); 5027 5028 // Set displayContent.layoutNeeded if window order changed. 5029 final int tmpSize = mTmpWindows.size(); 5030 final int winSize = windows.size(); 5031 int tmpNdx = 0, winNdx = 0; 5032 while (tmpNdx < tmpSize && winNdx < winSize) { 5033 // Skip over all exiting windows, they've been moved out of order. 5034 WindowState tmp; 5035 do { 5036 tmp = mTmpWindows.get(tmpNdx++); 5037 } while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting); 5038 5039 WindowState win; 5040 do { 5041 win = windows.get(winNdx++); 5042 } while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting); 5043 5044 if (tmp != win) { 5045 // Window order changed. 5046 displayContent.layoutNeeded = true; 5047 break; 5048 } 5049 } 5050 if (tmpNdx != winNdx) { 5051 // One list was different from the other. 5052 displayContent.layoutNeeded = true; 5053 } 5054 mTmpWindows.clear(); 5055 5056 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 5057 false /*updateInputWindows*/)) { 5058 mLayersController.assignLayersLocked(displayContent.getWindowList()); 5059 } 5060 5061 mInputMonitor.setUpdateInputWindowsNeededLw(); 5062 mWindowPlacerLocked.performSurfacePlacement(); 5063 mInputMonitor.updateInputWindowsLw(false /*force*/); 5064 //dump(); 5065 } 5066 moveTaskToTop(int taskId)5067 public void moveTaskToTop(int taskId) { 5068 final long origId = Binder.clearCallingIdentity(); 5069 try { 5070 synchronized(mWindowMap) { 5071 Task task = mTaskIdToTask.get(taskId); 5072 if (task == null) { 5073 // Normal behavior, addAppToken will be called next and task will be created. 5074 return; 5075 } 5076 final TaskStack stack = task.mStack; 5077 final DisplayContent displayContent = task.getDisplayContent(); 5078 displayContent.moveStack(stack, true); 5079 if (displayContent.isDefaultDisplay) { 5080 final TaskStack homeStack = displayContent.getHomeStack(); 5081 if (homeStack != stack) { 5082 // When a non-home stack moves to the top, the home stack moves to the 5083 // bottom. 5084 displayContent.moveStack(homeStack, false); 5085 } 5086 } 5087 stack.moveTaskToTop(task); 5088 if (mAppTransition.isTransitionSet()) { 5089 task.setSendingToBottom(false); 5090 } 5091 moveStackWindowsLocked(displayContent); 5092 } 5093 } finally { 5094 Binder.restoreCallingIdentity(origId); 5095 } 5096 } 5097 moveTaskToBottom(int taskId)5098 public void moveTaskToBottom(int taskId) { 5099 final long origId = Binder.clearCallingIdentity(); 5100 try { 5101 synchronized(mWindowMap) { 5102 Task task = mTaskIdToTask.get(taskId); 5103 if (task == null) { 5104 Slog.e(TAG_WM, "moveTaskToBottom: taskId=" + taskId 5105 + " not found in mTaskIdToTask"); 5106 return; 5107 } 5108 final TaskStack stack = task.mStack; 5109 stack.moveTaskToBottom(task); 5110 if (mAppTransition.isTransitionSet()) { 5111 task.setSendingToBottom(true); 5112 } 5113 moveStackWindowsLocked(stack.getDisplayContent()); 5114 } 5115 } finally { 5116 Binder.restoreCallingIdentity(origId); 5117 } 5118 } 5119 isStackVisibleLocked(int stackId)5120 boolean isStackVisibleLocked(int stackId) { 5121 final TaskStack stack = mStackIdToStack.get(stackId); 5122 return (stack != null && stack.isVisibleLocked()); 5123 } 5124 setDockedStackCreateState(int mode, Rect bounds)5125 public void setDockedStackCreateState(int mode, Rect bounds) { 5126 synchronized (mWindowMap) { 5127 setDockedStackCreateStateLocked(mode, bounds); 5128 } 5129 } 5130 setDockedStackCreateStateLocked(int mode, Rect bounds)5131 void setDockedStackCreateStateLocked(int mode, Rect bounds) { 5132 mDockedStackCreateMode = mode; 5133 mDockedStackCreateBounds = bounds; 5134 } 5135 5136 /** 5137 * Create a new TaskStack and place it on a DisplayContent. 5138 * @param stackId The unique identifier of the new stack. 5139 * @param displayId The unique identifier of the DisplayContent. 5140 * @param onTop If true the stack will be place at the top of the display, 5141 * else at the bottom 5142 * @return The initial bounds the stack was created with. null means fullscreen. 5143 */ attachStack(int stackId, int displayId, boolean onTop)5144 public Rect attachStack(int stackId, int displayId, boolean onTop) { 5145 final long origId = Binder.clearCallingIdentity(); 5146 try { 5147 synchronized (mWindowMap) { 5148 final DisplayContent displayContent = mDisplayContents.get(displayId); 5149 boolean attachedToDisplay = false; 5150 if (displayContent != null) { 5151 TaskStack stack = mStackIdToStack.get(stackId); 5152 if (stack == null) { 5153 if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId); 5154 5155 stack = displayContent.getStackById(stackId); 5156 if (stack != null) { 5157 // It's already attached to the display. Detach and re-attach 5158 // because onTop might change, and be sure to clear mDeferDetach! 5159 displayContent.detachStack(stack); 5160 stack.mDeferDetach = false; 5161 attachedToDisplay = true; 5162 } else { 5163 stack = new TaskStack(this, stackId); 5164 } 5165 5166 mStackIdToStack.put(stackId, stack); 5167 if (stackId == DOCKED_STACK_ID) { 5168 getDefaultDisplayContentLocked().mDividerControllerLocked 5169 .notifyDockedStackExistsChanged(true); 5170 } 5171 } 5172 if (!attachedToDisplay) { 5173 stack.attachDisplayContent(displayContent); 5174 } 5175 displayContent.attachStack(stack, onTop); 5176 if (stack.getRawFullscreen()) { 5177 return null; 5178 } 5179 Rect bounds = new Rect(); 5180 stack.getRawBounds(bounds); 5181 return bounds; 5182 } 5183 } 5184 } finally { 5185 Binder.restoreCallingIdentity(origId); 5186 } 5187 return null; 5188 } 5189 detachStackLocked(DisplayContent displayContent, TaskStack stack)5190 void detachStackLocked(DisplayContent displayContent, TaskStack stack) { 5191 displayContent.detachStack(stack); 5192 stack.detachDisplay(); 5193 if (stack.mStackId == DOCKED_STACK_ID) { 5194 getDefaultDisplayContentLocked().mDividerControllerLocked 5195 .notifyDockedStackExistsChanged(false); 5196 } 5197 } 5198 detachStack(int stackId)5199 public void detachStack(int stackId) { 5200 synchronized (mWindowMap) { 5201 TaskStack stack = mStackIdToStack.get(stackId); 5202 if (stack != null) { 5203 final DisplayContent displayContent = stack.getDisplayContent(); 5204 if (displayContent != null) { 5205 if (stack.isAnimating()) { 5206 stack.mDeferDetach = true; 5207 return; 5208 } 5209 detachStackLocked(displayContent, stack); 5210 } 5211 } 5212 } 5213 } 5214 removeStack(int stackId)5215 public void removeStack(int stackId) { 5216 synchronized (mWindowMap) { 5217 mStackIdToStack.remove(stackId); 5218 } 5219 } 5220 removeTask(int taskId)5221 public void removeTask(int taskId) { 5222 synchronized (mWindowMap) { 5223 Task task = mTaskIdToTask.get(taskId); 5224 if (task == null) { 5225 if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + taskId); 5226 return; 5227 } 5228 task.removeLocked(); 5229 } 5230 } 5231 5232 @Override cancelTaskWindowTransition(int taskId)5233 public void cancelTaskWindowTransition(int taskId) { 5234 synchronized (mWindowMap) { 5235 Task task = mTaskIdToTask.get(taskId); 5236 if (task != null) { 5237 task.cancelTaskWindowTransition(); 5238 } 5239 } 5240 } 5241 5242 @Override cancelTaskThumbnailTransition(int taskId)5243 public void cancelTaskThumbnailTransition(int taskId) { 5244 synchronized (mWindowMap) { 5245 Task task = mTaskIdToTask.get(taskId); 5246 if (task != null) { 5247 task.cancelTaskThumbnailTransition(); 5248 } 5249 } 5250 } 5251 addTask(int taskId, int stackId, boolean toTop)5252 public void addTask(int taskId, int stackId, boolean toTop) { 5253 synchronized (mWindowMap) { 5254 if (DEBUG_STACK) Slog.i(TAG_WM, "addTask: adding taskId=" + taskId 5255 + " to " + (toTop ? "top" : "bottom")); 5256 Task task = mTaskIdToTask.get(taskId); 5257 if (task == null) { 5258 if (DEBUG_STACK) Slog.i(TAG_WM, "addTask: could not find taskId=" + taskId); 5259 return; 5260 } 5261 TaskStack stack = mStackIdToStack.get(stackId); 5262 stack.addTask(task, toTop); 5263 final DisplayContent displayContent = stack.getDisplayContent(); 5264 displayContent.layoutNeeded = true; 5265 mWindowPlacerLocked.performSurfacePlacement(); 5266 } 5267 } 5268 moveTaskToStack(int taskId, int stackId, boolean toTop)5269 public void moveTaskToStack(int taskId, int stackId, boolean toTop) { 5270 synchronized (mWindowMap) { 5271 if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: moving taskId=" + taskId 5272 + " to stackId=" + stackId + " at " + (toTop ? "top" : "bottom")); 5273 Task task = mTaskIdToTask.get(taskId); 5274 if (task == null) { 5275 if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: could not find taskId=" + taskId); 5276 return; 5277 } 5278 TaskStack stack = mStackIdToStack.get(stackId); 5279 if (stack == null) { 5280 if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: could not find stackId=" + stackId); 5281 return; 5282 } 5283 task.moveTaskToStack(stack, toTop); 5284 final DisplayContent displayContent = stack.getDisplayContent(); 5285 displayContent.layoutNeeded = true; 5286 mWindowPlacerLocked.performSurfacePlacement(); 5287 } 5288 } 5289 getStackDockedModeBounds(int stackId, Rect bounds, boolean ignoreVisibility)5290 public void getStackDockedModeBounds(int stackId, Rect bounds, boolean ignoreVisibility) { 5291 synchronized (mWindowMap) { 5292 final TaskStack stack = mStackIdToStack.get(stackId); 5293 if (stack != null) { 5294 stack.getStackDockedModeBoundsLocked(bounds, ignoreVisibility); 5295 return; 5296 } 5297 bounds.setEmpty(); 5298 } 5299 } 5300 5301 @Override getStackBounds(int stackId, Rect bounds)5302 public void getStackBounds(int stackId, Rect bounds) { 5303 synchronized (mWindowMap) { 5304 final TaskStack stack = mStackIdToStack.get(stackId); 5305 if (stack != null) { 5306 stack.getBounds(bounds); 5307 return; 5308 } 5309 bounds.setEmpty(); 5310 } 5311 } 5312 5313 @Override overridePlayingAppAnimationsLw(Animation a)5314 public void overridePlayingAppAnimationsLw(Animation a) { 5315 getDefaultDisplayContentLocked().overridePlayingAppAnimationsLw(a); 5316 } 5317 5318 /** 5319 * Re-sizes a stack and its containing tasks. 5320 * @param stackId Id of stack to resize. 5321 * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen. 5322 * @param configs Configurations for tasks in the resized stack, keyed by task id. 5323 * @param taskBounds Bounds for tasks in the resized stack, keyed by task id. 5324 * @return True if the stack is now fullscreen. 5325 * */ resizeStack(int stackId, Rect bounds, SparseArray<Configuration> configs, SparseArray<Rect> taskBounds, SparseArray<Rect> taskTempInsetBounds)5326 public boolean resizeStack(int stackId, Rect bounds, 5327 SparseArray<Configuration> configs, SparseArray<Rect> taskBounds, 5328 SparseArray<Rect> taskTempInsetBounds) { 5329 synchronized (mWindowMap) { 5330 final TaskStack stack = mStackIdToStack.get(stackId); 5331 if (stack == null) { 5332 throw new IllegalArgumentException("resizeStack: stackId " + stackId 5333 + " not found."); 5334 } 5335 if (stack.setBounds(bounds, configs, taskBounds, taskTempInsetBounds) 5336 && stack.isVisibleLocked()) { 5337 stack.getDisplayContent().layoutNeeded = true; 5338 mWindowPlacerLocked.performSurfacePlacement(); 5339 } 5340 return stack.getRawFullscreen(); 5341 } 5342 } 5343 prepareFreezingTaskBounds(int stackId)5344 public void prepareFreezingTaskBounds(int stackId) { 5345 synchronized (mWindowMap) { 5346 final TaskStack stack = mStackIdToStack.get(stackId); 5347 if (stack == null) { 5348 throw new IllegalArgumentException("prepareFreezingTaskBounds: stackId " + stackId 5349 + " not found."); 5350 } 5351 stack.prepareFreezingTaskBounds(); 5352 } 5353 } 5354 positionTaskInStack(int taskId, int stackId, int position, Rect bounds, Configuration config)5355 public void positionTaskInStack(int taskId, int stackId, int position, Rect bounds, 5356 Configuration config) { 5357 synchronized (mWindowMap) { 5358 if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskInStack: positioning taskId=" + taskId 5359 + " in stackId=" + stackId + " at " + position); 5360 Task task = mTaskIdToTask.get(taskId); 5361 if (task == null) { 5362 if (DEBUG_STACK) Slog.i(TAG_WM, 5363 "positionTaskInStack: could not find taskId=" + taskId); 5364 return; 5365 } 5366 TaskStack stack = mStackIdToStack.get(stackId); 5367 if (stack == null) { 5368 if (DEBUG_STACK) Slog.i(TAG_WM, 5369 "positionTaskInStack: could not find stackId=" + stackId); 5370 return; 5371 } 5372 task.positionTaskInStack(stack, position, bounds, config); 5373 final DisplayContent displayContent = stack.getDisplayContent(); 5374 displayContent.layoutNeeded = true; 5375 mWindowPlacerLocked.performSurfacePlacement(); 5376 } 5377 } 5378 5379 /** 5380 * Re-sizes the specified task and its containing windows. 5381 * Returns a {@link Configuration} object that contains configurations settings 5382 * that should be overridden due to the operation. 5383 */ resizeTask(int taskId, Rect bounds, Configuration configuration, boolean relayout, boolean forced)5384 public void resizeTask(int taskId, Rect bounds, Configuration configuration, 5385 boolean relayout, boolean forced) { 5386 synchronized (mWindowMap) { 5387 Task task = mTaskIdToTask.get(taskId); 5388 if (task == null) { 5389 throw new IllegalArgumentException("resizeTask: taskId " + taskId 5390 + " not found."); 5391 } 5392 5393 if (task.resizeLocked(bounds, configuration, forced) && relayout) { 5394 task.getDisplayContent().layoutNeeded = true; 5395 mWindowPlacerLocked.performSurfacePlacement(); 5396 } 5397 } 5398 } 5399 5400 /** 5401 * Puts a specific task into docked drag resizing mode. See {@link DragResizeMode}. 5402 * 5403 * @param taskId The id of the task to put into drag resize mode. 5404 * @param resizing Whether to put the task into drag resize mode. 5405 */ setTaskDockedResizing(int taskId, boolean resizing)5406 public void setTaskDockedResizing(int taskId, boolean resizing) { 5407 synchronized (mWindowMap) { 5408 Task task = mTaskIdToTask.get(taskId); 5409 if (task == null) { 5410 Slog.w(TAG, "setTaskDockedResizing: taskId " + taskId + " not found."); 5411 return; 5412 } 5413 task.setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER); 5414 } 5415 } 5416 scrollTask(int taskId, Rect bounds)5417 public void scrollTask(int taskId, Rect bounds) { 5418 synchronized (mWindowMap) { 5419 Task task = mTaskIdToTask.get(taskId); 5420 if (task == null) { 5421 throw new IllegalArgumentException("scrollTask: taskId " + taskId 5422 + " not found."); 5423 } 5424 5425 if (task.scrollLocked(bounds)) { 5426 task.getDisplayContent().layoutNeeded = true; 5427 mInputMonitor.setUpdateInputWindowsNeededLw(); 5428 mWindowPlacerLocked.performSurfacePlacement(); 5429 } 5430 } 5431 } 5432 /** 5433 * Starts deferring layout passes. Useful when doing multiple changes but to optimize 5434 * performance, only one layout pass should be done. This can be called multiple times, and 5435 * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout} 5436 */ deferSurfaceLayout()5437 public void deferSurfaceLayout() { 5438 synchronized (mWindowMap) { 5439 mWindowPlacerLocked.deferLayout(); 5440 } 5441 } 5442 5443 /** 5444 * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()} 5445 */ continueSurfaceLayout()5446 public void continueSurfaceLayout() { 5447 synchronized (mWindowMap) { 5448 mWindowPlacerLocked.continueLayout(); 5449 } 5450 } 5451 getTaskBounds(int taskId, Rect bounds)5452 public void getTaskBounds(int taskId, Rect bounds) { 5453 synchronized (mWindowMap) { 5454 Task task = mTaskIdToTask.get(taskId); 5455 if (task != null) { 5456 task.getBounds(bounds); 5457 return; 5458 } 5459 bounds.setEmpty(); 5460 } 5461 } 5462 5463 /** Return true if the input task id represents a valid window manager task. */ isValidTaskId(int taskId)5464 public boolean isValidTaskId(int taskId) { 5465 synchronized (mWindowMap) { 5466 return mTaskIdToTask.get(taskId) != null; 5467 } 5468 } 5469 5470 // ------------------------------------------------------------- 5471 // Misc IWindowSession methods 5472 // ------------------------------------------------------------- 5473 5474 @Override startFreezingScreen(int exitAnim, int enterAnim)5475 public void startFreezingScreen(int exitAnim, int enterAnim) { 5476 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5477 "startFreezingScreen()")) { 5478 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5479 } 5480 5481 synchronized(mWindowMap) { 5482 if (!mClientFreezingScreen) { 5483 mClientFreezingScreen = true; 5484 final long origId = Binder.clearCallingIdentity(); 5485 try { 5486 startFreezingDisplayLocked(false, exitAnim, enterAnim); 5487 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 5488 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 5489 } finally { 5490 Binder.restoreCallingIdentity(origId); 5491 } 5492 } 5493 } 5494 } 5495 5496 @Override stopFreezingScreen()5497 public void stopFreezingScreen() { 5498 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5499 "stopFreezingScreen()")) { 5500 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5501 } 5502 5503 synchronized(mWindowMap) { 5504 if (mClientFreezingScreen) { 5505 mClientFreezingScreen = false; 5506 mLastFinishedFreezeSource = "client"; 5507 final long origId = Binder.clearCallingIdentity(); 5508 try { 5509 stopFreezingDisplayLocked(); 5510 } finally { 5511 Binder.restoreCallingIdentity(origId); 5512 } 5513 } 5514 } 5515 } 5516 5517 @Override disableKeyguard(IBinder token, String tag)5518 public void disableKeyguard(IBinder token, String tag) { 5519 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5520 != PackageManager.PERMISSION_GRANTED) { 5521 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5522 } 5523 // If this isn't coming from the system then don't allow disabling the lockscreen 5524 // to bypass security. 5525 if (Binder.getCallingUid() != Process.SYSTEM_UID && isKeyguardSecure()) { 5526 Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard"); 5527 return; 5528 } 5529 5530 // If this isn't coming from the current user, ignore it. 5531 if (Binder.getCallingUserHandle().getIdentifier() != mCurrentUserId) { 5532 Log.d(TAG_WM, "non-current user, ignore disableKeyguard"); 5533 return; 5534 } 5535 5536 if (token == null) { 5537 throw new IllegalArgumentException("token == null"); 5538 } 5539 5540 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5541 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 5542 } 5543 5544 @Override reenableKeyguard(IBinder token)5545 public void reenableKeyguard(IBinder token) { 5546 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5547 != PackageManager.PERMISSION_GRANTED) { 5548 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5549 } 5550 5551 if (token == null) { 5552 throw new IllegalArgumentException("token == null"); 5553 } 5554 5555 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5556 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 5557 } 5558 5559 /** 5560 * @see android.app.KeyguardManager#exitKeyguardSecurely 5561 */ 5562 @Override exitKeyguardSecurely(final IOnKeyguardExitResult callback)5563 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5564 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5565 != PackageManager.PERMISSION_GRANTED) { 5566 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5567 } 5568 5569 if (callback == null) { 5570 throw new IllegalArgumentException("callback == null"); 5571 } 5572 5573 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5574 @Override 5575 public void onKeyguardExitResult(boolean success) { 5576 try { 5577 callback.onKeyguardExitResult(success); 5578 } catch (RemoteException e) { 5579 // Client has died, we don't care. 5580 } 5581 } 5582 }); 5583 } 5584 5585 @Override inKeyguardRestrictedInputMode()5586 public boolean inKeyguardRestrictedInputMode() { 5587 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5588 } 5589 5590 @Override isKeyguardLocked()5591 public boolean isKeyguardLocked() { 5592 return mPolicy.isKeyguardLocked(); 5593 } 5594 5595 @Override isKeyguardSecure()5596 public boolean isKeyguardSecure() { 5597 int userId = UserHandle.getCallingUserId(); 5598 long origId = Binder.clearCallingIdentity(); 5599 try { 5600 return mPolicy.isKeyguardSecure(userId); 5601 } finally { 5602 Binder.restoreCallingIdentity(origId); 5603 } 5604 } 5605 5606 @Override dismissKeyguard()5607 public void dismissKeyguard() { 5608 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5609 != PackageManager.PERMISSION_GRANTED) { 5610 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5611 } 5612 synchronized(mWindowMap) { 5613 mPolicy.dismissKeyguardLw(); 5614 } 5615 } 5616 5617 @Override keyguardGoingAway(int flags)5618 public void keyguardGoingAway(int flags) { 5619 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5620 != PackageManager.PERMISSION_GRANTED) { 5621 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5622 } 5623 if (DEBUG_KEYGUARD) Slog.d(TAG_WM, 5624 "keyguardGoingAway: flags=0x" + Integer.toHexString(flags)); 5625 synchronized (mWindowMap) { 5626 mAnimator.mKeyguardGoingAway = true; 5627 mAnimator.mKeyguardGoingAwayFlags = flags; 5628 mWindowPlacerLocked.requestTraversal(); 5629 } 5630 } 5631 keyguardWaitingForActivityDrawn()5632 public void keyguardWaitingForActivityDrawn() { 5633 if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "keyguardWaitingForActivityDrawn"); 5634 synchronized (mWindowMap) { 5635 mKeyguardWaitingForActivityDrawn = true; 5636 } 5637 } 5638 notifyActivityDrawnForKeyguard()5639 public void notifyActivityDrawnForKeyguard() { 5640 if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "notifyActivityDrawnForKeyguard: waiting=" 5641 + mKeyguardWaitingForActivityDrawn + " Callers=" + Debug.getCallers(5)); 5642 synchronized (mWindowMap) { 5643 if (mKeyguardWaitingForActivityDrawn) { 5644 mPolicy.notifyActivityDrawnForKeyguardLw(); 5645 mKeyguardWaitingForActivityDrawn = false; 5646 } 5647 } 5648 } 5649 showGlobalActions()5650 void showGlobalActions() { 5651 mPolicy.showGlobalActions(); 5652 } 5653 5654 @Override closeSystemDialogs(String reason)5655 public void closeSystemDialogs(String reason) { 5656 synchronized(mWindowMap) { 5657 final int numDisplays = mDisplayContents.size(); 5658 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5659 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5660 final int numWindows = windows.size(); 5661 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5662 final WindowState w = windows.get(winNdx); 5663 if (w.mHasSurface) { 5664 try { 5665 w.mClient.closeSystemDialogs(reason); 5666 } catch (RemoteException e) { 5667 } 5668 } 5669 } 5670 } 5671 } 5672 } 5673 fixScale(float scale)5674 static float fixScale(float scale) { 5675 if (scale < 0) scale = 0; 5676 else if (scale > 20) scale = 20; 5677 return Math.abs(scale); 5678 } 5679 5680 @Override setAnimationScale(int which, float scale)5681 public void setAnimationScale(int which, float scale) { 5682 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5683 "setAnimationScale()")) { 5684 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5685 } 5686 5687 scale = fixScale(scale); 5688 switch (which) { 5689 case 0: mWindowAnimationScaleSetting = scale; break; 5690 case 1: mTransitionAnimationScaleSetting = scale; break; 5691 case 2: mAnimatorDurationScaleSetting = scale; break; 5692 } 5693 5694 // Persist setting 5695 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5696 } 5697 5698 @Override setAnimationScales(float[] scales)5699 public void setAnimationScales(float[] scales) { 5700 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5701 "setAnimationScale()")) { 5702 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5703 } 5704 5705 if (scales != null) { 5706 if (scales.length >= 1) { 5707 mWindowAnimationScaleSetting = fixScale(scales[0]); 5708 } 5709 if (scales.length >= 2) { 5710 mTransitionAnimationScaleSetting = fixScale(scales[1]); 5711 } 5712 if (scales.length >= 3) { 5713 mAnimatorDurationScaleSetting = fixScale(scales[2]); 5714 dispatchNewAnimatorScaleLocked(null); 5715 } 5716 } 5717 5718 // Persist setting 5719 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5720 } 5721 setAnimatorDurationScale(float scale)5722 private void setAnimatorDurationScale(float scale) { 5723 mAnimatorDurationScaleSetting = scale; 5724 ValueAnimator.setDurationScale(scale); 5725 } 5726 getWindowAnimationScaleLocked()5727 public float getWindowAnimationScaleLocked() { 5728 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; 5729 } 5730 getTransitionAnimationScaleLocked()5731 public float getTransitionAnimationScaleLocked() { 5732 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; 5733 } 5734 5735 @Override getAnimationScale(int which)5736 public float getAnimationScale(int which) { 5737 switch (which) { 5738 case 0: return mWindowAnimationScaleSetting; 5739 case 1: return mTransitionAnimationScaleSetting; 5740 case 2: return mAnimatorDurationScaleSetting; 5741 } 5742 return 0; 5743 } 5744 5745 @Override getAnimationScales()5746 public float[] getAnimationScales() { 5747 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting, 5748 mAnimatorDurationScaleSetting }; 5749 } 5750 5751 @Override getCurrentAnimatorScale()5752 public float getCurrentAnimatorScale() { 5753 synchronized(mWindowMap) { 5754 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting; 5755 } 5756 } 5757 dispatchNewAnimatorScaleLocked(Session session)5758 void dispatchNewAnimatorScaleLocked(Session session) { 5759 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget(); 5760 } 5761 5762 @Override registerPointerEventListener(PointerEventListener listener)5763 public void registerPointerEventListener(PointerEventListener listener) { 5764 mPointerEventDispatcher.registerInputEventListener(listener); 5765 } 5766 5767 @Override unregisterPointerEventListener(PointerEventListener listener)5768 public void unregisterPointerEventListener(PointerEventListener listener) { 5769 mPointerEventDispatcher.unregisterInputEventListener(listener); 5770 } 5771 5772 // Called by window manager policy. Not exposed externally. 5773 @Override getLidState()5774 public int getLidState() { 5775 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5776 InputManagerService.SW_LID); 5777 if (sw > 0) { 5778 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5779 return LID_CLOSED; 5780 } else if (sw == 0) { 5781 // Switch state: AKEY_STATE_UP. 5782 return LID_OPEN; 5783 } else { 5784 // Switch state: AKEY_STATE_UNKNOWN. 5785 return LID_ABSENT; 5786 } 5787 } 5788 5789 // Called by window manager policy. Not exposed externally. 5790 @Override lockDeviceNow()5791 public void lockDeviceNow() { 5792 lockNow(null); 5793 } 5794 5795 // Called by window manager policy. Not exposed externally. 5796 @Override getCameraLensCoverState()5797 public int getCameraLensCoverState() { 5798 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5799 InputManagerService.SW_CAMERA_LENS_COVER); 5800 if (sw > 0) { 5801 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5802 return CAMERA_LENS_COVERED; 5803 } else if (sw == 0) { 5804 // Switch state: AKEY_STATE_UP. 5805 return CAMERA_LENS_UNCOVERED; 5806 } else { 5807 // Switch state: AKEY_STATE_UNKNOWN. 5808 return CAMERA_LENS_COVER_ABSENT; 5809 } 5810 } 5811 5812 // Called by window manager policy. Not exposed externally. 5813 @Override switchInputMethod(boolean forwardDirection)5814 public void switchInputMethod(boolean forwardDirection) { 5815 final InputMethodManagerInternal inputMethodManagerInternal = 5816 LocalServices.getService(InputMethodManagerInternal.class); 5817 if (inputMethodManagerInternal != null) { 5818 inputMethodManagerInternal.switchInputMethod(forwardDirection); 5819 } 5820 } 5821 5822 // Called by window manager policy. Not exposed externally. 5823 @Override shutdown(boolean confirm)5824 public void shutdown(boolean confirm) { 5825 ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm); 5826 } 5827 5828 // Called by window manager policy. Not exposed externally. 5829 @Override reboot(boolean confirm)5830 public void reboot(boolean confirm) { 5831 ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm); 5832 } 5833 5834 // Called by window manager policy. Not exposed externally. 5835 @Override rebootSafeMode(boolean confirm)5836 public void rebootSafeMode(boolean confirm) { 5837 ShutdownThread.rebootSafeMode(mContext, confirm); 5838 } 5839 setCurrentProfileIds(final int[] currentProfileIds)5840 public void setCurrentProfileIds(final int[] currentProfileIds) { 5841 synchronized (mWindowMap) { 5842 mCurrentProfileIds = currentProfileIds; 5843 } 5844 } 5845 setCurrentUser(final int newUserId, final int[] currentProfileIds)5846 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) { 5847 synchronized (mWindowMap) { 5848 mCurrentUserId = newUserId; 5849 mCurrentProfileIds = currentProfileIds; 5850 mAppTransition.setCurrentUser(newUserId); 5851 mPolicy.setCurrentUserLw(newUserId); 5852 5853 // If keyguard was disabled, re-enable it 5854 // TODO: Keep track of keyguardEnabled state per user and use here... 5855 // e.g. enabled = mKeyguardDisableHandler.getEnabledStateForUser(newUserId); 5856 mPolicy.enableKeyguard(true); 5857 5858 // Hide windows that should not be seen by the new user. 5859 final int numDisplays = mDisplayContents.size(); 5860 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5861 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 5862 displayContent.switchUserStacks(); 5863 rebuildAppWindowListLocked(displayContent); 5864 } 5865 mWindowPlacerLocked.performSurfacePlacement(); 5866 5867 // Notify whether the docked stack exists for the current user 5868 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 5869 displayContent.mDividerControllerLocked 5870 .notifyDockedStackExistsChanged(hasDockedTasksForUser(newUserId)); 5871 5872 // If the display is already prepared, update the density. 5873 // Otherwise, we'll update it when it's prepared. 5874 if (mDisplayReady) { 5875 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId); 5876 final int targetDensity = forcedDensity != 0 ? forcedDensity 5877 : displayContent.mInitialDisplayDensity; 5878 setForcedDisplayDensityLocked(displayContent, targetDensity); 5879 } 5880 } 5881 } 5882 5883 /** 5884 * Returns whether there is a docked task for the current user. 5885 */ hasDockedTasksForUser(int userId)5886 boolean hasDockedTasksForUser(int userId) { 5887 final TaskStack stack = mStackIdToStack.get(DOCKED_STACK_ID); 5888 if (stack == null) { 5889 return false; 5890 } 5891 5892 final ArrayList<Task> tasks = stack.getTasks(); 5893 boolean hasUserTask = false; 5894 for (int i = tasks.size() - 1; i >= 0 && !hasUserTask; i--) { 5895 final Task task = tasks.get(i); 5896 hasUserTask = (task.mUserId == userId); 5897 } 5898 return hasUserTask; 5899 } 5900 5901 /* Called by WindowState */ isCurrentProfileLocked(int userId)5902 boolean isCurrentProfileLocked(int userId) { 5903 if (userId == mCurrentUserId) return true; 5904 for (int i = 0; i < mCurrentProfileIds.length; i++) { 5905 if (mCurrentProfileIds[i] == userId) return true; 5906 } 5907 return false; 5908 } 5909 enableScreenAfterBoot()5910 public void enableScreenAfterBoot() { 5911 synchronized(mWindowMap) { 5912 if (DEBUG_BOOT) { 5913 RuntimeException here = new RuntimeException("here"); 5914 here.fillInStackTrace(); 5915 Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5916 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5917 + " mShowingBootMessages=" + mShowingBootMessages 5918 + " mSystemBooted=" + mSystemBooted, here); 5919 } 5920 if (mSystemBooted) { 5921 return; 5922 } 5923 mSystemBooted = true; 5924 hideBootMessagesLocked(); 5925 // If the screen still doesn't come up after 30 seconds, give 5926 // up and turn it on. 5927 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000); 5928 } 5929 5930 mPolicy.systemBooted(); 5931 5932 performEnableScreen(); 5933 } 5934 5935 @Override enableScreenIfNeeded()5936 public void enableScreenIfNeeded() { 5937 synchronized (mWindowMap) { 5938 enableScreenIfNeededLocked(); 5939 } 5940 } 5941 enableScreenIfNeededLocked()5942 void enableScreenIfNeededLocked() { 5943 if (DEBUG_BOOT) { 5944 RuntimeException here = new RuntimeException("here"); 5945 here.fillInStackTrace(); 5946 Slog.i(TAG_WM, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5947 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5948 + " mShowingBootMessages=" + mShowingBootMessages 5949 + " mSystemBooted=" + mSystemBooted, here); 5950 } 5951 if (mDisplayEnabled) { 5952 return; 5953 } 5954 if (!mSystemBooted && !mShowingBootMessages) { 5955 return; 5956 } 5957 mH.sendEmptyMessage(H.ENABLE_SCREEN); 5958 } 5959 performBootTimeout()5960 public void performBootTimeout() { 5961 synchronized(mWindowMap) { 5962 if (mDisplayEnabled) { 5963 return; 5964 } 5965 Slog.w(TAG_WM, "***** BOOT TIMEOUT: forcing display enabled"); 5966 mForceDisplayEnabled = true; 5967 } 5968 performEnableScreen(); 5969 } 5970 checkWaitingForWindowsLocked()5971 private boolean checkWaitingForWindowsLocked() { 5972 5973 boolean haveBootMsg = false; 5974 boolean haveApp = false; 5975 // if the wallpaper service is disabled on the device, we're never going to have 5976 // wallpaper, don't bother waiting for it 5977 boolean haveWallpaper = false; 5978 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5979 com.android.internal.R.bool.config_enableWallpaperService) 5980 && !mOnlyCore; 5981 boolean haveKeyguard = true; 5982 // TODO(multidisplay): Expand to all displays? 5983 final WindowList windows = getDefaultWindowListLocked(); 5984 final int N = windows.size(); 5985 for (int i=0; i<N; i++) { 5986 WindowState w = windows.get(i); 5987 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5988 return true; 5989 } 5990 if (w.isDrawnLw()) { 5991 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5992 haveBootMsg = true; 5993 } else if (w.mAttrs.type == TYPE_APPLICATION 5994 || w.mAttrs.type == TYPE_DRAWN_APPLICATION) { 5995 haveApp = true; 5996 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5997 haveWallpaper = true; 5998 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 5999 haveKeyguard = mPolicy.isKeyguardDrawnLw(); 6000 } 6001 } 6002 } 6003 6004 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 6005 Slog.i(TAG_WM, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 6006 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 6007 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 6008 + " haveKeyguard=" + haveKeyguard); 6009 } 6010 6011 // If we are turning on the screen to show the boot message, 6012 // don't do it until the boot message is actually displayed. 6013 if (!mSystemBooted && !haveBootMsg) { 6014 return true; 6015 } 6016 6017 // If we are turning on the screen after the boot is completed 6018 // normally, don't do so until we have the application and 6019 // wallpaper. 6020 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 6021 (wallpaperEnabled && !haveWallpaper))) { 6022 return true; 6023 } 6024 6025 return false; 6026 } 6027 performEnableScreen()6028 public void performEnableScreen() { 6029 synchronized(mWindowMap) { 6030 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 6031 + " mForceDisplayEnabled=" + mForceDisplayEnabled 6032 + " mShowingBootMessages=" + mShowingBootMessages 6033 + " mSystemBooted=" + mSystemBooted 6034 + " mOnlyCore=" + mOnlyCore, 6035 new RuntimeException("here").fillInStackTrace()); 6036 if (mDisplayEnabled) { 6037 return; 6038 } 6039 if (!mSystemBooted && !mShowingBootMessages) { 6040 return; 6041 } 6042 6043 // Don't enable the screen until all existing windows have been drawn. 6044 if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) { 6045 return; 6046 } 6047 6048 if (!mBootAnimationStopped) { 6049 // Do this one time. 6050 Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0); 6051 try { 6052 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 6053 if (surfaceFlinger != null) { 6054 //Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 6055 Parcel data = Parcel.obtain(); 6056 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 6057 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 6058 data, null, 0); 6059 data.recycle(); 6060 } 6061 } catch (RemoteException ex) { 6062 Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!"); 6063 } 6064 mBootAnimationStopped = true; 6065 } 6066 6067 if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) { 6068 if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete"); 6069 return; 6070 } 6071 6072 EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis()); 6073 Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0); 6074 mDisplayEnabled = true; 6075 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!"); 6076 6077 // Enable input dispatch. 6078 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 6079 } 6080 6081 try { 6082 mActivityManager.bootAnimationComplete(); 6083 } catch (RemoteException e) { 6084 } 6085 6086 mPolicy.enableScreenAfterBoot(); 6087 6088 // Make sure the last requested orientation has been applied. 6089 updateRotationUnchecked(false, false); 6090 } 6091 checkBootAnimationCompleteLocked()6092 private boolean checkBootAnimationCompleteLocked() { 6093 if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) { 6094 mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED); 6095 mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED, 6096 BOOT_ANIMATION_POLL_INTERVAL); 6097 if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Waiting for anim complete"); 6098 return false; 6099 } 6100 if (DEBUG_BOOT) Slog.i(TAG_WM, "checkBootAnimationComplete: Animation complete!"); 6101 return true; 6102 } 6103 showBootMessage(final CharSequence msg, final boolean always)6104 public void showBootMessage(final CharSequence msg, final boolean always) { 6105 boolean first = false; 6106 synchronized(mWindowMap) { 6107 if (DEBUG_BOOT) { 6108 RuntimeException here = new RuntimeException("here"); 6109 here.fillInStackTrace(); 6110 Slog.i(TAG_WM, "showBootMessage: msg=" + msg + " always=" + always 6111 + " mAllowBootMessages=" + mAllowBootMessages 6112 + " mShowingBootMessages=" + mShowingBootMessages 6113 + " mSystemBooted=" + mSystemBooted, here); 6114 } 6115 if (!mAllowBootMessages) { 6116 return; 6117 } 6118 if (!mShowingBootMessages) { 6119 if (!always) { 6120 return; 6121 } 6122 first = true; 6123 } 6124 if (mSystemBooted) { 6125 return; 6126 } 6127 mShowingBootMessages = true; 6128 mPolicy.showBootMessage(msg, always); 6129 } 6130 if (first) { 6131 performEnableScreen(); 6132 } 6133 } 6134 hideBootMessagesLocked()6135 public void hideBootMessagesLocked() { 6136 if (DEBUG_BOOT) { 6137 RuntimeException here = new RuntimeException("here"); 6138 here.fillInStackTrace(); 6139 Slog.i(TAG_WM, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 6140 + " mForceDisplayEnabled=" + mForceDisplayEnabled 6141 + " mShowingBootMessages=" + mShowingBootMessages 6142 + " mSystemBooted=" + mSystemBooted, here); 6143 } 6144 if (mShowingBootMessages) { 6145 mShowingBootMessages = false; 6146 mPolicy.hideBootMessages(); 6147 } 6148 } 6149 6150 @Override setInTouchMode(boolean mode)6151 public void setInTouchMode(boolean mode) { 6152 synchronized(mWindowMap) { 6153 mInTouchMode = mode; 6154 } 6155 } 6156 updateCircularDisplayMaskIfNeeded()6157 private void updateCircularDisplayMaskIfNeeded() { 6158 // we're fullscreen and not hosted in an ActivityView 6159 if (mContext.getResources().getConfiguration().isScreenRound() 6160 && mContext.getResources().getBoolean( 6161 com.android.internal.R.bool.config_windowShowCircularMask)) { 6162 final int currentUserId; 6163 synchronized(mWindowMap) { 6164 currentUserId = mCurrentUserId; 6165 } 6166 // Device configuration calls for a circular display mask, but we only enable the mask 6167 // if the accessibility color inversion feature is disabled, as the inverted mask 6168 // causes artifacts. 6169 int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(), 6170 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, currentUserId); 6171 int showMask = (inversionState == 1) ? 0 : 1; 6172 Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK); 6173 m.arg1 = showMask; 6174 mH.sendMessage(m); 6175 } 6176 } 6177 showEmulatorDisplayOverlayIfNeeded()6178 public void showEmulatorDisplayOverlayIfNeeded() { 6179 if (mContext.getResources().getBoolean( 6180 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay) 6181 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false) 6182 && Build.IS_EMULATOR) { 6183 mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY)); 6184 } 6185 } 6186 showCircularMask(boolean visible)6187 public void showCircularMask(boolean visible) { 6188 synchronized(mWindowMap) { 6189 6190 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, 6191 ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")"); 6192 SurfaceControl.openTransaction(); 6193 try { 6194 if (visible) { 6195 // TODO(multi-display): support multiple displays 6196 if (mCircularDisplayMask == null) { 6197 int screenOffset = mContext.getResources().getInteger( 6198 com.android.internal.R.integer.config_windowOutsetBottom); 6199 int maskThickness = mContext.getResources().getDimensionPixelSize( 6200 com.android.internal.R.dimen.circular_display_mask_thickness); 6201 6202 mCircularDisplayMask = new CircularDisplayMask( 6203 getDefaultDisplayContentLocked().getDisplay(), 6204 mFxSession, 6205 mPolicy.windowTypeToLayerLw( 6206 WindowManager.LayoutParams.TYPE_POINTER) 6207 * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness); 6208 } 6209 mCircularDisplayMask.setVisibility(true); 6210 } else if (mCircularDisplayMask != null) { 6211 mCircularDisplayMask.setVisibility(false); 6212 mCircularDisplayMask = null; 6213 } 6214 } finally { 6215 SurfaceControl.closeTransaction(); 6216 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, 6217 "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")"); 6218 } 6219 } 6220 } 6221 showEmulatorDisplayOverlay()6222 public void showEmulatorDisplayOverlay() { 6223 synchronized(mWindowMap) { 6224 6225 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, 6226 ">>> OPEN TRANSACTION showEmulatorDisplayOverlay"); 6227 SurfaceControl.openTransaction(); 6228 try { 6229 if (mEmulatorDisplayOverlay == null) { 6230 mEmulatorDisplayOverlay = new EmulatorDisplayOverlay( 6231 mContext, 6232 getDefaultDisplayContentLocked().getDisplay(), 6233 mFxSession, 6234 mPolicy.windowTypeToLayerLw( 6235 WindowManager.LayoutParams.TYPE_POINTER) 6236 * TYPE_LAYER_MULTIPLIER + 10); 6237 } 6238 mEmulatorDisplayOverlay.setVisibility(true); 6239 } finally { 6240 SurfaceControl.closeTransaction(); 6241 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, 6242 "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay"); 6243 } 6244 } 6245 } 6246 6247 // TODO: more accounting of which pid(s) turned it on, keep count, 6248 // only allow disables from pids which have count on, etc. 6249 @Override showStrictModeViolation(boolean on)6250 public void showStrictModeViolation(boolean on) { 6251 int pid = Binder.getCallingPid(); 6252 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 6253 } 6254 showStrictModeViolation(int arg, int pid)6255 private void showStrictModeViolation(int arg, int pid) { 6256 final boolean on = arg != 0; 6257 synchronized(mWindowMap) { 6258 // Ignoring requests to enable the red border from clients 6259 // which aren't on screen. (e.g. Broadcast Receivers in 6260 // the background..) 6261 if (on) { 6262 boolean isVisible = false; 6263 final int numDisplays = mDisplayContents.size(); 6264 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6265 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6266 final int numWindows = windows.size(); 6267 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6268 final WindowState ws = windows.get(winNdx); 6269 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 6270 isVisible = true; 6271 break; 6272 } 6273 } 6274 } 6275 if (!isVisible) { 6276 return; 6277 } 6278 } 6279 6280 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM, 6281 ">>> OPEN TRANSACTION showStrictModeViolation"); 6282 SurfaceControl.openTransaction(); 6283 try { 6284 // TODO(multi-display): support multiple displays 6285 if (mStrictModeFlash == null) { 6286 mStrictModeFlash = new StrictModeFlash( 6287 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 6288 } 6289 mStrictModeFlash.setVisibility(on); 6290 } finally { 6291 SurfaceControl.closeTransaction(); 6292 if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM, 6293 "<<< CLOSE TRANSACTION showStrictModeViolation"); 6294 } 6295 } 6296 } 6297 6298 @Override setStrictModeVisualIndicatorPreference(String value)6299 public void setStrictModeVisualIndicatorPreference(String value) { 6300 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 6301 } 6302 convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh)6303 private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) { 6304 if (rot == Surface.ROTATION_90) { 6305 final int tmp = crop.top; 6306 crop.top = dw - crop.right; 6307 crop.right = crop.bottom; 6308 crop.bottom = dw - crop.left; 6309 crop.left = tmp; 6310 } else if (rot == Surface.ROTATION_180) { 6311 int tmp = crop.top; 6312 crop.top = dh - crop.bottom; 6313 crop.bottom = dh - tmp; 6314 tmp = crop.right; 6315 crop.right = dw - crop.left; 6316 crop.left = dw - tmp; 6317 } else if (rot == Surface.ROTATION_270) { 6318 final int tmp = crop.top; 6319 crop.top = crop.left; 6320 crop.left = dh - crop.bottom; 6321 crop.bottom = crop.right; 6322 crop.right = dh - tmp; 6323 } 6324 } 6325 6326 @Override screenshotWallpaper()6327 public Bitmap screenshotWallpaper() { 6328 if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER, 6329 "screenshotWallpaper()")) { 6330 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 6331 } 6332 try { 6333 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper"); 6334 return screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1, true, 1f, 6335 Bitmap.Config.ARGB_8888, true); 6336 } finally { 6337 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 6338 } 6339 } 6340 6341 /** 6342 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 6343 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 6344 * of the target image. 6345 */ 6346 @Override requestAssistScreenshot(final IAssistScreenshotReceiver receiver)6347 public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) { 6348 if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER, 6349 "requestAssistScreenshot()")) { 6350 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 6351 } 6352 6353 FgThread.getHandler().post(new Runnable() { 6354 @Override 6355 public void run() { 6356 Bitmap bm = screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1, 6357 true, 1f, Bitmap.Config.ARGB_8888, false); 6358 try { 6359 receiver.send(bm); 6360 } catch (RemoteException e) { 6361 } 6362 } 6363 }); 6364 6365 return true; 6366 } 6367 6368 /** 6369 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 6370 * In portrait mode, it grabs the full screenshot. 6371 * 6372 * @param displayId the Display to take a screenshot of. 6373 * @param width the width of the target bitmap 6374 * @param height the height of the target bitmap 6375 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1 6376 */ 6377 @Override screenshotApplications(IBinder appToken, int displayId, int width, int height, float frameScale)6378 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height, 6379 float frameScale) { 6380 if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER, 6381 "screenshotApplications()")) { 6382 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 6383 } 6384 try { 6385 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications"); 6386 return screenshotApplicationsInner(appToken, displayId, width, height, false, 6387 frameScale, Bitmap.Config.RGB_565, false); 6388 } finally { 6389 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 6390 } 6391 } 6392 6393 /** 6394 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 6395 * In portrait mode, it grabs the full screenshot. 6396 * 6397 * @param displayId the Display to take a screenshot of. 6398 * @param width the width of the target bitmap 6399 * @param height the height of the target bitmap 6400 * @param includeFullDisplay true if the screen should not be cropped before capture 6401 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1 6402 * @param config of the output bitmap 6403 * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot 6404 */ screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config, boolean wallpaperOnly)6405 Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height, 6406 boolean includeFullDisplay, float frameScale, Bitmap.Config config, 6407 boolean wallpaperOnly) { 6408 final DisplayContent displayContent; 6409 synchronized(mWindowMap) { 6410 displayContent = getDisplayContentLocked(displayId); 6411 if (displayContent == null) { 6412 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 6413 + ": returning null. No Display for displayId=" + displayId); 6414 return null; 6415 } 6416 } 6417 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6418 int dw = displayInfo.logicalWidth; 6419 int dh = displayInfo.logicalHeight; 6420 if (dw == 0 || dh == 0) { 6421 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 6422 + ": returning null. logical widthxheight=" + dw + "x" + dh); 6423 return null; 6424 } 6425 6426 Bitmap bm = null; 6427 6428 int maxLayer = 0; 6429 final Rect frame = new Rect(); 6430 final Rect stackBounds = new Rect(); 6431 6432 boolean screenshotReady; 6433 int minLayer; 6434 if (appToken == null && !wallpaperOnly) { 6435 screenshotReady = true; 6436 minLayer = 0; 6437 } else { 6438 screenshotReady = false; 6439 minLayer = Integer.MAX_VALUE; 6440 } 6441 6442 WindowState appWin = null; 6443 6444 boolean includeImeInScreenshot; 6445 synchronized(mWindowMap) { 6446 final AppWindowToken imeTargetAppToken = 6447 mInputMethodTarget != null ? mInputMethodTarget.mAppToken : null; 6448 // We only include the Ime in the screenshot if the app we are screenshoting is the IME 6449 // target and isn't in multi-window mode. We don't screenshot the IME in multi-window 6450 // mode because the frame of the IME might not overlap with that of the app. 6451 // E.g. IME target app at the top in split-screen mode and the IME at the bottom 6452 // overlapping with the bottom app. 6453 includeImeInScreenshot = imeTargetAppToken != null 6454 && imeTargetAppToken.appToken != null 6455 && imeTargetAppToken.appToken.asBinder() == appToken 6456 && !mInputMethodTarget.isInMultiWindowMode(); 6457 } 6458 6459 final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1) 6460 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 6461 6462 synchronized(mWindowMap) { 6463 // Figure out the part of the screen that is actually the app. 6464 appWin = null; 6465 final WindowList windows = displayContent.getWindowList(); 6466 for (int i = windows.size() - 1; i >= 0; i--) { 6467 WindowState ws = windows.get(i); 6468 if (!ws.mHasSurface) { 6469 continue; 6470 } 6471 if (ws.mLayer >= aboveAppLayer) { 6472 continue; 6473 } 6474 if (wallpaperOnly && !ws.mIsWallpaper) { 6475 continue; 6476 } 6477 if (ws.mIsImWindow) { 6478 if (!includeImeInScreenshot) { 6479 continue; 6480 } 6481 } else if (ws.mIsWallpaper) { 6482 // If this is the wallpaper layer and we're only looking for the wallpaper layer 6483 // then the target window state is this one. 6484 if (wallpaperOnly) { 6485 appWin = ws; 6486 } 6487 6488 if (appWin == null) { 6489 // We have not ran across the target window yet, so it is probably 6490 // behind the wallpaper. This can happen when the keyguard is up and 6491 // all windows are moved behind the wallpaper. We don't want to 6492 // include the wallpaper layer in the screenshot as it will coverup 6493 // the layer of the target window. 6494 continue; 6495 } 6496 // Fall through. The target window is in front of the wallpaper. For this 6497 // case we want to include the wallpaper layer in the screenshot because 6498 // the target window might have some transparent areas. 6499 } else if (appToken != null) { 6500 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 6501 // This app window is of no interest if it is not associated with the 6502 // screenshot app. 6503 continue; 6504 } 6505 appWin = ws; 6506 } 6507 6508 // Include this window. 6509 6510 final WindowStateAnimator winAnim = ws.mWinAnimator; 6511 int layer = winAnim.mSurfaceController.getLayer(); 6512 if (maxLayer < layer) { 6513 maxLayer = layer; 6514 } 6515 if (minLayer > layer) { 6516 minLayer = layer; 6517 } 6518 6519 // Don't include wallpaper in bounds calculation 6520 if (!includeFullDisplay && !ws.mIsWallpaper) { 6521 final Rect wf = ws.mFrame; 6522 final Rect cr = ws.mContentInsets; 6523 int left = wf.left + cr.left; 6524 int top = wf.top + cr.top; 6525 int right = wf.right - cr.right; 6526 int bottom = wf.bottom - cr.bottom; 6527 frame.union(left, top, right, bottom); 6528 ws.getVisibleBounds(stackBounds); 6529 if (!Rect.intersects(frame, stackBounds)) { 6530 // Set frame empty if there's no intersection. 6531 frame.setEmpty(); 6532 } 6533 } 6534 6535 final boolean foundTargetWs = 6536 (ws.mAppToken != null && ws.mAppToken.token == appToken) 6537 || (appWin != null && wallpaperOnly); 6538 if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) { 6539 screenshotReady = true; 6540 } 6541 6542 if (ws.isObscuringFullscreen(displayInfo)){ 6543 break; 6544 } 6545 } 6546 6547 if (appToken != null && appWin == null) { 6548 // Can't find a window to snapshot. 6549 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, 6550 "Screenshot: Couldn't find a surface matching " + appToken); 6551 return null; 6552 } 6553 6554 if (!screenshotReady) { 6555 Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken + 6556 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + 6557 appWin.mWinAnimator.mDrawState))); 6558 return null; 6559 } 6560 6561 // Screenshot is ready to be taken. Everything from here below will continue 6562 // through the bottom of the loop and return a value. We only stay in the loop 6563 // because we don't want to release the mWindowMap lock until the screenshot is 6564 // taken. 6565 6566 if (maxLayer == 0) { 6567 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 6568 + ": returning null maxLayer=" + maxLayer); 6569 return null; 6570 } 6571 6572 if (!includeFullDisplay) { 6573 // Constrain frame to the screen size. 6574 if (!frame.intersect(0, 0, dw, dh)) { 6575 frame.setEmpty(); 6576 } 6577 } else { 6578 // Caller just wants entire display. 6579 frame.set(0, 0, dw, dh); 6580 } 6581 if (frame.isEmpty()) { 6582 return null; 6583 } 6584 6585 if (width < 0) { 6586 width = (int) (frame.width() * frameScale); 6587 } 6588 if (height < 0) { 6589 height = (int) (frame.height() * frameScale); 6590 } 6591 6592 // Tell surface flinger what part of the image to crop. Take the top 6593 // right part of the application, and crop the larger dimension to fit. 6594 Rect crop = new Rect(frame); 6595 if (width / (float) frame.width() < height / (float) frame.height()) { 6596 int cropWidth = (int)((float)width / (float)height * frame.height()); 6597 crop.right = crop.left + cropWidth; 6598 } else { 6599 int cropHeight = (int)((float)height / (float)width * frame.width()); 6600 crop.bottom = crop.top + cropHeight; 6601 } 6602 6603 // The screenshot API does not apply the current screen rotation. 6604 int rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 6605 6606 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 6607 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 6608 } 6609 6610 // Surfaceflinger is not aware of orientation, so convert our logical 6611 // crop to surfaceflinger's portrait orientation. 6612 convertCropForSurfaceFlinger(crop, rot, dw, dh); 6613 6614 if (DEBUG_SCREENSHOT) { 6615 Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 6616 + maxLayer + " appToken=" + appToken); 6617 for (int i = 0; i < windows.size(); i++) { 6618 WindowState win = windows.get(i); 6619 WindowSurfaceController controller = win.mWinAnimator.mSurfaceController; 6620 Slog.i(TAG_WM, win + ": " + win.mLayer 6621 + " animLayer=" + win.mWinAnimator.mAnimLayer 6622 + " surfaceLayer=" + ((controller == null) 6623 ? "null" : controller.getLayer())); 6624 } 6625 } 6626 6627 ScreenRotationAnimation screenRotationAnimation = 6628 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6629 final boolean inRotation = screenRotationAnimation != null && 6630 screenRotationAnimation.isAnimating(); 6631 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, 6632 "Taking screenshot while rotating"); 6633 6634 // We force pending transactions to flush before taking 6635 // the screenshot by pushing an empty synchronous transaction. 6636 SurfaceControl.openTransaction(); 6637 SurfaceControl.closeTransactionSync(); 6638 6639 bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer, 6640 inRotation, rot); 6641 if (bm == null) { 6642 Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh 6643 + ") to layer " + maxLayer); 6644 return null; 6645 } 6646 } 6647 6648 if (DEBUG_SCREENSHOT) { 6649 // TEST IF IT's ALL BLACK 6650 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 6651 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 6652 boolean allBlack = true; 6653 final int firstColor = buffer[0]; 6654 for (int i = 0; i < buffer.length; i++) { 6655 if (buffer[i] != firstColor) { 6656 allBlack = false; 6657 break; 6658 } 6659 } 6660 if (allBlack) { 6661 Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" + 6662 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 6663 (appWin != null ? 6664 appWin.mWinAnimator.mSurfaceController.getLayer() : "null") + 6665 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 6666 } 6667 } 6668 6669 // Create a copy of the screenshot that is immutable and backed in ashmem. 6670 // This greatly reduces the overhead of passing the bitmap between processes. 6671 Bitmap ret = bm.createAshmemBitmap(config); 6672 bm.recycle(); 6673 return ret; 6674 } 6675 6676 /** 6677 * Freeze rotation changes. (Enable "rotation lock".) 6678 * Persists across reboots. 6679 * @param rotation The desired rotation to freeze to, or -1 to use the 6680 * current rotation. 6681 */ 6682 @Override freezeRotation(int rotation)6683 public void freezeRotation(int rotation) { 6684 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 6685 "freezeRotation()")) { 6686 throw new SecurityException("Requires SET_ORIENTATION permission"); 6687 } 6688 if (rotation < -1 || rotation > Surface.ROTATION_270) { 6689 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 6690 + "rotation constant."); 6691 } 6692 6693 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation=" + mRotation); 6694 6695 long origId = Binder.clearCallingIdentity(); 6696 try { 6697 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 6698 rotation == -1 ? mRotation : rotation); 6699 } finally { 6700 Binder.restoreCallingIdentity(origId); 6701 } 6702 6703 updateRotationUnchecked(false, false); 6704 } 6705 6706 /** 6707 * Thaw rotation changes. (Disable "rotation lock".) 6708 * Persists across reboots. 6709 */ 6710 @Override thawRotation()6711 public void thawRotation() { 6712 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 6713 "thawRotation()")) { 6714 throw new SecurityException("Requires SET_ORIENTATION permission"); 6715 } 6716 6717 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation=" + mRotation); 6718 6719 long origId = Binder.clearCallingIdentity(); 6720 try { 6721 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 6722 777); // rot not used 6723 } finally { 6724 Binder.restoreCallingIdentity(origId); 6725 } 6726 6727 updateRotationUnchecked(false, false); 6728 } 6729 6730 /** 6731 * Recalculate the current rotation. 6732 * 6733 * Called by the window manager policy whenever the state of the system changes 6734 * such that the current rotation might need to be updated, such as when the 6735 * device is docked or rotated into a new posture. 6736 */ 6737 @Override updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout)6738 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 6739 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 6740 } 6741 6742 /** 6743 * Temporarily pauses rotation changes until resumed. 6744 * 6745 * This can be used to prevent rotation changes from occurring while the user is 6746 * performing certain operations, such as drag and drop. 6747 * 6748 * This call nests and must be matched by an equal number of calls to 6749 * {@link #resumeRotationLocked}. 6750 */ pauseRotationLocked()6751 void pauseRotationLocked() { 6752 mDeferredRotationPauseCount += 1; 6753 } 6754 6755 /** 6756 * Resumes normal rotation changes after being paused. 6757 */ resumeRotationLocked()6758 void resumeRotationLocked() { 6759 if (mDeferredRotationPauseCount > 0) { 6760 mDeferredRotationPauseCount -= 1; 6761 if (mDeferredRotationPauseCount == 0) { 6762 boolean changed = updateRotationUncheckedLocked(false); 6763 if (changed) { 6764 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6765 } 6766 } 6767 } 6768 } 6769 updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout)6770 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 6771 if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked(" 6772 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 6773 6774 long origId = Binder.clearCallingIdentity(); 6775 boolean changed; 6776 synchronized(mWindowMap) { 6777 changed = updateRotationUncheckedLocked(false); 6778 if (!changed || forceRelayout) { 6779 getDefaultDisplayContentLocked().layoutNeeded = true; 6780 mWindowPlacerLocked.performSurfacePlacement(); 6781 } 6782 } 6783 6784 if (changed || alwaysSendConfiguration) { 6785 sendNewConfiguration(); 6786 } 6787 6788 Binder.restoreCallingIdentity(origId); 6789 } 6790 6791 6792 // TODO(multidisplay): Rotate any display? 6793 /** 6794 * Updates the current rotation. 6795 * 6796 * Returns true if the rotation has been changed. In this case YOU 6797 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 6798 */ updateRotationUncheckedLocked(boolean inTransaction)6799 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 6800 if (mDeferredRotationPauseCount > 0) { 6801 // Rotation updates have been paused temporarily. Defer the update until 6802 // updates have been resumed. 6803 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused."); 6804 return false; 6805 } 6806 6807 ScreenRotationAnimation screenRotationAnimation = 6808 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6809 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 6810 // Rotation updates cannot be performed while the previous rotation change 6811 // animation is still in progress. Skip this update. We will try updating 6812 // again after the animation is finished and the display is unfrozen. 6813 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress."); 6814 return false; 6815 } 6816 if (mDisplayFrozen) { 6817 // Even if the screen rotation animation has finished (e.g. isAnimating 6818 // returns false), there is still some time where we haven't yet unfrozen 6819 // the display. We also need to abort rotation here. 6820 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, still finishing previous rotation"); 6821 return false; 6822 } 6823 6824 if (!mDisplayEnabled) { 6825 // No point choosing a rotation if the display is not enabled. 6826 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled."); 6827 return false; 6828 } 6829 6830 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6831 final WindowList windows = displayContent.getWindowList(); 6832 6833 final int oldRotation = mRotation; 6834 int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation); 6835 boolean rotateSeamlessly = mPolicy.shouldRotateSeamlessly(oldRotation, rotation); 6836 6837 if (rotateSeamlessly) { 6838 for (int i = windows.size() - 1; i >= 0; i--) { 6839 WindowState w = windows.get(i); 6840 // We can't rotate (seamlessly or not) while waiting for the last seamless rotation 6841 // to complete (that is, waiting for windows to redraw). It's tempting to check 6842 // w.mSeamlessRotationCount but that could be incorrect in the case of window-removal. 6843 if (w.mSeamlesslyRotated) { 6844 return false; 6845 } 6846 // In what can only be called an unfortunate workaround we require 6847 // seamlessly rotated child windows to have the TRANSFORM_TO_DISPLAY_INVERSE 6848 // flag. Due to limitations in the client API, there is no way for 6849 // the client to set this flag in a race free fashion. If we seamlessly rotate 6850 // a window which does not have this flag, but then gains it, we will get 6851 // an incorrect visual result (rotated viewfinder). This means if we want to 6852 // support seamlessly rotating windows which could gain this flag, we can't 6853 // rotate windows without it. This limits seamless rotation in N to camera framework 6854 // users, windows without children, and native code. This is unfortunate but 6855 // having the camera work is our primary goal. 6856 if (w.isChildWindow() & w.isVisibleNow() && 6857 !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse()) { 6858 rotateSeamlessly = false; 6859 } 6860 } 6861 } 6862 6863 // TODO: Implement forced rotation changes. 6864 // Set mAltOrientation to indicate that the application is receiving 6865 // an orientation that has different metrics than it expected. 6866 // eg. Portrait instead of Landscape. 6867 6868 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 6869 mLastOrientation, rotation); 6870 6871 if (DEBUG_ORIENTATION) { 6872 Slog.v(TAG_WM, "Selected orientation " 6873 + mLastOrientation + ", got rotation " + rotation 6874 + " which has " + (altOrientation ? "incompatible" : "compatible") 6875 + " metrics"); 6876 } 6877 6878 if (mRotation == rotation && mAltOrientation == altOrientation) { 6879 // No change. 6880 return false; 6881 } 6882 6883 if (DEBUG_ORIENTATION) { 6884 Slog.v(TAG_WM, 6885 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 6886 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 6887 + ", lastOrientation=" + mLastOrientation); 6888 } 6889 6890 mRotation = rotation; 6891 mAltOrientation = altOrientation; 6892 mPolicy.setRotationLw(mRotation); 6893 6894 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; 6895 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 6896 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 6897 mWaitingForConfig = true; 6898 displayContent.layoutNeeded = true; 6899 final int[] anim = new int[2]; 6900 if (displayContent.isDimming()) { 6901 anim[0] = anim[1] = 0; 6902 } else { 6903 mPolicy.selectRotationAnimationLw(anim); 6904 } 6905 6906 if (!rotateSeamlessly) { 6907 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6908 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6909 screenRotationAnimation = 6910 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6911 } else { 6912 // The screen rotation animation uses a screenshot to freeze the screen 6913 // while windows resize underneath. 6914 // When we are rotating seamlessly, we allow the elements to transition 6915 // to their rotated state independently and without a freeze required. 6916 screenRotationAnimation = null; 6917 6918 // We have to reset this in case a window was removed before it 6919 // finished seamless rotation. 6920 mSeamlessRotationCount = 0; 6921 } 6922 6923 // We need to update our screen size information to match the new rotation. If the rotation 6924 // has actually changed then this method will return true and, according to the comment at 6925 // the top of the method, the caller is obligated to call computeNewConfigurationLocked(). 6926 // By updating the Display info here it will be available to 6927 // computeScreenConfigurationLocked later. 6928 updateDisplayAndOrientationLocked(mCurConfiguration.uiMode); 6929 6930 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6931 if (!inTransaction) { 6932 if (SHOW_TRANSACTIONS) { 6933 Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked"); 6934 } 6935 SurfaceControl.openTransaction(); 6936 } 6937 try { 6938 // NOTE: We disable the rotation in the emulator because 6939 // it doesn't support hardware OpenGL emulation yet. 6940 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6941 && screenRotationAnimation.hasScreenshot()) { 6942 if (screenRotationAnimation.setRotationInTransaction( 6943 rotation, mFxSession, 6944 MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), 6945 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6946 scheduleAnimationLocked(); 6947 } 6948 } 6949 6950 if (rotateSeamlessly) { 6951 for (int i = windows.size() - 1; i >= 0; i--) { 6952 WindowState w = windows.get(i); 6953 w.mWinAnimator.seamlesslyRotateWindow(oldRotation, mRotation); 6954 } 6955 } 6956 6957 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6958 } finally { 6959 if (!inTransaction) { 6960 SurfaceControl.closeTransaction(); 6961 if (SHOW_LIGHT_TRANSACTIONS) { 6962 Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6963 } 6964 } 6965 } 6966 6967 for (int i = windows.size() - 1; i >= 0; i--) { 6968 WindowState w = windows.get(i); 6969 // Discard surface after orientation change, these can't be reused. 6970 if (w.mAppToken != null) { 6971 w.mAppToken.destroySavedSurfaces(); 6972 } 6973 if (w.mHasSurface && !rotateSeamlessly) { 6974 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w); 6975 w.mOrientationChanging = true; 6976 mWindowPlacerLocked.mOrientationChangeComplete = false; 6977 w.mLastFreezeDuration = 0; 6978 } 6979 } 6980 if (rotateSeamlessly) { 6981 mH.removeMessages(H.SEAMLESS_ROTATION_TIMEOUT); 6982 mH.sendEmptyMessageDelayed(H.SEAMLESS_ROTATION_TIMEOUT, SEAMLESS_ROTATION_TIMEOUT_DURATION); 6983 } 6984 6985 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6986 try { 6987 mRotationWatchers.get(i).watcher.onRotationChanged(rotation); 6988 } catch (RemoteException e) { 6989 } 6990 } 6991 6992 // TODO (multidisplay): Magnification is supported only for the default display. 6993 // Announce rotation only if we will not animate as we already have the 6994 // windows in final state. Otherwise, we make this call at the rotation end. 6995 if (screenRotationAnimation == null && mAccessibilityController != null 6996 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6997 mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), 6998 rotation); 6999 } 7000 7001 return true; 7002 } 7003 7004 @Override getRotation()7005 public int getRotation() { 7006 return mRotation; 7007 } 7008 7009 @Override isRotationFrozen()7010 public boolean isRotationFrozen() { 7011 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 7012 } 7013 7014 @Override watchRotation(IRotationWatcher watcher)7015 public int watchRotation(IRotationWatcher watcher) { 7016 final IBinder watcherBinder = watcher.asBinder(); 7017 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 7018 @Override 7019 public void binderDied() { 7020 synchronized (mWindowMap) { 7021 for (int i=0; i<mRotationWatchers.size(); i++) { 7022 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) { 7023 RotationWatcher removed = mRotationWatchers.remove(i); 7024 IBinder binder = removed.watcher.asBinder(); 7025 if (binder != null) { 7026 binder.unlinkToDeath(this, 0); 7027 } 7028 i--; 7029 } 7030 } 7031 } 7032 } 7033 }; 7034 7035 synchronized (mWindowMap) { 7036 try { 7037 watcher.asBinder().linkToDeath(dr, 0); 7038 mRotationWatchers.add(new RotationWatcher(watcher, dr)); 7039 } catch (RemoteException e) { 7040 // Client died, no cleanup needed. 7041 } 7042 7043 return mRotation; 7044 } 7045 } 7046 7047 @Override removeRotationWatcher(IRotationWatcher watcher)7048 public void removeRotationWatcher(IRotationWatcher watcher) { 7049 final IBinder watcherBinder = watcher.asBinder(); 7050 synchronized (mWindowMap) { 7051 for (int i=0; i<mRotationWatchers.size(); i++) { 7052 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 7053 if (watcherBinder == rotationWatcher.watcher.asBinder()) { 7054 RotationWatcher removed = mRotationWatchers.remove(i); 7055 IBinder binder = removed.watcher.asBinder(); 7056 if (binder != null) { 7057 binder.unlinkToDeath(removed.deathRecipient, 0); 7058 } 7059 i--; 7060 } 7061 } 7062 } 7063 } 7064 7065 /** 7066 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 7067 * theme attribute) on devices that feature a physical options menu key attempt to position 7068 * their menu panel window along the edge of the screen nearest the physical menu key. 7069 * This lowers the travel distance between invoking the menu panel and selecting 7070 * a menu option. 7071 * 7072 * This method helps control where that menu is placed. Its current implementation makes 7073 * assumptions about the menu key and its relationship to the screen based on whether 7074 * the device's natural orientation is portrait (width < height) or landscape. 7075 * 7076 * The menu key is assumed to be located along the bottom edge of natural-portrait 7077 * devices and along the right edge of natural-landscape devices. If these assumptions 7078 * do not hold for the target device, this method should be changed to reflect that. 7079 * 7080 * @return A {@link Gravity} value for placing the options menu window 7081 */ 7082 @Override getPreferredOptionsPanelGravity()7083 public int getPreferredOptionsPanelGravity() { 7084 synchronized (mWindowMap) { 7085 final int rotation = getRotation(); 7086 7087 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 7088 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7089 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 7090 // On devices with a natural orientation of portrait 7091 switch (rotation) { 7092 default: 7093 case Surface.ROTATION_0: 7094 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 7095 case Surface.ROTATION_90: 7096 return Gravity.RIGHT | Gravity.BOTTOM; 7097 case Surface.ROTATION_180: 7098 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 7099 case Surface.ROTATION_270: 7100 return Gravity.START | Gravity.BOTTOM; 7101 } 7102 } 7103 7104 // On devices with a natural orientation of landscape 7105 switch (rotation) { 7106 default: 7107 case Surface.ROTATION_0: 7108 return Gravity.RIGHT | Gravity.BOTTOM; 7109 case Surface.ROTATION_90: 7110 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 7111 case Surface.ROTATION_180: 7112 return Gravity.START | Gravity.BOTTOM; 7113 case Surface.ROTATION_270: 7114 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 7115 } 7116 } 7117 } 7118 7119 /** 7120 * Starts the view server on the specified port. 7121 * 7122 * @param port The port to listener to. 7123 * 7124 * @return True if the server was successfully started, false otherwise. 7125 * 7126 * @see com.android.server.wm.ViewServer 7127 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 7128 */ 7129 @Override startViewServer(int port)7130 public boolean startViewServer(int port) { 7131 if (isSystemSecure()) { 7132 return false; 7133 } 7134 7135 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 7136 return false; 7137 } 7138 7139 if (port < 1024) { 7140 return false; 7141 } 7142 7143 if (mViewServer != null) { 7144 if (!mViewServer.isRunning()) { 7145 try { 7146 return mViewServer.start(); 7147 } catch (IOException e) { 7148 Slog.w(TAG_WM, "View server did not start"); 7149 } 7150 } 7151 return false; 7152 } 7153 7154 try { 7155 mViewServer = new ViewServer(this, port); 7156 return mViewServer.start(); 7157 } catch (IOException e) { 7158 Slog.w(TAG_WM, "View server did not start"); 7159 } 7160 return false; 7161 } 7162 isSystemSecure()7163 private boolean isSystemSecure() { 7164 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 7165 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 7166 } 7167 7168 /** 7169 * Stops the view server if it exists. 7170 * 7171 * @return True if the server stopped, false if it wasn't started or 7172 * couldn't be stopped. 7173 * 7174 * @see com.android.server.wm.ViewServer 7175 */ 7176 @Override stopViewServer()7177 public boolean stopViewServer() { 7178 if (isSystemSecure()) { 7179 return false; 7180 } 7181 7182 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 7183 return false; 7184 } 7185 7186 if (mViewServer != null) { 7187 return mViewServer.stop(); 7188 } 7189 return false; 7190 } 7191 7192 /** 7193 * Indicates whether the view server is running. 7194 * 7195 * @return True if the server is running, false otherwise. 7196 * 7197 * @see com.android.server.wm.ViewServer 7198 */ 7199 @Override isViewServerRunning()7200 public boolean isViewServerRunning() { 7201 if (isSystemSecure()) { 7202 return false; 7203 } 7204 7205 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 7206 return false; 7207 } 7208 7209 return mViewServer != null && mViewServer.isRunning(); 7210 } 7211 7212 /** 7213 * Lists all availble windows in the system. The listing is written in the 7214 * specified Socket's output stream with the following syntax: 7215 * windowHashCodeInHexadecimal windowName 7216 * Each line of the ouput represents a different window. 7217 * 7218 * @param client The remote client to send the listing to. 7219 * @return False if an error occured, true otherwise. 7220 */ viewServerListWindows(Socket client)7221 boolean viewServerListWindows(Socket client) { 7222 if (isSystemSecure()) { 7223 return false; 7224 } 7225 7226 boolean result = true; 7227 7228 WindowList windows = new WindowList(); 7229 synchronized (mWindowMap) { 7230 //noinspection unchecked 7231 final int numDisplays = mDisplayContents.size(); 7232 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 7233 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 7234 windows.addAll(displayContent.getWindowList()); 7235 } 7236 } 7237 7238 BufferedWriter out = null; 7239 7240 // Any uncaught exception will crash the system process 7241 try { 7242 OutputStream clientStream = client.getOutputStream(); 7243 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 7244 7245 final int count = windows.size(); 7246 for (int i = 0; i < count; i++) { 7247 final WindowState w = windows.get(i); 7248 out.write(Integer.toHexString(System.identityHashCode(w))); 7249 out.write(' '); 7250 out.append(w.mAttrs.getTitle()); 7251 out.write('\n'); 7252 } 7253 7254 out.write("DONE.\n"); 7255 out.flush(); 7256 } catch (Exception e) { 7257 result = false; 7258 } finally { 7259 if (out != null) { 7260 try { 7261 out.close(); 7262 } catch (IOException e) { 7263 result = false; 7264 } 7265 } 7266 } 7267 7268 return result; 7269 } 7270 7271 // TODO(multidisplay): Extend to multiple displays. 7272 /** 7273 * Returns the focused window in the following format: 7274 * windowHashCodeInHexadecimal windowName 7275 * 7276 * @param client The remote client to send the listing to. 7277 * @return False if an error occurred, true otherwise. 7278 */ viewServerGetFocusedWindow(Socket client)7279 boolean viewServerGetFocusedWindow(Socket client) { 7280 if (isSystemSecure()) { 7281 return false; 7282 } 7283 7284 boolean result = true; 7285 7286 WindowState focusedWindow = getFocusedWindow(); 7287 7288 BufferedWriter out = null; 7289 7290 // Any uncaught exception will crash the system process 7291 try { 7292 OutputStream clientStream = client.getOutputStream(); 7293 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 7294 7295 if(focusedWindow != null) { 7296 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 7297 out.write(' '); 7298 out.append(focusedWindow.mAttrs.getTitle()); 7299 } 7300 out.write('\n'); 7301 out.flush(); 7302 } catch (Exception e) { 7303 result = false; 7304 } finally { 7305 if (out != null) { 7306 try { 7307 out.close(); 7308 } catch (IOException e) { 7309 result = false; 7310 } 7311 } 7312 } 7313 7314 return result; 7315 } 7316 7317 /** 7318 * Sends a command to a target window. The result of the command, if any, will be 7319 * written in the output stream of the specified socket. 7320 * 7321 * The parameters must follow this syntax: 7322 * windowHashcode extra 7323 * 7324 * Where XX is the length in characeters of the windowTitle. 7325 * 7326 * The first parameter is the target window. The window with the specified hashcode 7327 * will be the target. If no target can be found, nothing happens. The extra parameters 7328 * will be delivered to the target window and as parameters to the command itself. 7329 * 7330 * @param client The remote client to sent the result, if any, to. 7331 * @param command The command to execute. 7332 * @param parameters The command parameters. 7333 * 7334 * @return True if the command was successfully delivered, false otherwise. This does 7335 * not indicate whether the command itself was successful. 7336 */ viewServerWindowCommand(Socket client, String command, String parameters)7337 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 7338 if (isSystemSecure()) { 7339 return false; 7340 } 7341 7342 boolean success = true; 7343 Parcel data = null; 7344 Parcel reply = null; 7345 7346 BufferedWriter out = null; 7347 7348 // Any uncaught exception will crash the system process 7349 try { 7350 // Find the hashcode of the window 7351 int index = parameters.indexOf(' '); 7352 if (index == -1) { 7353 index = parameters.length(); 7354 } 7355 final String code = parameters.substring(0, index); 7356 int hashCode = (int) Long.parseLong(code, 16); 7357 7358 // Extract the command's parameter after the window description 7359 if (index < parameters.length()) { 7360 parameters = parameters.substring(index + 1); 7361 } else { 7362 parameters = ""; 7363 } 7364 7365 final WindowState window = findWindow(hashCode); 7366 if (window == null) { 7367 return false; 7368 } 7369 7370 data = Parcel.obtain(); 7371 data.writeInterfaceToken("android.view.IWindow"); 7372 data.writeString(command); 7373 data.writeString(parameters); 7374 data.writeInt(1); 7375 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 7376 7377 reply = Parcel.obtain(); 7378 7379 final IBinder binder = window.mClient.asBinder(); 7380 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 7381 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 7382 7383 reply.readException(); 7384 7385 if (!client.isOutputShutdown()) { 7386 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 7387 out.write("DONE\n"); 7388 out.flush(); 7389 } 7390 7391 } catch (Exception e) { 7392 Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e); 7393 success = false; 7394 } finally { 7395 if (data != null) { 7396 data.recycle(); 7397 } 7398 if (reply != null) { 7399 reply.recycle(); 7400 } 7401 if (out != null) { 7402 try { 7403 out.close(); 7404 } catch (IOException e) { 7405 7406 } 7407 } 7408 } 7409 7410 return success; 7411 } 7412 addWindowChangeListener(WindowChangeListener listener)7413 public void addWindowChangeListener(WindowChangeListener listener) { 7414 synchronized(mWindowMap) { 7415 mWindowChangeListeners.add(listener); 7416 } 7417 } 7418 removeWindowChangeListener(WindowChangeListener listener)7419 public void removeWindowChangeListener(WindowChangeListener listener) { 7420 synchronized(mWindowMap) { 7421 mWindowChangeListeners.remove(listener); 7422 } 7423 } 7424 notifyWindowsChanged()7425 private void notifyWindowsChanged() { 7426 WindowChangeListener[] windowChangeListeners; 7427 synchronized(mWindowMap) { 7428 if(mWindowChangeListeners.isEmpty()) { 7429 return; 7430 } 7431 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 7432 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 7433 } 7434 int N = windowChangeListeners.length; 7435 for(int i = 0; i < N; i++) { 7436 windowChangeListeners[i].windowsChanged(); 7437 } 7438 } 7439 notifyFocusChanged()7440 private void notifyFocusChanged() { 7441 WindowChangeListener[] windowChangeListeners; 7442 synchronized(mWindowMap) { 7443 if(mWindowChangeListeners.isEmpty()) { 7444 return; 7445 } 7446 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 7447 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 7448 } 7449 int N = windowChangeListeners.length; 7450 for(int i = 0; i < N; i++) { 7451 windowChangeListeners[i].focusChanged(); 7452 } 7453 } 7454 findWindow(int hashCode)7455 private WindowState findWindow(int hashCode) { 7456 if (hashCode == -1) { 7457 // TODO(multidisplay): Extend to multiple displays. 7458 return getFocusedWindow(); 7459 } 7460 7461 synchronized (mWindowMap) { 7462 final int numDisplays = mDisplayContents.size(); 7463 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 7464 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 7465 final int numWindows = windows.size(); 7466 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 7467 final WindowState w = windows.get(winNdx); 7468 if (System.identityHashCode(w) == hashCode) { 7469 return w; 7470 } 7471 } 7472 } 7473 } 7474 7475 return null; 7476 } 7477 7478 /* 7479 * Instruct the Activity Manager to fetch the current configuration and broadcast 7480 * that to config-changed listeners if appropriate. 7481 */ sendNewConfiguration()7482 void sendNewConfiguration() { 7483 try { 7484 mActivityManager.updateConfiguration(null); 7485 } catch (RemoteException e) { 7486 } 7487 } 7488 computeNewConfiguration()7489 public Configuration computeNewConfiguration() { 7490 synchronized (mWindowMap) { 7491 return computeNewConfigurationLocked(); 7492 } 7493 } 7494 computeNewConfigurationLocked()7495 private Configuration computeNewConfigurationLocked() { 7496 if (!mDisplayReady) { 7497 return null; 7498 } 7499 Configuration config = new Configuration(); 7500 config.fontScale = 0; 7501 computeScreenConfigurationLocked(config); 7502 return config; 7503 } 7504 adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode, int dw, int dh)7505 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode, 7506 int dw, int dh) { 7507 // TODO: Multidisplay: for now only use with default display. 7508 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode); 7509 if (width < displayInfo.smallestNominalAppWidth) { 7510 displayInfo.smallestNominalAppWidth = width; 7511 } 7512 if (width > displayInfo.largestNominalAppWidth) { 7513 displayInfo.largestNominalAppWidth = width; 7514 } 7515 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode); 7516 if (height < displayInfo.smallestNominalAppHeight) { 7517 displayInfo.smallestNominalAppHeight = height; 7518 } 7519 if (height > displayInfo.largestNominalAppHeight) { 7520 displayInfo.largestNominalAppHeight = height; 7521 } 7522 } 7523 reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh, int uiMode)7524 private int reduceConfigLayout(int curLayout, int rotation, float density, 7525 int dw, int dh, int uiMode) { 7526 // TODO: Multidisplay: for now only use with default display. 7527 // Get the app screen size at this rotation. 7528 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode); 7529 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode); 7530 7531 // Compute the screen layout size class for this rotation. 7532 int longSize = w; 7533 int shortSize = h; 7534 if (longSize < shortSize) { 7535 int tmp = longSize; 7536 longSize = shortSize; 7537 shortSize = tmp; 7538 } 7539 longSize = (int)(longSize/density); 7540 shortSize = (int)(shortSize/density); 7541 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 7542 } 7543 computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, int uiMode, int dw, int dh, float density, Configuration outConfig)7544 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 7545 int uiMode, int dw, int dh, float density, Configuration outConfig) { 7546 // TODO: Multidisplay: for now only use with default display. 7547 7548 // We need to determine the smallest width that will occur under normal 7549 // operation. To this, start with the base screen size and compute the 7550 // width under the different possible rotations. We need to un-rotate 7551 // the current screen dimensions before doing this. 7552 int unrotDw, unrotDh; 7553 if (rotated) { 7554 unrotDw = dh; 7555 unrotDh = dw; 7556 } else { 7557 unrotDw = dw; 7558 unrotDh = dh; 7559 } 7560 displayInfo.smallestNominalAppWidth = 1<<30; 7561 displayInfo.smallestNominalAppHeight = 1<<30; 7562 displayInfo.largestNominalAppWidth = 0; 7563 displayInfo.largestNominalAppHeight = 0; 7564 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh); 7565 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw); 7566 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh); 7567 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw); 7568 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 7569 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode); 7570 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode); 7571 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode); 7572 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode); 7573 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 7574 outConfig.screenLayout = sl; 7575 } 7576 reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, DisplayMetrics dm, int dw, int dh)7577 private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, 7578 DisplayMetrics dm, int dw, int dh) { 7579 // TODO: Multidisplay: for now only use with default display. 7580 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode); 7581 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode); 7582 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 7583 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 7584 if (curSize == 0 || size < curSize) { 7585 curSize = size; 7586 } 7587 return curSize; 7588 } 7589 computeCompatSmallestWidth(boolean rotated, int uiMode, DisplayMetrics dm, int dw, int dh)7590 private int computeCompatSmallestWidth(boolean rotated, int uiMode, DisplayMetrics dm, int dw, int dh) { 7591 // TODO: Multidisplay: for now only use with default display. 7592 mTmpDisplayMetrics.setTo(dm); 7593 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 7594 final int unrotDw, unrotDh; 7595 if (rotated) { 7596 unrotDw = dh; 7597 unrotDh = dw; 7598 } else { 7599 unrotDw = dw; 7600 unrotDh = dh; 7601 } 7602 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh); 7603 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw); 7604 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh); 7605 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw); 7606 return sw; 7607 } 7608 7609 /** Do not call if mDisplayReady == false */ updateDisplayAndOrientationLocked(int uiMode)7610 DisplayInfo updateDisplayAndOrientationLocked(int uiMode) { 7611 // TODO(multidisplay): For now, apply Configuration to main screen only. 7612 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7613 7614 // Use the effective "visual" dimensions based on current rotation 7615 final boolean rotated = (mRotation == Surface.ROTATION_90 7616 || mRotation == Surface.ROTATION_270); 7617 final int realdw = rotated ? 7618 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 7619 final int realdh = rotated ? 7620 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 7621 int dw = realdw; 7622 int dh = realdh; 7623 7624 if (mAltOrientation) { 7625 if (realdw > realdh) { 7626 // Turn landscape into portrait. 7627 int maxw = (int)(realdh/1.3f); 7628 if (maxw < realdw) { 7629 dw = maxw; 7630 } 7631 } else { 7632 // Turn portrait into landscape. 7633 int maxh = (int)(realdw/1.3f); 7634 if (maxh < realdh) { 7635 dh = maxh; 7636 } 7637 } 7638 } 7639 7640 // Update application display metrics. 7641 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode); 7642 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode); 7643 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7644 displayInfo.rotation = mRotation; 7645 displayInfo.logicalWidth = dw; 7646 displayInfo.logicalHeight = dh; 7647 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 7648 displayInfo.appWidth = appWidth; 7649 displayInfo.appHeight = appHeight; 7650 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 7651 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 7652 displayInfo.getAppMetrics(mDisplayMetrics); 7653 if (displayContent.mDisplayScalingDisabled) { 7654 displayInfo.flags |= Display.FLAG_SCALING_DISABLED; 7655 } else { 7656 displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED; 7657 } 7658 7659 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 7660 displayContent.getDisplayId(), displayInfo); 7661 7662 displayContent.mBaseDisplayRect.set(0, 0, dw, dh); 7663 if (false) { 7664 Slog.i(TAG_WM, "Set app display size: " + appWidth + " x " + appHeight); 7665 } 7666 7667 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics, 7668 mCompatDisplayMetrics); 7669 return displayInfo; 7670 } 7671 7672 /** Do not call if mDisplayReady == false */ computeScreenConfigurationLocked(Configuration config)7673 void computeScreenConfigurationLocked(Configuration config) { 7674 final DisplayInfo displayInfo = updateDisplayAndOrientationLocked( 7675 config.uiMode); 7676 7677 final int dw = displayInfo.logicalWidth; 7678 final int dh = displayInfo.logicalHeight; 7679 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 7680 Configuration.ORIENTATION_LANDSCAPE; 7681 config.screenWidthDp = 7682 (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation, config.uiMode) / 7683 mDisplayMetrics.density); 7684 config.screenHeightDp = 7685 (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation, config.uiMode) / 7686 mDisplayMetrics.density); 7687 final boolean rotated = (mRotation == Surface.ROTATION_90 7688 || mRotation == Surface.ROTATION_270); 7689 7690 computeSizeRangesAndScreenLayout(displayInfo, rotated, config.uiMode, dw, dh, 7691 mDisplayMetrics.density, config); 7692 7693 config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK) 7694 | ((displayInfo.flags & Display.FLAG_ROUND) != 0 7695 ? Configuration.SCREENLAYOUT_ROUND_YES 7696 : Configuration.SCREENLAYOUT_ROUND_NO); 7697 7698 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 7699 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 7700 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, 7701 mDisplayMetrics, dw, dh); 7702 config.densityDpi = displayInfo.logicalDensityDpi; 7703 7704 // Update the configuration based on available input devices, lid switch, 7705 // and platform configuration. 7706 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 7707 config.keyboard = Configuration.KEYBOARD_NOKEYS; 7708 config.navigation = Configuration.NAVIGATION_NONAV; 7709 7710 int keyboardPresence = 0; 7711 int navigationPresence = 0; 7712 final InputDevice[] devices = mInputManager.getInputDevices(); 7713 final int len = devices.length; 7714 for (int i = 0; i < len; i++) { 7715 InputDevice device = devices[i]; 7716 if (!device.isVirtual()) { 7717 final int sources = device.getSources(); 7718 final int presenceFlag = device.isExternal() ? 7719 WindowManagerPolicy.PRESENCE_EXTERNAL : 7720 WindowManagerPolicy.PRESENCE_INTERNAL; 7721 7722 if (mIsTouchDevice) { 7723 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 7724 InputDevice.SOURCE_TOUCHSCREEN) { 7725 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 7726 } 7727 } else { 7728 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 7729 } 7730 7731 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 7732 config.navigation = Configuration.NAVIGATION_TRACKBALL; 7733 navigationPresence |= presenceFlag; 7734 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 7735 && config.navigation == Configuration.NAVIGATION_NONAV) { 7736 config.navigation = Configuration.NAVIGATION_DPAD; 7737 navigationPresence |= presenceFlag; 7738 } 7739 7740 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 7741 config.keyboard = Configuration.KEYBOARD_QWERTY; 7742 keyboardPresence |= presenceFlag; 7743 } 7744 } 7745 } 7746 7747 if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) { 7748 config.navigation = Configuration.NAVIGATION_DPAD; 7749 navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL; 7750 } 7751 7752 // Determine whether a hard keyboard is available and enabled. 7753 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 7754 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 7755 mHardKeyboardAvailable = hardKeyboardAvailable; 7756 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 7757 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 7758 } 7759 7760 // Let the policy update hidden states. 7761 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 7762 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 7763 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 7764 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 7765 } 7766 notifyHardKeyboardStatusChange()7767 void notifyHardKeyboardStatusChange() { 7768 final boolean available; 7769 final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener; 7770 synchronized (mWindowMap) { 7771 listener = mHardKeyboardStatusChangeListener; 7772 available = mHardKeyboardAvailable; 7773 } 7774 if (listener != null) { 7775 listener.onHardKeyboardStatusChange(available); 7776 } 7777 } 7778 startMovingTask(IWindow window, float startX, float startY)7779 boolean startMovingTask(IWindow window, float startX, float startY) { 7780 WindowState win = null; 7781 synchronized (mWindowMap) { 7782 win = windowForClientLocked(null, window, false); 7783 // win shouldn't be null here, pass it down to startPositioningLocked 7784 // to get warning if it's null. 7785 if (!startPositioningLocked(win, false /*resize*/, startX, startY)) { 7786 return false; 7787 } 7788 } 7789 try { 7790 mActivityManager.setFocusedTask(win.getTask().mTaskId); 7791 } catch(RemoteException e) {} 7792 return true; 7793 } 7794 startScrollingTask(DisplayContent displayContent, int startX, int startY)7795 private void startScrollingTask(DisplayContent displayContent, int startX, int startY) { 7796 if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, 7797 "startScrollingTask: " + "{" + startX + ", " + startY + "}"); 7798 7799 Task task = null; 7800 synchronized (mWindowMap) { 7801 int taskId = displayContent.taskIdFromPoint(startX, startY); 7802 if (taskId >= 0) { 7803 task = mTaskIdToTask.get(taskId); 7804 } 7805 if (task == null || !task.isDockedInEffect() || !startPositioningLocked( 7806 task.getTopVisibleAppMainWindow(), false /*resize*/, startX, startY)) { 7807 return; 7808 } 7809 } 7810 try { 7811 mActivityManager.setFocusedTask(task.mTaskId); 7812 } catch(RemoteException e) {} 7813 } 7814 handleTapOutsideTask(DisplayContent displayContent, int x, int y)7815 private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) { 7816 int taskId = -1; 7817 synchronized (mWindowMap) { 7818 final Task task = displayContent.findTaskForControlPoint(x, y); 7819 if (task != null) { 7820 if (!startPositioningLocked( 7821 task.getTopVisibleAppMainWindow(), true /*resize*/, x, y)) { 7822 return; 7823 } 7824 taskId = task.mTaskId; 7825 } else { 7826 taskId = displayContent.taskIdFromPoint(x, y); 7827 } 7828 } 7829 if (taskId >= 0) { 7830 try { 7831 mActivityManager.setFocusedTask(taskId); 7832 } catch(RemoteException e) {} 7833 } 7834 } 7835 startPositioningLocked( WindowState win, boolean resize, float startX, float startY)7836 private boolean startPositioningLocked( 7837 WindowState win, boolean resize, float startX, float startY) { 7838 if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "startPositioningLocked: " 7839 + "win=" + win + ", resize=" + resize + ", {" + startX + ", " + startY + "}"); 7840 7841 if (win == null || win.getAppToken() == null) { 7842 Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win); 7843 return false; 7844 } 7845 if (win.mInputChannel == null) { 7846 Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, " 7847 + " probably being removed"); 7848 return false; 7849 } 7850 7851 final DisplayContent displayContent = win.getDisplayContent(); 7852 if (displayContent == null) { 7853 Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win); 7854 return false; 7855 } 7856 7857 Display display = displayContent.getDisplay(); 7858 mTaskPositioner = new TaskPositioner(this); 7859 mTaskPositioner.register(display); 7860 mInputMonitor.updateInputWindowsLw(true /*force*/); 7861 7862 // We need to grab the touch focus so that the touch events during the 7863 // resizing/scrolling are not sent to the app. 'win' is the main window 7864 // of the app, it may not have focus since there might be other windows 7865 // on top (eg. a dialog window). 7866 WindowState transferFocusFromWin = win; 7867 if (mCurrentFocus != null && mCurrentFocus != win 7868 && mCurrentFocus.mAppToken == win.mAppToken) { 7869 transferFocusFromWin = mCurrentFocus; 7870 } 7871 if (!mInputManager.transferTouchFocus( 7872 transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) { 7873 Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus"); 7874 mTaskPositioner.unregister(); 7875 mTaskPositioner = null; 7876 mInputMonitor.updateInputWindowsLw(true /*force*/); 7877 return false; 7878 } 7879 7880 mTaskPositioner.startDragLocked(win, resize, startX, startY); 7881 return true; 7882 } 7883 finishPositioning()7884 private void finishPositioning() { 7885 if (DEBUG_TASK_POSITIONING) { 7886 Slog.d(TAG_WM, "finishPositioning"); 7887 } 7888 synchronized (mWindowMap) { 7889 if (mTaskPositioner != null) { 7890 mTaskPositioner.unregister(); 7891 mTaskPositioner = null; 7892 mInputMonitor.updateInputWindowsLw(true /*force*/); 7893 } 7894 } 7895 } 7896 adjustForImeIfNeeded(final DisplayContent displayContent)7897 void adjustForImeIfNeeded(final DisplayContent displayContent) { 7898 final WindowState imeWin = mInputMethodWindow; 7899 final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw() 7900 && !displayContent.mDividerControllerLocked.isImeHideRequested(); 7901 final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID); 7902 final TaskStack imeTargetStack = getImeFocusStackLocked(); 7903 final int imeDockSide = (dockVisible && imeTargetStack != null) ? 7904 imeTargetStack.getDockSide() : DOCKED_INVALID; 7905 final boolean imeOnTop = (imeDockSide == DOCKED_TOP); 7906 final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM); 7907 final boolean dockMinimized = displayContent.mDividerControllerLocked.isMinimizedDock(); 7908 final int imeHeight = mPolicy.getInputMethodWindowVisibleHeightLw(); 7909 final boolean imeHeightChanged = imeVisible && 7910 imeHeight != displayContent.mDividerControllerLocked.getImeHeightAdjustedFor(); 7911 7912 // The divider could be adjusted for IME position, or be thinner than usual, 7913 // or both. There are three possible cases: 7914 // - If IME is visible, and focus is on top, divider is not moved for IME but thinner. 7915 // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner. 7916 // - If IME is not visible, divider is not moved and is normal width. 7917 7918 if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) { 7919 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 7920 for (int i = stacks.size() - 1; i >= 0; --i) { 7921 final TaskStack stack = stacks.get(i); 7922 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM; 7923 if (stack.isVisibleLocked() && (imeOnBottom || isDockedOnBottom)) { 7924 stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged); 7925 } else { 7926 stack.resetAdjustedForIme(false); 7927 } 7928 } 7929 displayContent.mDividerControllerLocked.setAdjustedForIme( 7930 imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight); 7931 } else { 7932 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 7933 for (int i = stacks.size() - 1; i >= 0; --i) { 7934 final TaskStack stack = stacks.get(i); 7935 stack.resetAdjustedForIme(!dockVisible); 7936 } 7937 displayContent.mDividerControllerLocked.setAdjustedForIme( 7938 false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight); 7939 } 7940 } 7941 7942 // ------------------------------------------------------------- 7943 // Drag and drop 7944 // ------------------------------------------------------------- 7945 prepareDragSurface(IWindow window, SurfaceSession session, int flags, int width, int height, Surface outSurface)7946 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 7947 int flags, int width, int height, Surface outSurface) { 7948 if (DEBUG_DRAG) { 7949 Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height 7950 + " flags=" + Integer.toHexString(flags) + " win=" + window 7951 + " asbinder=" + window.asBinder()); 7952 } 7953 7954 final int callerPid = Binder.getCallingPid(); 7955 final int callerUid = Binder.getCallingUid(); 7956 final long origId = Binder.clearCallingIdentity(); 7957 IBinder token = null; 7958 7959 try { 7960 synchronized (mWindowMap) { 7961 try { 7962 if (mDragState == null) { 7963 // TODO(multi-display): support other displays 7964 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7965 final Display display = displayContent.getDisplay(); 7966 7967 SurfaceControl surface = new SurfaceControl(session, "drag surface", 7968 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 7969 surface.setLayerStack(display.getLayerStack()); 7970 float alpha = 1; 7971 if ((flags & View.DRAG_FLAG_OPAQUE) == 0) { 7972 alpha = DRAG_SHADOW_ALPHA_TRANSPARENT; 7973 } 7974 surface.setAlpha(alpha); 7975 7976 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG " 7977 + surface + ": CREATE"); 7978 outSurface.copyFrom(surface); 7979 final IBinder winBinder = window.asBinder(); 7980 token = new Binder(); 7981 mDragState = new DragState(this, token, surface, flags, winBinder); 7982 mDragState.mPid = callerPid; 7983 mDragState.mUid = callerUid; 7984 mDragState.mOriginalAlpha = alpha; 7985 token = mDragState.mToken = new Binder(); 7986 7987 // 5 second timeout for this window to actually begin the drag 7988 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 7989 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 7990 mH.sendMessageDelayed(msg, 5000); 7991 } else { 7992 Slog.w(TAG_WM, "Drag already in progress"); 7993 } 7994 } catch (OutOfResourcesException e) { 7995 Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e); 7996 if (mDragState != null) { 7997 mDragState.reset(); 7998 mDragState = null; 7999 } 8000 } 8001 } 8002 } finally { 8003 Binder.restoreCallingIdentity(origId); 8004 } 8005 8006 return token; 8007 } 8008 8009 // ------------------------------------------------------------- 8010 // Input Events and Focus Management 8011 // ------------------------------------------------------------- 8012 8013 final InputMonitor mInputMonitor = new InputMonitor(this); 8014 private boolean mEventDispatchingEnabled; 8015 8016 @Override pauseKeyDispatching(IBinder _token)8017 public void pauseKeyDispatching(IBinder _token) { 8018 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 8019 "pauseKeyDispatching()")) { 8020 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 8021 } 8022 8023 synchronized (mWindowMap) { 8024 WindowToken token = mTokenMap.get(_token); 8025 if (token != null) { 8026 mInputMonitor.pauseDispatchingLw(token); 8027 } 8028 } 8029 } 8030 8031 @Override resumeKeyDispatching(IBinder _token)8032 public void resumeKeyDispatching(IBinder _token) { 8033 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 8034 "resumeKeyDispatching()")) { 8035 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 8036 } 8037 8038 synchronized (mWindowMap) { 8039 WindowToken token = mTokenMap.get(_token); 8040 if (token != null) { 8041 mInputMonitor.resumeDispatchingLw(token); 8042 } 8043 } 8044 } 8045 8046 @Override setEventDispatching(boolean enabled)8047 public void setEventDispatching(boolean enabled) { 8048 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 8049 "setEventDispatching()")) { 8050 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 8051 } 8052 8053 synchronized (mWindowMap) { 8054 mEventDispatchingEnabled = enabled; 8055 if (mDisplayEnabled) { 8056 mInputMonitor.setEventDispatchingLw(enabled); 8057 } 8058 } 8059 } 8060 getFocusedWindow()8061 private WindowState getFocusedWindow() { 8062 synchronized (mWindowMap) { 8063 return getFocusedWindowLocked(); 8064 } 8065 } 8066 getFocusedWindowLocked()8067 private WindowState getFocusedWindowLocked() { 8068 return mCurrentFocus; 8069 } 8070 getImeFocusStackLocked()8071 TaskStack getImeFocusStackLocked() { 8072 // Don't use mCurrentFocus.getStack() because it returns home stack for system windows. 8073 // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE 8074 // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved 8075 // to make room for IME, but the window is not the focused window that's taking input. 8076 return (mFocusedApp != null && mFocusedApp.mTask != null) ? 8077 mFocusedApp.mTask.mStack : null; 8078 } 8079 showAuditSafeModeNotification()8080 private void showAuditSafeModeNotification() { 8081 PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, 8082 new Intent(Intent.ACTION_VIEW, 8083 Uri.parse("https://support.google.com/nexus/answer/2852139")), 0); 8084 8085 String title = mContext.getString(R.string.audit_safemode_notification); 8086 8087 Notification notification = new Notification.Builder(mContext) 8088 .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning) 8089 .setWhen(0) 8090 .setOngoing(true) 8091 .setTicker(title) 8092 .setLocalOnly(true) 8093 .setPriority(Notification.PRIORITY_HIGH) 8094 .setVisibility(Notification.VISIBILITY_PUBLIC) 8095 .setColor(mContext.getColor( 8096 com.android.internal.R.color.system_notification_accent_color)) 8097 .setContentTitle(title) 8098 .setContentText(mContext.getString(R.string.audit_safemode_notification_details)) 8099 .setContentIntent(pendingIntent) 8100 .build(); 8101 8102 NotificationManager notificationManager = (NotificationManager) mContext 8103 .getSystemService(Context.NOTIFICATION_SERVICE); 8104 8105 notificationManager.notifyAsUser(null, R.string.audit_safemode_notification, notification, 8106 UserHandle.ALL); 8107 } 8108 detectSafeMode()8109 public boolean detectSafeMode() { 8110 if (!mInputMonitor.waitForInputDevicesReady( 8111 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 8112 Slog.w(TAG_WM, "Devices still not ready after waiting " 8113 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 8114 + " milliseconds before attempting to detect safe mode."); 8115 } 8116 8117 if (Settings.Global.getInt( 8118 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) { 8119 return false; 8120 } 8121 8122 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 8123 KeyEvent.KEYCODE_MENU); 8124 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 8125 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 8126 KeyEvent.KEYCODE_DPAD_CENTER); 8127 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 8128 InputManagerService.BTN_MOUSE); 8129 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 8130 KeyEvent.KEYCODE_VOLUME_DOWN); 8131 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 8132 || volumeDownState > 0; 8133 try { 8134 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0 8135 || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) { 8136 int auditSafeMode = SystemProperties.getInt(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, 0); 8137 8138 if (auditSafeMode == 0) { 8139 mSafeMode = true; 8140 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 8141 } else { 8142 // stay in safe mode until we have updated to a newer build 8143 int buildDate = SystemProperties.getInt(PROPERTY_BUILD_DATE_UTC, 0); 8144 8145 if (auditSafeMode >= buildDate) { 8146 mSafeMode = true; 8147 showAuditSafeModeNotification(); 8148 } else { 8149 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 8150 SystemProperties.set(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, ""); 8151 } 8152 } 8153 } 8154 } catch (IllegalArgumentException e) { 8155 } 8156 if (mSafeMode) { 8157 Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 8158 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 8159 SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1"); 8160 } else { 8161 Log.i(TAG_WM, "SAFE MODE not enabled"); 8162 } 8163 mPolicy.setSafeMode(mSafeMode); 8164 return mSafeMode; 8165 } 8166 displayReady()8167 public void displayReady() { 8168 for (Display display : mDisplays) { 8169 displayReady(display.getDisplayId()); 8170 } 8171 8172 synchronized(mWindowMap) { 8173 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8174 readForcedDisplayPropertiesLocked(displayContent); 8175 mDisplayReady = true; 8176 } 8177 8178 try { 8179 mActivityManager.updateConfiguration(null); 8180 } catch (RemoteException e) { 8181 } 8182 8183 synchronized(mWindowMap) { 8184 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 8185 PackageManager.FEATURE_TOUCHSCREEN); 8186 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 8187 } 8188 8189 try { 8190 mActivityManager.updateConfiguration(null); 8191 } catch (RemoteException e) { 8192 } 8193 8194 updateCircularDisplayMaskIfNeeded(); 8195 } 8196 displayReady(int displayId)8197 private void displayReady(int displayId) { 8198 synchronized(mWindowMap) { 8199 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8200 if (displayContent != null) { 8201 mAnimator.addDisplayLocked(displayId); 8202 displayContent.initializeDisplayBaseInfo(); 8203 if (displayContent.mTapDetector != null) { 8204 displayContent.mTapDetector.init(); 8205 } 8206 } 8207 } 8208 } 8209 systemReady()8210 public void systemReady() { 8211 mPolicy.systemReady(); 8212 } 8213 8214 // ------------------------------------------------------------- 8215 // Async Handler 8216 // ------------------------------------------------------------- 8217 8218 final class H extends Handler { 8219 public static final int REPORT_FOCUS_CHANGE = 2; 8220 public static final int REPORT_LOSING_FOCUS = 3; 8221 public static final int DO_TRAVERSAL = 4; 8222 public static final int ADD_STARTING = 5; 8223 public static final int REMOVE_STARTING = 6; 8224 public static final int FINISHED_STARTING = 7; 8225 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 8226 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 8227 public static final int WINDOW_FREEZE_TIMEOUT = 11; 8228 8229 public static final int APP_TRANSITION_TIMEOUT = 13; 8230 public static final int PERSIST_ANIMATION_SCALE = 14; 8231 public static final int FORCE_GC = 15; 8232 public static final int ENABLE_SCREEN = 16; 8233 public static final int APP_FREEZE_TIMEOUT = 17; 8234 public static final int SEND_NEW_CONFIGURATION = 18; 8235 public static final int REPORT_WINDOWS_CHANGE = 19; 8236 public static final int DRAG_START_TIMEOUT = 20; 8237 public static final int DRAG_END_TIMEOUT = 21; 8238 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 8239 public static final int BOOT_TIMEOUT = 23; 8240 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 8241 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 8242 public static final int DO_ANIMATION_CALLBACK = 26; 8243 8244 public static final int DO_DISPLAY_ADDED = 27; 8245 public static final int DO_DISPLAY_REMOVED = 28; 8246 public static final int DO_DISPLAY_CHANGED = 29; 8247 8248 public static final int CLIENT_FREEZE_TIMEOUT = 30; 8249 public static final int TAP_OUTSIDE_TASK = 31; 8250 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 8251 8252 public static final int ALL_WINDOWS_DRAWN = 33; 8253 8254 public static final int NEW_ANIMATOR_SCALE = 34; 8255 8256 public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35; 8257 public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36; 8258 8259 public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37; 8260 public static final int RESET_ANR_MESSAGE = 38; 8261 public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39; 8262 8263 public static final int FINISH_TASK_POSITIONING = 40; 8264 8265 public static final int UPDATE_DOCKED_STACK_DIVIDER = 41; 8266 8267 public static final int RESIZE_STACK = 42; 8268 public static final int RESIZE_TASK = 43; 8269 8270 public static final int TWO_FINGER_SCROLL_START = 44; 8271 8272 public static final int WINDOW_REPLACEMENT_TIMEOUT = 46; 8273 8274 public static final int NOTIFY_APP_TRANSITION_STARTING = 47; 8275 public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48; 8276 public static final int NOTIFY_APP_TRANSITION_FINISHED = 49; 8277 public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50; 8278 public static final int UPDATE_ANIMATION_SCALE = 51; 8279 public static final int WINDOW_HIDE_TIMEOUT = 52; 8280 public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53; 8281 public static final int SEAMLESS_ROTATION_TIMEOUT = 54; 8282 8283 /** 8284 * Used to denote that an integer field in a message will not be used. 8285 */ 8286 public static final int UNUSED = 0; 8287 8288 @Override handleMessage(Message msg)8289 public void handleMessage(Message msg) { 8290 if (DEBUG_WINDOW_TRACE) { 8291 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what); 8292 } 8293 switch (msg.what) { 8294 case REPORT_FOCUS_CHANGE: { 8295 WindowState lastFocus; 8296 WindowState newFocus; 8297 8298 AccessibilityController accessibilityController = null; 8299 8300 synchronized(mWindowMap) { 8301 // TODO(multidisplay): Accessibility supported only of default desiplay. 8302 if (mAccessibilityController != null && getDefaultDisplayContentLocked() 8303 .getDisplayId() == Display.DEFAULT_DISPLAY) { 8304 accessibilityController = mAccessibilityController; 8305 } 8306 8307 lastFocus = mLastFocus; 8308 newFocus = mCurrentFocus; 8309 if (lastFocus == newFocus) { 8310 // Focus is not changing, so nothing to do. 8311 return; 8312 } 8313 mLastFocus = newFocus; 8314 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus + 8315 " to " + newFocus); 8316 if (newFocus != null && lastFocus != null 8317 && !newFocus.isDisplayedLw()) { 8318 //Slog.i(TAG_WM, "Delaying loss of focus..."); 8319 mLosingFocus.add(lastFocus); 8320 lastFocus = null; 8321 } 8322 } 8323 8324 // First notify the accessibility manager for the change so it has 8325 // the windows before the newly focused one starts firing eventgs. 8326 if (accessibilityController != null) { 8327 accessibilityController.onWindowFocusChangedNotLocked(); 8328 } 8329 8330 //System.out.println("Changing focus from " + lastFocus 8331 // + " to " + newFocus); 8332 if (newFocus != null) { 8333 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus); 8334 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 8335 notifyFocusChanged(); 8336 } 8337 8338 if (lastFocus != null) { 8339 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus); 8340 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 8341 } 8342 } break; 8343 8344 case REPORT_LOSING_FOCUS: { 8345 ArrayList<WindowState> losers; 8346 8347 synchronized(mWindowMap) { 8348 losers = mLosingFocus; 8349 mLosingFocus = new ArrayList<WindowState>(); 8350 } 8351 8352 final int N = losers.size(); 8353 for (int i=0; i<N; i++) { 8354 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " + 8355 losers.get(i)); 8356 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 8357 } 8358 } break; 8359 8360 case DO_TRAVERSAL: { 8361 synchronized(mWindowMap) { 8362 mWindowPlacerLocked.performSurfacePlacement(); 8363 } 8364 } break; 8365 8366 case ADD_STARTING: { 8367 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 8368 final StartingData sd = wtoken.startingData; 8369 8370 if (sd == null) { 8371 // Animation has been canceled... do nothing. 8372 return; 8373 } 8374 8375 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting " 8376 + wtoken + ": pkg=" + sd.pkg); 8377 8378 View view = null; 8379 try { 8380 final Configuration overrideConfig = wtoken != null && wtoken.mTask != null 8381 ? wtoken.mTask.mOverrideConfig : null; 8382 view = mPolicy.addStartingWindow(wtoken.token, sd.pkg, sd.theme, 8383 sd.compatInfo, sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, 8384 sd.windowFlags, overrideConfig); 8385 } catch (Exception e) { 8386 Slog.w(TAG_WM, "Exception when adding starting window", e); 8387 } 8388 8389 if (view != null) { 8390 boolean abort = false; 8391 8392 synchronized(mWindowMap) { 8393 if (wtoken.removed || wtoken.startingData == null) { 8394 // If the window was successfully added, then 8395 // we need to remove it. 8396 if (wtoken.startingWindow != null) { 8397 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, 8398 "Aborted starting " + wtoken 8399 + ": removed=" + wtoken.removed 8400 + " startingData=" + wtoken.startingData); 8401 wtoken.startingWindow = null; 8402 wtoken.startingData = null; 8403 abort = true; 8404 } 8405 } else { 8406 wtoken.startingView = view; 8407 } 8408 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM, 8409 "Added starting " + wtoken 8410 + ": startingWindow=" 8411 + wtoken.startingWindow + " startingView=" 8412 + wtoken.startingView); 8413 } 8414 8415 if (abort) { 8416 try { 8417 mPolicy.removeStartingWindow(wtoken.token, view); 8418 } catch (Exception e) { 8419 Slog.w(TAG_WM, "Exception when removing starting window", e); 8420 } 8421 } 8422 } 8423 } break; 8424 8425 case REMOVE_STARTING: { 8426 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 8427 IBinder token = null; 8428 View view = null; 8429 synchronized (mWindowMap) { 8430 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting " 8431 + wtoken + ": startingWindow=" 8432 + wtoken.startingWindow + " startingView=" 8433 + wtoken.startingView); 8434 if (wtoken.startingWindow != null) { 8435 view = wtoken.startingView; 8436 token = wtoken.token; 8437 wtoken.startingData = null; 8438 wtoken.startingView = null; 8439 wtoken.startingWindow = null; 8440 wtoken.startingDisplayed = false; 8441 } 8442 } 8443 if (view != null) { 8444 try { 8445 mPolicy.removeStartingWindow(token, view); 8446 } catch (Exception e) { 8447 Slog.w(TAG_WM, "Exception when removing starting window", e); 8448 } 8449 } 8450 } break; 8451 8452 case FINISHED_STARTING: { 8453 IBinder token = null; 8454 View view = null; 8455 while (true) { 8456 synchronized (mWindowMap) { 8457 final int N = mFinishedStarting.size(); 8458 if (N <= 0) { 8459 break; 8460 } 8461 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 8462 8463 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, 8464 "Finished starting " + wtoken 8465 + ": startingWindow=" + wtoken.startingWindow 8466 + " startingView=" + wtoken.startingView); 8467 8468 if (wtoken.startingWindow == null) { 8469 continue; 8470 } 8471 8472 view = wtoken.startingView; 8473 token = wtoken.token; 8474 wtoken.startingData = null; 8475 wtoken.startingView = null; 8476 wtoken.startingWindow = null; 8477 wtoken.startingDisplayed = false; 8478 } 8479 8480 try { 8481 mPolicy.removeStartingWindow(token, view); 8482 } catch (Exception e) { 8483 Slog.w(TAG_WM, "Exception when removing starting window", e); 8484 } 8485 } 8486 } break; 8487 8488 case REPORT_APPLICATION_TOKEN_DRAWN: { 8489 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 8490 8491 try { 8492 if (DEBUG_VISIBILITY) Slog.v( 8493 TAG_WM, "Reporting drawn in " + wtoken); 8494 wtoken.appToken.windowsDrawn(); 8495 } catch (RemoteException ex) { 8496 } 8497 } break; 8498 8499 case REPORT_APPLICATION_TOKEN_WINDOWS: { 8500 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 8501 8502 boolean nowVisible = msg.arg1 != 0; 8503 boolean nowGone = msg.arg2 != 0; 8504 8505 try { 8506 if (DEBUG_VISIBILITY) Slog.v( 8507 TAG_WM, "Reporting visible in " + wtoken 8508 + " visible=" + nowVisible 8509 + " gone=" + nowGone); 8510 if (nowVisible) { 8511 wtoken.appToken.windowsVisible(); 8512 } else { 8513 wtoken.appToken.windowsGone(); 8514 } 8515 } catch (RemoteException ex) { 8516 } 8517 } break; 8518 8519 case WINDOW_FREEZE_TIMEOUT: { 8520 // TODO(multidisplay): Can non-default displays rotate? 8521 synchronized (mWindowMap) { 8522 Slog.w(TAG_WM, "Window freeze timeout expired."); 8523 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 8524 final WindowList windows = getDefaultWindowListLocked(); 8525 int i = windows.size(); 8526 while (i > 0) { 8527 i--; 8528 WindowState w = windows.get(i); 8529 if (w.mOrientationChanging) { 8530 w.mOrientationChanging = false; 8531 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8532 - mDisplayFreezeTime); 8533 Slog.w(TAG_WM, "Force clearing orientation change: " + w); 8534 } 8535 } 8536 mWindowPlacerLocked.performSurfacePlacement(); 8537 } 8538 break; 8539 } 8540 8541 case APP_TRANSITION_TIMEOUT: { 8542 synchronized (mWindowMap) { 8543 if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty() 8544 || !mClosingApps.isEmpty()) { 8545 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT." 8546 + " isTransitionSet()=" + mAppTransition.isTransitionSet() 8547 + " mOpeningApps.size()=" + mOpeningApps.size() 8548 + " mClosingApps.size()=" + mClosingApps.size()); 8549 mAppTransition.setTimeout(); 8550 mWindowPlacerLocked.performSurfacePlacement(); 8551 } 8552 } 8553 break; 8554 } 8555 8556 case PERSIST_ANIMATION_SCALE: { 8557 Settings.Global.putFloat(mContext.getContentResolver(), 8558 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 8559 Settings.Global.putFloat(mContext.getContentResolver(), 8560 Settings.Global.TRANSITION_ANIMATION_SCALE, 8561 mTransitionAnimationScaleSetting); 8562 Settings.Global.putFloat(mContext.getContentResolver(), 8563 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 8564 break; 8565 } 8566 8567 case UPDATE_ANIMATION_SCALE: { 8568 @UpdateAnimationScaleMode 8569 final int mode = msg.arg1; 8570 switch (mode) { 8571 case WINDOW_ANIMATION_SCALE: { 8572 mWindowAnimationScaleSetting = Settings.Global.getFloat( 8573 mContext.getContentResolver(), 8574 Settings.Global.WINDOW_ANIMATION_SCALE, 8575 mWindowAnimationScaleSetting); 8576 break; 8577 } 8578 case TRANSITION_ANIMATION_SCALE: { 8579 mTransitionAnimationScaleSetting = Settings.Global.getFloat( 8580 mContext.getContentResolver(), 8581 Settings.Global.TRANSITION_ANIMATION_SCALE, 8582 mTransitionAnimationScaleSetting); 8583 break; 8584 } 8585 case ANIMATION_DURATION_SCALE: { 8586 mAnimatorDurationScaleSetting = Settings.Global.getFloat( 8587 mContext.getContentResolver(), 8588 Settings.Global.ANIMATOR_DURATION_SCALE, 8589 mAnimatorDurationScaleSetting); 8590 dispatchNewAnimatorScaleLocked(null); 8591 break; 8592 } 8593 } 8594 break; 8595 } 8596 8597 case FORCE_GC: { 8598 synchronized (mWindowMap) { 8599 // Since we're holding both mWindowMap and mAnimator we don't need to 8600 // hold mAnimator.mLayoutToAnim. 8601 if (mAnimator.isAnimating() || mAnimationScheduled) { 8602 // If we are animating, don't do the gc now but 8603 // delay a bit so we don't interrupt the animation. 8604 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 8605 return; 8606 } 8607 // If we are currently rotating the display, it will 8608 // schedule a new message when done. 8609 if (mDisplayFrozen) { 8610 return; 8611 } 8612 } 8613 Runtime.getRuntime().gc(); 8614 break; 8615 } 8616 8617 case ENABLE_SCREEN: { 8618 performEnableScreen(); 8619 break; 8620 } 8621 8622 case APP_FREEZE_TIMEOUT: { 8623 synchronized (mWindowMap) { 8624 Slog.w(TAG_WM, "App freeze timeout expired."); 8625 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 8626 final int numStacks = mStackIdToStack.size(); 8627 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8628 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 8629 final ArrayList<Task> tasks = stack.getTasks(); 8630 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8631 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8632 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8633 AppWindowToken tok = tokens.get(tokenNdx); 8634 if (tok.mAppAnimator.freezingScreen) { 8635 Slog.w(TAG_WM, "Force clearing freeze: " + tok); 8636 unsetAppFreezingScreenLocked(tok, true, true); 8637 } 8638 } 8639 } 8640 } 8641 } 8642 break; 8643 } 8644 8645 case CLIENT_FREEZE_TIMEOUT: { 8646 synchronized (mWindowMap) { 8647 if (mClientFreezingScreen) { 8648 mClientFreezingScreen = false; 8649 mLastFinishedFreezeSource = "client-timeout"; 8650 stopFreezingDisplayLocked(); 8651 } 8652 } 8653 break; 8654 } 8655 8656 case SEND_NEW_CONFIGURATION: { 8657 removeMessages(SEND_NEW_CONFIGURATION); 8658 sendNewConfiguration(); 8659 break; 8660 } 8661 8662 case REPORT_WINDOWS_CHANGE: { 8663 if (mWindowsChanged) { 8664 synchronized (mWindowMap) { 8665 mWindowsChanged = false; 8666 } 8667 notifyWindowsChanged(); 8668 } 8669 break; 8670 } 8671 8672 case DRAG_START_TIMEOUT: { 8673 IBinder win = (IBinder)msg.obj; 8674 if (DEBUG_DRAG) { 8675 Slog.w(TAG_WM, "Timeout starting drag by win " + win); 8676 } 8677 synchronized (mWindowMap) { 8678 // !!! TODO: ANR the app that has failed to start the drag in time 8679 if (mDragState != null) { 8680 mDragState.unregister(); 8681 mInputMonitor.updateInputWindowsLw(true /*force*/); 8682 mDragState.reset(); 8683 mDragState = null; 8684 } 8685 } 8686 break; 8687 } 8688 8689 case DRAG_END_TIMEOUT: { 8690 IBinder win = (IBinder)msg.obj; 8691 if (DEBUG_DRAG) { 8692 Slog.w(TAG_WM, "Timeout ending drag to win " + win); 8693 } 8694 synchronized (mWindowMap) { 8695 // !!! TODO: ANR the drag-receiving app 8696 if (mDragState != null) { 8697 mDragState.mDragResult = false; 8698 mDragState.endDragLw(); 8699 } 8700 } 8701 break; 8702 } 8703 8704 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 8705 notifyHardKeyboardStatusChange(); 8706 break; 8707 } 8708 8709 case BOOT_TIMEOUT: { 8710 performBootTimeout(); 8711 break; 8712 } 8713 8714 case WAITING_FOR_DRAWN_TIMEOUT: { 8715 Runnable callback = null; 8716 synchronized (mWindowMap) { 8717 Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 8718 mWaitingForDrawn.clear(); 8719 callback = mWaitingForDrawnCallback; 8720 mWaitingForDrawnCallback = null; 8721 } 8722 if (callback != null) { 8723 callback.run(); 8724 } 8725 break; 8726 } 8727 8728 case SHOW_STRICT_MODE_VIOLATION: { 8729 showStrictModeViolation(msg.arg1, msg.arg2); 8730 break; 8731 } 8732 8733 case SHOW_CIRCULAR_DISPLAY_MASK: { 8734 showCircularMask(msg.arg1 == 1); 8735 break; 8736 } 8737 8738 case SHOW_EMULATOR_DISPLAY_OVERLAY: { 8739 showEmulatorDisplayOverlay(); 8740 break; 8741 } 8742 8743 case DO_ANIMATION_CALLBACK: { 8744 try { 8745 ((IRemoteCallback)msg.obj).sendResult(null); 8746 } catch (RemoteException e) { 8747 } 8748 break; 8749 } 8750 8751 case DO_DISPLAY_ADDED: 8752 handleDisplayAdded(msg.arg1); 8753 break; 8754 8755 case DO_DISPLAY_REMOVED: 8756 synchronized (mWindowMap) { 8757 handleDisplayRemovedLocked(msg.arg1); 8758 } 8759 break; 8760 8761 case DO_DISPLAY_CHANGED: 8762 synchronized (mWindowMap) { 8763 handleDisplayChangedLocked(msg.arg1); 8764 } 8765 break; 8766 8767 case TWO_FINGER_SCROLL_START: { 8768 startScrollingTask((DisplayContent)msg.obj, msg.arg1, msg.arg2); 8769 } 8770 break; 8771 8772 case TAP_OUTSIDE_TASK: { 8773 handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2); 8774 } 8775 break; 8776 8777 case FINISH_TASK_POSITIONING: { 8778 finishPositioning(); 8779 } 8780 break; 8781 8782 case NOTIFY_ACTIVITY_DRAWN: 8783 try { 8784 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 8785 } catch (RemoteException e) { 8786 } 8787 break; 8788 case ALL_WINDOWS_DRAWN: { 8789 Runnable callback; 8790 synchronized (mWindowMap) { 8791 callback = mWaitingForDrawnCallback; 8792 mWaitingForDrawnCallback = null; 8793 } 8794 if (callback != null) { 8795 callback.run(); 8796 } 8797 } 8798 case NEW_ANIMATOR_SCALE: { 8799 float scale = getCurrentAnimatorScale(); 8800 ValueAnimator.setDurationScale(scale); 8801 Session session = (Session)msg.obj; 8802 if (session != null) { 8803 try { 8804 session.mCallback.onAnimatorScaleChanged(scale); 8805 } catch (RemoteException e) { 8806 } 8807 } else { 8808 ArrayList<IWindowSessionCallback> callbacks 8809 = new ArrayList<IWindowSessionCallback>(); 8810 synchronized (mWindowMap) { 8811 for (int i=0; i<mSessions.size(); i++) { 8812 callbacks.add(mSessions.valueAt(i).mCallback); 8813 } 8814 8815 } 8816 for (int i=0; i<callbacks.size(); i++) { 8817 try { 8818 callbacks.get(i).onAnimatorScaleChanged(scale); 8819 } catch (RemoteException e) { 8820 } 8821 } 8822 } 8823 } 8824 break; 8825 case CHECK_IF_BOOT_ANIMATION_FINISHED: { 8826 final boolean bootAnimationComplete; 8827 synchronized (mWindowMap) { 8828 if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:"); 8829 bootAnimationComplete = checkBootAnimationCompleteLocked(); 8830 } 8831 if (bootAnimationComplete) { 8832 performEnableScreen(); 8833 } 8834 } 8835 break; 8836 case RESET_ANR_MESSAGE: { 8837 synchronized (mWindowMap) { 8838 mLastANRState = null; 8839 } 8840 } 8841 break; 8842 case WALLPAPER_DRAW_PENDING_TIMEOUT: { 8843 synchronized (mWindowMap) { 8844 if (mWallpaperControllerLocked.processWallpaperDrawPendingTimeout()) { 8845 mWindowPlacerLocked.performSurfacePlacement(); 8846 } 8847 } 8848 } 8849 case UPDATE_DOCKED_STACK_DIVIDER: { 8850 synchronized (mWindowMap) { 8851 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8852 displayContent.getDockedDividerController().reevaluateVisibility(false); 8853 adjustForImeIfNeeded(displayContent); 8854 } 8855 } 8856 break; 8857 case RESIZE_TASK: { 8858 try { 8859 mActivityManager.resizeTask(msg.arg1, (Rect) msg.obj, msg.arg2); 8860 } catch (RemoteException e) { 8861 // This will not happen since we are in the same process. 8862 } 8863 } 8864 break; 8865 case RESIZE_STACK: { 8866 try { 8867 mActivityManager.resizeStack( 8868 msg.arg1, (Rect) msg.obj, msg.arg2 == 1, false, false, -1); 8869 } catch (RemoteException e) { 8870 // This will not happen since we are in the same process. 8871 } 8872 } 8873 break; 8874 case WINDOW_REPLACEMENT_TIMEOUT: { 8875 synchronized (mWindowMap) { 8876 for (int i = mReplacingWindowTimeouts.size() - 1; i >= 0; i--) { 8877 final AppWindowToken token = mReplacingWindowTimeouts.get(i); 8878 token.clearTimedoutReplacesLocked(); 8879 } 8880 mReplacingWindowTimeouts.clear(); 8881 } 8882 } 8883 case NOTIFY_APP_TRANSITION_STARTING: { 8884 mAmInternal.notifyAppTransitionStarting(msg.arg1); 8885 } 8886 break; 8887 case NOTIFY_APP_TRANSITION_CANCELLED: { 8888 mAmInternal.notifyAppTransitionCancelled(); 8889 } 8890 break; 8891 case NOTIFY_APP_TRANSITION_FINISHED: { 8892 mAmInternal.notifyAppTransitionFinished(); 8893 } 8894 break; 8895 case NOTIFY_STARTING_WINDOW_DRAWN: { 8896 mAmInternal.notifyStartingWindowDrawn(); 8897 } 8898 break; 8899 case WINDOW_HIDE_TIMEOUT: { 8900 final WindowState window = (WindowState) msg.obj; 8901 synchronized(mWindowMap) { 8902 // TODO: This is all about fixing b/21693547 8903 // where partially initialized Toasts get stuck 8904 // around and keep the screen on. We'd like 8905 // to just remove the toast...but this can cause clients 8906 // who miss the timeout due to normal circumstances (e.g. 8907 // running under debugger) to crash (b/29105388). The windows will 8908 // eventually be removed when the client process finishes. 8909 // The best we can do for now is remove the FLAG_KEEP_SCREEN_ON 8910 // and prevent the symptoms of b/21693547. Since apps don't 8911 // support windows being removed under them we hide the window 8912 // and it will be removed when the app dies. 8913 window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON; 8914 window.hidePermanentlyLw(); 8915 window.setDisplayLayoutNeeded(); 8916 mWindowPlacerLocked.performSurfacePlacement(); 8917 } 8918 } 8919 break; 8920 case NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED: { 8921 mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1); 8922 } 8923 break; 8924 case SEAMLESS_ROTATION_TIMEOUT: { 8925 // Rotation only supported on primary display. 8926 // TODO(multi-display) 8927 synchronized(mWindowMap) { 8928 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8929 final WindowList windows = displayContent.getWindowList(); 8930 boolean layoutNeeded = false; 8931 for (int i = windows.size() - 1; i >= 0; i--) { 8932 WindowState w = windows.get(i); 8933 if (w.mSeamlesslyRotated) { 8934 layoutNeeded = true; 8935 w.setDisplayLayoutNeeded(); 8936 markForSeamlessRotation(w, false); 8937 } 8938 } 8939 if (layoutNeeded) { 8940 mWindowPlacerLocked.performSurfacePlacement(); 8941 } 8942 } 8943 } 8944 break; 8945 } 8946 if (DEBUG_WINDOW_TRACE) { 8947 Slog.v(TAG_WM, "handleMessage: exit"); 8948 } 8949 } 8950 } 8951 destroyPreservedSurfaceLocked()8952 void destroyPreservedSurfaceLocked() { 8953 for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) { 8954 final WindowState w = mDestroyPreservedSurface.get(i); 8955 w.mWinAnimator.destroyPreservedSurfaceLocked(); 8956 } 8957 mDestroyPreservedSurface.clear(); 8958 } 8959 stopUsingSavedSurfaceLocked()8960 void stopUsingSavedSurfaceLocked() { 8961 for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) { 8962 final AppWindowToken wtoken = mFinishedEarlyAnim.get(i); 8963 wtoken.stopUsingSavedSurfaceLocked(); 8964 } 8965 mFinishedEarlyAnim.clear(); 8966 } 8967 8968 // ------------------------------------------------------------- 8969 // IWindowManager API 8970 // ------------------------------------------------------------- 8971 8972 @Override openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext)8973 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 8974 IInputContext inputContext) { 8975 if (client == null) throw new IllegalArgumentException("null client"); 8976 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 8977 Session session = new Session(this, callback, client, inputContext); 8978 return session; 8979 } 8980 8981 @Override inputMethodClientHasFocus(IInputMethodClient client)8982 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 8983 synchronized (mWindowMap) { 8984 // The focus for the client is the window immediately below 8985 // where we would place the input method window. 8986 int idx = findDesiredInputMethodWindowIndexLocked(false); 8987 if (idx > 0) { 8988 // TODO(multidisplay): IMEs are only supported on the default display. 8989 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 8990 if (DEBUG_INPUT_METHOD) { 8991 Slog.i(TAG_WM, "Desired input method target: " + imFocus); 8992 Slog.i(TAG_WM, "Current focus: " + mCurrentFocus); 8993 Slog.i(TAG_WM, "Last focus: " + mLastFocus); 8994 } 8995 if (imFocus != null) { 8996 // This may be a starting window, in which case we still want 8997 // to count it as okay. 8998 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 8999 && imFocus.mAppToken != null) { 9000 // The client has definitely started, so it really should 9001 // have a window in this app token. Let's look for it. 9002 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 9003 WindowState w = imFocus.mAppToken.windows.get(i); 9004 if (w != imFocus) { 9005 Log.i(TAG_WM, "Switching to real app window: " + w); 9006 imFocus = w; 9007 break; 9008 } 9009 } 9010 } 9011 if (DEBUG_INPUT_METHOD) { 9012 Slog.i(TAG_WM, "IM target client: " + imFocus.mSession.mClient); 9013 if (imFocus.mSession.mClient != null) { 9014 Slog.i(TAG_WM, "IM target client binder: " 9015 + imFocus.mSession.mClient.asBinder()); 9016 Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder()); 9017 } 9018 } 9019 if (imFocus.mSession.mClient != null && 9020 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 9021 return true; 9022 } 9023 } 9024 } 9025 9026 // Okay, how about this... what is the current focus? 9027 // It seems in some cases we may not have moved the IM 9028 // target window, such as when it was in a pop-up window, 9029 // so let's also look at the current focus. (An example: 9030 // go to Gmail, start searching so the keyboard goes up, 9031 // press home. Sometimes the IME won't go down.) 9032 // Would be nice to fix this more correctly, but it's 9033 // way at the end of a release, and this should be good enough. 9034 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 9035 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 9036 return true; 9037 } 9038 } 9039 return false; 9040 } 9041 9042 @Override getInitialDisplaySize(int displayId, Point size)9043 public void getInitialDisplaySize(int displayId, Point size) { 9044 synchronized (mWindowMap) { 9045 final DisplayContent displayContent = getDisplayContentLocked(displayId); 9046 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 9047 size.x = displayContent.mInitialDisplayWidth; 9048 size.y = displayContent.mInitialDisplayHeight; 9049 } 9050 } 9051 } 9052 9053 @Override getBaseDisplaySize(int displayId, Point size)9054 public void getBaseDisplaySize(int displayId, Point size) { 9055 synchronized (mWindowMap) { 9056 final DisplayContent displayContent = getDisplayContentLocked(displayId); 9057 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 9058 size.x = displayContent.mBaseDisplayWidth; 9059 size.y = displayContent.mBaseDisplayHeight; 9060 } 9061 } 9062 } 9063 9064 @Override setForcedDisplaySize(int displayId, int width, int height)9065 public void setForcedDisplaySize(int displayId, int width, int height) { 9066 if (mContext.checkCallingOrSelfPermission( 9067 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 9068 PackageManager.PERMISSION_GRANTED) { 9069 throw new SecurityException("Must hold permission " + 9070 android.Manifest.permission.WRITE_SECURE_SETTINGS); 9071 } 9072 if (displayId != Display.DEFAULT_DISPLAY) { 9073 throw new IllegalArgumentException("Can only set the default display"); 9074 } 9075 final long ident = Binder.clearCallingIdentity(); 9076 try { 9077 synchronized(mWindowMap) { 9078 // Set some sort of reasonable bounds on the size of the display that we 9079 // will try to emulate. 9080 final int MIN_WIDTH = 200; 9081 final int MIN_HEIGHT = 200; 9082 final int MAX_SCALE = 2; 9083 final DisplayContent displayContent = getDisplayContentLocked(displayId); 9084 if (displayContent != null) { 9085 width = Math.min(Math.max(width, MIN_WIDTH), 9086 displayContent.mInitialDisplayWidth * MAX_SCALE); 9087 height = Math.min(Math.max(height, MIN_HEIGHT), 9088 displayContent.mInitialDisplayHeight * MAX_SCALE); 9089 setForcedDisplaySizeLocked(displayContent, width, height); 9090 Settings.Global.putString(mContext.getContentResolver(), 9091 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 9092 } 9093 } 9094 } finally { 9095 Binder.restoreCallingIdentity(ident); 9096 } 9097 } 9098 9099 @Override setForcedDisplayScalingMode(int displayId, int mode)9100 public void setForcedDisplayScalingMode(int displayId, int mode) { 9101 if (mContext.checkCallingOrSelfPermission( 9102 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 9103 PackageManager.PERMISSION_GRANTED) { 9104 throw new SecurityException("Must hold permission " + 9105 android.Manifest.permission.WRITE_SECURE_SETTINGS); 9106 } 9107 if (displayId != Display.DEFAULT_DISPLAY) { 9108 throw new IllegalArgumentException("Can only set the default display"); 9109 } 9110 final long ident = Binder.clearCallingIdentity(); 9111 try { 9112 synchronized(mWindowMap) { 9113 final DisplayContent displayContent = getDisplayContentLocked(displayId); 9114 if (displayContent != null) { 9115 if (mode < 0 || mode > 1) { 9116 mode = 0; 9117 } 9118 setForcedDisplayScalingModeLocked(displayContent, mode); 9119 Settings.Global.putInt(mContext.getContentResolver(), 9120 Settings.Global.DISPLAY_SCALING_FORCE, mode); 9121 } 9122 } 9123 } finally { 9124 Binder.restoreCallingIdentity(ident); 9125 } 9126 } 9127 setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode)9128 private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) { 9129 Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off")); 9130 displayContent.mDisplayScalingDisabled = (mode != 0); 9131 reconfigureDisplayLocked(displayContent); 9132 } 9133 readForcedDisplayPropertiesLocked(final DisplayContent displayContent)9134 private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) { 9135 // Display size. 9136 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 9137 Settings.Global.DISPLAY_SIZE_FORCED); 9138 if (sizeStr == null || sizeStr.length() == 0) { 9139 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 9140 } 9141 if (sizeStr != null && sizeStr.length() > 0) { 9142 final int pos = sizeStr.indexOf(','); 9143 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 9144 int width, height; 9145 try { 9146 width = Integer.parseInt(sizeStr.substring(0, pos)); 9147 height = Integer.parseInt(sizeStr.substring(pos+1)); 9148 if (displayContent.mBaseDisplayWidth != width 9149 || displayContent.mBaseDisplayHeight != height) { 9150 Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height); 9151 displayContent.mBaseDisplayWidth = width; 9152 displayContent.mBaseDisplayHeight = height; 9153 } 9154 } catch (NumberFormatException ex) { 9155 } 9156 } 9157 } 9158 9159 // Display density. 9160 final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId); 9161 if (density != 0) { 9162 displayContent.mBaseDisplayDensity = density; 9163 } 9164 9165 // Display scaling mode. 9166 int mode = Settings.Global.getInt(mContext.getContentResolver(), 9167 Settings.Global.DISPLAY_SCALING_FORCE, 0); 9168 if (mode != 0) { 9169 Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED"); 9170 displayContent.mDisplayScalingDisabled = true; 9171 } 9172 } 9173 9174 // displayContent must not be null setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height)9175 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 9176 Slog.i(TAG_WM, "Using new display size: " + width + "x" + height); 9177 displayContent.mBaseDisplayWidth = width; 9178 displayContent.mBaseDisplayHeight = height; 9179 reconfigureDisplayLocked(displayContent); 9180 } 9181 9182 @Override clearForcedDisplaySize(int displayId)9183 public void clearForcedDisplaySize(int displayId) { 9184 if (mContext.checkCallingOrSelfPermission( 9185 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 9186 PackageManager.PERMISSION_GRANTED) { 9187 throw new SecurityException("Must hold permission " + 9188 android.Manifest.permission.WRITE_SECURE_SETTINGS); 9189 } 9190 if (displayId != Display.DEFAULT_DISPLAY) { 9191 throw new IllegalArgumentException("Can only set the default display"); 9192 } 9193 final long ident = Binder.clearCallingIdentity(); 9194 try { 9195 synchronized(mWindowMap) { 9196 final DisplayContent displayContent = getDisplayContentLocked(displayId); 9197 if (displayContent != null) { 9198 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 9199 displayContent.mInitialDisplayHeight); 9200 Settings.Global.putString(mContext.getContentResolver(), 9201 Settings.Global.DISPLAY_SIZE_FORCED, ""); 9202 } 9203 } 9204 } finally { 9205 Binder.restoreCallingIdentity(ident); 9206 } 9207 } 9208 9209 @Override getInitialDisplayDensity(int displayId)9210 public int getInitialDisplayDensity(int displayId) { 9211 synchronized (mWindowMap) { 9212 final DisplayContent displayContent = getDisplayContentLocked(displayId); 9213 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 9214 return displayContent.mInitialDisplayDensity; 9215 } 9216 } 9217 return -1; 9218 } 9219 9220 @Override getBaseDisplayDensity(int displayId)9221 public int getBaseDisplayDensity(int displayId) { 9222 synchronized (mWindowMap) { 9223 final DisplayContent displayContent = getDisplayContentLocked(displayId); 9224 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 9225 return displayContent.mBaseDisplayDensity; 9226 } 9227 } 9228 return -1; 9229 } 9230 9231 @Override setForcedDisplayDensityForUser(int displayId, int density, int userId)9232 public void setForcedDisplayDensityForUser(int displayId, int density, int userId) { 9233 if (mContext.checkCallingOrSelfPermission( 9234 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 9235 PackageManager.PERMISSION_GRANTED) { 9236 throw new SecurityException("Must hold permission " + 9237 android.Manifest.permission.WRITE_SECURE_SETTINGS); 9238 } 9239 if (displayId != Display.DEFAULT_DISPLAY) { 9240 throw new IllegalArgumentException("Can only set the default display"); 9241 } 9242 9243 final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 9244 Binder.getCallingUid(), userId, false, true, "setForcedDisplayDensityForUser", 9245 null); 9246 final long ident = Binder.clearCallingIdentity(); 9247 try { 9248 synchronized(mWindowMap) { 9249 final DisplayContent displayContent = getDisplayContentLocked(displayId); 9250 if (displayContent != null && mCurrentUserId == targetUserId) { 9251 setForcedDisplayDensityLocked(displayContent, density); 9252 } 9253 Settings.Secure.putStringForUser(mContext.getContentResolver(), 9254 Settings.Secure.DISPLAY_DENSITY_FORCED, 9255 Integer.toString(density), targetUserId); 9256 } 9257 } finally { 9258 Binder.restoreCallingIdentity(ident); 9259 } 9260 } 9261 9262 @Override clearForcedDisplayDensityForUser(int displayId, int userId)9263 public void clearForcedDisplayDensityForUser(int displayId, int userId) { 9264 if (mContext.checkCallingOrSelfPermission( 9265 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 9266 PackageManager.PERMISSION_GRANTED) { 9267 throw new SecurityException("Must hold permission " + 9268 android.Manifest.permission.WRITE_SECURE_SETTINGS); 9269 } 9270 if (displayId != Display.DEFAULT_DISPLAY) { 9271 throw new IllegalArgumentException("Can only set the default display"); 9272 } 9273 9274 final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 9275 Binder.getCallingUid(), userId, false, true, "clearForcedDisplayDensityForUser", 9276 null); 9277 final long ident = Binder.clearCallingIdentity(); 9278 try { 9279 synchronized(mWindowMap) { 9280 final DisplayContent displayContent = getDisplayContentLocked(displayId); 9281 if (displayContent != null && mCurrentUserId == callingUserId) { 9282 setForcedDisplayDensityLocked(displayContent, 9283 displayContent.mInitialDisplayDensity); 9284 } 9285 Settings.Secure.putStringForUser(mContext.getContentResolver(), 9286 Settings.Secure.DISPLAY_DENSITY_FORCED, "", callingUserId); 9287 } 9288 } finally { 9289 Binder.restoreCallingIdentity(ident); 9290 } 9291 } 9292 9293 /** 9294 * @param userId the ID of the user 9295 * @return the forced display density for the specified user, if set, or 9296 * {@code 0} if not set 9297 */ getForcedDisplayDensityForUserLocked(int userId)9298 private int getForcedDisplayDensityForUserLocked(int userId) { 9299 String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(), 9300 Settings.Secure.DISPLAY_DENSITY_FORCED, userId); 9301 if (densityStr == null || densityStr.length() == 0) { 9302 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 9303 } 9304 if (densityStr != null && densityStr.length() > 0) { 9305 try { 9306 return Integer.parseInt(densityStr); 9307 } catch (NumberFormatException ex) { 9308 } 9309 } 9310 return 0; 9311 } 9312 9313 /** 9314 * Forces the given display to the use the specified density. 9315 * 9316 * @param displayContent the display to modify 9317 * @param density the density in DPI to use 9318 */ setForcedDisplayDensityLocked(@onNull DisplayContent displayContent, int density)9319 private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent, 9320 int density) { 9321 displayContent.mBaseDisplayDensity = density; 9322 reconfigureDisplayLocked(displayContent); 9323 } 9324 9325 // displayContent must not be null reconfigureDisplayLocked(DisplayContent displayContent)9326 private void reconfigureDisplayLocked(DisplayContent displayContent) { 9327 // TODO: Multidisplay: for now only use with default display. 9328 if (!mDisplayReady) { 9329 return; 9330 } 9331 configureDisplayPolicyLocked(displayContent); 9332 displayContent.layoutNeeded = true; 9333 9334 boolean configChanged = updateOrientationFromAppTokensLocked(false); 9335 mTempConfiguration.setToDefaults(); 9336 mTempConfiguration.updateFrom(mCurConfiguration); 9337 computeScreenConfigurationLocked(mTempConfiguration); 9338 configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0; 9339 9340 if (configChanged) { 9341 mWaitingForConfig = true; 9342 startFreezingDisplayLocked(false, 0, 0); 9343 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9344 if (!mReconfigureOnConfigurationChanged.contains(displayContent)) { 9345 mReconfigureOnConfigurationChanged.add(displayContent); 9346 } 9347 } 9348 9349 mWindowPlacerLocked.performSurfacePlacement(); 9350 } 9351 configureDisplayPolicyLocked(DisplayContent displayContent)9352 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 9353 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 9354 displayContent.mBaseDisplayWidth, 9355 displayContent.mBaseDisplayHeight, 9356 displayContent.mBaseDisplayDensity); 9357 9358 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9359 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 9360 displayInfo.overscanLeft, displayInfo.overscanTop, 9361 displayInfo.overscanRight, displayInfo.overscanBottom); 9362 } 9363 9364 @Override setOverscan(int displayId, int left, int top, int right, int bottom)9365 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 9366 if (mContext.checkCallingOrSelfPermission( 9367 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 9368 PackageManager.PERMISSION_GRANTED) { 9369 throw new SecurityException("Must hold permission " + 9370 android.Manifest.permission.WRITE_SECURE_SETTINGS); 9371 } 9372 final long ident = Binder.clearCallingIdentity(); 9373 try { 9374 synchronized(mWindowMap) { 9375 DisplayContent displayContent = getDisplayContentLocked(displayId); 9376 if (displayContent != null) { 9377 setOverscanLocked(displayContent, left, top, right, bottom); 9378 } 9379 } 9380 } finally { 9381 Binder.restoreCallingIdentity(ident); 9382 } 9383 } 9384 setOverscanLocked(DisplayContent displayContent, int left, int top, int right, int bottom)9385 private void setOverscanLocked(DisplayContent displayContent, 9386 int left, int top, int right, int bottom) { 9387 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9388 displayInfo.overscanLeft = left; 9389 displayInfo.overscanTop = top; 9390 displayInfo.overscanRight = right; 9391 displayInfo.overscanBottom = bottom; 9392 9393 mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top, 9394 right, bottom); 9395 mDisplaySettings.writeSettingsLocked(); 9396 9397 reconfigureDisplayLocked(displayContent); 9398 } 9399 9400 // ------------------------------------------------------------- 9401 // Internals 9402 // ------------------------------------------------------------- 9403 windowForClientLocked(Session session, IWindow client, boolean throwOnError)9404 final WindowState windowForClientLocked(Session session, IWindow client, 9405 boolean throwOnError) { 9406 return windowForClientLocked(session, client.asBinder(), throwOnError); 9407 } 9408 windowForClientLocked(Session session, IBinder client, boolean throwOnError)9409 final WindowState windowForClientLocked(Session session, IBinder client, 9410 boolean throwOnError) { 9411 WindowState win = mWindowMap.get(client); 9412 if (localLOGV) Slog.v( 9413 TAG_WM, "Looking up client " + client + ": " + win); 9414 if (win == null) { 9415 RuntimeException ex = new IllegalArgumentException( 9416 "Requested window " + client + " does not exist"); 9417 if (throwOnError) { 9418 throw ex; 9419 } 9420 Slog.w(TAG_WM, "Failed looking up window", ex); 9421 return null; 9422 } 9423 if (session != null && win.mSession != session) { 9424 RuntimeException ex = new IllegalArgumentException( 9425 "Requested window " + client + " is in session " + 9426 win.mSession + ", not " + session); 9427 if (throwOnError) { 9428 throw ex; 9429 } 9430 Slog.w(TAG_WM, "Failed looking up window", ex); 9431 return null; 9432 } 9433 9434 return win; 9435 } 9436 rebuildAppWindowListLocked()9437 final void rebuildAppWindowListLocked() { 9438 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 9439 } 9440 rebuildAppWindowListLocked(final DisplayContent displayContent)9441 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 9442 final WindowList windows = displayContent.getWindowList(); 9443 int NW = windows.size(); 9444 int i; 9445 int lastBelow = -1; 9446 int numRemoved = 0; 9447 9448 if (mRebuildTmp.length < NW) { 9449 mRebuildTmp = new WindowState[NW+10]; 9450 } 9451 9452 // First remove all existing app windows. 9453 i=0; 9454 while (i < NW) { 9455 WindowState w = windows.get(i); 9456 if (w.mAppToken != null) { 9457 WindowState win = windows.remove(i); 9458 win.mRebuilding = true; 9459 mRebuildTmp[numRemoved] = win; 9460 mWindowsChanged = true; 9461 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win); 9462 NW--; 9463 numRemoved++; 9464 continue; 9465 } else if (lastBelow == i-1) { 9466 if (w.mAttrs.type == TYPE_WALLPAPER) { 9467 lastBelow = i; 9468 } 9469 } 9470 i++; 9471 } 9472 9473 // Keep whatever windows were below the app windows still below, 9474 // by skipping them. 9475 lastBelow++; 9476 i = lastBelow; 9477 9478 // First add all of the exiting app tokens... these are no longer 9479 // in the main app list, but still have windows shown. We put them 9480 // in the back because now that the animation is over we no longer 9481 // will care about them. 9482 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 9483 final int numStacks = stacks.size(); 9484 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 9485 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 9486 int NT = exitingAppTokens.size(); 9487 for (int j = 0; j < NT; j++) { 9488 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 9489 } 9490 } 9491 9492 // And add in the still active app tokens in Z order. 9493 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 9494 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9495 final int numTasks = tasks.size(); 9496 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 9497 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9498 final int numTokens = tokens.size(); 9499 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 9500 final AppWindowToken wtoken = tokens.get(tokenNdx); 9501 if (wtoken.mIsExiting && !wtoken.waitingForReplacement()) { 9502 continue; 9503 } 9504 i = reAddAppWindowsLocked(displayContent, i, wtoken); 9505 } 9506 } 9507 } 9508 9509 i -= lastBelow; 9510 if (i != numRemoved) { 9511 displayContent.layoutNeeded = true; 9512 Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed " 9513 + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() " 9514 + " callers=" + Debug.getCallers(10)); 9515 for (i = 0; i < numRemoved; i++) { 9516 WindowState ws = mRebuildTmp[i]; 9517 if (ws.mRebuilding) { 9518 StringWriter sw = new StringWriter(); 9519 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 9520 ws.dump(pw, "", true); 9521 pw.flush(); 9522 Slog.w(TAG_WM, "This window was lost: " + ws); 9523 Slog.w(TAG_WM, sw.toString()); 9524 ws.mWinAnimator.destroySurfaceLocked(); 9525 } 9526 } 9527 Slog.w(TAG_WM, "Current app token list:"); 9528 dumpAppTokensLocked(); 9529 Slog.w(TAG_WM, "Final window list:"); 9530 dumpWindowsLocked(); 9531 } 9532 Arrays.fill(mRebuildTmp, null); 9533 } 9534 makeWindowFreezingScreenIfNeededLocked(WindowState w)9535 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 9536 // If the screen is currently frozen or off, then keep 9537 // it frozen/off until this window draws at its new 9538 // orientation. 9539 if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { 9540 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w); 9541 w.mOrientationChanging = true; 9542 w.mLastFreezeDuration = 0; 9543 mWindowPlacerLocked.mOrientationChangeComplete = false; 9544 if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) { 9545 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; 9546 // XXX should probably keep timeout from 9547 // when we first froze the display. 9548 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9549 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 9550 WINDOW_FREEZE_TIMEOUT_DURATION); 9551 } 9552 } 9553 } 9554 9555 /** 9556 * @return bitmap indicating if another pass through layout must be made. 9557 */ handleAnimatingStoppedAndTransitionLocked()9558 int handleAnimatingStoppedAndTransitionLocked() { 9559 int changes = 0; 9560 9561 mAppTransition.setIdle(); 9562 9563 for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) { 9564 final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i); 9565 mAppTransition.notifyAppTransitionFinishedLocked(token); 9566 } 9567 mNoAnimationNotifyOnTransitionFinished.clear(); 9568 9569 mWallpaperControllerLocked.hideDeferredWallpapersIfNeeded(); 9570 9571 // Restore window app tokens to the ActivityManager views 9572 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 9573 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9574 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9575 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9576 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9577 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9578 tokens.get(tokenNdx).sendingToBottom = false; 9579 } 9580 } 9581 } 9582 rebuildAppWindowListLocked(); 9583 9584 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 9585 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM, 9586 "Wallpaper layer changed: assigning layers + relayout"); 9587 moveInputMethodWindowsIfNeededLocked(true); 9588 mWindowPlacerLocked.mWallpaperMayChange = true; 9589 // Since the window list has been rebuilt, focus might 9590 // have to be recomputed since the actual order of windows 9591 // might have changed again. 9592 mFocusMayChange = true; 9593 9594 return changes; 9595 } 9596 updateResizingWindows(final WindowState w)9597 void updateResizingWindows(final WindowState w) { 9598 final WindowStateAnimator winAnimator = w.mWinAnimator; 9599 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq && !w.isGoneForLayoutLw()) { 9600 final Task task = w.getTask(); 9601 // In the case of stack bound animations, the window frames 9602 // will update (unlike other animations which just modifiy 9603 // various transformation properties). We don't want to 9604 // notify the client of frame changes in this case. Not only 9605 // is it a lot of churn, but the frame may not correspond 9606 // to the surface size or the onscreen area at various 9607 // phases in the animation, and the client will become 9608 // sad and confused. 9609 if (task != null && task.mStack.getBoundsAnimating()) { 9610 return; 9611 } 9612 w.setReportResizeHints(); 9613 boolean configChanged = w.isConfigChanged(); 9614 if (DEBUG_CONFIGURATION && configChanged) { 9615 Slog.v(TAG_WM, "Win " + w + " config changed: " 9616 + mCurConfiguration); 9617 } 9618 final boolean dragResizingChanged = w.isDragResizeChanged() 9619 && !w.isDragResizingChangeReported(); 9620 9621 if (localLOGV) Slog.v(TAG_WM, "Resizing " + w 9622 + ": configChanged=" + configChanged 9623 + " dragResizingChanged=" + dragResizingChanged 9624 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 9625 9626 // We update mLastFrame always rather than in the conditional with the 9627 // last inset variables, because mFrameSizeChanged only tracks the 9628 // width and height changing. 9629 w.mLastFrame.set(w.mFrame); 9630 9631 if (w.mContentInsetsChanged 9632 || w.mVisibleInsetsChanged 9633 || winAnimator.mSurfaceResized 9634 || w.mOutsetsChanged 9635 || w.mFrameSizeChanged 9636 || configChanged 9637 || dragResizingChanged 9638 || !w.isResizedWhileNotDragResizingReported()) { 9639 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 9640 Slog.v(TAG_WM, "Resize reasons for w=" + w + ": " 9641 + " contentInsetsChanged=" + w.mContentInsetsChanged 9642 + " " + w.mContentInsets.toShortString() 9643 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 9644 + " " + w.mVisibleInsets.toShortString() 9645 + " stableInsetsChanged=" + w.mStableInsetsChanged 9646 + " " + w.mStableInsets.toShortString() 9647 + " outsetsChanged=" + w.mOutsetsChanged 9648 + " " + w.mOutsets.toShortString() 9649 + " surfaceResized=" + winAnimator.mSurfaceResized 9650 + " configChanged=" + configChanged 9651 + " dragResizingChanged=" + dragResizingChanged 9652 + " resizedWhileNotDragResizingReported=" 9653 + w.isResizedWhileNotDragResizingReported()); 9654 } 9655 9656 // If it's a dead window left on screen, and the configuration changed, 9657 // there is nothing we can do about it. Remove the window now. 9658 if (w.mAppToken != null && w.mAppDied) { 9659 w.mAppToken.removeAllDeadWindows(); 9660 return; 9661 } 9662 9663 w.mLastOverscanInsets.set(w.mOverscanInsets); 9664 w.mLastContentInsets.set(w.mContentInsets); 9665 w.mLastVisibleInsets.set(w.mVisibleInsets); 9666 w.mLastStableInsets.set(w.mStableInsets); 9667 w.mLastOutsets.set(w.mOutsets); 9668 makeWindowFreezingScreenIfNeededLocked(w); 9669 // If the orientation is changing, or we're starting or ending 9670 // a drag resizing action, then we need to hold off on unfreezing 9671 // the display until this window has been redrawn; to do that, 9672 // we need to go through the process of getting informed by the 9673 // application when it has finished drawing. 9674 if (w.mOrientationChanging || dragResizingChanged 9675 || w.isResizedWhileNotDragResizing()) { 9676 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) { 9677 Slog.v(TAG_WM, "Orientation or resize start waiting for draw" 9678 + ", mDrawState=DRAW_PENDING in " + w 9679 + ", surfaceController " + winAnimator.mSurfaceController); 9680 } 9681 winAnimator.mDrawState = DRAW_PENDING; 9682 if (w.mAppToken != null) { 9683 w.mAppToken.clearAllDrawn(); 9684 } 9685 } 9686 if (!mResizingWindows.contains(w)) { 9687 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM, 9688 "Resizing window " + w); 9689 mResizingWindows.add(w); 9690 } 9691 } else if (w.mOrientationChanging) { 9692 if (w.isDrawnLw()) { 9693 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 9694 "Orientation not waiting for draw in " 9695 + w + ", surfaceController " + winAnimator.mSurfaceController); 9696 w.mOrientationChanging = false; 9697 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 9698 - mDisplayFreezeTime); 9699 } 9700 } 9701 } 9702 } 9703 checkDrawnWindowsLocked()9704 void checkDrawnWindowsLocked() { 9705 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9706 return; 9707 } 9708 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9709 WindowState win = mWaitingForDrawn.get(j); 9710 if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win + 9711 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9712 " mHasSurface=" + win.mHasSurface + 9713 " drawState=" + win.mWinAnimator.mDrawState); 9714 if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) { 9715 // Window has been removed or hidden; no draw will now happen, so stop waiting. 9716 if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win); 9717 mWaitingForDrawn.remove(win); 9718 } else if (win.hasDrawnLw()) { 9719 // Window is now drawn (and shown). 9720 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win); 9721 mWaitingForDrawn.remove(win); 9722 } 9723 } 9724 if (mWaitingForDrawn.isEmpty()) { 9725 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!"); 9726 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9727 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9728 } 9729 } 9730 setHoldScreenLocked(final Session newHoldScreen)9731 void setHoldScreenLocked(final Session newHoldScreen) { 9732 final boolean hold = newHoldScreen != null; 9733 9734 if (hold && mHoldingScreenOn != newHoldScreen) { 9735 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9736 } 9737 mHoldingScreenOn = newHoldScreen; 9738 9739 final boolean state = mHoldingScreenWakeLock.isHeld(); 9740 if (hold != state) { 9741 if (hold) { 9742 if (DEBUG_KEEP_SCREEN_ON) { 9743 Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to " + 9744 mWindowPlacerLocked.mHoldScreenWindow); 9745 } 9746 mLastWakeLockHoldingWindow = mWindowPlacerLocked.mHoldScreenWindow; 9747 mLastWakeLockObscuringWindow = null; 9748 mHoldingScreenWakeLock.acquire(); 9749 mPolicy.keepScreenOnStartedLw(); 9750 } else { 9751 if (DEBUG_KEEP_SCREEN_ON) { 9752 Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by " + 9753 mWindowPlacerLocked.mObsuringWindow); 9754 } 9755 mLastWakeLockHoldingWindow = null; 9756 mLastWakeLockObscuringWindow = mWindowPlacerLocked.mObsuringWindow; 9757 mPolicy.keepScreenOnStoppedLw(); 9758 mHoldingScreenWakeLock.release(); 9759 } 9760 } 9761 } 9762 requestTraversal()9763 void requestTraversal() { 9764 synchronized (mWindowMap) { 9765 mWindowPlacerLocked.requestTraversal(); 9766 } 9767 } 9768 9769 /** Note that Locked in this case is on mLayoutToAnim */ scheduleAnimationLocked()9770 void scheduleAnimationLocked() { 9771 if (!mAnimationScheduled) { 9772 mAnimationScheduled = true; 9773 mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback); 9774 } 9775 } 9776 needsLayout()9777 boolean needsLayout() { 9778 final int numDisplays = mDisplayContents.size(); 9779 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9780 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9781 if (displayContent.layoutNeeded) { 9782 return true; 9783 } 9784 } 9785 return false; 9786 } 9787 9788 /** If a window that has an animation specifying a colored background and the current wallpaper 9789 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9790 * suddenly disappear. */ adjustAnimationBackground(WindowStateAnimator winAnimator)9791 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9792 WindowList windows = winAnimator.mWin.getWindowList(); 9793 for (int i = windows.size() - 1; i >= 0; --i) { 9794 WindowState testWin = windows.get(i); 9795 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9796 return testWin.mWinAnimator.mAnimLayer; 9797 } 9798 } 9799 return winAnimator.mAnimLayer; 9800 } 9801 reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, boolean secure)9802 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9803 boolean secure) { 9804 final WindowSurfaceController surfaceController = winAnimator.mSurfaceController; 9805 boolean leakedSurface = false; 9806 boolean killedApps = false; 9807 9808 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9809 winAnimator.mSession.mPid, operation); 9810 9811 final long callingIdentity = Binder.clearCallingIdentity(); 9812 try { 9813 // There was some problem... first, do a sanity check of the window list to make sure 9814 // we haven't left any dangling surfaces around. 9815 9816 Slog.i(TAG_WM, "Out of memory for surface! Looking for leaks..."); 9817 final int numDisplays = mDisplayContents.size(); 9818 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9819 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9820 final int numWindows = windows.size(); 9821 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9822 final WindowState ws = windows.get(winNdx); 9823 final WindowStateAnimator wsa = ws.mWinAnimator; 9824 if (wsa.mSurfaceController == null) { 9825 continue; 9826 } 9827 if (!mSessions.contains(wsa.mSession)) { 9828 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): " 9829 + ws + " surface=" + wsa.mSurfaceController 9830 + " token=" + ws.mToken 9831 + " pid=" + ws.mSession.mPid 9832 + " uid=" + ws.mSession.mUid); 9833 wsa.destroySurface(); 9834 mForceRemoves.add(ws); 9835 leakedSurface = true; 9836 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9837 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " 9838 + ws + " surface=" + wsa.mSurfaceController 9839 + " token=" + ws.mAppToken 9840 + " saved=" + ws.hasSavedSurface()); 9841 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false); 9842 wsa.destroySurface(); 9843 leakedSurface = true; 9844 } 9845 } 9846 } 9847 9848 if (!leakedSurface) { 9849 Slog.w(TAG_WM, "No leaked surfaces; killing applicatons!"); 9850 SparseIntArray pidCandidates = new SparseIntArray(); 9851 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9852 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9853 final int numWindows = windows.size(); 9854 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9855 final WindowState ws = windows.get(winNdx); 9856 if (mForceRemoves.contains(ws)) { 9857 continue; 9858 } 9859 WindowStateAnimator wsa = ws.mWinAnimator; 9860 if (wsa.mSurfaceController != null) { 9861 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9862 } 9863 } 9864 if (pidCandidates.size() > 0) { 9865 int[] pids = new int[pidCandidates.size()]; 9866 for (int i=0; i<pids.length; i++) { 9867 pids[i] = pidCandidates.keyAt(i); 9868 } 9869 try { 9870 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9871 killedApps = true; 9872 } 9873 } catch (RemoteException e) { 9874 } 9875 } 9876 } 9877 } 9878 9879 if (leakedSurface || killedApps) { 9880 // We managed to reclaim some memory, so get rid of the trouble 9881 // surface and ask the app to request another one. 9882 Slog.w(TAG_WM, "Looks like we have reclaimed some memory, clearing surface for retry."); 9883 if (surfaceController != null) { 9884 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9885 "RECOVER DESTROY", false); 9886 winAnimator.destroySurface(); 9887 scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken); 9888 } 9889 9890 try { 9891 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9892 } catch (RemoteException e) { 9893 } 9894 } 9895 } finally { 9896 Binder.restoreCallingIdentity(callingIdentity); 9897 } 9898 9899 return leakedSurface || killedApps; 9900 } 9901 updateFocusedWindowLocked(int mode, boolean updateInputWindows)9902 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9903 WindowState newFocus = computeFocusedWindowLocked(); 9904 if (mCurrentFocus != newFocus) { 9905 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9906 // This check makes sure that we don't already have the focus 9907 // change message pending. 9908 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9909 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9910 // TODO(multidisplay): Focused windows on default display only. 9911 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9912 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9913 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9914 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9915 if (imWindowChanged) { 9916 displayContent.layoutNeeded = true; 9917 newFocus = computeFocusedWindowLocked(); 9918 } 9919 9920 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " + 9921 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9922 final WindowState oldFocus = mCurrentFocus; 9923 mCurrentFocus = newFocus; 9924 mLosingFocus.remove(newFocus); 9925 9926 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9927 9928 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9929 // Focus of the input method window changed. Perform layout if needed. 9930 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9931 mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/, 9932 updateInputWindows); 9933 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9934 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9935 // Client will do the layout, but we need to assign layers 9936 // for handleNewWindowLocked() below. 9937 mLayersController.assignLayersLocked(displayContent.getWindowList()); 9938 } 9939 } 9940 9941 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9942 // The change in focus caused us to need to do a layout. Okay. 9943 displayContent.layoutNeeded = true; 9944 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9945 mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/, 9946 updateInputWindows); 9947 } 9948 } 9949 9950 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9951 // If we defer assigning layers, then the caller is responsible for 9952 // doing this part. 9953 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9954 } 9955 9956 adjustForImeIfNeeded(displayContent); 9957 9958 // We may need to schedule some toast windows to be removed. The 9959 // toasts for an app that does not have input focus are removed 9960 // within a timeout to prevent apps to redress other apps' UI. 9961 getDefaultDisplayContentLocked().scheduleToastWindowsTimeoutIfNeededLocked( 9962 oldFocus, newFocus); 9963 9964 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9965 return true; 9966 } 9967 return false; 9968 } 9969 computeFocusedWindowLocked()9970 private WindowState computeFocusedWindowLocked() { 9971 final int displayCount = mDisplayContents.size(); 9972 for (int i = 0; i < displayCount; i++) { 9973 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9974 WindowState win = findFocusedWindowLocked(displayContent); 9975 if (win != null) { 9976 return win; 9977 } 9978 } 9979 return null; 9980 } 9981 findFocusedWindowLocked(DisplayContent displayContent)9982 WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9983 final WindowList windows = displayContent.getWindowList(); 9984 for (int i = windows.size() - 1; i >= 0; i--) { 9985 final WindowState win = windows.get(i); 9986 9987 if (localLOGV || DEBUG_FOCUS) Slog.v( 9988 TAG_WM, "Looking for focus: " + i 9989 + " = " + win 9990 + ", flags=" + win.mAttrs.flags 9991 + ", canReceive=" + win.canReceiveKeys()); 9992 9993 if (!win.canReceiveKeys()) { 9994 continue; 9995 } 9996 9997 AppWindowToken wtoken = win.mAppToken; 9998 9999 // If this window's application has been removed, just skip it. 10000 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 10001 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because " 10002 + (wtoken.removed ? "removed" : "sendingToBottom")); 10003 continue; 10004 } 10005 10006 // Descend through all of the app tokens and find the first that either matches 10007 // win.mAppToken (return win) or mFocusedApp (return null). 10008 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 10009 mFocusedApp != null) { 10010 ArrayList<Task> tasks = displayContent.getTasks(); 10011 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 10012 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 10013 int tokenNdx = tokens.size() - 1; 10014 for ( ; tokenNdx >= 0; --tokenNdx) { 10015 final AppWindowToken token = tokens.get(tokenNdx); 10016 if (wtoken == token) { 10017 break; 10018 } 10019 if (mFocusedApp == token && token.windowsAreFocusable()) { 10020 // Whoops, we are below the focused app whose windows are focusable... 10021 // No focus for you!!! 10022 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, 10023 "findFocusedWindow: Reached focused app=" + mFocusedApp); 10024 return null; 10025 } 10026 } 10027 if (tokenNdx >= 0) { 10028 // Early exit from loop, must have found the matching token. 10029 break; 10030 } 10031 } 10032 } 10033 10034 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + i + 10035 " = " + win); 10036 return win; 10037 } 10038 10039 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows."); 10040 return null; 10041 } 10042 startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim)10043 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 10044 if (mDisplayFrozen) { 10045 return; 10046 } 10047 10048 if (!mDisplayReady || !mPolicy.isScreenOn()) { 10049 // No need to freeze the screen before the system is ready or if 10050 // the screen is off. 10051 return; 10052 } 10053 10054 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 10055 "startFreezingDisplayLocked: inTransaction=" + inTransaction 10056 + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim 10057 + " called by " + Debug.getCallers(8)); 10058 mScreenFrozenLock.acquire(); 10059 10060 mDisplayFrozen = true; 10061 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 10062 mLastFinishedFreezeSource = null; 10063 10064 mInputMonitor.freezeInputDispatchingLw(); 10065 10066 // Clear the last input window -- that is just used for 10067 // clean transitions between IMEs, and if we are freezing 10068 // the screen then the whole world is changing behind the scenes. 10069 mPolicy.setLastInputMethodWindowLw(null, null); 10070 10071 if (mAppTransition.isTransitionSet()) { 10072 mAppTransition.freeze(); 10073 } 10074 10075 if (PROFILE_ORIENTATION) { 10076 File file = new File("/data/system/frozen"); 10077 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10078 } 10079 10080 if (CUSTOM_SCREEN_ROTATION) { 10081 mExitAnimId = exitAnim; 10082 mEnterAnimId = enterAnim; 10083 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10084 final int displayId = displayContent.getDisplayId(); 10085 ScreenRotationAnimation screenRotationAnimation = 10086 mAnimator.getScreenRotationAnimationLocked(displayId); 10087 if (screenRotationAnimation != null) { 10088 screenRotationAnimation.kill(); 10089 } 10090 10091 // Check whether the current screen contains any secure content. 10092 boolean isSecure = false; 10093 final WindowList windows = getDefaultWindowListLocked(); 10094 final int N = windows.size(); 10095 for (int i = 0; i < N; i++) { 10096 WindowState ws = windows.get(i); 10097 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10098 isSecure = true; 10099 break; 10100 } 10101 } 10102 10103 // TODO(multidisplay): rotation on main screen only. 10104 displayContent.updateDisplayInfo(); 10105 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10106 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10107 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10108 } 10109 } 10110 stopFreezingDisplayLocked()10111 void stopFreezingDisplayLocked() { 10112 if (!mDisplayFrozen) { 10113 return; 10114 } 10115 10116 if (mWaitingForConfig || mAppsFreezingScreen > 0 10117 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE 10118 || mClientFreezingScreen || !mOpeningApps.isEmpty()) { 10119 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 10120 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10121 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10122 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10123 + ", mClientFreezingScreen=" + mClientFreezingScreen 10124 + ", mOpeningApps.size()=" + mOpeningApps.size()); 10125 return; 10126 } 10127 10128 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 10129 "stopFreezingDisplayLocked: Unfreezing now"); 10130 10131 mDisplayFrozen = false; 10132 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10133 StringBuilder sb = new StringBuilder(128); 10134 sb.append("Screen frozen for "); 10135 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10136 if (mLastFinishedFreezeSource != null) { 10137 sb.append(" due to "); 10138 sb.append(mLastFinishedFreezeSource); 10139 } 10140 Slog.i(TAG_WM, sb.toString()); 10141 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10142 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10143 if (PROFILE_ORIENTATION) { 10144 Debug.stopMethodTracing(); 10145 } 10146 10147 boolean updateRotation = false; 10148 10149 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10150 final int displayId = displayContent.getDisplayId(); 10151 ScreenRotationAnimation screenRotationAnimation = 10152 mAnimator.getScreenRotationAnimationLocked(displayId); 10153 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10154 && screenRotationAnimation.hasScreenshot()) { 10155 if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation"); 10156 // TODO(multidisplay): rotation on main screen only. 10157 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10158 // Get rotation animation again, with new top window 10159 boolean isDimming = displayContent.isDimming(); 10160 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10161 mExitAnimId = mEnterAnimId = 0; 10162 } 10163 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10164 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 10165 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10166 scheduleAnimationLocked(); 10167 } else { 10168 screenRotationAnimation.kill(); 10169 mAnimator.setScreenRotationAnimationLocked(displayId, null); 10170 updateRotation = true; 10171 } 10172 } else { 10173 if (screenRotationAnimation != null) { 10174 screenRotationAnimation.kill(); 10175 mAnimator.setScreenRotationAnimationLocked(displayId, null); 10176 } 10177 updateRotation = true; 10178 } 10179 10180 mInputMonitor.thawInputDispatchingLw(); 10181 10182 boolean configChanged; 10183 10184 // While the display is frozen we don't re-compute the orientation 10185 // to avoid inconsistent states. However, something interesting 10186 // could have actually changed during that time so re-evaluate it 10187 // now to catch that. 10188 configChanged = updateOrientationFromAppTokensLocked(false); 10189 10190 // A little kludge: a lot could have happened while the 10191 // display was frozen, so now that we are coming back we 10192 // do a gc so that any remote references the system 10193 // processes holds on others can be released if they are 10194 // no longer needed. 10195 mH.removeMessages(H.FORCE_GC); 10196 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10197 10198 mScreenFrozenLock.release(); 10199 10200 if (updateRotation) { 10201 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation"); 10202 configChanged |= updateRotationUncheckedLocked(false); 10203 } 10204 10205 if (configChanged) { 10206 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10207 } 10208 } 10209 getPropertyInt(String[] tokens, int index, int defUnits, int defDps, DisplayMetrics dm)10210 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10211 DisplayMetrics dm) { 10212 if (index < tokens.length) { 10213 String str = tokens[index]; 10214 if (str != null && str.length() > 0) { 10215 try { 10216 int val = Integer.parseInt(str); 10217 return val; 10218 } catch (Exception e) { 10219 } 10220 } 10221 } 10222 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10223 return defDps; 10224 } 10225 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10226 return val; 10227 } 10228 createWatermarkInTransaction()10229 void createWatermarkInTransaction() { 10230 if (mWatermark != null) { 10231 return; 10232 } 10233 10234 File file = new File("/system/etc/setup.conf"); 10235 FileInputStream in = null; 10236 DataInputStream ind = null; 10237 try { 10238 in = new FileInputStream(file); 10239 ind = new DataInputStream(in); 10240 String line = ind.readLine(); 10241 if (line != null) { 10242 String[] toks = line.split("%"); 10243 if (toks != null && toks.length > 0) { 10244 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10245 mRealDisplayMetrics, mFxSession, toks); 10246 } 10247 } 10248 } catch (FileNotFoundException e) { 10249 } catch (IOException e) { 10250 } finally { 10251 if (ind != null) { 10252 try { 10253 ind.close(); 10254 } catch (IOException e) { 10255 } 10256 } else if (in != null) { 10257 try { 10258 in.close(); 10259 } catch (IOException e) { 10260 } 10261 } 10262 } 10263 } 10264 10265 @Override setRecentsVisibility(boolean visible)10266 public void setRecentsVisibility(boolean visible) { 10267 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10268 != PackageManager.PERMISSION_GRANTED) { 10269 throw new SecurityException("Caller does not hold permission " 10270 + android.Manifest.permission.STATUS_BAR); 10271 } 10272 10273 synchronized (mWindowMap) { 10274 mPolicy.setRecentsVisibilityLw(visible); 10275 } 10276 } 10277 10278 @Override setTvPipVisibility(boolean visible)10279 public void setTvPipVisibility(boolean visible) { 10280 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10281 != PackageManager.PERMISSION_GRANTED) { 10282 throw new SecurityException("Caller does not hold permission " 10283 + android.Manifest.permission.STATUS_BAR); 10284 } 10285 10286 synchronized (mWindowMap) { 10287 mPolicy.setTvPipVisibilityLw(visible); 10288 } 10289 } 10290 10291 @Override statusBarVisibilityChanged(int visibility)10292 public void statusBarVisibilityChanged(int visibility) { 10293 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10294 != PackageManager.PERMISSION_GRANTED) { 10295 throw new SecurityException("Caller does not hold permission " 10296 + android.Manifest.permission.STATUS_BAR); 10297 } 10298 10299 synchronized (mWindowMap) { 10300 mLastStatusBarVisibility = visibility; 10301 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10302 updateStatusBarVisibilityLocked(visibility); 10303 } 10304 } 10305 10306 // TOOD(multidisplay): StatusBar on multiple screens? updateStatusBarVisibilityLocked(int visibility)10307 boolean updateStatusBarVisibilityLocked(int visibility) { 10308 if (mLastDispatchedSystemUiVisibility == visibility) { 10309 return false; 10310 } 10311 final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility) 10312 // We are only interested in differences of one of the 10313 // clearable flags... 10314 & View.SYSTEM_UI_CLEARABLE_FLAGS 10315 // ...if it has actually been cleared. 10316 & ~visibility; 10317 10318 mLastDispatchedSystemUiVisibility = visibility; 10319 mInputManager.setSystemUiVisibility(visibility); 10320 final WindowList windows = getDefaultWindowListLocked(); 10321 final int N = windows.size(); 10322 for (int i = 0; i < N; i++) { 10323 WindowState ws = windows.get(i); 10324 try { 10325 int curValue = ws.mSystemUiVisibility; 10326 int diff = (curValue ^ visibility) & globalDiff; 10327 int newValue = (curValue&~diff) | (visibility&diff); 10328 if (newValue != curValue) { 10329 ws.mSeq++; 10330 ws.mSystemUiVisibility = newValue; 10331 } 10332 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10333 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10334 visibility, newValue, diff); 10335 } 10336 } catch (RemoteException e) { 10337 // so sorry 10338 } 10339 } 10340 return true; 10341 } 10342 10343 @Override reevaluateStatusBarVisibility()10344 public void reevaluateStatusBarVisibility() { 10345 synchronized (mWindowMap) { 10346 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10347 if (updateStatusBarVisibilityLocked(visibility)) { 10348 mWindowPlacerLocked.requestTraversal(); 10349 } 10350 } 10351 } 10352 10353 private static final class HideNavInputConsumer extends InputConsumerImpl 10354 implements WindowManagerPolicy.InputConsumer { 10355 private final InputEventReceiver mInputEventReceiver; 10356 HideNavInputConsumer(WindowManagerService service, Looper looper, InputEventReceiver.Factory inputEventReceiverFactory)10357 HideNavInputConsumer(WindowManagerService service, Looper looper, 10358 InputEventReceiver.Factory inputEventReceiverFactory) { 10359 super(service, "input consumer", null); 10360 mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver( 10361 mClientChannel, looper); 10362 } 10363 10364 @Override dismiss()10365 public void dismiss() { 10366 if (mService.removeInputConsumer()) { 10367 synchronized (mService.mWindowMap) { 10368 mInputEventReceiver.dispose(); 10369 disposeChannelsLw(); 10370 } 10371 } 10372 } 10373 } 10374 10375 @Override addInputConsumer(Looper looper, InputEventReceiver.Factory inputEventReceiverFactory)10376 public WindowManagerPolicy.InputConsumer addInputConsumer(Looper looper, 10377 InputEventReceiver.Factory inputEventReceiverFactory) { 10378 synchronized (mWindowMap) { 10379 HideNavInputConsumer inputConsumerImpl = new HideNavInputConsumer( 10380 this, looper, inputEventReceiverFactory); 10381 mInputConsumer = inputConsumerImpl; 10382 mInputMonitor.updateInputWindowsLw(true); 10383 return inputConsumerImpl; 10384 } 10385 } 10386 removeInputConsumer()10387 boolean removeInputConsumer() { 10388 synchronized (mWindowMap) { 10389 if (mInputConsumer != null) { 10390 mInputConsumer = null; 10391 mInputMonitor.updateInputWindowsLw(true); 10392 return true; 10393 } 10394 return false; 10395 } 10396 } 10397 10398 @Override createWallpaperInputConsumer(InputChannel inputChannel)10399 public void createWallpaperInputConsumer(InputChannel inputChannel) { 10400 synchronized (mWindowMap) { 10401 mWallpaperInputConsumer = new InputConsumerImpl(this, "wallpaper input", inputChannel); 10402 mWallpaperInputConsumer.mWindowHandle.hasWallpaper = true; 10403 mInputMonitor.updateInputWindowsLw(true); 10404 } 10405 } 10406 10407 @Override removeWallpaperInputConsumer()10408 public void removeWallpaperInputConsumer() { 10409 synchronized (mWindowMap) { 10410 if (mWallpaperInputConsumer != null) { 10411 mWallpaperInputConsumer.disposeChannelsLw(); 10412 mWallpaperInputConsumer = null; 10413 mInputMonitor.updateInputWindowsLw(true); 10414 } 10415 } 10416 } 10417 10418 @Override hasNavigationBar()10419 public boolean hasNavigationBar() { 10420 return mPolicy.hasNavigationBar(); 10421 } 10422 10423 @Override lockNow(Bundle options)10424 public void lockNow(Bundle options) { 10425 mPolicy.lockNow(options); 10426 } 10427 showRecentApps(boolean fromHome)10428 public void showRecentApps(boolean fromHome) { 10429 mPolicy.showRecentApps(fromHome); 10430 } 10431 10432 @Override isSafeModeEnabled()10433 public boolean isSafeModeEnabled() { 10434 return mSafeMode; 10435 } 10436 10437 @Override clearWindowContentFrameStats(IBinder token)10438 public boolean clearWindowContentFrameStats(IBinder token) { 10439 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10440 "clearWindowContentFrameStats()")) { 10441 throw new SecurityException("Requires FRAME_STATS permission"); 10442 } 10443 synchronized (mWindowMap) { 10444 WindowState windowState = mWindowMap.get(token); 10445 if (windowState == null) { 10446 return false; 10447 } 10448 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController; 10449 if (surfaceController == null) { 10450 return false; 10451 } 10452 return surfaceController.clearWindowContentFrameStats(); 10453 } 10454 } 10455 10456 @Override getWindowContentFrameStats(IBinder token)10457 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 10458 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10459 "getWindowContentFrameStats()")) { 10460 throw new SecurityException("Requires FRAME_STATS permission"); 10461 } 10462 synchronized (mWindowMap) { 10463 WindowState windowState = mWindowMap.get(token); 10464 if (windowState == null) { 10465 return null; 10466 } 10467 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController; 10468 if (surfaceController == null) { 10469 return null; 10470 } 10471 if (mTempWindowRenderStats == null) { 10472 mTempWindowRenderStats = new WindowContentFrameStats(); 10473 } 10474 WindowContentFrameStats stats = mTempWindowRenderStats; 10475 if (!surfaceController.getWindowContentFrameStats(stats)) { 10476 return null; 10477 } 10478 return stats; 10479 } 10480 } 10481 notifyAppRelaunching(IBinder token)10482 public void notifyAppRelaunching(IBinder token) { 10483 synchronized (mWindowMap) { 10484 AppWindowToken appWindow = findAppWindowToken(token); 10485 if (appWindow != null) { 10486 appWindow.startRelaunching(); 10487 } 10488 } 10489 } 10490 notifyAppRelaunchingFinished(IBinder token)10491 public void notifyAppRelaunchingFinished(IBinder token) { 10492 synchronized (mWindowMap) { 10493 AppWindowToken appWindow = findAppWindowToken(token); 10494 if (appWindow != null) { 10495 appWindow.finishRelaunching(); 10496 } 10497 } 10498 } 10499 notifyAppRelaunchesCleared(IBinder token)10500 public void notifyAppRelaunchesCleared(IBinder token) { 10501 synchronized (mWindowMap) { 10502 final AppWindowToken appWindow = findAppWindowToken(token); 10503 if (appWindow != null) { 10504 appWindow.clearRelaunching(); 10505 } 10506 } 10507 } 10508 10509 @Override getDockedDividerInsetsLw()10510 public int getDockedDividerInsetsLw() { 10511 return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets(); 10512 } 10513 dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll)10514 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10515 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10516 mPolicy.dump(" ", pw, args); 10517 } 10518 dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll)10519 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10520 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10521 mAnimator.dumpLocked(pw, " ", dumpAll); 10522 } 10523 dumpTokensLocked(PrintWriter pw, boolean dumpAll)10524 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10525 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10526 if (!mTokenMap.isEmpty()) { 10527 pw.println(" All tokens:"); 10528 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10529 while (it.hasNext()) { 10530 WindowToken token = it.next(); 10531 pw.print(" "); pw.print(token); 10532 if (dumpAll) { 10533 pw.println(':'); 10534 token.dump(pw, " "); 10535 } else { 10536 pw.println(); 10537 } 10538 } 10539 } 10540 mWallpaperControllerLocked.dumpTokens(pw, " ", dumpAll); 10541 if (!mFinishedStarting.isEmpty()) { 10542 pw.println(); 10543 pw.println(" Finishing start of application tokens:"); 10544 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10545 WindowToken token = mFinishedStarting.get(i); 10546 pw.print(" Finished Starting #"); pw.print(i); 10547 pw.print(' '); pw.print(token); 10548 if (dumpAll) { 10549 pw.println(':'); 10550 token.dump(pw, " "); 10551 } else { 10552 pw.println(); 10553 } 10554 } 10555 } 10556 if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) { 10557 pw.println(); 10558 if (mOpeningApps.size() > 0) { 10559 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10560 } 10561 if (mClosingApps.size() > 0) { 10562 pw.print(" mClosingApps="); pw.println(mClosingApps); 10563 } 10564 } 10565 } 10566 dumpSessionsLocked(PrintWriter pw, boolean dumpAll)10567 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10568 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10569 for (int i=0; i<mSessions.size(); i++) { 10570 Session s = mSessions.valueAt(i); 10571 pw.print(" Session "); pw.print(s); pw.println(':'); 10572 s.dump(pw, " "); 10573 } 10574 } 10575 dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll)10576 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10577 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10578 if (mDisplayReady) { 10579 final int numDisplays = mDisplayContents.size(); 10580 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10581 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10582 displayContent.dump(" ", pw); 10583 } 10584 } else { 10585 pw.println(" NO DISPLAY"); 10586 } 10587 } 10588 dumpWindowsLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)10589 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10590 ArrayList<WindowState> windows) { 10591 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10592 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10593 } 10594 dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)10595 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10596 ArrayList<WindowState> windows) { 10597 final int numDisplays = mDisplayContents.size(); 10598 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10599 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10600 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10601 final WindowState w = windowList.get(winNdx); 10602 if (windows == null || windows.contains(w)) { 10603 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10604 pw.print(w); pw.println(":"); 10605 w.dump(pw, " ", dumpAll || windows != null); 10606 } 10607 } 10608 } 10609 if (mInputMethodDialogs.size() > 0) { 10610 pw.println(); 10611 pw.println(" Input method dialogs:"); 10612 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10613 WindowState w = mInputMethodDialogs.get(i); 10614 if (windows == null || windows.contains(w)) { 10615 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10616 } 10617 } 10618 } 10619 if (mPendingRemove.size() > 0) { 10620 pw.println(); 10621 pw.println(" Remove pending for:"); 10622 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10623 WindowState w = mPendingRemove.get(i); 10624 if (windows == null || windows.contains(w)) { 10625 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10626 pw.print(w); 10627 if (dumpAll) { 10628 pw.println(":"); 10629 w.dump(pw, " ", true); 10630 } else { 10631 pw.println(); 10632 } 10633 } 10634 } 10635 } 10636 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10637 pw.println(); 10638 pw.println(" Windows force removing:"); 10639 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10640 WindowState w = mForceRemoves.get(i); 10641 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10642 pw.print(w); 10643 if (dumpAll) { 10644 pw.println(":"); 10645 w.dump(pw, " ", true); 10646 } else { 10647 pw.println(); 10648 } 10649 } 10650 } 10651 if (mDestroySurface.size() > 0) { 10652 pw.println(); 10653 pw.println(" Windows waiting to destroy their surface:"); 10654 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10655 WindowState w = mDestroySurface.get(i); 10656 if (windows == null || windows.contains(w)) { 10657 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10658 pw.print(w); 10659 if (dumpAll) { 10660 pw.println(":"); 10661 w.dump(pw, " ", true); 10662 } else { 10663 pw.println(); 10664 } 10665 } 10666 } 10667 } 10668 if (mLosingFocus.size() > 0) { 10669 pw.println(); 10670 pw.println(" Windows losing focus:"); 10671 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10672 WindowState w = mLosingFocus.get(i); 10673 if (windows == null || windows.contains(w)) { 10674 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10675 pw.print(w); 10676 if (dumpAll) { 10677 pw.println(":"); 10678 w.dump(pw, " ", true); 10679 } else { 10680 pw.println(); 10681 } 10682 } 10683 } 10684 } 10685 if (mResizingWindows.size() > 0) { 10686 pw.println(); 10687 pw.println(" Windows waiting to resize:"); 10688 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10689 WindowState w = mResizingWindows.get(i); 10690 if (windows == null || windows.contains(w)) { 10691 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10692 pw.print(w); 10693 if (dumpAll) { 10694 pw.println(":"); 10695 w.dump(pw, " ", true); 10696 } else { 10697 pw.println(); 10698 } 10699 } 10700 } 10701 } 10702 if (mWaitingForDrawn.size() > 0) { 10703 pw.println(); 10704 pw.println(" Clients waiting for these windows to be drawn:"); 10705 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10706 WindowState win = mWaitingForDrawn.get(i); 10707 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10708 } 10709 } 10710 pw.println(); 10711 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10712 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad); 10713 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10714 if (mLastFocus != mCurrentFocus) { 10715 pw.print(" mLastFocus="); pw.println(mLastFocus); 10716 } 10717 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10718 if (mInputMethodTarget != null) { 10719 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10720 } 10721 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10722 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10723 pw.print(" mLastDisplayFreezeDuration="); 10724 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10725 if ( mLastFinishedFreezeSource != null) { 10726 pw.print(" due to "); 10727 pw.print(mLastFinishedFreezeSource); 10728 } 10729 pw.println(); 10730 pw.print(" mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow); 10731 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow); 10732 pw.println(); 10733 10734 mInputMonitor.dump(pw, " "); 10735 10736 if (dumpAll) { 10737 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10738 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10739 if (mLastStatusBarVisibility != 0) { 10740 pw.print(" mLastStatusBarVisibility=0x"); 10741 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10742 } 10743 if (mInputMethodWindow != null) { 10744 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10745 } 10746 mWindowPlacerLocked.dump(pw, " "); 10747 mWallpaperControllerLocked.dump(pw, " "); 10748 mLayersController.dump(pw, " "); 10749 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10750 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10751 if (needsLayout()) { 10752 pw.print(" layoutNeeded on displays="); 10753 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10754 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10755 if (displayContent.layoutNeeded) { 10756 pw.print(displayContent.getDisplayId()); 10757 } 10758 } 10759 pw.println(); 10760 } 10761 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10762 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10763 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10764 pw.print(" client="); pw.print(mClientFreezingScreen); 10765 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10766 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10767 pw.print(" mRotation="); pw.print(mRotation); 10768 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10769 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10770 pw.print(" mLastOrientation="); pw.println(mLastOrientation); 10771 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10772 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 10773 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 10774 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 10775 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 10776 pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation); 10777 pw.println(" mLayoutToAnim:"); 10778 mAppTransition.dump(pw, " "); 10779 } 10780 } 10781 dumpWindows(PrintWriter pw, String name, String[] args, int opti, boolean dumpAll)10782 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10783 int opti, boolean dumpAll) { 10784 WindowList windows = new WindowList(); 10785 if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) { 10786 final boolean appsOnly = name.contains("apps"); 10787 final boolean visibleOnly = name.contains("visible"); 10788 synchronized(mWindowMap) { 10789 if (appsOnly) { 10790 dumpDisplayContentsLocked(pw, true); 10791 } 10792 10793 final int numDisplays = mDisplayContents.size(); 10794 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10795 final WindowList windowList = 10796 mDisplayContents.valueAt(displayNdx).getWindowList(); 10797 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10798 final WindowState w = windowList.get(winNdx); 10799 if ((!visibleOnly || w.mWinAnimator.getShown()) 10800 && (!appsOnly || w.mAppToken != null)) { 10801 windows.add(w); 10802 } 10803 } 10804 } 10805 } 10806 } else { 10807 int objectId = 0; 10808 // See if this is an object ID. 10809 try { 10810 objectId = Integer.parseInt(name, 16); 10811 name = null; 10812 } catch (RuntimeException e) { 10813 } 10814 synchronized(mWindowMap) { 10815 final int numDisplays = mDisplayContents.size(); 10816 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10817 final WindowList windowList = 10818 mDisplayContents.valueAt(displayNdx).getWindowList(); 10819 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10820 final WindowState w = windowList.get(winNdx); 10821 if (name != null) { 10822 if (w.mAttrs.getTitle().toString().contains(name)) { 10823 windows.add(w); 10824 } 10825 } else if (System.identityHashCode(w) == objectId) { 10826 windows.add(w); 10827 } 10828 } 10829 } 10830 } 10831 } 10832 10833 if (windows.size() <= 0) { 10834 return false; 10835 } 10836 10837 synchronized(mWindowMap) { 10838 dumpWindowsLocked(pw, dumpAll, windows); 10839 } 10840 return true; 10841 } 10842 dumpLastANRLocked(PrintWriter pw)10843 void dumpLastANRLocked(PrintWriter pw) { 10844 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10845 if (mLastANRState == null) { 10846 pw.println(" <no ANR has occurred since boot>"); 10847 } else { 10848 pw.println(mLastANRState); 10849 } 10850 } 10851 10852 /** 10853 * Saves information about the state of the window manager at 10854 * the time an ANR occurred before anything else in the system changes 10855 * in response. 10856 * 10857 * @param appWindowToken The application that ANR'd, may be null. 10858 * @param windowState The window that ANR'd, may be null. 10859 * @param reason The reason for the ANR, may be null. 10860 */ saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason)10861 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10862 String reason) { 10863 StringWriter sw = new StringWriter(); 10864 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10865 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10866 if (appWindowToken != null) { 10867 pw.println(" Application at fault: " + appWindowToken.stringName); 10868 } 10869 if (windowState != null) { 10870 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10871 } 10872 if (reason != null) { 10873 pw.println(" Reason: " + reason); 10874 } 10875 pw.println(); 10876 dumpWindowsNoHeaderLocked(pw, true, null); 10877 pw.println(); 10878 pw.println("Last ANR continued"); 10879 dumpDisplayContentsLocked(pw, true); 10880 pw.close(); 10881 mLastANRState = sw.toString(); 10882 10883 mH.removeMessages(H.RESET_ANR_MESSAGE); 10884 mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS); 10885 } 10886 10887 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)10888 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10889 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10890 != PackageManager.PERMISSION_GRANTED) { 10891 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10892 + Binder.getCallingPid() 10893 + ", uid=" + Binder.getCallingUid()); 10894 return; 10895 } 10896 10897 boolean dumpAll = false; 10898 10899 int opti = 0; 10900 while (opti < args.length) { 10901 String opt = args[opti]; 10902 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10903 break; 10904 } 10905 opti++; 10906 if ("-a".equals(opt)) { 10907 dumpAll = true; 10908 } else if ("-h".equals(opt)) { 10909 pw.println("Window manager dump options:"); 10910 pw.println(" [-a] [-h] [cmd] ..."); 10911 pw.println(" cmd may be one of:"); 10912 pw.println(" l[astanr]: last ANR information"); 10913 pw.println(" p[policy]: policy state"); 10914 pw.println(" a[animator]: animator state"); 10915 pw.println(" s[essions]: active sessions"); 10916 pw.println(" surfaces: active surfaces (debugging enabled only)"); 10917 pw.println(" d[isplays]: active display contents"); 10918 pw.println(" t[okens]: token list"); 10919 pw.println(" w[indows]: window list"); 10920 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10921 pw.println(" be a partial substring in a window name, a"); 10922 pw.println(" Window hex object identifier, or"); 10923 pw.println(" \"all\" for all windows, or"); 10924 pw.println(" \"visible\" for the visible windows."); 10925 pw.println(" \"visible-apps\" for the visible app windows."); 10926 pw.println(" -a: include all available server state."); 10927 return; 10928 } else { 10929 pw.println("Unknown argument: " + opt + "; use -h for help"); 10930 } 10931 } 10932 10933 // Is the caller requesting to dump a particular piece of data? 10934 if (opti < args.length) { 10935 String cmd = args[opti]; 10936 opti++; 10937 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10938 synchronized(mWindowMap) { 10939 dumpLastANRLocked(pw); 10940 } 10941 return; 10942 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10943 synchronized(mWindowMap) { 10944 dumpPolicyLocked(pw, args, true); 10945 } 10946 return; 10947 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10948 synchronized(mWindowMap) { 10949 dumpAnimatorLocked(pw, args, true); 10950 } 10951 return; 10952 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10953 synchronized(mWindowMap) { 10954 dumpSessionsLocked(pw, true); 10955 } 10956 return; 10957 } else if ("surfaces".equals(cmd)) { 10958 synchronized(mWindowMap) { 10959 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null); 10960 } 10961 return; 10962 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10963 synchronized(mWindowMap) { 10964 dumpDisplayContentsLocked(pw, true); 10965 } 10966 return; 10967 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10968 synchronized(mWindowMap) { 10969 dumpTokensLocked(pw, true); 10970 } 10971 return; 10972 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10973 synchronized(mWindowMap) { 10974 dumpWindowsLocked(pw, true, null); 10975 } 10976 return; 10977 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10978 synchronized(mWindowMap) { 10979 dumpWindowsLocked(pw, true, null); 10980 } 10981 return; 10982 } else { 10983 // Dumping a single name? 10984 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10985 pw.println("Bad window command, or no windows match: " + cmd); 10986 pw.println("Use -h for help."); 10987 } 10988 return; 10989 } 10990 } 10991 10992 synchronized(mWindowMap) { 10993 pw.println(); 10994 if (dumpAll) { 10995 pw.println("-------------------------------------------------------------------------------"); 10996 } 10997 dumpLastANRLocked(pw); 10998 pw.println(); 10999 if (dumpAll) { 11000 pw.println("-------------------------------------------------------------------------------"); 11001 } 11002 dumpPolicyLocked(pw, args, dumpAll); 11003 pw.println(); 11004 if (dumpAll) { 11005 pw.println("-------------------------------------------------------------------------------"); 11006 } 11007 dumpAnimatorLocked(pw, args, dumpAll); 11008 pw.println(); 11009 if (dumpAll) { 11010 pw.println("-------------------------------------------------------------------------------"); 11011 } 11012 dumpSessionsLocked(pw, dumpAll); 11013 pw.println(); 11014 if (dumpAll) { 11015 pw.println("-------------------------------------------------------------------------------"); 11016 } 11017 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ? 11018 "-------------------------------------------------------------------------------" 11019 : null); 11020 pw.println(); 11021 if (dumpAll) { 11022 pw.println("-------------------------------------------------------------------------------"); 11023 } 11024 dumpDisplayContentsLocked(pw, dumpAll); 11025 pw.println(); 11026 if (dumpAll) { 11027 pw.println("-------------------------------------------------------------------------------"); 11028 } 11029 dumpTokensLocked(pw, dumpAll); 11030 pw.println(); 11031 if (dumpAll) { 11032 pw.println("-------------------------------------------------------------------------------"); 11033 } 11034 dumpWindowsLocked(pw, dumpAll, null); 11035 } 11036 } 11037 11038 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 11039 @Override monitor()11040 public void monitor() { 11041 synchronized (mWindowMap) { } 11042 } 11043 newDisplayContentLocked(final Display display)11044 private DisplayContent newDisplayContentLocked(final Display display) { 11045 DisplayContent displayContent = new DisplayContent(display, this); 11046 final int displayId = display.getDisplayId(); 11047 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display); 11048 mDisplayContents.put(displayId, displayContent); 11049 11050 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 11051 final Rect rect = new Rect(); 11052 mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect); 11053 displayInfo.overscanLeft = rect.left; 11054 displayInfo.overscanTop = rect.top; 11055 displayInfo.overscanRight = rect.right; 11056 displayInfo.overscanBottom = rect.bottom; 11057 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId, displayInfo); 11058 configureDisplayPolicyLocked(displayContent); 11059 11060 // TODO: Create an input channel for each display with touch capability. 11061 if (displayId == Display.DEFAULT_DISPLAY) { 11062 displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent); 11063 registerPointerEventListener(displayContent.mTapDetector); 11064 registerPointerEventListener(mMousePositionTracker); 11065 } 11066 11067 return displayContent; 11068 } 11069 createDisplayContentLocked(final Display display)11070 public void createDisplayContentLocked(final Display display) { 11071 if (display == null) { 11072 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 11073 } 11074 getDisplayContentLocked(display.getDisplayId()); 11075 } 11076 11077 /** 11078 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 11079 * there is a Display for the displayId. 11080 * @param displayId The display the caller is interested in. 11081 * @return The DisplayContent associated with displayId or null if there is no Display for it. 11082 */ getDisplayContentLocked(final int displayId)11083 public DisplayContent getDisplayContentLocked(final int displayId) { 11084 DisplayContent displayContent = mDisplayContents.get(displayId); 11085 if (displayContent == null) { 11086 final Display display = mDisplayManager.getDisplay(displayId); 11087 if (display != null) { 11088 displayContent = newDisplayContentLocked(display); 11089 } 11090 } 11091 return displayContent; 11092 } 11093 11094 // There is an inherent assumption that this will never return null. getDefaultDisplayContentLocked()11095 public DisplayContent getDefaultDisplayContentLocked() { 11096 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 11097 } 11098 getDefaultWindowListLocked()11099 public WindowList getDefaultWindowListLocked() { 11100 return getDefaultDisplayContentLocked().getWindowList(); 11101 } 11102 getDefaultDisplayInfoLocked()11103 public DisplayInfo getDefaultDisplayInfoLocked() { 11104 return getDefaultDisplayContentLocked().getDisplayInfo(); 11105 } 11106 11107 /** 11108 * Return the list of WindowStates associated on the passed display. 11109 * @param display The screen to return windows from. 11110 * @return The list of WindowStates on the screen, or null if the there is no screen. 11111 */ getWindowListLocked(final Display display)11112 public WindowList getWindowListLocked(final Display display) { 11113 return getWindowListLocked(display.getDisplayId()); 11114 } 11115 11116 /** 11117 * Return the list of WindowStates associated on the passed display. 11118 * @param displayId The screen to return windows from. 11119 * @return The list of WindowStates on the screen, or null if the there is no screen. 11120 */ getWindowListLocked(final int displayId)11121 public WindowList getWindowListLocked(final int displayId) { 11122 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11123 return displayContent != null ? displayContent.getWindowList() : null; 11124 } 11125 onDisplayAdded(int displayId)11126 public void onDisplayAdded(int displayId) { 11127 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 11128 } 11129 handleDisplayAdded(int displayId)11130 public void handleDisplayAdded(int displayId) { 11131 synchronized (mWindowMap) { 11132 final Display display = mDisplayManager.getDisplay(displayId); 11133 if (display != null) { 11134 createDisplayContentLocked(display); 11135 displayReady(displayId); 11136 } 11137 mWindowPlacerLocked.requestTraversal(); 11138 } 11139 } 11140 onDisplayRemoved(int displayId)11141 public void onDisplayRemoved(int displayId) { 11142 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 11143 } 11144 handleDisplayRemovedLocked(int displayId)11145 private void handleDisplayRemovedLocked(int displayId) { 11146 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11147 if (displayContent != null) { 11148 if (displayContent.isAnimating()) { 11149 displayContent.mDeferredRemoval = true; 11150 return; 11151 } 11152 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + displayContent); 11153 mDisplayContents.delete(displayId); 11154 displayContent.close(); 11155 if (displayId == Display.DEFAULT_DISPLAY) { 11156 unregisterPointerEventListener(displayContent.mTapDetector); 11157 unregisterPointerEventListener(mMousePositionTracker); 11158 } 11159 } 11160 mAnimator.removeDisplayLocked(displayId); 11161 mWindowPlacerLocked.requestTraversal(); 11162 } 11163 onDisplayChanged(int displayId)11164 public void onDisplayChanged(int displayId) { 11165 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 11166 } 11167 handleDisplayChangedLocked(int displayId)11168 private void handleDisplayChangedLocked(int displayId) { 11169 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11170 if (displayContent != null) { 11171 displayContent.updateDisplayInfo(); 11172 } 11173 mWindowPlacerLocked.requestTraversal(); 11174 } 11175 11176 @Override getWindowManagerLock()11177 public Object getWindowManagerLock() { 11178 return mWindowMap; 11179 } 11180 11181 /** 11182 * Hint to a token that its activity will relaunch, which will trigger removal and addition of 11183 * a window. 11184 * @param token Application token for which the activity will be relaunched. 11185 */ setReplacingWindow(IBinder token, boolean animate)11186 public void setReplacingWindow(IBinder token, boolean animate) { 11187 AppWindowToken appWindowToken = null; 11188 synchronized (mWindowMap) { 11189 appWindowToken = findAppWindowToken(token); 11190 if (appWindowToken == null || !appWindowToken.isVisible()) { 11191 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token " 11192 + token); 11193 return; 11194 } 11195 appWindowToken.setReplacingWindows(animate); 11196 } 11197 } 11198 11199 /** 11200 * Hint to a token that its windows will be replaced across activity relaunch. 11201 * The windows would otherwise be removed shortly following this as the 11202 * activity is torn down. 11203 * @param token Application token for which the activity will be relaunched. 11204 * @param childrenOnly Whether to mark only child windows for replacement 11205 * (for the case where main windows are being preserved/ 11206 * reused rather than replaced). 11207 * 11208 */ setReplacingWindows(IBinder token, boolean childrenOnly)11209 public void setReplacingWindows(IBinder token, boolean childrenOnly) { 11210 AppWindowToken appWindowToken = null; 11211 synchronized (mWindowMap) { 11212 appWindowToken = findAppWindowToken(token); 11213 if (appWindowToken == null || !appWindowToken.isVisible()) { 11214 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token " 11215 + token); 11216 return; 11217 } 11218 11219 if (childrenOnly) { 11220 appWindowToken.setReplacingChildren(); 11221 } else { 11222 appWindowToken.setReplacingWindows(false /* animate */); 11223 } 11224 11225 scheduleClearReplacingWindowIfNeeded(token, true /* replacing */); 11226 } 11227 } 11228 11229 /** 11230 * If we're replacing the window, schedule a timer to clear the replaced window 11231 * after a timeout, in case the replacing window is not coming. 11232 * 11233 * If we're not replacing the window, clear the replace window settings of the app. 11234 * 11235 * @param token Application token for the activity whose window might be replaced. 11236 * @param replacing Whether the window is being replaced or not. 11237 */ scheduleClearReplacingWindowIfNeeded(IBinder token, boolean replacing)11238 public void scheduleClearReplacingWindowIfNeeded(IBinder token, boolean replacing) { 11239 AppWindowToken appWindowToken = null; 11240 synchronized (mWindowMap) { 11241 appWindowToken = findAppWindowToken(token); 11242 if (appWindowToken == null) { 11243 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token " 11244 + token); 11245 return; 11246 } 11247 if (replacing) { 11248 scheduleReplacingWindowTimeouts(appWindowToken); 11249 } else { 11250 appWindowToken.resetReplacingWindows(); 11251 } 11252 } 11253 } 11254 scheduleReplacingWindowTimeouts(AppWindowToken appWindowToken)11255 void scheduleReplacingWindowTimeouts(AppWindowToken appWindowToken) { 11256 if (!mReplacingWindowTimeouts.contains(appWindowToken)) { 11257 mReplacingWindowTimeouts.add(appWindowToken); 11258 } 11259 mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT); 11260 mH.sendEmptyMessageDelayed( 11261 H.WINDOW_REPLACEMENT_TIMEOUT, WINDOW_REPLACEMENT_TIMEOUT_DURATION); 11262 } 11263 11264 @Override getDockedStackSide()11265 public int getDockedStackSide() { 11266 synchronized (mWindowMap) { 11267 final TaskStack dockedStack = getDefaultDisplayContentLocked() 11268 .getDockedStackVisibleForUserLocked(); 11269 return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(); 11270 } 11271 } 11272 11273 @Override setDockedStackResizing(boolean resizing)11274 public void setDockedStackResizing(boolean resizing) { 11275 synchronized (mWindowMap) { 11276 getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing); 11277 requestTraversal(); 11278 } 11279 } 11280 11281 @Override setDockedStackDividerTouchRegion(Rect touchRegion)11282 public void setDockedStackDividerTouchRegion(Rect touchRegion) { 11283 synchronized (mWindowMap) { 11284 getDefaultDisplayContentLocked().getDockedDividerController() 11285 .setTouchRegion(touchRegion); 11286 setFocusTaskRegionLocked(); 11287 } 11288 } 11289 11290 @Override setResizeDimLayer(boolean visible, int targetStackId, float alpha)11291 public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) { 11292 synchronized (mWindowMap) { 11293 getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer( 11294 visible, targetStackId, alpha); 11295 } 11296 } 11297 animateResizePinnedStack(final Rect bounds, final int animationDuration)11298 public void animateResizePinnedStack(final Rect bounds, final int animationDuration) { 11299 synchronized (mWindowMap) { 11300 final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID); 11301 if (stack == null) { 11302 Slog.w(TAG, "animateResizePinnedStack: stackId " + PINNED_STACK_ID + " not found."); 11303 return; 11304 } 11305 final Rect originalBounds = new Rect(); 11306 stack.getBounds(originalBounds); 11307 UiThread.getHandler().post(new Runnable() { 11308 @Override 11309 public void run() { 11310 mBoundsAnimationController.animateBounds( 11311 stack, originalBounds, bounds, animationDuration); 11312 } 11313 }); 11314 } 11315 } 11316 setTaskResizeable(int taskId, int resizeMode)11317 public void setTaskResizeable(int taskId, int resizeMode) { 11318 synchronized (mWindowMap) { 11319 final Task task = mTaskIdToTask.get(taskId); 11320 if (task != null) { 11321 task.setResizeable(resizeMode); 11322 } 11323 } 11324 } 11325 setForceResizableTasks(boolean forceResizableTasks)11326 public void setForceResizableTasks(boolean forceResizableTasks) { 11327 synchronized (mWindowMap) { 11328 mForceResizableTasks = forceResizableTasks; 11329 } 11330 } 11331 dipToPixel(int dip, DisplayMetrics displayMetrics)11332 static int dipToPixel(int dip, DisplayMetrics displayMetrics) { 11333 return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics); 11334 } 11335 11336 @Override registerDockedStackListener(IDockedStackListener listener)11337 public void registerDockedStackListener(IDockedStackListener listener) { 11338 if (!checkCallingPermission(android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS, 11339 "registerDockedStackListener()")) { 11340 return; 11341 } 11342 // TODO(multi-display): The listener is registered on the default display only. 11343 getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener( 11344 listener); 11345 } 11346 11347 @Override requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId)11348 public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) { 11349 try { 11350 WindowState focusedWindow = getFocusedWindow(); 11351 if (focusedWindow != null && focusedWindow.mClient != null) { 11352 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId); 11353 } 11354 } catch (RemoteException e) { 11355 } 11356 } 11357 11358 @Override getStableInsets(Rect outInsets)11359 public void getStableInsets(Rect outInsets) throws RemoteException { 11360 synchronized (mWindowMap) { 11361 getStableInsetsLocked(outInsets); 11362 } 11363 } 11364 getStableInsetsLocked(Rect outInsets)11365 void getStableInsetsLocked(Rect outInsets) { 11366 final DisplayInfo di = getDefaultDisplayInfoLocked(); 11367 mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets); 11368 } 11369 getNonDecorInsetsLocked(Rect outInsets)11370 private void getNonDecorInsetsLocked(Rect outInsets) { 11371 final DisplayInfo di = getDefaultDisplayInfoLocked(); 11372 mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets); 11373 } 11374 11375 /** 11376 * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable 11377 * inset areas. 11378 * 11379 * @param inOutBounds The inOutBounds to subtract the stable inset areas from. 11380 */ subtractStableInsets(Rect inOutBounds)11381 public void subtractStableInsets(Rect inOutBounds) { 11382 synchronized (mWindowMap) { 11383 getStableInsetsLocked(mTmpRect2); 11384 final DisplayInfo di = getDefaultDisplayInfoLocked(); 11385 mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight); 11386 subtractInsets(mTmpRect, mTmpRect2, inOutBounds); 11387 } 11388 } 11389 11390 /** 11391 * Intersects the specified {@code inOutBounds} with the display frame that excludes 11392 * areas that could never be removed in Honeycomb. See 11393 * {@link WindowManagerPolicy#getNonDecorInsetsLw}. 11394 * 11395 * @param inOutBounds The inOutBounds to subtract the inset areas from. 11396 */ subtractNonDecorInsets(Rect inOutBounds)11397 public void subtractNonDecorInsets(Rect inOutBounds) { 11398 synchronized (mWindowMap) { 11399 getNonDecorInsetsLocked(mTmpRect2); 11400 final DisplayInfo di = getDefaultDisplayInfoLocked(); 11401 mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight); 11402 subtractInsets(mTmpRect, mTmpRect2, inOutBounds); 11403 } 11404 } 11405 subtractInsets(Rect display, Rect insets, Rect inOutBounds)11406 void subtractInsets(Rect display, Rect insets, Rect inOutBounds) { 11407 mTmpRect3.set(display); 11408 mTmpRect3.inset(insets); 11409 inOutBounds.intersect(mTmpRect3); 11410 } 11411 11412 /** 11413 * Calculates the smallest width for a task given the {@param bounds}. It does that by iterating 11414 * across all screen orientations, and returns the minimum of the task width taking into account 11415 * that the bounds might change because the snap algorithm snaps to a different value. 11416 * 11417 * @return the smallest width to be used in the Configuration, in dips 11418 */ getSmallestWidthForTaskBounds(Rect bounds)11419 public int getSmallestWidthForTaskBounds(Rect bounds) { 11420 synchronized (mWindowMap) { 11421 return getDefaultDisplayContentLocked().getDockedDividerController() 11422 .getSmallestWidthDpForBounds(bounds); 11423 } 11424 } 11425 11426 private MousePositionTracker mMousePositionTracker = new MousePositionTracker(); 11427 11428 private static class MousePositionTracker implements PointerEventListener { 11429 private boolean mLatestEventWasMouse; 11430 private float mLatestMouseX; 11431 private float mLatestMouseY; 11432 updatePosition(float x, float y)11433 void updatePosition(float x, float y) { 11434 synchronized (this) { 11435 mLatestEventWasMouse = true; 11436 mLatestMouseX = x; 11437 mLatestMouseY = y; 11438 } 11439 } 11440 11441 @Override onPointerEvent(MotionEvent motionEvent)11442 public void onPointerEvent(MotionEvent motionEvent) { 11443 if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) { 11444 updatePosition(motionEvent.getRawX(), motionEvent.getRawY()); 11445 } else { 11446 synchronized (this) { 11447 mLatestEventWasMouse = false; 11448 } 11449 } 11450 } 11451 }; 11452 updatePointerIcon(IWindow client)11453 void updatePointerIcon(IWindow client) { 11454 float mouseX, mouseY; 11455 11456 synchronized(mMousePositionTracker) { 11457 if (!mMousePositionTracker.mLatestEventWasMouse) { 11458 return; 11459 } 11460 mouseX = mMousePositionTracker.mLatestMouseX; 11461 mouseY = mMousePositionTracker.mLatestMouseY; 11462 } 11463 11464 synchronized (mWindowMap) { 11465 if (mDragState != null) { 11466 // Drag cursor overrides the app cursor. 11467 return; 11468 } 11469 WindowState callingWin = windowForClientLocked(null, client, false); 11470 if (callingWin == null) { 11471 Slog.w(TAG_WM, "Bad requesting window " + client); 11472 return; 11473 } 11474 final DisplayContent displayContent = callingWin.getDisplayContent(); 11475 if (displayContent == null) { 11476 return; 11477 } 11478 WindowState windowUnderPointer = 11479 displayContent.getTouchableWinAtPointLocked(mouseX, mouseY); 11480 if (windowUnderPointer != callingWin) { 11481 return; 11482 } 11483 try { 11484 windowUnderPointer.mClient.updatePointerIcon( 11485 windowUnderPointer.translateToWindowX(mouseX), 11486 windowUnderPointer.translateToWindowY(mouseY)); 11487 } catch (RemoteException e) { 11488 Slog.w(TAG_WM, "unable to update pointer icon"); 11489 } 11490 } 11491 } 11492 restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY)11493 void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) { 11494 // Mouse position tracker has not been getting updates while dragging, update it now. 11495 mMousePositionTracker.updatePosition(latestX, latestY); 11496 11497 WindowState windowUnderPointer = 11498 displayContent.getTouchableWinAtPointLocked(latestX, latestY); 11499 if (windowUnderPointer != null) { 11500 try { 11501 windowUnderPointer.mClient.updatePointerIcon( 11502 windowUnderPointer.translateToWindowX(latestX), 11503 windowUnderPointer.translateToWindowY(latestY)); 11504 } catch (RemoteException e) { 11505 Slog.w(TAG_WM, "unable to restore pointer icon"); 11506 } 11507 } else { 11508 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT); 11509 } 11510 } 11511 11512 @Override registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)11513 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver) 11514 throws RemoteException { 11515 if (!checkCallingPermission(Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS, 11516 "registerShortcutKey")) { 11517 throw new SecurityException( 11518 "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission"); 11519 } 11520 mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver); 11521 } 11522 markForSeamlessRotation(WindowState w, boolean seamlesslyRotated)11523 void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) { 11524 if (seamlesslyRotated == w.mSeamlesslyRotated) { 11525 return; 11526 } 11527 w.mSeamlesslyRotated = seamlesslyRotated; 11528 if (seamlesslyRotated) { 11529 mSeamlessRotationCount++; 11530 } else { 11531 mSeamlessRotationCount--; 11532 } 11533 if (mSeamlessRotationCount == 0) { 11534 if (DEBUG_ORIENTATION) { 11535 Slog.i(TAG, "Performing post-rotate rotation after seamless rotation"); 11536 } 11537 if (updateRotationUncheckedLocked(false)) { 11538 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 11539 } 11540 } 11541 } 11542 11543 private final class LocalService extends WindowManagerInternal { 11544 @Override requestTraversalFromDisplayManager()11545 public void requestTraversalFromDisplayManager() { 11546 requestTraversal(); 11547 } 11548 11549 @Override setMagnificationSpec(MagnificationSpec spec)11550 public void setMagnificationSpec(MagnificationSpec spec) { 11551 synchronized (mWindowMap) { 11552 if (mAccessibilityController != null) { 11553 mAccessibilityController.setMagnificationSpecLocked(spec); 11554 } else { 11555 throw new IllegalStateException("Magnification callbacks not set!"); 11556 } 11557 } 11558 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11559 spec.recycle(); 11560 } 11561 } 11562 11563 @Override getMagnificationRegion(@onNull Region magnificationRegion)11564 public void getMagnificationRegion(@NonNull Region magnificationRegion) { 11565 synchronized (mWindowMap) { 11566 if (mAccessibilityController != null) { 11567 mAccessibilityController.getMagnificationRegionLocked(magnificationRegion); 11568 } else { 11569 throw new IllegalStateException("Magnification callbacks not set!"); 11570 } 11571 } 11572 } 11573 11574 @Override getCompatibleMagnificationSpecForWindow(IBinder windowToken)11575 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11576 synchronized (mWindowMap) { 11577 WindowState windowState = mWindowMap.get(windowToken); 11578 if (windowState == null) { 11579 return null; 11580 } 11581 MagnificationSpec spec = null; 11582 if (mAccessibilityController != null) { 11583 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11584 } 11585 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11586 return null; 11587 } 11588 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11589 spec.scale *= windowState.mGlobalScale; 11590 return spec; 11591 } 11592 } 11593 11594 @Override setMagnificationCallbacks(@ullable MagnificationCallbacks callbacks)11595 public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) { 11596 synchronized (mWindowMap) { 11597 if (mAccessibilityController == null) { 11598 mAccessibilityController = new AccessibilityController( 11599 WindowManagerService.this); 11600 } 11601 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11602 if (!mAccessibilityController.hasCallbacksLocked()) { 11603 mAccessibilityController = null; 11604 } 11605 } 11606 } 11607 11608 @Override setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback)11609 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11610 synchronized (mWindowMap) { 11611 if (mAccessibilityController == null) { 11612 mAccessibilityController = new AccessibilityController( 11613 WindowManagerService.this); 11614 } 11615 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11616 if (!mAccessibilityController.hasCallbacksLocked()) { 11617 mAccessibilityController = null; 11618 } 11619 } 11620 } 11621 11622 @Override setInputFilter(IInputFilter filter)11623 public void setInputFilter(IInputFilter filter) { 11624 mInputManager.setInputFilter(filter); 11625 } 11626 11627 @Override getFocusedWindowToken()11628 public IBinder getFocusedWindowToken() { 11629 synchronized (mWindowMap) { 11630 WindowState windowState = getFocusedWindowLocked(); 11631 if (windowState != null) { 11632 return windowState.mClient.asBinder(); 11633 } 11634 return null; 11635 } 11636 } 11637 11638 @Override isKeyguardLocked()11639 public boolean isKeyguardLocked() { 11640 return WindowManagerService.this.isKeyguardLocked(); 11641 } 11642 11643 @Override showGlobalActions()11644 public void showGlobalActions() { 11645 WindowManagerService.this.showGlobalActions(); 11646 } 11647 11648 @Override getWindowFrame(IBinder token, Rect outBounds)11649 public void getWindowFrame(IBinder token, Rect outBounds) { 11650 synchronized (mWindowMap) { 11651 WindowState windowState = mWindowMap.get(token); 11652 if (windowState != null) { 11653 outBounds.set(windowState.mFrame); 11654 } else { 11655 outBounds.setEmpty(); 11656 } 11657 } 11658 } 11659 11660 @Override waitForAllWindowsDrawn(Runnable callback, long timeout)11661 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 11662 boolean allWindowsDrawn = false; 11663 synchronized (mWindowMap) { 11664 mWaitingForDrawnCallback = callback; 11665 final WindowList windows = getDefaultWindowListLocked(); 11666 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11667 final WindowState win = windows.get(winNdx); 11668 final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs); 11669 final boolean keyguard = mPolicy.isKeyguardHostWindow(win.mAttrs); 11670 if (win.isVisibleLw() 11671 && (win.mAppToken != null || isForceHiding || keyguard)) { 11672 win.mWinAnimator.mDrawState = DRAW_PENDING; 11673 // Force add to mResizingWindows. 11674 win.mLastContentInsets.set(-1, -1, -1, -1); 11675 mWaitingForDrawn.add(win); 11676 11677 // No need to wait for the windows below Keyguard. 11678 if (isForceHiding) { 11679 break; 11680 } 11681 } 11682 } 11683 mWindowPlacerLocked.requestTraversal(); 11684 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11685 if (mWaitingForDrawn.isEmpty()) { 11686 allWindowsDrawn = true; 11687 } else { 11688 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11689 checkDrawnWindowsLocked(); 11690 } 11691 } 11692 if (allWindowsDrawn) { 11693 callback.run(); 11694 } 11695 } 11696 11697 @Override addWindowToken(IBinder token, int type)11698 public void addWindowToken(IBinder token, int type) { 11699 WindowManagerService.this.addWindowToken(token, type); 11700 } 11701 11702 @Override removeWindowToken(IBinder token, boolean removeWindows)11703 public void removeWindowToken(IBinder token, boolean removeWindows) { 11704 synchronized(mWindowMap) { 11705 if (removeWindows) { 11706 WindowToken wtoken = mTokenMap.remove(token); 11707 if (wtoken != null) { 11708 wtoken.removeAllWindows(); 11709 } 11710 } 11711 WindowManagerService.this.removeWindowToken(token); 11712 } 11713 } 11714 11715 @Override registerAppTransitionListener(AppTransitionListener listener)11716 public void registerAppTransitionListener(AppTransitionListener listener) { 11717 synchronized (mWindowMap) { 11718 mAppTransition.registerListenerLocked(listener); 11719 } 11720 } 11721 11722 @Override getInputMethodWindowVisibleHeight()11723 public int getInputMethodWindowVisibleHeight() { 11724 synchronized (mWindowMap) { 11725 return mPolicy.getInputMethodWindowVisibleHeightLw(); 11726 } 11727 } 11728 11729 @Override saveLastInputMethodWindowForTransition()11730 public void saveLastInputMethodWindowForTransition() { 11731 synchronized (mWindowMap) { 11732 if (mInputMethodWindow != null) { 11733 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 11734 } 11735 } 11736 } 11737 11738 @Override clearLastInputMethodWindowForTransition()11739 public void clearLastInputMethodWindowForTransition() { 11740 synchronized (mWindowMap) { 11741 mPolicy.setLastInputMethodWindowLw(null, null); 11742 } 11743 } 11744 11745 @Override isHardKeyboardAvailable()11746 public boolean isHardKeyboardAvailable() { 11747 synchronized (mWindowMap) { 11748 return mHardKeyboardAvailable; 11749 } 11750 } 11751 11752 @Override setOnHardKeyboardStatusChangeListener( OnHardKeyboardStatusChangeListener listener)11753 public void setOnHardKeyboardStatusChangeListener( 11754 OnHardKeyboardStatusChangeListener listener) { 11755 synchronized (mWindowMap) { 11756 mHardKeyboardStatusChangeListener = listener; 11757 } 11758 } 11759 11760 @Override isStackVisible(int stackId)11761 public boolean isStackVisible(int stackId) { 11762 synchronized (mWindowMap) { 11763 return WindowManagerService.this.isStackVisibleLocked(stackId); 11764 } 11765 } 11766 11767 @Override isDockedDividerResizing()11768 public boolean isDockedDividerResizing() { 11769 synchronized (mWindowMap) { 11770 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing(); 11771 } 11772 } 11773 } 11774 } 11775