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