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