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