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