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