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