WindowManagerService.java revision 7641e817e55cb88130f0d9ece7de24067c0b4d06
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wm; 18 19import static android.view.WindowManager.LayoutParams.*; 20 21import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 22import android.app.AppOpsManager; 23import android.os.Build; 24import android.os.SystemService; 25import android.util.ArraySet; 26import android.util.TimeUtils; 27import android.view.IWindowId; 28 29import android.view.IWindowSessionCallback; 30import android.view.WindowContentFrameStats; 31import com.android.internal.app.IBatteryStats; 32import com.android.internal.policy.PolicyManager; 33import com.android.internal.policy.impl.PhoneWindowManager; 34import com.android.internal.util.FastPrintWriter; 35import com.android.internal.view.IInputContext; 36import com.android.internal.view.IInputMethodClient; 37import com.android.internal.view.IInputMethodManager; 38import com.android.internal.view.WindowManagerPolicyThread; 39import com.android.server.AttributeCache; 40import com.android.server.DisplayThread; 41import com.android.server.EventLogTags; 42import com.android.server.LocalServices; 43import com.android.server.UiThread; 44import com.android.server.Watchdog; 45import com.android.server.am.BatteryStatsService; 46import com.android.server.input.InputManagerService; 47import com.android.server.power.ShutdownThread; 48 49import android.Manifest; 50import android.app.ActivityManagerNative; 51import android.app.IActivityManager; 52import android.app.StatusBarManager; 53import android.app.admin.DevicePolicyManager; 54import android.animation.ValueAnimator; 55import android.content.BroadcastReceiver; 56import android.content.ContentResolver; 57import android.content.Context; 58import android.content.Intent; 59import android.content.IntentFilter; 60import android.content.pm.ActivityInfo; 61import android.content.pm.PackageManager; 62import android.content.res.CompatibilityInfo; 63import android.content.res.Configuration; 64import android.database.ContentObserver; 65import android.graphics.Bitmap; 66import android.graphics.Bitmap.Config; 67import android.graphics.Canvas; 68import android.graphics.Matrix; 69import android.graphics.PixelFormat; 70import android.graphics.Point; 71import android.graphics.Rect; 72import android.graphics.RectF; 73import android.graphics.Region; 74import android.hardware.display.DisplayManager; 75import android.hardware.display.DisplayManagerInternal; 76import android.net.Uri; 77import android.os.Binder; 78import android.os.Bundle; 79import android.os.Debug; 80import android.os.Handler; 81import android.os.IBinder; 82import android.os.IRemoteCallback; 83import android.os.Looper; 84import android.os.Message; 85import android.os.Parcel; 86import android.os.ParcelFileDescriptor; 87import android.os.PowerManager; 88import android.os.PowerManagerInternal; 89import android.os.Process; 90import android.os.RemoteException; 91import android.os.ServiceManager; 92import android.os.StrictMode; 93import android.os.SystemClock; 94import android.os.SystemProperties; 95import android.os.Trace; 96import android.os.UserHandle; 97import android.os.WorkSource; 98import android.provider.Settings; 99import android.util.DisplayMetrics; 100import android.util.EventLog; 101import android.util.Log; 102import android.util.SparseArray; 103import android.util.Pair; 104import android.util.Slog; 105import android.util.SparseIntArray; 106import android.util.TypedValue; 107import android.view.Choreographer; 108import android.view.Display; 109import android.view.DisplayInfo; 110import android.view.Gravity; 111import android.view.IApplicationToken; 112import android.view.IInputFilter; 113import android.view.IOnKeyguardExitResult; 114import android.view.IRotationWatcher; 115import android.view.IWindow; 116import android.view.IWindowManager; 117import android.view.IWindowSession; 118import android.view.InputChannel; 119import android.view.InputDevice; 120import android.view.InputEvent; 121import android.view.InputEventReceiver; 122import android.view.KeyEvent; 123import android.view.MagnificationSpec; 124import android.view.MotionEvent; 125import android.view.WindowManagerInternal; 126import android.view.Surface.OutOfResourcesException; 127import android.view.Surface; 128import android.view.SurfaceControl; 129import android.view.SurfaceSession; 130import android.view.View; 131import android.view.ViewTreeObserver; 132import android.view.WindowManager; 133import android.view.WindowManagerGlobal; 134import android.view.WindowManagerPolicy; 135import android.view.WindowManager.LayoutParams; 136import android.view.WindowManagerPolicy.FakeWindow; 137import android.view.WindowManagerPolicy.PointerEventListener; 138import android.view.animation.Animation; 139import android.view.animation.AnimationUtils; 140import android.view.animation.Transformation; 141 142import java.io.BufferedWriter; 143import java.io.DataInputStream; 144import java.io.File; 145import java.io.FileDescriptor; 146import java.io.FileInputStream; 147import java.io.FileNotFoundException; 148import java.io.IOException; 149import java.io.OutputStream; 150import java.io.OutputStreamWriter; 151import java.io.PrintWriter; 152import java.io.StringWriter; 153import java.net.Socket; 154import java.text.DateFormat; 155import java.util.ArrayList; 156import java.util.Date; 157import java.util.HashMap; 158import java.util.Iterator; 159import java.util.List; 160 161/** {@hide} */ 162public class WindowManagerService extends IWindowManager.Stub 163 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { 164 static final String TAG = "WindowManager"; 165 static final boolean DEBUG = false; 166 static final boolean DEBUG_ADD_REMOVE = false; 167 static final boolean DEBUG_FOCUS = false; 168 static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false; 169 static final boolean DEBUG_ANIM = false; 170 static final boolean DEBUG_KEYGUARD = false; 171 static final boolean DEBUG_LAYOUT = false; 172 static final boolean DEBUG_RESIZE = false; 173 static final boolean DEBUG_LAYERS = false; 174 static final boolean DEBUG_INPUT = false; 175 static final boolean DEBUG_INPUT_METHOD = false; 176 static final boolean DEBUG_VISIBILITY = false; 177 static final boolean DEBUG_WINDOW_MOVEMENT = false; 178 static final boolean DEBUG_TOKEN_MOVEMENT = false; 179 static final boolean DEBUG_ORIENTATION = false; 180 static final boolean DEBUG_APP_ORIENTATION = false; 181 static final boolean DEBUG_CONFIGURATION = false; 182 static final boolean DEBUG_APP_TRANSITIONS = false; 183 static final boolean DEBUG_STARTING_WINDOW = false; 184 static final boolean DEBUG_REORDER = false; 185 static final boolean DEBUG_WALLPAPER = false; 186 static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER; 187 static final boolean DEBUG_DRAG = false; 188 static final boolean DEBUG_SCREEN_ON = false; 189 static final boolean DEBUG_SCREENSHOT = false; 190 static final boolean DEBUG_BOOT = false; 191 static final boolean DEBUG_LAYOUT_REPEATS = true; 192 static final boolean DEBUG_SURFACE_TRACE = false; 193 static final boolean DEBUG_WINDOW_TRACE = false; 194 static final boolean DEBUG_TASK_MOVEMENT = false; 195 static final boolean DEBUG_STACK = false; 196 static final boolean DEBUG_DISPLAY = false; 197 static final boolean SHOW_SURFACE_ALLOC = false; 198 static final boolean SHOW_TRANSACTIONS = false; 199 static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; 200 static final boolean HIDE_STACK_CRAWLS = true; 201 static final int LAYOUT_REPEAT_THRESHOLD = 4; 202 203 static final boolean PROFILE_ORIENTATION = false; 204 static final boolean localLOGV = DEBUG; 205 206 /** How much to multiply the policy's type layer, to reserve room 207 * for multiple windows of the same type and Z-ordering adjustment 208 * with TYPE_LAYER_OFFSET. */ 209 static final int TYPE_LAYER_MULTIPLIER = 10000; 210 211 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above 212 * or below others in the same layer. */ 213 static final int TYPE_LAYER_OFFSET = 1000; 214 215 /** How much to increment the layer for each window, to reserve room 216 * for effect surfaces between them. 217 */ 218 static final int WINDOW_LAYER_MULTIPLIER = 5; 219 220 /** 221 * Dim surface layer is immediately below target window. 222 */ 223 static final int LAYER_OFFSET_DIM = 1; 224 225 /** 226 * Blur surface layer is immediately below dim layer. 227 */ 228 static final int LAYER_OFFSET_BLUR = 2; 229 230 /** 231 * FocusedStackFrame layer is immediately above focused window. 232 */ 233 static final int LAYER_OFFSET_FOCUSED_STACK = 1; 234 235 /** 236 * Animation thumbnail is as far as possible below the window above 237 * the thumbnail (or in other words as far as possible above the window 238 * below it). 239 */ 240 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1; 241 242 /** 243 * Layer at which to put the rotation freeze snapshot. 244 */ 245 static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1; 246 247 /** 248 * Layer at which to put the mask for emulated screen sizes. 249 */ 250 static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200; 251 252 /** The maximum length we will accept for a loaded animation duration: 253 * this is 10 seconds. 254 */ 255 static final int MAX_ANIMATION_DURATION = 10*1000; 256 257 /** Amount of time (in milliseconds) to animate the fade-in-out transition for 258 * compatible windows. 259 */ 260 static final int DEFAULT_FADE_IN_OUT_DURATION = 400; 261 262 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 263 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 264 265 /** 266 * If true, the window manager will do its own custom freezing and general 267 * management of the screen during rotation. 268 */ 269 static final boolean CUSTOM_SCREEN_ROTATION = true; 270 271 // Maximum number of milliseconds to wait for input devices to be enumerated before 272 // proceding with safe mode detection. 273 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 274 275 // Default input dispatching timeout in nanoseconds. 276 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; 277 278 // Poll interval in milliseconds for watching boot animation finished. 279 private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; 280 281 // The name of the boot animation service in init.rc. 282 private static final String BOOT_ANIMATION_SERVICE = "bootanim"; 283 284 /** Minimum value for attachStack and resizeStack weight value */ 285 public static final float STACK_WEIGHT_MIN = 0.2f; 286 287 /** Maximum value for attachStack and resizeStack weight value */ 288 public static final float STACK_WEIGHT_MAX = 0.8f; 289 290 static final int UPDATE_FOCUS_NORMAL = 0; 291 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 292 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 293 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 294 295 private static final String SYSTEM_SECURE = "ro.secure"; 296 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 297 298 private static final String DENSITY_OVERRIDE = "ro.config.density_override"; 299 private static final String SIZE_OVERRIDE = "ro.config.size_override"; 300 301 private static final int MAX_SCREENSHOT_RETRIES = 3; 302 303 // The flag describing a full screen app window (where the app takes care of drawing under the 304 // SystemUI bars) 305 private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN = 306 View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 307 308 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular"; 309 310 final private KeyguardDisableHandler mKeyguardDisableHandler; 311 312 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 313 @Override 314 public void onReceive(Context context, Intent intent) { 315 final String action = intent.getAction(); 316 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) { 317 mKeyguardDisableHandler.sendEmptyMessage( 318 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED); 319 } 320 } 321 }; 322 323 /** 324 * Current user when multi-user is enabled. Don't show windows of 325 * non-current user. Also see mCurrentProfileIds. 326 */ 327 int mCurrentUserId; 328 /** 329 * Users that are profiles of the current user. These are also allowed to show windows 330 * on the current user. 331 */ 332 int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; 333 334 final Context mContext; 335 336 final boolean mHaveInputMethods; 337 338 final boolean mHasPermanentDpad; 339 340 final boolean mAllowBootMessages; 341 342 final boolean mLimitedAlphaCompositing; 343 344 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager(); 345 346 final IActivityManager mActivityManager; 347 348 final IBatteryStats mBatteryStats; 349 350 final AppOpsManager mAppOps; 351 352 final DisplaySettings mDisplaySettings; 353 354 /** 355 * All currently active sessions with clients. 356 */ 357 final ArraySet<Session> mSessions = new ArraySet<Session>(); 358 359 /** 360 * Mapping from an IWindow IBinder to the server's Window object. 361 * This is also used as the lock for all of our state. 362 * NOTE: Never call into methods that lock ActivityManagerService while holding this object. 363 */ 364 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>(); 365 366 /** 367 * Mapping from a token IBinder to a WindowToken object. 368 */ 369 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>(); 370 371 /** 372 * List of window tokens that have finished starting their application, 373 * and now need to have the policy remove their windows. 374 */ 375 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>(); 376 377 /** 378 * Fake windows added to the window manager. Note: ordered from top to 379 * bottom, opposite of mWindows. 380 */ 381 final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>(); 382 383 /** 384 * Windows that are being resized. Used so we can tell the client about 385 * the resize after closing the transaction in which we resized the 386 * underlying surface. 387 */ 388 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>(); 389 390 /** 391 * Windows whose animations have ended and now must be removed. 392 */ 393 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>(); 394 395 /** 396 * Stacks whose animations have ended and whose tasks, apps, selves may now be removed. 397 */ 398 final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>(); 399 400 /** 401 * Used when processing mPendingRemove to avoid working on the original array. 402 */ 403 WindowState[] mPendingRemoveTmp = new WindowState[20]; 404 405 /** 406 * Windows whose surface should be destroyed. 407 */ 408 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>(); 409 410 /** 411 * Windows that have lost input focus and are waiting for the new 412 * focus window to be displayed before they are told about this. 413 */ 414 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>(); 415 416 /** 417 * This is set when we have run out of memory, and will either be an empty 418 * list or contain windows that need to be force removed. 419 */ 420 ArrayList<WindowState> mForceRemoves; 421 422 /** 423 * Windows that clients are waiting to have drawn. 424 */ 425 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>(); 426 /** 427 * And the callback to make when they've all been drawn. 428 */ 429 Runnable mWaitingForDrawnCallback; 430 431 /** 432 * Windows that have called relayout() while we were running animations, 433 * so we need to tell when the animation is done. 434 */ 435 final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>(); 436 437 /** 438 * Used when rebuilding window list to keep track of windows that have 439 * been removed. 440 */ 441 WindowState[] mRebuildTmp = new WindowState[20]; 442 443 /** 444 * Stores for each user whether screencapture is disabled 445 * This array is essentially a cache for all userId for 446 * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled} 447 */ 448 SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<Boolean>(); 449 450 IInputMethodManager mInputMethodManager; 451 452 AccessibilityController mAccessibilityController; 453 454 final SurfaceSession mFxSession; 455 Watermark mWatermark; 456 StrictModeFlash mStrictModeFlash; 457 CircularDisplayMask mCircularDisplayMask; 458 EmulatorDisplayOverlay mEmulatorDisplayOverlay; 459 FocusedStackFrame mFocusedStackFrame; 460 461 int mFocusedStackLayer; 462 463 final float[] mTmpFloats = new float[9]; 464 final Rect mTmpContentRect = new Rect(); 465 466 boolean mDisplayReady; 467 boolean mSafeMode; 468 boolean mDisplayEnabled = false; 469 boolean mSystemBooted = false; 470 boolean mForceDisplayEnabled = false; 471 boolean mShowingBootMessages = false; 472 boolean mBootAnimationStopped = false; 473 474 String mLastANRState; 475 476 /** All DisplayContents in the world, kept here */ 477 SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2); 478 479 int mRotation = 0; 480 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 481 boolean mAltOrientation = false; 482 483 private boolean mKeyguardWaitingForActivityDrawn; 484 485 class RotationWatcher { 486 IRotationWatcher watcher; 487 IBinder.DeathRecipient deathRecipient; 488 RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) { 489 watcher = w; 490 deathRecipient = d; 491 } 492 } 493 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>(); 494 int mDeferredRotationPauseCount; 495 496 int mSystemDecorLayer = 0; 497 final Rect mScreenRect = new Rect(); 498 499 boolean mTraversalScheduled = false; 500 boolean mDisplayFrozen = false; 501 long mDisplayFreezeTime = 0; 502 int mLastDisplayFreezeDuration = 0; 503 Object mLastFinishedFreezeSource = null; 504 boolean mWaitingForConfig = false; 505 boolean mWindowsFreezingScreen = false; 506 boolean mClientFreezingScreen = false; 507 int mAppsFreezingScreen = 0; 508 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 509 510 int mLayoutSeq = 0; 511 512 int mLastStatusBarVisibility = 0; 513 514 // State while inside of layoutAndPlaceSurfacesLocked(). 515 boolean mFocusMayChange; 516 517 Configuration mCurConfiguration = new Configuration(); 518 519 // This is held as long as we have the screen frozen, to give us time to 520 // perform a rotation animation when turning off shows the lock screen which 521 // changes the orientation. 522 private final PowerManager.WakeLock mScreenFrozenLock; 523 524 final AppTransition mAppTransition; 525 boolean mStartingIconInTransition = false; 526 boolean mSkipAppTransitionAnimation = false; 527 528 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>(); 529 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<AppWindowToken>(); 530 531 boolean mIsTouchDevice; 532 533 final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 534 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 535 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 536 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 537 538 final H mH = new H(); 539 540 final Choreographer mChoreographer = Choreographer.getInstance(); 541 542 WindowState mCurrentFocus = null; 543 WindowState mLastFocus = null; 544 545 /** This just indicates the window the input method is on top of, not 546 * necessarily the window its input is going to. */ 547 WindowState mInputMethodTarget = null; 548 549 /** If true hold off on modifying the animation layer of mInputMethodTarget */ 550 boolean mInputMethodTargetWaitingAnim; 551 int mInputMethodAnimLayerAdjustment; 552 553 WindowState mInputMethodWindow = null; 554 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); 555 556 boolean mHardKeyboardAvailable; 557 boolean mShowImeWithHardKeyboard; 558 OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 559 SettingsObserver mSettingsObserver; 560 561 private final class SettingsObserver extends ContentObserver { 562 private final Uri mShowImeWithHardKeyboardUri = 563 Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD); 564 565 private final Uri mDisplayInversionEnabledUri = 566 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 567 568 public SettingsObserver() { 569 super(new Handler()); 570 ContentResolver resolver = mContext.getContentResolver(); 571 resolver.registerContentObserver(mShowImeWithHardKeyboardUri, false, this); 572 resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this); 573 } 574 575 @Override 576 public void onChange(boolean selfChange, Uri uri) { 577 if (mShowImeWithHardKeyboardUri.equals(uri)) { 578 updateShowImeWithHardKeyboard(); 579 } else if (mDisplayInversionEnabledUri.equals(uri)) { 580 updateCircularDisplayMaskIfNeeded(); 581 } 582 } 583 } 584 585 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); 586 587 // If non-null, this is the currently visible window that is associated 588 // with the wallpaper. 589 WindowState mWallpaperTarget = null; 590 // If non-null, we are in the middle of animating from one wallpaper target 591 // to another, and this is the lower one in Z-order. 592 WindowState mLowerWallpaperTarget = null; 593 // If non-null, we are in the middle of animating from one wallpaper target 594 // to another, and this is the higher one in Z-order. 595 WindowState mUpperWallpaperTarget = null; 596 int mWallpaperAnimLayerAdjustment; 597 float mLastWallpaperX = -1; 598 float mLastWallpaperY = -1; 599 float mLastWallpaperXStep = -1; 600 float mLastWallpaperYStep = -1; 601 int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE; 602 int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE; 603 // This is set when we are waiting for a wallpaper to tell us it is done 604 // changing its scroll position. 605 WindowState mWaitingOnWallpaper; 606 // The last time we had a timeout when waiting for a wallpaper. 607 long mLastWallpaperTimeoutTime; 608 // We give a wallpaper up to 150ms to finish scrolling. 609 static final long WALLPAPER_TIMEOUT = 150; 610 // Time we wait after a timeout before trying to wait again. 611 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000; 612 boolean mAnimateWallpaperWithTarget; 613 614 AppWindowToken mFocusedApp = null; 615 616 PowerManager mPowerManager; 617 PowerManagerInternal mPowerManagerInternal; 618 619 float mWindowAnimationScaleSetting = 1.0f; 620 float mTransitionAnimationScaleSetting = 1.0f; 621 float mAnimatorDurationScaleSetting = 1.0f; 622 boolean mAnimationsDisabled = false; 623 624 final InputManagerService mInputManager; 625 final DisplayManagerInternal mDisplayManagerInternal; 626 final DisplayManager mDisplayManager; 627 628 // Who is holding the screen on. 629 Session mHoldingScreenOn; 630 PowerManager.WakeLock mHoldingScreenWakeLock; 631 632 boolean mTurnOnScreen; 633 634 // Whether or not a layout can cause a wake up when theater mode is enabled. 635 boolean mAllowTheaterModeWakeFromLayout; 636 637 DragState mDragState = null; 638 639 // For frozen screen animations. 640 int mExitAnimId, mEnterAnimId; 641 642 /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple 643 * methods. */ 644 class LayoutFields { 645 static final int SET_UPDATE_ROTATION = 1 << 0; 646 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1; 647 static final int SET_FORCE_HIDING_CHANGED = 1 << 2; 648 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3; 649 static final int SET_TURN_ON_SCREEN = 1 << 4; 650 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5; 651 652 boolean mWallpaperForceHidingChanged = false; 653 boolean mWallpaperMayChange = false; 654 boolean mOrientationChangeComplete = true; 655 Object mLastWindowFreezeSource = null; 656 private Session mHoldScreen = null; 657 private boolean mObscured = false; 658 private boolean mSyswin = false; 659 private float mScreenBrightness = -1; 660 private float mButtonBrightness = -1; 661 private long mUserActivityTimeout = -1; 662 private boolean mUpdateRotation = false; 663 boolean mWallpaperActionPending = false; 664 665 // Set to true when the display contains content to show the user. 666 // When false, the display manager may choose to mirror or blank the display. 667 boolean mDisplayHasContent = false; 668 669 // Only set while traversing the default display based on its content. 670 // Affects the behavior of mirroring on secondary displays. 671 boolean mObscureApplicationContentOnSecondaryDisplays = false; 672 673 float mPreferredRefreshRate = 0; 674 } 675 final LayoutFields mInnerFields = new LayoutFields(); 676 677 boolean mAnimationScheduled; 678 679 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 680 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 681 private int mTransactionSequence; 682 683 /** Only do a maximum of 6 repeated layouts. After that quit */ 684 private int mLayoutRepeatCount; 685 686 final WindowAnimator mAnimator; 687 688 SparseArray<Task> mTaskIdToTask = new SparseArray<Task>(); 689 690 /** All of the TaskStacks in the window manager, unordered. For an ordered list call 691 * DisplayContent.getStacks(). */ 692 SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>(); 693 694 private final PointerEventDispatcher mPointerEventDispatcher; 695 696 private WindowContentFrameStats mTempWindowRenderStats; 697 698 final class DragInputEventReceiver extends InputEventReceiver { 699 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { 700 super(inputChannel, looper); 701 } 702 703 @Override 704 public void onInputEvent(InputEvent event) { 705 boolean handled = false; 706 try { 707 if (event instanceof MotionEvent 708 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 709 && mDragState != null) { 710 final MotionEvent motionEvent = (MotionEvent)event; 711 boolean endDrag = false; 712 final float newX = motionEvent.getRawX(); 713 final float newY = motionEvent.getRawY(); 714 715 switch (motionEvent.getAction()) { 716 case MotionEvent.ACTION_DOWN: { 717 if (DEBUG_DRAG) { 718 Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer"); 719 } 720 } break; 721 722 case MotionEvent.ACTION_MOVE: { 723 synchronized (mWindowMap) { 724 // move the surface and tell the involved window(s) where we are 725 mDragState.notifyMoveLw(newX, newY); 726 } 727 } break; 728 729 case MotionEvent.ACTION_UP: { 730 if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at " 731 + newX + "," + newY); 732 synchronized (mWindowMap) { 733 endDrag = mDragState.notifyDropLw(newX, newY); 734 } 735 } break; 736 737 case MotionEvent.ACTION_CANCEL: { 738 if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!"); 739 endDrag = true; 740 } break; 741 } 742 743 if (endDrag) { 744 if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state"); 745 // tell all the windows that the drag has ended 746 synchronized (mWindowMap) { 747 mDragState.endDragLw(); 748 } 749 } 750 751 handled = true; 752 } 753 } catch (Exception e) { 754 Slog.e(TAG, "Exception caught by drag handleMotion", e); 755 } finally { 756 finishInputEvent(event, handled); 757 } 758 } 759 } 760 761 /** 762 * Whether the UI is currently running in touch mode (not showing 763 * navigational focus because the user is directly pressing the screen). 764 */ 765 boolean mInTouchMode = true; 766 767 private ViewServer mViewServer; 768 private final ArrayList<WindowChangeListener> mWindowChangeListeners = 769 new ArrayList<WindowChangeListener>(); 770 private boolean mWindowsChanged = false; 771 772 public interface WindowChangeListener { 773 public void windowsChanged(); 774 public void focusChanged(); 775 } 776 777 final Configuration mTempConfiguration = new Configuration(); 778 779 // The desired scaling factor for compatible apps. 780 float mCompatibleScreenScale; 781 782 // If true, only the core apps and services are being launched because the device 783 // is in a special boot mode, such as being encrypted or waiting for a decryption password. 784 // For example, when this flag is true, there will be no wallpaper service. 785 final boolean mOnlyCore; 786 787 public static WindowManagerService main(final Context context, 788 final InputManagerService im, 789 final boolean haveInputMethods, final boolean showBootMsgs, 790 final boolean onlyCore) { 791 final WindowManagerService[] holder = new WindowManagerService[1]; 792 DisplayThread.getHandler().runWithScissors(new Runnable() { 793 @Override 794 public void run() { 795 holder[0] = new WindowManagerService(context, im, 796 haveInputMethods, showBootMsgs, onlyCore); 797 } 798 }, 0); 799 return holder[0]; 800 } 801 802 private void initPolicy() { 803 UiThread.getHandler().runWithScissors(new Runnable() { 804 @Override 805 public void run() { 806 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 807 808 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); 809 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer() 810 * TYPE_LAYER_MULTIPLIER 811 + TYPE_LAYER_OFFSET; 812 } 813 }, 0); 814 } 815 816 private WindowManagerService(Context context, InputManagerService inputManager, 817 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { 818 mContext = context; 819 mHaveInputMethods = haveInputMethods; 820 mAllowBootMessages = showBootMsgs; 821 mOnlyCore = onlyCore; 822 mLimitedAlphaCompositing = context.getResources().getBoolean( 823 com.android.internal.R.bool.config_sf_limitedAlpha); 824 mHasPermanentDpad = context.getResources().getBoolean( 825 com.android.internal.R.bool.config_hasPermanentDpad); 826 mInputManager = inputManager; // Must be before createDisplayContentLocked. 827 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 828 mDisplaySettings = new DisplaySettings(context); 829 mDisplaySettings.readSettingsLocked(); 830 831 LocalServices.addService(WindowManagerPolicy.class, mPolicy); 832 833 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG)); 834 835 mFxSession = new SurfaceSession(); 836 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 837 Display[] displays = mDisplayManager.getDisplays(); 838 for (Display display : displays) { 839 createDisplayContentLocked(display); 840 } 841 842 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 843 844 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 845 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 846 mPowerManagerInternal.registerLowPowerModeObserver( 847 new PowerManagerInternal.LowPowerModeListener() { 848 @Override 849 public void onLowPowerModeChanged(boolean enabled) { 850 synchronized (mWindowMap) { 851 if (mAnimationsDisabled != enabled) { 852 mAnimationsDisabled = enabled; 853 dispatchNewAnimatorScaleLocked(null); 854 } 855 } 856 } 857 }); 858 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled(); 859 mScreenFrozenLock = mPowerManager.newWakeLock( 860 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 861 mScreenFrozenLock.setReferenceCounted(false); 862 863 mAppTransition = new AppTransition(context, mH); 864 865 mActivityManager = ActivityManagerNative.getDefault(); 866 mBatteryStats = BatteryStatsService.getService(); 867 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 868 AppOpsManager.OnOpChangedInternalListener opListener = 869 new AppOpsManager.OnOpChangedInternalListener() { 870 @Override public void onOpChanged(int op, String packageName) { 871 updateAppOpsState(); 872 } 873 }; 874 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener); 875 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener); 876 877 // Get persisted window scale setting 878 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 879 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 880 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 881 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting); 882 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 883 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 884 885 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 886 IntentFilter filter = new IntentFilter(); 887 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 888 mContext.registerReceiver(mBroadcastReceiver, filter); 889 890 mSettingsObserver = new SettingsObserver(); 891 updateShowImeWithHardKeyboard(); 892 893 mHoldingScreenWakeLock = mPowerManager.newWakeLock( 894 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG); 895 mHoldingScreenWakeLock.setReferenceCounted(false); 896 897 mAnimator = new WindowAnimator(this); 898 899 mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean( 900 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout); 901 902 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 903 initPolicy(); 904 905 // Add ourself to the Watchdog monitors. 906 Watchdog.getInstance().addMonitor(this); 907 908 SurfaceControl.openTransaction(); 909 try { 910 createWatermarkInTransaction(); 911 mFocusedStackFrame = new FocusedStackFrame( 912 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 913 } finally { 914 SurfaceControl.closeTransaction(); 915 } 916 917 updateCircularDisplayMaskIfNeeded(); 918 showEmulatorDisplayOverlayIfNeeded(); 919 } 920 921 public InputMonitor getInputMonitor() { 922 return mInputMonitor; 923 } 924 925 @Override 926 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 927 throws RemoteException { 928 try { 929 return super.onTransact(code, data, reply, flags); 930 } catch (RuntimeException e) { 931 // The window manager only throws security exceptions, so let's 932 // log all others. 933 if (!(e instanceof SecurityException)) { 934 Slog.wtf(TAG, "Window Manager Crash", e); 935 } 936 throw e; 937 } 938 } 939 940 private void placeWindowAfter(WindowState pos, WindowState window) { 941 final WindowList windows = pos.getWindowList(); 942 final int i = windows.indexOf(pos); 943 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 944 TAG, "Adding window " + window + " at " 945 + (i+1) + " of " + windows.size() + " (after " + pos + ")"); 946 windows.add(i+1, window); 947 mWindowsChanged = true; 948 } 949 950 private void placeWindowBefore(WindowState pos, WindowState window) { 951 final WindowList windows = pos.getWindowList(); 952 int i = windows.indexOf(pos); 953 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 954 TAG, "Adding window " + window + " at " 955 + i + " of " + windows.size() + " (before " + pos + ")"); 956 if (i < 0) { 957 Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows); 958 i = 0; 959 } 960 windows.add(i, window); 961 mWindowsChanged = true; 962 } 963 964 //This method finds out the index of a window that has the same app token as 965 //win. used for z ordering the windows in mWindows 966 private int findIdxBasedOnAppTokens(WindowState win) { 967 WindowList windows = win.getWindowList(); 968 for(int j = windows.size() - 1; j >= 0; j--) { 969 WindowState wentry = windows.get(j); 970 if(wentry.mAppToken == win.mAppToken) { 971 return j; 972 } 973 } 974 return -1; 975 } 976 977 /** 978 * Return the list of Windows from the passed token on the given Display. 979 * @param token The token with all the windows. 980 * @param displayContent The display we are interested in. 981 * @return List of windows from token that are on displayContent. 982 */ 983 WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) { 984 final WindowList windowList = new WindowList(); 985 final int count = token.windows.size(); 986 for (int i = 0; i < count; i++) { 987 final WindowState win = token.windows.get(i); 988 if (win.getDisplayContent() == displayContent) { 989 windowList.add(win); 990 } 991 } 992 return windowList; 993 } 994 995 /** 996 * Recursive search through a WindowList and all of its windows' children. 997 * @param targetWin The window to search for. 998 * @param windows The list to search. 999 * @return The index of win in windows or of the window that is an ancestor of win. 1000 */ 1001 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) { 1002 for (int i = windows.size() - 1; i >= 0; i--) { 1003 final WindowState w = windows.get(i); 1004 if (w == targetWin) { 1005 return i; 1006 } 1007 if (!w.mChildWindows.isEmpty()) { 1008 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) { 1009 return i; 1010 } 1011 } 1012 } 1013 return -1; 1014 } 1015 1016 private int addAppWindowToListLocked(final WindowState win) { 1017 final IWindow client = win.mClient; 1018 final WindowToken token = win.mToken; 1019 final DisplayContent displayContent = win.getDisplayContent(); 1020 if (displayContent == null) { 1021 // It doesn't matter this display is going away. 1022 return 0; 1023 } 1024 1025 final WindowList windows = win.getWindowList(); 1026 final int N = windows.size(); 1027 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1028 int tokenWindowsPos = 0; 1029 int windowListPos = tokenWindowList.size(); 1030 if (!tokenWindowList.isEmpty()) { 1031 // If this application has existing windows, we 1032 // simply place the new window on top of them... but 1033 // keep the starting window on top. 1034 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 1035 // Base windows go behind everything else. 1036 WindowState lowestWindow = tokenWindowList.get(0); 1037 placeWindowBefore(lowestWindow, win); 1038 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows); 1039 } else { 1040 AppWindowToken atoken = win.mAppToken; 1041 WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 1042 if (atoken != null && lastWindow == atoken.startingWindow) { 1043 placeWindowBefore(lastWindow, win); 1044 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows); 1045 } else { 1046 int newIdx = findIdxBasedOnAppTokens(win); 1047 //there is a window above this one associated with the same 1048 //apptoken note that the window could be a floating window 1049 //that was created later or a window at the top of the list of 1050 //windows associated with this token. 1051 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1052 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + 1053 N); 1054 windows.add(newIdx + 1, win); 1055 if (newIdx < 0) { 1056 // No window from token found on win's display. 1057 tokenWindowsPos = 0; 1058 } else { 1059 tokenWindowsPos = indexOfWinInWindowList( 1060 windows.get(newIdx), token.windows) + 1; 1061 } 1062 mWindowsChanged = true; 1063 } 1064 } 1065 return tokenWindowsPos; 1066 } 1067 1068 // No windows from this token on this display 1069 if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder() 1070 + " (token=" + token + ")"); 1071 // Figure out where the window should go, based on the 1072 // order of applications. 1073 WindowState pos = null; 1074 1075 final ArrayList<Task> tasks = displayContent.getTasks(); 1076 int taskNdx; 1077 int tokenNdx = -1; 1078 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1079 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1080 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 1081 final AppWindowToken t = tokens.get(tokenNdx); 1082 if (t == token) { 1083 --tokenNdx; 1084 if (tokenNdx < 0) { 1085 --taskNdx; 1086 if (taskNdx >= 0) { 1087 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1; 1088 } 1089 } 1090 break; 1091 } 1092 1093 // We haven't reached the token yet; if this token 1094 // is not going to the bottom and has windows on this display, we can 1095 // use it as an anchor for when we do reach the token. 1096 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1097 if (!t.sendingToBottom && tokenWindowList.size() > 0) { 1098 pos = tokenWindowList.get(0); 1099 } 1100 } 1101 if (tokenNdx >= 0) { 1102 // early exit 1103 break; 1104 } 1105 } 1106 1107 // We now know the index into the apps. If we found 1108 // an app window above, that gives us the position; else 1109 // we need to look some more. 1110 if (pos != null) { 1111 // Move behind any windows attached to this one. 1112 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1113 if (atoken != null) { 1114 tokenWindowList = 1115 getTokenWindowsOnDisplay(atoken, displayContent); 1116 final int NC = tokenWindowList.size(); 1117 if (NC > 0) { 1118 WindowState bottom = tokenWindowList.get(0); 1119 if (bottom.mSubLayer < 0) { 1120 pos = bottom; 1121 } 1122 } 1123 } 1124 placeWindowBefore(pos, win); 1125 return tokenWindowsPos; 1126 } 1127 1128 // Continue looking down until we find the first 1129 // token that has windows on this display. 1130 for ( ; taskNdx >= 0; --taskNdx) { 1131 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1132 for ( ; tokenNdx >= 0; --tokenNdx) { 1133 final AppWindowToken t = tokens.get(tokenNdx); 1134 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1135 final int NW = tokenWindowList.size(); 1136 if (NW > 0) { 1137 pos = tokenWindowList.get(NW-1); 1138 break; 1139 } 1140 } 1141 if (tokenNdx >= 0) { 1142 // found 1143 break; 1144 } 1145 } 1146 1147 if (pos != null) { 1148 // Move in front of any windows attached to this 1149 // one. 1150 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1151 if (atoken != null) { 1152 final int NC = atoken.windows.size(); 1153 if (NC > 0) { 1154 WindowState top = atoken.windows.get(NC-1); 1155 if (top.mSubLayer >= 0) { 1156 pos = top; 1157 } 1158 } 1159 } 1160 placeWindowAfter(pos, win); 1161 return tokenWindowsPos; 1162 } 1163 1164 // Just search for the start of this layer. 1165 final int myLayer = win.mBaseLayer; 1166 int i; 1167 for (i = 0; i < N; i++) { 1168 WindowState w = windows.get(i); 1169 if (w.mBaseLayer > myLayer) { 1170 break; 1171 } 1172 } 1173 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1174 "Based on layer: Adding window " + win + " at " + i + " of " + N); 1175 windows.add(i, win); 1176 mWindowsChanged = true; 1177 return tokenWindowsPos; 1178 } 1179 1180 private void addFreeWindowToListLocked(final WindowState win) { 1181 final WindowList windows = win.getWindowList(); 1182 1183 // Figure out where window should go, based on layer. 1184 final int myLayer = win.mBaseLayer; 1185 int i; 1186 for (i = windows.size() - 1; i >= 0; i--) { 1187 if (windows.get(i).mBaseLayer <= myLayer) { 1188 break; 1189 } 1190 } 1191 i++; 1192 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1193 "Free window: Adding window " + win + " at " + i + " of " + windows.size()); 1194 windows.add(i, win); 1195 mWindowsChanged = true; 1196 } 1197 1198 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) { 1199 final WindowToken token = win.mToken; 1200 final DisplayContent displayContent = win.getDisplayContent(); 1201 if (displayContent == null) { 1202 return; 1203 } 1204 final WindowState attached = win.mAttachedWindow; 1205 1206 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1207 1208 // Figure out this window's ordering relative to the window 1209 // it is attached to. 1210 final int NA = tokenWindowList.size(); 1211 final int sublayer = win.mSubLayer; 1212 int largestSublayer = Integer.MIN_VALUE; 1213 WindowState windowWithLargestSublayer = null; 1214 int i; 1215 for (i = 0; i < NA; i++) { 1216 WindowState w = tokenWindowList.get(i); 1217 final int wSublayer = w.mSubLayer; 1218 if (wSublayer >= largestSublayer) { 1219 largestSublayer = wSublayer; 1220 windowWithLargestSublayer = w; 1221 } 1222 if (sublayer < 0) { 1223 // For negative sublayers, we go below all windows 1224 // in the same sublayer. 1225 if (wSublayer >= sublayer) { 1226 if (addToToken) { 1227 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1228 token.windows.add(i, win); 1229 } 1230 placeWindowBefore(wSublayer >= 0 ? attached : w, win); 1231 break; 1232 } 1233 } else { 1234 // For positive sublayers, we go above all windows 1235 // in the same sublayer. 1236 if (wSublayer > sublayer) { 1237 if (addToToken) { 1238 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1239 token.windows.add(i, win); 1240 } 1241 placeWindowBefore(w, win); 1242 break; 1243 } 1244 } 1245 } 1246 if (i >= NA) { 1247 if (addToToken) { 1248 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1249 token.windows.add(win); 1250 } 1251 if (sublayer < 0) { 1252 placeWindowBefore(attached, win); 1253 } else { 1254 placeWindowAfter(largestSublayer >= 0 1255 ? windowWithLargestSublayer 1256 : attached, 1257 win); 1258 } 1259 } 1260 } 1261 1262 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) { 1263 if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win + 1264 " Callers=" + Debug.getCallers(4)); 1265 if (win.mAttachedWindow == null) { 1266 final WindowToken token = win.mToken; 1267 int tokenWindowsPos = 0; 1268 if (token.appWindowToken != null) { 1269 tokenWindowsPos = addAppWindowToListLocked(win); 1270 } else { 1271 addFreeWindowToListLocked(win); 1272 } 1273 if (addToToken) { 1274 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1275 token.windows.add(tokenWindowsPos, win); 1276 } 1277 } else { 1278 addAttachedWindowToListLocked(win, addToToken); 1279 } 1280 1281 if (win.mAppToken != null && addToToken) { 1282 win.mAppToken.allAppWindows.add(win); 1283 } 1284 } 1285 1286 static boolean canBeImeTarget(WindowState w) { 1287 final int fl = w.mAttrs.flags 1288 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1289 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) 1290 || w.mAttrs.type == TYPE_APPLICATION_STARTING) { 1291 if (DEBUG_INPUT_METHOD) { 1292 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1293 if (!w.isVisibleOrAdding()) { 1294 Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurfaceControl 1295 + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility 1296 + " policyVis=" + w.mPolicyVisibility 1297 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1298 + " attachHid=" + w.mAttachedHidden 1299 + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); 1300 if (w.mAppToken != null) { 1301 Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1302 } 1303 } 1304 } 1305 return w.isVisibleOrAdding(); 1306 } 1307 return false; 1308 } 1309 1310 /** 1311 * Dig through the WindowStates and find the one that the Input Method will target. 1312 * @param willMove 1313 * @return The index+1 in mWindows of the discovered target. 1314 */ 1315 int findDesiredInputMethodWindowIndexLocked(boolean willMove) { 1316 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1317 // same display. Or even when the current IME/target are not on the same screen as the next 1318 // IME/target. For now only look for input windows on the main screen. 1319 WindowList windows = getDefaultWindowListLocked(); 1320 WindowState w = null; 1321 int i; 1322 for (i = windows.size() - 1; i >= 0; --i) { 1323 WindowState win = windows.get(i); 1324 1325 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i 1326 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1327 if (canBeImeTarget(win)) { 1328 w = win; 1329 //Slog.i(TAG, "Putting input method here!"); 1330 1331 // Yet more tricksyness! If this window is a "starting" 1332 // window, we do actually want to be on top of it, but 1333 // it is not -really- where input will go. So if the caller 1334 // is not actually looking to move the IME, look down below 1335 // for a real window to target... 1336 if (!willMove 1337 && w.mAttrs.type == TYPE_APPLICATION_STARTING 1338 && i > 0) { 1339 WindowState wb = windows.get(i-1); 1340 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1341 i--; 1342 w = wb; 1343 } 1344 } 1345 break; 1346 } 1347 } 1348 1349 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1350 1351 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w); 1352 1353 // Now, a special case -- if the last target's window is in the 1354 // process of exiting, and is above the new target, keep on the 1355 // last target to avoid flicker. Consider for example a Dialog with 1356 // the IME shown: when the Dialog is dismissed, we want to keep 1357 // the IME above it until it is completely gone so it doesn't drop 1358 // behind the dialog or its full-screen scrim. 1359 final WindowState curTarget = mInputMethodTarget; 1360 if (curTarget != null 1361 && curTarget.isDisplayedLw() 1362 && curTarget.isClosing() 1363 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1364 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing"); 1365 return windows.indexOf(curTarget) + 1; 1366 } 1367 1368 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target=" 1369 + w + " willMove=" + willMove); 1370 1371 if (willMove && w != null) { 1372 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1373 if (token != null) { 1374 1375 // Now some fun for dealing with window animations that 1376 // modify the Z order. We need to look at all windows below 1377 // the current target that are in this app, finding the highest 1378 // visible one in layering. 1379 WindowState highestTarget = null; 1380 int highestPos = 0; 1381 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1382 WindowList curWindows = curTarget.getWindowList(); 1383 int pos = curWindows.indexOf(curTarget); 1384 while (pos >= 0) { 1385 WindowState win = curWindows.get(pos); 1386 if (win.mAppToken != token) { 1387 break; 1388 } 1389 if (!win.mRemoved) { 1390 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1391 highestTarget.mWinAnimator.mAnimLayer) { 1392 highestTarget = win; 1393 highestPos = pos; 1394 } 1395 } 1396 pos--; 1397 } 1398 } 1399 1400 if (highestTarget != null) { 1401 if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget 1402 + " animating=" + highestTarget.mWinAnimator.isAnimating() 1403 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1404 + " new layer=" + w.mWinAnimator.mAnimLayer); 1405 1406 if (mAppTransition.isTransitionSet()) { 1407 // If we are currently setting up for an animation, 1408 // hold everything until we can find out what will happen. 1409 mInputMethodTargetWaitingAnim = true; 1410 mInputMethodTarget = highestTarget; 1411 return highestPos + 1; 1412 } else if (highestTarget.mWinAnimator.isAnimating() && 1413 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1414 // If the window we are currently targeting is involved 1415 // with an animation, and it is on top of the next target 1416 // we will be over, then hold off on moving until 1417 // that is done. 1418 mInputMethodTargetWaitingAnim = true; 1419 mInputMethodTarget = highestTarget; 1420 return highestPos + 1; 1421 } 1422 } 1423 } 1424 } 1425 1426 //Slog.i(TAG, "Placing input method @" + (i+1)); 1427 if (w != null) { 1428 if (willMove) { 1429 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to " 1430 + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1431 mInputMethodTarget = w; 1432 mInputMethodTargetWaitingAnim = false; 1433 if (w.mAppToken != null) { 1434 setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment); 1435 } else { 1436 setInputMethodAnimLayerAdjustment(0); 1437 } 1438 } 1439 return i+1; 1440 } 1441 if (willMove) { 1442 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null." 1443 + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1444 mInputMethodTarget = null; 1445 setInputMethodAnimLayerAdjustment(0); 1446 } 1447 return -1; 1448 } 1449 1450 void addInputMethodWindowToListLocked(WindowState win) { 1451 int pos = findDesiredInputMethodWindowIndexLocked(true); 1452 if (pos >= 0) { 1453 win.mTargetAppToken = mInputMethodTarget.mAppToken; 1454 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1455 TAG, "Adding input method window " + win + " at " + pos); 1456 // TODO(multidisplay): IMEs are only supported on the default display. 1457 getDefaultWindowListLocked().add(pos, win); 1458 mWindowsChanged = true; 1459 moveInputMethodDialogsLocked(pos+1); 1460 return; 1461 } 1462 win.mTargetAppToken = null; 1463 addWindowToListInOrderLocked(win, true); 1464 moveInputMethodDialogsLocked(pos); 1465 } 1466 1467 void setInputMethodAnimLayerAdjustment(int adj) { 1468 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj); 1469 mInputMethodAnimLayerAdjustment = adj; 1470 WindowState imw = mInputMethodWindow; 1471 if (imw != null) { 1472 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1473 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1474 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1475 int wi = imw.mChildWindows.size(); 1476 while (wi > 0) { 1477 wi--; 1478 WindowState cw = imw.mChildWindows.get(wi); 1479 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj; 1480 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw 1481 + " anim layer: " + cw.mWinAnimator.mAnimLayer); 1482 } 1483 } 1484 int di = mInputMethodDialogs.size(); 1485 while (di > 0) { 1486 di --; 1487 imw = mInputMethodDialogs.get(di); 1488 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1489 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1490 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1491 } 1492 } 1493 1494 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { 1495 WindowList windows = win.getWindowList(); 1496 int wpos = windows.indexOf(win); 1497 if (wpos >= 0) { 1498 if (wpos < interestingPos) interestingPos--; 1499 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win); 1500 windows.remove(wpos); 1501 mWindowsChanged = true; 1502 int NC = win.mChildWindows.size(); 1503 while (NC > 0) { 1504 NC--; 1505 WindowState cw = win.mChildWindows.get(NC); 1506 int cpos = windows.indexOf(cw); 1507 if (cpos >= 0) { 1508 if (cpos < interestingPos) interestingPos--; 1509 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at " 1510 + cpos + ": " + cw); 1511 windows.remove(cpos); 1512 } 1513 } 1514 } 1515 return interestingPos; 1516 } 1517 1518 private void reAddWindowToListInOrderLocked(WindowState win) { 1519 addWindowToListInOrderLocked(win, false); 1520 // This is a hack to get all of the child windows added as well 1521 // at the right position. Child windows should be rare and 1522 // this case should be rare, so it shouldn't be that big a deal. 1523 WindowList windows = win.getWindowList(); 1524 int wpos = windows.indexOf(win); 1525 if (wpos >= 0) { 1526 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win); 1527 windows.remove(wpos); 1528 mWindowsChanged = true; 1529 reAddWindowLocked(wpos, win); 1530 } 1531 } 1532 1533 void logWindowList(final WindowList windows, String prefix) { 1534 int N = windows.size(); 1535 while (N > 0) { 1536 N--; 1537 Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N)); 1538 } 1539 } 1540 1541 void moveInputMethodDialogsLocked(int pos) { 1542 ArrayList<WindowState> dialogs = mInputMethodDialogs; 1543 1544 // TODO(multidisplay): IMEs are only supported on the default display. 1545 WindowList windows = getDefaultWindowListLocked(); 1546 final int N = dialogs.size(); 1547 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos); 1548 for (int i=0; i<N; i++) { 1549 pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); 1550 } 1551 if (DEBUG_INPUT_METHOD) { 1552 Slog.v(TAG, "Window list w/pos=" + pos); 1553 logWindowList(windows, " "); 1554 } 1555 1556 if (pos >= 0) { 1557 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; 1558 // Skip windows owned by the input method. 1559 if (mInputMethodWindow != null) { 1560 while (pos < windows.size()) { 1561 WindowState wp = windows.get(pos); 1562 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) { 1563 pos++; 1564 continue; 1565 } 1566 break; 1567 } 1568 } 1569 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos); 1570 for (int i=0; i<N; i++) { 1571 WindowState win = dialogs.get(i); 1572 win.mTargetAppToken = targetAppToken; 1573 pos = reAddWindowLocked(pos, win); 1574 } 1575 if (DEBUG_INPUT_METHOD) { 1576 Slog.v(TAG, "Final window list:"); 1577 logWindowList(windows, " "); 1578 } 1579 return; 1580 } 1581 for (int i=0; i<N; i++) { 1582 WindowState win = dialogs.get(i); 1583 win.mTargetAppToken = null; 1584 reAddWindowToListInOrderLocked(win); 1585 if (DEBUG_INPUT_METHOD) { 1586 Slog.v(TAG, "No IM target, final list:"); 1587 logWindowList(windows, " "); 1588 } 1589 } 1590 } 1591 1592 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { 1593 final WindowState imWin = mInputMethodWindow; 1594 final int DN = mInputMethodDialogs.size(); 1595 if (imWin == null && DN == 0) { 1596 return false; 1597 } 1598 1599 // TODO(multidisplay): IMEs are only supported on the default display. 1600 WindowList windows = getDefaultWindowListLocked(); 1601 1602 int imPos = findDesiredInputMethodWindowIndexLocked(true); 1603 if (imPos >= 0) { 1604 // In this case, the input method windows are to be placed 1605 // immediately above the window they are targeting. 1606 1607 // First check to see if the input method windows are already 1608 // located here, and contiguous. 1609 final int N = windows.size(); 1610 WindowState firstImWin = imPos < N 1611 ? windows.get(imPos) : null; 1612 1613 // Figure out the actual input method window that should be 1614 // at the bottom of their stack. 1615 WindowState baseImWin = imWin != null 1616 ? imWin : mInputMethodDialogs.get(0); 1617 if (baseImWin.mChildWindows.size() > 0) { 1618 WindowState cw = baseImWin.mChildWindows.get(0); 1619 if (cw.mSubLayer < 0) baseImWin = cw; 1620 } 1621 1622 if (firstImWin == baseImWin) { 1623 // The windows haven't moved... but are they still contiguous? 1624 // First find the top IM window. 1625 int pos = imPos+1; 1626 while (pos < N) { 1627 if (!(windows.get(pos)).mIsImWindow) { 1628 break; 1629 } 1630 pos++; 1631 } 1632 pos++; 1633 // Now there should be no more input method windows above. 1634 while (pos < N) { 1635 if ((windows.get(pos)).mIsImWindow) { 1636 break; 1637 } 1638 pos++; 1639 } 1640 if (pos >= N) { 1641 // Z order is good. 1642 // The IM target window may be changed, so update the mTargetAppToken. 1643 if (imWin != null) { 1644 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1645 } 1646 return false; 1647 } 1648 } 1649 1650 if (imWin != null) { 1651 if (DEBUG_INPUT_METHOD) { 1652 Slog.v(TAG, "Moving IM from " + imPos); 1653 logWindowList(windows, " "); 1654 } 1655 imPos = tmpRemoveWindowLocked(imPos, imWin); 1656 if (DEBUG_INPUT_METHOD) { 1657 Slog.v(TAG, "List after removing with new pos " + imPos + ":"); 1658 logWindowList(windows, " "); 1659 } 1660 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1661 reAddWindowLocked(imPos, imWin); 1662 if (DEBUG_INPUT_METHOD) { 1663 Slog.v(TAG, "List after moving IM to " + imPos + ":"); 1664 logWindowList(windows, " "); 1665 } 1666 if (DN > 0) moveInputMethodDialogsLocked(imPos+1); 1667 } else { 1668 moveInputMethodDialogsLocked(imPos); 1669 } 1670 1671 } else { 1672 // In this case, the input method windows go in a fixed layer, 1673 // because they aren't currently associated with a focus window. 1674 1675 if (imWin != null) { 1676 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos); 1677 tmpRemoveWindowLocked(0, imWin); 1678 imWin.mTargetAppToken = null; 1679 reAddWindowToListInOrderLocked(imWin); 1680 if (DEBUG_INPUT_METHOD) { 1681 Slog.v(TAG, "List with no IM target:"); 1682 logWindowList(windows, " "); 1683 } 1684 if (DN > 0) moveInputMethodDialogsLocked(-1); 1685 } else { 1686 moveInputMethodDialogsLocked(-1); 1687 } 1688 1689 } 1690 1691 if (needAssignLayers) { 1692 assignLayersLocked(windows); 1693 } 1694 1695 return true; 1696 } 1697 1698 final boolean isWallpaperVisible(WindowState wallpaperTarget) { 1699 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" 1700 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") 1701 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) 1702 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null) 1703 + " upper=" + mUpperWallpaperTarget 1704 + " lower=" + mLowerWallpaperTarget); 1705 return (wallpaperTarget != null 1706 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null 1707 && wallpaperTarget.mAppToken.mAppAnimator.animation != null))) 1708 || mUpperWallpaperTarget != null 1709 || mLowerWallpaperTarget != null; 1710 } 1711 1712 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; 1713 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; 1714 1715 int adjustWallpaperWindowsLocked() { 1716 mInnerFields.mWallpaperMayChange = false; 1717 boolean targetChanged = false; 1718 1719 // TODO(multidisplay): Wallpapers on main screen only. 1720 final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo(); 1721 final int dw = displayInfo.logicalWidth; 1722 final int dh = displayInfo.logicalHeight; 1723 1724 // First find top-most window that has asked to be on top of the 1725 // wallpaper; all wallpapers go behind it. 1726 final WindowList windows = getDefaultWindowListLocked(); 1727 int N = windows.size(); 1728 WindowState w = null; 1729 WindowState foundW = null; 1730 int foundI = 0; 1731 WindowState topCurW = null; 1732 int topCurI = 0; 1733 int windowDetachedI = -1; 1734 int i = N; 1735 while (i > 0) { 1736 i--; 1737 w = windows.get(i); 1738 if ((w.mAttrs.type == TYPE_WALLPAPER)) { 1739 if (topCurW == null) { 1740 topCurW = w; 1741 topCurI = i; 1742 } 1743 continue; 1744 } 1745 topCurW = null; 1746 if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) { 1747 // If this window's app token is hidden and not animating, 1748 // it is of no interest to us. 1749 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) { 1750 if (DEBUG_WALLPAPER) Slog.v(TAG, 1751 "Skipping hidden and not animating token: " + w); 1752 continue; 1753 } 1754 } 1755 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen=" 1756 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState); 1757 1758 // If the app is executing an animation because the keyguard is going away, keep the 1759 // wallpaper during the animation so it doesn't flicker out. 1760 final boolean hasWallpaper = (w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 1761 || (w.mAppToken != null 1762 && w.mWinAnimator.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.name, 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 // Force an additional layout pass where WindowStateAnimator# 9543 // commitFinishDrawingLocked() will call performShowLocked(). 9544 displayContent.layoutNeeded = true; 9545 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9546 } 9547 } 9548 } 9549 } 9550 } 9551 } 9552 9553 // "Something has changed! Let's make it correct now." 9554 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9555 if (DEBUG_WINDOW_TRACE) { 9556 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9557 + Debug.getCallers(3)); 9558 } 9559 9560 final long currentTime = SystemClock.uptimeMillis(); 9561 9562 int i; 9563 boolean updateInputWindowsNeeded = false; 9564 9565 if (mFocusMayChange) { 9566 mFocusMayChange = false; 9567 updateInputWindowsNeeded = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9568 false /*updateInputWindows*/); 9569 } 9570 9571 // Initialize state of exiting tokens. 9572 final int numDisplays = mDisplayContents.size(); 9573 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9574 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9575 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9576 displayContent.mExitingTokens.get(i).hasVisible = false; 9577 } 9578 } 9579 9580 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9581 // Initialize state of exiting applications. 9582 final AppTokenList exitingAppTokens = 9583 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9584 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9585 exitingAppTokens.get(tokenNdx).hasVisible = false; 9586 } 9587 } 9588 9589 mInnerFields.mHoldScreen = null; 9590 mInnerFields.mScreenBrightness = -1; 9591 mInnerFields.mButtonBrightness = -1; 9592 mInnerFields.mUserActivityTimeout = -1; 9593 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9594 9595 mTransactionSequence++; 9596 9597 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9598 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9599 final int defaultDw = defaultInfo.logicalWidth; 9600 final int defaultDh = defaultInfo.logicalHeight; 9601 9602 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9603 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9604 SurfaceControl.openTransaction(); 9605 try { 9606 9607 if (mWatermark != null) { 9608 mWatermark.positionSurface(defaultDw, defaultDh); 9609 } 9610 if (mStrictModeFlash != null) { 9611 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9612 } 9613 if (mCircularDisplayMask != null) { 9614 mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation); 9615 } 9616 if (mEmulatorDisplayOverlay != null) { 9617 mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, mRotation); 9618 } 9619 9620 boolean focusDisplayed = false; 9621 9622 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9623 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9624 boolean updateAllDrawn = false; 9625 WindowList windows = displayContent.getWindowList(); 9626 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9627 final int displayId = displayContent.getDisplayId(); 9628 final int dw = displayInfo.logicalWidth; 9629 final int dh = displayInfo.logicalHeight; 9630 final int innerDw = displayInfo.appWidth; 9631 final int innerDh = displayInfo.appHeight; 9632 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9633 9634 // Reset for each display. 9635 mInnerFields.mDisplayHasContent = false; 9636 mInnerFields.mPreferredRefreshRate = 0; 9637 9638 int repeats = 0; 9639 do { 9640 repeats++; 9641 if (repeats > 6) { 9642 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9643 displayContent.layoutNeeded = false; 9644 break; 9645 } 9646 9647 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9648 displayContent.pendingLayoutChanges); 9649 9650 if ((displayContent.pendingLayoutChanges & 9651 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9652 (adjustWallpaperWindowsLocked() & 9653 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9654 assignLayersLocked(windows); 9655 displayContent.layoutNeeded = true; 9656 } 9657 9658 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9659 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9660 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9661 if (updateOrientationFromAppTokensLocked(true)) { 9662 displayContent.layoutNeeded = true; 9663 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9664 } 9665 } 9666 9667 if ((displayContent.pendingLayoutChanges 9668 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9669 displayContent.layoutNeeded = true; 9670 } 9671 9672 // FIRST LOOP: Perform a layout, if needed. 9673 if (repeats < 4) { 9674 performLayoutLockedInner(displayContent, repeats == 1, 9675 false /*updateInputWindows*/); 9676 } else { 9677 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9678 } 9679 9680 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9681 // it is animating. 9682 displayContent.pendingLayoutChanges = 0; 9683 9684 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9685 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9686 9687 if (isDefaultDisplay) { 9688 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9689 for (i = windows.size() - 1; i >= 0; i--) { 9690 WindowState w = windows.get(i); 9691 if (w.mHasSurface) { 9692 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.mAttachedWindow); 9693 } 9694 } 9695 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9696 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9697 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9698 } 9699 } while (displayContent.pendingLayoutChanges != 0); 9700 9701 mInnerFields.mObscured = false; 9702 mInnerFields.mSyswin = false; 9703 displayContent.resetDimming(); 9704 9705 // Only used if default window 9706 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9707 9708 final int N = windows.size(); 9709 for (i=N-1; i>=0; i--) { 9710 WindowState w = windows.get(i); 9711 final TaskStack stack = w.getStack(); 9712 if (stack == null && w.getAttrs().type != TYPE_PRIVATE_PRESENTATION) { 9713 continue; 9714 } 9715 9716 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9717 9718 // Update effect. 9719 w.mObscured = mInnerFields.mObscured; 9720 if (!mInnerFields.mObscured) { 9721 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9722 } 9723 9724 if (stack != null && !stack.testDimmingTag()) { 9725 handleFlagDimBehind(w); 9726 } 9727 9728 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9729 && w.isVisibleLw()) { 9730 // This is the wallpaper target and its obscured state 9731 // changed... make sure the current wallaper's visibility 9732 // has been updated accordingly. 9733 updateWallpaperVisibilityLocked(); 9734 } 9735 9736 final WindowStateAnimator winAnimator = w.mWinAnimator; 9737 9738 // If the window has moved due to its containing 9739 // content frame changing, then we'd like to animate 9740 // it. 9741 if (w.mHasSurface && w.shouldAnimateMove()) { 9742 // Frame has moved, containing content frame 9743 // has also moved, and we're not currently animating... 9744 // let's do something. 9745 Animation a = AnimationUtils.loadAnimation(mContext, 9746 com.android.internal.R.anim.window_move_from_decor); 9747 winAnimator.setAnimation(a); 9748 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9749 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9750 9751 //TODO (multidisplay): Accessibility supported only for the default display. 9752 if (mAccessibilityController != null 9753 && displayId == Display.DEFAULT_DISPLAY) { 9754 mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 9755 } 9756 9757 try { 9758 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9759 } catch (RemoteException e) { 9760 } 9761 } 9762 9763 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9764 w.mContentChanged = false; 9765 9766 // Moved from updateWindowsAndWallpaperLocked(). 9767 if (w.mHasSurface) { 9768 // Take care of the window being ready to display. 9769 final boolean committed = 9770 winAnimator.commitFinishDrawingLocked(currentTime); 9771 if (isDefaultDisplay && committed) { 9772 if (w.mAttrs.type == TYPE_DREAM) { 9773 // HACK: When a dream is shown, it may at that 9774 // point hide the lock screen. So we need to 9775 // redo the layout to let the phone window manager 9776 // make this happen. 9777 displayContent.pendingLayoutChanges |= 9778 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9779 if (DEBUG_LAYOUT_REPEATS) { 9780 debugLayoutRepeats( 9781 "dream and commitFinishDrawingLocked true", 9782 displayContent.pendingLayoutChanges); 9783 } 9784 } 9785 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9786 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9787 "First draw done in potential wallpaper target " + w); 9788 mInnerFields.mWallpaperMayChange = true; 9789 displayContent.pendingLayoutChanges |= 9790 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9791 if (DEBUG_LAYOUT_REPEATS) { 9792 debugLayoutRepeats( 9793 "wallpaper and commitFinishDrawingLocked true", 9794 displayContent.pendingLayoutChanges); 9795 } 9796 } 9797 } 9798 9799 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9800 9801 final AppWindowToken atoken = w.mAppToken; 9802 if (DEBUG_STARTING_WINDOW && atoken != null 9803 && w == atoken.startingWindow) { 9804 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9805 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9806 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9807 } 9808 if (atoken != null 9809 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9810 if (atoken.lastTransactionSequence != mTransactionSequence) { 9811 atoken.lastTransactionSequence = mTransactionSequence; 9812 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9813 atoken.startingDisplayed = false; 9814 } 9815 if ((w.isOnScreenIgnoringKeyguard() 9816 || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9817 && !w.mExiting && !w.mDestroying) { 9818 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9819 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9820 + ", isAnimating=" + winAnimator.isAnimating()); 9821 if (!w.isDrawnLw()) { 9822 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9823 + " pv=" + w.mPolicyVisibility 9824 + " mDrawState=" + winAnimator.drawStateToString() 9825 + " ah=" + w.mAttachedHidden 9826 + " th=" + atoken.hiddenRequested 9827 + " a=" + winAnimator.mAnimating); 9828 } 9829 } 9830 if (w != atoken.startingWindow) { 9831 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9832 atoken.numInterestingWindows++; 9833 if (w.isDrawnLw()) { 9834 atoken.numDrawnWindows++; 9835 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9836 "tokenMayBeDrawn: " + atoken 9837 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9838 + " mAppFreezing=" + w.mAppFreezing); 9839 updateAllDrawn = true; 9840 } 9841 } 9842 } else if (w.isDrawnLw()) { 9843 atoken.startingDisplayed = true; 9844 } 9845 } 9846 } 9847 } 9848 9849 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9850 && w.isDisplayedLw()) { 9851 focusDisplayed = true; 9852 } 9853 9854 updateResizingWindows(w); 9855 } 9856 9857 mDisplayManagerInternal.setDisplayProperties(displayId, 9858 mInnerFields.mDisplayHasContent, mInnerFields.mPreferredRefreshRate, 9859 true /* inTraversal, must call performTraversalInTrans... below */); 9860 9861 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9862 9863 if (updateAllDrawn) { 9864 updateAllDrawnLocked(displayContent); 9865 } 9866 } 9867 9868 if (focusDisplayed) { 9869 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9870 } 9871 9872 // Give the display manager a chance to adjust properties 9873 // like display rotation if it needs to. 9874 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9875 9876 } catch (RuntimeException e) { 9877 Slog.wtf(TAG, "Unhandled exception in Window Manager", e); 9878 } finally { 9879 SurfaceControl.closeTransaction(); 9880 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9881 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9882 } 9883 9884 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9885 9886 // If we are ready to perform an app transition, check through 9887 // all of the app tokens to be shown and see if they are ready 9888 // to go. 9889 if (mAppTransition.isReady()) { 9890 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9891 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9892 defaultDisplay.pendingLayoutChanges); 9893 } 9894 9895 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9896 // We have finished the animation of an app transition. To do 9897 // this, we have delayed a lot of operations like showing and 9898 // hiding apps, moving apps in Z-order, etc. The app token list 9899 // reflects the correct Z-order, but the window list may now 9900 // be out of sync with it. So here we will just rebuild the 9901 // entire app window list. Fun! 9902 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9903 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9904 defaultDisplay.pendingLayoutChanges); 9905 } 9906 9907 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9908 && !mAppTransition.isReady()) { 9909 // At this point, there was a window with a wallpaper that 9910 // was force hiding other windows behind it, but now it 9911 // is going away. This may be simple -- just animate 9912 // away the wallpaper and its window -- or it may be 9913 // hard -- the wallpaper now needs to be shown behind 9914 // something that was hidden. 9915 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9916 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9917 defaultDisplay.pendingLayoutChanges); 9918 } 9919 mInnerFields.mWallpaperForceHidingChanged = false; 9920 9921 if (mInnerFields.mWallpaperMayChange) { 9922 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9923 defaultDisplay.pendingLayoutChanges |= 9924 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9925 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9926 defaultDisplay.pendingLayoutChanges); 9927 } 9928 9929 if (mFocusMayChange) { 9930 mFocusMayChange = false; 9931 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9932 false /*updateInputWindows*/)) { 9933 updateInputWindowsNeeded = true; 9934 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9935 } 9936 } 9937 9938 if (needsLayout()) { 9939 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9940 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9941 defaultDisplay.pendingLayoutChanges); 9942 } 9943 9944 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9945 WindowState win = mResizingWindows.get(i); 9946 if (win.mAppFreezing) { 9947 // Don't remove this window until rotation has completed. 9948 continue; 9949 } 9950 win.reportResized(); 9951 mResizingWindows.remove(i); 9952 } 9953 9954 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9955 "With display frozen, orientationChangeComplete=" 9956 + mInnerFields.mOrientationChangeComplete); 9957 if (mInnerFields.mOrientationChangeComplete) { 9958 if (mWindowsFreezingScreen) { 9959 mWindowsFreezingScreen = false; 9960 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9961 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9962 } 9963 stopFreezingDisplayLocked(); 9964 } 9965 9966 // Destroy the surface of any windows that are no longer visible. 9967 boolean wallpaperDestroyed = false; 9968 i = mDestroySurface.size(); 9969 if (i > 0) { 9970 do { 9971 i--; 9972 WindowState win = mDestroySurface.get(i); 9973 win.mDestroying = false; 9974 if (mInputMethodWindow == win) { 9975 mInputMethodWindow = null; 9976 } 9977 if (win == mWallpaperTarget) { 9978 wallpaperDestroyed = true; 9979 } 9980 win.mWinAnimator.destroySurfaceLocked(); 9981 } while (i > 0); 9982 mDestroySurface.clear(); 9983 } 9984 9985 // Time to remove any exiting tokens? 9986 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9987 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9988 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9989 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9990 WindowToken token = exitingTokens.get(i); 9991 if (!token.hasVisible) { 9992 exitingTokens.remove(i); 9993 if (token.windowType == TYPE_WALLPAPER) { 9994 mWallpaperTokens.remove(token); 9995 } 9996 } 9997 } 9998 } 9999 10000 // Time to remove any exiting applications? 10001 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 10002 // Initialize state of exiting applications. 10003 final AppTokenList exitingAppTokens = 10004 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 10005 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 10006 AppWindowToken token = exitingAppTokens.get(i); 10007 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 10008 // Make sure there is no animation running on this token, 10009 // so any windows associated with it will be removed as 10010 // soon as their animations are complete 10011 token.mAppAnimator.clearAnimation(); 10012 token.mAppAnimator.animating = false; 10013 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 10014 "performLayout: App token exiting now removed" + token); 10015 removeAppFromTaskLocked(token); 10016 exitingAppTokens.remove(i); 10017 } 10018 } 10019 } 10020 10021 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 10022 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 10023 try { 10024 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 10025 } catch (RemoteException e) { 10026 } 10027 } 10028 mRelayoutWhileAnimating.clear(); 10029 } 10030 10031 if (wallpaperDestroyed) { 10032 defaultDisplay.pendingLayoutChanges |= 10033 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 10034 defaultDisplay.layoutNeeded = true; 10035 } 10036 10037 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10038 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10039 if (displayContent.pendingLayoutChanges != 0) { 10040 displayContent.layoutNeeded = true; 10041 } 10042 } 10043 10044 // Finally update all input windows now that the window changes have stabilized. 10045 mInputMonitor.updateInputWindowsLw(true /*force*/); 10046 10047 setHoldScreenLocked(mInnerFields.mHoldScreen); 10048 if (!mDisplayFrozen) { 10049 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 10050 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 10051 } else { 10052 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 10053 toBrightnessOverride(mInnerFields.mScreenBrightness)); 10054 } 10055 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 10056 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 10057 } else { 10058 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 10059 toBrightnessOverride(mInnerFields.mButtonBrightness)); 10060 } 10061 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 10062 mInnerFields.mUserActivityTimeout); 10063 } 10064 10065 if (mTurnOnScreen) { 10066 if (mAllowTheaterModeWakeFromLayout 10067 || Settings.Global.getInt(mContext.getContentResolver(), 10068 Settings.Global.THEATER_MODE_ON, 0) == 0) { 10069 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 10070 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 10071 } 10072 mTurnOnScreen = false; 10073 } 10074 10075 if (mInnerFields.mUpdateRotation) { 10076 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10077 if (updateRotationUncheckedLocked(false)) { 10078 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10079 } else { 10080 mInnerFields.mUpdateRotation = false; 10081 } 10082 } 10083 10084 if (mWaitingForDrawnCallback != null || 10085 (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded && 10086 !mInnerFields.mUpdateRotation)) { 10087 checkDrawnWindowsLocked(); 10088 } 10089 10090 final int N = mPendingRemove.size(); 10091 if (N > 0) { 10092 if (mPendingRemoveTmp.length < N) { 10093 mPendingRemoveTmp = new WindowState[N+10]; 10094 } 10095 mPendingRemove.toArray(mPendingRemoveTmp); 10096 mPendingRemove.clear(); 10097 DisplayContentList displayList = new DisplayContentList(); 10098 for (i = 0; i < N; i++) { 10099 WindowState w = mPendingRemoveTmp[i]; 10100 removeWindowInnerLocked(w.mSession, w); 10101 final DisplayContent displayContent = w.getDisplayContent(); 10102 if (displayContent != null && !displayList.contains(displayContent)) { 10103 displayList.add(displayContent); 10104 } 10105 } 10106 10107 for (DisplayContent displayContent : displayList) { 10108 assignLayersLocked(displayContent.getWindowList()); 10109 displayContent.layoutNeeded = true; 10110 } 10111 } 10112 10113 // Remove all deferred displays stacks, tasks, and activities. 10114 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 10115 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 10116 } 10117 10118 if (updateInputWindowsNeeded) { 10119 mInputMonitor.updateInputWindowsLw(false /*force*/); 10120 } 10121 setFocusedStackFrame(); 10122 10123 // Check to see if we are now in a state where the screen should 10124 // be enabled, because the window obscured flags have changed. 10125 enableScreenIfNeededLocked(); 10126 10127 scheduleAnimationLocked(); 10128 10129 if (DEBUG_WINDOW_TRACE) { 10130 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 10131 + mAnimator.mAnimating); 10132 } 10133 } 10134 10135 private int toBrightnessOverride(float value) { 10136 return (int)(value * PowerManager.BRIGHTNESS_ON); 10137 } 10138 10139 void checkDrawnWindowsLocked() { 10140 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 10141 return; 10142 } 10143 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 10144 WindowState win = mWaitingForDrawn.get(j); 10145 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 10146 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 10147 " mHasSurface=" + win.mHasSurface + 10148 " drawState=" + win.mWinAnimator.mDrawState); 10149 if (win.mRemoved || !win.mHasSurface) { 10150 // Window has been removed; no draw will now happen, so stop waiting. 10151 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 10152 mWaitingForDrawn.remove(win); 10153 } else if (win.hasDrawnLw()) { 10154 // Window is now drawn (and shown). 10155 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 10156 mWaitingForDrawn.remove(win); 10157 } 10158 } 10159 if (mWaitingForDrawn.isEmpty()) { 10160 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 10161 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 10162 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 10163 } 10164 } 10165 10166 void setHoldScreenLocked(final Session newHoldScreen) { 10167 final boolean hold = newHoldScreen != null; 10168 10169 if (hold && mHoldingScreenOn != newHoldScreen) { 10170 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 10171 } 10172 mHoldingScreenOn = newHoldScreen; 10173 10174 final boolean state = mHoldingScreenWakeLock.isHeld(); 10175 if (hold != state) { 10176 if (hold) { 10177 mHoldingScreenWakeLock.acquire(); 10178 mPolicy.keepScreenOnStartedLw(); 10179 } else { 10180 mPolicy.keepScreenOnStoppedLw(); 10181 mHoldingScreenWakeLock.release(); 10182 } 10183 } 10184 } 10185 10186 void requestTraversal() { 10187 synchronized (mWindowMap) { 10188 requestTraversalLocked(); 10189 } 10190 } 10191 10192 void requestTraversalLocked() { 10193 if (!mTraversalScheduled) { 10194 mTraversalScheduled = true; 10195 mH.sendEmptyMessage(H.DO_TRAVERSAL); 10196 } 10197 } 10198 10199 /** Note that Locked in this case is on mLayoutToAnim */ 10200 void scheduleAnimationLocked() { 10201 if (!mAnimationScheduled) { 10202 mAnimationScheduled = true; 10203 mChoreographer.postCallback( 10204 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 10205 } 10206 } 10207 10208 private boolean needsLayout() { 10209 final int numDisplays = mDisplayContents.size(); 10210 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10211 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10212 if (displayContent.layoutNeeded) { 10213 return true; 10214 } 10215 } 10216 return false; 10217 } 10218 10219 boolean copyAnimToLayoutParamsLocked() { 10220 boolean doRequest = false; 10221 10222 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 10223 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 10224 mInnerFields.mUpdateRotation = true; 10225 doRequest = true; 10226 } 10227 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 10228 mInnerFields.mWallpaperMayChange = true; 10229 doRequest = true; 10230 } 10231 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 10232 mInnerFields.mWallpaperForceHidingChanged = true; 10233 doRequest = true; 10234 } 10235 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 10236 mInnerFields.mOrientationChangeComplete = false; 10237 } else { 10238 mInnerFields.mOrientationChangeComplete = true; 10239 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 10240 if (mWindowsFreezingScreen) { 10241 doRequest = true; 10242 } 10243 } 10244 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 10245 mTurnOnScreen = true; 10246 } 10247 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 10248 mInnerFields.mWallpaperActionPending = true; 10249 } 10250 10251 return doRequest; 10252 } 10253 10254 /** If a window that has an animation specifying a colored background and the current wallpaper 10255 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 10256 * suddenly disappear. */ 10257 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 10258 WindowList windows = winAnimator.mWin.getWindowList(); 10259 for (int i = windows.size() - 1; i >= 0; --i) { 10260 WindowState testWin = windows.get(i); 10261 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 10262 return testWin.mWinAnimator.mAnimLayer; 10263 } 10264 } 10265 return winAnimator.mAnimLayer; 10266 } 10267 10268 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 10269 boolean secure) { 10270 final SurfaceControl surface = winAnimator.mSurfaceControl; 10271 boolean leakedSurface = false; 10272 boolean killedApps = false; 10273 10274 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 10275 winAnimator.mSession.mPid, operation); 10276 10277 if (mForceRemoves == null) { 10278 mForceRemoves = new ArrayList<WindowState>(); 10279 } 10280 10281 long callingIdentity = Binder.clearCallingIdentity(); 10282 try { 10283 // There was some problem... first, do a sanity check of the 10284 // window list to make sure we haven't left any dangling surfaces 10285 // around. 10286 10287 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 10288 final int numDisplays = mDisplayContents.size(); 10289 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10290 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 10291 final int numWindows = windows.size(); 10292 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 10293 final WindowState ws = windows.get(winNdx); 10294 WindowStateAnimator wsa = ws.mWinAnimator; 10295 if (wsa.mSurfaceControl != null) { 10296 if (!mSessions.contains(wsa.mSession)) { 10297 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 10298 + ws + " surface=" + wsa.mSurfaceControl 10299 + " token=" + ws.mToken 10300 + " pid=" + ws.mSession.mPid 10301 + " uid=" + ws.mSession.mUid); 10302 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 10303 wsa.mSurfaceControl.destroy(); 10304 wsa.mSurfaceShown = false; 10305 wsa.mSurfaceControl = null; 10306 ws.mHasSurface = false; 10307 mForceRemoves.add(ws); 10308 leakedSurface = true; 10309 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 10310 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 10311 + ws + " surface=" + wsa.mSurfaceControl 10312 + " token=" + ws.mAppToken); 10313 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 10314 wsa.mSurfaceControl.destroy(); 10315 wsa.mSurfaceShown = false; 10316 wsa.mSurfaceControl = null; 10317 ws.mHasSurface = false; 10318 leakedSurface = true; 10319 } 10320 } 10321 } 10322 } 10323 10324 if (!leakedSurface) { 10325 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 10326 SparseIntArray pidCandidates = new SparseIntArray(); 10327 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10328 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 10329 final int numWindows = windows.size(); 10330 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 10331 final WindowState ws = windows.get(winNdx); 10332 if (mForceRemoves.contains(ws)) { 10333 continue; 10334 } 10335 WindowStateAnimator wsa = ws.mWinAnimator; 10336 if (wsa.mSurfaceControl != null) { 10337 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 10338 } 10339 } 10340 if (pidCandidates.size() > 0) { 10341 int[] pids = new int[pidCandidates.size()]; 10342 for (int i=0; i<pids.length; i++) { 10343 pids[i] = pidCandidates.keyAt(i); 10344 } 10345 try { 10346 if (mActivityManager.killPids(pids, "Free memory", secure)) { 10347 killedApps = true; 10348 } 10349 } catch (RemoteException e) { 10350 } 10351 } 10352 } 10353 } 10354 10355 if (leakedSurface || killedApps) { 10356 // We managed to reclaim some memory, so get rid of the trouble 10357 // surface and ask the app to request another one. 10358 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 10359 if (surface != null) { 10360 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 10361 "RECOVER DESTROY", null); 10362 surface.destroy(); 10363 winAnimator.mSurfaceShown = false; 10364 winAnimator.mSurfaceControl = null; 10365 winAnimator.mWin.mHasSurface = false; 10366 scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken); 10367 } 10368 10369 try { 10370 winAnimator.mWin.mClient.dispatchGetNewSurface(); 10371 } catch (RemoteException e) { 10372 } 10373 } 10374 } finally { 10375 Binder.restoreCallingIdentity(callingIdentity); 10376 } 10377 10378 return leakedSurface || killedApps; 10379 } 10380 10381 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 10382 WindowState newFocus = computeFocusedWindowLocked(); 10383 if (mCurrentFocus != newFocus) { 10384 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 10385 // This check makes sure that we don't already have the focus 10386 // change message pending. 10387 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 10388 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 10389 // TODO(multidisplay): Focused windows on default display only. 10390 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10391 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 10392 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 10393 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 10394 if (imWindowChanged) { 10395 displayContent.layoutNeeded = true; 10396 newFocus = computeFocusedWindowLocked(); 10397 } 10398 10399 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 10400 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 10401 final WindowState oldFocus = mCurrentFocus; 10402 mCurrentFocus = newFocus; 10403 mLosingFocus.remove(newFocus); 10404 10405 // TODO(multidisplay): Accessibilty supported only of default desiplay. 10406 if (mAccessibilityController != null 10407 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 10408 mAccessibilityController.onWindowFocusChangedLocked(); 10409 } 10410 10411 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 10412 10413 if (imWindowChanged && oldFocus != mInputMethodWindow) { 10414 // Focus of the input method window changed. Perform layout if needed. 10415 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 10416 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 10417 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 10418 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 10419 // Client will do the layout, but we need to assign layers 10420 // for handleNewWindowLocked() below. 10421 assignLayersLocked(displayContent.getWindowList()); 10422 } 10423 } 10424 10425 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 10426 // The change in focus caused us to need to do a layout. Okay. 10427 displayContent.layoutNeeded = true; 10428 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 10429 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 10430 } 10431 } 10432 10433 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 10434 // If we defer assigning layers, then the caller is responsible for 10435 // doing this part. 10436 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 10437 } 10438 10439 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 10440 return true; 10441 } 10442 return false; 10443 } 10444 10445 private WindowState computeFocusedWindowLocked() { 10446 if (mAnimator.mUniverseBackground != null 10447 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 10448 return mAnimator.mUniverseBackground.mWin; 10449 } 10450 10451 final int displayCount = mDisplayContents.size(); 10452 for (int i = 0; i < displayCount; i++) { 10453 final DisplayContent displayContent = mDisplayContents.valueAt(i); 10454 WindowState win = findFocusedWindowLocked(displayContent); 10455 if (win != null) { 10456 return win; 10457 } 10458 } 10459 return null; 10460 } 10461 10462 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 10463 final WindowList windows = displayContent.getWindowList(); 10464 for (int i = windows.size() - 1; i >= 0; i--) { 10465 final WindowState win = windows.get(i); 10466 10467 if (localLOGV || DEBUG_FOCUS) Slog.v( 10468 TAG, "Looking for focus: " + i 10469 + " = " + win 10470 + ", flags=" + win.mAttrs.flags 10471 + ", canReceive=" + win.canReceiveKeys()); 10472 10473 AppWindowToken wtoken = win.mAppToken; 10474 10475 // If this window's application has been removed, just skip it. 10476 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 10477 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 10478 + (wtoken.removed ? "removed" : "sendingToBottom")); 10479 continue; 10480 } 10481 10482 if (!win.canReceiveKeys()) { 10483 continue; 10484 } 10485 10486 // Descend through all of the app tokens and find the first that either matches 10487 // win.mAppToken (return win) or mFocusedApp (return null). 10488 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 10489 mFocusedApp != null) { 10490 ArrayList<Task> tasks = displayContent.getTasks(); 10491 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 10492 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 10493 int tokenNdx = tokens.size() - 1; 10494 for ( ; tokenNdx >= 0; --tokenNdx) { 10495 final AppWindowToken token = tokens.get(tokenNdx); 10496 if (wtoken == token) { 10497 break; 10498 } 10499 if (mFocusedApp == token) { 10500 // Whoops, we are below the focused app... no focus for you! 10501 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 10502 "findFocusedWindow: Reached focused app=" + mFocusedApp); 10503 return null; 10504 } 10505 } 10506 if (tokenNdx >= 0) { 10507 // Early exit from loop, must have found the matching token. 10508 break; 10509 } 10510 } 10511 } 10512 10513 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 10514 " = " + win); 10515 return win; 10516 } 10517 10518 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 10519 return null; 10520 } 10521 10522 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 10523 if (mDisplayFrozen) { 10524 return; 10525 } 10526 10527 if (!mDisplayReady || !mPolicy.isScreenOn()) { 10528 // No need to freeze the screen before the system is ready or if 10529 // the screen is off. 10530 return; 10531 } 10532 10533 mScreenFrozenLock.acquire(); 10534 10535 mDisplayFrozen = true; 10536 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 10537 mLastFinishedFreezeSource = null; 10538 10539 mInputMonitor.freezeInputDispatchingLw(); 10540 10541 // Clear the last input window -- that is just used for 10542 // clean transitions between IMEs, and if we are freezing 10543 // the screen then the whole world is changing behind the scenes. 10544 mPolicy.setLastInputMethodWindowLw(null, null); 10545 10546 if (mAppTransition.isTransitionSet()) { 10547 mAppTransition.freeze(); 10548 } 10549 10550 if (PROFILE_ORIENTATION) { 10551 File file = new File("/data/system/frozen"); 10552 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10553 } 10554 10555 if (CUSTOM_SCREEN_ROTATION) { 10556 mExitAnimId = exitAnim; 10557 mEnterAnimId = enterAnim; 10558 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10559 final int displayId = displayContent.getDisplayId(); 10560 ScreenRotationAnimation screenRotationAnimation = 10561 mAnimator.getScreenRotationAnimationLocked(displayId); 10562 if (screenRotationAnimation != null) { 10563 screenRotationAnimation.kill(); 10564 } 10565 10566 // Check whether the current screen contains any secure content. 10567 boolean isSecure = false; 10568 final WindowList windows = getDefaultWindowListLocked(); 10569 final int N = windows.size(); 10570 for (int i = 0; i < N; i++) { 10571 WindowState ws = windows.get(i); 10572 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10573 isSecure = true; 10574 break; 10575 } 10576 } 10577 10578 // TODO(multidisplay): rotation on main screen only. 10579 displayContent.updateDisplayInfo(); 10580 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10581 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10582 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10583 } 10584 } 10585 10586 private void stopFreezingDisplayLocked() { 10587 if (!mDisplayFrozen) { 10588 return; 10589 } 10590 10591 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10592 || mClientFreezingScreen) { 10593 if (DEBUG_ORIENTATION) Slog.d(TAG, 10594 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10595 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10596 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10597 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10598 return; 10599 } 10600 10601 mDisplayFrozen = false; 10602 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10603 StringBuilder sb = new StringBuilder(128); 10604 sb.append("Screen frozen for "); 10605 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10606 if (mLastFinishedFreezeSource != null) { 10607 sb.append(" due to "); 10608 sb.append(mLastFinishedFreezeSource); 10609 } 10610 Slog.i(TAG, sb.toString()); 10611 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10612 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10613 if (PROFILE_ORIENTATION) { 10614 Debug.stopMethodTracing(); 10615 } 10616 10617 boolean updateRotation = false; 10618 10619 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10620 final int displayId = displayContent.getDisplayId(); 10621 ScreenRotationAnimation screenRotationAnimation = 10622 mAnimator.getScreenRotationAnimationLocked(displayId); 10623 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10624 && screenRotationAnimation.hasScreenshot()) { 10625 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10626 // TODO(multidisplay): rotation on main screen only. 10627 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10628 // Get rotation animation again, with new top window 10629 boolean isDimming = displayContent.isDimming(); 10630 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10631 mExitAnimId = mEnterAnimId = 0; 10632 } 10633 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10634 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 10635 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10636 scheduleAnimationLocked(); 10637 } else { 10638 screenRotationAnimation.kill(); 10639 screenRotationAnimation = null; 10640 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10641 updateRotation = true; 10642 } 10643 } else { 10644 if (screenRotationAnimation != null) { 10645 screenRotationAnimation.kill(); 10646 screenRotationAnimation = null; 10647 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10648 } 10649 updateRotation = true; 10650 } 10651 10652 mInputMonitor.thawInputDispatchingLw(); 10653 10654 boolean configChanged; 10655 10656 // While the display is frozen we don't re-compute the orientation 10657 // to avoid inconsistent states. However, something interesting 10658 // could have actually changed during that time so re-evaluate it 10659 // now to catch that. 10660 configChanged = updateOrientationFromAppTokensLocked(false); 10661 10662 // A little kludge: a lot could have happened while the 10663 // display was frozen, so now that we are coming back we 10664 // do a gc so that any remote references the system 10665 // processes holds on others can be released if they are 10666 // no longer needed. 10667 mH.removeMessages(H.FORCE_GC); 10668 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10669 10670 mScreenFrozenLock.release(); 10671 10672 if (updateRotation) { 10673 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10674 configChanged |= updateRotationUncheckedLocked(false); 10675 } 10676 10677 if (configChanged) { 10678 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10679 } 10680 } 10681 10682 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10683 DisplayMetrics dm) { 10684 if (index < tokens.length) { 10685 String str = tokens[index]; 10686 if (str != null && str.length() > 0) { 10687 try { 10688 int val = Integer.parseInt(str); 10689 return val; 10690 } catch (Exception e) { 10691 } 10692 } 10693 } 10694 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10695 return defDps; 10696 } 10697 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10698 return val; 10699 } 10700 10701 void createWatermarkInTransaction() { 10702 if (mWatermark != null) { 10703 return; 10704 } 10705 10706 File file = new File("/system/etc/setup.conf"); 10707 FileInputStream in = null; 10708 DataInputStream ind = null; 10709 try { 10710 in = new FileInputStream(file); 10711 ind = new DataInputStream(in); 10712 String line = ind.readLine(); 10713 if (line != null) { 10714 String[] toks = line.split("%"); 10715 if (toks != null && toks.length > 0) { 10716 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10717 mRealDisplayMetrics, mFxSession, toks); 10718 } 10719 } 10720 } catch (FileNotFoundException e) { 10721 } catch (IOException e) { 10722 } finally { 10723 if (ind != null) { 10724 try { 10725 ind.close(); 10726 } catch (IOException e) { 10727 } 10728 } else if (in != null) { 10729 try { 10730 in.close(); 10731 } catch (IOException e) { 10732 } 10733 } 10734 } 10735 } 10736 10737 @Override 10738 public void statusBarVisibilityChanged(int visibility) { 10739 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10740 != PackageManager.PERMISSION_GRANTED) { 10741 throw new SecurityException("Caller does not hold permission " 10742 + android.Manifest.permission.STATUS_BAR); 10743 } 10744 10745 synchronized (mWindowMap) { 10746 mLastStatusBarVisibility = visibility; 10747 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10748 updateStatusBarVisibilityLocked(visibility); 10749 } 10750 } 10751 10752 // TOOD(multidisplay): StatusBar on multiple screens? 10753 void updateStatusBarVisibilityLocked(int visibility) { 10754 mInputManager.setSystemUiVisibility(visibility); 10755 final WindowList windows = getDefaultWindowListLocked(); 10756 final int N = windows.size(); 10757 for (int i = 0; i < N; i++) { 10758 WindowState ws = windows.get(i); 10759 try { 10760 int curValue = ws.mSystemUiVisibility; 10761 int diff = curValue ^ visibility; 10762 // We are only interested in differences of one of the 10763 // clearable flags... 10764 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10765 // ...if it has actually been cleared. 10766 diff &= ~visibility; 10767 int newValue = (curValue&~diff) | (visibility&diff); 10768 if (newValue != curValue) { 10769 ws.mSeq++; 10770 ws.mSystemUiVisibility = newValue; 10771 } 10772 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10773 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10774 visibility, newValue, diff); 10775 } 10776 } catch (RemoteException e) { 10777 // so sorry 10778 } 10779 } 10780 } 10781 10782 @Override 10783 public void reevaluateStatusBarVisibility() { 10784 synchronized (mWindowMap) { 10785 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10786 updateStatusBarVisibilityLocked(visibility); 10787 performLayoutAndPlaceSurfacesLocked(); 10788 } 10789 } 10790 10791 @Override 10792 public FakeWindow addFakeWindow(Looper looper, 10793 InputEventReceiver.Factory inputEventReceiverFactory, 10794 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10795 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10796 synchronized (mWindowMap) { 10797 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10798 name, windowType, layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 10799 int i=0; 10800 while (i<mFakeWindows.size()) { 10801 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10802 break; 10803 } 10804 } 10805 mFakeWindows.add(i, fw); 10806 mInputMonitor.updateInputWindowsLw(true); 10807 return fw; 10808 } 10809 } 10810 10811 boolean removeFakeWindowLocked(FakeWindow window) { 10812 synchronized (mWindowMap) { 10813 if (mFakeWindows.remove(window)) { 10814 mInputMonitor.updateInputWindowsLw(true); 10815 return true; 10816 } 10817 return false; 10818 } 10819 } 10820 10821 // It is assumed that this method is called only by InputMethodManagerService. 10822 public void saveLastInputMethodWindowForTransition() { 10823 synchronized (mWindowMap) { 10824 // TODO(multidisplay): Pass in the displayID. 10825 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10826 if (mInputMethodWindow != null) { 10827 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10828 } 10829 } 10830 } 10831 10832 public int getInputMethodWindowVisibleHeight() { 10833 synchronized (mWindowMap) { 10834 return mPolicy.getInputMethodWindowVisibleHeightLw(); 10835 } 10836 } 10837 10838 @Override 10839 public boolean hasNavigationBar() { 10840 return mPolicy.hasNavigationBar(); 10841 } 10842 10843 @Override 10844 public void lockNow(Bundle options) { 10845 mPolicy.lockNow(options); 10846 } 10847 10848 public void showRecentApps() { 10849 mPolicy.showRecentApps(); 10850 } 10851 10852 @Override 10853 public boolean isSafeModeEnabled() { 10854 return mSafeMode; 10855 } 10856 10857 @Override 10858 public boolean clearWindowContentFrameStats(IBinder token) { 10859 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10860 "clearWindowContentFrameStats()")) { 10861 throw new SecurityException("Requires FRAME_STATS permission"); 10862 } 10863 synchronized (mWindowMap) { 10864 WindowState windowState = mWindowMap.get(token); 10865 if (windowState == null) { 10866 return false; 10867 } 10868 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10869 if (surfaceControl == null) { 10870 return false; 10871 } 10872 return surfaceControl.clearContentFrameStats(); 10873 } 10874 } 10875 10876 @Override 10877 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 10878 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10879 "getWindowContentFrameStats()")) { 10880 throw new SecurityException("Requires FRAME_STATS permission"); 10881 } 10882 synchronized (mWindowMap) { 10883 WindowState windowState = mWindowMap.get(token); 10884 if (windowState == null) { 10885 return null; 10886 } 10887 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10888 if (surfaceControl == null) { 10889 return null; 10890 } 10891 if (mTempWindowRenderStats == null) { 10892 mTempWindowRenderStats = new WindowContentFrameStats(); 10893 } 10894 WindowContentFrameStats stats = mTempWindowRenderStats; 10895 if (!surfaceControl.getContentFrameStats(stats)) { 10896 return null; 10897 } 10898 return stats; 10899 } 10900 } 10901 10902 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10903 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10904 mPolicy.dump(" ", pw, args); 10905 } 10906 10907 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10908 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10909 mAnimator.dumpLocked(pw, " ", dumpAll); 10910 } 10911 10912 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10913 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10914 if (mTokenMap.size() > 0) { 10915 pw.println(" All tokens:"); 10916 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10917 while (it.hasNext()) { 10918 WindowToken token = it.next(); 10919 pw.print(" "); pw.print(token); 10920 if (dumpAll) { 10921 pw.println(':'); 10922 token.dump(pw, " "); 10923 } else { 10924 pw.println(); 10925 } 10926 } 10927 } 10928 if (mWallpaperTokens.size() > 0) { 10929 pw.println(); 10930 pw.println(" Wallpaper tokens:"); 10931 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10932 WindowToken token = mWallpaperTokens.get(i); 10933 pw.print(" Wallpaper #"); pw.print(i); 10934 pw.print(' '); pw.print(token); 10935 if (dumpAll) { 10936 pw.println(':'); 10937 token.dump(pw, " "); 10938 } else { 10939 pw.println(); 10940 } 10941 } 10942 } 10943 if (mFinishedStarting.size() > 0) { 10944 pw.println(); 10945 pw.println(" Finishing start of application tokens:"); 10946 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10947 WindowToken token = mFinishedStarting.get(i); 10948 pw.print(" Finished Starting #"); pw.print(i); 10949 pw.print(' '); pw.print(token); 10950 if (dumpAll) { 10951 pw.println(':'); 10952 token.dump(pw, " "); 10953 } else { 10954 pw.println(); 10955 } 10956 } 10957 } 10958 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10959 pw.println(); 10960 if (mOpeningApps.size() > 0) { 10961 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10962 } 10963 if (mClosingApps.size() > 0) { 10964 pw.print(" mClosingApps="); pw.println(mClosingApps); 10965 } 10966 } 10967 } 10968 10969 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10970 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10971 for (int i=0; i<mSessions.size(); i++) { 10972 Session s = mSessions.valueAt(i); 10973 pw.print(" Session "); pw.print(s); pw.println(':'); 10974 s.dump(pw, " "); 10975 } 10976 } 10977 10978 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10979 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10980 if (mDisplayReady) { 10981 final int numDisplays = mDisplayContents.size(); 10982 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10983 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10984 displayContent.dump(" ", pw); 10985 } 10986 } else { 10987 pw.println(" NO DISPLAY"); 10988 } 10989 } 10990 10991 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10992 ArrayList<WindowState> windows) { 10993 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10994 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10995 } 10996 10997 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10998 ArrayList<WindowState> windows) { 10999 final int numDisplays = mDisplayContents.size(); 11000 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11001 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 11002 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 11003 final WindowState w = windowList.get(winNdx); 11004 if (windows == null || windows.contains(w)) { 11005 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 11006 pw.print(w); pw.println(":"); 11007 w.dump(pw, " ", dumpAll || windows != null); 11008 } 11009 } 11010 } 11011 if (mInputMethodDialogs.size() > 0) { 11012 pw.println(); 11013 pw.println(" Input method dialogs:"); 11014 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 11015 WindowState w = mInputMethodDialogs.get(i); 11016 if (windows == null || windows.contains(w)) { 11017 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 11018 } 11019 } 11020 } 11021 if (mPendingRemove.size() > 0) { 11022 pw.println(); 11023 pw.println(" Remove pending for:"); 11024 for (int i=mPendingRemove.size()-1; i>=0; i--) { 11025 WindowState w = mPendingRemove.get(i); 11026 if (windows == null || windows.contains(w)) { 11027 pw.print(" Remove #"); pw.print(i); pw.print(' '); 11028 pw.print(w); 11029 if (dumpAll) { 11030 pw.println(":"); 11031 w.dump(pw, " ", true); 11032 } else { 11033 pw.println(); 11034 } 11035 } 11036 } 11037 } 11038 if (mForceRemoves != null && mForceRemoves.size() > 0) { 11039 pw.println(); 11040 pw.println(" Windows force removing:"); 11041 for (int i=mForceRemoves.size()-1; i>=0; i--) { 11042 WindowState w = mForceRemoves.get(i); 11043 pw.print(" Removing #"); pw.print(i); pw.print(' '); 11044 pw.print(w); 11045 if (dumpAll) { 11046 pw.println(":"); 11047 w.dump(pw, " ", true); 11048 } else { 11049 pw.println(); 11050 } 11051 } 11052 } 11053 if (mDestroySurface.size() > 0) { 11054 pw.println(); 11055 pw.println(" Windows waiting to destroy their surface:"); 11056 for (int i=mDestroySurface.size()-1; i>=0; i--) { 11057 WindowState w = mDestroySurface.get(i); 11058 if (windows == null || windows.contains(w)) { 11059 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 11060 pw.print(w); 11061 if (dumpAll) { 11062 pw.println(":"); 11063 w.dump(pw, " ", true); 11064 } else { 11065 pw.println(); 11066 } 11067 } 11068 } 11069 } 11070 if (mLosingFocus.size() > 0) { 11071 pw.println(); 11072 pw.println(" Windows losing focus:"); 11073 for (int i=mLosingFocus.size()-1; i>=0; i--) { 11074 WindowState w = mLosingFocus.get(i); 11075 if (windows == null || windows.contains(w)) { 11076 pw.print(" Losing #"); pw.print(i); pw.print(' '); 11077 pw.print(w); 11078 if (dumpAll) { 11079 pw.println(":"); 11080 w.dump(pw, " ", true); 11081 } else { 11082 pw.println(); 11083 } 11084 } 11085 } 11086 } 11087 if (mResizingWindows.size() > 0) { 11088 pw.println(); 11089 pw.println(" Windows waiting to resize:"); 11090 for (int i=mResizingWindows.size()-1; i>=0; i--) { 11091 WindowState w = mResizingWindows.get(i); 11092 if (windows == null || windows.contains(w)) { 11093 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 11094 pw.print(w); 11095 if (dumpAll) { 11096 pw.println(":"); 11097 w.dump(pw, " ", true); 11098 } else { 11099 pw.println(); 11100 } 11101 } 11102 } 11103 } 11104 if (mWaitingForDrawn.size() > 0) { 11105 pw.println(); 11106 pw.println(" Clients waiting for these windows to be drawn:"); 11107 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 11108 WindowState win = mWaitingForDrawn.get(i); 11109 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 11110 } 11111 } 11112 pw.println(); 11113 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 11114 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad); 11115 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 11116 if (mLastFocus != mCurrentFocus) { 11117 pw.print(" mLastFocus="); pw.println(mLastFocus); 11118 } 11119 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 11120 if (mInputMethodTarget != null) { 11121 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 11122 } 11123 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 11124 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 11125 pw.print(" mLastDisplayFreezeDuration="); 11126 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 11127 if ( mLastFinishedFreezeSource != null) { 11128 pw.print(" due to "); 11129 pw.print(mLastFinishedFreezeSource); 11130 } 11131 pw.println(); 11132 if (dumpAll) { 11133 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 11134 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 11135 if (mLastStatusBarVisibility != 0) { 11136 pw.print(" mLastStatusBarVisibility=0x"); 11137 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 11138 } 11139 if (mInputMethodWindow != null) { 11140 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 11141 } 11142 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 11143 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 11144 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 11145 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 11146 } 11147 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 11148 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 11149 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE 11150 || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 11151 pw.print(" mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX); 11152 pw.print(" mLastWallpaperDisplayOffsetY="); 11153 pw.println(mLastWallpaperDisplayOffsetY); 11154 } 11155 if (mInputMethodAnimLayerAdjustment != 0 || 11156 mWallpaperAnimLayerAdjustment != 0) { 11157 pw.print(" mInputMethodAnimLayerAdjustment="); 11158 pw.print(mInputMethodAnimLayerAdjustment); 11159 pw.print(" mWallpaperAnimLayerAdjustment="); 11160 pw.println(mWallpaperAnimLayerAdjustment); 11161 } 11162 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 11163 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 11164 if (needsLayout()) { 11165 pw.print(" layoutNeeded on displays="); 11166 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11167 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 11168 if (displayContent.layoutNeeded) { 11169 pw.print(displayContent.getDisplayId()); 11170 } 11171 } 11172 pw.println(); 11173 } 11174 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 11175 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 11176 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 11177 pw.print(" client="); pw.print(mClientFreezingScreen); 11178 pw.print(" apps="); pw.print(mAppsFreezingScreen); 11179 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 11180 pw.print(" mRotation="); pw.print(mRotation); 11181 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 11182 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 11183 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 11184 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 11185 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 11186 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 11187 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 11188 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 11189 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 11190 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 11191 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 11192 pw.println(" mLayoutToAnim:"); 11193 mAppTransition.dump(pw); 11194 } 11195 } 11196 11197 boolean dumpWindows(PrintWriter pw, String name, String[] args, 11198 int opti, boolean dumpAll) { 11199 WindowList windows = new WindowList(); 11200 if ("visible".equals(name)) { 11201 synchronized(mWindowMap) { 11202 final int numDisplays = mDisplayContents.size(); 11203 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11204 final WindowList windowList = 11205 mDisplayContents.valueAt(displayNdx).getWindowList(); 11206 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 11207 final WindowState w = windowList.get(winNdx); 11208 if (w.mWinAnimator.mSurfaceShown) { 11209 windows.add(w); 11210 } 11211 } 11212 } 11213 } 11214 } else { 11215 int objectId = 0; 11216 // See if this is an object ID. 11217 try { 11218 objectId = Integer.parseInt(name, 16); 11219 name = null; 11220 } catch (RuntimeException e) { 11221 } 11222 synchronized(mWindowMap) { 11223 final int numDisplays = mDisplayContents.size(); 11224 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11225 final WindowList windowList = 11226 mDisplayContents.valueAt(displayNdx).getWindowList(); 11227 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 11228 final WindowState w = windowList.get(winNdx); 11229 if (name != null) { 11230 if (w.mAttrs.getTitle().toString().contains(name)) { 11231 windows.add(w); 11232 } 11233 } else if (System.identityHashCode(w) == objectId) { 11234 windows.add(w); 11235 } 11236 } 11237 } 11238 } 11239 } 11240 11241 if (windows.size() <= 0) { 11242 return false; 11243 } 11244 11245 synchronized(mWindowMap) { 11246 dumpWindowsLocked(pw, dumpAll, windows); 11247 } 11248 return true; 11249 } 11250 11251 void dumpLastANRLocked(PrintWriter pw) { 11252 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 11253 if (mLastANRState == null) { 11254 pw.println(" <no ANR has occurred since boot>"); 11255 } else { 11256 pw.println(mLastANRState); 11257 } 11258 } 11259 11260 /** 11261 * Saves information about the state of the window manager at 11262 * the time an ANR occurred before anything else in the system changes 11263 * in response. 11264 * 11265 * @param appWindowToken The application that ANR'd, may be null. 11266 * @param windowState The window that ANR'd, may be null. 11267 * @param reason The reason for the ANR, may be null. 11268 */ 11269 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 11270 String reason) { 11271 StringWriter sw = new StringWriter(); 11272 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 11273 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 11274 if (appWindowToken != null) { 11275 pw.println(" Application at fault: " + appWindowToken.stringName); 11276 } 11277 if (windowState != null) { 11278 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 11279 } 11280 if (reason != null) { 11281 pw.println(" Reason: " + reason); 11282 } 11283 pw.println(); 11284 dumpWindowsNoHeaderLocked(pw, true, null); 11285 pw.close(); 11286 mLastANRState = sw.toString(); 11287 } 11288 11289 @Override 11290 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 11291 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 11292 != PackageManager.PERMISSION_GRANTED) { 11293 pw.println("Permission Denial: can't dump WindowManager from from pid=" 11294 + Binder.getCallingPid() 11295 + ", uid=" + Binder.getCallingUid()); 11296 return; 11297 } 11298 11299 boolean dumpAll = false; 11300 11301 int opti = 0; 11302 while (opti < args.length) { 11303 String opt = args[opti]; 11304 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 11305 break; 11306 } 11307 opti++; 11308 if ("-a".equals(opt)) { 11309 dumpAll = true; 11310 } else if ("-h".equals(opt)) { 11311 pw.println("Window manager dump options:"); 11312 pw.println(" [-a] [-h] [cmd] ..."); 11313 pw.println(" cmd may be one of:"); 11314 pw.println(" l[astanr]: last ANR information"); 11315 pw.println(" p[policy]: policy state"); 11316 pw.println(" a[animator]: animator state"); 11317 pw.println(" s[essions]: active sessions"); 11318 pw.println(" surfaces: active surfaces (debugging enabled only)"); 11319 pw.println(" d[isplays]: active display contents"); 11320 pw.println(" t[okens]: token list"); 11321 pw.println(" w[indows]: window list"); 11322 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 11323 pw.println(" be a partial substring in a window name, a"); 11324 pw.println(" Window hex object identifier, or"); 11325 pw.println(" \"all\" for all windows, or"); 11326 pw.println(" \"visible\" for the visible windows."); 11327 pw.println(" -a: include all available server state."); 11328 return; 11329 } else { 11330 pw.println("Unknown argument: " + opt + "; use -h for help"); 11331 } 11332 } 11333 11334 // Is the caller requesting to dump a particular piece of data? 11335 if (opti < args.length) { 11336 String cmd = args[opti]; 11337 opti++; 11338 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 11339 synchronized(mWindowMap) { 11340 dumpLastANRLocked(pw); 11341 } 11342 return; 11343 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 11344 synchronized(mWindowMap) { 11345 dumpPolicyLocked(pw, args, true); 11346 } 11347 return; 11348 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 11349 synchronized(mWindowMap) { 11350 dumpAnimatorLocked(pw, args, true); 11351 } 11352 return; 11353 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 11354 synchronized(mWindowMap) { 11355 dumpSessionsLocked(pw, true); 11356 } 11357 return; 11358 } else if ("surfaces".equals(cmd)) { 11359 synchronized(mWindowMap) { 11360 WindowStateAnimator.SurfaceTrace.dumpAllSurfaces(pw, null); 11361 } 11362 return; 11363 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 11364 synchronized(mWindowMap) { 11365 dumpDisplayContentsLocked(pw, true); 11366 } 11367 return; 11368 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 11369 synchronized(mWindowMap) { 11370 dumpTokensLocked(pw, true); 11371 } 11372 return; 11373 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 11374 synchronized(mWindowMap) { 11375 dumpWindowsLocked(pw, true, null); 11376 } 11377 return; 11378 } else if ("all".equals(cmd) || "a".equals(cmd)) { 11379 synchronized(mWindowMap) { 11380 dumpWindowsLocked(pw, true, null); 11381 } 11382 return; 11383 } else { 11384 // Dumping a single name? 11385 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 11386 pw.println("Bad window command, or no windows match: " + cmd); 11387 pw.println("Use -h for help."); 11388 } 11389 return; 11390 } 11391 } 11392 11393 synchronized(mWindowMap) { 11394 pw.println(); 11395 if (dumpAll) { 11396 pw.println("-------------------------------------------------------------------------------"); 11397 } 11398 dumpLastANRLocked(pw); 11399 pw.println(); 11400 if (dumpAll) { 11401 pw.println("-------------------------------------------------------------------------------"); 11402 } 11403 dumpPolicyLocked(pw, args, dumpAll); 11404 pw.println(); 11405 if (dumpAll) { 11406 pw.println("-------------------------------------------------------------------------------"); 11407 } 11408 dumpAnimatorLocked(pw, args, dumpAll); 11409 pw.println(); 11410 if (dumpAll) { 11411 pw.println("-------------------------------------------------------------------------------"); 11412 } 11413 dumpSessionsLocked(pw, dumpAll); 11414 pw.println(); 11415 if (dumpAll) { 11416 pw.println("-------------------------------------------------------------------------------"); 11417 } 11418 WindowStateAnimator.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ? 11419 "-------------------------------------------------------------------------------" 11420 : null); 11421 pw.println(); 11422 if (dumpAll) { 11423 pw.println("-------------------------------------------------------------------------------"); 11424 } 11425 dumpDisplayContentsLocked(pw, dumpAll); 11426 pw.println(); 11427 if (dumpAll) { 11428 pw.println("-------------------------------------------------------------------------------"); 11429 } 11430 dumpTokensLocked(pw, dumpAll); 11431 pw.println(); 11432 if (dumpAll) { 11433 pw.println("-------------------------------------------------------------------------------"); 11434 } 11435 dumpWindowsLocked(pw, dumpAll, null); 11436 } 11437 } 11438 11439 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 11440 @Override 11441 public void monitor() { 11442 synchronized (mWindowMap) { } 11443 } 11444 11445 public interface OnHardKeyboardStatusChangeListener { 11446 public void onHardKeyboardStatusChange(boolean available); 11447 } 11448 11449 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 11450 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 11451 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 11452 Integer.toHexString(pendingLayoutChanges)); 11453 } 11454 } 11455 11456 private DisplayContent newDisplayContentLocked(final Display display) { 11457 DisplayContent displayContent = new DisplayContent(display, this); 11458 final int displayId = display.getDisplayId(); 11459 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 11460 mDisplayContents.put(displayId, displayContent); 11461 11462 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 11463 final Rect rect = new Rect(); 11464 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 11465 synchronized (displayContent.mDisplaySizeLock) { 11466 displayInfo.overscanLeft = rect.left; 11467 displayInfo.overscanTop = rect.top; 11468 displayInfo.overscanRight = rect.right; 11469 displayInfo.overscanBottom = rect.bottom; 11470 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 11471 displayId, displayInfo); 11472 } 11473 configureDisplayPolicyLocked(displayContent); 11474 11475 // TODO: Create an input channel for each display with touch capability. 11476 if (displayId == Display.DEFAULT_DISPLAY) { 11477 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 11478 registerPointerEventListener(displayContent.mTapDetector); 11479 } 11480 11481 return displayContent; 11482 } 11483 11484 public void createDisplayContentLocked(final Display display) { 11485 if (display == null) { 11486 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 11487 } 11488 getDisplayContentLocked(display.getDisplayId()); 11489 } 11490 11491 /** 11492 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 11493 * there is a Display for the displayId. 11494 * @param displayId The display the caller is interested in. 11495 * @return The DisplayContent associated with displayId or null if there is no Display for it. 11496 */ 11497 public DisplayContent getDisplayContentLocked(final int displayId) { 11498 DisplayContent displayContent = mDisplayContents.get(displayId); 11499 if (displayContent == null) { 11500 final Display display = mDisplayManager.getDisplay(displayId); 11501 if (display != null) { 11502 displayContent = newDisplayContentLocked(display); 11503 } 11504 } 11505 return displayContent; 11506 } 11507 11508 // There is an inherent assumption that this will never return null. 11509 public DisplayContent getDefaultDisplayContentLocked() { 11510 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 11511 } 11512 11513 public WindowList getDefaultWindowListLocked() { 11514 return getDefaultDisplayContentLocked().getWindowList(); 11515 } 11516 11517 public DisplayInfo getDefaultDisplayInfoLocked() { 11518 return getDefaultDisplayContentLocked().getDisplayInfo(); 11519 } 11520 11521 /** 11522 * Return the list of WindowStates associated on the passed display. 11523 * @param display The screen to return windows from. 11524 * @return The list of WindowStates on the screen, or null if the there is no screen. 11525 */ 11526 public WindowList getWindowListLocked(final Display display) { 11527 return getWindowListLocked(display.getDisplayId()); 11528 } 11529 11530 /** 11531 * Return the list of WindowStates associated on the passed display. 11532 * @param displayId The screen to return windows from. 11533 * @return The list of WindowStates on the screen, or null if the there is no screen. 11534 */ 11535 public WindowList getWindowListLocked(final int displayId) { 11536 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11537 return displayContent != null ? displayContent.getWindowList() : null; 11538 } 11539 11540 public void onDisplayAdded(int displayId) { 11541 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 11542 } 11543 11544 public void handleDisplayAdded(int displayId) { 11545 synchronized (mWindowMap) { 11546 final Display display = mDisplayManager.getDisplay(displayId); 11547 if (display != null) { 11548 createDisplayContentLocked(display); 11549 displayReady(displayId); 11550 } 11551 requestTraversalLocked(); 11552 } 11553 } 11554 11555 public void onDisplayRemoved(int displayId) { 11556 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 11557 } 11558 11559 private void handleDisplayRemovedLocked(int displayId) { 11560 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11561 if (displayContent != null) { 11562 if (displayContent.isAnimating()) { 11563 displayContent.mDeferredRemoval = true; 11564 return; 11565 } 11566 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 11567 mDisplayContents.delete(displayId); 11568 displayContent.close(); 11569 if (displayId == Display.DEFAULT_DISPLAY) { 11570 unregisterPointerEventListener(displayContent.mTapDetector); 11571 } 11572 } 11573 mAnimator.removeDisplayLocked(displayId); 11574 requestTraversalLocked(); 11575 } 11576 11577 public void onDisplayChanged(int displayId) { 11578 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 11579 } 11580 11581 private void handleDisplayChangedLocked(int displayId) { 11582 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11583 if (displayContent != null) { 11584 displayContent.updateDisplayInfo(); 11585 } 11586 requestTraversalLocked(); 11587 } 11588 11589 @Override 11590 public Object getWindowManagerLock() { 11591 return mWindowMap; 11592 } 11593 11594 private final class LocalService extends WindowManagerInternal { 11595 @Override 11596 public void requestTraversalFromDisplayManager() { 11597 requestTraversal(); 11598 } 11599 11600 @Override 11601 public void setMagnificationSpec(MagnificationSpec spec) { 11602 synchronized (mWindowMap) { 11603 if (mAccessibilityController != null) { 11604 mAccessibilityController.setMagnificationSpecLocked(spec); 11605 } else { 11606 throw new IllegalStateException("Magnification callbacks not set!"); 11607 } 11608 } 11609 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11610 spec.recycle(); 11611 } 11612 } 11613 11614 @Override 11615 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11616 synchronized (mWindowMap) { 11617 WindowState windowState = mWindowMap.get(windowToken); 11618 if (windowState == null) { 11619 return null; 11620 } 11621 MagnificationSpec spec = null; 11622 if (mAccessibilityController != null) { 11623 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11624 } 11625 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11626 return null; 11627 } 11628 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11629 spec.scale *= windowState.mGlobalScale; 11630 return spec; 11631 } 11632 } 11633 11634 @Override 11635 public void setMagnificationCallbacks(MagnificationCallbacks callbacks) { 11636 synchronized (mWindowMap) { 11637 if (mAccessibilityController == null) { 11638 mAccessibilityController = new AccessibilityController( 11639 WindowManagerService.this); 11640 } 11641 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11642 if (!mAccessibilityController.hasCallbacksLocked()) { 11643 mAccessibilityController = null; 11644 } 11645 } 11646 } 11647 11648 @Override 11649 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11650 synchronized (mWindowMap) { 11651 if (mAccessibilityController == null) { 11652 mAccessibilityController = new AccessibilityController( 11653 WindowManagerService.this); 11654 } 11655 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11656 if (!mAccessibilityController.hasCallbacksLocked()) { 11657 mAccessibilityController = null; 11658 } 11659 } 11660 } 11661 11662 @Override 11663 public void setInputFilter(IInputFilter filter) { 11664 mInputManager.setInputFilter(filter); 11665 } 11666 11667 @Override 11668 public IBinder getFocusedWindowToken() { 11669 synchronized (mWindowMap) { 11670 WindowState windowState = getFocusedWindowLocked(); 11671 if (windowState != null) { 11672 return windowState.mClient.asBinder(); 11673 } 11674 return null; 11675 } 11676 } 11677 11678 @Override 11679 public boolean isKeyguardLocked() { 11680 return WindowManagerService.this.isKeyguardLocked(); 11681 } 11682 11683 @Override 11684 public void showGlobalActions() { 11685 WindowManagerService.this.showGlobalActions(); 11686 } 11687 11688 @Override 11689 public void getWindowFrame(IBinder token, Rect outBounds) { 11690 synchronized (mWindowMap) { 11691 WindowState windowState = mWindowMap.get(token); 11692 if (windowState != null) { 11693 outBounds.set(windowState.mFrame); 11694 } else { 11695 outBounds.setEmpty(); 11696 } 11697 } 11698 } 11699 11700 @Override 11701 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 11702 synchronized (mWindowMap) { 11703 mWaitingForDrawnCallback = callback; 11704 final WindowList windows = getDefaultWindowListLocked(); 11705 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11706 final WindowState win = windows.get(winNdx); 11707 if (win.isVisibleLw() 11708 && (win.mAppToken != null || mPolicy.isForceHiding(win.mAttrs))) { 11709 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 11710 // Force add to mResizingWindows. 11711 win.mLastContentInsets.set(-1, -1, -1, -1); 11712 mWaitingForDrawn.add(win); 11713 } 11714 } 11715 requestTraversalLocked(); 11716 } 11717 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11718 if (mWaitingForDrawn.isEmpty()) { 11719 callback.run(); 11720 } else { 11721 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11722 checkDrawnWindowsLocked(); 11723 } 11724 } 11725 11726 @Override 11727 public void addWindowToken(IBinder token, int type) { 11728 WindowManagerService.this.addWindowToken(token, type); 11729 } 11730 11731 @Override 11732 public void removeWindowToken(IBinder token, boolean removeWindows) { 11733 synchronized(mWindowMap) { 11734 if (removeWindows) { 11735 WindowToken wtoken = mTokenMap.remove(token); 11736 if (wtoken != null) { 11737 wtoken.removeAllWindows(); 11738 } 11739 } 11740 WindowManagerService.this.removeWindowToken(token); 11741 } 11742 } 11743 } 11744} 11745