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