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