WindowManagerService.java revision 3a0d878ab56475276c61d574af7651820a5cea5a
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(); 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.mKeyguardGoingAwayAnimation); 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, Rect outStableInsets, 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.getInsetHintLw(win.mAttrs, outContentInsets, outStableInsets); 2508 } else { 2509 outContentInsets.setEmpty(); 2510 outStableInsets.setEmpty(); 2511 } 2512 2513 if (mInTouchMode) { 2514 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2515 } 2516 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2517 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2518 } 2519 2520 mInputMonitor.setUpdateInputWindowsNeededLw(); 2521 2522 boolean focusChanged = false; 2523 if (win.canReceiveKeys()) { 2524 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2525 false /*updateInputWindows*/); 2526 if (focusChanged) { 2527 imMayMove = false; 2528 } 2529 } 2530 2531 if (imMayMove) { 2532 moveInputMethodWindowsIfNeededLocked(false); 2533 } 2534 2535 assignLayersLocked(displayContent.getWindowList()); 2536 // Don't do layout here, the window must call 2537 // relayout to be displayed, so we'll do it there. 2538 2539 if (focusChanged) { 2540 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/); 2541 } 2542 mInputMonitor.updateInputWindowsLw(false /*force*/); 2543 2544 if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG, "addWindow: New client " 2545 + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5)); 2546 2547 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2548 reportNewConfig = true; 2549 } 2550 } 2551 2552 if (reportNewConfig) { 2553 sendNewConfiguration(); 2554 } 2555 2556 Binder.restoreCallingIdentity(origId); 2557 2558 return res; 2559 } 2560 2561 /** 2562 * Returns whether screen capture is disabled for all windows of a specific user. 2563 */ 2564 boolean isScreenCaptureDisabledLocked(int userId) { 2565 Boolean disabled = mScreenCaptureDisabled.get(userId); 2566 if (disabled == null) { 2567 return false; 2568 } 2569 return disabled; 2570 } 2571 2572 /** 2573 * Set mScreenCaptureDisabled for specific user 2574 */ 2575 @Override 2576 public void setScreenCaptureDisabled(int userId, boolean disabled) { 2577 int callingUid = Binder.getCallingUid(); 2578 if (callingUid != Process.SYSTEM_UID) { 2579 throw new SecurityException("Only system can call setScreenCaptureDisabled."); 2580 } 2581 2582 synchronized(mWindowMap) { 2583 mScreenCaptureDisabled.put(userId, disabled); 2584 } 2585 } 2586 2587 public void removeWindow(Session session, IWindow client) { 2588 synchronized(mWindowMap) { 2589 WindowState win = windowForClientLocked(session, client, false); 2590 if (win == null) { 2591 return; 2592 } 2593 removeWindowLocked(session, win); 2594 } 2595 } 2596 2597 public void removeWindowLocked(Session session, WindowState win) { 2598 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2599 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win); 2600 } 2601 2602 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v( 2603 TAG, "Remove " + win + " client=" 2604 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) 2605 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers=" 2606 + Debug.getCallers(4)); 2607 2608 final long origId = Binder.clearCallingIdentity(); 2609 2610 win.disposeInputChannel(); 2611 2612 if (DEBUG_APP_TRANSITIONS) Slog.v( 2613 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl 2614 + " mExiting=" + win.mExiting 2615 + " isAnimating=" + win.mWinAnimator.isAnimating() 2616 + " app-animation=" 2617 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2618 + " inPendingTransaction=" 2619 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2620 + " mDisplayFrozen=" + mDisplayFrozen); 2621 // Visibility of the removed window. Will be used later to update orientation later on. 2622 boolean wasVisible = false; 2623 // First, see if we need to run an animation. If we do, we have 2624 // to hold off on removing the window until the animation is done. 2625 // If the display is frozen, just remove immediately, since the 2626 // animation wouldn't be seen. 2627 if (win.mHasSurface && okToDisplay()) { 2628 // If we are not currently running the exit animation, we 2629 // need to see about starting one. 2630 wasVisible = win.isWinVisibleLw(); 2631 if (wasVisible) { 2632 2633 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2634 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2635 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2636 } 2637 // Try starting an animation. 2638 if (win.mWinAnimator.applyAnimationLocked(transit, false)) { 2639 win.mExiting = true; 2640 } 2641 //TODO (multidisplay): Magnification is supported only for the default display. 2642 if (mAccessibilityController != null 2643 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2644 mAccessibilityController.onWindowTransitionLocked(win, transit); 2645 } 2646 } 2647 if (win.mExiting || win.mWinAnimator.isAnimating()) { 2648 // The exit animation is running... wait for it! 2649 //Slog.i(TAG, "*** Running exit animation..."); 2650 win.mExiting = true; 2651 win.mRemoveOnExit = true; 2652 final DisplayContent displayContent = win.getDisplayContent(); 2653 if (displayContent != null) { 2654 displayContent.layoutNeeded = true; 2655 } 2656 final boolean focusChanged = updateFocusedWindowLocked( 2657 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 2658 performLayoutAndPlaceSurfacesLocked(); 2659 if (win.mAppToken != null) { 2660 win.mAppToken.updateReportedVisibilityLocked(); 2661 } 2662 if (focusChanged) { 2663 mInputMonitor.updateInputWindowsLw(false /*force*/); 2664 } 2665 //dump(); 2666 Binder.restoreCallingIdentity(origId); 2667 return; 2668 } 2669 } 2670 2671 removeWindowInnerLocked(session, win); 2672 // Removing a visible window will effect the computed orientation 2673 // So just update orientation if needed. 2674 if (wasVisible && updateOrientationFromAppTokensLocked(false)) { 2675 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2676 } 2677 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2678 Binder.restoreCallingIdentity(origId); 2679 } 2680 2681 void removeWindowInnerLocked(Session session, WindowState win) { 2682 if (win.mRemoved) { 2683 // Nothing to do. 2684 return; 2685 } 2686 2687 for (int i=win.mChildWindows.size()-1; i>=0; i--) { 2688 WindowState cwin = win.mChildWindows.get(i); 2689 Slog.w(TAG, "Force-removing child win " + cwin + " from container " 2690 + win); 2691 removeWindowInnerLocked(cwin.mSession, cwin); 2692 } 2693 2694 win.mRemoved = true; 2695 2696 if (mInputMethodTarget == win) { 2697 moveInputMethodWindowsIfNeededLocked(false); 2698 } 2699 2700 if (false) { 2701 RuntimeException e = new RuntimeException("here"); 2702 e.fillInStackTrace(); 2703 Slog.w(TAG, "Removing window " + win, e); 2704 } 2705 2706 mPolicy.removeWindowLw(win); 2707 win.removeLocked(); 2708 2709 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); 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 overridePendingAppTransitionInPlace(String packageName, int anim) { 4128 synchronized(mWindowMap) { 4129 mAppTransition.overrideInPlaceAppTransition(packageName, anim); 4130 } 4131 } 4132 4133 @Override 4134 public void executeAppTransition() { 4135 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4136 "executeAppTransition()")) { 4137 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4138 } 4139 4140 synchronized(mWindowMap) { 4141 if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition, 4142 new RuntimeException("here").fillInStackTrace()); 4143 if (mAppTransition.isTransitionSet()) { 4144 mAppTransition.setReady(); 4145 final long origId = Binder.clearCallingIdentity(); 4146 try { 4147 performLayoutAndPlaceSurfacesLocked(); 4148 } finally { 4149 Binder.restoreCallingIdentity(origId); 4150 } 4151 } 4152 } 4153 } 4154 4155 @Override 4156 public void setAppStartingWindow(IBinder token, String pkg, 4157 int theme, CompatibilityInfo compatInfo, 4158 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, 4159 int windowFlags, IBinder transferFrom, boolean createIfNeeded) { 4160 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4161 "setAppStartingWindow()")) { 4162 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4163 } 4164 4165 synchronized(mWindowMap) { 4166 if (DEBUG_STARTING_WINDOW) Slog.v( 4167 TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg 4168 + " transferFrom=" + transferFrom); 4169 4170 AppWindowToken wtoken = findAppWindowToken(token); 4171 if (wtoken == null) { 4172 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token); 4173 return; 4174 } 4175 4176 // If the display is frozen, we won't do anything until the 4177 // actual window is displayed so there is no reason to put in 4178 // the starting window. 4179 if (!okToDisplay()) { 4180 return; 4181 } 4182 4183 if (wtoken.startingData != null) { 4184 return; 4185 } 4186 4187 if (transferFrom != null) { 4188 AppWindowToken ttoken = findAppWindowToken(transferFrom); 4189 if (ttoken != null) { 4190 WindowState startingWindow = ttoken.startingWindow; 4191 if (startingWindow != null) { 4192 if (mStartingIconInTransition) { 4193 // In this case, the starting icon has already 4194 // been displayed, so start letting windows get 4195 // shown immediately without any more transitions. 4196 mSkipAppTransitionAnimation = true; 4197 } 4198 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4199 "Moving existing starting " + startingWindow + " from " + ttoken 4200 + " to " + wtoken); 4201 final long origId = Binder.clearCallingIdentity(); 4202 4203 // Transfer the starting window over to the new 4204 // token. 4205 wtoken.startingData = ttoken.startingData; 4206 wtoken.startingView = ttoken.startingView; 4207 wtoken.startingDisplayed = ttoken.startingDisplayed; 4208 ttoken.startingDisplayed = false; 4209 wtoken.startingWindow = startingWindow; 4210 wtoken.reportedVisible = ttoken.reportedVisible; 4211 ttoken.startingData = null; 4212 ttoken.startingView = null; 4213 ttoken.startingWindow = null; 4214 ttoken.startingMoved = true; 4215 startingWindow.mToken = wtoken; 4216 startingWindow.mRootToken = wtoken; 4217 startingWindow.mAppToken = wtoken; 4218 startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator; 4219 4220 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { 4221 Slog.v(TAG, "Removing starting window: " + startingWindow); 4222 } 4223 startingWindow.getWindowList().remove(startingWindow); 4224 mWindowsChanged = true; 4225 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 4226 "Removing starting " + startingWindow + " from " + ttoken); 4227 ttoken.windows.remove(startingWindow); 4228 ttoken.allAppWindows.remove(startingWindow); 4229 addWindowToListInOrderLocked(startingWindow, true); 4230 4231 // Propagate other interesting state between the 4232 // tokens. If the old token is displayed, we should 4233 // immediately force the new one to be displayed. If 4234 // it is animating, we need to move that animation to 4235 // the new one. 4236 if (ttoken.allDrawn) { 4237 wtoken.allDrawn = true; 4238 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn; 4239 } 4240 if (ttoken.firstWindowDrawn) { 4241 wtoken.firstWindowDrawn = true; 4242 } 4243 if (!ttoken.hidden) { 4244 wtoken.hidden = false; 4245 wtoken.hiddenRequested = false; 4246 wtoken.willBeHidden = false; 4247 } 4248 if (wtoken.clientHidden != ttoken.clientHidden) { 4249 wtoken.clientHidden = ttoken.clientHidden; 4250 wtoken.sendAppVisibilityToClients(); 4251 } 4252 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4253 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4254 if (tAppAnimator.animation != null) { 4255 wAppAnimator.animation = tAppAnimator.animation; 4256 wAppAnimator.animating = tAppAnimator.animating; 4257 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; 4258 tAppAnimator.animation = null; 4259 tAppAnimator.animLayerAdjustment = 0; 4260 wAppAnimator.updateLayers(); 4261 tAppAnimator.updateLayers(); 4262 } 4263 4264 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4265 true /*updateInputWindows*/); 4266 getDefaultDisplayContentLocked().layoutNeeded = true; 4267 performLayoutAndPlaceSurfacesLocked(); 4268 Binder.restoreCallingIdentity(origId); 4269 return; 4270 } else if (ttoken.startingData != null) { 4271 // The previous app was getting ready to show a 4272 // starting window, but hasn't yet done so. Steal it! 4273 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4274 "Moving pending starting from " + ttoken 4275 + " to " + wtoken); 4276 wtoken.startingData = ttoken.startingData; 4277 ttoken.startingData = null; 4278 ttoken.startingMoved = true; 4279 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4280 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4281 // want to process the message ASAP, before any other queued 4282 // messages. 4283 mH.sendMessageAtFrontOfQueue(m); 4284 return; 4285 } 4286 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4287 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4288 if (tAppAnimator.thumbnail != null) { 4289 // The old token is animating with a thumbnail, transfer 4290 // that to the new token. 4291 if (wAppAnimator.thumbnail != null) { 4292 wAppAnimator.thumbnail.destroy(); 4293 } 4294 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 4295 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX; 4296 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY; 4297 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 4298 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 4299 tAppAnimator.thumbnail = null; 4300 } 4301 } 4302 } 4303 4304 // There is no existing starting window, and the caller doesn't 4305 // want us to create one, so that's it! 4306 if (!createIfNeeded) { 4307 return; 4308 } 4309 4310 // If this is a translucent window, then don't 4311 // show a starting window -- the current effect (a full-screen 4312 // opaque starting window that fades away to the real contents 4313 // when it is ready) does not work for this. 4314 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x" 4315 + Integer.toHexString(theme)); 4316 if (theme != 0) { 4317 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 4318 com.android.internal.R.styleable.Window, mCurrentUserId); 4319 if (ent == null) { 4320 // Whoops! App doesn't exist. Um. Okay. We'll just 4321 // pretend like we didn't see that. 4322 return; 4323 } 4324 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent=" 4325 + ent.array.getBoolean( 4326 com.android.internal.R.styleable.Window_windowIsTranslucent, false) 4327 + " Floating=" 4328 + ent.array.getBoolean( 4329 com.android.internal.R.styleable.Window_windowIsFloating, false) 4330 + " ShowWallpaper=" 4331 + ent.array.getBoolean( 4332 com.android.internal.R.styleable.Window_windowShowWallpaper, false)); 4333 if (ent.array.getBoolean( 4334 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { 4335 return; 4336 } 4337 if (ent.array.getBoolean( 4338 com.android.internal.R.styleable.Window_windowIsFloating, false)) { 4339 return; 4340 } 4341 if (ent.array.getBoolean( 4342 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { 4343 if (mWallpaperTarget == null) { 4344 // If this theme is requesting a wallpaper, and the wallpaper 4345 // is not curently visible, then this effectively serves as 4346 // an opaque window and our starting window transition animation 4347 // can still work. We just need to make sure the starting window 4348 // is also showing the wallpaper. 4349 windowFlags |= FLAG_SHOW_WALLPAPER; 4350 } else { 4351 return; 4352 } 4353 } 4354 } 4355 4356 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); 4357 mStartingIconInTransition = true; 4358 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, 4359 labelRes, icon, logo, windowFlags); 4360 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4361 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4362 // want to process the message ASAP, before any other queued 4363 // messages. 4364 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING"); 4365 mH.sendMessageAtFrontOfQueue(m); 4366 } 4367 } 4368 4369 public void removeAppStartingWindow(IBinder token) { 4370 synchronized (mWindowMap) { 4371 AppWindowToken wtoken = mTokenMap.get(token).appWindowToken; 4372 if (wtoken.startingWindow != null) { 4373 scheduleRemoveStartingWindowLocked(wtoken); 4374 } 4375 } 4376 } 4377 4378 @Override 4379 public void setAppWillBeHidden(IBinder token) { 4380 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4381 "setAppWillBeHidden()")) { 4382 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4383 } 4384 4385 AppWindowToken wtoken; 4386 4387 synchronized(mWindowMap) { 4388 wtoken = findAppWindowToken(token); 4389 if (wtoken == null) { 4390 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token); 4391 return; 4392 } 4393 wtoken.willBeHidden = true; 4394 } 4395 } 4396 4397 public void setAppFullscreen(IBinder token, boolean toOpaque) { 4398 synchronized (mWindowMap) { 4399 AppWindowToken atoken = findAppWindowToken(token); 4400 if (atoken != null) { 4401 atoken.appFullscreen = toOpaque; 4402 setWindowOpaqueLocked(token, toOpaque); 4403 requestTraversalLocked(); 4404 } 4405 } 4406 } 4407 4408 public void setWindowOpaque(IBinder token, boolean isOpaque) { 4409 synchronized (mWindowMap) { 4410 setWindowOpaqueLocked(token, isOpaque); 4411 } 4412 } 4413 4414 public void setWindowOpaqueLocked(IBinder token, boolean isOpaque) { 4415 AppWindowToken wtoken = findAppWindowToken(token); 4416 if (wtoken != null) { 4417 WindowState win = wtoken.findMainWindow(); 4418 if (win != null) { 4419 win.mWinAnimator.setOpaqueLocked(isOpaque); 4420 } 4421 } 4422 } 4423 4424 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4425 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { 4426 boolean delayed = false; 4427 4428 if (wtoken.clientHidden == visible) { 4429 wtoken.clientHidden = !visible; 4430 wtoken.sendAppVisibilityToClients(); 4431 } 4432 4433 wtoken.willBeHidden = false; 4434 if (wtoken.hidden == visible) { 4435 boolean changed = false; 4436 if (DEBUG_APP_TRANSITIONS) Slog.v( 4437 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4438 + " performLayout=" + performLayout); 4439 4440 boolean runningAppAnimation = false; 4441 4442 if (transit != AppTransition.TRANSIT_UNSET) { 4443 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4444 wtoken.mAppAnimator.animation = null; 4445 } 4446 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) { 4447 delayed = runningAppAnimation = true; 4448 } 4449 WindowState window = wtoken.findMainWindow(); 4450 //TODO (multidisplay): Magnification is supported only for the default display. 4451 if (window != null && mAccessibilityController != null 4452 && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 4453 mAccessibilityController.onAppWindowTransitionLocked(window, transit); 4454 } 4455 changed = true; 4456 } 4457 4458 final int N = wtoken.allAppWindows.size(); 4459 for (int i=0; i<N; i++) { 4460 WindowState win = wtoken.allAppWindows.get(i); 4461 if (win == wtoken.startingWindow) { 4462 continue; 4463 } 4464 4465 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); 4466 //win.dump(" "); 4467 if (visible) { 4468 if (!win.isVisibleNow()) { 4469 if (!runningAppAnimation) { 4470 win.mWinAnimator.applyAnimationLocked( 4471 WindowManagerPolicy.TRANSIT_ENTER, true); 4472 //TODO (multidisplay): Magnification is supported only for the default 4473 if (mAccessibilityController != null 4474 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4475 mAccessibilityController.onWindowTransitionLocked(win, 4476 WindowManagerPolicy.TRANSIT_ENTER); 4477 } 4478 } 4479 changed = true; 4480 final DisplayContent displayContent = win.getDisplayContent(); 4481 if (displayContent != null) { 4482 displayContent.layoutNeeded = true; 4483 } 4484 } 4485 } else if (win.isVisibleNow()) { 4486 if (!runningAppAnimation) { 4487 win.mWinAnimator.applyAnimationLocked( 4488 WindowManagerPolicy.TRANSIT_EXIT, false); 4489 //TODO (multidisplay): Magnification is supported only for the default 4490 if (mAccessibilityController != null 4491 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4492 mAccessibilityController.onWindowTransitionLocked(win, 4493 WindowManagerPolicy.TRANSIT_EXIT); 4494 } 4495 } 4496 changed = true; 4497 final DisplayContent displayContent = win.getDisplayContent(); 4498 if (displayContent != null) { 4499 displayContent.layoutNeeded = true; 4500 } 4501 } 4502 } 4503 4504 wtoken.hidden = wtoken.hiddenRequested = !visible; 4505 if (!visible) { 4506 unsetAppFreezingScreenLocked(wtoken, true, true); 4507 } else { 4508 // If we are being set visible, and the starting window is 4509 // not yet displayed, then make sure it doesn't get displayed. 4510 WindowState swin = wtoken.startingWindow; 4511 if (swin != null && !swin.isDrawnLw()) { 4512 swin.mPolicyVisibility = false; 4513 swin.mPolicyVisibilityAfterAnim = false; 4514 } 4515 } 4516 4517 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken 4518 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4519 + wtoken.hiddenRequested); 4520 4521 if (changed) { 4522 mInputMonitor.setUpdateInputWindowsNeededLw(); 4523 if (performLayout) { 4524 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4525 false /*updateInputWindows*/); 4526 performLayoutAndPlaceSurfacesLocked(); 4527 } 4528 mInputMonitor.updateInputWindowsLw(false /*force*/); 4529 } 4530 } 4531 4532 if (wtoken.mAppAnimator.animation != null) { 4533 delayed = true; 4534 } 4535 4536 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4537 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { 4538 delayed = true; 4539 } 4540 } 4541 4542 return delayed; 4543 } 4544 4545 void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) { 4546 if (transit != AppTransition.TRANSIT_UNSET) { 4547 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4548 wtoken.mAppAnimator.animation = null; 4549 } 4550 applyAnimationLocked(wtoken, null, transit, false, false); 4551 } 4552 } 4553 4554 @Override 4555 public void setAppVisibility(IBinder token, boolean visible) { 4556 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4557 "setAppVisibility()")) { 4558 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4559 } 4560 4561 AppWindowToken wtoken; 4562 4563 synchronized(mWindowMap) { 4564 wtoken = findAppWindowToken(token); 4565 if (wtoken == null) { 4566 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); 4567 return; 4568 } 4569 4570 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" + 4571 token + ", visible=" + visible + "): " + mAppTransition + 4572 " hidden=" + wtoken.hidden + " hiddenRequested=" + 4573 wtoken.hiddenRequested, HIDE_STACK_CRAWLS ? 4574 null : new RuntimeException("here").fillInStackTrace()); 4575 4576 // If we are preparing an app transition, then delay changing 4577 // the visibility of this token until we execute that transition. 4578 if (okToDisplay() && mAppTransition.isTransitionSet()) { 4579 wtoken.hiddenRequested = !visible; 4580 4581 if (!wtoken.startingDisplayed) { 4582 if (DEBUG_APP_TRANSITIONS) Slog.v( 4583 TAG, "Setting dummy animation on: " + wtoken); 4584 wtoken.mAppAnimator.setDummyAnimation(); 4585 } 4586 mOpeningApps.remove(wtoken); 4587 mClosingApps.remove(wtoken); 4588 wtoken.waitingToShow = wtoken.waitingToHide = false; 4589 wtoken.inPendingTransaction = true; 4590 if (visible) { 4591 mOpeningApps.add(wtoken); 4592 wtoken.startingMoved = false; 4593 wtoken.mEnteringAnimation = true; 4594 4595 // If the token is currently hidden (should be the 4596 // common case), then we need to set up to wait for 4597 // its windows to be ready. 4598 if (wtoken.hidden) { 4599 wtoken.allDrawn = false; 4600 wtoken.deferClearAllDrawn = false; 4601 wtoken.waitingToShow = true; 4602 4603 if (wtoken.clientHidden) { 4604 // In the case where we are making an app visible 4605 // but holding off for a transition, we still need 4606 // to tell the client to make its windows visible so 4607 // they get drawn. Otherwise, we will wait on 4608 // performing the transition until all windows have 4609 // been drawn, they never will be, and we are sad. 4610 wtoken.clientHidden = false; 4611 wtoken.sendAppVisibilityToClients(); 4612 } 4613 } 4614 } else { 4615 mClosingApps.add(wtoken); 4616 wtoken.mEnteringAnimation = false; 4617 4618 // If the token is currently visible (should be the 4619 // common case), then set up to wait for it to be hidden. 4620 if (!wtoken.hidden) { 4621 wtoken.waitingToHide = true; 4622 } 4623 } 4624 if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) { 4625 // We're launchingBehind, add the launching activity to mOpeningApps. 4626 final WindowState win = 4627 findFocusedWindowLocked(getDefaultDisplayContentLocked()); 4628 if (win != null) { 4629 final AppWindowToken focusedToken = win.mAppToken; 4630 if (focusedToken != null) { 4631 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "TRANSIT_TASK_OPEN_BEHIND, " + 4632 " adding " + focusedToken + " to mOpeningApps"); 4633 // Force animation to be loaded. 4634 focusedToken.hidden = true; 4635 mOpeningApps.add(focusedToken); 4636 } 4637 } 4638 } 4639 return; 4640 } 4641 4642 final long origId = Binder.clearCallingIdentity(); 4643 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET, 4644 true, wtoken.voiceInteraction); 4645 wtoken.updateReportedVisibilityLocked(); 4646 Binder.restoreCallingIdentity(origId); 4647 } 4648 } 4649 4650 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4651 boolean unfreezeSurfaceNow, boolean force) { 4652 if (wtoken.mAppAnimator.freezingScreen) { 4653 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken 4654 + " force=" + force); 4655 final int N = wtoken.allAppWindows.size(); 4656 boolean unfrozeWindows = false; 4657 for (int i=0; i<N; i++) { 4658 WindowState w = wtoken.allAppWindows.get(i); 4659 if (w.mAppFreezing) { 4660 w.mAppFreezing = false; 4661 if (w.mHasSurface && !w.mOrientationChanging) { 4662 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); 4663 w.mOrientationChanging = true; 4664 mInnerFields.mOrientationChangeComplete = false; 4665 } 4666 w.mLastFreezeDuration = 0; 4667 unfrozeWindows = true; 4668 final DisplayContent displayContent = w.getDisplayContent(); 4669 if (displayContent != null) { 4670 displayContent.layoutNeeded = true; 4671 } 4672 } 4673 } 4674 if (force || unfrozeWindows) { 4675 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); 4676 wtoken.mAppAnimator.freezingScreen = false; 4677 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime() 4678 - mDisplayFreezeTime); 4679 mAppsFreezingScreen--; 4680 mLastFinishedFreezeSource = wtoken; 4681 } 4682 if (unfreezeSurfaceNow) { 4683 if (unfrozeWindows) { 4684 performLayoutAndPlaceSurfacesLocked(); 4685 } 4686 stopFreezingDisplayLocked(); 4687 } 4688 } 4689 } 4690 4691 private void startAppFreezingScreenLocked(AppWindowToken wtoken) { 4692 if (DEBUG_ORIENTATION) { 4693 RuntimeException e = null; 4694 if (!HIDE_STACK_CRAWLS) { 4695 e = new RuntimeException(); 4696 e.fillInStackTrace(); 4697 } 4698 Slog.i(TAG, "Set freezing of " + wtoken.appToken 4699 + ": hidden=" + wtoken.hidden + " freezing=" 4700 + wtoken.mAppAnimator.freezingScreen, e); 4701 } 4702 if (!wtoken.hiddenRequested) { 4703 if (!wtoken.mAppAnimator.freezingScreen) { 4704 wtoken.mAppAnimator.freezingScreen = true; 4705 wtoken.mAppAnimator.lastFreezeDuration = 0; 4706 mAppsFreezingScreen++; 4707 if (mAppsFreezingScreen == 1) { 4708 startFreezingDisplayLocked(false, 0, 0); 4709 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4710 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000); 4711 } 4712 } 4713 final int N = wtoken.allAppWindows.size(); 4714 for (int i=0; i<N; i++) { 4715 WindowState w = wtoken.allAppWindows.get(i); 4716 w.mAppFreezing = true; 4717 } 4718 } 4719 } 4720 4721 @Override 4722 public void startAppFreezingScreen(IBinder token, int configChanges) { 4723 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4724 "setAppFreezingScreen()")) { 4725 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4726 } 4727 4728 synchronized(mWindowMap) { 4729 if (configChanges == 0 && okToDisplay()) { 4730 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); 4731 return; 4732 } 4733 4734 AppWindowToken wtoken = findAppWindowToken(token); 4735 if (wtoken == null || wtoken.appToken == null) { 4736 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); 4737 return; 4738 } 4739 final long origId = Binder.clearCallingIdentity(); 4740 startAppFreezingScreenLocked(wtoken); 4741 Binder.restoreCallingIdentity(origId); 4742 } 4743 } 4744 4745 @Override 4746 public void stopAppFreezingScreen(IBinder token, boolean force) { 4747 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4748 "setAppFreezingScreen()")) { 4749 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4750 } 4751 4752 synchronized(mWindowMap) { 4753 AppWindowToken wtoken = findAppWindowToken(token); 4754 if (wtoken == null || wtoken.appToken == null) { 4755 return; 4756 } 4757 final long origId = Binder.clearCallingIdentity(); 4758 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token 4759 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4760 unsetAppFreezingScreenLocked(wtoken, true, force); 4761 Binder.restoreCallingIdentity(origId); 4762 } 4763 } 4764 4765 void removeAppFromTaskLocked(AppWindowToken wtoken) { 4766 wtoken.removeAllWindows(); 4767 4768 final Task task = mTaskIdToTask.get(wtoken.groupId); 4769 if (task != null) { 4770 if (!task.removeAppToken(wtoken)) { 4771 Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found."); 4772 } 4773 } 4774 } 4775 4776 @Override 4777 public void removeAppToken(IBinder token) { 4778 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4779 "removeAppToken()")) { 4780 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4781 } 4782 4783 AppWindowToken wtoken = null; 4784 AppWindowToken startingToken = null; 4785 boolean delayed = false; 4786 4787 final long origId = Binder.clearCallingIdentity(); 4788 synchronized(mWindowMap) { 4789 WindowToken basewtoken = mTokenMap.remove(token); 4790 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4791 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); 4792 delayed = setTokenVisibilityLocked(wtoken, null, false, 4793 AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction); 4794 wtoken.inPendingTransaction = false; 4795 mOpeningApps.remove(wtoken); 4796 wtoken.waitingToShow = false; 4797 if (mClosingApps.contains(wtoken)) { 4798 delayed = true; 4799 } else if (mAppTransition.isTransitionSet()) { 4800 mClosingApps.add(wtoken); 4801 wtoken.waitingToHide = true; 4802 delayed = true; 4803 } 4804 if (DEBUG_APP_TRANSITIONS) Slog.v( 4805 TAG, "Removing app " + wtoken + " delayed=" + delayed 4806 + " animation=" + wtoken.mAppAnimator.animation 4807 + " animating=" + wtoken.mAppAnimator.animating); 4808 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " 4809 + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); 4810 final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack; 4811 if (delayed) { 4812 // set the token aside because it has an active animation to be finished 4813 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4814 "removeAppToken make exiting: " + wtoken); 4815 stack.mExitingAppTokens.add(wtoken); 4816 wtoken.mDeferRemoval = true; 4817 } else { 4818 // Make sure there is no animation running on this token, 4819 // so any windows associated with it will be removed as 4820 // soon as their animations are complete 4821 wtoken.mAppAnimator.clearAnimation(); 4822 wtoken.mAppAnimator.animating = false; 4823 removeAppFromTaskLocked(wtoken); 4824 } 4825 4826 wtoken.removed = true; 4827 if (wtoken.startingData != null) { 4828 startingToken = wtoken; 4829 } 4830 unsetAppFreezingScreenLocked(wtoken, true, true); 4831 if (mFocusedApp == wtoken) { 4832 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken); 4833 mFocusedApp = null; 4834 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4835 mInputMonitor.setFocusedAppLw(null); 4836 } 4837 } else { 4838 Slog.w(TAG, "Attempted to remove non-existing app token: " + token); 4839 } 4840 4841 if (!delayed && wtoken != null) { 4842 wtoken.updateReportedVisibilityLocked(); 4843 } 4844 4845 // Will only remove if startingToken non null. 4846 scheduleRemoveStartingWindowLocked(startingToken); 4847 } 4848 Binder.restoreCallingIdentity(origId); 4849 4850 } 4851 4852 void scheduleRemoveStartingWindowLocked(AppWindowToken wtoken) { 4853 if (mH.hasMessages(H.REMOVE_STARTING, wtoken)) { 4854 // Already scheduled. 4855 return; 4856 } 4857 if (wtoken != null && wtoken.startingWindow != null) { 4858 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4859 ": Schedule remove starting " + wtoken + (wtoken != null ? 4860 " startingWindow=" + wtoken.startingWindow : "")); 4861 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken); 4862 mH.sendMessage(m); 4863 } 4864 } 4865 4866 private boolean tmpRemoveAppWindowsLocked(WindowToken token) { 4867 WindowList windows = token.windows; 4868 final int NW = windows.size(); 4869 if (NW > 0) { 4870 mWindowsChanged = true; 4871 } 4872 for (int i = 0; i < NW; i++) { 4873 WindowState win = windows.get(i); 4874 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); 4875 win.getWindowList().remove(win); 4876 int j = win.mChildWindows.size(); 4877 while (j > 0) { 4878 j--; 4879 WindowState cwin = win.mChildWindows.get(j); 4880 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 4881 "Tmp removing child window " + cwin); 4882 cwin.getWindowList().remove(cwin); 4883 } 4884 } 4885 return NW > 0; 4886 } 4887 4888 void dumpAppTokensLocked() { 4889 final int numStacks = mStackIdToStack.size(); 4890 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 4891 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 4892 Slog.v(TAG, " Stack #" + stack.mStackId + " tasks from bottom to top:"); 4893 final ArrayList<Task> tasks = stack.getTasks(); 4894 final int numTasks = tasks.size(); 4895 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4896 final Task task = tasks.get(taskNdx); 4897 Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:"); 4898 AppTokenList tokens = task.mAppTokens; 4899 final int numTokens = tokens.size(); 4900 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4901 Slog.v(TAG, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token); 4902 } 4903 } 4904 } 4905 } 4906 4907 void dumpWindowsLocked() { 4908 final int numDisplays = mDisplayContents.size(); 4909 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4910 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4911 Slog.v(TAG, " Display #" + displayContent.getDisplayId()); 4912 final WindowList windows = displayContent.getWindowList(); 4913 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4914 Slog.v(TAG, " #" + winNdx + ": " + windows.get(winNdx)); 4915 } 4916 } 4917 } 4918 4919 private int findAppWindowInsertionPointLocked(AppWindowToken target) { 4920 final int taskId = target.groupId; 4921 Task targetTask = mTaskIdToTask.get(taskId); 4922 if (targetTask == null) { 4923 Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId=" 4924 + taskId); 4925 return 0; 4926 } 4927 DisplayContent displayContent = targetTask.getDisplayContent(); 4928 if (displayContent == null) { 4929 Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target); 4930 return 0; 4931 } 4932 final WindowList windows = displayContent.getWindowList(); 4933 final int NW = windows.size(); 4934 4935 boolean found = false; 4936 final ArrayList<Task> tasks = displayContent.getTasks(); 4937 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 4938 final Task task = tasks.get(taskNdx); 4939 if (!found && task.taskId != taskId) { 4940 continue; 4941 } 4942 AppTokenList tokens = task.mAppTokens; 4943 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4944 final AppWindowToken wtoken = tokens.get(tokenNdx); 4945 if (!found && wtoken == target) { 4946 found = true; 4947 } 4948 if (found) { 4949 // Find the first app token below the new position that has 4950 // a window displayed. 4951 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token); 4952 if (wtoken.sendingToBottom) { 4953 if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom"); 4954 continue; 4955 } 4956 for (int i = wtoken.windows.size() - 1; i >= 0; --i) { 4957 WindowState win = wtoken.windows.get(i); 4958 for (int j = win.mChildWindows.size() - 1; j >= 0; --j) { 4959 WindowState cwin = win.mChildWindows.get(j); 4960 if (cwin.mSubLayer >= 0) { 4961 for (int pos = NW - 1; pos >= 0; pos--) { 4962 if (windows.get(pos) == cwin) { 4963 if (DEBUG_REORDER) Slog.v(TAG, 4964 "Found child win @" + (pos + 1)); 4965 return pos + 1; 4966 } 4967 } 4968 } 4969 } 4970 for (int pos = NW - 1; pos >= 0; pos--) { 4971 if (windows.get(pos) == win) { 4972 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1)); 4973 return pos + 1; 4974 } 4975 } 4976 } 4977 } 4978 } 4979 } 4980 // Never put an app window underneath wallpaper. 4981 for (int pos = NW - 1; pos >= 0; pos--) { 4982 if (windows.get(pos).mIsWallpaper) { 4983 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos); 4984 return pos + 1; 4985 } 4986 } 4987 return 0; 4988 } 4989 4990 private final int reAddWindowLocked(int index, WindowState win) { 4991 final WindowList windows = win.getWindowList(); 4992 final int NCW = win.mChildWindows.size(); 4993 boolean added = false; 4994 for (int j=0; j<NCW; j++) { 4995 WindowState cwin = win.mChildWindows.get(j); 4996 if (!added && cwin.mSubLayer >= 0) { 4997 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " 4998 + index + ": " + cwin); 4999 win.mRebuilding = false; 5000 windows.add(index, win); 5001 index++; 5002 added = true; 5003 } 5004 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 5005 + index + ": " + cwin); 5006 cwin.mRebuilding = false; 5007 windows.add(index, cwin); 5008 index++; 5009 } 5010 if (!added) { 5011 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 5012 + index + ": " + win); 5013 win.mRebuilding = false; 5014 windows.add(index, win); 5015 index++; 5016 } 5017 mWindowsChanged = true; 5018 return index; 5019 } 5020 5021 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index, 5022 WindowToken token) { 5023 final int NW = token.windows.size(); 5024 for (int i=0; i<NW; i++) { 5025 final WindowState win = token.windows.get(i); 5026 final DisplayContent winDisplayContent = win.getDisplayContent(); 5027 if (winDisplayContent == displayContent || winDisplayContent == null) { 5028 win.mDisplayContent = displayContent; 5029 index = reAddWindowLocked(index, win); 5030 } 5031 } 5032 return index; 5033 } 5034 5035 void tmpRemoveTaskWindowsLocked(Task task) { 5036 AppTokenList tokens = task.mAppTokens; 5037 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 5038 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); 5039 } 5040 } 5041 5042 void moveStackWindowsLocked(DisplayContent displayContent) { 5043 // First remove all of the windows from the list. 5044 final ArrayList<Task> tasks = displayContent.getTasks(); 5045 final int numTasks = tasks.size(); 5046 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 5047 tmpRemoveTaskWindowsLocked(tasks.get(taskNdx)); 5048 } 5049 5050 // And now add them back at the correct place. 5051 // Where to start adding? 5052 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 5053 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 5054 final int numTokens = tokens.size(); 5055 if (numTokens == 0) { 5056 continue; 5057 } 5058 int pos = findAppWindowInsertionPointLocked(tokens.get(0)); 5059 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 5060 final AppWindowToken wtoken = tokens.get(tokenNdx); 5061 if (wtoken != null) { 5062 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 5063 if (newPos != pos) { 5064 displayContent.layoutNeeded = true; 5065 } 5066 pos = newPos; 5067 } 5068 } 5069 } 5070 5071 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 5072 false /*updateInputWindows*/)) { 5073 assignLayersLocked(displayContent.getWindowList()); 5074 } 5075 5076 mInputMonitor.setUpdateInputWindowsNeededLw(); 5077 performLayoutAndPlaceSurfacesLocked(); 5078 mInputMonitor.updateInputWindowsLw(false /*force*/); 5079 5080 //dump(); 5081 } 5082 5083 public void moveTaskToTop(int taskId) { 5084 final long origId = Binder.clearCallingIdentity(); 5085 try { 5086 synchronized(mWindowMap) { 5087 Task task = mTaskIdToTask.get(taskId); 5088 if (task == null) { 5089 // Normal behavior, addAppToken will be called next and task will be created. 5090 return; 5091 } 5092 final TaskStack stack = task.mStack; 5093 final DisplayContent displayContent = task.getDisplayContent(); 5094 displayContent.moveStack(stack, true); 5095 if (displayContent.isDefaultDisplay) { 5096 final TaskStack homeStack = displayContent.getHomeStack(); 5097 if (homeStack != stack) { 5098 // When a non-home stack moves to the top, the home stack moves to the 5099 // bottom. 5100 displayContent.moveStack(homeStack, false); 5101 } 5102 } 5103 stack.moveTaskToTop(task); 5104 if (mAppTransition.isTransitionSet()) { 5105 task.setSendingToBottom(false); 5106 } 5107 moveStackWindowsLocked(displayContent); 5108 } 5109 } finally { 5110 Binder.restoreCallingIdentity(origId); 5111 } 5112 } 5113 5114 public void moveTaskToBottom(int taskId) { 5115 final long origId = Binder.clearCallingIdentity(); 5116 try { 5117 synchronized(mWindowMap) { 5118 Task task = mTaskIdToTask.get(taskId); 5119 if (task == null) { 5120 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId 5121 + " not found in mTaskIdToTask"); 5122 return; 5123 } 5124 final TaskStack stack = task.mStack; 5125 stack.moveTaskToBottom(task); 5126 if (mAppTransition.isTransitionSet()) { 5127 task.setSendingToBottom(true); 5128 } 5129 moveStackWindowsLocked(stack.getDisplayContent()); 5130 } 5131 } finally { 5132 Binder.restoreCallingIdentity(origId); 5133 } 5134 } 5135 5136 /** 5137 * Create a new TaskStack and place it on a DisplayContent. 5138 * @param stackId The unique identifier of the new stack. 5139 * @param displayId The unique identifier of the DisplayContent. 5140 */ 5141 public void attachStack(int stackId, int displayId) { 5142 final long origId = Binder.clearCallingIdentity(); 5143 try { 5144 synchronized (mWindowMap) { 5145 final DisplayContent displayContent = mDisplayContents.get(displayId); 5146 if (displayContent != null) { 5147 TaskStack stack = mStackIdToStack.get(stackId); 5148 if (stack == null) { 5149 if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId); 5150 stack = new TaskStack(this, stackId); 5151 mStackIdToStack.put(stackId, stack); 5152 } 5153 stack.attachDisplayContent(displayContent); 5154 displayContent.attachStack(stack); 5155 moveStackWindowsLocked(displayContent); 5156 final WindowList windows = displayContent.getWindowList(); 5157 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 5158 windows.get(winNdx).reportResized(); 5159 } 5160 } 5161 } 5162 } finally { 5163 Binder.restoreCallingIdentity(origId); 5164 } 5165 } 5166 5167 void detachStackLocked(DisplayContent displayContent, TaskStack stack) { 5168 displayContent.detachStack(stack); 5169 stack.detachDisplay(); 5170 } 5171 5172 public void detachStack(int stackId) { 5173 synchronized (mWindowMap) { 5174 TaskStack stack = mStackIdToStack.get(stackId); 5175 if (stack != null) { 5176 final DisplayContent displayContent = stack.getDisplayContent(); 5177 if (displayContent != null) { 5178 if (stack.isAnimating()) { 5179 stack.mDeferDetach = true; 5180 return; 5181 } 5182 detachStackLocked(displayContent, stack); 5183 } 5184 } 5185 } 5186 } 5187 5188 public void removeStack(int stackId) { 5189 mStackIdToStack.remove(stackId); 5190 } 5191 5192 void removeTaskLocked(Task task) { 5193 final int taskId = task.taskId; 5194 final TaskStack stack = task.mStack; 5195 if (stack.isAnimating()) { 5196 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId); 5197 task.mDeferRemoval = true; 5198 return; 5199 } 5200 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId); 5201 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); 5202 task.mDeferRemoval = false; 5203 task.mStack.removeTask(task); 5204 mTaskIdToTask.delete(task.taskId); 5205 } 5206 5207 public void removeTask(int taskId) { 5208 synchronized (mWindowMap) { 5209 Task task = mTaskIdToTask.get(taskId); 5210 if (task == null) { 5211 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); 5212 return; 5213 } 5214 removeTaskLocked(task); 5215 } 5216 } 5217 5218 public void addTask(int taskId, int stackId, boolean toTop) { 5219 synchronized (mWindowMap) { 5220 if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId 5221 + " to " + (toTop ? "top" : "bottom")); 5222 Task task = mTaskIdToTask.get(taskId); 5223 if (task == null) { 5224 return; 5225 } 5226 TaskStack stack = mStackIdToStack.get(stackId); 5227 stack.addTask(task, toTop); 5228 final DisplayContent displayContent = stack.getDisplayContent(); 5229 displayContent.layoutNeeded = true; 5230 performLayoutAndPlaceSurfacesLocked(); 5231 } 5232 } 5233 5234 public void resizeStack(int stackId, Rect bounds) { 5235 synchronized (mWindowMap) { 5236 final TaskStack stack = mStackIdToStack.get(stackId); 5237 if (stack == null) { 5238 throw new IllegalArgumentException("resizeStack: stackId " + stackId 5239 + " not found."); 5240 } 5241 if (stack.setBounds(bounds)) { 5242 stack.resizeWindows(); 5243 stack.getDisplayContent().layoutNeeded = true; 5244 performLayoutAndPlaceSurfacesLocked(); 5245 } 5246 } 5247 } 5248 5249 public void getStackBounds(int stackId, Rect bounds) { 5250 final TaskStack stack = mStackIdToStack.get(stackId); 5251 if (stack != null) { 5252 stack.getBounds(bounds); 5253 return; 5254 } 5255 bounds.setEmpty(); 5256 } 5257 5258 // ------------------------------------------------------------- 5259 // Misc IWindowSession methods 5260 // ------------------------------------------------------------- 5261 5262 @Override 5263 public void startFreezingScreen(int exitAnim, int enterAnim) { 5264 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5265 "startFreezingScreen()")) { 5266 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5267 } 5268 5269 synchronized(mWindowMap) { 5270 if (!mClientFreezingScreen) { 5271 mClientFreezingScreen = true; 5272 final long origId = Binder.clearCallingIdentity(); 5273 try { 5274 startFreezingDisplayLocked(false, exitAnim, enterAnim); 5275 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 5276 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 5277 } finally { 5278 Binder.restoreCallingIdentity(origId); 5279 } 5280 } 5281 } 5282 } 5283 5284 @Override 5285 public void stopFreezingScreen() { 5286 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5287 "stopFreezingScreen()")) { 5288 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5289 } 5290 5291 synchronized(mWindowMap) { 5292 if (mClientFreezingScreen) { 5293 mClientFreezingScreen = false; 5294 mLastFinishedFreezeSource = "client"; 5295 final long origId = Binder.clearCallingIdentity(); 5296 try { 5297 stopFreezingDisplayLocked(); 5298 } finally { 5299 Binder.restoreCallingIdentity(origId); 5300 } 5301 } 5302 } 5303 } 5304 5305 @Override 5306 public void disableKeyguard(IBinder token, String tag) { 5307 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5308 != PackageManager.PERMISSION_GRANTED) { 5309 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5310 } 5311 5312 if (token == null) { 5313 throw new IllegalArgumentException("token == null"); 5314 } 5315 5316 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5317 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 5318 } 5319 5320 @Override 5321 public void reenableKeyguard(IBinder token) { 5322 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5323 != PackageManager.PERMISSION_GRANTED) { 5324 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5325 } 5326 5327 if (token == null) { 5328 throw new IllegalArgumentException("token == null"); 5329 } 5330 5331 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5332 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 5333 } 5334 5335 /** 5336 * @see android.app.KeyguardManager#exitKeyguardSecurely 5337 */ 5338 @Override 5339 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5340 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5341 != PackageManager.PERMISSION_GRANTED) { 5342 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5343 } 5344 5345 if (callback == null) { 5346 throw new IllegalArgumentException("callback == null"); 5347 } 5348 5349 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5350 @Override 5351 public void onKeyguardExitResult(boolean success) { 5352 try { 5353 callback.onKeyguardExitResult(success); 5354 } catch (RemoteException e) { 5355 // Client has died, we don't care. 5356 } 5357 } 5358 }); 5359 } 5360 5361 @Override 5362 public boolean inKeyguardRestrictedInputMode() { 5363 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5364 } 5365 5366 @Override 5367 public boolean isKeyguardLocked() { 5368 return mPolicy.isKeyguardLocked(); 5369 } 5370 5371 @Override 5372 public boolean isKeyguardSecure() { 5373 return mPolicy.isKeyguardSecure(); 5374 } 5375 5376 @Override 5377 public void dismissKeyguard() { 5378 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5379 != PackageManager.PERMISSION_GRANTED) { 5380 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5381 } 5382 synchronized(mWindowMap) { 5383 mPolicy.dismissKeyguardLw(); 5384 } 5385 } 5386 5387 @Override 5388 public void keyguardGoingAway(boolean disableWindowAnimations, 5389 boolean keyguardGoingToNotificationShade) { 5390 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5391 != PackageManager.PERMISSION_GRANTED) { 5392 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5393 } 5394 if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardGoingAway: disableWinAnim=" 5395 + disableWindowAnimations + " kgToNotifShade=" + keyguardGoingToNotificationShade); 5396 synchronized (mWindowMap) { 5397 mAnimator.mKeyguardGoingAway = true; 5398 mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade; 5399 mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations; 5400 requestTraversalLocked(); 5401 } 5402 } 5403 5404 public void keyguardWaitingForActivityDrawn() { 5405 if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardWaitingForActivityDrawn"); 5406 synchronized (mWindowMap) { 5407 mKeyguardWaitingForActivityDrawn = true; 5408 } 5409 } 5410 5411 public void notifyActivityDrawnForKeyguard() { 5412 if (DEBUG_KEYGUARD) Slog.d(TAG, "notifyActivityDrawnForKeyguard: waiting=" 5413 + mKeyguardWaitingForActivityDrawn + " Callers=" + Debug.getCallers(5)); 5414 synchronized (mWindowMap) { 5415 if (mKeyguardWaitingForActivityDrawn) { 5416 mPolicy.notifyActivityDrawnForKeyguardLw(); 5417 mKeyguardWaitingForActivityDrawn = false; 5418 } 5419 } 5420 } 5421 5422 void showGlobalActions() { 5423 mPolicy.showGlobalActions(); 5424 } 5425 5426 @Override 5427 public void closeSystemDialogs(String reason) { 5428 synchronized(mWindowMap) { 5429 final int numDisplays = mDisplayContents.size(); 5430 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5431 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5432 final int numWindows = windows.size(); 5433 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5434 final WindowState w = windows.get(winNdx); 5435 if (w.mHasSurface) { 5436 try { 5437 w.mClient.closeSystemDialogs(reason); 5438 } catch (RemoteException e) { 5439 } 5440 } 5441 } 5442 } 5443 } 5444 } 5445 5446 static float fixScale(float scale) { 5447 if (scale < 0) scale = 0; 5448 else if (scale > 20) scale = 20; 5449 return Math.abs(scale); 5450 } 5451 5452 @Override 5453 public void setAnimationScale(int which, float scale) { 5454 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5455 "setAnimationScale()")) { 5456 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5457 } 5458 5459 scale = fixScale(scale); 5460 switch (which) { 5461 case 0: mWindowAnimationScaleSetting = scale; break; 5462 case 1: mTransitionAnimationScaleSetting = scale; break; 5463 case 2: mAnimatorDurationScaleSetting = scale; break; 5464 } 5465 5466 // Persist setting 5467 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5468 } 5469 5470 @Override 5471 public void setAnimationScales(float[] scales) { 5472 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5473 "setAnimationScale()")) { 5474 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5475 } 5476 5477 if (scales != null) { 5478 if (scales.length >= 1) { 5479 mWindowAnimationScaleSetting = fixScale(scales[0]); 5480 } 5481 if (scales.length >= 2) { 5482 mTransitionAnimationScaleSetting = fixScale(scales[1]); 5483 } 5484 if (scales.length >= 3) { 5485 mAnimatorDurationScaleSetting = fixScale(scales[2]); 5486 dispatchNewAnimatorScaleLocked(null); 5487 } 5488 } 5489 5490 // Persist setting 5491 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5492 } 5493 5494 private void setAnimatorDurationScale(float scale) { 5495 mAnimatorDurationScaleSetting = scale; 5496 ValueAnimator.setDurationScale(scale); 5497 } 5498 5499 public float getWindowAnimationScaleLocked() { 5500 return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; 5501 } 5502 5503 public float getTransitionAnimationScaleLocked() { 5504 return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; 5505 } 5506 5507 @Override 5508 public float getAnimationScale(int which) { 5509 switch (which) { 5510 case 0: return mWindowAnimationScaleSetting; 5511 case 1: return mTransitionAnimationScaleSetting; 5512 case 2: return mAnimatorDurationScaleSetting; 5513 } 5514 return 0; 5515 } 5516 5517 @Override 5518 public float[] getAnimationScales() { 5519 return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting, 5520 mAnimatorDurationScaleSetting }; 5521 } 5522 5523 @Override 5524 public float getCurrentAnimatorScale() { 5525 synchronized(mWindowMap) { 5526 return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting; 5527 } 5528 } 5529 5530 void dispatchNewAnimatorScaleLocked(Session session) { 5531 mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget(); 5532 } 5533 5534 @Override 5535 public void registerPointerEventListener(PointerEventListener listener) { 5536 mPointerEventDispatcher.registerInputEventListener(listener); 5537 } 5538 5539 @Override 5540 public void unregisterPointerEventListener(PointerEventListener listener) { 5541 mPointerEventDispatcher.unregisterInputEventListener(listener); 5542 } 5543 5544 // Called by window manager policy. Not exposed externally. 5545 @Override 5546 public int getLidState() { 5547 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5548 InputManagerService.SW_LID); 5549 if (sw > 0) { 5550 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5551 return LID_CLOSED; 5552 } else if (sw == 0) { 5553 // Switch state: AKEY_STATE_UP. 5554 return LID_OPEN; 5555 } else { 5556 // Switch state: AKEY_STATE_UNKNOWN. 5557 return LID_ABSENT; 5558 } 5559 } 5560 5561 // Called by window manager policy. Not exposed externally. 5562 @Override 5563 public int getCameraLensCoverState() { 5564 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5565 InputManagerService.SW_CAMERA_LENS_COVER); 5566 if (sw > 0) { 5567 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5568 return CAMERA_LENS_COVERED; 5569 } else if (sw == 0) { 5570 // Switch state: AKEY_STATE_UP. 5571 return CAMERA_LENS_UNCOVERED; 5572 } else { 5573 // Switch state: AKEY_STATE_UNKNOWN. 5574 return CAMERA_LENS_COVER_ABSENT; 5575 } 5576 } 5577 5578 // Called by window manager policy. Not exposed externally. 5579 @Override 5580 public void switchKeyboardLayout(int deviceId, int direction) { 5581 mInputManager.switchKeyboardLayout(deviceId, direction); 5582 } 5583 5584 // Called by window manager policy. Not exposed externally. 5585 @Override 5586 public void shutdown(boolean confirm) { 5587 ShutdownThread.shutdown(mContext, confirm); 5588 } 5589 5590 // Called by window manager policy. Not exposed externally. 5591 @Override 5592 public void rebootSafeMode(boolean confirm) { 5593 ShutdownThread.rebootSafeMode(mContext, confirm); 5594 } 5595 5596 public void setCurrentProfileIds(final int[] currentProfileIds) { 5597 synchronized (mWindowMap) { 5598 mCurrentProfileIds = currentProfileIds; 5599 } 5600 } 5601 5602 public void setCurrentUser(final int newUserId, final int[] currentProfileIds) { 5603 synchronized (mWindowMap) { 5604 mCurrentUserId = newUserId; 5605 mCurrentProfileIds = currentProfileIds; 5606 mAppTransition.setCurrentUser(newUserId); 5607 mPolicy.setCurrentUserLw(newUserId); 5608 5609 // Hide windows that should not be seen by the new user. 5610 final int numDisplays = mDisplayContents.size(); 5611 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5612 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 5613 displayContent.switchUserStacks(newUserId); 5614 rebuildAppWindowListLocked(displayContent); 5615 } 5616 performLayoutAndPlaceSurfacesLocked(); 5617 } 5618 } 5619 5620 /* Called by WindowState */ 5621 boolean isCurrentProfileLocked(int userId) { 5622 if (userId == mCurrentUserId) return true; 5623 for (int i = 0; i < mCurrentProfileIds.length; i++) { 5624 if (mCurrentProfileIds[i] == userId) return true; 5625 } 5626 return false; 5627 } 5628 5629 public void enableScreenAfterBoot() { 5630 synchronized(mWindowMap) { 5631 if (DEBUG_BOOT) { 5632 RuntimeException here = new RuntimeException("here"); 5633 here.fillInStackTrace(); 5634 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5635 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5636 + " mShowingBootMessages=" + mShowingBootMessages 5637 + " mSystemBooted=" + mSystemBooted, here); 5638 } 5639 if (mSystemBooted) { 5640 return; 5641 } 5642 mSystemBooted = true; 5643 hideBootMessagesLocked(); 5644 // If the screen still doesn't come up after 30 seconds, give 5645 // up and turn it on. 5646 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000); 5647 } 5648 5649 mPolicy.systemBooted(); 5650 5651 performEnableScreen(); 5652 } 5653 5654 @Override 5655 public void enableScreenIfNeeded() { 5656 synchronized (mWindowMap) { 5657 enableScreenIfNeededLocked(); 5658 } 5659 } 5660 5661 void enableScreenIfNeededLocked() { 5662 if (DEBUG_BOOT) { 5663 RuntimeException here = new RuntimeException("here"); 5664 here.fillInStackTrace(); 5665 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5666 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5667 + " mShowingBootMessages=" + mShowingBootMessages 5668 + " mSystemBooted=" + mSystemBooted, here); 5669 } 5670 if (mDisplayEnabled) { 5671 return; 5672 } 5673 if (!mSystemBooted && !mShowingBootMessages) { 5674 return; 5675 } 5676 mH.sendEmptyMessage(H.ENABLE_SCREEN); 5677 } 5678 5679 public void performBootTimeout() { 5680 synchronized(mWindowMap) { 5681 if (mDisplayEnabled) { 5682 return; 5683 } 5684 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5685 mForceDisplayEnabled = true; 5686 } 5687 performEnableScreen(); 5688 } 5689 5690 private boolean checkWaitingForWindowsLocked() { 5691 5692 boolean haveBootMsg = false; 5693 boolean haveApp = false; 5694 // if the wallpaper service is disabled on the device, we're never going to have 5695 // wallpaper, don't bother waiting for it 5696 boolean haveWallpaper = false; 5697 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5698 com.android.internal.R.bool.config_enableWallpaperService) 5699 && !mOnlyCore; 5700 boolean haveKeyguard = true; 5701 // TODO(multidisplay): Expand to all displays? 5702 final WindowList windows = getDefaultWindowListLocked(); 5703 final int N = windows.size(); 5704 for (int i=0; i<N; i++) { 5705 WindowState w = windows.get(i); 5706 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5707 return true; 5708 } 5709 if (w.isDrawnLw()) { 5710 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5711 haveBootMsg = true; 5712 } else if (w.mAttrs.type == TYPE_APPLICATION) { 5713 haveApp = true; 5714 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5715 haveWallpaper = true; 5716 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 5717 haveKeyguard = mPolicy.isKeyguardDrawnLw(); 5718 } 5719 } 5720 } 5721 5722 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5723 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5724 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5725 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5726 + " haveKeyguard=" + haveKeyguard); 5727 } 5728 5729 // If we are turning on the screen to show the boot message, 5730 // don't do it until the boot message is actually displayed. 5731 if (!mSystemBooted && !haveBootMsg) { 5732 return true; 5733 } 5734 5735 // If we are turning on the screen after the boot is completed 5736 // normally, don't do so until we have the application and 5737 // wallpaper. 5738 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5739 (wallpaperEnabled && !haveWallpaper))) { 5740 return true; 5741 } 5742 5743 return false; 5744 } 5745 5746 public void performEnableScreen() { 5747 synchronized(mWindowMap) { 5748 if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5749 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5750 + " mShowingBootMessages=" + mShowingBootMessages 5751 + " mSystemBooted=" + mSystemBooted 5752 + " mOnlyCore=" + mOnlyCore, 5753 new RuntimeException("here").fillInStackTrace()); 5754 if (mDisplayEnabled) { 5755 return; 5756 } 5757 if (!mSystemBooted && !mShowingBootMessages) { 5758 return; 5759 } 5760 5761 // Don't enable the screen until all existing windows have been drawn. 5762 if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) { 5763 return; 5764 } 5765 5766 if (!mBootAnimationStopped) { 5767 // Do this one time. 5768 try { 5769 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5770 if (surfaceFlinger != null) { 5771 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5772 Parcel data = Parcel.obtain(); 5773 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5774 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5775 data, null, 0); 5776 data.recycle(); 5777 } 5778 } catch (RemoteException ex) { 5779 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5780 } 5781 mBootAnimationStopped = true; 5782 } 5783 5784 if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) { 5785 if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: Waiting for anim complete"); 5786 return; 5787 } 5788 5789 mDisplayEnabled = true; 5790 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5791 5792 // Enable input dispatch. 5793 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5794 } 5795 5796 try { 5797 mActivityManager.bootAnimationComplete(); 5798 } catch (RemoteException e) { 5799 } 5800 5801 mPolicy.enableScreenAfterBoot(); 5802 5803 // Make sure the last requested orientation has been applied. 5804 updateRotationUnchecked(false, false); 5805 } 5806 5807 private boolean checkBootAnimationCompleteLocked() { 5808 if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) { 5809 mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED); 5810 mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED, 5811 BOOT_ANIMATION_POLL_INTERVAL); 5812 if (DEBUG_BOOT) Slog.i(TAG, "checkBootAnimationComplete: Waiting for anim complete"); 5813 return false; 5814 } 5815 if (DEBUG_BOOT) Slog.i(TAG, "checkBootAnimationComplete: Animation complete!"); 5816 return true; 5817 } 5818 5819 public void showBootMessage(final CharSequence msg, final boolean always) { 5820 boolean first = false; 5821 synchronized(mWindowMap) { 5822 if (DEBUG_BOOT) { 5823 RuntimeException here = new RuntimeException("here"); 5824 here.fillInStackTrace(); 5825 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5826 + " mAllowBootMessages=" + mAllowBootMessages 5827 + " mShowingBootMessages=" + mShowingBootMessages 5828 + " mSystemBooted=" + mSystemBooted, here); 5829 } 5830 if (!mAllowBootMessages) { 5831 return; 5832 } 5833 if (!mShowingBootMessages) { 5834 if (!always) { 5835 return; 5836 } 5837 first = true; 5838 } 5839 if (mSystemBooted) { 5840 return; 5841 } 5842 mShowingBootMessages = true; 5843 mPolicy.showBootMessage(msg, always); 5844 } 5845 if (first) { 5846 performEnableScreen(); 5847 } 5848 } 5849 5850 public void hideBootMessagesLocked() { 5851 if (DEBUG_BOOT) { 5852 RuntimeException here = new RuntimeException("here"); 5853 here.fillInStackTrace(); 5854 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5855 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5856 + " mShowingBootMessages=" + mShowingBootMessages 5857 + " mSystemBooted=" + mSystemBooted, here); 5858 } 5859 if (mShowingBootMessages) { 5860 mShowingBootMessages = false; 5861 mPolicy.hideBootMessages(); 5862 } 5863 } 5864 5865 @Override 5866 public void setInTouchMode(boolean mode) { 5867 synchronized(mWindowMap) { 5868 mInTouchMode = mode; 5869 } 5870 } 5871 5872 public void updateCircularDisplayMaskIfNeeded() { 5873 // we're fullscreen and not hosted in an ActivityView 5874 if (mContext.getResources().getBoolean( 5875 com.android.internal.R.bool.config_windowIsRound) 5876 && mContext.getResources().getBoolean( 5877 com.android.internal.R.bool.config_windowShowCircularMask)) { 5878 // Device configuration calls for a circular display mask, but we only enable the mask 5879 // if the accessibility color inversion feature is disabled, as the inverted mask 5880 // causes artifacts. 5881 int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(), 5882 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, mCurrentUserId); 5883 int showMask = (inversionState == 1) ? 0 : 1; 5884 Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK); 5885 m.arg1 = showMask; 5886 mH.sendMessage(m); 5887 } 5888 } 5889 5890 public void showEmulatorDisplayOverlayIfNeeded() { 5891 if (mContext.getResources().getBoolean( 5892 com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay) 5893 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false) 5894 && Build.HARDWARE.contains("goldfish")) { 5895 mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY)); 5896 } 5897 } 5898 5899 public void showCircularMask(boolean visible) { 5900 synchronized(mWindowMap) { 5901 5902 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5903 ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")"); 5904 SurfaceControl.openTransaction(); 5905 try { 5906 if (visible) { 5907 // TODO(multi-display): support multiple displays 5908 if (mCircularDisplayMask == null) { 5909 int screenOffset = mContext.getResources().getDimensionPixelSize( 5910 com.android.internal.R.dimen.circular_display_mask_offset); 5911 5912 mCircularDisplayMask = new CircularDisplayMask( 5913 getDefaultDisplayContentLocked().getDisplay(), 5914 mFxSession, 5915 mPolicy.windowTypeToLayerLw( 5916 WindowManager.LayoutParams.TYPE_POINTER) 5917 * TYPE_LAYER_MULTIPLIER + 10, screenOffset); 5918 } 5919 mCircularDisplayMask.setVisibility(true); 5920 } else if (mCircularDisplayMask != null) { 5921 mCircularDisplayMask.setVisibility(false); 5922 mCircularDisplayMask = null; 5923 } 5924 } finally { 5925 SurfaceControl.closeTransaction(); 5926 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5927 "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")"); 5928 } 5929 } 5930 } 5931 5932 public void showEmulatorDisplayOverlay() { 5933 synchronized(mWindowMap) { 5934 5935 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5936 ">>> OPEN TRANSACTION showEmulatorDisplayOverlay"); 5937 SurfaceControl.openTransaction(); 5938 try { 5939 if (mEmulatorDisplayOverlay == null) { 5940 mEmulatorDisplayOverlay = new EmulatorDisplayOverlay( 5941 mContext, 5942 getDefaultDisplayContentLocked().getDisplay(), 5943 mFxSession, 5944 mPolicy.windowTypeToLayerLw( 5945 WindowManager.LayoutParams.TYPE_POINTER) 5946 * TYPE_LAYER_MULTIPLIER + 10); 5947 } 5948 mEmulatorDisplayOverlay.setVisibility(true); 5949 } finally { 5950 SurfaceControl.closeTransaction(); 5951 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5952 "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay"); 5953 } 5954 } 5955 } 5956 5957 // TODO: more accounting of which pid(s) turned it on, keep count, 5958 // only allow disables from pids which have count on, etc. 5959 @Override 5960 public void showStrictModeViolation(boolean on) { 5961 int pid = Binder.getCallingPid(); 5962 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5963 } 5964 5965 private void showStrictModeViolation(int arg, int pid) { 5966 final boolean on = arg != 0; 5967 synchronized(mWindowMap) { 5968 // Ignoring requests to enable the red border from clients 5969 // which aren't on screen. (e.g. Broadcast Receivers in 5970 // the background..) 5971 if (on) { 5972 boolean isVisible = false; 5973 final int numDisplays = mDisplayContents.size(); 5974 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5975 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5976 final int numWindows = windows.size(); 5977 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5978 final WindowState ws = windows.get(winNdx); 5979 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5980 isVisible = true; 5981 break; 5982 } 5983 } 5984 } 5985 if (!isVisible) { 5986 return; 5987 } 5988 } 5989 5990 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5991 ">>> OPEN TRANSACTION showStrictModeViolation"); 5992 SurfaceControl.openTransaction(); 5993 try { 5994 // TODO(multi-display): support multiple displays 5995 if (mStrictModeFlash == null) { 5996 mStrictModeFlash = new StrictModeFlash( 5997 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5998 } 5999 mStrictModeFlash.setVisibility(on); 6000 } finally { 6001 SurfaceControl.closeTransaction(); 6002 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 6003 "<<< CLOSE TRANSACTION showStrictModeViolation"); 6004 } 6005 } 6006 } 6007 6008 @Override 6009 public void setStrictModeVisualIndicatorPreference(String value) { 6010 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 6011 } 6012 6013 private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) { 6014 if (rot == Surface.ROTATION_90) { 6015 final int tmp = crop.top; 6016 crop.top = dw - crop.right; 6017 crop.right = crop.bottom; 6018 crop.bottom = dw - crop.left; 6019 crop.left = tmp; 6020 } else if (rot == Surface.ROTATION_180) { 6021 int tmp = crop.top; 6022 crop.top = dh - crop.bottom; 6023 crop.bottom = dh - tmp; 6024 tmp = crop.right; 6025 crop.right = dw - crop.left; 6026 crop.left = dw - tmp; 6027 } else if (rot == Surface.ROTATION_270) { 6028 final int tmp = crop.top; 6029 crop.top = crop.left; 6030 crop.left = dh - crop.bottom; 6031 crop.bottom = crop.right; 6032 crop.right = dh - tmp; 6033 } 6034 } 6035 6036 /** 6037 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 6038 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 6039 * of the target image. 6040 * 6041 * @param displayId the Display to take a screenshot of. 6042 * @param width the width of the target bitmap 6043 * @param height the height of the target bitmap 6044 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 6045 * will be the same config as the surface 6046 */ 6047 @Override 6048 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 6049 int height, boolean force565) { 6050 if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER, 6051 "screenshotApplications()")) { 6052 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 6053 } 6054 6055 final DisplayContent displayContent = getDisplayContentLocked(displayId); 6056 if (displayContent == null) { 6057 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 6058 + ": returning null. No Display for displayId=" + displayId); 6059 return null; 6060 } 6061 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6062 int dw = displayInfo.logicalWidth; 6063 int dh = displayInfo.logicalHeight; 6064 if (dw == 0 || dh == 0) { 6065 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 6066 + ": returning null. logical widthxheight=" + dw + "x" + dh); 6067 return null; 6068 } 6069 6070 Bitmap bm = null; 6071 6072 int maxLayer = 0; 6073 final Rect frame = new Rect(); 6074 final Rect stackBounds = new Rect(); 6075 6076 float scale = 0; 6077 int rot = Surface.ROTATION_0; 6078 6079 boolean screenshotReady; 6080 int minLayer; 6081 if (appToken == null) { 6082 screenshotReady = true; 6083 minLayer = 0; 6084 } else { 6085 screenshotReady = false; 6086 minLayer = Integer.MAX_VALUE; 6087 } 6088 6089 int retryCount = 0; 6090 WindowState appWin = null; 6091 6092 final boolean appIsImTarget = mInputMethodTarget != null 6093 && mInputMethodTarget.mAppToken != null 6094 && mInputMethodTarget.mAppToken.appToken != null 6095 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 6096 6097 final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1) 6098 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 6099 6100 while (true) { 6101 if (retryCount++ > 0) { 6102 // Reset max/min layers on retries so we don't accidentally take a screenshot of a 6103 // layer based on the previous try. 6104 maxLayer = 0; 6105 minLayer = Integer.MAX_VALUE; 6106 try { 6107 Thread.sleep(100); 6108 } catch (InterruptedException e) { 6109 } 6110 } 6111 synchronized(mWindowMap) { 6112 // Figure out the part of the screen that is actually the app. 6113 appWin = null; 6114 final WindowList windows = displayContent.getWindowList(); 6115 for (int i = windows.size() - 1; i >= 0; i--) { 6116 WindowState ws = windows.get(i); 6117 if (!ws.mHasSurface) { 6118 continue; 6119 } 6120 if (ws.mLayer >= aboveAppLayer) { 6121 continue; 6122 } 6123 if (ws.mIsImWindow) { 6124 if (!appIsImTarget) { 6125 continue; 6126 } 6127 } else if (ws.mIsWallpaper) { 6128 if (appWin == null) { 6129 // We have not ran across the target window yet, so it is probably 6130 // behind the wallpaper. This can happen when the keyguard is up and 6131 // all windows are moved behind the wallpaper. We don't want to 6132 // include the wallpaper layer in the screenshot as it will coverup 6133 // the layer of the target window. 6134 continue; 6135 } 6136 // Fall through. The target window is in front of the wallpaper. For this 6137 // case we want to include the wallpaper layer in the screenshot because 6138 // the target window might have some transparent areas. 6139 } else if (appToken != null) { 6140 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 6141 // This app window is of no interest if it is not associated with the 6142 // screenshot app. 6143 continue; 6144 } 6145 appWin = ws; 6146 } 6147 6148 // Include this window. 6149 6150 final WindowStateAnimator winAnim = ws.mWinAnimator; 6151 if (maxLayer < winAnim.mSurfaceLayer) { 6152 maxLayer = winAnim.mSurfaceLayer; 6153 } 6154 if (minLayer > winAnim.mSurfaceLayer) { 6155 minLayer = winAnim.mSurfaceLayer; 6156 } 6157 6158 // Don't include wallpaper in bounds calculation 6159 if (!ws.mIsWallpaper) { 6160 final Rect wf = ws.mFrame; 6161 final Rect cr = ws.mContentInsets; 6162 int left = wf.left + cr.left; 6163 int top = wf.top + cr.top; 6164 int right = wf.right - cr.right; 6165 int bottom = wf.bottom - cr.bottom; 6166 frame.union(left, top, right, bottom); 6167 ws.getStackBounds(stackBounds); 6168 frame.intersect(stackBounds); 6169 } 6170 6171 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 6172 ws.isDisplayedLw()) { 6173 screenshotReady = true; 6174 } 6175 } 6176 6177 if (appToken != null && appWin == null) { 6178 // Can't find a window to snapshot. 6179 if (DEBUG_SCREENSHOT) Slog.i(TAG, 6180 "Screenshot: Couldn't find a surface matching " + appToken); 6181 return null; 6182 } 6183 6184 if (!screenshotReady) { 6185 if (retryCount > MAX_SCREENSHOT_RETRIES) { 6186 Slog.i(TAG, "Screenshot max retries " + retryCount + " of " + appToken + 6187 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + 6188 appWin.mWinAnimator.mDrawState))); 6189 return null; 6190 } 6191 6192 // Delay and hope that window gets drawn. 6193 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 6194 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 6195 continue; 6196 } 6197 6198 // Screenshot is ready to be taken. Everything from here below will continue 6199 // through the bottom of the loop and return a value. We only stay in the loop 6200 // because we don't want to release the mWindowMap lock until the screenshot is 6201 // taken. 6202 6203 if (maxLayer == 0) { 6204 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 6205 + ": returning null maxLayer=" + maxLayer); 6206 return null; 6207 } 6208 6209 // Constrain frame to the screen size. 6210 frame.intersect(0, 0, dw, dh); 6211 6212 // Tell surface flinger what part of the image to crop. Take the top 6213 // right part of the application, and crop the larger dimension to fit. 6214 Rect crop = new Rect(frame); 6215 if (width / (float) frame.width() < height / (float) frame.height()) { 6216 int cropWidth = (int)((float)width / (float)height * frame.height()); 6217 crop.right = crop.left + cropWidth; 6218 } else { 6219 int cropHeight = (int)((float)height / (float)width * frame.width()); 6220 crop.bottom = crop.top + cropHeight; 6221 } 6222 6223 // The screenshot API does not apply the current screen rotation. 6224 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 6225 6226 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 6227 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 6228 } 6229 6230 // Surfaceflinger is not aware of orientation, so convert our logical 6231 // crop to surfaceflinger's portrait orientation. 6232 convertCropForSurfaceFlinger(crop, rot, dw, dh); 6233 6234 if (DEBUG_SCREENSHOT) { 6235 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 6236 + maxLayer + " appToken=" + appToken); 6237 for (int i = 0; i < windows.size(); i++) { 6238 WindowState win = windows.get(i); 6239 Slog.i(TAG, win + ": " + win.mLayer 6240 + " animLayer=" + win.mWinAnimator.mAnimLayer 6241 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 6242 } 6243 } 6244 6245 ScreenRotationAnimation screenRotationAnimation = 6246 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6247 final boolean inRotation = screenRotationAnimation != null && 6248 screenRotationAnimation.isAnimating(); 6249 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG, 6250 "Taking screenshot while rotating"); 6251 6252 bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer, 6253 inRotation, rot); 6254 if (bm == null) { 6255 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 6256 + ") to layer " + maxLayer); 6257 return null; 6258 } 6259 } 6260 6261 break; 6262 } 6263 6264 if (DEBUG_SCREENSHOT) { 6265 // TEST IF IT's ALL BLACK 6266 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 6267 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 6268 boolean allBlack = true; 6269 final int firstColor = buffer[0]; 6270 for (int i = 0; i < buffer.length; i++) { 6271 if (buffer[i] != firstColor) { 6272 allBlack = false; 6273 break; 6274 } 6275 } 6276 if (allBlack) { 6277 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 6278 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 6279 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 6280 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 6281 } 6282 } 6283 6284 // Copy the screenshot bitmap to another buffer so that the gralloc backed 6285 // bitmap will not have a long lifetime. Gralloc memory can be pinned or 6286 // duplicated and might have a higher cost than a skia backed buffer. 6287 Bitmap ret = bm.copy(bm.getConfig(),true); 6288 bm.recycle(); 6289 return ret; 6290 } 6291 6292 /** 6293 * Freeze rotation changes. (Enable "rotation lock".) 6294 * Persists across reboots. 6295 * @param rotation The desired rotation to freeze to, or -1 to use the 6296 * current rotation. 6297 */ 6298 @Override 6299 public void freezeRotation(int rotation) { 6300 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 6301 "freezeRotation()")) { 6302 throw new SecurityException("Requires SET_ORIENTATION permission"); 6303 } 6304 if (rotation < -1 || rotation > Surface.ROTATION_270) { 6305 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 6306 + "rotation constant."); 6307 } 6308 6309 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 6310 6311 long origId = Binder.clearCallingIdentity(); 6312 try { 6313 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 6314 rotation == -1 ? mRotation : rotation); 6315 } finally { 6316 Binder.restoreCallingIdentity(origId); 6317 } 6318 6319 updateRotationUnchecked(false, false); 6320 } 6321 6322 /** 6323 * Thaw rotation changes. (Disable "rotation lock".) 6324 * Persists across reboots. 6325 */ 6326 @Override 6327 public void thawRotation() { 6328 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 6329 "thawRotation()")) { 6330 throw new SecurityException("Requires SET_ORIENTATION permission"); 6331 } 6332 6333 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 6334 6335 long origId = Binder.clearCallingIdentity(); 6336 try { 6337 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 6338 777); // rot not used 6339 } finally { 6340 Binder.restoreCallingIdentity(origId); 6341 } 6342 6343 updateRotationUnchecked(false, false); 6344 } 6345 6346 /** 6347 * Recalculate the current rotation. 6348 * 6349 * Called by the window manager policy whenever the state of the system changes 6350 * such that the current rotation might need to be updated, such as when the 6351 * device is docked or rotated into a new posture. 6352 */ 6353 @Override 6354 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 6355 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 6356 } 6357 6358 /** 6359 * Temporarily pauses rotation changes until resumed. 6360 * 6361 * This can be used to prevent rotation changes from occurring while the user is 6362 * performing certain operations, such as drag and drop. 6363 * 6364 * This call nests and must be matched by an equal number of calls to 6365 * {@link #resumeRotationLocked}. 6366 */ 6367 void pauseRotationLocked() { 6368 mDeferredRotationPauseCount += 1; 6369 } 6370 6371 /** 6372 * Resumes normal rotation changes after being paused. 6373 */ 6374 void resumeRotationLocked() { 6375 if (mDeferredRotationPauseCount > 0) { 6376 mDeferredRotationPauseCount -= 1; 6377 if (mDeferredRotationPauseCount == 0) { 6378 boolean changed = updateRotationUncheckedLocked(false); 6379 if (changed) { 6380 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6381 } 6382 } 6383 } 6384 } 6385 6386 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 6387 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 6388 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 6389 6390 long origId = Binder.clearCallingIdentity(); 6391 boolean changed; 6392 synchronized(mWindowMap) { 6393 changed = updateRotationUncheckedLocked(false); 6394 if (!changed || forceRelayout) { 6395 getDefaultDisplayContentLocked().layoutNeeded = true; 6396 performLayoutAndPlaceSurfacesLocked(); 6397 } 6398 } 6399 6400 if (changed || alwaysSendConfiguration) { 6401 sendNewConfiguration(); 6402 } 6403 6404 Binder.restoreCallingIdentity(origId); 6405 } 6406 6407 // TODO(multidisplay): Rotate any display? 6408 /** 6409 * Updates the current rotation. 6410 * 6411 * Returns true if the rotation has been changed. In this case YOU 6412 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 6413 */ 6414 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 6415 if (mDeferredRotationPauseCount > 0) { 6416 // Rotation updates have been paused temporarily. Defer the update until 6417 // updates have been resumed. 6418 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 6419 return false; 6420 } 6421 6422 ScreenRotationAnimation screenRotationAnimation = 6423 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6424 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 6425 // Rotation updates cannot be performed while the previous rotation change 6426 // animation is still in progress. Skip this update. We will try updating 6427 // again after the animation is finished and the display is unfrozen. 6428 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 6429 return false; 6430 } 6431 6432 if (!mDisplayEnabled) { 6433 // No point choosing a rotation if the display is not enabled. 6434 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 6435 return false; 6436 } 6437 6438 // TODO: Implement forced rotation changes. 6439 // Set mAltOrientation to indicate that the application is receiving 6440 // an orientation that has different metrics than it expected. 6441 // eg. Portrait instead of Landscape. 6442 6443 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 6444 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 6445 mForcedAppOrientation, rotation); 6446 6447 if (DEBUG_ORIENTATION) { 6448 Slog.v(TAG, "Application requested orientation " 6449 + mForcedAppOrientation + ", got rotation " + rotation 6450 + " which has " + (altOrientation ? "incompatible" : "compatible") 6451 + " metrics"); 6452 } 6453 6454 if (mRotation == rotation && mAltOrientation == altOrientation) { 6455 // No change. 6456 return false; 6457 } 6458 6459 if (DEBUG_ORIENTATION) { 6460 Slog.v(TAG, 6461 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 6462 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 6463 + ", forceApp=" + mForcedAppOrientation); 6464 } 6465 6466 mRotation = rotation; 6467 mAltOrientation = altOrientation; 6468 mPolicy.setRotationLw(mRotation); 6469 6470 mWindowsFreezingScreen = true; 6471 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 6472 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 6473 mWaitingForConfig = true; 6474 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6475 displayContent.layoutNeeded = true; 6476 final int[] anim = new int[2]; 6477 if (displayContent.isDimming()) { 6478 anim[0] = anim[1] = 0; 6479 } else { 6480 mPolicy.selectRotationAnimationLw(anim); 6481 } 6482 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6483 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6484 screenRotationAnimation = 6485 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6486 6487 // We need to update our screen size information to match the new 6488 // rotation. Note that this is redundant with the later call to 6489 // sendNewConfiguration() that must be called after this function 6490 // returns... however we need to do the screen size part of that 6491 // before then so we have the correct size to use when initializing 6492 // the rotation animation for the new rotation. 6493 computeScreenConfigurationLocked(null); 6494 6495 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6496 if (!inTransaction) { 6497 if (SHOW_TRANSACTIONS) { 6498 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 6499 } 6500 SurfaceControl.openTransaction(); 6501 } 6502 try { 6503 // NOTE: We disable the rotation in the emulator because 6504 // it doesn't support hardware OpenGL emulation yet. 6505 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6506 && screenRotationAnimation.hasScreenshot()) { 6507 if (screenRotationAnimation.setRotationInTransaction( 6508 rotation, mFxSession, 6509 MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), 6510 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6511 scheduleAnimationLocked(); 6512 } 6513 } 6514 6515 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6516 } finally { 6517 if (!inTransaction) { 6518 SurfaceControl.closeTransaction(); 6519 if (SHOW_LIGHT_TRANSACTIONS) { 6520 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6521 } 6522 } 6523 } 6524 6525 final WindowList windows = displayContent.getWindowList(); 6526 for (int i = windows.size() - 1; i >= 0; i--) { 6527 WindowState w = windows.get(i); 6528 if (w.mHasSurface) { 6529 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 6530 w.mOrientationChanging = true; 6531 mInnerFields.mOrientationChangeComplete = false; 6532 } 6533 w.mLastFreezeDuration = 0; 6534 } 6535 6536 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6537 try { 6538 mRotationWatchers.get(i).watcher.onRotationChanged(rotation); 6539 } catch (RemoteException e) { 6540 } 6541 } 6542 6543 //TODO (multidisplay): Magnification is supported only for the default display. 6544 // Announce rotation only if we will not animate as we already have the 6545 // windows in final state. Otherwise, we make this call at the rotation end. 6546 if (screenRotationAnimation == null && mAccessibilityController != null 6547 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6548 mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), 6549 rotation); 6550 } 6551 6552 return true; 6553 } 6554 6555 @Override 6556 public int getRotation() { 6557 return mRotation; 6558 } 6559 6560 @Override 6561 public boolean isRotationFrozen() { 6562 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6563 } 6564 6565 @Override 6566 public int watchRotation(IRotationWatcher watcher) { 6567 final IBinder watcherBinder = watcher.asBinder(); 6568 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6569 @Override 6570 public void binderDied() { 6571 synchronized (mWindowMap) { 6572 for (int i=0; i<mRotationWatchers.size(); i++) { 6573 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) { 6574 RotationWatcher removed = mRotationWatchers.remove(i); 6575 IBinder binder = removed.watcher.asBinder(); 6576 if (binder != null) { 6577 binder.unlinkToDeath(this, 0); 6578 } 6579 i--; 6580 } 6581 } 6582 } 6583 } 6584 }; 6585 6586 synchronized (mWindowMap) { 6587 try { 6588 watcher.asBinder().linkToDeath(dr, 0); 6589 mRotationWatchers.add(new RotationWatcher(watcher, dr)); 6590 } catch (RemoteException e) { 6591 // Client died, no cleanup needed. 6592 } 6593 6594 return mRotation; 6595 } 6596 } 6597 6598 @Override 6599 public void removeRotationWatcher(IRotationWatcher watcher) { 6600 final IBinder watcherBinder = watcher.asBinder(); 6601 synchronized (mWindowMap) { 6602 for (int i=0; i<mRotationWatchers.size(); i++) { 6603 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 6604 if (watcherBinder == rotationWatcher.watcher.asBinder()) { 6605 RotationWatcher removed = mRotationWatchers.remove(i); 6606 IBinder binder = removed.watcher.asBinder(); 6607 if (binder != null) { 6608 binder.unlinkToDeath(removed.deathRecipient, 0); 6609 } 6610 i--; 6611 } 6612 } 6613 } 6614 } 6615 6616 /** 6617 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6618 * theme attribute) on devices that feature a physical options menu key attempt to position 6619 * their menu panel window along the edge of the screen nearest the physical menu key. 6620 * This lowers the travel distance between invoking the menu panel and selecting 6621 * a menu option. 6622 * 6623 * This method helps control where that menu is placed. Its current implementation makes 6624 * assumptions about the menu key and its relationship to the screen based on whether 6625 * the device's natural orientation is portrait (width < height) or landscape. 6626 * 6627 * The menu key is assumed to be located along the bottom edge of natural-portrait 6628 * devices and along the right edge of natural-landscape devices. If these assumptions 6629 * do not hold for the target device, this method should be changed to reflect that. 6630 * 6631 * @return A {@link Gravity} value for placing the options menu window 6632 */ 6633 @Override 6634 public int getPreferredOptionsPanelGravity() { 6635 synchronized (mWindowMap) { 6636 final int rotation = getRotation(); 6637 6638 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6639 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6640 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6641 // On devices with a natural orientation of portrait 6642 switch (rotation) { 6643 default: 6644 case Surface.ROTATION_0: 6645 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6646 case Surface.ROTATION_90: 6647 return Gravity.RIGHT | Gravity.BOTTOM; 6648 case Surface.ROTATION_180: 6649 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6650 case Surface.ROTATION_270: 6651 return Gravity.START | Gravity.BOTTOM; 6652 } 6653 } 6654 6655 // On devices with a natural orientation of landscape 6656 switch (rotation) { 6657 default: 6658 case Surface.ROTATION_0: 6659 return Gravity.RIGHT | Gravity.BOTTOM; 6660 case Surface.ROTATION_90: 6661 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6662 case Surface.ROTATION_180: 6663 return Gravity.START | Gravity.BOTTOM; 6664 case Surface.ROTATION_270: 6665 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6666 } 6667 } 6668 } 6669 6670 /** 6671 * Starts the view server on the specified port. 6672 * 6673 * @param port The port to listener to. 6674 * 6675 * @return True if the server was successfully started, false otherwise. 6676 * 6677 * @see com.android.server.wm.ViewServer 6678 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6679 */ 6680 @Override 6681 public boolean startViewServer(int port) { 6682 if (isSystemSecure()) { 6683 return false; 6684 } 6685 6686 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6687 return false; 6688 } 6689 6690 if (port < 1024) { 6691 return false; 6692 } 6693 6694 if (mViewServer != null) { 6695 if (!mViewServer.isRunning()) { 6696 try { 6697 return mViewServer.start(); 6698 } catch (IOException e) { 6699 Slog.w(TAG, "View server did not start"); 6700 } 6701 } 6702 return false; 6703 } 6704 6705 try { 6706 mViewServer = new ViewServer(this, port); 6707 return mViewServer.start(); 6708 } catch (IOException e) { 6709 Slog.w(TAG, "View server did not start"); 6710 } 6711 return false; 6712 } 6713 6714 private boolean isSystemSecure() { 6715 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6716 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6717 } 6718 6719 /** 6720 * Stops the view server if it exists. 6721 * 6722 * @return True if the server stopped, false if it wasn't started or 6723 * couldn't be stopped. 6724 * 6725 * @see com.android.server.wm.ViewServer 6726 */ 6727 @Override 6728 public boolean stopViewServer() { 6729 if (isSystemSecure()) { 6730 return false; 6731 } 6732 6733 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6734 return false; 6735 } 6736 6737 if (mViewServer != null) { 6738 return mViewServer.stop(); 6739 } 6740 return false; 6741 } 6742 6743 /** 6744 * Indicates whether the view server is running. 6745 * 6746 * @return True if the server is running, false otherwise. 6747 * 6748 * @see com.android.server.wm.ViewServer 6749 */ 6750 @Override 6751 public boolean isViewServerRunning() { 6752 if (isSystemSecure()) { 6753 return false; 6754 } 6755 6756 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6757 return false; 6758 } 6759 6760 return mViewServer != null && mViewServer.isRunning(); 6761 } 6762 6763 /** 6764 * Lists all availble windows in the system. The listing is written in the 6765 * specified Socket's output stream with the following syntax: 6766 * windowHashCodeInHexadecimal windowName 6767 * Each line of the ouput represents a different window. 6768 * 6769 * @param client The remote client to send the listing to. 6770 * @return False if an error occured, true otherwise. 6771 */ 6772 boolean viewServerListWindows(Socket client) { 6773 if (isSystemSecure()) { 6774 return false; 6775 } 6776 6777 boolean result = true; 6778 6779 WindowList windows = new WindowList(); 6780 synchronized (mWindowMap) { 6781 //noinspection unchecked 6782 final int numDisplays = mDisplayContents.size(); 6783 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6784 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6785 windows.addAll(displayContent.getWindowList()); 6786 } 6787 } 6788 6789 BufferedWriter out = null; 6790 6791 // Any uncaught exception will crash the system process 6792 try { 6793 OutputStream clientStream = client.getOutputStream(); 6794 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6795 6796 final int count = windows.size(); 6797 for (int i = 0; i < count; i++) { 6798 final WindowState w = windows.get(i); 6799 out.write(Integer.toHexString(System.identityHashCode(w))); 6800 out.write(' '); 6801 out.append(w.mAttrs.getTitle()); 6802 out.write('\n'); 6803 } 6804 6805 out.write("DONE.\n"); 6806 out.flush(); 6807 } catch (Exception e) { 6808 result = false; 6809 } finally { 6810 if (out != null) { 6811 try { 6812 out.close(); 6813 } catch (IOException e) { 6814 result = false; 6815 } 6816 } 6817 } 6818 6819 return result; 6820 } 6821 6822 // TODO(multidisplay): Extend to multiple displays. 6823 /** 6824 * Returns the focused window in the following format: 6825 * windowHashCodeInHexadecimal windowName 6826 * 6827 * @param client The remote client to send the listing to. 6828 * @return False if an error occurred, true otherwise. 6829 */ 6830 boolean viewServerGetFocusedWindow(Socket client) { 6831 if (isSystemSecure()) { 6832 return false; 6833 } 6834 6835 boolean result = true; 6836 6837 WindowState focusedWindow = getFocusedWindow(); 6838 6839 BufferedWriter out = null; 6840 6841 // Any uncaught exception will crash the system process 6842 try { 6843 OutputStream clientStream = client.getOutputStream(); 6844 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6845 6846 if(focusedWindow != null) { 6847 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6848 out.write(' '); 6849 out.append(focusedWindow.mAttrs.getTitle()); 6850 } 6851 out.write('\n'); 6852 out.flush(); 6853 } catch (Exception e) { 6854 result = false; 6855 } finally { 6856 if (out != null) { 6857 try { 6858 out.close(); 6859 } catch (IOException e) { 6860 result = false; 6861 } 6862 } 6863 } 6864 6865 return result; 6866 } 6867 6868 /** 6869 * Sends a command to a target window. The result of the command, if any, will be 6870 * written in the output stream of the specified socket. 6871 * 6872 * The parameters must follow this syntax: 6873 * windowHashcode extra 6874 * 6875 * Where XX is the length in characeters of the windowTitle. 6876 * 6877 * The first parameter is the target window. The window with the specified hashcode 6878 * will be the target. If no target can be found, nothing happens. The extra parameters 6879 * will be delivered to the target window and as parameters to the command itself. 6880 * 6881 * @param client The remote client to sent the result, if any, to. 6882 * @param command The command to execute. 6883 * @param parameters The command parameters. 6884 * 6885 * @return True if the command was successfully delivered, false otherwise. This does 6886 * not indicate whether the command itself was successful. 6887 */ 6888 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6889 if (isSystemSecure()) { 6890 return false; 6891 } 6892 6893 boolean success = true; 6894 Parcel data = null; 6895 Parcel reply = null; 6896 6897 BufferedWriter out = null; 6898 6899 // Any uncaught exception will crash the system process 6900 try { 6901 // Find the hashcode of the window 6902 int index = parameters.indexOf(' '); 6903 if (index == -1) { 6904 index = parameters.length(); 6905 } 6906 final String code = parameters.substring(0, index); 6907 int hashCode = (int) Long.parseLong(code, 16); 6908 6909 // Extract the command's parameter after the window description 6910 if (index < parameters.length()) { 6911 parameters = parameters.substring(index + 1); 6912 } else { 6913 parameters = ""; 6914 } 6915 6916 final WindowState window = findWindow(hashCode); 6917 if (window == null) { 6918 return false; 6919 } 6920 6921 data = Parcel.obtain(); 6922 data.writeInterfaceToken("android.view.IWindow"); 6923 data.writeString(command); 6924 data.writeString(parameters); 6925 data.writeInt(1); 6926 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6927 6928 reply = Parcel.obtain(); 6929 6930 final IBinder binder = window.mClient.asBinder(); 6931 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6932 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6933 6934 reply.readException(); 6935 6936 if (!client.isOutputShutdown()) { 6937 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6938 out.write("DONE\n"); 6939 out.flush(); 6940 } 6941 6942 } catch (Exception e) { 6943 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6944 success = false; 6945 } finally { 6946 if (data != null) { 6947 data.recycle(); 6948 } 6949 if (reply != null) { 6950 reply.recycle(); 6951 } 6952 if (out != null) { 6953 try { 6954 out.close(); 6955 } catch (IOException e) { 6956 6957 } 6958 } 6959 } 6960 6961 return success; 6962 } 6963 6964 public void addWindowChangeListener(WindowChangeListener listener) { 6965 synchronized(mWindowMap) { 6966 mWindowChangeListeners.add(listener); 6967 } 6968 } 6969 6970 public void removeWindowChangeListener(WindowChangeListener listener) { 6971 synchronized(mWindowMap) { 6972 mWindowChangeListeners.remove(listener); 6973 } 6974 } 6975 6976 private void notifyWindowsChanged() { 6977 WindowChangeListener[] windowChangeListeners; 6978 synchronized(mWindowMap) { 6979 if(mWindowChangeListeners.isEmpty()) { 6980 return; 6981 } 6982 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6983 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6984 } 6985 int N = windowChangeListeners.length; 6986 for(int i = 0; i < N; i++) { 6987 windowChangeListeners[i].windowsChanged(); 6988 } 6989 } 6990 6991 private void notifyFocusChanged() { 6992 WindowChangeListener[] windowChangeListeners; 6993 synchronized(mWindowMap) { 6994 if(mWindowChangeListeners.isEmpty()) { 6995 return; 6996 } 6997 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6998 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6999 } 7000 int N = windowChangeListeners.length; 7001 for(int i = 0; i < N; i++) { 7002 windowChangeListeners[i].focusChanged(); 7003 } 7004 } 7005 7006 private WindowState findWindow(int hashCode) { 7007 if (hashCode == -1) { 7008 // TODO(multidisplay): Extend to multiple displays. 7009 return getFocusedWindow(); 7010 } 7011 7012 synchronized (mWindowMap) { 7013 final int numDisplays = mDisplayContents.size(); 7014 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 7015 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 7016 final int numWindows = windows.size(); 7017 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 7018 final WindowState w = windows.get(winNdx); 7019 if (System.identityHashCode(w) == hashCode) { 7020 return w; 7021 } 7022 } 7023 } 7024 } 7025 7026 return null; 7027 } 7028 7029 /* 7030 * Instruct the Activity Manager to fetch the current configuration and broadcast 7031 * that to config-changed listeners if appropriate. 7032 */ 7033 void sendNewConfiguration() { 7034 try { 7035 mActivityManager.updateConfiguration(null); 7036 } catch (RemoteException e) { 7037 } 7038 } 7039 7040 public Configuration computeNewConfiguration() { 7041 synchronized (mWindowMap) { 7042 Configuration config = computeNewConfigurationLocked(); 7043 if (config == null && mWaitingForConfig) { 7044 // Nothing changed but we are waiting for something... stop that! 7045 mWaitingForConfig = false; 7046 mLastFinishedFreezeSource = "new-config"; 7047 performLayoutAndPlaceSurfacesLocked(); 7048 } 7049 return config; 7050 } 7051 } 7052 7053 Configuration computeNewConfigurationLocked() { 7054 Configuration config = new Configuration(); 7055 config.fontScale = 0; 7056 if (!computeScreenConfigurationLocked(config)) { 7057 return null; 7058 } 7059 return config; 7060 } 7061 7062 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 7063 // TODO: Multidisplay: for now only use with default display. 7064 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 7065 if (width < displayInfo.smallestNominalAppWidth) { 7066 displayInfo.smallestNominalAppWidth = width; 7067 } 7068 if (width > displayInfo.largestNominalAppWidth) { 7069 displayInfo.largestNominalAppWidth = width; 7070 } 7071 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 7072 if (height < displayInfo.smallestNominalAppHeight) { 7073 displayInfo.smallestNominalAppHeight = height; 7074 } 7075 if (height > displayInfo.largestNominalAppHeight) { 7076 displayInfo.largestNominalAppHeight = height; 7077 } 7078 } 7079 7080 private int reduceConfigLayout(int curLayout, int rotation, float density, 7081 int dw, int dh) { 7082 // TODO: Multidisplay: for now only use with default display. 7083 // Get the app screen size at this rotation. 7084 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 7085 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 7086 7087 // Compute the screen layout size class for this rotation. 7088 int longSize = w; 7089 int shortSize = h; 7090 if (longSize < shortSize) { 7091 int tmp = longSize; 7092 longSize = shortSize; 7093 shortSize = tmp; 7094 } 7095 longSize = (int)(longSize/density); 7096 shortSize = (int)(shortSize/density); 7097 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 7098 } 7099 7100 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 7101 int dw, int dh, float density, Configuration outConfig) { 7102 // TODO: Multidisplay: for now only use with default display. 7103 7104 // We need to determine the smallest width that will occur under normal 7105 // operation. To this, start with the base screen size and compute the 7106 // width under the different possible rotations. We need to un-rotate 7107 // the current screen dimensions before doing this. 7108 int unrotDw, unrotDh; 7109 if (rotated) { 7110 unrotDw = dh; 7111 unrotDh = dw; 7112 } else { 7113 unrotDw = dw; 7114 unrotDh = dh; 7115 } 7116 displayInfo.smallestNominalAppWidth = 1<<30; 7117 displayInfo.smallestNominalAppHeight = 1<<30; 7118 displayInfo.largestNominalAppWidth = 0; 7119 displayInfo.largestNominalAppHeight = 0; 7120 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 7121 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 7122 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 7123 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 7124 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 7125 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 7126 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 7127 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 7128 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 7129 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 7130 outConfig.screenLayout = sl; 7131 } 7132 7133 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 7134 int dw, int dh) { 7135 // TODO: Multidisplay: for now only use with default display. 7136 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 7137 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 7138 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 7139 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 7140 if (curSize == 0 || size < curSize) { 7141 curSize = size; 7142 } 7143 return curSize; 7144 } 7145 7146 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 7147 // TODO: Multidisplay: for now only use with default display. 7148 mTmpDisplayMetrics.setTo(dm); 7149 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 7150 final int unrotDw, unrotDh; 7151 if (rotated) { 7152 unrotDw = dh; 7153 unrotDh = dw; 7154 } else { 7155 unrotDw = dw; 7156 unrotDh = dh; 7157 } 7158 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 7159 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 7160 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 7161 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 7162 return sw; 7163 } 7164 7165 boolean computeScreenConfigurationLocked(Configuration config) { 7166 if (!mDisplayReady) { 7167 return false; 7168 } 7169 7170 // TODO(multidisplay): For now, apply Configuration to main screen only. 7171 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7172 7173 // Use the effective "visual" dimensions based on current rotation 7174 final boolean rotated = (mRotation == Surface.ROTATION_90 7175 || mRotation == Surface.ROTATION_270); 7176 final int realdw = rotated ? 7177 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 7178 final int realdh = rotated ? 7179 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 7180 int dw = realdw; 7181 int dh = realdh; 7182 7183 if (mAltOrientation) { 7184 if (realdw > realdh) { 7185 // Turn landscape into portrait. 7186 int maxw = (int)(realdh/1.3f); 7187 if (maxw < realdw) { 7188 dw = maxw; 7189 } 7190 } else { 7191 // Turn portrait into landscape. 7192 int maxh = (int)(realdw/1.3f); 7193 if (maxh < realdh) { 7194 dh = maxh; 7195 } 7196 } 7197 } 7198 7199 if (config != null) { 7200 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 7201 Configuration.ORIENTATION_LANDSCAPE; 7202 } 7203 7204 // Update application display metrics. 7205 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 7206 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 7207 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7208 synchronized(displayContent.mDisplaySizeLock) { 7209 displayInfo.rotation = mRotation; 7210 displayInfo.logicalWidth = dw; 7211 displayInfo.logicalHeight = dh; 7212 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 7213 displayInfo.appWidth = appWidth; 7214 displayInfo.appHeight = appHeight; 7215 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 7216 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 7217 displayInfo.getAppMetrics(mDisplayMetrics); 7218 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 7219 displayContent.getDisplayId(), displayInfo); 7220 } 7221 if (false) { 7222 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 7223 } 7224 7225 final DisplayMetrics dm = mDisplayMetrics; 7226 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 7227 mCompatDisplayMetrics); 7228 7229 if (config != null) { 7230 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 7231 / dm.density); 7232 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 7233 / dm.density); 7234 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 7235 7236 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 7237 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 7238 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 7239 config.densityDpi = displayContent.mBaseDisplayDensity; 7240 7241 // Update the configuration based on available input devices, lid switch, 7242 // and platform configuration. 7243 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 7244 config.keyboard = Configuration.KEYBOARD_NOKEYS; 7245 config.navigation = Configuration.NAVIGATION_NONAV; 7246 7247 int keyboardPresence = 0; 7248 int navigationPresence = 0; 7249 final InputDevice[] devices = mInputManager.getInputDevices(); 7250 final int len = devices.length; 7251 for (int i = 0; i < len; i++) { 7252 InputDevice device = devices[i]; 7253 if (!device.isVirtual()) { 7254 final int sources = device.getSources(); 7255 final int presenceFlag = device.isExternal() ? 7256 WindowManagerPolicy.PRESENCE_EXTERNAL : 7257 WindowManagerPolicy.PRESENCE_INTERNAL; 7258 7259 if (mIsTouchDevice) { 7260 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 7261 InputDevice.SOURCE_TOUCHSCREEN) { 7262 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 7263 } 7264 } else { 7265 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 7266 } 7267 7268 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 7269 config.navigation = Configuration.NAVIGATION_TRACKBALL; 7270 navigationPresence |= presenceFlag; 7271 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 7272 && config.navigation == Configuration.NAVIGATION_NONAV) { 7273 config.navigation = Configuration.NAVIGATION_DPAD; 7274 navigationPresence |= presenceFlag; 7275 } 7276 7277 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 7278 config.keyboard = Configuration.KEYBOARD_QWERTY; 7279 keyboardPresence |= presenceFlag; 7280 } 7281 } 7282 } 7283 7284 if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) { 7285 config.navigation = Configuration.NAVIGATION_DPAD; 7286 navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL; 7287 } 7288 7289 // Determine whether a hard keyboard is available and enabled. 7290 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 7291 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 7292 mHardKeyboardAvailable = hardKeyboardAvailable; 7293 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 7294 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 7295 } 7296 if (mShowImeWithHardKeyboard) { 7297 config.keyboard = Configuration.KEYBOARD_NOKEYS; 7298 } 7299 7300 // Let the policy update hidden states. 7301 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 7302 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 7303 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 7304 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 7305 } 7306 7307 return true; 7308 } 7309 7310 public boolean isHardKeyboardAvailable() { 7311 synchronized (mWindowMap) { 7312 return mHardKeyboardAvailable; 7313 } 7314 } 7315 7316 public void updateShowImeWithHardKeyboard() { 7317 final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser( 7318 mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, 7319 mCurrentUserId) == 1; 7320 synchronized (mWindowMap) { 7321 if (mShowImeWithHardKeyboard != showImeWithHardKeyboard) { 7322 mShowImeWithHardKeyboard = showImeWithHardKeyboard; 7323 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7324 } 7325 } 7326 } 7327 7328 public void setOnHardKeyboardStatusChangeListener( 7329 OnHardKeyboardStatusChangeListener listener) { 7330 synchronized (mWindowMap) { 7331 mHardKeyboardStatusChangeListener = listener; 7332 } 7333 } 7334 7335 void notifyHardKeyboardStatusChange() { 7336 final boolean available; 7337 final OnHardKeyboardStatusChangeListener listener; 7338 synchronized (mWindowMap) { 7339 listener = mHardKeyboardStatusChangeListener; 7340 available = mHardKeyboardAvailable; 7341 } 7342 if (listener != null) { 7343 listener.onHardKeyboardStatusChange(available); 7344 } 7345 } 7346 7347 // ------------------------------------------------------------- 7348 // Drag and drop 7349 // ------------------------------------------------------------- 7350 7351 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 7352 int flags, int width, int height, Surface outSurface) { 7353 if (DEBUG_DRAG) { 7354 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 7355 + " flags=" + Integer.toHexString(flags) + " win=" + window 7356 + " asbinder=" + window.asBinder()); 7357 } 7358 7359 final int callerPid = Binder.getCallingPid(); 7360 final long origId = Binder.clearCallingIdentity(); 7361 IBinder token = null; 7362 7363 try { 7364 synchronized (mWindowMap) { 7365 try { 7366 if (mDragState == null) { 7367 // TODO(multi-display): support other displays 7368 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7369 final Display display = displayContent.getDisplay(); 7370 SurfaceControl surface = new SurfaceControl(session, "drag surface", 7371 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 7372 surface.setLayerStack(display.getLayerStack()); 7373 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 7374 + surface + ": CREATE"); 7375 outSurface.copyFrom(surface); 7376 final IBinder winBinder = window.asBinder(); 7377 token = new Binder(); 7378 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 7379 token = mDragState.mToken = new Binder(); 7380 7381 // 5 second timeout for this window to actually begin the drag 7382 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 7383 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 7384 mH.sendMessageDelayed(msg, 5000); 7385 } else { 7386 Slog.w(TAG, "Drag already in progress"); 7387 } 7388 } catch (OutOfResourcesException e) { 7389 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 7390 if (mDragState != null) { 7391 mDragState.reset(); 7392 mDragState = null; 7393 } 7394 } 7395 } 7396 } finally { 7397 Binder.restoreCallingIdentity(origId); 7398 } 7399 7400 return token; 7401 } 7402 7403 // ------------------------------------------------------------- 7404 // Input Events and Focus Management 7405 // ------------------------------------------------------------- 7406 7407 final InputMonitor mInputMonitor = new InputMonitor(this); 7408 private boolean mEventDispatchingEnabled; 7409 7410 @Override 7411 public void pauseKeyDispatching(IBinder _token) { 7412 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7413 "pauseKeyDispatching()")) { 7414 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7415 } 7416 7417 synchronized (mWindowMap) { 7418 WindowToken token = mTokenMap.get(_token); 7419 if (token != null) { 7420 mInputMonitor.pauseDispatchingLw(token); 7421 } 7422 } 7423 } 7424 7425 @Override 7426 public void resumeKeyDispatching(IBinder _token) { 7427 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7428 "resumeKeyDispatching()")) { 7429 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7430 } 7431 7432 synchronized (mWindowMap) { 7433 WindowToken token = mTokenMap.get(_token); 7434 if (token != null) { 7435 mInputMonitor.resumeDispatchingLw(token); 7436 } 7437 } 7438 } 7439 7440 @Override 7441 public void setEventDispatching(boolean enabled) { 7442 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7443 "setEventDispatching()")) { 7444 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7445 } 7446 7447 synchronized (mWindowMap) { 7448 mEventDispatchingEnabled = enabled; 7449 if (mDisplayEnabled) { 7450 mInputMonitor.setEventDispatchingLw(enabled); 7451 } 7452 } 7453 } 7454 7455 private WindowState getFocusedWindow() { 7456 synchronized (mWindowMap) { 7457 return getFocusedWindowLocked(); 7458 } 7459 } 7460 7461 private WindowState getFocusedWindowLocked() { 7462 return mCurrentFocus; 7463 } 7464 7465 public boolean detectSafeMode() { 7466 if (!mInputMonitor.waitForInputDevicesReady( 7467 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7468 Slog.w(TAG, "Devices still not ready after waiting " 7469 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7470 + " milliseconds before attempting to detect safe mode."); 7471 } 7472 7473 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7474 KeyEvent.KEYCODE_MENU); 7475 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7476 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7477 KeyEvent.KEYCODE_DPAD_CENTER); 7478 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7479 InputManagerService.BTN_MOUSE); 7480 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7481 KeyEvent.KEYCODE_VOLUME_DOWN); 7482 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7483 || volumeDownState > 0; 7484 try { 7485 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7486 mSafeMode = true; 7487 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7488 } 7489 } catch (IllegalArgumentException e) { 7490 } 7491 if (mSafeMode) { 7492 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7493 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7494 } else { 7495 Log.i(TAG, "SAFE MODE not enabled"); 7496 } 7497 mPolicy.setSafeMode(mSafeMode); 7498 return mSafeMode; 7499 } 7500 7501 public void displayReady() { 7502 displayReady(Display.DEFAULT_DISPLAY); 7503 7504 synchronized(mWindowMap) { 7505 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7506 readForcedDisplaySizeAndDensityLocked(displayContent); 7507 mDisplayReady = true; 7508 } 7509 7510 try { 7511 mActivityManager.updateConfiguration(null); 7512 } catch (RemoteException e) { 7513 } 7514 7515 synchronized(mWindowMap) { 7516 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7517 PackageManager.FEATURE_TOUCHSCREEN); 7518 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7519 } 7520 7521 try { 7522 mActivityManager.updateConfiguration(null); 7523 } catch (RemoteException e) { 7524 } 7525 } 7526 7527 private void displayReady(int displayId) { 7528 synchronized(mWindowMap) { 7529 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7530 if (displayContent != null) { 7531 mAnimator.addDisplayLocked(displayId); 7532 synchronized(displayContent.mDisplaySizeLock) { 7533 // Bootstrap the default logical display from the display manager. 7534 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7535 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); 7536 if (newDisplayInfo != null) { 7537 displayInfo.copyFrom(newDisplayInfo); 7538 } 7539 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7540 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7541 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7542 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7543 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7544 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7545 displayContent.mBaseDisplayRect.set(0, 0, 7546 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7547 } 7548 } 7549 } 7550 } 7551 7552 public void systemReady() { 7553 mPolicy.systemReady(); 7554 } 7555 7556 // ------------------------------------------------------------- 7557 // Async Handler 7558 // ------------------------------------------------------------- 7559 7560 final class H extends Handler { 7561 public static final int REPORT_FOCUS_CHANGE = 2; 7562 public static final int REPORT_LOSING_FOCUS = 3; 7563 public static final int DO_TRAVERSAL = 4; 7564 public static final int ADD_STARTING = 5; 7565 public static final int REMOVE_STARTING = 6; 7566 public static final int FINISHED_STARTING = 7; 7567 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7568 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7569 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7570 7571 public static final int APP_TRANSITION_TIMEOUT = 13; 7572 public static final int PERSIST_ANIMATION_SCALE = 14; 7573 public static final int FORCE_GC = 15; 7574 public static final int ENABLE_SCREEN = 16; 7575 public static final int APP_FREEZE_TIMEOUT = 17; 7576 public static final int SEND_NEW_CONFIGURATION = 18; 7577 public static final int REPORT_WINDOWS_CHANGE = 19; 7578 public static final int DRAG_START_TIMEOUT = 20; 7579 public static final int DRAG_END_TIMEOUT = 21; 7580 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7581 public static final int BOOT_TIMEOUT = 23; 7582 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7583 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7584 public static final int DO_ANIMATION_CALLBACK = 26; 7585 7586 public static final int DO_DISPLAY_ADDED = 27; 7587 public static final int DO_DISPLAY_REMOVED = 28; 7588 public static final int DO_DISPLAY_CHANGED = 29; 7589 7590 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7591 public static final int TAP_OUTSIDE_STACK = 31; 7592 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7593 7594 public static final int ALL_WINDOWS_DRAWN = 33; 7595 7596 public static final int NEW_ANIMATOR_SCALE = 34; 7597 7598 public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35; 7599 public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36; 7600 7601 public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37; 7602 7603 @Override 7604 public void handleMessage(Message msg) { 7605 if (DEBUG_WINDOW_TRACE) { 7606 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7607 } 7608 switch (msg.what) { 7609 case REPORT_FOCUS_CHANGE: { 7610 WindowState lastFocus; 7611 WindowState newFocus; 7612 7613 AccessibilityController accessibilityController = null; 7614 7615 synchronized(mWindowMap) { 7616 // TODO(multidisplay): Accessibility supported only of default desiplay. 7617 if (mAccessibilityController != null && getDefaultDisplayContentLocked() 7618 .getDisplayId() == Display.DEFAULT_DISPLAY) { 7619 accessibilityController = mAccessibilityController; 7620 } 7621 7622 lastFocus = mLastFocus; 7623 newFocus = mCurrentFocus; 7624 if (lastFocus == newFocus) { 7625 // Focus is not changing, so nothing to do. 7626 return; 7627 } 7628 mLastFocus = newFocus; 7629 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7630 " to " + newFocus); 7631 if (newFocus != null && lastFocus != null 7632 && !newFocus.isDisplayedLw()) { 7633 //Slog.i(TAG, "Delaying loss of focus..."); 7634 mLosingFocus.add(lastFocus); 7635 lastFocus = null; 7636 } 7637 } 7638 7639 // First notify the accessibility manager for the change so it has 7640 // the windows before the newly focused one starts firing eventgs. 7641 if (accessibilityController != null) { 7642 accessibilityController.onWindowFocusChangedNotLocked(); 7643 } 7644 7645 //System.out.println("Changing focus from " + lastFocus 7646 // + " to " + newFocus); 7647 if (newFocus != null) { 7648 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7649 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7650 notifyFocusChanged(); 7651 } 7652 7653 if (lastFocus != null) { 7654 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7655 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7656 } 7657 } break; 7658 7659 case REPORT_LOSING_FOCUS: { 7660 ArrayList<WindowState> losers; 7661 7662 synchronized(mWindowMap) { 7663 losers = mLosingFocus; 7664 mLosingFocus = new ArrayList<WindowState>(); 7665 } 7666 7667 final int N = losers.size(); 7668 for (int i=0; i<N; i++) { 7669 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7670 losers.get(i)); 7671 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7672 } 7673 } break; 7674 7675 case DO_TRAVERSAL: { 7676 synchronized(mWindowMap) { 7677 mTraversalScheduled = false; 7678 performLayoutAndPlaceSurfacesLocked(); 7679 } 7680 } break; 7681 7682 case ADD_STARTING: { 7683 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7684 final StartingData sd = wtoken.startingData; 7685 7686 if (sd == null) { 7687 // Animation has been canceled... do nothing. 7688 return; 7689 } 7690 7691 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7692 + wtoken + ": pkg=" + sd.pkg); 7693 7694 View view = null; 7695 try { 7696 view = mPolicy.addStartingWindow( 7697 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7698 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7699 } catch (Exception e) { 7700 Slog.w(TAG, "Exception when adding starting window", e); 7701 } 7702 7703 if (view != null) { 7704 boolean abort = false; 7705 7706 synchronized(mWindowMap) { 7707 if (wtoken.removed || wtoken.startingData == null) { 7708 // If the window was successfully added, then 7709 // we need to remove it. 7710 if (wtoken.startingWindow != null) { 7711 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7712 "Aborted starting " + wtoken 7713 + ": removed=" + wtoken.removed 7714 + " startingData=" + wtoken.startingData); 7715 wtoken.startingWindow = null; 7716 wtoken.startingData = null; 7717 abort = true; 7718 } 7719 } else { 7720 wtoken.startingView = view; 7721 } 7722 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7723 "Added starting " + wtoken 7724 + ": startingWindow=" 7725 + wtoken.startingWindow + " startingView=" 7726 + wtoken.startingView); 7727 } 7728 7729 if (abort) { 7730 try { 7731 mPolicy.removeStartingWindow(wtoken.token, view); 7732 } catch (Exception e) { 7733 Slog.w(TAG, "Exception when removing starting window", e); 7734 } 7735 } 7736 } 7737 } break; 7738 7739 case REMOVE_STARTING: { 7740 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7741 IBinder token = null; 7742 View view = null; 7743 synchronized (mWindowMap) { 7744 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7745 + wtoken + ": startingWindow=" 7746 + wtoken.startingWindow + " startingView=" 7747 + wtoken.startingView); 7748 if (wtoken.startingWindow != null) { 7749 view = wtoken.startingView; 7750 token = wtoken.token; 7751 wtoken.startingData = null; 7752 wtoken.startingView = null; 7753 wtoken.startingWindow = null; 7754 wtoken.startingDisplayed = false; 7755 } 7756 } 7757 if (view != null) { 7758 try { 7759 mPolicy.removeStartingWindow(token, view); 7760 } catch (Exception e) { 7761 Slog.w(TAG, "Exception when removing starting window", e); 7762 } 7763 } 7764 } break; 7765 7766 case FINISHED_STARTING: { 7767 IBinder token = null; 7768 View view = null; 7769 while (true) { 7770 synchronized (mWindowMap) { 7771 final int N = mFinishedStarting.size(); 7772 if (N <= 0) { 7773 break; 7774 } 7775 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7776 7777 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7778 "Finished starting " + wtoken 7779 + ": startingWindow=" + wtoken.startingWindow 7780 + " startingView=" + wtoken.startingView); 7781 7782 if (wtoken.startingWindow == null) { 7783 continue; 7784 } 7785 7786 view = wtoken.startingView; 7787 token = wtoken.token; 7788 wtoken.startingData = null; 7789 wtoken.startingView = null; 7790 wtoken.startingWindow = null; 7791 wtoken.startingDisplayed = false; 7792 } 7793 7794 try { 7795 mPolicy.removeStartingWindow(token, view); 7796 } catch (Exception e) { 7797 Slog.w(TAG, "Exception when removing starting window", e); 7798 } 7799 } 7800 } break; 7801 7802 case REPORT_APPLICATION_TOKEN_DRAWN: { 7803 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7804 7805 try { 7806 if (DEBUG_VISIBILITY) Slog.v( 7807 TAG, "Reporting drawn in " + wtoken); 7808 wtoken.appToken.windowsDrawn(); 7809 } catch (RemoteException ex) { 7810 } 7811 } break; 7812 7813 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7814 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7815 7816 boolean nowVisible = msg.arg1 != 0; 7817 boolean nowGone = msg.arg2 != 0; 7818 7819 try { 7820 if (DEBUG_VISIBILITY) Slog.v( 7821 TAG, "Reporting visible in " + wtoken 7822 + " visible=" + nowVisible 7823 + " gone=" + nowGone); 7824 if (nowVisible) { 7825 wtoken.appToken.windowsVisible(); 7826 } else { 7827 wtoken.appToken.windowsGone(); 7828 } 7829 } catch (RemoteException ex) { 7830 } 7831 } break; 7832 7833 case WINDOW_FREEZE_TIMEOUT: { 7834 // TODO(multidisplay): Can non-default displays rotate? 7835 synchronized (mWindowMap) { 7836 Slog.w(TAG, "Window freeze timeout expired."); 7837 final WindowList windows = getDefaultWindowListLocked(); 7838 int i = windows.size(); 7839 while (i > 0) { 7840 i--; 7841 WindowState w = windows.get(i); 7842 if (w.mOrientationChanging) { 7843 w.mOrientationChanging = false; 7844 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7845 - mDisplayFreezeTime); 7846 Slog.w(TAG, "Force clearing orientation change: " + w); 7847 } 7848 } 7849 performLayoutAndPlaceSurfacesLocked(); 7850 } 7851 break; 7852 } 7853 7854 case APP_TRANSITION_TIMEOUT: { 7855 synchronized (mWindowMap) { 7856 if (mAppTransition.isTransitionSet()) { 7857 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7858 mAppTransition.setTimeout(); 7859 performLayoutAndPlaceSurfacesLocked(); 7860 } 7861 } 7862 break; 7863 } 7864 7865 case PERSIST_ANIMATION_SCALE: { 7866 Settings.Global.putFloat(mContext.getContentResolver(), 7867 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 7868 Settings.Global.putFloat(mContext.getContentResolver(), 7869 Settings.Global.TRANSITION_ANIMATION_SCALE, 7870 mTransitionAnimationScaleSetting); 7871 Settings.Global.putFloat(mContext.getContentResolver(), 7872 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 7873 break; 7874 } 7875 7876 case FORCE_GC: { 7877 synchronized (mWindowMap) { 7878 // Since we're holding both mWindowMap and mAnimator we don't need to 7879 // hold mAnimator.mLayoutToAnim. 7880 if (mAnimator.mAnimating || mAnimationScheduled) { 7881 // If we are animating, don't do the gc now but 7882 // delay a bit so we don't interrupt the animation. 7883 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7884 return; 7885 } 7886 // If we are currently rotating the display, it will 7887 // schedule a new message when done. 7888 if (mDisplayFrozen) { 7889 return; 7890 } 7891 } 7892 Runtime.getRuntime().gc(); 7893 break; 7894 } 7895 7896 case ENABLE_SCREEN: { 7897 performEnableScreen(); 7898 break; 7899 } 7900 7901 case APP_FREEZE_TIMEOUT: { 7902 synchronized (mWindowMap) { 7903 Slog.w(TAG, "App freeze timeout expired."); 7904 final int numStacks = mStackIdToStack.size(); 7905 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 7906 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 7907 final ArrayList<Task> tasks = stack.getTasks(); 7908 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7909 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7910 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7911 AppWindowToken tok = tokens.get(tokenNdx); 7912 if (tok.mAppAnimator.freezingScreen) { 7913 Slog.w(TAG, "Force clearing freeze: " + tok); 7914 unsetAppFreezingScreenLocked(tok, true, true); 7915 } 7916 } 7917 } 7918 } 7919 } 7920 break; 7921 } 7922 7923 case CLIENT_FREEZE_TIMEOUT: { 7924 synchronized (mWindowMap) { 7925 if (mClientFreezingScreen) { 7926 mClientFreezingScreen = false; 7927 mLastFinishedFreezeSource = "client-timeout"; 7928 stopFreezingDisplayLocked(); 7929 } 7930 } 7931 break; 7932 } 7933 7934 case SEND_NEW_CONFIGURATION: { 7935 removeMessages(SEND_NEW_CONFIGURATION); 7936 sendNewConfiguration(); 7937 break; 7938 } 7939 7940 case REPORT_WINDOWS_CHANGE: { 7941 if (mWindowsChanged) { 7942 synchronized (mWindowMap) { 7943 mWindowsChanged = false; 7944 } 7945 notifyWindowsChanged(); 7946 } 7947 break; 7948 } 7949 7950 case DRAG_START_TIMEOUT: { 7951 IBinder win = (IBinder)msg.obj; 7952 if (DEBUG_DRAG) { 7953 Slog.w(TAG, "Timeout starting drag by win " + win); 7954 } 7955 synchronized (mWindowMap) { 7956 // !!! TODO: ANR the app that has failed to start the drag in time 7957 if (mDragState != null) { 7958 mDragState.unregister(); 7959 mInputMonitor.updateInputWindowsLw(true /*force*/); 7960 mDragState.reset(); 7961 mDragState = null; 7962 } 7963 } 7964 break; 7965 } 7966 7967 case DRAG_END_TIMEOUT: { 7968 IBinder win = (IBinder)msg.obj; 7969 if (DEBUG_DRAG) { 7970 Slog.w(TAG, "Timeout ending drag to win " + win); 7971 } 7972 synchronized (mWindowMap) { 7973 // !!! TODO: ANR the drag-receiving app 7974 if (mDragState != null) { 7975 mDragState.mDragResult = false; 7976 mDragState.endDragLw(); 7977 } 7978 } 7979 break; 7980 } 7981 7982 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7983 notifyHardKeyboardStatusChange(); 7984 break; 7985 } 7986 7987 case BOOT_TIMEOUT: { 7988 performBootTimeout(); 7989 break; 7990 } 7991 7992 case WAITING_FOR_DRAWN_TIMEOUT: { 7993 Runnable callback = null; 7994 synchronized (mWindowMap) { 7995 Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 7996 mWaitingForDrawn.clear(); 7997 callback = mWaitingForDrawnCallback; 7998 mWaitingForDrawnCallback = null; 7999 } 8000 if (callback != null) { 8001 callback.run(); 8002 } 8003 break; 8004 } 8005 8006 case SHOW_STRICT_MODE_VIOLATION: { 8007 showStrictModeViolation(msg.arg1, msg.arg2); 8008 break; 8009 } 8010 8011 case SHOW_CIRCULAR_DISPLAY_MASK: { 8012 showCircularMask(msg.arg1 == 1); 8013 break; 8014 } 8015 8016 case SHOW_EMULATOR_DISPLAY_OVERLAY: { 8017 showEmulatorDisplayOverlay(); 8018 break; 8019 } 8020 8021 case DO_ANIMATION_CALLBACK: { 8022 try { 8023 ((IRemoteCallback)msg.obj).sendResult(null); 8024 } catch (RemoteException e) { 8025 } 8026 break; 8027 } 8028 8029 case DO_DISPLAY_ADDED: 8030 handleDisplayAdded(msg.arg1); 8031 break; 8032 8033 case DO_DISPLAY_REMOVED: 8034 synchronized (mWindowMap) { 8035 handleDisplayRemovedLocked(msg.arg1); 8036 } 8037 break; 8038 8039 case DO_DISPLAY_CHANGED: 8040 synchronized (mWindowMap) { 8041 handleDisplayChangedLocked(msg.arg1); 8042 } 8043 break; 8044 8045 case TAP_OUTSIDE_STACK: { 8046 int stackId; 8047 synchronized (mWindowMap) { 8048 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 8049 } 8050 if (stackId >= 0) { 8051 try { 8052 mActivityManager.setFocusedStack(stackId); 8053 } catch (RemoteException e) { 8054 } 8055 } 8056 } 8057 break; 8058 case NOTIFY_ACTIVITY_DRAWN: 8059 try { 8060 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 8061 } catch (RemoteException e) { 8062 } 8063 break; 8064 case ALL_WINDOWS_DRAWN: { 8065 Runnable callback; 8066 synchronized (mWindowMap) { 8067 callback = mWaitingForDrawnCallback; 8068 mWaitingForDrawnCallback = null; 8069 } 8070 if (callback != null) { 8071 callback.run(); 8072 } 8073 } 8074 case NEW_ANIMATOR_SCALE: { 8075 float scale = getCurrentAnimatorScale(); 8076 ValueAnimator.setDurationScale(scale); 8077 Session session = (Session)msg.obj; 8078 if (session != null) { 8079 try { 8080 session.mCallback.onAnimatorScaleChanged(scale); 8081 } catch (RemoteException e) { 8082 } 8083 } else { 8084 ArrayList<IWindowSessionCallback> callbacks 8085 = new ArrayList<IWindowSessionCallback>(); 8086 synchronized (mWindowMap) { 8087 for (int i=0; i<mSessions.size(); i++) { 8088 callbacks.add(mSessions.valueAt(i).mCallback); 8089 } 8090 8091 } 8092 for (int i=0; i<callbacks.size(); i++) { 8093 try { 8094 callbacks.get(i).onAnimatorScaleChanged(scale); 8095 } catch (RemoteException e) { 8096 } 8097 } 8098 } 8099 } 8100 break; 8101 case CHECK_IF_BOOT_ANIMATION_FINISHED: { 8102 final boolean bootAnimationComplete; 8103 synchronized (mWindowMap) { 8104 if (DEBUG_BOOT) Slog.i(TAG, "CHECK_IF_BOOT_ANIMATION_FINISHED:"); 8105 bootAnimationComplete = checkBootAnimationCompleteLocked(); 8106 } 8107 if (bootAnimationComplete) { 8108 performEnableScreen(); 8109 } 8110 } 8111 break; 8112 } 8113 if (DEBUG_WINDOW_TRACE) { 8114 Slog.v(TAG, "handleMessage: exit"); 8115 } 8116 } 8117 } 8118 8119 // ------------------------------------------------------------- 8120 // IWindowManager API 8121 // ------------------------------------------------------------- 8122 8123 @Override 8124 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 8125 IInputContext inputContext) { 8126 if (client == null) throw new IllegalArgumentException("null client"); 8127 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 8128 Session session = new Session(this, callback, client, inputContext); 8129 return session; 8130 } 8131 8132 @Override 8133 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 8134 synchronized (mWindowMap) { 8135 // The focus for the client is the window immediately below 8136 // where we would place the input method window. 8137 int idx = findDesiredInputMethodWindowIndexLocked(false); 8138 if (idx > 0) { 8139 // TODO(multidisplay): IMEs are only supported on the default display. 8140 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 8141 if (DEBUG_INPUT_METHOD) { 8142 Slog.i(TAG, "Desired input method target: " + imFocus); 8143 Slog.i(TAG, "Current focus: " + mCurrentFocus); 8144 Slog.i(TAG, "Last focus: " + mLastFocus); 8145 } 8146 if (imFocus != null) { 8147 // This may be a starting window, in which case we still want 8148 // to count it as okay. 8149 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 8150 && imFocus.mAppToken != null) { 8151 // The client has definitely started, so it really should 8152 // have a window in this app token. Let's look for it. 8153 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 8154 WindowState w = imFocus.mAppToken.windows.get(i); 8155 if (w != imFocus) { 8156 Log.i(TAG, "Switching to real app window: " + w); 8157 imFocus = w; 8158 break; 8159 } 8160 } 8161 } 8162 if (DEBUG_INPUT_METHOD) { 8163 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 8164 if (imFocus.mSession.mClient != null) { 8165 Slog.i(TAG, "IM target client binder: " 8166 + imFocus.mSession.mClient.asBinder()); 8167 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 8168 } 8169 } 8170 if (imFocus.mSession.mClient != null && 8171 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 8172 return true; 8173 } 8174 } 8175 } 8176 8177 // Okay, how about this... what is the current focus? 8178 // It seems in some cases we may not have moved the IM 8179 // target window, such as when it was in a pop-up window, 8180 // so let's also look at the current focus. (An example: 8181 // go to Gmail, start searching so the keyboard goes up, 8182 // press home. Sometimes the IME won't go down.) 8183 // Would be nice to fix this more correctly, but it's 8184 // way at the end of a release, and this should be good enough. 8185 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 8186 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 8187 return true; 8188 } 8189 } 8190 return false; 8191 } 8192 8193 @Override 8194 public void getInitialDisplaySize(int displayId, Point size) { 8195 synchronized (mWindowMap) { 8196 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8197 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8198 synchronized(displayContent.mDisplaySizeLock) { 8199 size.x = displayContent.mInitialDisplayWidth; 8200 size.y = displayContent.mInitialDisplayHeight; 8201 } 8202 } 8203 } 8204 } 8205 8206 @Override 8207 public void getBaseDisplaySize(int displayId, Point size) { 8208 synchronized (mWindowMap) { 8209 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8210 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8211 synchronized(displayContent.mDisplaySizeLock) { 8212 size.x = displayContent.mBaseDisplayWidth; 8213 size.y = displayContent.mBaseDisplayHeight; 8214 } 8215 } 8216 } 8217 } 8218 8219 @Override 8220 public void setForcedDisplaySize(int displayId, int width, int height) { 8221 if (mContext.checkCallingOrSelfPermission( 8222 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8223 PackageManager.PERMISSION_GRANTED) { 8224 throw new SecurityException("Must hold permission " + 8225 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8226 } 8227 if (displayId != Display.DEFAULT_DISPLAY) { 8228 throw new IllegalArgumentException("Can only set the default display"); 8229 } 8230 final long ident = Binder.clearCallingIdentity(); 8231 try { 8232 synchronized(mWindowMap) { 8233 // Set some sort of reasonable bounds on the size of the display that we 8234 // will try to emulate. 8235 final int MIN_WIDTH = 200; 8236 final int MIN_HEIGHT = 200; 8237 final int MAX_SCALE = 2; 8238 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8239 if (displayContent != null) { 8240 width = Math.min(Math.max(width, MIN_WIDTH), 8241 displayContent.mInitialDisplayWidth * MAX_SCALE); 8242 height = Math.min(Math.max(height, MIN_HEIGHT), 8243 displayContent.mInitialDisplayHeight * MAX_SCALE); 8244 setForcedDisplaySizeLocked(displayContent, width, height); 8245 Settings.Global.putString(mContext.getContentResolver(), 8246 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 8247 } 8248 } 8249 } finally { 8250 Binder.restoreCallingIdentity(ident); 8251 } 8252 } 8253 8254 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 8255 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 8256 Settings.Global.DISPLAY_SIZE_FORCED); 8257 if (sizeStr == null || sizeStr.length() == 0) { 8258 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 8259 } 8260 if (sizeStr != null && sizeStr.length() > 0) { 8261 final int pos = sizeStr.indexOf(','); 8262 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 8263 int width, height; 8264 try { 8265 width = Integer.parseInt(sizeStr.substring(0, pos)); 8266 height = Integer.parseInt(sizeStr.substring(pos+1)); 8267 synchronized(displayContent.mDisplaySizeLock) { 8268 if (displayContent.mBaseDisplayWidth != width 8269 || displayContent.mBaseDisplayHeight != height) { 8270 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 8271 displayContent.mBaseDisplayWidth = width; 8272 displayContent.mBaseDisplayHeight = height; 8273 } 8274 } 8275 } catch (NumberFormatException ex) { 8276 } 8277 } 8278 } 8279 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 8280 Settings.Global.DISPLAY_DENSITY_FORCED); 8281 if (densityStr == null || densityStr.length() == 0) { 8282 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 8283 } 8284 if (densityStr != null && densityStr.length() > 0) { 8285 int density; 8286 try { 8287 density = Integer.parseInt(densityStr); 8288 synchronized(displayContent.mDisplaySizeLock) { 8289 if (displayContent.mBaseDisplayDensity != density) { 8290 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 8291 displayContent.mBaseDisplayDensity = density; 8292 } 8293 } 8294 } catch (NumberFormatException ex) { 8295 } 8296 } 8297 } 8298 8299 // displayContent must not be null 8300 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 8301 Slog.i(TAG, "Using new display size: " + width + "x" + height); 8302 8303 synchronized(displayContent.mDisplaySizeLock) { 8304 displayContent.mBaseDisplayWidth = width; 8305 displayContent.mBaseDisplayHeight = height; 8306 } 8307 reconfigureDisplayLocked(displayContent); 8308 } 8309 8310 @Override 8311 public void clearForcedDisplaySize(int displayId) { 8312 if (mContext.checkCallingOrSelfPermission( 8313 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8314 PackageManager.PERMISSION_GRANTED) { 8315 throw new SecurityException("Must hold permission " + 8316 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8317 } 8318 if (displayId != Display.DEFAULT_DISPLAY) { 8319 throw new IllegalArgumentException("Can only set the default display"); 8320 } 8321 final long ident = Binder.clearCallingIdentity(); 8322 try { 8323 synchronized(mWindowMap) { 8324 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8325 if (displayContent != null) { 8326 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 8327 displayContent.mInitialDisplayHeight); 8328 Settings.Global.putString(mContext.getContentResolver(), 8329 Settings.Global.DISPLAY_SIZE_FORCED, ""); 8330 } 8331 } 8332 } finally { 8333 Binder.restoreCallingIdentity(ident); 8334 } 8335 } 8336 8337 @Override 8338 public int getInitialDisplayDensity(int displayId) { 8339 synchronized (mWindowMap) { 8340 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8341 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8342 synchronized(displayContent.mDisplaySizeLock) { 8343 return displayContent.mInitialDisplayDensity; 8344 } 8345 } 8346 } 8347 return -1; 8348 } 8349 8350 @Override 8351 public int getBaseDisplayDensity(int displayId) { 8352 synchronized (mWindowMap) { 8353 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8354 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8355 synchronized(displayContent.mDisplaySizeLock) { 8356 return displayContent.mBaseDisplayDensity; 8357 } 8358 } 8359 } 8360 return -1; 8361 } 8362 8363 @Override 8364 public void setForcedDisplayDensity(int displayId, int density) { 8365 if (mContext.checkCallingOrSelfPermission( 8366 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8367 PackageManager.PERMISSION_GRANTED) { 8368 throw new SecurityException("Must hold permission " + 8369 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8370 } 8371 if (displayId != Display.DEFAULT_DISPLAY) { 8372 throw new IllegalArgumentException("Can only set the default display"); 8373 } 8374 final long ident = Binder.clearCallingIdentity(); 8375 try { 8376 synchronized(mWindowMap) { 8377 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8378 if (displayContent != null) { 8379 setForcedDisplayDensityLocked(displayContent, density); 8380 Settings.Global.putString(mContext.getContentResolver(), 8381 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 8382 } 8383 } 8384 } finally { 8385 Binder.restoreCallingIdentity(ident); 8386 } 8387 } 8388 8389 // displayContent must not be null 8390 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 8391 Slog.i(TAG, "Using new display density: " + density); 8392 8393 synchronized(displayContent.mDisplaySizeLock) { 8394 displayContent.mBaseDisplayDensity = density; 8395 } 8396 reconfigureDisplayLocked(displayContent); 8397 } 8398 8399 @Override 8400 public void clearForcedDisplayDensity(int displayId) { 8401 if (mContext.checkCallingOrSelfPermission( 8402 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8403 PackageManager.PERMISSION_GRANTED) { 8404 throw new SecurityException("Must hold permission " + 8405 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8406 } 8407 if (displayId != Display.DEFAULT_DISPLAY) { 8408 throw new IllegalArgumentException("Can only set the default display"); 8409 } 8410 final long ident = Binder.clearCallingIdentity(); 8411 try { 8412 synchronized(mWindowMap) { 8413 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8414 if (displayContent != null) { 8415 setForcedDisplayDensityLocked(displayContent, 8416 displayContent.mInitialDisplayDensity); 8417 Settings.Global.putString(mContext.getContentResolver(), 8418 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 8419 } 8420 } 8421 } finally { 8422 Binder.restoreCallingIdentity(ident); 8423 } 8424 } 8425 8426 // displayContent must not be null 8427 private void reconfigureDisplayLocked(DisplayContent displayContent) { 8428 // TODO: Multidisplay: for now only use with default display. 8429 configureDisplayPolicyLocked(displayContent); 8430 displayContent.layoutNeeded = true; 8431 8432 boolean configChanged = updateOrientationFromAppTokensLocked(false); 8433 mTempConfiguration.setToDefaults(); 8434 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 8435 if (computeScreenConfigurationLocked(mTempConfiguration)) { 8436 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 8437 configChanged = true; 8438 } 8439 } 8440 8441 if (configChanged) { 8442 mWaitingForConfig = true; 8443 startFreezingDisplayLocked(false, 0, 0); 8444 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8445 } 8446 8447 performLayoutAndPlaceSurfacesLocked(); 8448 } 8449 8450 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8451 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8452 displayContent.mBaseDisplayWidth, 8453 displayContent.mBaseDisplayHeight, 8454 displayContent.mBaseDisplayDensity); 8455 8456 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8457 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8458 displayInfo.overscanLeft, displayInfo.overscanTop, 8459 displayInfo.overscanRight, displayInfo.overscanBottom); 8460 } 8461 8462 @Override 8463 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8464 if (mContext.checkCallingOrSelfPermission( 8465 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8466 PackageManager.PERMISSION_GRANTED) { 8467 throw new SecurityException("Must hold permission " + 8468 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8469 } 8470 final long ident = Binder.clearCallingIdentity(); 8471 try { 8472 synchronized(mWindowMap) { 8473 DisplayContent displayContent = getDisplayContentLocked(displayId); 8474 if (displayContent != null) { 8475 setOverscanLocked(displayContent, left, top, right, bottom); 8476 } 8477 } 8478 } finally { 8479 Binder.restoreCallingIdentity(ident); 8480 } 8481 } 8482 8483 private void setOverscanLocked(DisplayContent displayContent, 8484 int left, int top, int right, int bottom) { 8485 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8486 synchronized (displayContent.mDisplaySizeLock) { 8487 displayInfo.overscanLeft = left; 8488 displayInfo.overscanTop = top; 8489 displayInfo.overscanRight = right; 8490 displayInfo.overscanBottom = bottom; 8491 } 8492 8493 mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, left, top, right, bottom); 8494 mDisplaySettings.writeSettingsLocked(); 8495 8496 reconfigureDisplayLocked(displayContent); 8497 } 8498 8499 // ------------------------------------------------------------- 8500 // Internals 8501 // ------------------------------------------------------------- 8502 8503 final WindowState windowForClientLocked(Session session, IWindow client, 8504 boolean throwOnError) { 8505 return windowForClientLocked(session, client.asBinder(), throwOnError); 8506 } 8507 8508 final WindowState windowForClientLocked(Session session, IBinder client, 8509 boolean throwOnError) { 8510 WindowState win = mWindowMap.get(client); 8511 if (localLOGV) Slog.v( 8512 TAG, "Looking up client " + client + ": " + win); 8513 if (win == null) { 8514 RuntimeException ex = new IllegalArgumentException( 8515 "Requested window " + client + " does not exist"); 8516 if (throwOnError) { 8517 throw ex; 8518 } 8519 Slog.w(TAG, "Failed looking up window", ex); 8520 return null; 8521 } 8522 if (session != null && win.mSession != session) { 8523 RuntimeException ex = new IllegalArgumentException( 8524 "Requested window " + client + " is in session " + 8525 win.mSession + ", not " + session); 8526 if (throwOnError) { 8527 throw ex; 8528 } 8529 Slog.w(TAG, "Failed looking up window", ex); 8530 return null; 8531 } 8532 8533 return win; 8534 } 8535 8536 final void rebuildAppWindowListLocked() { 8537 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8538 } 8539 8540 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8541 final WindowList windows = displayContent.getWindowList(); 8542 int NW = windows.size(); 8543 int i; 8544 int lastBelow = -1; 8545 int numRemoved = 0; 8546 8547 if (mRebuildTmp.length < NW) { 8548 mRebuildTmp = new WindowState[NW+10]; 8549 } 8550 8551 // First remove all existing app windows. 8552 i=0; 8553 while (i < NW) { 8554 WindowState w = windows.get(i); 8555 if (w.mAppToken != null) { 8556 WindowState win = windows.remove(i); 8557 win.mRebuilding = true; 8558 mRebuildTmp[numRemoved] = win; 8559 mWindowsChanged = true; 8560 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8561 NW--; 8562 numRemoved++; 8563 continue; 8564 } else if (lastBelow == i-1) { 8565 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8566 lastBelow = i; 8567 } 8568 } 8569 i++; 8570 } 8571 8572 // Keep whatever windows were below the app windows still below, 8573 // by skipping them. 8574 lastBelow++; 8575 i = lastBelow; 8576 8577 // First add all of the exiting app tokens... these are no longer 8578 // in the main app list, but still have windows shown. We put them 8579 // in the back because now that the animation is over we no longer 8580 // will care about them. 8581 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8582 final int numStacks = stacks.size(); 8583 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8584 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8585 int NT = exitingAppTokens.size(); 8586 for (int j = 0; j < NT; j++) { 8587 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8588 } 8589 } 8590 8591 // And add in the still active app tokens in Z order. 8592 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8593 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8594 final int numTasks = tasks.size(); 8595 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8596 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8597 final int numTokens = tokens.size(); 8598 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8599 final AppWindowToken wtoken = tokens.get(tokenNdx); 8600 if (wtoken.mDeferRemoval) { 8601 continue; 8602 } 8603 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8604 } 8605 } 8606 } 8607 8608 i -= lastBelow; 8609 if (i != numRemoved) { 8610 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8611 numRemoved + " windows but added " + i, 8612 new RuntimeException("here").fillInStackTrace()); 8613 for (i=0; i<numRemoved; i++) { 8614 WindowState ws = mRebuildTmp[i]; 8615 if (ws.mRebuilding) { 8616 StringWriter sw = new StringWriter(); 8617 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8618 ws.dump(pw, "", true); 8619 pw.flush(); 8620 Slog.w(TAG, "This window was lost: " + ws); 8621 Slog.w(TAG, sw.toString()); 8622 ws.mWinAnimator.destroySurfaceLocked(); 8623 } 8624 } 8625 Slog.w(TAG, "Current app token list:"); 8626 dumpAppTokensLocked(); 8627 Slog.w(TAG, "Final window list:"); 8628 dumpWindowsLocked(); 8629 } 8630 } 8631 8632 private final void assignLayersLocked(WindowList windows) { 8633 int N = windows.size(); 8634 int curBaseLayer = 0; 8635 int curLayer = 0; 8636 int i; 8637 8638 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8639 new RuntimeException("here").fillInStackTrace()); 8640 8641 boolean anyLayerChanged = false; 8642 8643 for (i=0; i<N; i++) { 8644 final WindowState w = windows.get(i); 8645 final WindowStateAnimator winAnimator = w.mWinAnimator; 8646 boolean layerChanged = false; 8647 int oldLayer = w.mLayer; 8648 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8649 || (i > 0 && w.mIsWallpaper)) { 8650 curLayer += WINDOW_LAYER_MULTIPLIER; 8651 w.mLayer = curLayer; 8652 } else { 8653 curBaseLayer = curLayer = w.mBaseLayer; 8654 w.mLayer = curLayer; 8655 } 8656 if (w.mLayer != oldLayer) { 8657 layerChanged = true; 8658 anyLayerChanged = true; 8659 } 8660 final AppWindowToken wtoken = w.mAppToken; 8661 oldLayer = winAnimator.mAnimLayer; 8662 if (w.mTargetAppToken != null) { 8663 winAnimator.mAnimLayer = 8664 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8665 } else if (wtoken != null) { 8666 winAnimator.mAnimLayer = 8667 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8668 } else { 8669 winAnimator.mAnimLayer = w.mLayer; 8670 } 8671 if (w.mIsImWindow) { 8672 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8673 } else if (w.mIsWallpaper) { 8674 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8675 } 8676 if (winAnimator.mAnimLayer != oldLayer) { 8677 layerChanged = true; 8678 anyLayerChanged = true; 8679 } 8680 final TaskStack stack = w.getStack(); 8681 if (layerChanged && stack != null && stack.isDimming(winAnimator)) { 8682 // Force an animation pass just to update the mDimLayer layer. 8683 scheduleAnimationLocked(); 8684 } 8685 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8686 + "mBase=" + w.mBaseLayer 8687 + " mLayer=" + w.mLayer 8688 + (wtoken == null ? 8689 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8690 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8691 //System.out.println( 8692 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8693 } 8694 8695 //TODO (multidisplay): Magnification is supported only for the default display. 8696 if (mAccessibilityController != null && anyLayerChanged 8697 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8698 mAccessibilityController.onWindowLayersChangedLocked(); 8699 } 8700 } 8701 8702 private final void performLayoutAndPlaceSurfacesLocked() { 8703 int loopCount = 6; 8704 do { 8705 mTraversalScheduled = false; 8706 performLayoutAndPlaceSurfacesLockedLoop(); 8707 mH.removeMessages(H.DO_TRAVERSAL); 8708 loopCount--; 8709 } while (mTraversalScheduled && loopCount > 0); 8710 mInnerFields.mWallpaperActionPending = false; 8711 } 8712 8713 private boolean mInLayout = false; 8714 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8715 if (mInLayout) { 8716 if (DEBUG) { 8717 throw new RuntimeException("Recursive call!"); 8718 } 8719 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8720 + Debug.getCallers(3)); 8721 return; 8722 } 8723 8724 if (mWaitingForConfig) { 8725 // Our configuration has changed (most likely rotation), but we 8726 // don't yet have the complete configuration to report to 8727 // applications. Don't do any window layout until we have it. 8728 return; 8729 } 8730 8731 if (!mDisplayReady) { 8732 // Not yet initialized, nothing to do. 8733 return; 8734 } 8735 8736 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8737 mInLayout = true; 8738 boolean recoveringMemory = false; 8739 8740 try { 8741 if (mForceRemoves != null) { 8742 recoveringMemory = true; 8743 // Wait a little bit for things to settle down, and off we go. 8744 for (int i=0; i<mForceRemoves.size(); i++) { 8745 WindowState ws = mForceRemoves.get(i); 8746 Slog.i(TAG, "Force removing: " + ws); 8747 removeWindowInnerLocked(ws.mSession, ws); 8748 } 8749 mForceRemoves = null; 8750 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8751 Object tmp = new Object(); 8752 synchronized (tmp) { 8753 try { 8754 tmp.wait(250); 8755 } catch (InterruptedException e) { 8756 } 8757 } 8758 } 8759 } catch (RuntimeException e) { 8760 Slog.wtf(TAG, "Unhandled exception while force removing for memory", e); 8761 } 8762 8763 try { 8764 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8765 8766 mInLayout = false; 8767 8768 if (needsLayout()) { 8769 if (++mLayoutRepeatCount < 6) { 8770 requestTraversalLocked(); 8771 } else { 8772 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8773 mLayoutRepeatCount = 0; 8774 } 8775 } else { 8776 mLayoutRepeatCount = 0; 8777 } 8778 8779 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8780 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8781 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8782 } 8783 } catch (RuntimeException e) { 8784 mInLayout = false; 8785 Slog.wtf(TAG, "Unhandled exception while laying out windows", e); 8786 } 8787 8788 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8789 } 8790 8791 private final void performLayoutLockedInner(final DisplayContent displayContent, 8792 boolean initial, boolean updateInputWindows) { 8793 if (!displayContent.layoutNeeded) { 8794 return; 8795 } 8796 displayContent.layoutNeeded = false; 8797 WindowList windows = displayContent.getWindowList(); 8798 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8799 8800 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8801 final int dw = displayInfo.logicalWidth; 8802 final int dh = displayInfo.logicalHeight; 8803 8804 final int NFW = mFakeWindows.size(); 8805 for (int i=0; i<NFW; i++) { 8806 mFakeWindows.get(i).layout(dw, dh); 8807 } 8808 8809 final int N = windows.size(); 8810 int i; 8811 8812 if (DEBUG_LAYOUT) { 8813 Slog.v(TAG, "-------------------------------------"); 8814 Slog.v(TAG, "performLayout: needed=" 8815 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8816 } 8817 8818 WindowStateAnimator universeBackground = null; 8819 8820 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8821 if (isDefaultDisplay) { 8822 // Not needed on non-default displays. 8823 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8824 mScreenRect.set(0, 0, dw, dh); 8825 } 8826 8827 mPolicy.getContentRectLw(mTmpContentRect); 8828 displayContent.resize(mTmpContentRect); 8829 8830 int seq = mLayoutSeq+1; 8831 if (seq < 0) seq = 0; 8832 mLayoutSeq = seq; 8833 8834 boolean behindDream = false; 8835 8836 // First perform layout of any root windows (not attached 8837 // to another window). 8838 int topAttached = -1; 8839 for (i = N-1; i >= 0; i--) { 8840 final WindowState win = windows.get(i); 8841 8842 // Don't do layout of a window if it is not visible, or 8843 // soon won't be visible, to avoid wasting time and funky 8844 // changes while a window is animating away. 8845 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8846 || win.isGoneForLayoutLw(); 8847 8848 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8849 Slog.v(TAG, "1ST PASS " + win 8850 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8851 + " mLayoutAttached=" + win.mLayoutAttached 8852 + " screen changed=" + win.isConfigChanged()); 8853 final AppWindowToken atoken = win.mAppToken; 8854 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8855 + win.mViewVisibility + " mRelayoutCalled=" 8856 + win.mRelayoutCalled + " hidden=" 8857 + win.mRootToken.hidden + " hiddenRequested=" 8858 + (atoken != null && atoken.hiddenRequested) 8859 + " mAttachedHidden=" + win.mAttachedHidden); 8860 else Slog.v(TAG, " VIS: mViewVisibility=" 8861 + win.mViewVisibility + " mRelayoutCalled=" 8862 + win.mRelayoutCalled + " hidden=" 8863 + win.mRootToken.hidden + " hiddenRequested=" 8864 + (atoken != null && atoken.hiddenRequested) 8865 + " mAttachedHidden=" + win.mAttachedHidden); 8866 } 8867 8868 // If this view is GONE, then skip it -- keep the current 8869 // frame, and let the caller know so they can ignore it 8870 // if they want. (We do the normal layout for INVISIBLE 8871 // windows, since that means "perform layout as normal, 8872 // just don't display"). 8873 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8874 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8875 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 8876 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8877 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8878 if (!win.mLayoutAttached) { 8879 if (initial) { 8880 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8881 win.mContentChanged = false; 8882 } 8883 if (win.mAttrs.type == TYPE_DREAM) { 8884 // Don't layout windows behind a dream, so that if it 8885 // does stuff like hide the status bar we won't get a 8886 // bad transition when it goes away. 8887 behindDream = true; 8888 } 8889 win.mLayoutNeeded = false; 8890 win.prelayout(); 8891 mPolicy.layoutWindowLw(win, null); 8892 win.mLayoutSeq = seq; 8893 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8894 + win.mFrame + " mContainingFrame=" 8895 + win.mContainingFrame + " mDisplayFrame=" 8896 + win.mDisplayFrame); 8897 } else { 8898 if (topAttached < 0) topAttached = i; 8899 } 8900 } 8901 if (win.mViewVisibility == View.VISIBLE 8902 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8903 && universeBackground == null) { 8904 universeBackground = win.mWinAnimator; 8905 } 8906 } 8907 8908 if (mAnimator.mUniverseBackground != universeBackground) { 8909 mFocusMayChange = true; 8910 mAnimator.mUniverseBackground = universeBackground; 8911 } 8912 8913 boolean attachedBehindDream = false; 8914 8915 // Now perform layout of attached windows, which usually 8916 // depend on the position of the window they are attached to. 8917 // XXX does not deal with windows that are attached to windows 8918 // that are themselves attached. 8919 for (i = topAttached; i >= 0; i--) { 8920 final WindowState win = windows.get(i); 8921 8922 if (win.mLayoutAttached) { 8923 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8924 + " mHaveFrame=" + win.mHaveFrame 8925 + " mViewVisibility=" + win.mViewVisibility 8926 + " mRelayoutCalled=" + win.mRelayoutCalled); 8927 // If this view is GONE, then skip it -- keep the current 8928 // frame, and let the caller know so they can ignore it 8929 // if they want. (We do the normal layout for INVISIBLE 8930 // windows, since that means "perform layout as normal, 8931 // just don't display"). 8932 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8933 continue; 8934 } 8935 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8936 || !win.mHaveFrame || win.mLayoutNeeded) { 8937 if (initial) { 8938 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8939 win.mContentChanged = false; 8940 } 8941 win.mLayoutNeeded = false; 8942 win.prelayout(); 8943 mPolicy.layoutWindowLw(win, win.mAttachedWindow); 8944 win.mLayoutSeq = seq; 8945 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8946 + win.mFrame + " mContainingFrame=" 8947 + win.mContainingFrame + " mDisplayFrame=" 8948 + win.mDisplayFrame); 8949 } 8950 } else if (win.mAttrs.type == TYPE_DREAM) { 8951 // Don't layout windows behind a dream, so that if it 8952 // does stuff like hide the status bar we won't get a 8953 // bad transition when it goes away. 8954 attachedBehindDream = behindDream; 8955 } 8956 } 8957 8958 // Window frames may have changed. Tell the input dispatcher about it. 8959 mInputMonitor.setUpdateInputWindowsNeededLw(); 8960 if (updateInputWindows) { 8961 mInputMonitor.updateInputWindowsLw(false /*force*/); 8962 } 8963 8964 mPolicy.finishLayoutLw(); 8965 } 8966 8967 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8968 // If the screen is currently frozen or off, then keep 8969 // it frozen/off until this window draws at its new 8970 // orientation. 8971 if (!okToDisplay()) { 8972 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8973 w.mOrientationChanging = true; 8974 w.mLastFreezeDuration = 0; 8975 mInnerFields.mOrientationChangeComplete = false; 8976 if (!mWindowsFreezingScreen) { 8977 mWindowsFreezingScreen = true; 8978 // XXX should probably keep timeout from 8979 // when we first froze the display. 8980 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8981 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8982 WINDOW_FREEZE_TIMEOUT_DURATION); 8983 } 8984 } 8985 } 8986 8987 /** 8988 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8989 * @param windows List of windows on default display. 8990 * @return bitmap indicating if another pass through layout must be made. 8991 */ 8992 public int handleAppTransitionReadyLocked(WindowList windows) { 8993 int changes = 0; 8994 int i; 8995 int NN = mOpeningApps.size(); 8996 boolean goodToGo = true; 8997 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8998 "Checking " + NN + " opening apps (frozen=" 8999 + mDisplayFrozen + " timeout=" 9000 + mAppTransition.isTimeout() + ")..."); 9001 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 9002 // If the display isn't frozen, wait to do anything until 9003 // all of the apps are ready. Otherwise just go because 9004 // we'll unfreeze the display when everyone is ready. 9005 for (i=0; i<NN && goodToGo; i++) { 9006 AppWindowToken wtoken = mOpeningApps.valueAt(i); 9007 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 9008 "Check opening app=" + wtoken + ": allDrawn=" 9009 + wtoken.allDrawn + " startingDisplayed=" 9010 + wtoken.startingDisplayed + " startingMoved=" 9011 + wtoken.startingMoved); 9012 if (!wtoken.allDrawn && !wtoken.startingDisplayed 9013 && !wtoken.startingMoved) { 9014 goodToGo = false; 9015 } 9016 } 9017 } 9018 if (goodToGo) { 9019 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 9020 int transit = mAppTransition.getAppTransition(); 9021 if (mSkipAppTransitionAnimation) { 9022 transit = AppTransition.TRANSIT_UNSET; 9023 } 9024 mAppTransition.goodToGo(); 9025 mStartingIconInTransition = false; 9026 mSkipAppTransitionAnimation = false; 9027 9028 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 9029 9030 rebuildAppWindowListLocked(); 9031 9032 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 9033 WindowState oldWallpaper = 9034 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 9035 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 9036 ? null : mWallpaperTarget; 9037 9038 mInnerFields.mWallpaperMayChange = false; 9039 9040 // The top-most window will supply the layout params, 9041 // and we will determine it below. 9042 LayoutParams animLp = null; 9043 int bestAnimLayer = -1; 9044 boolean fullscreenAnim = false; 9045 boolean voiceInteraction = false; 9046 9047 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 9048 "New wallpaper target=" + mWallpaperTarget 9049 + ", oldWallpaper=" + oldWallpaper 9050 + ", lower target=" + mLowerWallpaperTarget 9051 + ", upper target=" + mUpperWallpaperTarget); 9052 9053 boolean openingAppHasWallpaper = false; 9054 boolean closingAppHasWallpaper = false; 9055 final AppWindowToken lowerWallpaperAppToken; 9056 final AppWindowToken upperWallpaperAppToken; 9057 if (mLowerWallpaperTarget == null) { 9058 lowerWallpaperAppToken = upperWallpaperAppToken = null; 9059 } else { 9060 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 9061 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 9062 } 9063 9064 // Do a first pass through the tokens for two 9065 // things: 9066 // (1) Determine if both the closing and opening 9067 // app token sets are wallpaper targets, in which 9068 // case special animations are needed 9069 // (since the wallpaper needs to stay static 9070 // behind them). 9071 // (2) Find the layout params of the top-most 9072 // application window in the tokens, which is 9073 // what will control the animation theme. 9074 final int NC = mClosingApps.size(); 9075 NN = NC + mOpeningApps.size(); 9076 for (i=0; i<NN; i++) { 9077 final AppWindowToken wtoken; 9078 if (i < NC) { 9079 wtoken = mClosingApps.valueAt(i); 9080 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 9081 closingAppHasWallpaper = true; 9082 } 9083 } else { 9084 wtoken = mOpeningApps.valueAt(i - NC); 9085 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 9086 openingAppHasWallpaper = true; 9087 } 9088 } 9089 9090 voiceInteraction |= wtoken.voiceInteraction; 9091 9092 if (wtoken.appFullscreen) { 9093 WindowState ws = wtoken.findMainWindow(); 9094 if (ws != null) { 9095 animLp = ws.mAttrs; 9096 bestAnimLayer = ws.mLayer; 9097 fullscreenAnim = true; 9098 } 9099 } else if (!fullscreenAnim) { 9100 WindowState ws = wtoken.findMainWindow(); 9101 if (ws != null) { 9102 if (ws.mLayer > bestAnimLayer) { 9103 animLp = ws.mAttrs; 9104 bestAnimLayer = ws.mLayer; 9105 } 9106 } 9107 } 9108 } 9109 9110 mAnimateWallpaperWithTarget = false; 9111 if (closingAppHasWallpaper && openingAppHasWallpaper) { 9112 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 9113 switch (transit) { 9114 case AppTransition.TRANSIT_ACTIVITY_OPEN: 9115 case AppTransition.TRANSIT_TASK_OPEN: 9116 case AppTransition.TRANSIT_TASK_TO_FRONT: 9117 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 9118 break; 9119 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 9120 case AppTransition.TRANSIT_TASK_CLOSE: 9121 case AppTransition.TRANSIT_TASK_TO_BACK: 9122 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 9123 break; 9124 } 9125 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 9126 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 9127 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 9128 // We are transitioning from an activity with 9129 // a wallpaper to one without. 9130 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 9131 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 9132 "New transit away from wallpaper: " + transit); 9133 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 9134 // We are transitioning from an activity without 9135 // a wallpaper to now showing the wallpaper 9136 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 9137 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 9138 "New transit into wallpaper: " + transit); 9139 } else { 9140 mAnimateWallpaperWithTarget = true; 9141 } 9142 9143 // If all closing windows are obscured, then there is 9144 // no need to do an animation. This is the case, for 9145 // example, when this transition is being done behind 9146 // the lock screen. 9147 if (!mPolicy.allowAppAnimationsLw()) { 9148 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 9149 "Animations disallowed by keyguard or dream."); 9150 animLp = null; 9151 } 9152 9153 AppWindowToken topOpeningApp = null; 9154 AppWindowToken topClosingApp = null; 9155 int topOpeningLayer = 0; 9156 int topClosingLayer = 0; 9157 9158 // Process all applications animating in place 9159 if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) { 9160 // Find the focused window 9161 final WindowState win = 9162 findFocusedWindowLocked(getDefaultDisplayContentLocked()); 9163 if (win != null) { 9164 final AppWindowToken wtoken = win.mAppToken; 9165 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 9166 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken); 9167 appAnimator.clearThumbnail(); 9168 appAnimator.animation = null; 9169 updateTokenInPlaceLocked(wtoken, transit); 9170 wtoken.updateReportedVisibilityLocked(); 9171 9172 appAnimator.mAllAppWinAnimators.clear(); 9173 final int N = wtoken.allAppWindows.size(); 9174 for (int j = 0; j < N; j++) { 9175 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 9176 } 9177 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 9178 } 9179 } 9180 9181 NN = mOpeningApps.size(); 9182 for (i=0; i<NN; i++) { 9183 AppWindowToken wtoken = mOpeningApps.valueAt(i); 9184 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 9185 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 9186 appAnimator.clearThumbnail(); 9187 appAnimator.animation = null; 9188 wtoken.inPendingTransaction = false; 9189 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction); 9190 wtoken.updateReportedVisibilityLocked(); 9191 wtoken.waitingToShow = false; 9192 9193 appAnimator.mAllAppWinAnimators.clear(); 9194 final int N = wtoken.allAppWindows.size(); 9195 for (int j = 0; j < N; j++) { 9196 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 9197 } 9198 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 9199 9200 if (animLp != null) { 9201 int layer = -1; 9202 for (int j=0; j<wtoken.windows.size(); j++) { 9203 WindowState win = wtoken.windows.get(j); 9204 if (win.mWinAnimator.mAnimLayer > layer) { 9205 layer = win.mWinAnimator.mAnimLayer; 9206 } 9207 } 9208 if (topOpeningApp == null || layer > topOpeningLayer) { 9209 topOpeningApp = wtoken; 9210 topOpeningLayer = layer; 9211 } 9212 } 9213 } 9214 NN = mClosingApps.size(); 9215 for (i=0; i<NN; i++) { 9216 AppWindowToken wtoken = mClosingApps.valueAt(i); 9217 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 9218 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 9219 appAnimator.clearThumbnail(); 9220 appAnimator.animation = null; 9221 wtoken.inPendingTransaction = false; 9222 setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction); 9223 wtoken.updateReportedVisibilityLocked(); 9224 wtoken.waitingToHide = false; 9225 // Force the allDrawn flag, because we want to start 9226 // this guy's animations regardless of whether it's 9227 // gotten drawn. 9228 wtoken.allDrawn = true; 9229 wtoken.deferClearAllDrawn = false; 9230 // Ensure that apps that are mid-starting are also scheduled to have their 9231 // starting windows removed after the animation is complete 9232 if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) { 9233 scheduleRemoveStartingWindowLocked(wtoken); 9234 } 9235 9236 if (animLp != null) { 9237 int layer = -1; 9238 for (int j=0; j<wtoken.windows.size(); j++) { 9239 WindowState win = wtoken.windows.get(j); 9240 if (win.mWinAnimator.mAnimLayer > layer) { 9241 layer = win.mWinAnimator.mAnimLayer; 9242 } 9243 } 9244 if (topClosingApp == null || layer > topClosingLayer) { 9245 topClosingApp = wtoken; 9246 topClosingLayer = layer; 9247 } 9248 } 9249 } 9250 9251 AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null : 9252 topOpeningApp.mAppAnimator; 9253 AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null : 9254 topClosingApp.mAppAnimator; 9255 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 9256 if (nextAppTransitionThumbnail != null 9257 && openingAppAnimator != null && openingAppAnimator.animation != null && 9258 nextAppTransitionThumbnail.getConfig() != Config.ALPHA_8) { 9259 // This thumbnail animation is very special, we need to have 9260 // an extra surface with the thumbnail included with the animation. 9261 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 9262 nextAppTransitionThumbnail.getHeight()); 9263 try { 9264 // TODO(multi-display): support other displays 9265 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9266 final Display display = displayContent.getDisplay(); 9267 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9268 9269 // Create a new surface for the thumbnail 9270 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 9271 "thumbnail anim", dirty.width(), dirty.height(), 9272 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 9273 surfaceControl.setLayerStack(display.getLayerStack()); 9274 if (SHOW_TRANSACTIONS) { 9275 Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 9276 } 9277 9278 // Draw the thumbnail onto the surface 9279 Surface drawSurface = new Surface(); 9280 drawSurface.copyFrom(surfaceControl); 9281 Canvas c = drawSurface.lockCanvas(dirty); 9282 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 9283 drawSurface.unlockCanvasAndPost(c); 9284 drawSurface.release(); 9285 9286 // Get the thumbnail animation 9287 Animation anim; 9288 if (mAppTransition.isNextThumbnailTransitionAspectScaled()) { 9289 // For the new aspect-scaled transition, we want it to always show 9290 // above the animating opening/closing window, and we want to 9291 // synchronize its thumbnail surface with the surface for the 9292 // open/close animation (only on the way down) 9293 anim = mAppTransition.createThumbnailAspectScaleAnimationLocked( 9294 displayInfo.appWidth, displayInfo.appHeight, 9295 displayInfo.logicalWidth, transit); 9296 openingAppAnimator.thumbnailForceAboveLayer = Math.max(topOpeningLayer, 9297 topClosingLayer); 9298 openingAppAnimator.deferThumbnailDestruction = 9299 !mAppTransition.isNextThumbnailTransitionScaleUp(); 9300 } else { 9301 anim = mAppTransition.createThumbnailScaleAnimationLocked( 9302 displayInfo.appWidth, displayInfo.appHeight, transit); 9303 } 9304 anim.restrictDuration(MAX_ANIMATION_DURATION); 9305 anim.scaleCurrentDuration(getTransitionAnimationScaleLocked()); 9306 9307 openingAppAnimator.thumbnail = surfaceControl; 9308 openingAppAnimator.thumbnailLayer = topOpeningLayer; 9309 openingAppAnimator.thumbnailAnimation = anim; 9310 openingAppAnimator.thumbnailX = mAppTransition.getStartingX(); 9311 openingAppAnimator.thumbnailY = mAppTransition.getStartingY(); 9312 } catch (OutOfResourcesException e) { 9313 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 9314 + " h=" + dirty.height(), e); 9315 openingAppAnimator.clearThumbnail(); 9316 } 9317 } 9318 9319 mAppTransition.postAnimationCallback(); 9320 mAppTransition.clear(); 9321 9322 mOpeningApps.clear(); 9323 mClosingApps.clear(); 9324 9325 // This has changed the visibility of windows, so perform 9326 // a new layout to get them all up-to-date. 9327 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 9328 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 9329 getDefaultDisplayContentLocked().layoutNeeded = true; 9330 9331 // TODO(multidisplay): IMEs are only supported on the default display. 9332 if (windows == getDefaultWindowListLocked() 9333 && !moveInputMethodWindowsIfNeededLocked(true)) { 9334 assignLayersLocked(windows); 9335 } 9336 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/); 9337 mFocusMayChange = false; 9338 notifyActivityDrawnForKeyguard(); 9339 } 9340 9341 return changes; 9342 } 9343 9344 /** 9345 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 9346 * @return bitmap indicating if another pass through layout must be made. 9347 */ 9348 private int handleAnimatingStoppedAndTransitionLocked() { 9349 int changes = 0; 9350 9351 mAppTransition.setIdle(); 9352 // Restore window app tokens to the ActivityManager views 9353 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 9354 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9355 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9356 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9357 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9358 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9359 tokens.get(tokenNdx).sendingToBottom = false; 9360 } 9361 } 9362 } 9363 rebuildAppWindowListLocked(); 9364 9365 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 9366 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9367 "Wallpaper layer changed: assigning layers + relayout"); 9368 moveInputMethodWindowsIfNeededLocked(true); 9369 mInnerFields.mWallpaperMayChange = true; 9370 // Since the window list has been rebuilt, focus might 9371 // have to be recomputed since the actual order of windows 9372 // might have changed again. 9373 mFocusMayChange = true; 9374 9375 return changes; 9376 } 9377 9378 private void updateResizingWindows(final WindowState w) { 9379 final WindowStateAnimator winAnimator = w.mWinAnimator; 9380 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 9381 w.setInsetsChanged(); 9382 boolean configChanged = w.isConfigChanged(); 9383 if (DEBUG_CONFIGURATION && configChanged) { 9384 Slog.v(TAG, "Win " + w + " config changed: " 9385 + mCurConfiguration); 9386 } 9387 if (localLOGV) Slog.v(TAG, "Resizing " + w 9388 + ": configChanged=" + configChanged 9389 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 9390 w.mLastFrame.set(w.mFrame); 9391 if (w.mContentInsetsChanged 9392 || w.mVisibleInsetsChanged 9393 || winAnimator.mSurfaceResized 9394 || configChanged) { 9395 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 9396 Slog.v(TAG, "Resize reasons for w=" + w + ": " 9397 + " contentInsetsChanged=" + w.mContentInsetsChanged 9398 + " " + w.mContentInsets.toShortString() 9399 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 9400 + " " + w.mVisibleInsets.toShortString() 9401 + " stableInsetsChanged=" + w.mStableInsetsChanged 9402 + " " + w.mStableInsets.toShortString() 9403 + " surfaceResized=" + winAnimator.mSurfaceResized 9404 + " configChanged=" + configChanged); 9405 } 9406 9407 w.mLastOverscanInsets.set(w.mOverscanInsets); 9408 w.mLastContentInsets.set(w.mContentInsets); 9409 w.mLastVisibleInsets.set(w.mVisibleInsets); 9410 w.mLastStableInsets.set(w.mStableInsets); 9411 makeWindowFreezingScreenIfNeededLocked(w); 9412 // If the orientation is changing, then we need to 9413 // hold off on unfreezing the display until this 9414 // window has been redrawn; to do that, we need 9415 // to go through the process of getting informed 9416 // by the application when it has finished drawing. 9417 if (w.mOrientationChanging) { 9418 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 9419 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 9420 + w + ", surface " + winAnimator.mSurfaceControl); 9421 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 9422 if (w.mAppToken != null) { 9423 w.mAppToken.allDrawn = false; 9424 w.mAppToken.deferClearAllDrawn = false; 9425 } 9426 } 9427 if (!mResizingWindows.contains(w)) { 9428 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 9429 "Resizing window " + w + " to " + winAnimator.mSurfaceW 9430 + "x" + winAnimator.mSurfaceH); 9431 mResizingWindows.add(w); 9432 } 9433 } else if (w.mOrientationChanging) { 9434 if (w.isDrawnLw()) { 9435 if (DEBUG_ORIENTATION) Slog.v(TAG, 9436 "Orientation not waiting for draw in " 9437 + w + ", surface " + winAnimator.mSurfaceControl); 9438 w.mOrientationChanging = false; 9439 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 9440 - mDisplayFreezeTime); 9441 } 9442 } 9443 } 9444 } 9445 9446 /** 9447 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 9448 * 9449 * @param w WindowState this method is applied to. 9450 * @param currentTime The time which animations use for calculating transitions. 9451 * @param innerDw Width of app window. 9452 * @param innerDh Height of app window. 9453 */ 9454 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 9455 final int innerDw, final int innerDh) { 9456 final WindowManager.LayoutParams attrs = w.mAttrs; 9457 final int attrFlags = attrs.flags; 9458 final boolean canBeSeen = w.isDisplayedLw(); 9459 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 9460 9461 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 9462 // This window completely covers everything behind it, 9463 // so we want to leave all of them as undimmed (for 9464 // performance reasons). 9465 mInnerFields.mObscured = true; 9466 } 9467 9468 if (w.mHasSurface) { 9469 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 9470 mInnerFields.mHoldScreen = w.mSession; 9471 } 9472 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 9473 && mInnerFields.mScreenBrightness < 0) { 9474 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 9475 } 9476 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 9477 && mInnerFields.mButtonBrightness < 0) { 9478 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 9479 } 9480 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 9481 && mInnerFields.mUserActivityTimeout < 0) { 9482 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 9483 } 9484 9485 final int type = attrs.type; 9486 if (canBeSeen 9487 && (type == TYPE_SYSTEM_DIALOG 9488 || type == TYPE_SYSTEM_ERROR 9489 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { 9490 mInnerFields.mSyswin = true; 9491 } 9492 9493 if (canBeSeen) { 9494 // This function assumes that the contents of the default display are 9495 // processed first before secondary displays. 9496 final DisplayContent displayContent = w.getDisplayContent(); 9497 if (displayContent != null && displayContent.isDefaultDisplay) { 9498 // While a dream or keyguard is showing, obscure ordinary application 9499 // content on secondary displays (by forcibly enabling mirroring unless 9500 // there is other content we want to show) but still allow opaque 9501 // keyguard dialogs to be shown. 9502 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 9503 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 9504 } 9505 mInnerFields.mDisplayHasContent = true; 9506 } else if (displayContent != null && 9507 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 9508 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 9509 // Allow full screen keyguard presentation dialogs to be seen. 9510 mInnerFields.mDisplayHasContent = true; 9511 } 9512 if (mInnerFields.mPreferredRefreshRate == 0 9513 && w.mAttrs.preferredRefreshRate != 0) { 9514 mInnerFields.mPreferredRefreshRate = w.mAttrs.preferredRefreshRate; 9515 } 9516 } 9517 } 9518 } 9519 9520 private void handleFlagDimBehind(WindowState w) { 9521 final WindowManager.LayoutParams attrs = w.mAttrs; 9522 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 9523 && w.isDisplayedLw() 9524 && !w.mExiting) { 9525 final WindowStateAnimator winAnimator = w.mWinAnimator; 9526 final TaskStack stack = w.getStack(); 9527 if (stack == null) { 9528 return; 9529 } 9530 stack.setDimmingTag(); 9531 if (!stack.isDimming(winAnimator)) { 9532 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 9533 stack.startDimmingIfNeeded(winAnimator); 9534 } 9535 } 9536 } 9537 9538 private void updateAllDrawnLocked(DisplayContent displayContent) { 9539 // See if any windows have been drawn, so they (and others 9540 // associated with them) can now be shown. 9541 ArrayList<TaskStack> stacks = displayContent.getStacks(); 9542 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9543 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9544 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9545 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9546 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9547 final AppWindowToken wtoken = tokens.get(tokenNdx); 9548 if (!wtoken.allDrawn) { 9549 int numInteresting = wtoken.numInterestingWindows; 9550 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 9551 if (DEBUG_VISIBILITY) Slog.v(TAG, 9552 "allDrawn: " + wtoken 9553 + " interesting=" + numInteresting 9554 + " drawn=" + wtoken.numDrawnWindows); 9555 wtoken.allDrawn = true; 9556 // Force an additional layout pass where WindowStateAnimator# 9557 // commitFinishDrawingLocked() will call performShowLocked(). 9558 displayContent.layoutNeeded = true; 9559 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9560 } 9561 } 9562 } 9563 } 9564 } 9565 } 9566 9567 // "Something has changed! Let's make it correct now." 9568 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9569 if (DEBUG_WINDOW_TRACE) { 9570 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9571 + Debug.getCallers(3)); 9572 } 9573 9574 final long currentTime = SystemClock.uptimeMillis(); 9575 9576 int i; 9577 boolean updateInputWindowsNeeded = false; 9578 9579 if (mFocusMayChange) { 9580 mFocusMayChange = false; 9581 updateInputWindowsNeeded = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9582 false /*updateInputWindows*/); 9583 } 9584 9585 // Initialize state of exiting tokens. 9586 final int numDisplays = mDisplayContents.size(); 9587 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9588 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9589 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9590 displayContent.mExitingTokens.get(i).hasVisible = false; 9591 } 9592 } 9593 9594 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9595 // Initialize state of exiting applications. 9596 final AppTokenList exitingAppTokens = 9597 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9598 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9599 exitingAppTokens.get(tokenNdx).hasVisible = false; 9600 } 9601 } 9602 9603 mInnerFields.mHoldScreen = null; 9604 mInnerFields.mScreenBrightness = -1; 9605 mInnerFields.mButtonBrightness = -1; 9606 mInnerFields.mUserActivityTimeout = -1; 9607 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9608 9609 mTransactionSequence++; 9610 9611 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9612 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9613 final int defaultDw = defaultInfo.logicalWidth; 9614 final int defaultDh = defaultInfo.logicalHeight; 9615 9616 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9617 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9618 SurfaceControl.openTransaction(); 9619 try { 9620 9621 if (mWatermark != null) { 9622 mWatermark.positionSurface(defaultDw, defaultDh); 9623 } 9624 if (mStrictModeFlash != null) { 9625 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9626 } 9627 if (mCircularDisplayMask != null) { 9628 mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation); 9629 } 9630 if (mEmulatorDisplayOverlay != null) { 9631 mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, mRotation); 9632 } 9633 9634 boolean focusDisplayed = false; 9635 9636 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9637 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9638 boolean updateAllDrawn = false; 9639 WindowList windows = displayContent.getWindowList(); 9640 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9641 final int displayId = displayContent.getDisplayId(); 9642 final int dw = displayInfo.logicalWidth; 9643 final int dh = displayInfo.logicalHeight; 9644 final int innerDw = displayInfo.appWidth; 9645 final int innerDh = displayInfo.appHeight; 9646 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9647 9648 // Reset for each display. 9649 mInnerFields.mDisplayHasContent = false; 9650 mInnerFields.mPreferredRefreshRate = 0; 9651 9652 int repeats = 0; 9653 do { 9654 repeats++; 9655 if (repeats > 6) { 9656 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9657 displayContent.layoutNeeded = false; 9658 break; 9659 } 9660 9661 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9662 displayContent.pendingLayoutChanges); 9663 9664 if ((displayContent.pendingLayoutChanges & 9665 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9666 (adjustWallpaperWindowsLocked() & 9667 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9668 assignLayersLocked(windows); 9669 displayContent.layoutNeeded = true; 9670 } 9671 9672 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9673 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9674 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9675 if (updateOrientationFromAppTokensLocked(true)) { 9676 displayContent.layoutNeeded = true; 9677 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9678 } 9679 } 9680 9681 if ((displayContent.pendingLayoutChanges 9682 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9683 displayContent.layoutNeeded = true; 9684 } 9685 9686 // FIRST LOOP: Perform a layout, if needed. 9687 if (repeats < 4) { 9688 performLayoutLockedInner(displayContent, repeats == 1, 9689 false /*updateInputWindows*/); 9690 } else { 9691 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9692 } 9693 9694 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9695 // it is animating. 9696 displayContent.pendingLayoutChanges = 0; 9697 9698 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9699 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9700 9701 if (isDefaultDisplay) { 9702 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9703 for (i = windows.size() - 1; i >= 0; i--) { 9704 WindowState w = windows.get(i); 9705 if (w.mHasSurface) { 9706 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.mAttachedWindow); 9707 } 9708 } 9709 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9710 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9711 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9712 } 9713 } while (displayContent.pendingLayoutChanges != 0); 9714 9715 mInnerFields.mObscured = false; 9716 mInnerFields.mSyswin = false; 9717 displayContent.resetDimming(); 9718 9719 // Only used if default window 9720 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9721 9722 final int N = windows.size(); 9723 for (i=N-1; i>=0; i--) { 9724 WindowState w = windows.get(i); 9725 final TaskStack stack = w.getStack(); 9726 if (stack == null && w.getAttrs().type != TYPE_PRIVATE_PRESENTATION) { 9727 continue; 9728 } 9729 9730 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9731 9732 // Update effect. 9733 w.mObscured = mInnerFields.mObscured; 9734 if (!mInnerFields.mObscured) { 9735 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9736 } 9737 9738 if (stack != null && !stack.testDimmingTag()) { 9739 handleFlagDimBehind(w); 9740 } 9741 9742 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9743 && w.isVisibleLw()) { 9744 // This is the wallpaper target and its obscured state 9745 // changed... make sure the current wallaper's visibility 9746 // has been updated accordingly. 9747 updateWallpaperVisibilityLocked(); 9748 } 9749 9750 final WindowStateAnimator winAnimator = w.mWinAnimator; 9751 9752 // If the window has moved due to its containing 9753 // content frame changing, then we'd like to animate 9754 // it. 9755 if (w.mHasSurface && w.shouldAnimateMove()) { 9756 // Frame has moved, containing content frame 9757 // has also moved, and we're not currently animating... 9758 // let's do something. 9759 Animation a = AnimationUtils.loadAnimation(mContext, 9760 com.android.internal.R.anim.window_move_from_decor); 9761 winAnimator.setAnimation(a); 9762 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9763 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9764 9765 //TODO (multidisplay): Accessibility supported only for the default display. 9766 if (mAccessibilityController != null 9767 && displayId == Display.DEFAULT_DISPLAY) { 9768 mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 9769 } 9770 9771 try { 9772 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9773 } catch (RemoteException e) { 9774 } 9775 } 9776 9777 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9778 w.mContentChanged = false; 9779 9780 // Moved from updateWindowsAndWallpaperLocked(). 9781 if (w.mHasSurface && !w.isHiddenFromUserLocked()) { 9782 // Take care of the window being ready to display. 9783 final boolean committed = 9784 winAnimator.commitFinishDrawingLocked(currentTime); 9785 if (isDefaultDisplay && committed) { 9786 if (w.mAttrs.type == TYPE_DREAM) { 9787 // HACK: When a dream is shown, it may at that 9788 // point hide the lock screen. So we need to 9789 // redo the layout to let the phone window manager 9790 // make this happen. 9791 displayContent.pendingLayoutChanges |= 9792 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9793 if (DEBUG_LAYOUT_REPEATS) { 9794 debugLayoutRepeats( 9795 "dream and commitFinishDrawingLocked true", 9796 displayContent.pendingLayoutChanges); 9797 } 9798 } 9799 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9800 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9801 "First draw done in potential wallpaper target " + w); 9802 mInnerFields.mWallpaperMayChange = true; 9803 displayContent.pendingLayoutChanges |= 9804 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9805 if (DEBUG_LAYOUT_REPEATS) { 9806 debugLayoutRepeats( 9807 "wallpaper and commitFinishDrawingLocked true", 9808 displayContent.pendingLayoutChanges); 9809 } 9810 } 9811 } 9812 9813 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9814 9815 final AppWindowToken atoken = w.mAppToken; 9816 if (DEBUG_STARTING_WINDOW && atoken != null 9817 && w == atoken.startingWindow) { 9818 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9819 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9820 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9821 } 9822 if (atoken != null 9823 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9824 if (atoken.lastTransactionSequence != mTransactionSequence) { 9825 atoken.lastTransactionSequence = mTransactionSequence; 9826 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9827 atoken.startingDisplayed = false; 9828 } 9829 if ((w.isOnScreenIgnoringKeyguard() 9830 || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9831 && !w.mExiting && !w.mDestroying) { 9832 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9833 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9834 + ", isAnimating=" + winAnimator.isAnimating()); 9835 if (!w.isDrawnLw()) { 9836 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9837 + " pv=" + w.mPolicyVisibility 9838 + " mDrawState=" + winAnimator.drawStateToString() 9839 + " ah=" + w.mAttachedHidden 9840 + " th=" + atoken.hiddenRequested 9841 + " a=" + winAnimator.mAnimating); 9842 } 9843 } 9844 if (w != atoken.startingWindow) { 9845 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9846 atoken.numInterestingWindows++; 9847 if (w.isDrawnLw()) { 9848 atoken.numDrawnWindows++; 9849 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9850 "tokenMayBeDrawn: " + atoken 9851 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9852 + " mAppFreezing=" + w.mAppFreezing); 9853 updateAllDrawn = true; 9854 } 9855 } 9856 } else if (w.isDrawnLw()) { 9857 atoken.startingDisplayed = true; 9858 } 9859 } 9860 } 9861 } 9862 9863 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9864 && w.isDisplayedLw()) { 9865 focusDisplayed = true; 9866 } 9867 9868 updateResizingWindows(w); 9869 } 9870 9871 mDisplayManagerInternal.setDisplayProperties(displayId, 9872 mInnerFields.mDisplayHasContent, mInnerFields.mPreferredRefreshRate, 9873 true /* inTraversal, must call performTraversalInTrans... below */); 9874 9875 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9876 9877 if (updateAllDrawn) { 9878 updateAllDrawnLocked(displayContent); 9879 } 9880 } 9881 9882 if (focusDisplayed) { 9883 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9884 } 9885 9886 // Give the display manager a chance to adjust properties 9887 // like display rotation if it needs to. 9888 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9889 9890 } catch (RuntimeException e) { 9891 Slog.wtf(TAG, "Unhandled exception in Window Manager", e); 9892 } finally { 9893 SurfaceControl.closeTransaction(); 9894 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9895 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9896 } 9897 9898 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9899 9900 // If we are ready to perform an app transition, check through 9901 // all of the app tokens to be shown and see if they are ready 9902 // to go. 9903 if (mAppTransition.isReady()) { 9904 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9905 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9906 defaultDisplay.pendingLayoutChanges); 9907 } 9908 9909 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9910 // We have finished the animation of an app transition. To do 9911 // this, we have delayed a lot of operations like showing and 9912 // hiding apps, moving apps in Z-order, etc. The app token list 9913 // reflects the correct Z-order, but the window list may now 9914 // be out of sync with it. So here we will just rebuild the 9915 // entire app window list. Fun! 9916 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9917 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9918 defaultDisplay.pendingLayoutChanges); 9919 } 9920 9921 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9922 && !mAppTransition.isReady()) { 9923 // At this point, there was a window with a wallpaper that 9924 // was force hiding other windows behind it, but now it 9925 // is going away. This may be simple -- just animate 9926 // away the wallpaper and its window -- or it may be 9927 // hard -- the wallpaper now needs to be shown behind 9928 // something that was hidden. 9929 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9930 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9931 defaultDisplay.pendingLayoutChanges); 9932 } 9933 mInnerFields.mWallpaperForceHidingChanged = false; 9934 9935 if (mInnerFields.mWallpaperMayChange) { 9936 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9937 defaultDisplay.pendingLayoutChanges |= 9938 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9939 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9940 defaultDisplay.pendingLayoutChanges); 9941 } 9942 9943 if (mFocusMayChange) { 9944 mFocusMayChange = false; 9945 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9946 false /*updateInputWindows*/)) { 9947 updateInputWindowsNeeded = true; 9948 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9949 } 9950 } 9951 9952 if (needsLayout()) { 9953 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9954 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9955 defaultDisplay.pendingLayoutChanges); 9956 } 9957 9958 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9959 WindowState win = mResizingWindows.get(i); 9960 if (win.mAppFreezing) { 9961 // Don't remove this window until rotation has completed. 9962 continue; 9963 } 9964 win.reportResized(); 9965 mResizingWindows.remove(i); 9966 } 9967 9968 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9969 "With display frozen, orientationChangeComplete=" 9970 + mInnerFields.mOrientationChangeComplete); 9971 if (mInnerFields.mOrientationChangeComplete) { 9972 if (mWindowsFreezingScreen) { 9973 mWindowsFreezingScreen = false; 9974 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9975 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9976 } 9977 stopFreezingDisplayLocked(); 9978 } 9979 9980 // Destroy the surface of any windows that are no longer visible. 9981 boolean wallpaperDestroyed = false; 9982 i = mDestroySurface.size(); 9983 if (i > 0) { 9984 do { 9985 i--; 9986 WindowState win = mDestroySurface.get(i); 9987 win.mDestroying = false; 9988 if (mInputMethodWindow == win) { 9989 mInputMethodWindow = null; 9990 } 9991 if (win == mWallpaperTarget) { 9992 wallpaperDestroyed = true; 9993 } 9994 win.mWinAnimator.destroySurfaceLocked(); 9995 } while (i > 0); 9996 mDestroySurface.clear(); 9997 } 9998 9999 // Time to remove any exiting tokens? 10000 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10001 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10002 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 10003 for (i = exitingTokens.size() - 1; i >= 0; i--) { 10004 WindowToken token = exitingTokens.get(i); 10005 if (!token.hasVisible) { 10006 exitingTokens.remove(i); 10007 if (token.windowType == TYPE_WALLPAPER) { 10008 mWallpaperTokens.remove(token); 10009 } 10010 } 10011 } 10012 } 10013 10014 // Time to remove any exiting applications? 10015 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 10016 // Initialize state of exiting applications. 10017 final AppTokenList exitingAppTokens = 10018 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 10019 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 10020 AppWindowToken token = exitingAppTokens.get(i); 10021 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 10022 // Make sure there is no animation running on this token, 10023 // so any windows associated with it will be removed as 10024 // soon as their animations are complete 10025 token.mAppAnimator.clearAnimation(); 10026 token.mAppAnimator.animating = false; 10027 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 10028 "performLayout: App token exiting now removed" + token); 10029 removeAppFromTaskLocked(token); 10030 exitingAppTokens.remove(i); 10031 } 10032 } 10033 } 10034 10035 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 10036 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 10037 try { 10038 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 10039 } catch (RemoteException e) { 10040 } 10041 } 10042 mRelayoutWhileAnimating.clear(); 10043 } 10044 10045 if (wallpaperDestroyed) { 10046 defaultDisplay.pendingLayoutChanges |= 10047 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 10048 defaultDisplay.layoutNeeded = true; 10049 } 10050 10051 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10052 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10053 if (displayContent.pendingLayoutChanges != 0) { 10054 displayContent.layoutNeeded = true; 10055 } 10056 } 10057 10058 // Finally update all input windows now that the window changes have stabilized. 10059 mInputMonitor.updateInputWindowsLw(true /*force*/); 10060 10061 setHoldScreenLocked(mInnerFields.mHoldScreen); 10062 if (!mDisplayFrozen) { 10063 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 10064 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 10065 } else { 10066 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 10067 toBrightnessOverride(mInnerFields.mScreenBrightness)); 10068 } 10069 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 10070 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 10071 } else { 10072 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 10073 toBrightnessOverride(mInnerFields.mButtonBrightness)); 10074 } 10075 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 10076 mInnerFields.mUserActivityTimeout); 10077 } 10078 10079 if (mTurnOnScreen) { 10080 if (mAllowTheaterModeWakeFromLayout 10081 || Settings.Global.getInt(mContext.getContentResolver(), 10082 Settings.Global.THEATER_MODE_ON, 0) == 0) { 10083 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 10084 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 10085 } 10086 mTurnOnScreen = false; 10087 } 10088 10089 if (mInnerFields.mUpdateRotation) { 10090 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10091 if (updateRotationUncheckedLocked(false)) { 10092 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10093 } else { 10094 mInnerFields.mUpdateRotation = false; 10095 } 10096 } 10097 10098 if (mWaitingForDrawnCallback != null || 10099 (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded && 10100 !mInnerFields.mUpdateRotation)) { 10101 checkDrawnWindowsLocked(); 10102 } 10103 10104 final int N = mPendingRemove.size(); 10105 if (N > 0) { 10106 if (mPendingRemoveTmp.length < N) { 10107 mPendingRemoveTmp = new WindowState[N+10]; 10108 } 10109 mPendingRemove.toArray(mPendingRemoveTmp); 10110 mPendingRemove.clear(); 10111 DisplayContentList displayList = new DisplayContentList(); 10112 for (i = 0; i < N; i++) { 10113 WindowState w = mPendingRemoveTmp[i]; 10114 removeWindowInnerLocked(w.mSession, w); 10115 final DisplayContent displayContent = w.getDisplayContent(); 10116 if (displayContent != null && !displayList.contains(displayContent)) { 10117 displayList.add(displayContent); 10118 } 10119 } 10120 10121 for (DisplayContent displayContent : displayList) { 10122 assignLayersLocked(displayContent.getWindowList()); 10123 displayContent.layoutNeeded = true; 10124 } 10125 } 10126 10127 // Remove all deferred displays stacks, tasks, and activities. 10128 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 10129 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 10130 } 10131 10132 if (updateInputWindowsNeeded) { 10133 mInputMonitor.updateInputWindowsLw(false /*force*/); 10134 } 10135 setFocusedStackFrame(); 10136 10137 // Check to see if we are now in a state where the screen should 10138 // be enabled, because the window obscured flags have changed. 10139 enableScreenIfNeededLocked(); 10140 10141 scheduleAnimationLocked(); 10142 10143 if (DEBUG_WINDOW_TRACE) { 10144 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 10145 + mAnimator.mAnimating); 10146 } 10147 } 10148 10149 private int toBrightnessOverride(float value) { 10150 return (int)(value * PowerManager.BRIGHTNESS_ON); 10151 } 10152 10153 void checkDrawnWindowsLocked() { 10154 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 10155 return; 10156 } 10157 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 10158 WindowState win = mWaitingForDrawn.get(j); 10159 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 10160 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 10161 " mHasSurface=" + win.mHasSurface + 10162 " drawState=" + win.mWinAnimator.mDrawState); 10163 if (win.mRemoved || !win.mHasSurface) { 10164 // Window has been removed; no draw will now happen, so stop waiting. 10165 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 10166 mWaitingForDrawn.remove(win); 10167 } else if (win.hasDrawnLw()) { 10168 // Window is now drawn (and shown). 10169 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 10170 mWaitingForDrawn.remove(win); 10171 } 10172 } 10173 if (mWaitingForDrawn.isEmpty()) { 10174 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 10175 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 10176 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 10177 } 10178 } 10179 10180 void setHoldScreenLocked(final Session newHoldScreen) { 10181 final boolean hold = newHoldScreen != null; 10182 10183 if (hold && mHoldingScreenOn != newHoldScreen) { 10184 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 10185 } 10186 mHoldingScreenOn = newHoldScreen; 10187 10188 final boolean state = mHoldingScreenWakeLock.isHeld(); 10189 if (hold != state) { 10190 if (hold) { 10191 mHoldingScreenWakeLock.acquire(); 10192 mPolicy.keepScreenOnStartedLw(); 10193 } else { 10194 mPolicy.keepScreenOnStoppedLw(); 10195 mHoldingScreenWakeLock.release(); 10196 } 10197 } 10198 } 10199 10200 void requestTraversal() { 10201 synchronized (mWindowMap) { 10202 requestTraversalLocked(); 10203 } 10204 } 10205 10206 void requestTraversalLocked() { 10207 if (!mTraversalScheduled) { 10208 mTraversalScheduled = true; 10209 mH.sendEmptyMessage(H.DO_TRAVERSAL); 10210 } 10211 } 10212 10213 /** Note that Locked in this case is on mLayoutToAnim */ 10214 void scheduleAnimationLocked() { 10215 if (!mAnimationScheduled) { 10216 mAnimationScheduled = true; 10217 mChoreographer.postCallback( 10218 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 10219 } 10220 } 10221 10222 private boolean needsLayout() { 10223 final int numDisplays = mDisplayContents.size(); 10224 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10225 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10226 if (displayContent.layoutNeeded) { 10227 return true; 10228 } 10229 } 10230 return false; 10231 } 10232 10233 boolean copyAnimToLayoutParamsLocked() { 10234 boolean doRequest = false; 10235 10236 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 10237 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 10238 mInnerFields.mUpdateRotation = true; 10239 doRequest = true; 10240 } 10241 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 10242 mInnerFields.mWallpaperMayChange = true; 10243 doRequest = true; 10244 } 10245 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 10246 mInnerFields.mWallpaperForceHidingChanged = true; 10247 doRequest = true; 10248 } 10249 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 10250 mInnerFields.mOrientationChangeComplete = false; 10251 } else { 10252 mInnerFields.mOrientationChangeComplete = true; 10253 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 10254 if (mWindowsFreezingScreen) { 10255 doRequest = true; 10256 } 10257 } 10258 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 10259 mTurnOnScreen = true; 10260 } 10261 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 10262 mInnerFields.mWallpaperActionPending = true; 10263 } 10264 10265 return doRequest; 10266 } 10267 10268 /** If a window that has an animation specifying a colored background and the current wallpaper 10269 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 10270 * suddenly disappear. */ 10271 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 10272 WindowList windows = winAnimator.mWin.getWindowList(); 10273 for (int i = windows.size() - 1; i >= 0; --i) { 10274 WindowState testWin = windows.get(i); 10275 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 10276 return testWin.mWinAnimator.mAnimLayer; 10277 } 10278 } 10279 return winAnimator.mAnimLayer; 10280 } 10281 10282 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 10283 boolean secure) { 10284 final SurfaceControl surface = winAnimator.mSurfaceControl; 10285 boolean leakedSurface = false; 10286 boolean killedApps = false; 10287 10288 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 10289 winAnimator.mSession.mPid, operation); 10290 10291 if (mForceRemoves == null) { 10292 mForceRemoves = new ArrayList<WindowState>(); 10293 } 10294 10295 long callingIdentity = Binder.clearCallingIdentity(); 10296 try { 10297 // There was some problem... first, do a sanity check of the 10298 // window list to make sure we haven't left any dangling surfaces 10299 // around. 10300 10301 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 10302 final int numDisplays = mDisplayContents.size(); 10303 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10304 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 10305 final int numWindows = windows.size(); 10306 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 10307 final WindowState ws = windows.get(winNdx); 10308 WindowStateAnimator wsa = ws.mWinAnimator; 10309 if (wsa.mSurfaceControl != null) { 10310 if (!mSessions.contains(wsa.mSession)) { 10311 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 10312 + ws + " surface=" + wsa.mSurfaceControl 10313 + " token=" + ws.mToken 10314 + " pid=" + ws.mSession.mPid 10315 + " uid=" + ws.mSession.mUid); 10316 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 10317 wsa.mSurfaceControl.destroy(); 10318 wsa.mSurfaceShown = false; 10319 wsa.mSurfaceControl = null; 10320 ws.mHasSurface = false; 10321 mForceRemoves.add(ws); 10322 leakedSurface = true; 10323 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 10324 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 10325 + ws + " surface=" + wsa.mSurfaceControl 10326 + " token=" + ws.mAppToken); 10327 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 10328 wsa.mSurfaceControl.destroy(); 10329 wsa.mSurfaceShown = false; 10330 wsa.mSurfaceControl = null; 10331 ws.mHasSurface = false; 10332 leakedSurface = true; 10333 } 10334 } 10335 } 10336 } 10337 10338 if (!leakedSurface) { 10339 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 10340 SparseIntArray pidCandidates = new SparseIntArray(); 10341 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10342 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 10343 final int numWindows = windows.size(); 10344 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 10345 final WindowState ws = windows.get(winNdx); 10346 if (mForceRemoves.contains(ws)) { 10347 continue; 10348 } 10349 WindowStateAnimator wsa = ws.mWinAnimator; 10350 if (wsa.mSurfaceControl != null) { 10351 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 10352 } 10353 } 10354 if (pidCandidates.size() > 0) { 10355 int[] pids = new int[pidCandidates.size()]; 10356 for (int i=0; i<pids.length; i++) { 10357 pids[i] = pidCandidates.keyAt(i); 10358 } 10359 try { 10360 if (mActivityManager.killPids(pids, "Free memory", secure)) { 10361 killedApps = true; 10362 } 10363 } catch (RemoteException e) { 10364 } 10365 } 10366 } 10367 } 10368 10369 if (leakedSurface || killedApps) { 10370 // We managed to reclaim some memory, so get rid of the trouble 10371 // surface and ask the app to request another one. 10372 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 10373 if (surface != null) { 10374 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 10375 "RECOVER DESTROY", null); 10376 surface.destroy(); 10377 winAnimator.mSurfaceShown = false; 10378 winAnimator.mSurfaceControl = null; 10379 winAnimator.mWin.mHasSurface = false; 10380 scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken); 10381 } 10382 10383 try { 10384 winAnimator.mWin.mClient.dispatchGetNewSurface(); 10385 } catch (RemoteException e) { 10386 } 10387 } 10388 } finally { 10389 Binder.restoreCallingIdentity(callingIdentity); 10390 } 10391 10392 return leakedSurface || killedApps; 10393 } 10394 10395 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 10396 WindowState newFocus = computeFocusedWindowLocked(); 10397 if (mCurrentFocus != newFocus) { 10398 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 10399 // This check makes sure that we don't already have the focus 10400 // change message pending. 10401 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 10402 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 10403 // TODO(multidisplay): Focused windows on default display only. 10404 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10405 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 10406 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 10407 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 10408 if (imWindowChanged) { 10409 displayContent.layoutNeeded = true; 10410 newFocus = computeFocusedWindowLocked(); 10411 } 10412 10413 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 10414 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 10415 final WindowState oldFocus = mCurrentFocus; 10416 mCurrentFocus = newFocus; 10417 mLosingFocus.remove(newFocus); 10418 10419 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 10420 10421 if (imWindowChanged && oldFocus != mInputMethodWindow) { 10422 // Focus of the input method window changed. Perform layout if needed. 10423 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 10424 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 10425 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 10426 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 10427 // Client will do the layout, but we need to assign layers 10428 // for handleNewWindowLocked() below. 10429 assignLayersLocked(displayContent.getWindowList()); 10430 } 10431 } 10432 10433 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 10434 // The change in focus caused us to need to do a layout. Okay. 10435 displayContent.layoutNeeded = true; 10436 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 10437 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 10438 } 10439 } 10440 10441 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 10442 // If we defer assigning layers, then the caller is responsible for 10443 // doing this part. 10444 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 10445 } 10446 10447 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 10448 return true; 10449 } 10450 return false; 10451 } 10452 10453 private WindowState computeFocusedWindowLocked() { 10454 if (mAnimator.mUniverseBackground != null 10455 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 10456 return mAnimator.mUniverseBackground.mWin; 10457 } 10458 10459 final int displayCount = mDisplayContents.size(); 10460 for (int i = 0; i < displayCount; i++) { 10461 final DisplayContent displayContent = mDisplayContents.valueAt(i); 10462 WindowState win = findFocusedWindowLocked(displayContent); 10463 if (win != null) { 10464 return win; 10465 } 10466 } 10467 return null; 10468 } 10469 10470 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 10471 final WindowList windows = displayContent.getWindowList(); 10472 for (int i = windows.size() - 1; i >= 0; i--) { 10473 final WindowState win = windows.get(i); 10474 10475 if (localLOGV || DEBUG_FOCUS) Slog.v( 10476 TAG, "Looking for focus: " + i 10477 + " = " + win 10478 + ", flags=" + win.mAttrs.flags 10479 + ", canReceive=" + win.canReceiveKeys()); 10480 10481 AppWindowToken wtoken = win.mAppToken; 10482 10483 // If this window's application has been removed, just skip it. 10484 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 10485 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 10486 + (wtoken.removed ? "removed" : "sendingToBottom")); 10487 continue; 10488 } 10489 10490 if (!win.canReceiveKeys()) { 10491 continue; 10492 } 10493 10494 // Descend through all of the app tokens and find the first that either matches 10495 // win.mAppToken (return win) or mFocusedApp (return null). 10496 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 10497 mFocusedApp != null) { 10498 ArrayList<Task> tasks = displayContent.getTasks(); 10499 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 10500 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 10501 int tokenNdx = tokens.size() - 1; 10502 for ( ; tokenNdx >= 0; --tokenNdx) { 10503 final AppWindowToken token = tokens.get(tokenNdx); 10504 if (wtoken == token) { 10505 break; 10506 } 10507 if (mFocusedApp == token) { 10508 // Whoops, we are below the focused app... no focus for you! 10509 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 10510 "findFocusedWindow: Reached focused app=" + mFocusedApp); 10511 return null; 10512 } 10513 } 10514 if (tokenNdx >= 0) { 10515 // Early exit from loop, must have found the matching token. 10516 break; 10517 } 10518 } 10519 } 10520 10521 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 10522 " = " + win); 10523 return win; 10524 } 10525 10526 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 10527 return null; 10528 } 10529 10530 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 10531 if (mDisplayFrozen) { 10532 return; 10533 } 10534 10535 if (!mDisplayReady || !mPolicy.isScreenOn()) { 10536 // No need to freeze the screen before the system is ready or if 10537 // the screen is off. 10538 return; 10539 } 10540 10541 mScreenFrozenLock.acquire(); 10542 10543 mDisplayFrozen = true; 10544 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 10545 mLastFinishedFreezeSource = null; 10546 10547 mInputMonitor.freezeInputDispatchingLw(); 10548 10549 // Clear the last input window -- that is just used for 10550 // clean transitions between IMEs, and if we are freezing 10551 // the screen then the whole world is changing behind the scenes. 10552 mPolicy.setLastInputMethodWindowLw(null, null); 10553 10554 if (mAppTransition.isTransitionSet()) { 10555 mAppTransition.freeze(); 10556 } 10557 10558 if (PROFILE_ORIENTATION) { 10559 File file = new File("/data/system/frozen"); 10560 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10561 } 10562 10563 if (CUSTOM_SCREEN_ROTATION) { 10564 mExitAnimId = exitAnim; 10565 mEnterAnimId = enterAnim; 10566 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10567 final int displayId = displayContent.getDisplayId(); 10568 ScreenRotationAnimation screenRotationAnimation = 10569 mAnimator.getScreenRotationAnimationLocked(displayId); 10570 if (screenRotationAnimation != null) { 10571 screenRotationAnimation.kill(); 10572 } 10573 10574 // Check whether the current screen contains any secure content. 10575 boolean isSecure = false; 10576 final WindowList windows = getDefaultWindowListLocked(); 10577 final int N = windows.size(); 10578 for (int i = 0; i < N; i++) { 10579 WindowState ws = windows.get(i); 10580 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10581 isSecure = true; 10582 break; 10583 } 10584 } 10585 10586 // TODO(multidisplay): rotation on main screen only. 10587 displayContent.updateDisplayInfo(); 10588 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10589 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10590 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10591 } 10592 } 10593 10594 private void stopFreezingDisplayLocked() { 10595 if (!mDisplayFrozen) { 10596 return; 10597 } 10598 10599 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10600 || mClientFreezingScreen) { 10601 if (DEBUG_ORIENTATION) Slog.d(TAG, 10602 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10603 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10604 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10605 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10606 return; 10607 } 10608 10609 mDisplayFrozen = false; 10610 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10611 StringBuilder sb = new StringBuilder(128); 10612 sb.append("Screen frozen for "); 10613 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10614 if (mLastFinishedFreezeSource != null) { 10615 sb.append(" due to "); 10616 sb.append(mLastFinishedFreezeSource); 10617 } 10618 Slog.i(TAG, sb.toString()); 10619 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10620 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10621 if (PROFILE_ORIENTATION) { 10622 Debug.stopMethodTracing(); 10623 } 10624 10625 boolean updateRotation = false; 10626 10627 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10628 final int displayId = displayContent.getDisplayId(); 10629 ScreenRotationAnimation screenRotationAnimation = 10630 mAnimator.getScreenRotationAnimationLocked(displayId); 10631 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10632 && screenRotationAnimation.hasScreenshot()) { 10633 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10634 // TODO(multidisplay): rotation on main screen only. 10635 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10636 // Get rotation animation again, with new top window 10637 boolean isDimming = displayContent.isDimming(); 10638 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10639 mExitAnimId = mEnterAnimId = 0; 10640 } 10641 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10642 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 10643 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10644 scheduleAnimationLocked(); 10645 } else { 10646 screenRotationAnimation.kill(); 10647 screenRotationAnimation = null; 10648 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10649 updateRotation = true; 10650 } 10651 } else { 10652 if (screenRotationAnimation != null) { 10653 screenRotationAnimation.kill(); 10654 screenRotationAnimation = null; 10655 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10656 } 10657 updateRotation = true; 10658 } 10659 10660 mInputMonitor.thawInputDispatchingLw(); 10661 10662 boolean configChanged; 10663 10664 // While the display is frozen we don't re-compute the orientation 10665 // to avoid inconsistent states. However, something interesting 10666 // could have actually changed during that time so re-evaluate it 10667 // now to catch that. 10668 configChanged = updateOrientationFromAppTokensLocked(false); 10669 10670 // A little kludge: a lot could have happened while the 10671 // display was frozen, so now that we are coming back we 10672 // do a gc so that any remote references the system 10673 // processes holds on others can be released if they are 10674 // no longer needed. 10675 mH.removeMessages(H.FORCE_GC); 10676 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10677 10678 mScreenFrozenLock.release(); 10679 10680 if (updateRotation) { 10681 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10682 configChanged |= updateRotationUncheckedLocked(false); 10683 } 10684 10685 if (configChanged) { 10686 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10687 } 10688 } 10689 10690 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10691 DisplayMetrics dm) { 10692 if (index < tokens.length) { 10693 String str = tokens[index]; 10694 if (str != null && str.length() > 0) { 10695 try { 10696 int val = Integer.parseInt(str); 10697 return val; 10698 } catch (Exception e) { 10699 } 10700 } 10701 } 10702 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10703 return defDps; 10704 } 10705 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10706 return val; 10707 } 10708 10709 void createWatermarkInTransaction() { 10710 if (mWatermark != null) { 10711 return; 10712 } 10713 10714 File file = new File("/system/etc/setup.conf"); 10715 FileInputStream in = null; 10716 DataInputStream ind = null; 10717 try { 10718 in = new FileInputStream(file); 10719 ind = new DataInputStream(in); 10720 String line = ind.readLine(); 10721 if (line != null) { 10722 String[] toks = line.split("%"); 10723 if (toks != null && toks.length > 0) { 10724 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10725 mRealDisplayMetrics, mFxSession, toks); 10726 } 10727 } 10728 } catch (FileNotFoundException e) { 10729 } catch (IOException e) { 10730 } finally { 10731 if (ind != null) { 10732 try { 10733 ind.close(); 10734 } catch (IOException e) { 10735 } 10736 } else if (in != null) { 10737 try { 10738 in.close(); 10739 } catch (IOException e) { 10740 } 10741 } 10742 } 10743 } 10744 10745 @Override 10746 public void statusBarVisibilityChanged(int visibility) { 10747 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10748 != PackageManager.PERMISSION_GRANTED) { 10749 throw new SecurityException("Caller does not hold permission " 10750 + android.Manifest.permission.STATUS_BAR); 10751 } 10752 10753 synchronized (mWindowMap) { 10754 mLastStatusBarVisibility = visibility; 10755 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10756 updateStatusBarVisibilityLocked(visibility); 10757 } 10758 } 10759 10760 // TOOD(multidisplay): StatusBar on multiple screens? 10761 void updateStatusBarVisibilityLocked(int visibility) { 10762 mInputManager.setSystemUiVisibility(visibility); 10763 final WindowList windows = getDefaultWindowListLocked(); 10764 final int N = windows.size(); 10765 for (int i = 0; i < N; i++) { 10766 WindowState ws = windows.get(i); 10767 try { 10768 int curValue = ws.mSystemUiVisibility; 10769 int diff = curValue ^ visibility; 10770 // We are only interested in differences of one of the 10771 // clearable flags... 10772 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10773 // ...if it has actually been cleared. 10774 diff &= ~visibility; 10775 int newValue = (curValue&~diff) | (visibility&diff); 10776 if (newValue != curValue) { 10777 ws.mSeq++; 10778 ws.mSystemUiVisibility = newValue; 10779 } 10780 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10781 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10782 visibility, newValue, diff); 10783 } 10784 } catch (RemoteException e) { 10785 // so sorry 10786 } 10787 } 10788 } 10789 10790 @Override 10791 public void reevaluateStatusBarVisibility() { 10792 synchronized (mWindowMap) { 10793 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10794 updateStatusBarVisibilityLocked(visibility); 10795 performLayoutAndPlaceSurfacesLocked(); 10796 } 10797 } 10798 10799 @Override 10800 public FakeWindow addFakeWindow(Looper looper, 10801 InputEventReceiver.Factory inputEventReceiverFactory, 10802 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10803 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10804 synchronized (mWindowMap) { 10805 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10806 name, windowType, layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 10807 int i=0; 10808 while (i<mFakeWindows.size()) { 10809 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10810 break; 10811 } 10812 } 10813 mFakeWindows.add(i, fw); 10814 mInputMonitor.updateInputWindowsLw(true); 10815 return fw; 10816 } 10817 } 10818 10819 boolean removeFakeWindowLocked(FakeWindow window) { 10820 synchronized (mWindowMap) { 10821 if (mFakeWindows.remove(window)) { 10822 mInputMonitor.updateInputWindowsLw(true); 10823 return true; 10824 } 10825 return false; 10826 } 10827 } 10828 10829 // It is assumed that this method is called only by InputMethodManagerService. 10830 public void saveLastInputMethodWindowForTransition() { 10831 synchronized (mWindowMap) { 10832 // TODO(multidisplay): Pass in the displayID. 10833 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10834 if (mInputMethodWindow != null) { 10835 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10836 } 10837 } 10838 } 10839 10840 public int getInputMethodWindowVisibleHeight() { 10841 synchronized (mWindowMap) { 10842 return mPolicy.getInputMethodWindowVisibleHeightLw(); 10843 } 10844 } 10845 10846 @Override 10847 public boolean hasNavigationBar() { 10848 return mPolicy.hasNavigationBar(); 10849 } 10850 10851 @Override 10852 public void lockNow(Bundle options) { 10853 mPolicy.lockNow(options); 10854 } 10855 10856 public void showRecentApps() { 10857 mPolicy.showRecentApps(); 10858 } 10859 10860 @Override 10861 public boolean isSafeModeEnabled() { 10862 return mSafeMode; 10863 } 10864 10865 @Override 10866 public boolean clearWindowContentFrameStats(IBinder token) { 10867 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10868 "clearWindowContentFrameStats()")) { 10869 throw new SecurityException("Requires FRAME_STATS permission"); 10870 } 10871 synchronized (mWindowMap) { 10872 WindowState windowState = mWindowMap.get(token); 10873 if (windowState == null) { 10874 return false; 10875 } 10876 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10877 if (surfaceControl == null) { 10878 return false; 10879 } 10880 return surfaceControl.clearContentFrameStats(); 10881 } 10882 } 10883 10884 @Override 10885 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 10886 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10887 "getWindowContentFrameStats()")) { 10888 throw new SecurityException("Requires FRAME_STATS permission"); 10889 } 10890 synchronized (mWindowMap) { 10891 WindowState windowState = mWindowMap.get(token); 10892 if (windowState == null) { 10893 return null; 10894 } 10895 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10896 if (surfaceControl == null) { 10897 return null; 10898 } 10899 if (mTempWindowRenderStats == null) { 10900 mTempWindowRenderStats = new WindowContentFrameStats(); 10901 } 10902 WindowContentFrameStats stats = mTempWindowRenderStats; 10903 if (!surfaceControl.getContentFrameStats(stats)) { 10904 return null; 10905 } 10906 return stats; 10907 } 10908 } 10909 10910 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10911 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10912 mPolicy.dump(" ", pw, args); 10913 } 10914 10915 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10916 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10917 mAnimator.dumpLocked(pw, " ", dumpAll); 10918 } 10919 10920 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10921 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10922 if (mTokenMap.size() > 0) { 10923 pw.println(" All tokens:"); 10924 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10925 while (it.hasNext()) { 10926 WindowToken token = it.next(); 10927 pw.print(" "); pw.print(token); 10928 if (dumpAll) { 10929 pw.println(':'); 10930 token.dump(pw, " "); 10931 } else { 10932 pw.println(); 10933 } 10934 } 10935 } 10936 if (mWallpaperTokens.size() > 0) { 10937 pw.println(); 10938 pw.println(" Wallpaper tokens:"); 10939 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10940 WindowToken token = mWallpaperTokens.get(i); 10941 pw.print(" Wallpaper #"); pw.print(i); 10942 pw.print(' '); pw.print(token); 10943 if (dumpAll) { 10944 pw.println(':'); 10945 token.dump(pw, " "); 10946 } else { 10947 pw.println(); 10948 } 10949 } 10950 } 10951 if (mFinishedStarting.size() > 0) { 10952 pw.println(); 10953 pw.println(" Finishing start of application tokens:"); 10954 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10955 WindowToken token = mFinishedStarting.get(i); 10956 pw.print(" Finished Starting #"); pw.print(i); 10957 pw.print(' '); pw.print(token); 10958 if (dumpAll) { 10959 pw.println(':'); 10960 token.dump(pw, " "); 10961 } else { 10962 pw.println(); 10963 } 10964 } 10965 } 10966 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10967 pw.println(); 10968 if (mOpeningApps.size() > 0) { 10969 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10970 } 10971 if (mClosingApps.size() > 0) { 10972 pw.print(" mClosingApps="); pw.println(mClosingApps); 10973 } 10974 } 10975 } 10976 10977 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10978 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10979 for (int i=0; i<mSessions.size(); i++) { 10980 Session s = mSessions.valueAt(i); 10981 pw.print(" Session "); pw.print(s); pw.println(':'); 10982 s.dump(pw, " "); 10983 } 10984 } 10985 10986 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10987 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10988 if (mDisplayReady) { 10989 final int numDisplays = mDisplayContents.size(); 10990 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10991 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10992 displayContent.dump(" ", pw); 10993 } 10994 } else { 10995 pw.println(" NO DISPLAY"); 10996 } 10997 } 10998 10999 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 11000 ArrayList<WindowState> windows) { 11001 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 11002 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 11003 } 11004 11005 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 11006 ArrayList<WindowState> windows) { 11007 final int numDisplays = mDisplayContents.size(); 11008 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11009 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 11010 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 11011 final WindowState w = windowList.get(winNdx); 11012 if (windows == null || windows.contains(w)) { 11013 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 11014 pw.print(w); pw.println(":"); 11015 w.dump(pw, " ", dumpAll || windows != null); 11016 } 11017 } 11018 } 11019 if (mInputMethodDialogs.size() > 0) { 11020 pw.println(); 11021 pw.println(" Input method dialogs:"); 11022 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 11023 WindowState w = mInputMethodDialogs.get(i); 11024 if (windows == null || windows.contains(w)) { 11025 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 11026 } 11027 } 11028 } 11029 if (mPendingRemove.size() > 0) { 11030 pw.println(); 11031 pw.println(" Remove pending for:"); 11032 for (int i=mPendingRemove.size()-1; i>=0; i--) { 11033 WindowState w = mPendingRemove.get(i); 11034 if (windows == null || windows.contains(w)) { 11035 pw.print(" Remove #"); pw.print(i); pw.print(' '); 11036 pw.print(w); 11037 if (dumpAll) { 11038 pw.println(":"); 11039 w.dump(pw, " ", true); 11040 } else { 11041 pw.println(); 11042 } 11043 } 11044 } 11045 } 11046 if (mForceRemoves != null && mForceRemoves.size() > 0) { 11047 pw.println(); 11048 pw.println(" Windows force removing:"); 11049 for (int i=mForceRemoves.size()-1; i>=0; i--) { 11050 WindowState w = mForceRemoves.get(i); 11051 pw.print(" Removing #"); pw.print(i); pw.print(' '); 11052 pw.print(w); 11053 if (dumpAll) { 11054 pw.println(":"); 11055 w.dump(pw, " ", true); 11056 } else { 11057 pw.println(); 11058 } 11059 } 11060 } 11061 if (mDestroySurface.size() > 0) { 11062 pw.println(); 11063 pw.println(" Windows waiting to destroy their surface:"); 11064 for (int i=mDestroySurface.size()-1; i>=0; i--) { 11065 WindowState w = mDestroySurface.get(i); 11066 if (windows == null || windows.contains(w)) { 11067 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 11068 pw.print(w); 11069 if (dumpAll) { 11070 pw.println(":"); 11071 w.dump(pw, " ", true); 11072 } else { 11073 pw.println(); 11074 } 11075 } 11076 } 11077 } 11078 if (mLosingFocus.size() > 0) { 11079 pw.println(); 11080 pw.println(" Windows losing focus:"); 11081 for (int i=mLosingFocus.size()-1; i>=0; i--) { 11082 WindowState w = mLosingFocus.get(i); 11083 if (windows == null || windows.contains(w)) { 11084 pw.print(" Losing #"); pw.print(i); pw.print(' '); 11085 pw.print(w); 11086 if (dumpAll) { 11087 pw.println(":"); 11088 w.dump(pw, " ", true); 11089 } else { 11090 pw.println(); 11091 } 11092 } 11093 } 11094 } 11095 if (mResizingWindows.size() > 0) { 11096 pw.println(); 11097 pw.println(" Windows waiting to resize:"); 11098 for (int i=mResizingWindows.size()-1; i>=0; i--) { 11099 WindowState w = mResizingWindows.get(i); 11100 if (windows == null || windows.contains(w)) { 11101 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 11102 pw.print(w); 11103 if (dumpAll) { 11104 pw.println(":"); 11105 w.dump(pw, " ", true); 11106 } else { 11107 pw.println(); 11108 } 11109 } 11110 } 11111 } 11112 if (mWaitingForDrawn.size() > 0) { 11113 pw.println(); 11114 pw.println(" Clients waiting for these windows to be drawn:"); 11115 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 11116 WindowState win = mWaitingForDrawn.get(i); 11117 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 11118 } 11119 } 11120 pw.println(); 11121 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 11122 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad); 11123 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 11124 if (mLastFocus != mCurrentFocus) { 11125 pw.print(" mLastFocus="); pw.println(mLastFocus); 11126 } 11127 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 11128 if (mInputMethodTarget != null) { 11129 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 11130 } 11131 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 11132 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 11133 pw.print(" mLastDisplayFreezeDuration="); 11134 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 11135 if ( mLastFinishedFreezeSource != null) { 11136 pw.print(" due to "); 11137 pw.print(mLastFinishedFreezeSource); 11138 } 11139 pw.println(); 11140 if (dumpAll) { 11141 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 11142 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 11143 if (mLastStatusBarVisibility != 0) { 11144 pw.print(" mLastStatusBarVisibility=0x"); 11145 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 11146 } 11147 if (mInputMethodWindow != null) { 11148 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 11149 } 11150 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 11151 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 11152 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 11153 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 11154 } 11155 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 11156 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 11157 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE 11158 || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 11159 pw.print(" mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX); 11160 pw.print(" mLastWallpaperDisplayOffsetY="); 11161 pw.println(mLastWallpaperDisplayOffsetY); 11162 } 11163 if (mInputMethodAnimLayerAdjustment != 0 || 11164 mWallpaperAnimLayerAdjustment != 0) { 11165 pw.print(" mInputMethodAnimLayerAdjustment="); 11166 pw.print(mInputMethodAnimLayerAdjustment); 11167 pw.print(" mWallpaperAnimLayerAdjustment="); 11168 pw.println(mWallpaperAnimLayerAdjustment); 11169 } 11170 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 11171 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 11172 if (needsLayout()) { 11173 pw.print(" layoutNeeded on displays="); 11174 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11175 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 11176 if (displayContent.layoutNeeded) { 11177 pw.print(displayContent.getDisplayId()); 11178 } 11179 } 11180 pw.println(); 11181 } 11182 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 11183 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 11184 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 11185 pw.print(" client="); pw.print(mClientFreezingScreen); 11186 pw.print(" apps="); pw.print(mAppsFreezingScreen); 11187 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 11188 pw.print(" mRotation="); pw.print(mRotation); 11189 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 11190 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 11191 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 11192 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 11193 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 11194 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 11195 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 11196 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 11197 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 11198 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 11199 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 11200 pw.println(" mLayoutToAnim:"); 11201 mAppTransition.dump(pw); 11202 } 11203 } 11204 11205 boolean dumpWindows(PrintWriter pw, String name, String[] args, 11206 int opti, boolean dumpAll) { 11207 WindowList windows = new WindowList(); 11208 if ("visible".equals(name)) { 11209 synchronized(mWindowMap) { 11210 final int numDisplays = mDisplayContents.size(); 11211 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11212 final WindowList windowList = 11213 mDisplayContents.valueAt(displayNdx).getWindowList(); 11214 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 11215 final WindowState w = windowList.get(winNdx); 11216 if (w.mWinAnimator.mSurfaceShown) { 11217 windows.add(w); 11218 } 11219 } 11220 } 11221 } 11222 } else { 11223 int objectId = 0; 11224 // See if this is an object ID. 11225 try { 11226 objectId = Integer.parseInt(name, 16); 11227 name = null; 11228 } catch (RuntimeException e) { 11229 } 11230 synchronized(mWindowMap) { 11231 final int numDisplays = mDisplayContents.size(); 11232 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11233 final WindowList windowList = 11234 mDisplayContents.valueAt(displayNdx).getWindowList(); 11235 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 11236 final WindowState w = windowList.get(winNdx); 11237 if (name != null) { 11238 if (w.mAttrs.getTitle().toString().contains(name)) { 11239 windows.add(w); 11240 } 11241 } else if (System.identityHashCode(w) == objectId) { 11242 windows.add(w); 11243 } 11244 } 11245 } 11246 } 11247 } 11248 11249 if (windows.size() <= 0) { 11250 return false; 11251 } 11252 11253 synchronized(mWindowMap) { 11254 dumpWindowsLocked(pw, dumpAll, windows); 11255 } 11256 return true; 11257 } 11258 11259 void dumpLastANRLocked(PrintWriter pw) { 11260 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 11261 if (mLastANRState == null) { 11262 pw.println(" <no ANR has occurred since boot>"); 11263 } else { 11264 pw.println(mLastANRState); 11265 } 11266 } 11267 11268 /** 11269 * Saves information about the state of the window manager at 11270 * the time an ANR occurred before anything else in the system changes 11271 * in response. 11272 * 11273 * @param appWindowToken The application that ANR'd, may be null. 11274 * @param windowState The window that ANR'd, may be null. 11275 * @param reason The reason for the ANR, may be null. 11276 */ 11277 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 11278 String reason) { 11279 StringWriter sw = new StringWriter(); 11280 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 11281 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 11282 if (appWindowToken != null) { 11283 pw.println(" Application at fault: " + appWindowToken.stringName); 11284 } 11285 if (windowState != null) { 11286 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 11287 } 11288 if (reason != null) { 11289 pw.println(" Reason: " + reason); 11290 } 11291 pw.println(); 11292 dumpWindowsNoHeaderLocked(pw, true, null); 11293 pw.close(); 11294 mLastANRState = sw.toString(); 11295 } 11296 11297 @Override 11298 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 11299 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 11300 != PackageManager.PERMISSION_GRANTED) { 11301 pw.println("Permission Denial: can't dump WindowManager from from pid=" 11302 + Binder.getCallingPid() 11303 + ", uid=" + Binder.getCallingUid()); 11304 return; 11305 } 11306 11307 boolean dumpAll = false; 11308 11309 int opti = 0; 11310 while (opti < args.length) { 11311 String opt = args[opti]; 11312 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 11313 break; 11314 } 11315 opti++; 11316 if ("-a".equals(opt)) { 11317 dumpAll = true; 11318 } else if ("-h".equals(opt)) { 11319 pw.println("Window manager dump options:"); 11320 pw.println(" [-a] [-h] [cmd] ..."); 11321 pw.println(" cmd may be one of:"); 11322 pw.println(" l[astanr]: last ANR information"); 11323 pw.println(" p[policy]: policy state"); 11324 pw.println(" a[animator]: animator state"); 11325 pw.println(" s[essions]: active sessions"); 11326 pw.println(" surfaces: active surfaces (debugging enabled only)"); 11327 pw.println(" d[isplays]: active display contents"); 11328 pw.println(" t[okens]: token list"); 11329 pw.println(" w[indows]: window list"); 11330 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 11331 pw.println(" be a partial substring in a window name, a"); 11332 pw.println(" Window hex object identifier, or"); 11333 pw.println(" \"all\" for all windows, or"); 11334 pw.println(" \"visible\" for the visible windows."); 11335 pw.println(" -a: include all available server state."); 11336 return; 11337 } else { 11338 pw.println("Unknown argument: " + opt + "; use -h for help"); 11339 } 11340 } 11341 11342 // Is the caller requesting to dump a particular piece of data? 11343 if (opti < args.length) { 11344 String cmd = args[opti]; 11345 opti++; 11346 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 11347 synchronized(mWindowMap) { 11348 dumpLastANRLocked(pw); 11349 } 11350 return; 11351 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 11352 synchronized(mWindowMap) { 11353 dumpPolicyLocked(pw, args, true); 11354 } 11355 return; 11356 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 11357 synchronized(mWindowMap) { 11358 dumpAnimatorLocked(pw, args, true); 11359 } 11360 return; 11361 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 11362 synchronized(mWindowMap) { 11363 dumpSessionsLocked(pw, true); 11364 } 11365 return; 11366 } else if ("surfaces".equals(cmd)) { 11367 synchronized(mWindowMap) { 11368 WindowStateAnimator.SurfaceTrace.dumpAllSurfaces(pw, null); 11369 } 11370 return; 11371 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 11372 synchronized(mWindowMap) { 11373 dumpDisplayContentsLocked(pw, true); 11374 } 11375 return; 11376 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 11377 synchronized(mWindowMap) { 11378 dumpTokensLocked(pw, true); 11379 } 11380 return; 11381 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 11382 synchronized(mWindowMap) { 11383 dumpWindowsLocked(pw, true, null); 11384 } 11385 return; 11386 } else if ("all".equals(cmd) || "a".equals(cmd)) { 11387 synchronized(mWindowMap) { 11388 dumpWindowsLocked(pw, true, null); 11389 } 11390 return; 11391 } else { 11392 // Dumping a single name? 11393 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 11394 pw.println("Bad window command, or no windows match: " + cmd); 11395 pw.println("Use -h for help."); 11396 } 11397 return; 11398 } 11399 } 11400 11401 synchronized(mWindowMap) { 11402 pw.println(); 11403 if (dumpAll) { 11404 pw.println("-------------------------------------------------------------------------------"); 11405 } 11406 dumpLastANRLocked(pw); 11407 pw.println(); 11408 if (dumpAll) { 11409 pw.println("-------------------------------------------------------------------------------"); 11410 } 11411 dumpPolicyLocked(pw, args, dumpAll); 11412 pw.println(); 11413 if (dumpAll) { 11414 pw.println("-------------------------------------------------------------------------------"); 11415 } 11416 dumpAnimatorLocked(pw, args, dumpAll); 11417 pw.println(); 11418 if (dumpAll) { 11419 pw.println("-------------------------------------------------------------------------------"); 11420 } 11421 dumpSessionsLocked(pw, dumpAll); 11422 pw.println(); 11423 if (dumpAll) { 11424 pw.println("-------------------------------------------------------------------------------"); 11425 } 11426 WindowStateAnimator.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ? 11427 "-------------------------------------------------------------------------------" 11428 : null); 11429 pw.println(); 11430 if (dumpAll) { 11431 pw.println("-------------------------------------------------------------------------------"); 11432 } 11433 dumpDisplayContentsLocked(pw, dumpAll); 11434 pw.println(); 11435 if (dumpAll) { 11436 pw.println("-------------------------------------------------------------------------------"); 11437 } 11438 dumpTokensLocked(pw, dumpAll); 11439 pw.println(); 11440 if (dumpAll) { 11441 pw.println("-------------------------------------------------------------------------------"); 11442 } 11443 dumpWindowsLocked(pw, dumpAll, null); 11444 } 11445 } 11446 11447 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 11448 @Override 11449 public void monitor() { 11450 synchronized (mWindowMap) { } 11451 } 11452 11453 public interface OnHardKeyboardStatusChangeListener { 11454 public void onHardKeyboardStatusChange(boolean available); 11455 } 11456 11457 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 11458 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 11459 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 11460 Integer.toHexString(pendingLayoutChanges)); 11461 } 11462 } 11463 11464 private DisplayContent newDisplayContentLocked(final Display display) { 11465 DisplayContent displayContent = new DisplayContent(display, this); 11466 final int displayId = display.getDisplayId(); 11467 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 11468 mDisplayContents.put(displayId, displayContent); 11469 11470 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 11471 final Rect rect = new Rect(); 11472 mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect); 11473 synchronized (displayContent.mDisplaySizeLock) { 11474 displayInfo.overscanLeft = rect.left; 11475 displayInfo.overscanTop = rect.top; 11476 displayInfo.overscanRight = rect.right; 11477 displayInfo.overscanBottom = rect.bottom; 11478 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 11479 displayId, displayInfo); 11480 } 11481 configureDisplayPolicyLocked(displayContent); 11482 11483 // TODO: Create an input channel for each display with touch capability. 11484 if (displayId == Display.DEFAULT_DISPLAY) { 11485 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 11486 registerPointerEventListener(displayContent.mTapDetector); 11487 } 11488 11489 return displayContent; 11490 } 11491 11492 public void createDisplayContentLocked(final Display display) { 11493 if (display == null) { 11494 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 11495 } 11496 getDisplayContentLocked(display.getDisplayId()); 11497 } 11498 11499 /** 11500 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 11501 * there is a Display for the displayId. 11502 * @param displayId The display the caller is interested in. 11503 * @return The DisplayContent associated with displayId or null if there is no Display for it. 11504 */ 11505 public DisplayContent getDisplayContentLocked(final int displayId) { 11506 DisplayContent displayContent = mDisplayContents.get(displayId); 11507 if (displayContent == null) { 11508 final Display display = mDisplayManager.getDisplay(displayId); 11509 if (display != null) { 11510 displayContent = newDisplayContentLocked(display); 11511 } 11512 } 11513 return displayContent; 11514 } 11515 11516 // There is an inherent assumption that this will never return null. 11517 public DisplayContent getDefaultDisplayContentLocked() { 11518 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 11519 } 11520 11521 public WindowList getDefaultWindowListLocked() { 11522 return getDefaultDisplayContentLocked().getWindowList(); 11523 } 11524 11525 public DisplayInfo getDefaultDisplayInfoLocked() { 11526 return getDefaultDisplayContentLocked().getDisplayInfo(); 11527 } 11528 11529 /** 11530 * Return the list of WindowStates associated on the passed display. 11531 * @param display The screen to return windows from. 11532 * @return The list of WindowStates on the screen, or null if the there is no screen. 11533 */ 11534 public WindowList getWindowListLocked(final Display display) { 11535 return getWindowListLocked(display.getDisplayId()); 11536 } 11537 11538 /** 11539 * Return the list of WindowStates associated on the passed display. 11540 * @param displayId The screen to return windows from. 11541 * @return The list of WindowStates on the screen, or null if the there is no screen. 11542 */ 11543 public WindowList getWindowListLocked(final int displayId) { 11544 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11545 return displayContent != null ? displayContent.getWindowList() : null; 11546 } 11547 11548 public void onDisplayAdded(int displayId) { 11549 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 11550 } 11551 11552 public void handleDisplayAdded(int displayId) { 11553 synchronized (mWindowMap) { 11554 final Display display = mDisplayManager.getDisplay(displayId); 11555 if (display != null) { 11556 createDisplayContentLocked(display); 11557 displayReady(displayId); 11558 } 11559 requestTraversalLocked(); 11560 } 11561 } 11562 11563 public void onDisplayRemoved(int displayId) { 11564 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 11565 } 11566 11567 private void handleDisplayRemovedLocked(int displayId) { 11568 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11569 if (displayContent != null) { 11570 if (displayContent.isAnimating()) { 11571 displayContent.mDeferredRemoval = true; 11572 return; 11573 } 11574 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 11575 mDisplayContents.delete(displayId); 11576 displayContent.close(); 11577 if (displayId == Display.DEFAULT_DISPLAY) { 11578 unregisterPointerEventListener(displayContent.mTapDetector); 11579 } 11580 } 11581 mAnimator.removeDisplayLocked(displayId); 11582 requestTraversalLocked(); 11583 } 11584 11585 public void onDisplayChanged(int displayId) { 11586 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 11587 } 11588 11589 private void handleDisplayChangedLocked(int displayId) { 11590 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11591 if (displayContent != null) { 11592 displayContent.updateDisplayInfo(); 11593 } 11594 requestTraversalLocked(); 11595 } 11596 11597 @Override 11598 public Object getWindowManagerLock() { 11599 return mWindowMap; 11600 } 11601 11602 private final class LocalService extends WindowManagerInternal { 11603 @Override 11604 public void requestTraversalFromDisplayManager() { 11605 requestTraversal(); 11606 } 11607 11608 @Override 11609 public void setMagnificationSpec(MagnificationSpec spec) { 11610 synchronized (mWindowMap) { 11611 if (mAccessibilityController != null) { 11612 mAccessibilityController.setMagnificationSpecLocked(spec); 11613 } else { 11614 throw new IllegalStateException("Magnification callbacks not set!"); 11615 } 11616 } 11617 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11618 spec.recycle(); 11619 } 11620 } 11621 11622 @Override 11623 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11624 synchronized (mWindowMap) { 11625 WindowState windowState = mWindowMap.get(windowToken); 11626 if (windowState == null) { 11627 return null; 11628 } 11629 MagnificationSpec spec = null; 11630 if (mAccessibilityController != null) { 11631 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11632 } 11633 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11634 return null; 11635 } 11636 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11637 spec.scale *= windowState.mGlobalScale; 11638 return spec; 11639 } 11640 } 11641 11642 @Override 11643 public void setMagnificationCallbacks(MagnificationCallbacks callbacks) { 11644 synchronized (mWindowMap) { 11645 if (mAccessibilityController == null) { 11646 mAccessibilityController = new AccessibilityController( 11647 WindowManagerService.this); 11648 } 11649 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11650 if (!mAccessibilityController.hasCallbacksLocked()) { 11651 mAccessibilityController = null; 11652 } 11653 } 11654 } 11655 11656 @Override 11657 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11658 synchronized (mWindowMap) { 11659 if (mAccessibilityController == null) { 11660 mAccessibilityController = new AccessibilityController( 11661 WindowManagerService.this); 11662 } 11663 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11664 if (!mAccessibilityController.hasCallbacksLocked()) { 11665 mAccessibilityController = null; 11666 } 11667 } 11668 } 11669 11670 @Override 11671 public void setInputFilter(IInputFilter filter) { 11672 mInputManager.setInputFilter(filter); 11673 } 11674 11675 @Override 11676 public IBinder getFocusedWindowToken() { 11677 synchronized (mWindowMap) { 11678 WindowState windowState = getFocusedWindowLocked(); 11679 if (windowState != null) { 11680 return windowState.mClient.asBinder(); 11681 } 11682 return null; 11683 } 11684 } 11685 11686 @Override 11687 public boolean isKeyguardLocked() { 11688 return WindowManagerService.this.isKeyguardLocked(); 11689 } 11690 11691 @Override 11692 public void showGlobalActions() { 11693 WindowManagerService.this.showGlobalActions(); 11694 } 11695 11696 @Override 11697 public void getWindowFrame(IBinder token, Rect outBounds) { 11698 synchronized (mWindowMap) { 11699 WindowState windowState = mWindowMap.get(token); 11700 if (windowState != null) { 11701 outBounds.set(windowState.mFrame); 11702 } else { 11703 outBounds.setEmpty(); 11704 } 11705 } 11706 } 11707 11708 @Override 11709 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 11710 synchronized (mWindowMap) { 11711 mWaitingForDrawnCallback = callback; 11712 final WindowList windows = getDefaultWindowListLocked(); 11713 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11714 final WindowState win = windows.get(winNdx); 11715 if (win.isVisibleLw() 11716 && (win.mAppToken != null || mPolicy.isForceHiding(win.mAttrs))) { 11717 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 11718 // Force add to mResizingWindows. 11719 win.mLastContentInsets.set(-1, -1, -1, -1); 11720 mWaitingForDrawn.add(win); 11721 } 11722 } 11723 requestTraversalLocked(); 11724 } 11725 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11726 if (mWaitingForDrawn.isEmpty()) { 11727 callback.run(); 11728 } else { 11729 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11730 checkDrawnWindowsLocked(); 11731 } 11732 } 11733 11734 @Override 11735 public void addWindowToken(IBinder token, int type) { 11736 WindowManagerService.this.addWindowToken(token, type); 11737 } 11738 11739 @Override 11740 public void removeWindowToken(IBinder token, boolean removeWindows) { 11741 synchronized(mWindowMap) { 11742 if (removeWindows) { 11743 WindowToken wtoken = mTokenMap.remove(token); 11744 if (wtoken != null) { 11745 wtoken.removeAllWindows(); 11746 } 11747 } 11748 WindowManagerService.this.removeWindowToken(token); 11749 } 11750 } 11751 } 11752} 11753