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