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