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