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