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