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