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