WindowManagerService.java revision 9a64513c7fccc2a9cf331a384906a7669b29b3f4
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wm; 18 19import static android.view.WindowManager.LayoutParams.*; 20 21import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 22import android.app.AppOpsManager; 23import android.os.Build; 24import android.os.SystemService; 25import android.util.ArraySet; 26import android.util.TimeUtils; 27import android.view.IWindowId; 28 29import android.view.IWindowSessionCallback; 30import android.view.WindowContentFrameStats; 31import com.android.internal.app.IBatteryStats; 32import com.android.internal.policy.PolicyManager; 33import com.android.internal.policy.impl.PhoneWindowManager; 34import com.android.internal.util.FastPrintWriter; 35import com.android.internal.view.IInputContext; 36import com.android.internal.view.IInputMethodClient; 37import com.android.internal.view.IInputMethodManager; 38import com.android.internal.view.WindowManagerPolicyThread; 39import com.android.server.AttributeCache; 40import com.android.server.DisplayThread; 41import com.android.server.EventLogTags; 42import com.android.server.LocalServices; 43import com.android.server.UiThread; 44import com.android.server.Watchdog; 45import com.android.server.am.BatteryStatsService; 46import com.android.server.input.InputManagerService; 47import com.android.server.power.ShutdownThread; 48 49import android.Manifest; 50import android.app.ActivityManagerNative; 51import android.app.IActivityManager; 52import android.app.StatusBarManager; 53import android.app.admin.DevicePolicyManager; 54import android.animation.ValueAnimator; 55import android.content.BroadcastReceiver; 56import android.content.ContentResolver; 57import android.content.Context; 58import android.content.Intent; 59import android.content.IntentFilter; 60import android.content.pm.ActivityInfo; 61import android.content.pm.PackageManager; 62import android.content.res.CompatibilityInfo; 63import android.content.res.Configuration; 64import android.database.ContentObserver; 65import android.graphics.Bitmap; 66import android.graphics.Bitmap.Config; 67import android.graphics.Canvas; 68import android.graphics.Matrix; 69import android.graphics.PixelFormat; 70import android.graphics.Point; 71import android.graphics.Rect; 72import android.graphics.RectF; 73import android.graphics.Region; 74import android.hardware.display.DisplayManager; 75import android.hardware.display.DisplayManagerInternal; 76import android.os.Binder; 77import android.os.Bundle; 78import android.os.Debug; 79import android.os.Handler; 80import android.os.IBinder; 81import android.os.IRemoteCallback; 82import android.os.Looper; 83import android.os.Message; 84import android.os.Parcel; 85import android.os.ParcelFileDescriptor; 86import android.os.PowerManager; 87import android.os.PowerManagerInternal; 88import android.os.Process; 89import android.os.RemoteException; 90import android.os.ServiceManager; 91import android.os.StrictMode; 92import android.os.SystemClock; 93import android.os.SystemProperties; 94import android.os.Trace; 95import android.os.UserHandle; 96import android.os.WorkSource; 97import android.provider.Settings; 98import android.util.DisplayMetrics; 99import android.util.EventLog; 100import android.util.Log; 101import android.util.SparseArray; 102import android.util.Pair; 103import android.util.Slog; 104import android.util.SparseIntArray; 105import android.util.TypedValue; 106import android.view.Choreographer; 107import android.view.Display; 108import android.view.DisplayInfo; 109import android.view.Gravity; 110import android.view.IApplicationToken; 111import android.view.IInputFilter; 112import android.view.IOnKeyguardExitResult; 113import android.view.IRotationWatcher; 114import android.view.IWindow; 115import android.view.IWindowManager; 116import android.view.IWindowSession; 117import android.view.InputChannel; 118import android.view.InputDevice; 119import android.view.InputEvent; 120import android.view.InputEventReceiver; 121import android.view.KeyEvent; 122import android.view.MagnificationSpec; 123import android.view.MotionEvent; 124import android.view.WindowManagerInternal; 125import android.view.Surface.OutOfResourcesException; 126import android.view.Surface; 127import android.view.SurfaceControl; 128import android.view.SurfaceSession; 129import android.view.View; 130import android.view.ViewTreeObserver; 131import android.view.WindowManager; 132import android.view.WindowManagerGlobal; 133import android.view.WindowManagerPolicy; 134import android.view.WindowManager.LayoutParams; 135import android.view.WindowManagerPolicy.FakeWindow; 136import android.view.WindowManagerPolicy.PointerEventListener; 137import android.view.animation.Animation; 138import android.view.animation.AnimationUtils; 139import android.view.animation.Transformation; 140 141import java.io.BufferedWriter; 142import java.io.DataInputStream; 143import java.io.File; 144import java.io.FileDescriptor; 145import java.io.FileInputStream; 146import java.io.FileNotFoundException; 147import java.io.IOException; 148import java.io.OutputStream; 149import java.io.OutputStreamWriter; 150import java.io.PrintWriter; 151import java.io.StringWriter; 152import java.net.Socket; 153import java.text.DateFormat; 154import java.util.ArrayList; 155import java.util.Date; 156import java.util.HashMap; 157import java.util.Iterator; 158import java.util.List; 159 160/** {@hide} */ 161public class WindowManagerService extends IWindowManager.Stub 162 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { 163 static final String TAG = "WindowManager"; 164 static final boolean DEBUG = false; 165 static final boolean DEBUG_ADD_REMOVE = false; 166 static final boolean DEBUG_FOCUS = false; 167 static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false; 168 static final boolean DEBUG_ANIM = false; 169 static final boolean DEBUG_LAYOUT = false; 170 static final boolean DEBUG_RESIZE = false; 171 static final boolean DEBUG_LAYERS = false; 172 static final boolean DEBUG_INPUT = false; 173 static final boolean DEBUG_INPUT_METHOD = false; 174 static final boolean DEBUG_VISIBILITY = false; 175 static final boolean DEBUG_WINDOW_MOVEMENT = false; 176 static final boolean DEBUG_TOKEN_MOVEMENT = false; 177 static final boolean DEBUG_ORIENTATION = false; 178 static final boolean DEBUG_APP_ORIENTATION = false; 179 static final boolean DEBUG_CONFIGURATION = false; 180 static final boolean DEBUG_APP_TRANSITIONS = false; 181 static final boolean DEBUG_STARTING_WINDOW = false; 182 static final boolean DEBUG_REORDER = false; 183 static final boolean DEBUG_WALLPAPER = false; 184 static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER; 185 static final boolean DEBUG_DRAG = false; 186 static final boolean DEBUG_SCREEN_ON = false; 187 static final boolean DEBUG_SCREENSHOT = false; 188 static final boolean DEBUG_BOOT = false; 189 static final boolean DEBUG_LAYOUT_REPEATS = true; 190 static final boolean DEBUG_SURFACE_TRACE = false; 191 static final boolean DEBUG_WINDOW_TRACE = false; 192 static final boolean DEBUG_TASK_MOVEMENT = false; 193 static final boolean DEBUG_STACK = false; 194 static final boolean DEBUG_DISPLAY = false; 195 static final boolean SHOW_SURFACE_ALLOC = false; 196 static final boolean SHOW_TRANSACTIONS = false; 197 static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; 198 static final boolean HIDE_STACK_CRAWLS = true; 199 static final int LAYOUT_REPEAT_THRESHOLD = 4; 200 201 static final boolean PROFILE_ORIENTATION = false; 202 static final boolean localLOGV = DEBUG; 203 204 /** How much to multiply the policy's type layer, to reserve room 205 * for multiple windows of the same type and Z-ordering adjustment 206 * with TYPE_LAYER_OFFSET. */ 207 static final int TYPE_LAYER_MULTIPLIER = 10000; 208 209 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above 210 * or below others in the same layer. */ 211 static final int TYPE_LAYER_OFFSET = 1000; 212 213 /** How much to increment the layer for each window, to reserve room 214 * for effect surfaces between them. 215 */ 216 static final int WINDOW_LAYER_MULTIPLIER = 5; 217 218 /** 219 * Dim surface layer is immediately below target window. 220 */ 221 static final int LAYER_OFFSET_DIM = 1; 222 223 /** 224 * Blur surface layer is immediately below dim layer. 225 */ 226 static final int LAYER_OFFSET_BLUR = 2; 227 228 /** 229 * FocusedStackFrame layer is immediately above focused window. 230 */ 231 static final int LAYER_OFFSET_FOCUSED_STACK = 1; 232 233 /** 234 * Animation thumbnail is as far as possible below the window above 235 * the thumbnail (or in other words as far as possible above the window 236 * below it). 237 */ 238 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1; 239 240 /** 241 * Layer at which to put the rotation freeze snapshot. 242 */ 243 static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1; 244 245 /** 246 * Layer at which to put the mask for emulated screen sizes. 247 */ 248 static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200; 249 250 /** The maximum length we will accept for a loaded animation duration: 251 * this is 10 seconds. 252 */ 253 static final int MAX_ANIMATION_DURATION = 10*1000; 254 255 /** Amount of time (in milliseconds) to animate the fade-in-out transition for 256 * compatible windows. 257 */ 258 static final int DEFAULT_FADE_IN_OUT_DURATION = 400; 259 260 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 261 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 262 263 /** 264 * If true, the window manager will do its own custom freezing and general 265 * management of the screen during rotation. 266 */ 267 static final boolean CUSTOM_SCREEN_ROTATION = true; 268 269 // Maximum number of milliseconds to wait for input devices to be enumerated before 270 // proceding with safe mode detection. 271 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 272 273 // Default input dispatching timeout in nanoseconds. 274 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; 275 276 // Poll interval in milliseconds for watching boot animation finished. 277 private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; 278 279 // The name of the boot animation service in init.rc. 280 private static final String BOOT_ANIMATION_SERVICE = "bootanim"; 281 282 /** Minimum value for attachStack and resizeStack weight value */ 283 public static final float STACK_WEIGHT_MIN = 0.2f; 284 285 /** Maximum value for attachStack and resizeStack weight value */ 286 public static final float STACK_WEIGHT_MAX = 0.8f; 287 288 static final int UPDATE_FOCUS_NORMAL = 0; 289 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 290 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 291 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 292 293 private static final String SYSTEM_SECURE = "ro.secure"; 294 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 295 296 private static final String DENSITY_OVERRIDE = "ro.config.density_override"; 297 private static final String SIZE_OVERRIDE = "ro.config.size_override"; 298 299 private static final int MAX_SCREENSHOT_RETRIES = 3; 300 301 // The flag describing a full screen app window (where the app takes care of drawing under the 302 // SystemUI bars) 303 private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN = 304 View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 305 306 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular"; 307 308 final private KeyguardDisableHandler mKeyguardDisableHandler; 309 310 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 311 @Override 312 public void onReceive(Context context, Intent intent) { 313 final String action = intent.getAction(); 314 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) { 315 mKeyguardDisableHandler.sendEmptyMessage( 316 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED); 317 } 318 } 319 }; 320 321 /** 322 * Current user when multi-user is enabled. Don't show windows of 323 * non-current user. Also see mCurrentProfileIds. 324 */ 325 int mCurrentUserId; 326 /** 327 * Users that are profiles of the current user. These are also allowed to show windows 328 * on the current user. 329 */ 330 int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; 331 332 final Context mContext; 333 334 final boolean mHaveInputMethods; 335 336 final boolean mHasPermanentDpad; 337 338 final boolean mAllowBootMessages; 339 340 final boolean mLimitedAlphaCompositing; 341 342 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager(); 343 344 final IActivityManager mActivityManager; 345 346 final IBatteryStats mBatteryStats; 347 348 final AppOpsManager mAppOps; 349 350 final DisplaySettings mDisplaySettings; 351 352 /** 353 * All currently active sessions with clients. 354 */ 355 final ArraySet<Session> mSessions = new ArraySet<Session>(); 356 357 /** 358 * Mapping from an IWindow IBinder to the server's Window object. 359 * This is also used as the lock for all of our state. 360 * NOTE: Never call into methods that lock ActivityManagerService while holding this object. 361 */ 362 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>(); 363 364 /** 365 * Mapping from a token IBinder to a WindowToken object. 366 */ 367 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>(); 368 369 /** 370 * List of window tokens that have finished starting their application, 371 * and now need to have the policy remove their windows. 372 */ 373 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>(); 374 375 /** 376 * Fake windows added to the window manager. Note: ordered from top to 377 * bottom, opposite of mWindows. 378 */ 379 final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>(); 380 381 /** 382 * Windows that are being resized. Used so we can tell the client about 383 * the resize after closing the transaction in which we resized the 384 * underlying surface. 385 */ 386 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>(); 387 388 /** 389 * Windows whose animations have ended and now must be removed. 390 */ 391 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>(); 392 393 /** 394 * Stacks whose animations have ended and whose tasks, apps, selves may now be removed. 395 */ 396 final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>(); 397 398 /** 399 * Used when processing mPendingRemove to avoid working on the original array. 400 */ 401 WindowState[] mPendingRemoveTmp = new WindowState[20]; 402 403 /** 404 * Windows whose surface should be destroyed. 405 */ 406 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>(); 407 408 /** 409 * Windows that have lost input focus and are waiting for the new 410 * focus window to be displayed before they are told about this. 411 */ 412 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>(); 413 414 /** 415 * This is set when we have run out of memory, and will either be an empty 416 * list or contain windows that need to be force removed. 417 */ 418 ArrayList<WindowState> mForceRemoves; 419 420 /** 421 * Windows that clients are waiting to have drawn. 422 */ 423 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>(); 424 /** 425 * And the callback to make when they've all been drawn. 426 */ 427 Runnable mWaitingForDrawnCallback; 428 429 /** 430 * Windows that have called relayout() while we were running animations, 431 * so we need to tell when the animation is done. 432 */ 433 final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>(); 434 435 /** 436 * Used when rebuilding window list to keep track of windows that have 437 * been removed. 438 */ 439 WindowState[] mRebuildTmp = new WindowState[20]; 440 441 /** 442 * Stores for each user whether screencapture is disabled 443 * This array is essentially a cache for all userId for 444 * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled} 445 */ 446 SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<Boolean>(); 447 448 IInputMethodManager mInputMethodManager; 449 450 AccessibilityController mAccessibilityController; 451 452 final SurfaceSession mFxSession; 453 Watermark mWatermark; 454 StrictModeFlash mStrictModeFlash; 455 CircularDisplayMask mCircularDisplayMask; 456 EmulatorDisplayOverlay mEmulatorDisplayOverlay; 457 FocusedStackFrame mFocusedStackFrame; 458 459 int mFocusedStackLayer; 460 461 final float[] mTmpFloats = new float[9]; 462 final Rect mTmpContentRect = new Rect(); 463 464 boolean mDisplayReady; 465 boolean mSafeMode; 466 boolean mDisplayEnabled = false; 467 boolean mSystemBooted = false; 468 boolean mForceDisplayEnabled = false; 469 boolean mShowingBootMessages = false; 470 boolean mBootAnimationStopped = false; 471 472 String mLastANRState; 473 474 /** All DisplayContents in the world, kept here */ 475 SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2); 476 477 int mRotation = 0; 478 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 479 boolean mAltOrientation = false; 480 481 private boolean mKeyguardWaitingForActivityDrawn; 482 483 class RotationWatcher { 484 IRotationWatcher watcher; 485 IBinder.DeathRecipient deathRecipient; 486 RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) { 487 watcher = w; 488 deathRecipient = d; 489 } 490 } 491 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>(); 492 int mDeferredRotationPauseCount; 493 494 int mSystemDecorLayer = 0; 495 final Rect mScreenRect = new Rect(); 496 497 boolean mTraversalScheduled = false; 498 boolean mDisplayFrozen = false; 499 long mDisplayFreezeTime = 0; 500 int mLastDisplayFreezeDuration = 0; 501 Object mLastFinishedFreezeSource = null; 502 boolean mWaitingForConfig = false; 503 boolean mWindowsFreezingScreen = false; 504 boolean mClientFreezingScreen = false; 505 int mAppsFreezingScreen = 0; 506 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 507 508 int mLayoutSeq = 0; 509 510 int mLastStatusBarVisibility = 0; 511 512 // State while inside of layoutAndPlaceSurfacesLocked(). 513 boolean mFocusMayChange; 514 515 Configuration mCurConfiguration = new Configuration(); 516 517 // This is held as long as we have the screen frozen, to give us time to 518 // perform a rotation animation when turning off shows the lock screen which 519 // changes the orientation. 520 private final PowerManager.WakeLock mScreenFrozenLock; 521 522 final AppTransition mAppTransition; 523 boolean mStartingIconInTransition = false; 524 boolean mSkipAppTransitionAnimation = false; 525 526 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>(); 527 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<AppWindowToken>(); 528 529 boolean mIsTouchDevice; 530 531 final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 532 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 533 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 534 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 535 536 final H mH = new H(); 537 538 final Choreographer mChoreographer = Choreographer.getInstance(); 539 540 WindowState mCurrentFocus = null; 541 WindowState mLastFocus = null; 542 543 /** This just indicates the window the input method is on top of, not 544 * necessarily the window its input is going to. */ 545 WindowState mInputMethodTarget = null; 546 547 /** If true hold off on modifying the animation layer of mInputMethodTarget */ 548 boolean mInputMethodTargetWaitingAnim; 549 int mInputMethodAnimLayerAdjustment; 550 551 WindowState mInputMethodWindow = null; 552 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); 553 554 boolean mHardKeyboardAvailable; 555 boolean mShowImeWithHardKeyboard; 556 OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 557 SettingsObserver mSettingsObserver; 558 559 private final class SettingsObserver extends ContentObserver { 560 public SettingsObserver() { 561 super(new Handler()); 562 ContentResolver resolver = mContext.getContentResolver(); 563 resolver.registerContentObserver(Settings.Secure.getUriFor( 564 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this); 565 } 566 567 @Override 568 public void onChange(boolean selfChange) { 569 updateShowImeWithHardKeyboard(); 570 } 571 } 572 573 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); 574 575 // If non-null, this is the currently visible window that is associated 576 // with the wallpaper. 577 WindowState mWallpaperTarget = null; 578 // If non-null, we are in the middle of animating from one wallpaper target 579 // to another, and this is the lower one in Z-order. 580 WindowState mLowerWallpaperTarget = null; 581 // If non-null, we are in the middle of animating from one wallpaper target 582 // to another, and this is the higher one in Z-order. 583 WindowState mUpperWallpaperTarget = null; 584 int mWallpaperAnimLayerAdjustment; 585 float mLastWallpaperX = -1; 586 float mLastWallpaperY = -1; 587 float mLastWallpaperXStep = -1; 588 float mLastWallpaperYStep = -1; 589 int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE; 590 int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE; 591 // This is set when we are waiting for a wallpaper to tell us it is done 592 // changing its scroll position. 593 WindowState mWaitingOnWallpaper; 594 // The last time we had a timeout when waiting for a wallpaper. 595 long mLastWallpaperTimeoutTime; 596 // We give a wallpaper up to 150ms to finish scrolling. 597 static final long WALLPAPER_TIMEOUT = 150; 598 // Time we wait after a timeout before trying to wait again. 599 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000; 600 boolean mAnimateWallpaperWithTarget; 601 602 AppWindowToken mFocusedApp = null; 603 604 PowerManager mPowerManager; 605 PowerManagerInternal mPowerManagerInternal; 606 607 float mWindowAnimationScaleSetting = 1.0f; 608 float mTransitionAnimationScaleSetting = 1.0f; 609 float mAnimatorDurationScaleSetting = 1.0f; 610 boolean mAnimationsDisabled = false; 611 612 final InputManagerService mInputManager; 613 final DisplayManagerInternal mDisplayManagerInternal; 614 final DisplayManager mDisplayManager; 615 616 // Who is holding the screen on. 617 Session mHoldingScreenOn; 618 PowerManager.WakeLock mHoldingScreenWakeLock; 619 620 boolean mTurnOnScreen; 621 622 DragState mDragState = null; 623 624 // For frozen screen animations. 625 int mExitAnimId, mEnterAnimId; 626 627 /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple 628 * methods. */ 629 class LayoutFields { 630 static final int SET_UPDATE_ROTATION = 1 << 0; 631 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1; 632 static final int SET_FORCE_HIDING_CHANGED = 1 << 2; 633 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3; 634 static final int SET_TURN_ON_SCREEN = 1 << 4; 635 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5; 636 637 boolean mWallpaperForceHidingChanged = false; 638 boolean mWallpaperMayChange = false; 639 boolean mOrientationChangeComplete = true; 640 Object mLastWindowFreezeSource = null; 641 private Session mHoldScreen = null; 642 private boolean mObscured = false; 643 private boolean mSyswin = false; 644 private float mScreenBrightness = -1; 645 private float mButtonBrightness = -1; 646 private long mUserActivityTimeout = -1; 647 private boolean mUpdateRotation = false; 648 boolean mWallpaperActionPending = false; 649 650 // Set to true when the display contains content to show the user. 651 // When false, the display manager may choose to mirror or blank the display. 652 boolean mDisplayHasContent = false; 653 654 // Only set while traversing the default display based on its content. 655 // Affects the behavior of mirroring on secondary displays. 656 boolean mObscureApplicationContentOnSecondaryDisplays = false; 657 658 float mPreferredRefreshRate = 0; 659 } 660 final LayoutFields mInnerFields = new LayoutFields(); 661 662 boolean mAnimationScheduled; 663 664 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 665 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 666 private int mTransactionSequence; 667 668 /** Only do a maximum of 6 repeated layouts. After that quit */ 669 private int mLayoutRepeatCount; 670 671 final WindowAnimator mAnimator; 672 673 SparseArray<Task> mTaskIdToTask = new SparseArray<Task>(); 674 675 /** All of the TaskStacks in the window manager, unordered. For an ordered list call 676 * DisplayContent.getStacks(). */ 677 SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>(); 678 679 private final PointerEventDispatcher mPointerEventDispatcher; 680 681 private WindowContentFrameStats mTempWindowRenderStats; 682 683 final class DragInputEventReceiver extends InputEventReceiver { 684 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { 685 super(inputChannel, looper); 686 } 687 688 @Override 689 public void onInputEvent(InputEvent event) { 690 boolean handled = false; 691 try { 692 if (event instanceof MotionEvent 693 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 694 && mDragState != null) { 695 final MotionEvent motionEvent = (MotionEvent)event; 696 boolean endDrag = false; 697 final float newX = motionEvent.getRawX(); 698 final float newY = motionEvent.getRawY(); 699 700 switch (motionEvent.getAction()) { 701 case MotionEvent.ACTION_DOWN: { 702 if (DEBUG_DRAG) { 703 Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer"); 704 } 705 } break; 706 707 case MotionEvent.ACTION_MOVE: { 708 synchronized (mWindowMap) { 709 // move the surface and tell the involved window(s) where we are 710 mDragState.notifyMoveLw(newX, newY); 711 } 712 } break; 713 714 case MotionEvent.ACTION_UP: { 715 if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at " 716 + newX + "," + newY); 717 synchronized (mWindowMap) { 718 endDrag = mDragState.notifyDropLw(newX, newY); 719 } 720 } break; 721 722 case MotionEvent.ACTION_CANCEL: { 723 if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!"); 724 endDrag = true; 725 } break; 726 } 727 728 if (endDrag) { 729 if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state"); 730 // tell all the windows that the drag has ended 731 synchronized (mWindowMap) { 732 mDragState.endDragLw(); 733 } 734 } 735 736 handled = true; 737 } 738 } catch (Exception e) { 739 Slog.e(TAG, "Exception caught by drag handleMotion", e); 740 } finally { 741 finishInputEvent(event, handled); 742 } 743 } 744 } 745 746 /** 747 * Whether the UI is currently running in touch mode (not showing 748 * navigational focus because the user is directly pressing the screen). 749 */ 750 boolean mInTouchMode = true; 751 752 private ViewServer mViewServer; 753 private final ArrayList<WindowChangeListener> mWindowChangeListeners = 754 new ArrayList<WindowChangeListener>(); 755 private boolean mWindowsChanged = false; 756 757 public interface WindowChangeListener { 758 public void windowsChanged(); 759 public void focusChanged(); 760 } 761 762 final Configuration mTempConfiguration = new Configuration(); 763 764 // The desired scaling factor for compatible apps. 765 float mCompatibleScreenScale; 766 767 // If true, only the core apps and services are being launched because the device 768 // is in a special boot mode, such as being encrypted or waiting for a decryption password. 769 // For example, when this flag is true, there will be no wallpaper service. 770 final boolean mOnlyCore; 771 772 public static WindowManagerService main(final Context context, 773 final InputManagerService im, 774 final boolean haveInputMethods, final boolean showBootMsgs, 775 final boolean onlyCore) { 776 final WindowManagerService[] holder = new WindowManagerService[1]; 777 DisplayThread.getHandler().runWithScissors(new Runnable() { 778 @Override 779 public void run() { 780 holder[0] = new WindowManagerService(context, im, 781 haveInputMethods, showBootMsgs, onlyCore); 782 } 783 }, 0); 784 return holder[0]; 785 } 786 787 private void initPolicy() { 788 UiThread.getHandler().runWithScissors(new Runnable() { 789 @Override 790 public void run() { 791 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 792 793 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); 794 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer() 795 * TYPE_LAYER_MULTIPLIER 796 + TYPE_LAYER_OFFSET; 797 } 798 }, 0); 799 } 800 801 private WindowManagerService(Context context, InputManagerService inputManager, 802 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { 803 mContext = context; 804 mHaveInputMethods = haveInputMethods; 805 mAllowBootMessages = showBootMsgs; 806 mOnlyCore = onlyCore; 807 mLimitedAlphaCompositing = context.getResources().getBoolean( 808 com.android.internal.R.bool.config_sf_limitedAlpha); 809 mHasPermanentDpad = context.getResources().getBoolean( 810 com.android.internal.R.bool.config_hasPermanentDpad); 811 mInputManager = inputManager; // Must be before createDisplayContentLocked. 812 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 813 mDisplaySettings = new DisplaySettings(context); 814 mDisplaySettings.readSettingsLocked(); 815 816 LocalServices.addService(WindowManagerPolicy.class, mPolicy); 817 818 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG)); 819 820 mFxSession = new SurfaceSession(); 821 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 822 Display[] displays = mDisplayManager.getDisplays(); 823 for (Display display : displays) { 824 createDisplayContentLocked(display); 825 } 826 827 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 828 829 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 830 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 831 mPowerManagerInternal.registerLowPowerModeObserver( 832 new PowerManagerInternal.LowPowerModeListener() { 833 @Override 834 public void onLowPowerModeChanged(boolean enabled) { 835 synchronized (mWindowMap) { 836 if (mAnimationsDisabled != enabled) { 837 mAnimationsDisabled = enabled; 838 dispatchNewAnimatorScaleLocked(null); 839 } 840 } 841 } 842 }); 843 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled(); 844 mScreenFrozenLock = mPowerManager.newWakeLock( 845 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 846 mScreenFrozenLock.setReferenceCounted(false); 847 848 mAppTransition = new AppTransition(context, mH); 849 850 mActivityManager = ActivityManagerNative.getDefault(); 851 mBatteryStats = BatteryStatsService.getService(); 852 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 853 AppOpsManager.OnOpChangedInternalListener opListener = 854 new AppOpsManager.OnOpChangedInternalListener() { 855 @Override public void onOpChanged(int op, String packageName) { 856 updateAppOpsState(); 857 } 858 }; 859 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener); 860 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener); 861 862 // Get persisted window scale setting 863 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 864 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 865 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 866 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting); 867 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 868 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 869 870 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 871 IntentFilter filter = new IntentFilter(); 872 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 873 mContext.registerReceiver(mBroadcastReceiver, filter); 874 875 mSettingsObserver = new SettingsObserver(); 876 updateShowImeWithHardKeyboard(); 877 878 mHoldingScreenWakeLock = mPowerManager.newWakeLock( 879 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG); 880 mHoldingScreenWakeLock.setReferenceCounted(false); 881 882 mAnimator = new WindowAnimator(this); 883 884 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 885 initPolicy(); 886 887 // Add ourself to the Watchdog monitors. 888 Watchdog.getInstance().addMonitor(this); 889 890 SurfaceControl.openTransaction(); 891 try { 892 createWatermarkInTransaction(); 893 mFocusedStackFrame = new FocusedStackFrame( 894 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 895 } finally { 896 SurfaceControl.closeTransaction(); 897 } 898 899 showCircularDisplayMaskIfNeeded(); 900 showEmulatorDisplayOverlayIfNeeded(); 901 } 902 903 public InputMonitor getInputMonitor() { 904 return mInputMonitor; 905 } 906 907 @Override 908 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 909 throws RemoteException { 910 try { 911 return super.onTransact(code, data, reply, flags); 912 } catch (RuntimeException e) { 913 // The window manager only throws security exceptions, so let's 914 // log all others. 915 if (!(e instanceof SecurityException)) { 916 Slog.wtf(TAG, "Window Manager Crash", e); 917 } 918 throw e; 919 } 920 } 921 922 private void placeWindowAfter(WindowState pos, WindowState window) { 923 final WindowList windows = pos.getWindowList(); 924 final int i = windows.indexOf(pos); 925 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 926 TAG, "Adding window " + window + " at " 927 + (i+1) + " of " + windows.size() + " (after " + pos + ")"); 928 windows.add(i+1, window); 929 mWindowsChanged = true; 930 } 931 932 private void placeWindowBefore(WindowState pos, WindowState window) { 933 final WindowList windows = pos.getWindowList(); 934 int i = windows.indexOf(pos); 935 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 936 TAG, "Adding window " + window + " at " 937 + i + " of " + windows.size() + " (before " + pos + ")"); 938 if (i < 0) { 939 Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows); 940 i = 0; 941 } 942 windows.add(i, window); 943 mWindowsChanged = true; 944 } 945 946 //This method finds out the index of a window that has the same app token as 947 //win. used for z ordering the windows in mWindows 948 private int findIdxBasedOnAppTokens(WindowState win) { 949 WindowList windows = win.getWindowList(); 950 for(int j = windows.size() - 1; j >= 0; j--) { 951 WindowState wentry = windows.get(j); 952 if(wentry.mAppToken == win.mAppToken) { 953 return j; 954 } 955 } 956 return -1; 957 } 958 959 /** 960 * Return the list of Windows from the passed token on the given Display. 961 * @param token The token with all the windows. 962 * @param displayContent The display we are interested in. 963 * @return List of windows from token that are on displayContent. 964 */ 965 WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) { 966 final WindowList windowList = new WindowList(); 967 final int count = token.windows.size(); 968 for (int i = 0; i < count; i++) { 969 final WindowState win = token.windows.get(i); 970 if (win.getDisplayContent() == displayContent) { 971 windowList.add(win); 972 } 973 } 974 return windowList; 975 } 976 977 /** 978 * Recursive search through a WindowList and all of its windows' children. 979 * @param targetWin The window to search for. 980 * @param windows The list to search. 981 * @return The index of win in windows or of the window that is an ancestor of win. 982 */ 983 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) { 984 for (int i = windows.size() - 1; i >= 0; i--) { 985 final WindowState w = windows.get(i); 986 if (w == targetWin) { 987 return i; 988 } 989 if (!w.mChildWindows.isEmpty()) { 990 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) { 991 return i; 992 } 993 } 994 } 995 return -1; 996 } 997 998 private int addAppWindowToListLocked(final WindowState win) { 999 final IWindow client = win.mClient; 1000 final WindowToken token = win.mToken; 1001 final DisplayContent displayContent = win.getDisplayContent(); 1002 if (displayContent == null) { 1003 // It doesn't matter this display is going away. 1004 return 0; 1005 } 1006 1007 final WindowList windows = win.getWindowList(); 1008 final int N = windows.size(); 1009 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1010 int tokenWindowsPos = 0; 1011 int windowListPos = tokenWindowList.size(); 1012 if (!tokenWindowList.isEmpty()) { 1013 // If this application has existing windows, we 1014 // simply place the new window on top of them... but 1015 // keep the starting window on top. 1016 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 1017 // Base windows go behind everything else. 1018 WindowState lowestWindow = tokenWindowList.get(0); 1019 placeWindowBefore(lowestWindow, win); 1020 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows); 1021 } else { 1022 AppWindowToken atoken = win.mAppToken; 1023 WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 1024 if (atoken != null && lastWindow == atoken.startingWindow) { 1025 placeWindowBefore(lastWindow, win); 1026 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows); 1027 } else { 1028 int newIdx = findIdxBasedOnAppTokens(win); 1029 //there is a window above this one associated with the same 1030 //apptoken note that the window could be a floating window 1031 //that was created later or a window at the top of the list of 1032 //windows associated with this token. 1033 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1034 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + 1035 N); 1036 windows.add(newIdx + 1, win); 1037 if (newIdx < 0) { 1038 // No window from token found on win's display. 1039 tokenWindowsPos = 0; 1040 } else { 1041 tokenWindowsPos = indexOfWinInWindowList( 1042 windows.get(newIdx), token.windows) + 1; 1043 } 1044 mWindowsChanged = true; 1045 } 1046 } 1047 return tokenWindowsPos; 1048 } 1049 1050 // No windows from this token on this display 1051 if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder() 1052 + " (token=" + token + ")"); 1053 // Figure out where the window should go, based on the 1054 // order of applications. 1055 WindowState pos = null; 1056 1057 final ArrayList<Task> tasks = displayContent.getTasks(); 1058 int taskNdx; 1059 int tokenNdx = -1; 1060 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1061 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1062 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 1063 final AppWindowToken t = tokens.get(tokenNdx); 1064 if (t == token) { 1065 --tokenNdx; 1066 if (tokenNdx < 0) { 1067 --taskNdx; 1068 if (taskNdx >= 0) { 1069 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1; 1070 } 1071 } 1072 break; 1073 } 1074 1075 // We haven't reached the token yet; if this token 1076 // is not going to the bottom and has windows on this display, we can 1077 // use it as an anchor for when we do reach the token. 1078 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1079 if (!t.sendingToBottom && tokenWindowList.size() > 0) { 1080 pos = tokenWindowList.get(0); 1081 } 1082 } 1083 if (tokenNdx >= 0) { 1084 // early exit 1085 break; 1086 } 1087 } 1088 1089 // We now know the index into the apps. If we found 1090 // an app window above, that gives us the position; else 1091 // we need to look some more. 1092 if (pos != null) { 1093 // Move behind any windows attached to this one. 1094 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1095 if (atoken != null) { 1096 tokenWindowList = 1097 getTokenWindowsOnDisplay(atoken, displayContent); 1098 final int NC = tokenWindowList.size(); 1099 if (NC > 0) { 1100 WindowState bottom = tokenWindowList.get(0); 1101 if (bottom.mSubLayer < 0) { 1102 pos = bottom; 1103 } 1104 } 1105 } 1106 placeWindowBefore(pos, win); 1107 return tokenWindowsPos; 1108 } 1109 1110 // Continue looking down until we find the first 1111 // token that has windows on this display. 1112 for ( ; taskNdx >= 0; --taskNdx) { 1113 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1114 for ( ; tokenNdx >= 0; --tokenNdx) { 1115 final AppWindowToken t = tokens.get(tokenNdx); 1116 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1117 final int NW = tokenWindowList.size(); 1118 if (NW > 0) { 1119 pos = tokenWindowList.get(NW-1); 1120 break; 1121 } 1122 } 1123 if (tokenNdx >= 0) { 1124 // found 1125 break; 1126 } 1127 } 1128 1129 if (pos != null) { 1130 // Move in front of any windows attached to this 1131 // one. 1132 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1133 if (atoken != null) { 1134 final int NC = atoken.windows.size(); 1135 if (NC > 0) { 1136 WindowState top = atoken.windows.get(NC-1); 1137 if (top.mSubLayer >= 0) { 1138 pos = top; 1139 } 1140 } 1141 } 1142 placeWindowAfter(pos, win); 1143 return tokenWindowsPos; 1144 } 1145 1146 // Just search for the start of this layer. 1147 final int myLayer = win.mBaseLayer; 1148 int i; 1149 for (i = 0; i < N; i++) { 1150 WindowState w = windows.get(i); 1151 if (w.mBaseLayer > myLayer) { 1152 break; 1153 } 1154 } 1155 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1156 "Based on layer: Adding window " + win + " at " + i + " of " + N); 1157 windows.add(i, win); 1158 mWindowsChanged = true; 1159 return tokenWindowsPos; 1160 } 1161 1162 private void addFreeWindowToListLocked(final WindowState win) { 1163 final WindowList windows = win.getWindowList(); 1164 1165 // Figure out where window should go, based on layer. 1166 final int myLayer = win.mBaseLayer; 1167 int i; 1168 for (i = windows.size() - 1; i >= 0; i--) { 1169 if (windows.get(i).mBaseLayer <= myLayer) { 1170 break; 1171 } 1172 } 1173 i++; 1174 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1175 "Free window: Adding window " + win + " at " + i + " of " + windows.size()); 1176 windows.add(i, win); 1177 mWindowsChanged = true; 1178 } 1179 1180 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) { 1181 final WindowToken token = win.mToken; 1182 final DisplayContent displayContent = win.getDisplayContent(); 1183 if (displayContent == null) { 1184 return; 1185 } 1186 final WindowState attached = win.mAttachedWindow; 1187 1188 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1189 1190 // Figure out this window's ordering relative to the window 1191 // it is attached to. 1192 final int NA = tokenWindowList.size(); 1193 final int sublayer = win.mSubLayer; 1194 int largestSublayer = Integer.MIN_VALUE; 1195 WindowState windowWithLargestSublayer = null; 1196 int i; 1197 for (i = 0; i < NA; i++) { 1198 WindowState w = tokenWindowList.get(i); 1199 final int wSublayer = w.mSubLayer; 1200 if (wSublayer >= largestSublayer) { 1201 largestSublayer = wSublayer; 1202 windowWithLargestSublayer = w; 1203 } 1204 if (sublayer < 0) { 1205 // For negative sublayers, we go below all windows 1206 // in the same sublayer. 1207 if (wSublayer >= sublayer) { 1208 if (addToToken) { 1209 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1210 token.windows.add(i, win); 1211 } 1212 placeWindowBefore(wSublayer >= 0 ? attached : w, win); 1213 break; 1214 } 1215 } else { 1216 // For positive sublayers, we go above all windows 1217 // in the same sublayer. 1218 if (wSublayer > sublayer) { 1219 if (addToToken) { 1220 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1221 token.windows.add(i, win); 1222 } 1223 placeWindowBefore(w, win); 1224 break; 1225 } 1226 } 1227 } 1228 if (i >= NA) { 1229 if (addToToken) { 1230 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1231 token.windows.add(win); 1232 } 1233 if (sublayer < 0) { 1234 placeWindowBefore(attached, win); 1235 } else { 1236 placeWindowAfter(largestSublayer >= 0 1237 ? windowWithLargestSublayer 1238 : attached, 1239 win); 1240 } 1241 } 1242 } 1243 1244 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) { 1245 if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win + 1246 " Callers=" + Debug.getCallers(4)); 1247 if (win.mAttachedWindow == null) { 1248 final WindowToken token = win.mToken; 1249 int tokenWindowsPos = 0; 1250 if (token.appWindowToken != null) { 1251 tokenWindowsPos = addAppWindowToListLocked(win); 1252 } else { 1253 addFreeWindowToListLocked(win); 1254 } 1255 if (addToToken) { 1256 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1257 token.windows.add(tokenWindowsPos, win); 1258 } 1259 } else { 1260 addAttachedWindowToListLocked(win, addToToken); 1261 } 1262 1263 if (win.mAppToken != null && addToToken) { 1264 win.mAppToken.allAppWindows.add(win); 1265 } 1266 } 1267 1268 static boolean canBeImeTarget(WindowState w) { 1269 final int fl = w.mAttrs.flags 1270 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1271 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) 1272 || w.mAttrs.type == TYPE_APPLICATION_STARTING) { 1273 if (DEBUG_INPUT_METHOD) { 1274 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1275 if (!w.isVisibleOrAdding()) { 1276 Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurfaceControl 1277 + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility 1278 + " policyVis=" + w.mPolicyVisibility 1279 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1280 + " attachHid=" + w.mAttachedHidden 1281 + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); 1282 if (w.mAppToken != null) { 1283 Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1284 } 1285 } 1286 } 1287 return w.isVisibleOrAdding(); 1288 } 1289 return false; 1290 } 1291 1292 /** 1293 * Dig through the WindowStates and find the one that the Input Method will target. 1294 * @param willMove 1295 * @return The index+1 in mWindows of the discovered target. 1296 */ 1297 int findDesiredInputMethodWindowIndexLocked(boolean willMove) { 1298 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1299 // same display. Or even when the current IME/target are not on the same screen as the next 1300 // IME/target. For now only look for input windows on the main screen. 1301 WindowList windows = getDefaultWindowListLocked(); 1302 WindowState w = null; 1303 int i; 1304 for (i = windows.size() - 1; i >= 0; --i) { 1305 WindowState win = windows.get(i); 1306 1307 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i 1308 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1309 if (canBeImeTarget(win)) { 1310 w = win; 1311 //Slog.i(TAG, "Putting input method here!"); 1312 1313 // Yet more tricksyness! If this window is a "starting" 1314 // window, we do actually want to be on top of it, but 1315 // it is not -really- where input will go. So if the caller 1316 // is not actually looking to move the IME, look down below 1317 // for a real window to target... 1318 if (!willMove 1319 && w.mAttrs.type == TYPE_APPLICATION_STARTING 1320 && i > 0) { 1321 WindowState wb = windows.get(i-1); 1322 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1323 i--; 1324 w = wb; 1325 } 1326 } 1327 break; 1328 } 1329 } 1330 1331 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1332 1333 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w); 1334 1335 // Now, a special case -- if the last target's window is in the 1336 // process of exiting, and is above the new target, keep on the 1337 // last target to avoid flicker. Consider for example a Dialog with 1338 // the IME shown: when the Dialog is dismissed, we want to keep 1339 // the IME above it until it is completely gone so it doesn't drop 1340 // behind the dialog or its full-screen scrim. 1341 final WindowState curTarget = mInputMethodTarget; 1342 if (curTarget != null 1343 && curTarget.isDisplayedLw() 1344 && curTarget.isClosing() 1345 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1346 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing"); 1347 return windows.indexOf(curTarget) + 1; 1348 } 1349 1350 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target=" 1351 + w + " willMove=" + willMove); 1352 1353 if (willMove && w != null) { 1354 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1355 if (token != null) { 1356 1357 // Now some fun for dealing with window animations that 1358 // modify the Z order. We need to look at all windows below 1359 // the current target that are in this app, finding the highest 1360 // visible one in layering. 1361 WindowState highestTarget = null; 1362 int highestPos = 0; 1363 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1364 WindowList curWindows = curTarget.getWindowList(); 1365 int pos = curWindows.indexOf(curTarget); 1366 while (pos >= 0) { 1367 WindowState win = curWindows.get(pos); 1368 if (win.mAppToken != token) { 1369 break; 1370 } 1371 if (!win.mRemoved) { 1372 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1373 highestTarget.mWinAnimator.mAnimLayer) { 1374 highestTarget = win; 1375 highestPos = pos; 1376 } 1377 } 1378 pos--; 1379 } 1380 } 1381 1382 if (highestTarget != null) { 1383 if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget 1384 + " animating=" + highestTarget.mWinAnimator.isAnimating() 1385 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1386 + " new layer=" + w.mWinAnimator.mAnimLayer); 1387 1388 if (mAppTransition.isTransitionSet()) { 1389 // If we are currently setting up for an animation, 1390 // hold everything until we can find out what will happen. 1391 mInputMethodTargetWaitingAnim = true; 1392 mInputMethodTarget = highestTarget; 1393 return highestPos + 1; 1394 } else if (highestTarget.mWinAnimator.isAnimating() && 1395 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1396 // If the window we are currently targeting is involved 1397 // with an animation, and it is on top of the next target 1398 // we will be over, then hold off on moving until 1399 // that is done. 1400 mInputMethodTargetWaitingAnim = true; 1401 mInputMethodTarget = highestTarget; 1402 return highestPos + 1; 1403 } 1404 } 1405 } 1406 } 1407 1408 //Slog.i(TAG, "Placing input method @" + (i+1)); 1409 if (w != null) { 1410 if (willMove) { 1411 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to " 1412 + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1413 mInputMethodTarget = w; 1414 mInputMethodTargetWaitingAnim = false; 1415 if (w.mAppToken != null) { 1416 setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment); 1417 } else { 1418 setInputMethodAnimLayerAdjustment(0); 1419 } 1420 } 1421 return i+1; 1422 } 1423 if (willMove) { 1424 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null." 1425 + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1426 mInputMethodTarget = null; 1427 setInputMethodAnimLayerAdjustment(0); 1428 } 1429 return -1; 1430 } 1431 1432 void addInputMethodWindowToListLocked(WindowState win) { 1433 int pos = findDesiredInputMethodWindowIndexLocked(true); 1434 if (pos >= 0) { 1435 win.mTargetAppToken = mInputMethodTarget.mAppToken; 1436 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1437 TAG, "Adding input method window " + win + " at " + pos); 1438 // TODO(multidisplay): IMEs are only supported on the default display. 1439 getDefaultWindowListLocked().add(pos, win); 1440 mWindowsChanged = true; 1441 moveInputMethodDialogsLocked(pos+1); 1442 return; 1443 } 1444 win.mTargetAppToken = null; 1445 addWindowToListInOrderLocked(win, true); 1446 moveInputMethodDialogsLocked(pos); 1447 } 1448 1449 void setInputMethodAnimLayerAdjustment(int adj) { 1450 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj); 1451 mInputMethodAnimLayerAdjustment = adj; 1452 WindowState imw = mInputMethodWindow; 1453 if (imw != null) { 1454 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1455 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1456 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1457 int wi = imw.mChildWindows.size(); 1458 while (wi > 0) { 1459 wi--; 1460 WindowState cw = imw.mChildWindows.get(wi); 1461 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj; 1462 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw 1463 + " anim layer: " + cw.mWinAnimator.mAnimLayer); 1464 } 1465 } 1466 int di = mInputMethodDialogs.size(); 1467 while (di > 0) { 1468 di --; 1469 imw = mInputMethodDialogs.get(di); 1470 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1471 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1472 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1473 } 1474 } 1475 1476 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { 1477 WindowList windows = win.getWindowList(); 1478 int wpos = windows.indexOf(win); 1479 if (wpos >= 0) { 1480 if (wpos < interestingPos) interestingPos--; 1481 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win); 1482 windows.remove(wpos); 1483 mWindowsChanged = true; 1484 int NC = win.mChildWindows.size(); 1485 while (NC > 0) { 1486 NC--; 1487 WindowState cw = win.mChildWindows.get(NC); 1488 int cpos = windows.indexOf(cw); 1489 if (cpos >= 0) { 1490 if (cpos < interestingPos) interestingPos--; 1491 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at " 1492 + cpos + ": " + cw); 1493 windows.remove(cpos); 1494 } 1495 } 1496 } 1497 return interestingPos; 1498 } 1499 1500 private void reAddWindowToListInOrderLocked(WindowState win) { 1501 addWindowToListInOrderLocked(win, false); 1502 // This is a hack to get all of the child windows added as well 1503 // at the right position. Child windows should be rare and 1504 // this case should be rare, so it shouldn't be that big a deal. 1505 WindowList windows = win.getWindowList(); 1506 int wpos = windows.indexOf(win); 1507 if (wpos >= 0) { 1508 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win); 1509 windows.remove(wpos); 1510 mWindowsChanged = true; 1511 reAddWindowLocked(wpos, win); 1512 } 1513 } 1514 1515 void logWindowList(final WindowList windows, String prefix) { 1516 int N = windows.size(); 1517 while (N > 0) { 1518 N--; 1519 Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N)); 1520 } 1521 } 1522 1523 void moveInputMethodDialogsLocked(int pos) { 1524 ArrayList<WindowState> dialogs = mInputMethodDialogs; 1525 1526 // TODO(multidisplay): IMEs are only supported on the default display. 1527 WindowList windows = getDefaultWindowListLocked(); 1528 final int N = dialogs.size(); 1529 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos); 1530 for (int i=0; i<N; i++) { 1531 pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); 1532 } 1533 if (DEBUG_INPUT_METHOD) { 1534 Slog.v(TAG, "Window list w/pos=" + pos); 1535 logWindowList(windows, " "); 1536 } 1537 1538 if (pos >= 0) { 1539 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; 1540 // Skip windows owned by the input method. 1541 if (mInputMethodWindow != null) { 1542 while (pos < windows.size()) { 1543 WindowState wp = windows.get(pos); 1544 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) { 1545 pos++; 1546 continue; 1547 } 1548 break; 1549 } 1550 } 1551 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos); 1552 for (int i=0; i<N; i++) { 1553 WindowState win = dialogs.get(i); 1554 win.mTargetAppToken = targetAppToken; 1555 pos = reAddWindowLocked(pos, win); 1556 } 1557 if (DEBUG_INPUT_METHOD) { 1558 Slog.v(TAG, "Final window list:"); 1559 logWindowList(windows, " "); 1560 } 1561 return; 1562 } 1563 for (int i=0; i<N; i++) { 1564 WindowState win = dialogs.get(i); 1565 win.mTargetAppToken = null; 1566 reAddWindowToListInOrderLocked(win); 1567 if (DEBUG_INPUT_METHOD) { 1568 Slog.v(TAG, "No IM target, final list:"); 1569 logWindowList(windows, " "); 1570 } 1571 } 1572 } 1573 1574 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { 1575 final WindowState imWin = mInputMethodWindow; 1576 final int DN = mInputMethodDialogs.size(); 1577 if (imWin == null && DN == 0) { 1578 return false; 1579 } 1580 1581 // TODO(multidisplay): IMEs are only supported on the default display. 1582 WindowList windows = getDefaultWindowListLocked(); 1583 1584 int imPos = findDesiredInputMethodWindowIndexLocked(true); 1585 if (imPos >= 0) { 1586 // In this case, the input method windows are to be placed 1587 // immediately above the window they are targeting. 1588 1589 // First check to see if the input method windows are already 1590 // located here, and contiguous. 1591 final int N = windows.size(); 1592 WindowState firstImWin = imPos < N 1593 ? windows.get(imPos) : null; 1594 1595 // Figure out the actual input method window that should be 1596 // at the bottom of their stack. 1597 WindowState baseImWin = imWin != null 1598 ? imWin : mInputMethodDialogs.get(0); 1599 if (baseImWin.mChildWindows.size() > 0) { 1600 WindowState cw = baseImWin.mChildWindows.get(0); 1601 if (cw.mSubLayer < 0) baseImWin = cw; 1602 } 1603 1604 if (firstImWin == baseImWin) { 1605 // The windows haven't moved... but are they still contiguous? 1606 // First find the top IM window. 1607 int pos = imPos+1; 1608 while (pos < N) { 1609 if (!(windows.get(pos)).mIsImWindow) { 1610 break; 1611 } 1612 pos++; 1613 } 1614 pos++; 1615 // Now there should be no more input method windows above. 1616 while (pos < N) { 1617 if ((windows.get(pos)).mIsImWindow) { 1618 break; 1619 } 1620 pos++; 1621 } 1622 if (pos >= N) { 1623 // Z order is good. 1624 // The IM target window may be changed, so update the mTargetAppToken. 1625 if (imWin != null) { 1626 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1627 } 1628 return false; 1629 } 1630 } 1631 1632 if (imWin != null) { 1633 if (DEBUG_INPUT_METHOD) { 1634 Slog.v(TAG, "Moving IM from " + imPos); 1635 logWindowList(windows, " "); 1636 } 1637 imPos = tmpRemoveWindowLocked(imPos, imWin); 1638 if (DEBUG_INPUT_METHOD) { 1639 Slog.v(TAG, "List after removing with new pos " + imPos + ":"); 1640 logWindowList(windows, " "); 1641 } 1642 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1643 reAddWindowLocked(imPos, imWin); 1644 if (DEBUG_INPUT_METHOD) { 1645 Slog.v(TAG, "List after moving IM to " + imPos + ":"); 1646 logWindowList(windows, " "); 1647 } 1648 if (DN > 0) moveInputMethodDialogsLocked(imPos+1); 1649 } else { 1650 moveInputMethodDialogsLocked(imPos); 1651 } 1652 1653 } else { 1654 // In this case, the input method windows go in a fixed layer, 1655 // because they aren't currently associated with a focus window. 1656 1657 if (imWin != null) { 1658 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos); 1659 tmpRemoveWindowLocked(0, imWin); 1660 imWin.mTargetAppToken = null; 1661 reAddWindowToListInOrderLocked(imWin); 1662 if (DEBUG_INPUT_METHOD) { 1663 Slog.v(TAG, "List with no IM target:"); 1664 logWindowList(windows, " "); 1665 } 1666 if (DN > 0) moveInputMethodDialogsLocked(-1); 1667 } else { 1668 moveInputMethodDialogsLocked(-1); 1669 } 1670 1671 } 1672 1673 if (needAssignLayers) { 1674 assignLayersLocked(windows); 1675 } 1676 1677 return true; 1678 } 1679 1680 final boolean isWallpaperVisible(WindowState wallpaperTarget) { 1681 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" 1682 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") 1683 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) 1684 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null) 1685 + " upper=" + mUpperWallpaperTarget 1686 + " lower=" + mLowerWallpaperTarget); 1687 return (wallpaperTarget != null 1688 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null 1689 && wallpaperTarget.mAppToken.mAppAnimator.animation != null))) 1690 || mUpperWallpaperTarget != null 1691 || mLowerWallpaperTarget != null; 1692 } 1693 1694 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; 1695 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; 1696 1697 int adjustWallpaperWindowsLocked() { 1698 mInnerFields.mWallpaperMayChange = false; 1699 boolean targetChanged = false; 1700 1701 // TODO(multidisplay): Wallpapers on main screen only. 1702 final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo(); 1703 final int dw = displayInfo.logicalWidth; 1704 final int dh = displayInfo.logicalHeight; 1705 1706 // First find top-most window that has asked to be on top of the 1707 // wallpaper; all wallpapers go behind it. 1708 final WindowList windows = getDefaultWindowListLocked(); 1709 int N = windows.size(); 1710 WindowState w = null; 1711 WindowState foundW = null; 1712 int foundI = 0; 1713 WindowState topCurW = null; 1714 int topCurI = 0; 1715 int windowDetachedI = -1; 1716 int i = N; 1717 while (i > 0) { 1718 i--; 1719 w = windows.get(i); 1720 if ((w.mAttrs.type == TYPE_WALLPAPER)) { 1721 if (topCurW == null) { 1722 topCurW = w; 1723 topCurI = i; 1724 } 1725 continue; 1726 } 1727 topCurW = null; 1728 if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) { 1729 // If this window's app token is hidden and not animating, 1730 // it is of no interest to us. 1731 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) { 1732 if (DEBUG_WALLPAPER) Slog.v(TAG, 1733 "Skipping hidden and not animating token: " + w); 1734 continue; 1735 } 1736 } 1737 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen=" 1738 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState); 1739 1740 // If the app is executing an animation because the keyguard is going away, keep the 1741 // wallpaper during the animation so it doesn't flicker out. 1742 final boolean hasWallpaper = (w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 1743 || (w.mAppToken != null 1744 && w.mWinAnimator.keyguardGoingAwayAnimation); 1745 if (hasWallpaper && w.isOnScreen() 1746 && (mWallpaperTarget == w || w.isDrawFinishedLw())) { 1747 if (DEBUG_WALLPAPER) Slog.v(TAG, 1748 "Found wallpaper target: #" + i + "=" + w); 1749 foundW = w; 1750 foundI = i; 1751 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) { 1752 // The current wallpaper target is animating, so we'll 1753 // look behind it for another possible target and figure 1754 // out what is going on below. 1755 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w 1756 + ": token animating, looking behind."); 1757 continue; 1758 } 1759 break; 1760 } else if (w == mAnimator.mWindowDetachedWallpaper) { 1761 windowDetachedI = i; 1762 } 1763 } 1764 1765 if (foundW == null && windowDetachedI >= 0) { 1766 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 1767 "Found animating detached wallpaper activity: #" + i + "=" + w); 1768 foundW = w; 1769 foundI = windowDetachedI; 1770 } 1771 1772 if (mWallpaperTarget != foundW 1773 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) { 1774 if (DEBUG_WALLPAPER_LIGHT) { 1775 Slog.v(TAG, "New wallpaper target: " + foundW 1776 + " oldTarget: " + mWallpaperTarget); 1777 } 1778 1779 mLowerWallpaperTarget = null; 1780 mUpperWallpaperTarget = null; 1781 1782 WindowState oldW = mWallpaperTarget; 1783 mWallpaperTarget = foundW; 1784 targetChanged = true; 1785 1786 // Now what is happening... if the current and new targets are 1787 // animating, then we are in our super special mode! 1788 if (foundW != null && oldW != null) { 1789 boolean oldAnim = oldW.isAnimatingLw(); 1790 boolean foundAnim = foundW.isAnimatingLw(); 1791 if (DEBUG_WALLPAPER_LIGHT) { 1792 Slog.v(TAG, "New animation: " + foundAnim 1793 + " old animation: " + oldAnim); 1794 } 1795 if (foundAnim && oldAnim) { 1796 int oldI = windows.indexOf(oldW); 1797 if (DEBUG_WALLPAPER_LIGHT) { 1798 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI); 1799 } 1800 if (oldI >= 0) { 1801 if (DEBUG_WALLPAPER_LIGHT) { 1802 Slog.v(TAG, "Animating wallpapers: old#" + oldI 1803 + "=" + oldW + "; new#" + foundI 1804 + "=" + foundW); 1805 } 1806 1807 // Set the new target correctly. 1808 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) { 1809 if (DEBUG_WALLPAPER_LIGHT) { 1810 Slog.v(TAG, "Old wallpaper still the target."); 1811 } 1812 mWallpaperTarget = oldW; 1813 foundW = oldW; 1814 foundI = oldI; 1815 } 1816 // Now set the upper and lower wallpaper targets 1817 // correctly, and make sure that we are positioning 1818 // the wallpaper below the lower. 1819 else if (foundI > oldI) { 1820 // The new target is on top of the old one. 1821 if (DEBUG_WALLPAPER_LIGHT) { 1822 Slog.v(TAG, "Found target above old target."); 1823 } 1824 mUpperWallpaperTarget = foundW; 1825 mLowerWallpaperTarget = oldW; 1826 foundW = oldW; 1827 foundI = oldI; 1828 } else { 1829 // The new target is below the old one. 1830 if (DEBUG_WALLPAPER_LIGHT) { 1831 Slog.v(TAG, "Found target below old target."); 1832 } 1833 mUpperWallpaperTarget = oldW; 1834 mLowerWallpaperTarget = foundW; 1835 } 1836 } 1837 } 1838 } 1839 1840 } else if (mLowerWallpaperTarget != null) { 1841 // Is it time to stop animating? 1842 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) { 1843 if (DEBUG_WALLPAPER_LIGHT) { 1844 Slog.v(TAG, "No longer animating wallpaper targets!"); 1845 } 1846 mLowerWallpaperTarget = null; 1847 mUpperWallpaperTarget = null; 1848 mWallpaperTarget = foundW; 1849 targetChanged = true; 1850 } 1851 } 1852 1853 boolean visible = foundW != null; 1854 if (visible) { 1855 // The window is visible to the compositor... but is it visible 1856 // to the user? That is what the wallpaper cares about. 1857 visible = isWallpaperVisible(foundW); 1858 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible); 1859 1860 // If the wallpaper target is animating, we may need to copy 1861 // its layer adjustment. Only do this if we are not transfering 1862 // between two wallpaper targets. 1863 mWallpaperAnimLayerAdjustment = 1864 (mLowerWallpaperTarget == null && foundW.mAppToken != null) 1865 ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0; 1866 1867 final int maxLayer = mPolicy.getMaxWallpaperLayer() 1868 * TYPE_LAYER_MULTIPLIER 1869 + TYPE_LAYER_OFFSET; 1870 1871 // Now w is the window we are supposed to be behind... but we 1872 // need to be sure to also be behind any of its attached windows, 1873 // AND any starting window associated with it, AND below the 1874 // maximum layer the policy allows for wallpapers. 1875 while (foundI > 0) { 1876 WindowState wb = windows.get(foundI-1); 1877 if (wb.mBaseLayer < maxLayer && 1878 wb.mAttachedWindow != foundW && 1879 (foundW.mAttachedWindow == null || 1880 wb.mAttachedWindow != foundW.mAttachedWindow) && 1881 (wb.mAttrs.type != TYPE_APPLICATION_STARTING || 1882 foundW.mToken == null || wb.mToken != foundW.mToken)) { 1883 // This window is not related to the previous one in any 1884 // interesting way, so stop here. 1885 break; 1886 } 1887 foundW = wb; 1888 foundI--; 1889 } 1890 } else { 1891 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target"); 1892 } 1893 1894 if (foundW == null && topCurW != null) { 1895 // There is no wallpaper target, so it goes at the bottom. 1896 // We will assume it is the same place as last time, if known. 1897 foundW = topCurW; 1898 foundI = topCurI+1; 1899 } else { 1900 // Okay i is the position immediately above the wallpaper. Look at 1901 // what is below it for later. 1902 foundW = foundI > 0 ? windows.get(foundI-1) : null; 1903 } 1904 1905 if (visible) { 1906 if (mWallpaperTarget.mWallpaperX >= 0) { 1907 mLastWallpaperX = mWallpaperTarget.mWallpaperX; 1908 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep; 1909 } 1910 if (mWallpaperTarget.mWallpaperY >= 0) { 1911 mLastWallpaperY = mWallpaperTarget.mWallpaperY; 1912 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep; 1913 } 1914 if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) { 1915 mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX; 1916 } 1917 if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 1918 mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY; 1919 } 1920 } 1921 1922 // Start stepping backwards from here, ensuring that our wallpaper windows 1923 // are correctly placed. 1924 int changed = 0; 1925 int curTokenIndex = mWallpaperTokens.size(); 1926 while (curTokenIndex > 0) { 1927 curTokenIndex--; 1928 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1929 if (token.hidden == visible) { 1930 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, 1931 "Wallpaper token " + token + " hidden=" + !visible); 1932 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED; 1933 token.hidden = !visible; 1934 // Need to do a layout to ensure the wallpaper now has the 1935 // correct size. 1936 getDefaultDisplayContentLocked().layoutNeeded = true; 1937 } 1938 1939 int curWallpaperIndex = token.windows.size(); 1940 while (curWallpaperIndex > 0) { 1941 curWallpaperIndex--; 1942 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1943 1944 if (visible) { 1945 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 1946 } 1947 1948 // First, make sure the client has the current visibility 1949 // state. 1950 dispatchWallpaperVisibility(wallpaper, visible); 1951 1952 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; 1953 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win " 1954 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1955 1956 // First, if this window is at the current index, then all 1957 // is well. 1958 if (wallpaper == foundW) { 1959 foundI--; 1960 foundW = foundI > 0 1961 ? windows.get(foundI-1) : null; 1962 continue; 1963 } 1964 1965 // The window didn't match... the current wallpaper window, 1966 // wherever it is, is in the wrong place, so make sure it is 1967 // not in the list. 1968 int oldIndex = windows.indexOf(wallpaper); 1969 if (oldIndex >= 0) { 1970 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at " 1971 + oldIndex + ": " + wallpaper); 1972 windows.remove(oldIndex); 1973 mWindowsChanged = true; 1974 if (oldIndex < foundI) { 1975 foundI--; 1976 } 1977 } 1978 1979 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost 1980 // layer. For keyguard over wallpaper put the wallpaper under the keyguard. 1981 int insertionIndex = 0; 1982 if (visible && foundW != null) { 1983 final int type = foundW.mAttrs.type; 1984 final int privateFlags = foundW.mAttrs.privateFlags; 1985 if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 1986 || type == TYPE_KEYGUARD_SCRIM) { 1987 insertionIndex = windows.indexOf(foundW); 1988 } 1989 } 1990 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 1991 Slog.v(TAG, "Moving wallpaper " + wallpaper 1992 + " from " + oldIndex + " to " + insertionIndex); 1993 } 1994 1995 windows.add(insertionIndex, wallpaper); 1996 mWindowsChanged = true; 1997 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED; 1998 } 1999 } 2000 2001 /* 2002 final TaskStack targetStack = 2003 mWallpaperTarget == null ? null : mWallpaperTarget.getStack(); 2004 if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 && 2005 targetStack != null && !targetStack.isHomeStack()) { 2006 // If the wallpaper target is not on the home stack then make sure that all windows 2007 // from other non-home stacks are above the wallpaper. 2008 for (i = foundI - 1; i >= 0; --i) { 2009 WindowState win = windows.get(i); 2010 if (!win.isVisibleLw()) { 2011 continue; 2012 } 2013 final TaskStack winStack = win.getStack(); 2014 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) { 2015 windows.remove(i); 2016 windows.add(foundI + 1, win); 2017 } 2018 } 2019 } 2020 */ 2021 2022 if (targetChanged && DEBUG_WALLPAPER_LIGHT) { 2023 Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget 2024 + " lower=" + mLowerWallpaperTarget + " upper=" 2025 + mUpperWallpaperTarget); 2026 } 2027 2028 return changed; 2029 } 2030 2031 void setWallpaperAnimLayerAdjustmentLocked(int adj) { 2032 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, 2033 "Setting wallpaper layer adj to " + adj); 2034 mWallpaperAnimLayerAdjustment = adj; 2035 int curTokenIndex = mWallpaperTokens.size(); 2036 while (curTokenIndex > 0) { 2037 curTokenIndex--; 2038 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2039 int curWallpaperIndex = token.windows.size(); 2040 while (curWallpaperIndex > 0) { 2041 curWallpaperIndex--; 2042 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2043 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj; 2044 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win " 2045 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 2046 } 2047 } 2048 } 2049 2050 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh, 2051 boolean sync) { 2052 boolean changed = false; 2053 boolean rawChanged = false; 2054 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f; 2055 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f; 2056 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw; 2057 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0; 2058 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) { 2059 offset += mLastWallpaperDisplayOffsetX; 2060 } 2061 changed = wallpaperWin.mXOffset != offset; 2062 if (changed) { 2063 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 2064 + wallpaperWin + " x: " + offset); 2065 wallpaperWin.mXOffset = offset; 2066 } 2067 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) { 2068 wallpaperWin.mWallpaperX = wpx; 2069 wallpaperWin.mWallpaperXStep = wpxs; 2070 rawChanged = true; 2071 } 2072 2073 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f; 2074 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f; 2075 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh; 2076 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0; 2077 if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 2078 offset += mLastWallpaperDisplayOffsetY; 2079 } 2080 if (wallpaperWin.mYOffset != offset) { 2081 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 2082 + wallpaperWin + " y: " + offset); 2083 changed = true; 2084 wallpaperWin.mYOffset = offset; 2085 } 2086 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) { 2087 wallpaperWin.mWallpaperY = wpy; 2088 wallpaperWin.mWallpaperYStep = wpys; 2089 rawChanged = true; 2090 } 2091 2092 if (rawChanged && (wallpaperWin.mAttrs.privateFlags & 2093 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) { 2094 try { 2095 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset " 2096 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX 2097 + " y=" + wallpaperWin.mWallpaperY); 2098 if (sync) { 2099 mWaitingOnWallpaper = wallpaperWin; 2100 } 2101 wallpaperWin.mClient.dispatchWallpaperOffsets( 2102 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, 2103 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync); 2104 if (sync) { 2105 if (mWaitingOnWallpaper != null) { 2106 long start = SystemClock.uptimeMillis(); 2107 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) 2108 < start) { 2109 try { 2110 if (DEBUG_WALLPAPER) Slog.v(TAG, 2111 "Waiting for offset complete..."); 2112 mWindowMap.wait(WALLPAPER_TIMEOUT); 2113 } catch (InterruptedException e) { 2114 } 2115 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!"); 2116 if ((start+WALLPAPER_TIMEOUT) 2117 < SystemClock.uptimeMillis()) { 2118 Slog.i(TAG, "Timeout waiting for wallpaper to offset: " 2119 + wallpaperWin); 2120 mLastWallpaperTimeoutTime = start; 2121 } 2122 } 2123 mWaitingOnWallpaper = null; 2124 } 2125 } 2126 } catch (RemoteException e) { 2127 } 2128 } 2129 2130 return changed; 2131 } 2132 2133 void wallpaperOffsetsComplete(IBinder window) { 2134 synchronized (mWindowMap) { 2135 if (mWaitingOnWallpaper != null && 2136 mWaitingOnWallpaper.mClient.asBinder() == window) { 2137 mWaitingOnWallpaper = null; 2138 mWindowMap.notifyAll(); 2139 } 2140 } 2141 } 2142 2143 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) { 2144 final DisplayContent displayContent = changingTarget.getDisplayContent(); 2145 if (displayContent == null) { 2146 return; 2147 } 2148 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2149 final int dw = displayInfo.logicalWidth; 2150 final int dh = displayInfo.logicalHeight; 2151 2152 WindowState target = mWallpaperTarget; 2153 if (target != null) { 2154 if (target.mWallpaperX >= 0) { 2155 mLastWallpaperX = target.mWallpaperX; 2156 } else if (changingTarget.mWallpaperX >= 0) { 2157 mLastWallpaperX = changingTarget.mWallpaperX; 2158 } 2159 if (target.mWallpaperY >= 0) { 2160 mLastWallpaperY = target.mWallpaperY; 2161 } else if (changingTarget.mWallpaperY >= 0) { 2162 mLastWallpaperY = changingTarget.mWallpaperY; 2163 } 2164 if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) { 2165 mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX; 2166 } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) { 2167 mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX; 2168 } 2169 if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 2170 mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY; 2171 } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 2172 mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY; 2173 } 2174 } 2175 2176 int curTokenIndex = mWallpaperTokens.size(); 2177 while (curTokenIndex > 0) { 2178 curTokenIndex--; 2179 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2180 int curWallpaperIndex = token.windows.size(); 2181 while (curWallpaperIndex > 0) { 2182 curWallpaperIndex--; 2183 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2184 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) { 2185 WindowStateAnimator winAnimator = wallpaper.mWinAnimator; 2186 winAnimator.computeShownFrameLocked(); 2187 // No need to lay out the windows - we can just set the wallpaper position 2188 // directly. 2189 winAnimator.setWallpaperOffset(wallpaper.mShownFrame); 2190 // We only want to be synchronous with one wallpaper. 2191 sync = false; 2192 } 2193 } 2194 } 2195 } 2196 2197 /** 2198 * Check wallpaper for visiblity change and notify window if so. 2199 * @param wallpaper The wallpaper to test and notify. 2200 * @param visible Current visibility. 2201 */ 2202 void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) { 2203 if (wallpaper.mWallpaperVisible != visible) { 2204 wallpaper.mWallpaperVisible = visible; 2205 try { 2206 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 2207 "Updating vis of wallpaper " + wallpaper 2208 + ": " + visible + " from:\n" + Debug.getCallers(4, " ")); 2209 wallpaper.mClient.dispatchAppVisibility(visible); 2210 } catch (RemoteException e) { 2211 } 2212 } 2213 } 2214 2215 void updateWallpaperVisibilityLocked() { 2216 final boolean visible = isWallpaperVisible(mWallpaperTarget); 2217 final DisplayContent displayContent = mWallpaperTarget.getDisplayContent(); 2218 if (displayContent == null) { 2219 return; 2220 } 2221 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2222 final int dw = displayInfo.logicalWidth; 2223 final int dh = displayInfo.logicalHeight; 2224 2225 int curTokenIndex = mWallpaperTokens.size(); 2226 while (curTokenIndex > 0) { 2227 curTokenIndex--; 2228 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2229 if (token.hidden == visible) { 2230 token.hidden = !visible; 2231 // Need to do a layout to ensure the wallpaper now has the 2232 // correct size. 2233 getDefaultDisplayContentLocked().layoutNeeded = true; 2234 } 2235 2236 int curWallpaperIndex = token.windows.size(); 2237 while (curWallpaperIndex > 0) { 2238 curWallpaperIndex--; 2239 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2240 if (visible) { 2241 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 2242 } 2243 2244 dispatchWallpaperVisibility(wallpaper, visible); 2245 } 2246 } 2247 } 2248 2249 public int addWindow(Session session, IWindow client, int seq, 2250 WindowManager.LayoutParams attrs, int viewVisibility, int displayId, 2251 Rect outContentInsets, InputChannel outInputChannel) { 2252 int[] appOp = new int[1]; 2253 int res = mPolicy.checkAddPermission(attrs, appOp); 2254 if (res != WindowManagerGlobal.ADD_OKAY) { 2255 return res; 2256 } 2257 2258 boolean reportNewConfig = false; 2259 WindowState attachedWindow = null; 2260 WindowState win = null; 2261 long origId; 2262 final int type = attrs.type; 2263 2264 synchronized(mWindowMap) { 2265 if (!mDisplayReady) { 2266 throw new IllegalStateException("Display has not been initialialized"); 2267 } 2268 2269 final DisplayContent displayContent = getDisplayContentLocked(displayId); 2270 if (displayContent == null) { 2271 Slog.w(TAG, "Attempted to add window to a display that does not exist: " 2272 + displayId + ". Aborting."); 2273 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2274 } 2275 if (!displayContent.hasAccess(session.mUid)) { 2276 Slog.w(TAG, "Attempted to add window to a display for which the application " 2277 + "does not have access: " + displayId + ". Aborting."); 2278 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2279 } 2280 2281 if (mWindowMap.containsKey(client.asBinder())) { 2282 Slog.w(TAG, "Window " + client + " is already added"); 2283 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 2284 } 2285 2286 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 2287 attachedWindow = windowForClientLocked(null, attrs.token, false); 2288 if (attachedWindow == null) { 2289 Slog.w(TAG, "Attempted to add window with token that is not a window: " 2290 + attrs.token + ". Aborting."); 2291 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2292 } 2293 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW 2294 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { 2295 Slog.w(TAG, "Attempted to add window with token that is a sub-window: " 2296 + attrs.token + ". Aborting."); 2297 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2298 } 2299 } 2300 2301 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) { 2302 Slog.w(TAG, "Attempted to add private presentation window to a non-private display. Aborting."); 2303 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2304 } 2305 2306 boolean addToken = false; 2307 WindowToken token = mTokenMap.get(attrs.token); 2308 if (token == null) { 2309 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2310 Slog.w(TAG, "Attempted to add application window with unknown token " 2311 + attrs.token + ". Aborting."); 2312 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2313 } 2314 if (type == TYPE_INPUT_METHOD) { 2315 Slog.w(TAG, "Attempted to add input method window with unknown token " 2316 + attrs.token + ". Aborting."); 2317 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2318 } 2319 if (type == TYPE_VOICE_INTERACTION) { 2320 Slog.w(TAG, "Attempted to add voice interaction window with unknown token " 2321 + attrs.token + ". Aborting."); 2322 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2323 } 2324 if (type == TYPE_WALLPAPER) { 2325 Slog.w(TAG, "Attempted to add wallpaper window with unknown token " 2326 + attrs.token + ". Aborting."); 2327 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2328 } 2329 if (type == TYPE_DREAM) { 2330 Slog.w(TAG, "Attempted to add Dream window with unknown token " 2331 + attrs.token + ". Aborting."); 2332 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2333 } 2334 token = new WindowToken(this, attrs.token, -1, false); 2335 addToken = true; 2336 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2337 AppWindowToken atoken = token.appWindowToken; 2338 if (atoken == null) { 2339 Slog.w(TAG, "Attempted to add window with non-application token " 2340 + token + ". Aborting."); 2341 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 2342 } else if (atoken.removed) { 2343 Slog.w(TAG, "Attempted to add window with exiting application token " 2344 + token + ". Aborting."); 2345 return WindowManagerGlobal.ADD_APP_EXITING; 2346 } 2347 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { 2348 // No need for this guy! 2349 if (localLOGV) Slog.v( 2350 TAG, "**** NO NEED TO START: " + attrs.getTitle()); 2351 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; 2352 } 2353 } else if (type == TYPE_INPUT_METHOD) { 2354 if (token.windowType != TYPE_INPUT_METHOD) { 2355 Slog.w(TAG, "Attempted to add input method window with bad token " 2356 + attrs.token + ". Aborting."); 2357 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2358 } 2359 } else if (type == TYPE_VOICE_INTERACTION) { 2360 if (token.windowType != TYPE_VOICE_INTERACTION) { 2361 Slog.w(TAG, "Attempted to add voice interaction window with bad token " 2362 + attrs.token + ". Aborting."); 2363 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2364 } 2365 } else if (type == TYPE_WALLPAPER) { 2366 if (token.windowType != TYPE_WALLPAPER) { 2367 Slog.w(TAG, "Attempted to add wallpaper window with bad token " 2368 + attrs.token + ". Aborting."); 2369 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2370 } 2371 } else if (type == TYPE_DREAM) { 2372 if (token.windowType != TYPE_DREAM) { 2373 Slog.w(TAG, "Attempted to add Dream window with bad token " 2374 + attrs.token + ". Aborting."); 2375 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2376 } 2377 } else if (token.appWindowToken != null) { 2378 Slog.w(TAG, "Non-null appWindowToken for system window of type=" + type); 2379 // It is not valid to use an app token with other system types; we will 2380 // instead make a new token for it (as if null had been passed in for the token). 2381 attrs.token = null; 2382 token = new WindowToken(this, null, -1, false); 2383 addToken = true; 2384 } 2385 2386 win = new WindowState(this, session, client, token, 2387 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent); 2388 if (win.mDeathRecipient == null) { 2389 // Client has apparently died, so there is no reason to 2390 // continue. 2391 Slog.w(TAG, "Adding window client " + client.asBinder() 2392 + " that is dead, aborting."); 2393 return WindowManagerGlobal.ADD_APP_EXITING; 2394 } 2395 2396 if (win.getDisplayContent() == null) { 2397 Slog.w(TAG, "Adding window to Display that has been removed."); 2398 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2399 } 2400 2401 mPolicy.adjustWindowParamsLw(win.mAttrs); 2402 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 2403 2404 res = mPolicy.prepareAddWindowLw(win, attrs); 2405 if (res != WindowManagerGlobal.ADD_OKAY) { 2406 return res; 2407 } 2408 2409 if (outInputChannel != null && (attrs.inputFeatures 2410 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { 2411 String name = win.makeInputChannelName(); 2412 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); 2413 win.setInputChannel(inputChannels[0]); 2414 inputChannels[1].transferTo(outInputChannel); 2415 2416 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); 2417 } 2418 2419 // From now on, no exceptions or errors allowed! 2420 2421 res = WindowManagerGlobal.ADD_OKAY; 2422 2423 origId = Binder.clearCallingIdentity(); 2424 2425 if (addToken) { 2426 mTokenMap.put(attrs.token, token); 2427 } 2428 win.attach(); 2429 mWindowMap.put(client.asBinder(), win); 2430 if (win.mAppOp != AppOpsManager.OP_NONE) { 2431 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage()) 2432 != AppOpsManager.MODE_ALLOWED) { 2433 win.setAppOpVisibilityLw(false); 2434 } 2435 } 2436 2437 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { 2438 token.appWindowToken.startingWindow = win; 2439 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken 2440 + " startingWindow=" + win); 2441 } 2442 2443 boolean imMayMove = true; 2444 2445 if (type == TYPE_INPUT_METHOD) { 2446 win.mGivenInsetsPending = true; 2447 mInputMethodWindow = win; 2448 addInputMethodWindowToListLocked(win); 2449 imMayMove = false; 2450 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 2451 mInputMethodDialogs.add(win); 2452 addWindowToListInOrderLocked(win, true); 2453 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); 2454 imMayMove = false; 2455 } else { 2456 addWindowToListInOrderLocked(win, true); 2457 if (type == TYPE_WALLPAPER) { 2458 mLastWallpaperTimeoutTime = 0; 2459 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2460 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2461 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2462 } else if (mWallpaperTarget != null 2463 && mWallpaperTarget.mLayer >= win.mBaseLayer) { 2464 // If there is currently a wallpaper being shown, and 2465 // the base layer of the new window is below the current 2466 // layer of the target window, then adjust the wallpaper. 2467 // This is to avoid a new window being placed between the 2468 // wallpaper and its target. 2469 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2470 } 2471 } 2472 2473 win.mWinAnimator.mEnterAnimationPending = true; 2474 2475 if (displayContent.isDefaultDisplay) { 2476 mPolicy.getContentInsetHintLw(attrs, outContentInsets); 2477 } else { 2478 outContentInsets.setEmpty(); 2479 } 2480 2481 if (mInTouchMode) { 2482 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2483 } 2484 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2485 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2486 } 2487 2488 mInputMonitor.setUpdateInputWindowsNeededLw(); 2489 2490 boolean focusChanged = false; 2491 if (win.canReceiveKeys()) { 2492 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2493 false /*updateInputWindows*/); 2494 if (focusChanged) { 2495 imMayMove = false; 2496 } 2497 } 2498 2499 if (imMayMove) { 2500 moveInputMethodWindowsIfNeededLocked(false); 2501 } 2502 2503 assignLayersLocked(displayContent.getWindowList()); 2504 // Don't do layout here, the window must call 2505 // relayout to be displayed, so we'll do it there. 2506 2507 if (focusChanged) { 2508 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/); 2509 } 2510 mInputMonitor.updateInputWindowsLw(false /*force*/); 2511 2512 if (localLOGV) Slog.v( 2513 TAG, "New client " + client.asBinder() 2514 + ": window=" + win); 2515 2516 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2517 reportNewConfig = true; 2518 } 2519 } 2520 2521 if (reportNewConfig) { 2522 sendNewConfiguration(); 2523 } 2524 2525 Binder.restoreCallingIdentity(origId); 2526 2527 return res; 2528 } 2529 2530 /** 2531 * Returns whether screen capture is disabled for all windows of a specific user. 2532 */ 2533 boolean isScreenCaptureDisabledLocked(int userId) { 2534 Boolean disabled = mScreenCaptureDisabled.get(userId); 2535 if (disabled == null) { 2536 return false; 2537 } 2538 return disabled; 2539 } 2540 2541 /** 2542 * Set mScreenCaptureDisabled for specific user 2543 */ 2544 @Override 2545 public void setScreenCaptureDisabled(int userId, boolean disabled) { 2546 int callingUid = Binder.getCallingUid(); 2547 if (callingUid != Process.SYSTEM_UID) { 2548 throw new SecurityException("Only system can call setScreenCaptureDisabled."); 2549 } 2550 2551 synchronized(mWindowMap) { 2552 mScreenCaptureDisabled.put(userId, disabled); 2553 } 2554 } 2555 2556 public void removeWindow(Session session, IWindow client) { 2557 synchronized(mWindowMap) { 2558 WindowState win = windowForClientLocked(session, client, false); 2559 if (win == null) { 2560 return; 2561 } 2562 removeWindowLocked(session, win); 2563 } 2564 } 2565 2566 public void removeWindowLocked(Session session, WindowState win) { 2567 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2568 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win); 2569 } 2570 2571 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v( 2572 TAG, "Remove " + win + " client=" 2573 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) 2574 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers=" 2575 + Debug.getCallers(4)); 2576 2577 final long origId = Binder.clearCallingIdentity(); 2578 2579 win.disposeInputChannel(); 2580 2581 if (DEBUG_APP_TRANSITIONS) Slog.v( 2582 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl 2583 + " mExiting=" + win.mExiting 2584 + " isAnimating=" + win.mWinAnimator.isAnimating() 2585 + " app-animation=" 2586 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2587 + " inPendingTransaction=" 2588 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2589 + " mDisplayFrozen=" + mDisplayFrozen); 2590 // Visibility of the removed window. Will be used later to update orientation later on. 2591 boolean wasVisible = false; 2592 // First, see if we need to run an animation. If we do, we have 2593 // to hold off on removing the window until the animation is done. 2594 // If the display is frozen, just remove immediately, since the 2595 // animation wouldn't be seen. 2596 if (win.mHasSurface && okToDisplay()) { 2597 // If we are not currently running the exit animation, we 2598 // need to see about starting one. 2599 wasVisible = win.isWinVisibleLw(); 2600 if (wasVisible) { 2601 2602 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2603 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2604 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2605 } 2606 // Try starting an animation. 2607 if (win.mWinAnimator.applyAnimationLocked(transit, false)) { 2608 win.mExiting = true; 2609 } 2610 //TODO (multidisplay): Magnification is supported only for the default display. 2611 if (mAccessibilityController != null 2612 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2613 mAccessibilityController.onWindowTransitionLocked(win, transit); 2614 } 2615 } 2616 if (win.mExiting || win.mWinAnimator.isAnimating()) { 2617 // The exit animation is running... wait for it! 2618 //Slog.i(TAG, "*** Running exit animation..."); 2619 win.mExiting = true; 2620 win.mRemoveOnExit = true; 2621 final DisplayContent displayContent = win.getDisplayContent(); 2622 if (displayContent != null) { 2623 displayContent.layoutNeeded = true; 2624 } 2625 final boolean focusChanged = updateFocusedWindowLocked( 2626 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 2627 performLayoutAndPlaceSurfacesLocked(); 2628 if (win.mAppToken != null) { 2629 win.mAppToken.updateReportedVisibilityLocked(); 2630 } 2631 if (focusChanged) { 2632 mInputMonitor.updateInputWindowsLw(false /*force*/); 2633 } 2634 //dump(); 2635 Binder.restoreCallingIdentity(origId); 2636 return; 2637 } 2638 } 2639 2640 removeWindowInnerLocked(session, win); 2641 // Removing a visible window will effect the computed orientation 2642 // So just update orientation if needed. 2643 if (wasVisible && updateOrientationFromAppTokensLocked(false)) { 2644 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2645 } 2646 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2647 Binder.restoreCallingIdentity(origId); 2648 } 2649 2650 void removeWindowInnerLocked(Session session, WindowState win) { 2651 if (win.mRemoved) { 2652 // Nothing to do. 2653 return; 2654 } 2655 2656 for (int i=win.mChildWindows.size()-1; i>=0; i--) { 2657 WindowState cwin = win.mChildWindows.get(i); 2658 Slog.w(TAG, "Force-removing child win " + cwin + " from container " 2659 + win); 2660 removeWindowInnerLocked(cwin.mSession, cwin); 2661 } 2662 2663 win.mRemoved = true; 2664 2665 if (mInputMethodTarget == win) { 2666 moveInputMethodWindowsIfNeededLocked(false); 2667 } 2668 2669 if (false) { 2670 RuntimeException e = new RuntimeException("here"); 2671 e.fillInStackTrace(); 2672 Slog.w(TAG, "Removing window " + win, e); 2673 } 2674 2675 mPolicy.removeWindowLw(win); 2676 win.removeLocked(); 2677 2678 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); 2679 mWindowMap.remove(win.mClient.asBinder()); 2680 if (win.mAppOp != AppOpsManager.OP_NONE) { 2681 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); 2682 } 2683 2684 mPendingRemove.remove(win); 2685 mResizingWindows.remove(win); 2686 mWindowsChanged = true; 2687 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win); 2688 2689 if (mInputMethodWindow == win) { 2690 mInputMethodWindow = null; 2691 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { 2692 mInputMethodDialogs.remove(win); 2693 } 2694 2695 final WindowToken token = win.mToken; 2696 final AppWindowToken atoken = win.mAppToken; 2697 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token); 2698 token.windows.remove(win); 2699 if (atoken != null) { 2700 atoken.allAppWindows.remove(win); 2701 } 2702 if (localLOGV) Slog.v( 2703 TAG, "**** Removing window " + win + ": count=" 2704 + token.windows.size()); 2705 if (token.windows.size() == 0) { 2706 if (!token.explicit) { 2707 mTokenMap.remove(token.token); 2708 } else if (atoken != null) { 2709 atoken.firstWindowDrawn = false; 2710 } 2711 } 2712 2713 if (atoken != null) { 2714 if (atoken.startingWindow == win) { 2715 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "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 boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser( 7230 mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, 7231 mCurrentUserId) == 1; 7232 synchronized (mWindowMap) { 7233 mShowImeWithHardKeyboard = showImeWithHardKeyboard; 7234 } 7235 } 7236 7237 public void setOnHardKeyboardStatusChangeListener( 7238 OnHardKeyboardStatusChangeListener listener) { 7239 synchronized (mWindowMap) { 7240 mHardKeyboardStatusChangeListener = listener; 7241 } 7242 } 7243 7244 void notifyHardKeyboardStatusChange() { 7245 final boolean available; 7246 final OnHardKeyboardStatusChangeListener listener; 7247 synchronized (mWindowMap) { 7248 listener = mHardKeyboardStatusChangeListener; 7249 available = mHardKeyboardAvailable; 7250 } 7251 if (listener != null) { 7252 listener.onHardKeyboardStatusChange(available); 7253 } 7254 } 7255 7256 // ------------------------------------------------------------- 7257 // Drag and drop 7258 // ------------------------------------------------------------- 7259 7260 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 7261 int flags, int width, int height, Surface outSurface) { 7262 if (DEBUG_DRAG) { 7263 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 7264 + " flags=" + Integer.toHexString(flags) + " win=" + window 7265 + " asbinder=" + window.asBinder()); 7266 } 7267 7268 final int callerPid = Binder.getCallingPid(); 7269 final long origId = Binder.clearCallingIdentity(); 7270 IBinder token = null; 7271 7272 try { 7273 synchronized (mWindowMap) { 7274 try { 7275 if (mDragState == null) { 7276 // TODO(multi-display): support other displays 7277 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7278 final Display display = displayContent.getDisplay(); 7279 SurfaceControl surface = new SurfaceControl(session, "drag surface", 7280 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 7281 surface.setLayerStack(display.getLayerStack()); 7282 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 7283 + surface + ": CREATE"); 7284 outSurface.copyFrom(surface); 7285 final IBinder winBinder = window.asBinder(); 7286 token = new Binder(); 7287 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 7288 token = mDragState.mToken = new Binder(); 7289 7290 // 5 second timeout for this window to actually begin the drag 7291 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 7292 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 7293 mH.sendMessageDelayed(msg, 5000); 7294 } else { 7295 Slog.w(TAG, "Drag already in progress"); 7296 } 7297 } catch (OutOfResourcesException e) { 7298 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 7299 if (mDragState != null) { 7300 mDragState.reset(); 7301 mDragState = null; 7302 } 7303 } 7304 } 7305 } finally { 7306 Binder.restoreCallingIdentity(origId); 7307 } 7308 7309 return token; 7310 } 7311 7312 // ------------------------------------------------------------- 7313 // Input Events and Focus Management 7314 // ------------------------------------------------------------- 7315 7316 final InputMonitor mInputMonitor = new InputMonitor(this); 7317 private boolean mEventDispatchingEnabled; 7318 7319 @Override 7320 public void pauseKeyDispatching(IBinder _token) { 7321 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7322 "pauseKeyDispatching()")) { 7323 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7324 } 7325 7326 synchronized (mWindowMap) { 7327 WindowToken token = mTokenMap.get(_token); 7328 if (token != null) { 7329 mInputMonitor.pauseDispatchingLw(token); 7330 } 7331 } 7332 } 7333 7334 @Override 7335 public void resumeKeyDispatching(IBinder _token) { 7336 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7337 "resumeKeyDispatching()")) { 7338 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7339 } 7340 7341 synchronized (mWindowMap) { 7342 WindowToken token = mTokenMap.get(_token); 7343 if (token != null) { 7344 mInputMonitor.resumeDispatchingLw(token); 7345 } 7346 } 7347 } 7348 7349 @Override 7350 public void setEventDispatching(boolean enabled) { 7351 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7352 "setEventDispatching()")) { 7353 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7354 } 7355 7356 synchronized (mWindowMap) { 7357 mEventDispatchingEnabled = enabled; 7358 if (mDisplayEnabled) { 7359 mInputMonitor.setEventDispatchingLw(enabled); 7360 } 7361 } 7362 } 7363 7364 private WindowState getFocusedWindow() { 7365 synchronized (mWindowMap) { 7366 return getFocusedWindowLocked(); 7367 } 7368 } 7369 7370 private WindowState getFocusedWindowLocked() { 7371 return mCurrentFocus; 7372 } 7373 7374 public boolean detectSafeMode() { 7375 if (!mInputMonitor.waitForInputDevicesReady( 7376 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7377 Slog.w(TAG, "Devices still not ready after waiting " 7378 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7379 + " milliseconds before attempting to detect safe mode."); 7380 } 7381 7382 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7383 KeyEvent.KEYCODE_MENU); 7384 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7385 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7386 KeyEvent.KEYCODE_DPAD_CENTER); 7387 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7388 InputManagerService.BTN_MOUSE); 7389 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7390 KeyEvent.KEYCODE_VOLUME_DOWN); 7391 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7392 || volumeDownState > 0; 7393 try { 7394 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7395 mSafeMode = true; 7396 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7397 } 7398 } catch (IllegalArgumentException e) { 7399 } 7400 if (mSafeMode) { 7401 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7402 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7403 } else { 7404 Log.i(TAG, "SAFE MODE not enabled"); 7405 } 7406 mPolicy.setSafeMode(mSafeMode); 7407 return mSafeMode; 7408 } 7409 7410 public void displayReady() { 7411 displayReady(Display.DEFAULT_DISPLAY); 7412 7413 synchronized(mWindowMap) { 7414 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7415 readForcedDisplaySizeAndDensityLocked(displayContent); 7416 mDisplayReady = true; 7417 } 7418 7419 try { 7420 mActivityManager.updateConfiguration(null); 7421 } catch (RemoteException e) { 7422 } 7423 7424 synchronized(mWindowMap) { 7425 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7426 PackageManager.FEATURE_TOUCHSCREEN); 7427 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7428 } 7429 7430 try { 7431 mActivityManager.updateConfiguration(null); 7432 } catch (RemoteException e) { 7433 } 7434 } 7435 7436 private void displayReady(int displayId) { 7437 synchronized(mWindowMap) { 7438 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7439 if (displayContent != null) { 7440 mAnimator.addDisplayLocked(displayId); 7441 synchronized(displayContent.mDisplaySizeLock) { 7442 // Bootstrap the default logical display from the display manager. 7443 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7444 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); 7445 if (newDisplayInfo != null) { 7446 displayInfo.copyFrom(newDisplayInfo); 7447 } 7448 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7449 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7450 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7451 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7452 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7453 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7454 displayContent.mBaseDisplayRect.set(0, 0, 7455 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7456 } 7457 } 7458 } 7459 } 7460 7461 public void systemReady() { 7462 mPolicy.systemReady(); 7463 } 7464 7465 // ------------------------------------------------------------- 7466 // Async Handler 7467 // ------------------------------------------------------------- 7468 7469 final class H extends Handler { 7470 public static final int REPORT_FOCUS_CHANGE = 2; 7471 public static final int REPORT_LOSING_FOCUS = 3; 7472 public static final int DO_TRAVERSAL = 4; 7473 public static final int ADD_STARTING = 5; 7474 public static final int REMOVE_STARTING = 6; 7475 public static final int FINISHED_STARTING = 7; 7476 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7477 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7478 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7479 7480 public static final int APP_TRANSITION_TIMEOUT = 13; 7481 public static final int PERSIST_ANIMATION_SCALE = 14; 7482 public static final int FORCE_GC = 15; 7483 public static final int ENABLE_SCREEN = 16; 7484 public static final int APP_FREEZE_TIMEOUT = 17; 7485 public static final int SEND_NEW_CONFIGURATION = 18; 7486 public static final int REPORT_WINDOWS_CHANGE = 19; 7487 public static final int DRAG_START_TIMEOUT = 20; 7488 public static final int DRAG_END_TIMEOUT = 21; 7489 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7490 public static final int BOOT_TIMEOUT = 23; 7491 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7492 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7493 public static final int DO_ANIMATION_CALLBACK = 26; 7494 7495 public static final int DO_DISPLAY_ADDED = 27; 7496 public static final int DO_DISPLAY_REMOVED = 28; 7497 public static final int DO_DISPLAY_CHANGED = 29; 7498 7499 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7500 public static final int TAP_OUTSIDE_STACK = 31; 7501 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7502 7503 public static final int ALL_WINDOWS_DRAWN = 33; 7504 7505 public static final int NEW_ANIMATOR_SCALE = 34; 7506 7507 public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35; 7508 public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36; 7509 7510 public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37; 7511 7512 @Override 7513 public void handleMessage(Message msg) { 7514 if (DEBUG_WINDOW_TRACE) { 7515 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7516 } 7517 switch (msg.what) { 7518 case REPORT_FOCUS_CHANGE: { 7519 WindowState lastFocus; 7520 WindowState newFocus; 7521 7522 synchronized(mWindowMap) { 7523 lastFocus = mLastFocus; 7524 newFocus = mCurrentFocus; 7525 if (lastFocus == newFocus) { 7526 // Focus is not changing, so nothing to do. 7527 return; 7528 } 7529 mLastFocus = newFocus; 7530 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7531 " to " + newFocus); 7532 if (newFocus != null && lastFocus != null 7533 && !newFocus.isDisplayedLw()) { 7534 //Slog.i(TAG, "Delaying loss of focus..."); 7535 mLosingFocus.add(lastFocus); 7536 lastFocus = null; 7537 } 7538 } 7539 7540 //System.out.println("Changing focus from " + lastFocus 7541 // + " to " + newFocus); 7542 if (newFocus != null) { 7543 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7544 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7545 notifyFocusChanged(); 7546 } 7547 7548 if (lastFocus != null) { 7549 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7550 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7551 } 7552 } break; 7553 7554 case REPORT_LOSING_FOCUS: { 7555 ArrayList<WindowState> losers; 7556 7557 synchronized(mWindowMap) { 7558 losers = mLosingFocus; 7559 mLosingFocus = new ArrayList<WindowState>(); 7560 } 7561 7562 final int N = losers.size(); 7563 for (int i=0; i<N; i++) { 7564 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7565 losers.get(i)); 7566 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7567 } 7568 } break; 7569 7570 case DO_TRAVERSAL: { 7571 synchronized(mWindowMap) { 7572 mTraversalScheduled = false; 7573 performLayoutAndPlaceSurfacesLocked(); 7574 } 7575 } break; 7576 7577 case ADD_STARTING: { 7578 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7579 final StartingData sd = wtoken.startingData; 7580 7581 if (sd == null) { 7582 // Animation has been canceled... do nothing. 7583 return; 7584 } 7585 7586 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7587 + wtoken + ": pkg=" + sd.pkg); 7588 7589 View view = null; 7590 try { 7591 view = mPolicy.addStartingWindow( 7592 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7593 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7594 } catch (Exception e) { 7595 Slog.w(TAG, "Exception when adding starting window", e); 7596 } 7597 7598 if (view != null) { 7599 boolean abort = false; 7600 7601 synchronized(mWindowMap) { 7602 if (wtoken.removed || wtoken.startingData == null) { 7603 // If the window was successfully added, then 7604 // we need to remove it. 7605 if (wtoken.startingWindow != null) { 7606 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7607 "Aborted starting " + wtoken 7608 + ": removed=" + wtoken.removed 7609 + " startingData=" + wtoken.startingData); 7610 wtoken.startingWindow = null; 7611 wtoken.startingData = null; 7612 abort = true; 7613 } 7614 } else { 7615 wtoken.startingView = view; 7616 } 7617 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7618 "Added starting " + wtoken 7619 + ": startingWindow=" 7620 + wtoken.startingWindow + " startingView=" 7621 + wtoken.startingView); 7622 } 7623 7624 if (abort) { 7625 try { 7626 mPolicy.removeStartingWindow(wtoken.token, view); 7627 } catch (Exception e) { 7628 Slog.w(TAG, "Exception when removing starting window", e); 7629 } 7630 } 7631 } 7632 } break; 7633 7634 case REMOVE_STARTING: { 7635 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7636 IBinder token = null; 7637 View view = null; 7638 synchronized (mWindowMap) { 7639 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7640 + wtoken + ": startingWindow=" 7641 + wtoken.startingWindow + " startingView=" 7642 + wtoken.startingView); 7643 if (wtoken.startingWindow != null) { 7644 view = wtoken.startingView; 7645 token = wtoken.token; 7646 wtoken.startingData = null; 7647 wtoken.startingView = null; 7648 wtoken.startingWindow = null; 7649 wtoken.startingDisplayed = false; 7650 } 7651 } 7652 if (view != null) { 7653 try { 7654 mPolicy.removeStartingWindow(token, view); 7655 } catch (Exception e) { 7656 Slog.w(TAG, "Exception when removing starting window", e); 7657 } 7658 } 7659 } break; 7660 7661 case FINISHED_STARTING: { 7662 IBinder token = null; 7663 View view = null; 7664 while (true) { 7665 synchronized (mWindowMap) { 7666 final int N = mFinishedStarting.size(); 7667 if (N <= 0) { 7668 break; 7669 } 7670 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7671 7672 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7673 "Finished starting " + wtoken 7674 + ": startingWindow=" + wtoken.startingWindow 7675 + " startingView=" + wtoken.startingView); 7676 7677 if (wtoken.startingWindow == null) { 7678 continue; 7679 } 7680 7681 view = wtoken.startingView; 7682 token = wtoken.token; 7683 wtoken.startingData = null; 7684 wtoken.startingView = null; 7685 wtoken.startingWindow = null; 7686 wtoken.startingDisplayed = false; 7687 } 7688 7689 try { 7690 mPolicy.removeStartingWindow(token, view); 7691 } catch (Exception e) { 7692 Slog.w(TAG, "Exception when removing starting window", e); 7693 } 7694 } 7695 } break; 7696 7697 case REPORT_APPLICATION_TOKEN_DRAWN: { 7698 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7699 7700 try { 7701 if (DEBUG_VISIBILITY) Slog.v( 7702 TAG, "Reporting drawn in " + wtoken); 7703 wtoken.appToken.windowsDrawn(); 7704 } catch (RemoteException ex) { 7705 } 7706 } break; 7707 7708 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7709 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7710 7711 boolean nowVisible = msg.arg1 != 0; 7712 boolean nowGone = msg.arg2 != 0; 7713 7714 try { 7715 if (DEBUG_VISIBILITY) Slog.v( 7716 TAG, "Reporting visible in " + wtoken 7717 + " visible=" + nowVisible 7718 + " gone=" + nowGone); 7719 if (nowVisible) { 7720 wtoken.appToken.windowsVisible(); 7721 } else { 7722 wtoken.appToken.windowsGone(); 7723 } 7724 } catch (RemoteException ex) { 7725 } 7726 } break; 7727 7728 case WINDOW_FREEZE_TIMEOUT: { 7729 // TODO(multidisplay): Can non-default displays rotate? 7730 synchronized (mWindowMap) { 7731 Slog.w(TAG, "Window freeze timeout expired."); 7732 final WindowList windows = getDefaultWindowListLocked(); 7733 int i = windows.size(); 7734 while (i > 0) { 7735 i--; 7736 WindowState w = windows.get(i); 7737 if (w.mOrientationChanging) { 7738 w.mOrientationChanging = false; 7739 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7740 - mDisplayFreezeTime); 7741 Slog.w(TAG, "Force clearing orientation change: " + w); 7742 } 7743 } 7744 performLayoutAndPlaceSurfacesLocked(); 7745 } 7746 break; 7747 } 7748 7749 case APP_TRANSITION_TIMEOUT: { 7750 synchronized (mWindowMap) { 7751 if (mAppTransition.isTransitionSet()) { 7752 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7753 mAppTransition.setTimeout(); 7754 performLayoutAndPlaceSurfacesLocked(); 7755 } 7756 } 7757 break; 7758 } 7759 7760 case PERSIST_ANIMATION_SCALE: { 7761 Settings.Global.putFloat(mContext.getContentResolver(), 7762 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 7763 Settings.Global.putFloat(mContext.getContentResolver(), 7764 Settings.Global.TRANSITION_ANIMATION_SCALE, 7765 mTransitionAnimationScaleSetting); 7766 Settings.Global.putFloat(mContext.getContentResolver(), 7767 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 7768 break; 7769 } 7770 7771 case FORCE_GC: { 7772 synchronized (mWindowMap) { 7773 // Since we're holding both mWindowMap and mAnimator we don't need to 7774 // hold mAnimator.mLayoutToAnim. 7775 if (mAnimator.mAnimating || mAnimationScheduled) { 7776 // If we are animating, don't do the gc now but 7777 // delay a bit so we don't interrupt the animation. 7778 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7779 return; 7780 } 7781 // If we are currently rotating the display, it will 7782 // schedule a new message when done. 7783 if (mDisplayFrozen) { 7784 return; 7785 } 7786 } 7787 Runtime.getRuntime().gc(); 7788 break; 7789 } 7790 7791 case ENABLE_SCREEN: { 7792 performEnableScreen(); 7793 break; 7794 } 7795 7796 case APP_FREEZE_TIMEOUT: { 7797 synchronized (mWindowMap) { 7798 Slog.w(TAG, "App freeze timeout expired."); 7799 final int numStacks = mStackIdToStack.size(); 7800 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 7801 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 7802 final ArrayList<Task> tasks = stack.getTasks(); 7803 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7804 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7805 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7806 AppWindowToken tok = tokens.get(tokenNdx); 7807 if (tok.mAppAnimator.freezingScreen) { 7808 Slog.w(TAG, "Force clearing freeze: " + tok); 7809 unsetAppFreezingScreenLocked(tok, true, true); 7810 } 7811 } 7812 } 7813 } 7814 } 7815 break; 7816 } 7817 7818 case CLIENT_FREEZE_TIMEOUT: { 7819 synchronized (mWindowMap) { 7820 if (mClientFreezingScreen) { 7821 mClientFreezingScreen = false; 7822 mLastFinishedFreezeSource = "client-timeout"; 7823 stopFreezingDisplayLocked(); 7824 } 7825 } 7826 break; 7827 } 7828 7829 case SEND_NEW_CONFIGURATION: { 7830 removeMessages(SEND_NEW_CONFIGURATION); 7831 sendNewConfiguration(); 7832 break; 7833 } 7834 7835 case REPORT_WINDOWS_CHANGE: { 7836 if (mWindowsChanged) { 7837 synchronized (mWindowMap) { 7838 mWindowsChanged = false; 7839 } 7840 notifyWindowsChanged(); 7841 } 7842 break; 7843 } 7844 7845 case DRAG_START_TIMEOUT: { 7846 IBinder win = (IBinder)msg.obj; 7847 if (DEBUG_DRAG) { 7848 Slog.w(TAG, "Timeout starting drag by win " + win); 7849 } 7850 synchronized (mWindowMap) { 7851 // !!! TODO: ANR the app that has failed to start the drag in time 7852 if (mDragState != null) { 7853 mDragState.unregister(); 7854 mInputMonitor.updateInputWindowsLw(true /*force*/); 7855 mDragState.reset(); 7856 mDragState = null; 7857 } 7858 } 7859 break; 7860 } 7861 7862 case DRAG_END_TIMEOUT: { 7863 IBinder win = (IBinder)msg.obj; 7864 if (DEBUG_DRAG) { 7865 Slog.w(TAG, "Timeout ending drag to win " + win); 7866 } 7867 synchronized (mWindowMap) { 7868 // !!! TODO: ANR the drag-receiving app 7869 if (mDragState != null) { 7870 mDragState.mDragResult = false; 7871 mDragState.endDragLw(); 7872 } 7873 } 7874 break; 7875 } 7876 7877 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7878 notifyHardKeyboardStatusChange(); 7879 break; 7880 } 7881 7882 case BOOT_TIMEOUT: { 7883 performBootTimeout(); 7884 break; 7885 } 7886 7887 case WAITING_FOR_DRAWN_TIMEOUT: { 7888 Runnable callback = null; 7889 synchronized (mWindowMap) { 7890 Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 7891 mWaitingForDrawn.clear(); 7892 callback = mWaitingForDrawnCallback; 7893 mWaitingForDrawnCallback = null; 7894 } 7895 if (callback != null) { 7896 callback.run(); 7897 } 7898 break; 7899 } 7900 7901 case SHOW_STRICT_MODE_VIOLATION: { 7902 showStrictModeViolation(msg.arg1, msg.arg2); 7903 break; 7904 } 7905 7906 case SHOW_CIRCULAR_DISPLAY_MASK: { 7907 showCircularMask(); 7908 break; 7909 } 7910 7911 case SHOW_EMULATOR_DISPLAY_OVERLAY: { 7912 showEmulatorDisplayOverlay(); 7913 break; 7914 } 7915 7916 case DO_ANIMATION_CALLBACK: { 7917 try { 7918 ((IRemoteCallback)msg.obj).sendResult(null); 7919 } catch (RemoteException e) { 7920 } 7921 break; 7922 } 7923 7924 case DO_DISPLAY_ADDED: 7925 handleDisplayAdded(msg.arg1); 7926 break; 7927 7928 case DO_DISPLAY_REMOVED: 7929 synchronized (mWindowMap) { 7930 handleDisplayRemovedLocked(msg.arg1); 7931 } 7932 break; 7933 7934 case DO_DISPLAY_CHANGED: 7935 synchronized (mWindowMap) { 7936 handleDisplayChangedLocked(msg.arg1); 7937 } 7938 break; 7939 7940 case TAP_OUTSIDE_STACK: { 7941 int stackId; 7942 synchronized (mWindowMap) { 7943 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7944 } 7945 if (stackId >= 0) { 7946 try { 7947 mActivityManager.setFocusedStack(stackId); 7948 } catch (RemoteException e) { 7949 } 7950 } 7951 } 7952 break; 7953 case NOTIFY_ACTIVITY_DRAWN: 7954 try { 7955 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7956 } catch (RemoteException e) { 7957 } 7958 break; 7959 case ALL_WINDOWS_DRAWN: { 7960 Runnable callback; 7961 synchronized (mWindowMap) { 7962 callback = mWaitingForDrawnCallback; 7963 mWaitingForDrawnCallback = null; 7964 } 7965 if (callback != null) { 7966 callback.run(); 7967 } 7968 } 7969 case NEW_ANIMATOR_SCALE: { 7970 float scale = getCurrentAnimatorScale(); 7971 ValueAnimator.setDurationScale(scale); 7972 Session session = (Session)msg.obj; 7973 if (session != null) { 7974 try { 7975 session.mCallback.onAnimatorScaleChanged(scale); 7976 } catch (RemoteException e) { 7977 } 7978 } else { 7979 ArrayList<IWindowSessionCallback> callbacks 7980 = new ArrayList<IWindowSessionCallback>(); 7981 synchronized (mWindowMap) { 7982 for (int i=0; i<mSessions.size(); i++) { 7983 callbacks.add(mSessions.valueAt(i).mCallback); 7984 } 7985 7986 } 7987 for (int i=0; i<callbacks.size(); i++) { 7988 try { 7989 callbacks.get(i).onAnimatorScaleChanged(scale); 7990 } catch (RemoteException e) { 7991 } 7992 } 7993 } 7994 } 7995 break; 7996 case CHECK_IF_BOOT_ANIMATION_FINISHED: { 7997 final boolean bootAnimationComplete; 7998 synchronized (mWindowMap) { 7999 if (DEBUG_BOOT) Slog.i(TAG, "CHECK_IF_BOOT_ANIMATION_FINISHED:"); 8000 bootAnimationComplete = checkBootAnimationCompleteLocked(); 8001 } 8002 if (bootAnimationComplete) { 8003 performEnableScreen(); 8004 } 8005 } 8006 break; 8007 } 8008 if (DEBUG_WINDOW_TRACE) { 8009 Slog.v(TAG, "handleMessage: exit"); 8010 } 8011 } 8012 } 8013 8014 // ------------------------------------------------------------- 8015 // IWindowManager API 8016 // ------------------------------------------------------------- 8017 8018 @Override 8019 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 8020 IInputContext inputContext) { 8021 if (client == null) throw new IllegalArgumentException("null client"); 8022 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 8023 Session session = new Session(this, callback, client, inputContext); 8024 return session; 8025 } 8026 8027 @Override 8028 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 8029 synchronized (mWindowMap) { 8030 // The focus for the client is the window immediately below 8031 // where we would place the input method window. 8032 int idx = findDesiredInputMethodWindowIndexLocked(false); 8033 if (idx > 0) { 8034 // TODO(multidisplay): IMEs are only supported on the default display. 8035 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 8036 if (DEBUG_INPUT_METHOD) { 8037 Slog.i(TAG, "Desired input method target: " + imFocus); 8038 Slog.i(TAG, "Current focus: " + mCurrentFocus); 8039 Slog.i(TAG, "Last focus: " + mLastFocus); 8040 } 8041 if (imFocus != null) { 8042 // This may be a starting window, in which case we still want 8043 // to count it as okay. 8044 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 8045 && imFocus.mAppToken != null) { 8046 // The client has definitely started, so it really should 8047 // have a window in this app token. Let's look for it. 8048 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 8049 WindowState w = imFocus.mAppToken.windows.get(i); 8050 if (w != imFocus) { 8051 Log.i(TAG, "Switching to real app window: " + w); 8052 imFocus = w; 8053 break; 8054 } 8055 } 8056 } 8057 if (DEBUG_INPUT_METHOD) { 8058 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 8059 if (imFocus.mSession.mClient != null) { 8060 Slog.i(TAG, "IM target client binder: " 8061 + imFocus.mSession.mClient.asBinder()); 8062 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 8063 } 8064 } 8065 if (imFocus.mSession.mClient != null && 8066 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 8067 return true; 8068 } 8069 } 8070 } 8071 8072 // Okay, how about this... what is the current focus? 8073 // It seems in some cases we may not have moved the IM 8074 // target window, such as when it was in a pop-up window, 8075 // so let's also look at the current focus. (An example: 8076 // go to Gmail, start searching so the keyboard goes up, 8077 // press home. Sometimes the IME won't go down.) 8078 // Would be nice to fix this more correctly, but it's 8079 // way at the end of a release, and this should be good enough. 8080 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 8081 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 8082 return true; 8083 } 8084 } 8085 return false; 8086 } 8087 8088 @Override 8089 public void getInitialDisplaySize(int displayId, Point size) { 8090 synchronized (mWindowMap) { 8091 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8092 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8093 synchronized(displayContent.mDisplaySizeLock) { 8094 size.x = displayContent.mInitialDisplayWidth; 8095 size.y = displayContent.mInitialDisplayHeight; 8096 } 8097 } 8098 } 8099 } 8100 8101 @Override 8102 public void getBaseDisplaySize(int displayId, Point size) { 8103 synchronized (mWindowMap) { 8104 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8105 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8106 synchronized(displayContent.mDisplaySizeLock) { 8107 size.x = displayContent.mBaseDisplayWidth; 8108 size.y = displayContent.mBaseDisplayHeight; 8109 } 8110 } 8111 } 8112 } 8113 8114 @Override 8115 public void setForcedDisplaySize(int displayId, int width, int height) { 8116 if (mContext.checkCallingOrSelfPermission( 8117 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8118 PackageManager.PERMISSION_GRANTED) { 8119 throw new SecurityException("Must hold permission " + 8120 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8121 } 8122 if (displayId != Display.DEFAULT_DISPLAY) { 8123 throw new IllegalArgumentException("Can only set the default display"); 8124 } 8125 final long ident = Binder.clearCallingIdentity(); 8126 try { 8127 synchronized(mWindowMap) { 8128 // Set some sort of reasonable bounds on the size of the display that we 8129 // will try to emulate. 8130 final int MIN_WIDTH = 200; 8131 final int MIN_HEIGHT = 200; 8132 final int MAX_SCALE = 2; 8133 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8134 if (displayContent != null) { 8135 width = Math.min(Math.max(width, MIN_WIDTH), 8136 displayContent.mInitialDisplayWidth * MAX_SCALE); 8137 height = Math.min(Math.max(height, MIN_HEIGHT), 8138 displayContent.mInitialDisplayHeight * MAX_SCALE); 8139 setForcedDisplaySizeLocked(displayContent, width, height); 8140 Settings.Global.putString(mContext.getContentResolver(), 8141 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 8142 } 8143 } 8144 } finally { 8145 Binder.restoreCallingIdentity(ident); 8146 } 8147 } 8148 8149 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 8150 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 8151 Settings.Global.DISPLAY_SIZE_FORCED); 8152 if (sizeStr == null || sizeStr.length() == 0) { 8153 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 8154 } 8155 if (sizeStr != null && sizeStr.length() > 0) { 8156 final int pos = sizeStr.indexOf(','); 8157 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 8158 int width, height; 8159 try { 8160 width = Integer.parseInt(sizeStr.substring(0, pos)); 8161 height = Integer.parseInt(sizeStr.substring(pos+1)); 8162 synchronized(displayContent.mDisplaySizeLock) { 8163 if (displayContent.mBaseDisplayWidth != width 8164 || displayContent.mBaseDisplayHeight != height) { 8165 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 8166 displayContent.mBaseDisplayWidth = width; 8167 displayContent.mBaseDisplayHeight = height; 8168 } 8169 } 8170 } catch (NumberFormatException ex) { 8171 } 8172 } 8173 } 8174 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 8175 Settings.Global.DISPLAY_DENSITY_FORCED); 8176 if (densityStr == null || densityStr.length() == 0) { 8177 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 8178 } 8179 if (densityStr != null && densityStr.length() > 0) { 8180 int density; 8181 try { 8182 density = Integer.parseInt(densityStr); 8183 synchronized(displayContent.mDisplaySizeLock) { 8184 if (displayContent.mBaseDisplayDensity != density) { 8185 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 8186 displayContent.mBaseDisplayDensity = density; 8187 } 8188 } 8189 } catch (NumberFormatException ex) { 8190 } 8191 } 8192 } 8193 8194 // displayContent must not be null 8195 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 8196 Slog.i(TAG, "Using new display size: " + width + "x" + height); 8197 8198 synchronized(displayContent.mDisplaySizeLock) { 8199 displayContent.mBaseDisplayWidth = width; 8200 displayContent.mBaseDisplayHeight = height; 8201 } 8202 reconfigureDisplayLocked(displayContent); 8203 } 8204 8205 @Override 8206 public void clearForcedDisplaySize(int displayId) { 8207 if (mContext.checkCallingOrSelfPermission( 8208 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8209 PackageManager.PERMISSION_GRANTED) { 8210 throw new SecurityException("Must hold permission " + 8211 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8212 } 8213 if (displayId != Display.DEFAULT_DISPLAY) { 8214 throw new IllegalArgumentException("Can only set the default display"); 8215 } 8216 final long ident = Binder.clearCallingIdentity(); 8217 try { 8218 synchronized(mWindowMap) { 8219 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8220 if (displayContent != null) { 8221 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 8222 displayContent.mInitialDisplayHeight); 8223 Settings.Global.putString(mContext.getContentResolver(), 8224 Settings.Global.DISPLAY_SIZE_FORCED, ""); 8225 } 8226 } 8227 } finally { 8228 Binder.restoreCallingIdentity(ident); 8229 } 8230 } 8231 8232 @Override 8233 public int getInitialDisplayDensity(int displayId) { 8234 synchronized (mWindowMap) { 8235 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8236 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8237 synchronized(displayContent.mDisplaySizeLock) { 8238 return displayContent.mInitialDisplayDensity; 8239 } 8240 } 8241 } 8242 return -1; 8243 } 8244 8245 @Override 8246 public int getBaseDisplayDensity(int displayId) { 8247 synchronized (mWindowMap) { 8248 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8249 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8250 synchronized(displayContent.mDisplaySizeLock) { 8251 return displayContent.mBaseDisplayDensity; 8252 } 8253 } 8254 } 8255 return -1; 8256 } 8257 8258 @Override 8259 public void setForcedDisplayDensity(int displayId, int density) { 8260 if (mContext.checkCallingOrSelfPermission( 8261 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8262 PackageManager.PERMISSION_GRANTED) { 8263 throw new SecurityException("Must hold permission " + 8264 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8265 } 8266 if (displayId != Display.DEFAULT_DISPLAY) { 8267 throw new IllegalArgumentException("Can only set the default display"); 8268 } 8269 final long ident = Binder.clearCallingIdentity(); 8270 try { 8271 synchronized(mWindowMap) { 8272 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8273 if (displayContent != null) { 8274 setForcedDisplayDensityLocked(displayContent, density); 8275 Settings.Global.putString(mContext.getContentResolver(), 8276 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 8277 } 8278 } 8279 } finally { 8280 Binder.restoreCallingIdentity(ident); 8281 } 8282 } 8283 8284 // displayContent must not be null 8285 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 8286 Slog.i(TAG, "Using new display density: " + density); 8287 8288 synchronized(displayContent.mDisplaySizeLock) { 8289 displayContent.mBaseDisplayDensity = density; 8290 } 8291 reconfigureDisplayLocked(displayContent); 8292 } 8293 8294 @Override 8295 public void clearForcedDisplayDensity(int displayId) { 8296 if (mContext.checkCallingOrSelfPermission( 8297 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8298 PackageManager.PERMISSION_GRANTED) { 8299 throw new SecurityException("Must hold permission " + 8300 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8301 } 8302 if (displayId != Display.DEFAULT_DISPLAY) { 8303 throw new IllegalArgumentException("Can only set the default display"); 8304 } 8305 final long ident = Binder.clearCallingIdentity(); 8306 try { 8307 synchronized(mWindowMap) { 8308 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8309 if (displayContent != null) { 8310 setForcedDisplayDensityLocked(displayContent, 8311 displayContent.mInitialDisplayDensity); 8312 Settings.Global.putString(mContext.getContentResolver(), 8313 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 8314 } 8315 } 8316 } finally { 8317 Binder.restoreCallingIdentity(ident); 8318 } 8319 } 8320 8321 // displayContent must not be null 8322 private void reconfigureDisplayLocked(DisplayContent displayContent) { 8323 // TODO: Multidisplay: for now only use with default display. 8324 configureDisplayPolicyLocked(displayContent); 8325 displayContent.layoutNeeded = true; 8326 8327 boolean configChanged = updateOrientationFromAppTokensLocked(false); 8328 mTempConfiguration.setToDefaults(); 8329 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 8330 if (computeScreenConfigurationLocked(mTempConfiguration)) { 8331 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 8332 configChanged = true; 8333 } 8334 } 8335 8336 if (configChanged) { 8337 mWaitingForConfig = true; 8338 startFreezingDisplayLocked(false, 0, 0); 8339 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8340 } 8341 8342 performLayoutAndPlaceSurfacesLocked(); 8343 } 8344 8345 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8346 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8347 displayContent.mBaseDisplayWidth, 8348 displayContent.mBaseDisplayHeight, 8349 displayContent.mBaseDisplayDensity); 8350 8351 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8352 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8353 displayInfo.overscanLeft, displayInfo.overscanTop, 8354 displayInfo.overscanRight, displayInfo.overscanBottom); 8355 } 8356 8357 @Override 8358 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8359 if (mContext.checkCallingOrSelfPermission( 8360 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8361 PackageManager.PERMISSION_GRANTED) { 8362 throw new SecurityException("Must hold permission " + 8363 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8364 } 8365 final long ident = Binder.clearCallingIdentity(); 8366 try { 8367 synchronized(mWindowMap) { 8368 DisplayContent displayContent = getDisplayContentLocked(displayId); 8369 if (displayContent != null) { 8370 setOverscanLocked(displayContent, left, top, right, bottom); 8371 } 8372 } 8373 } finally { 8374 Binder.restoreCallingIdentity(ident); 8375 } 8376 } 8377 8378 private void setOverscanLocked(DisplayContent displayContent, 8379 int left, int top, int right, int bottom) { 8380 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8381 synchronized (displayContent.mDisplaySizeLock) { 8382 displayInfo.overscanLeft = left; 8383 displayInfo.overscanTop = top; 8384 displayInfo.overscanRight = right; 8385 displayInfo.overscanBottom = bottom; 8386 } 8387 8388 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 8389 mDisplaySettings.writeSettingsLocked(); 8390 8391 reconfigureDisplayLocked(displayContent); 8392 } 8393 8394 // ------------------------------------------------------------- 8395 // Internals 8396 // ------------------------------------------------------------- 8397 8398 final WindowState windowForClientLocked(Session session, IWindow client, 8399 boolean throwOnError) { 8400 return windowForClientLocked(session, client.asBinder(), throwOnError); 8401 } 8402 8403 final WindowState windowForClientLocked(Session session, IBinder client, 8404 boolean throwOnError) { 8405 WindowState win = mWindowMap.get(client); 8406 if (localLOGV) Slog.v( 8407 TAG, "Looking up client " + client + ": " + win); 8408 if (win == null) { 8409 RuntimeException ex = new IllegalArgumentException( 8410 "Requested window " + client + " does not exist"); 8411 if (throwOnError) { 8412 throw ex; 8413 } 8414 Slog.w(TAG, "Failed looking up window", ex); 8415 return null; 8416 } 8417 if (session != null && win.mSession != session) { 8418 RuntimeException ex = new IllegalArgumentException( 8419 "Requested window " + client + " is in session " + 8420 win.mSession + ", not " + session); 8421 if (throwOnError) { 8422 throw ex; 8423 } 8424 Slog.w(TAG, "Failed looking up window", ex); 8425 return null; 8426 } 8427 8428 return win; 8429 } 8430 8431 final void rebuildAppWindowListLocked() { 8432 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8433 } 8434 8435 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8436 final WindowList windows = displayContent.getWindowList(); 8437 int NW = windows.size(); 8438 int i; 8439 int lastBelow = -1; 8440 int numRemoved = 0; 8441 8442 if (mRebuildTmp.length < NW) { 8443 mRebuildTmp = new WindowState[NW+10]; 8444 } 8445 8446 // First remove all existing app windows. 8447 i=0; 8448 while (i < NW) { 8449 WindowState w = windows.get(i); 8450 if (w.mAppToken != null) { 8451 WindowState win = windows.remove(i); 8452 win.mRebuilding = true; 8453 mRebuildTmp[numRemoved] = win; 8454 mWindowsChanged = true; 8455 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8456 NW--; 8457 numRemoved++; 8458 continue; 8459 } else if (lastBelow == i-1) { 8460 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8461 lastBelow = i; 8462 } 8463 } 8464 i++; 8465 } 8466 8467 // Keep whatever windows were below the app windows still below, 8468 // by skipping them. 8469 lastBelow++; 8470 i = lastBelow; 8471 8472 // First add all of the exiting app tokens... these are no longer 8473 // in the main app list, but still have windows shown. We put them 8474 // in the back because now that the animation is over we no longer 8475 // will care about them. 8476 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8477 final int numStacks = stacks.size(); 8478 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8479 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8480 int NT = exitingAppTokens.size(); 8481 for (int j = 0; j < NT; j++) { 8482 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8483 } 8484 } 8485 8486 // And add in the still active app tokens in Z order. 8487 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8488 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8489 final int numTasks = tasks.size(); 8490 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8491 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8492 final int numTokens = tokens.size(); 8493 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8494 final AppWindowToken wtoken = tokens.get(tokenNdx); 8495 if (wtoken.mDeferRemoval) { 8496 continue; 8497 } 8498 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8499 } 8500 } 8501 } 8502 8503 i -= lastBelow; 8504 if (i != numRemoved) { 8505 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8506 numRemoved + " windows but added " + i, 8507 new RuntimeException("here").fillInStackTrace()); 8508 for (i=0; i<numRemoved; i++) { 8509 WindowState ws = mRebuildTmp[i]; 8510 if (ws.mRebuilding) { 8511 StringWriter sw = new StringWriter(); 8512 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8513 ws.dump(pw, "", true); 8514 pw.flush(); 8515 Slog.w(TAG, "This window was lost: " + ws); 8516 Slog.w(TAG, sw.toString()); 8517 ws.mWinAnimator.destroySurfaceLocked(); 8518 } 8519 } 8520 Slog.w(TAG, "Current app token list:"); 8521 dumpAppTokensLocked(); 8522 Slog.w(TAG, "Final window list:"); 8523 dumpWindowsLocked(); 8524 } 8525 } 8526 8527 private final void assignLayersLocked(WindowList windows) { 8528 int N = windows.size(); 8529 int curBaseLayer = 0; 8530 int curLayer = 0; 8531 int i; 8532 8533 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8534 new RuntimeException("here").fillInStackTrace()); 8535 8536 boolean anyLayerChanged = false; 8537 8538 for (i=0; i<N; i++) { 8539 final WindowState w = windows.get(i); 8540 final WindowStateAnimator winAnimator = w.mWinAnimator; 8541 boolean layerChanged = false; 8542 int oldLayer = w.mLayer; 8543 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8544 || (i > 0 && w.mIsWallpaper)) { 8545 curLayer += WINDOW_LAYER_MULTIPLIER; 8546 w.mLayer = curLayer; 8547 } else { 8548 curBaseLayer = curLayer = w.mBaseLayer; 8549 w.mLayer = curLayer; 8550 } 8551 if (w.mLayer != oldLayer) { 8552 layerChanged = true; 8553 anyLayerChanged = true; 8554 } 8555 final AppWindowToken wtoken = w.mAppToken; 8556 oldLayer = winAnimator.mAnimLayer; 8557 if (w.mTargetAppToken != null) { 8558 winAnimator.mAnimLayer = 8559 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8560 } else if (wtoken != null) { 8561 winAnimator.mAnimLayer = 8562 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8563 } else { 8564 winAnimator.mAnimLayer = w.mLayer; 8565 } 8566 if (w.mIsImWindow) { 8567 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8568 } else if (w.mIsWallpaper) { 8569 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8570 } 8571 if (winAnimator.mAnimLayer != oldLayer) { 8572 layerChanged = true; 8573 anyLayerChanged = true; 8574 } 8575 final TaskStack stack = w.getStack(); 8576 if (layerChanged && stack != null && stack.isDimming(winAnimator)) { 8577 // Force an animation pass just to update the mDimLayer layer. 8578 scheduleAnimationLocked(); 8579 } 8580 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8581 + "mBase=" + w.mBaseLayer 8582 + " mLayer=" + w.mLayer 8583 + (wtoken == null ? 8584 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8585 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8586 //System.out.println( 8587 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8588 } 8589 8590 //TODO (multidisplay): Magnification is supported only for the default display. 8591 if (mAccessibilityController != null && anyLayerChanged 8592 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8593 mAccessibilityController.onWindowLayersChangedLocked(); 8594 } 8595 } 8596 8597 private final void performLayoutAndPlaceSurfacesLocked() { 8598 int loopCount = 6; 8599 do { 8600 mTraversalScheduled = false; 8601 performLayoutAndPlaceSurfacesLockedLoop(); 8602 mH.removeMessages(H.DO_TRAVERSAL); 8603 loopCount--; 8604 } while (mTraversalScheduled && loopCount > 0); 8605 mInnerFields.mWallpaperActionPending = false; 8606 } 8607 8608 private boolean mInLayout = false; 8609 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8610 if (mInLayout) { 8611 if (DEBUG) { 8612 throw new RuntimeException("Recursive call!"); 8613 } 8614 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8615 + Debug.getCallers(3)); 8616 return; 8617 } 8618 8619 if (mWaitingForConfig) { 8620 // Our configuration has changed (most likely rotation), but we 8621 // don't yet have the complete configuration to report to 8622 // applications. Don't do any window layout until we have it. 8623 return; 8624 } 8625 8626 if (!mDisplayReady) { 8627 // Not yet initialized, nothing to do. 8628 return; 8629 } 8630 8631 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8632 mInLayout = true; 8633 boolean recoveringMemory = false; 8634 8635 try { 8636 if (mForceRemoves != null) { 8637 recoveringMemory = true; 8638 // Wait a little bit for things to settle down, and off we go. 8639 for (int i=0; i<mForceRemoves.size(); i++) { 8640 WindowState ws = mForceRemoves.get(i); 8641 Slog.i(TAG, "Force removing: " + ws); 8642 removeWindowInnerLocked(ws.mSession, ws); 8643 } 8644 mForceRemoves = null; 8645 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8646 Object tmp = new Object(); 8647 synchronized (tmp) { 8648 try { 8649 tmp.wait(250); 8650 } catch (InterruptedException e) { 8651 } 8652 } 8653 } 8654 } catch (RuntimeException e) { 8655 Slog.wtf(TAG, "Unhandled exception while force removing for memory", e); 8656 } 8657 8658 try { 8659 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8660 8661 mInLayout = false; 8662 8663 if (needsLayout()) { 8664 if (++mLayoutRepeatCount < 6) { 8665 requestTraversalLocked(); 8666 } else { 8667 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8668 mLayoutRepeatCount = 0; 8669 } 8670 } else { 8671 mLayoutRepeatCount = 0; 8672 } 8673 8674 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8675 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8676 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8677 } 8678 } catch (RuntimeException e) { 8679 mInLayout = false; 8680 Slog.wtf(TAG, "Unhandled exception while laying out windows", e); 8681 } 8682 8683 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8684 } 8685 8686 private final void performLayoutLockedInner(final DisplayContent displayContent, 8687 boolean initial, boolean updateInputWindows) { 8688 if (!displayContent.layoutNeeded) { 8689 return; 8690 } 8691 displayContent.layoutNeeded = false; 8692 WindowList windows = displayContent.getWindowList(); 8693 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8694 8695 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8696 final int dw = displayInfo.logicalWidth; 8697 final int dh = displayInfo.logicalHeight; 8698 8699 final int NFW = mFakeWindows.size(); 8700 for (int i=0; i<NFW; i++) { 8701 mFakeWindows.get(i).layout(dw, dh); 8702 } 8703 8704 final int N = windows.size(); 8705 int i; 8706 8707 if (DEBUG_LAYOUT) { 8708 Slog.v(TAG, "-------------------------------------"); 8709 Slog.v(TAG, "performLayout: needed=" 8710 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8711 } 8712 8713 WindowStateAnimator universeBackground = null; 8714 8715 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8716 if (isDefaultDisplay) { 8717 // Not needed on non-default displays. 8718 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8719 mScreenRect.set(0, 0, dw, dh); 8720 } 8721 8722 mPolicy.getContentRectLw(mTmpContentRect); 8723 displayContent.resize(mTmpContentRect); 8724 8725 int seq = mLayoutSeq+1; 8726 if (seq < 0) seq = 0; 8727 mLayoutSeq = seq; 8728 8729 boolean behindDream = false; 8730 8731 // First perform layout of any root windows (not attached 8732 // to another window). 8733 int topAttached = -1; 8734 for (i = N-1; i >= 0; i--) { 8735 final WindowState win = windows.get(i); 8736 8737 // Don't do layout of a window if it is not visible, or 8738 // soon won't be visible, to avoid wasting time and funky 8739 // changes while a window is animating away. 8740 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8741 || win.isGoneForLayoutLw(); 8742 8743 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8744 Slog.v(TAG, "1ST PASS " + win 8745 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8746 + " mLayoutAttached=" + win.mLayoutAttached 8747 + " screen changed=" + win.isConfigChanged()); 8748 final AppWindowToken atoken = win.mAppToken; 8749 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8750 + win.mViewVisibility + " mRelayoutCalled=" 8751 + win.mRelayoutCalled + " hidden=" 8752 + win.mRootToken.hidden + " hiddenRequested=" 8753 + (atoken != null && atoken.hiddenRequested) 8754 + " mAttachedHidden=" + win.mAttachedHidden); 8755 else Slog.v(TAG, " VIS: mViewVisibility=" 8756 + win.mViewVisibility + " mRelayoutCalled=" 8757 + win.mRelayoutCalled + " hidden=" 8758 + win.mRootToken.hidden + " hiddenRequested=" 8759 + (atoken != null && atoken.hiddenRequested) 8760 + " mAttachedHidden=" + win.mAttachedHidden); 8761 } 8762 8763 // If this view is GONE, then skip it -- keep the current 8764 // frame, and let the caller know so they can ignore it 8765 // if they want. (We do the normal layout for INVISIBLE 8766 // windows, since that means "perform layout as normal, 8767 // just don't display"). 8768 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8769 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8770 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 8771 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8772 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8773 if (!win.mLayoutAttached) { 8774 if (initial) { 8775 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8776 win.mContentChanged = false; 8777 } 8778 if (win.mAttrs.type == TYPE_DREAM) { 8779 // Don't layout windows behind a dream, so that if it 8780 // does stuff like hide the status bar we won't get a 8781 // bad transition when it goes away. 8782 behindDream = true; 8783 } 8784 win.mLayoutNeeded = false; 8785 win.prelayout(); 8786 mPolicy.layoutWindowLw(win, null); 8787 win.mLayoutSeq = seq; 8788 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8789 + win.mFrame + " mContainingFrame=" 8790 + win.mContainingFrame + " mDisplayFrame=" 8791 + win.mDisplayFrame); 8792 } else { 8793 if (topAttached < 0) topAttached = i; 8794 } 8795 } 8796 if (win.mViewVisibility == View.VISIBLE 8797 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8798 && universeBackground == null) { 8799 universeBackground = win.mWinAnimator; 8800 } 8801 } 8802 8803 if (mAnimator.mUniverseBackground != universeBackground) { 8804 mFocusMayChange = true; 8805 mAnimator.mUniverseBackground = universeBackground; 8806 } 8807 8808 boolean attachedBehindDream = false; 8809 8810 // Now perform layout of attached windows, which usually 8811 // depend on the position of the window they are attached to. 8812 // XXX does not deal with windows that are attached to windows 8813 // that are themselves attached. 8814 for (i = topAttached; i >= 0; i--) { 8815 final WindowState win = windows.get(i); 8816 8817 if (win.mLayoutAttached) { 8818 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8819 + " mHaveFrame=" + win.mHaveFrame 8820 + " mViewVisibility=" + win.mViewVisibility 8821 + " mRelayoutCalled=" + win.mRelayoutCalled); 8822 // If this view is GONE, then skip it -- keep the current 8823 // frame, and let the caller know so they can ignore it 8824 // if they want. (We do the normal layout for INVISIBLE 8825 // windows, since that means "perform layout as normal, 8826 // just don't display"). 8827 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8828 continue; 8829 } 8830 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8831 || !win.mHaveFrame || win.mLayoutNeeded) { 8832 if (initial) { 8833 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8834 win.mContentChanged = false; 8835 } 8836 win.mLayoutNeeded = false; 8837 win.prelayout(); 8838 mPolicy.layoutWindowLw(win, win.mAttachedWindow); 8839 win.mLayoutSeq = seq; 8840 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8841 + win.mFrame + " mContainingFrame=" 8842 + win.mContainingFrame + " mDisplayFrame=" 8843 + win.mDisplayFrame); 8844 } 8845 } else if (win.mAttrs.type == TYPE_DREAM) { 8846 // Don't layout windows behind a dream, so that if it 8847 // does stuff like hide the status bar we won't get a 8848 // bad transition when it goes away. 8849 attachedBehindDream = behindDream; 8850 } 8851 } 8852 8853 // Window frames may have changed. Tell the input dispatcher about it. 8854 mInputMonitor.setUpdateInputWindowsNeededLw(); 8855 if (updateInputWindows) { 8856 mInputMonitor.updateInputWindowsLw(false /*force*/); 8857 } 8858 8859 mPolicy.finishLayoutLw(); 8860 } 8861 8862 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8863 // If the screen is currently frozen or off, then keep 8864 // it frozen/off until this window draws at its new 8865 // orientation. 8866 if (!okToDisplay()) { 8867 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8868 w.mOrientationChanging = true; 8869 w.mLastFreezeDuration = 0; 8870 mInnerFields.mOrientationChangeComplete = false; 8871 if (!mWindowsFreezingScreen) { 8872 mWindowsFreezingScreen = true; 8873 // XXX should probably keep timeout from 8874 // when we first froze the display. 8875 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8876 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8877 WINDOW_FREEZE_TIMEOUT_DURATION); 8878 } 8879 } 8880 } 8881 8882 /** 8883 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8884 * @param windows List of windows on default display. 8885 * @return bitmap indicating if another pass through layout must be made. 8886 */ 8887 public int handleAppTransitionReadyLocked(WindowList windows) { 8888 int changes = 0; 8889 int i; 8890 int NN = mOpeningApps.size(); 8891 boolean goodToGo = true; 8892 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8893 "Checking " + NN + " opening apps (frozen=" 8894 + mDisplayFrozen + " timeout=" 8895 + mAppTransition.isTimeout() + ")..."); 8896 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8897 // If the display isn't frozen, wait to do anything until 8898 // all of the apps are ready. Otherwise just go because 8899 // we'll unfreeze the display when everyone is ready. 8900 for (i=0; i<NN && goodToGo; i++) { 8901 AppWindowToken wtoken = mOpeningApps.valueAt(i); 8902 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8903 "Check opening app=" + wtoken + ": allDrawn=" 8904 + wtoken.allDrawn + " startingDisplayed=" 8905 + wtoken.startingDisplayed + " startingMoved=" 8906 + wtoken.startingMoved); 8907 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8908 && !wtoken.startingMoved) { 8909 goodToGo = false; 8910 } 8911 } 8912 } 8913 if (goodToGo) { 8914 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8915 int transit = mAppTransition.getAppTransition(); 8916 if (mSkipAppTransitionAnimation) { 8917 transit = AppTransition.TRANSIT_UNSET; 8918 } 8919 mAppTransition.goodToGo(); 8920 mStartingIconInTransition = false; 8921 mSkipAppTransitionAnimation = false; 8922 8923 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8924 8925 rebuildAppWindowListLocked(); 8926 8927 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8928 WindowState oldWallpaper = 8929 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8930 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8931 ? null : mWallpaperTarget; 8932 8933 mInnerFields.mWallpaperMayChange = false; 8934 8935 // The top-most window will supply the layout params, 8936 // and we will determine it below. 8937 LayoutParams animLp = null; 8938 int bestAnimLayer = -1; 8939 boolean fullscreenAnim = false; 8940 boolean voiceInteraction = false; 8941 8942 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8943 "New wallpaper target=" + mWallpaperTarget 8944 + ", oldWallpaper=" + oldWallpaper 8945 + ", lower target=" + mLowerWallpaperTarget 8946 + ", upper target=" + mUpperWallpaperTarget); 8947 8948 boolean openingAppHasWallpaper = false; 8949 boolean closingAppHasWallpaper = false; 8950 final AppWindowToken lowerWallpaperAppToken; 8951 final AppWindowToken upperWallpaperAppToken; 8952 if (mLowerWallpaperTarget == null) { 8953 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8954 } else { 8955 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8956 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8957 } 8958 8959 // Do a first pass through the tokens for two 8960 // things: 8961 // (1) Determine if both the closing and opening 8962 // app token sets are wallpaper targets, in which 8963 // case special animations are needed 8964 // (since the wallpaper needs to stay static 8965 // behind them). 8966 // (2) Find the layout params of the top-most 8967 // application window in the tokens, which is 8968 // what will control the animation theme. 8969 final int NC = mClosingApps.size(); 8970 NN = NC + mOpeningApps.size(); 8971 for (i=0; i<NN; i++) { 8972 final AppWindowToken wtoken; 8973 if (i < NC) { 8974 wtoken = mClosingApps.valueAt(i); 8975 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8976 closingAppHasWallpaper = true; 8977 } 8978 } else { 8979 wtoken = mOpeningApps.valueAt(i - NC); 8980 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8981 openingAppHasWallpaper = true; 8982 } 8983 } 8984 8985 voiceInteraction |= wtoken.voiceInteraction; 8986 8987 if (wtoken.appFullscreen) { 8988 WindowState ws = wtoken.findMainWindow(); 8989 if (ws != null) { 8990 animLp = ws.mAttrs; 8991 bestAnimLayer = ws.mLayer; 8992 fullscreenAnim = true; 8993 } 8994 } else if (!fullscreenAnim) { 8995 WindowState ws = wtoken.findMainWindow(); 8996 if (ws != null) { 8997 if (ws.mLayer > bestAnimLayer) { 8998 animLp = ws.mAttrs; 8999 bestAnimLayer = ws.mLayer; 9000 } 9001 } 9002 } 9003 } 9004 9005 mAnimateWallpaperWithTarget = false; 9006 if (closingAppHasWallpaper && openingAppHasWallpaper) { 9007 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 9008 switch (transit) { 9009 case AppTransition.TRANSIT_ACTIVITY_OPEN: 9010 case AppTransition.TRANSIT_TASK_OPEN: 9011 case AppTransition.TRANSIT_TASK_TO_FRONT: 9012 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 9013 break; 9014 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 9015 case AppTransition.TRANSIT_TASK_CLOSE: 9016 case AppTransition.TRANSIT_TASK_TO_BACK: 9017 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 9018 break; 9019 } 9020 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 9021 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 9022 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 9023 // We are transitioning from an activity with 9024 // a wallpaper to one without. 9025 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 9026 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 9027 "New transit away from wallpaper: " + transit); 9028 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 9029 // We are transitioning from an activity without 9030 // a wallpaper to now showing the wallpaper 9031 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 9032 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 9033 "New transit into wallpaper: " + transit); 9034 } else { 9035 mAnimateWallpaperWithTarget = true; 9036 } 9037 9038 // If all closing windows are obscured, then there is 9039 // no need to do an animation. This is the case, for 9040 // example, when this transition is being done behind 9041 // the lock screen. 9042 if (!mPolicy.allowAppAnimationsLw()) { 9043 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 9044 "Animations disallowed by keyguard or dream."); 9045 animLp = null; 9046 } 9047 9048 AppWindowToken topOpeningApp = null; 9049 AppWindowToken topClosingApp = null; 9050 int topOpeningLayer = 0; 9051 int topClosingLayer = 0; 9052 9053 NN = mOpeningApps.size(); 9054 for (i=0; i<NN; i++) { 9055 AppWindowToken wtoken = mOpeningApps.valueAt(i); 9056 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 9057 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 9058 appAnimator.clearThumbnail(); 9059 appAnimator.animation = null; 9060 wtoken.inPendingTransaction = false; 9061 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction); 9062 wtoken.updateReportedVisibilityLocked(); 9063 wtoken.waitingToShow = false; 9064 9065 appAnimator.mAllAppWinAnimators.clear(); 9066 final int N = wtoken.allAppWindows.size(); 9067 for (int j = 0; j < N; j++) { 9068 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 9069 } 9070 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 9071 9072 if (animLp != null) { 9073 int layer = -1; 9074 for (int j=0; j<wtoken.windows.size(); j++) { 9075 WindowState win = wtoken.windows.get(j); 9076 if (win.mWinAnimator.mAnimLayer > layer) { 9077 layer = win.mWinAnimator.mAnimLayer; 9078 } 9079 } 9080 if (topOpeningApp == null || layer > topOpeningLayer) { 9081 topOpeningApp = wtoken; 9082 topOpeningLayer = layer; 9083 } 9084 } 9085 } 9086 NN = mClosingApps.size(); 9087 for (i=0; i<NN; i++) { 9088 AppWindowToken wtoken = mClosingApps.valueAt(i); 9089 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 9090 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 9091 appAnimator.clearThumbnail(); 9092 appAnimator.animation = null; 9093 wtoken.inPendingTransaction = false; 9094 setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction); 9095 wtoken.updateReportedVisibilityLocked(); 9096 wtoken.waitingToHide = false; 9097 // Force the allDrawn flag, because we want to start 9098 // this guy's animations regardless of whether it's 9099 // gotten drawn. 9100 wtoken.allDrawn = true; 9101 wtoken.deferClearAllDrawn = false; 9102 // Ensure that apps that are mid-starting are also scheduled to have their 9103 // starting windows removed after the animation is complete 9104 if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) { 9105 scheduleRemoveStartingWindowLocked(wtoken); 9106 } 9107 9108 if (animLp != null) { 9109 int layer = -1; 9110 for (int j=0; j<wtoken.windows.size(); j++) { 9111 WindowState win = wtoken.windows.get(j); 9112 if (win.mWinAnimator.mAnimLayer > layer) { 9113 layer = win.mWinAnimator.mAnimLayer; 9114 } 9115 } 9116 if (topClosingApp == null || layer > topClosingLayer) { 9117 topClosingApp = wtoken; 9118 topClosingLayer = layer; 9119 } 9120 } 9121 } 9122 9123 AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null : 9124 topOpeningApp.mAppAnimator; 9125 AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null : 9126 topClosingApp.mAppAnimator; 9127 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 9128 if (nextAppTransitionThumbnail != null 9129 && openingAppAnimator != null && openingAppAnimator.animation != null && 9130 nextAppTransitionThumbnail.getConfig() != Config.ALPHA_8) { 9131 // This thumbnail animation is very special, we need to have 9132 // an extra surface with the thumbnail included with the animation. 9133 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 9134 nextAppTransitionThumbnail.getHeight()); 9135 try { 9136 // TODO(multi-display): support other displays 9137 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9138 final Display display = displayContent.getDisplay(); 9139 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9140 9141 // Create a new surface for the thumbnail 9142 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 9143 "thumbnail anim", dirty.width(), dirty.height(), 9144 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 9145 surfaceControl.setLayerStack(display.getLayerStack()); 9146 if (SHOW_TRANSACTIONS) { 9147 Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 9148 } 9149 9150 // Draw the thumbnail onto the surface 9151 Surface drawSurface = new Surface(); 9152 drawSurface.copyFrom(surfaceControl); 9153 Canvas c = drawSurface.lockCanvas(dirty); 9154 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 9155 drawSurface.unlockCanvasAndPost(c); 9156 drawSurface.release(); 9157 9158 // Get the thumbnail animation 9159 Animation anim; 9160 if (mAppTransition.isNextThumbnailTransitionAspectScaled()) { 9161 // For the new aspect-scaled transition, we want it to always show 9162 // above the animating opening/closing window, and we want to 9163 // synchronize its thumbnail surface with the surface for the 9164 // open/close animation (only on the way down) 9165 anim = mAppTransition.createThumbnailAspectScaleAnimationLocked( 9166 displayInfo.appWidth, displayInfo.appHeight, 9167 displayInfo.logicalWidth, transit); 9168 openingAppAnimator.thumbnailForceAboveLayer = Math.max(topOpeningLayer, 9169 topClosingLayer); 9170 openingAppAnimator.deferThumbnailDestruction = 9171 !mAppTransition.isNextThumbnailTransitionScaleUp(); 9172 if (openingAppAnimator.deferThumbnailDestruction) { 9173 if (closingAppAnimator != null && 9174 closingAppAnimator.animation != null) { 9175 closingAppAnimator.deferredThumbnail = surfaceControl; 9176 } 9177 } 9178 } else { 9179 anim = mAppTransition.createThumbnailScaleAnimationLocked( 9180 displayInfo.appWidth, displayInfo.appHeight, transit); 9181 } 9182 anim.restrictDuration(MAX_ANIMATION_DURATION); 9183 anim.scaleCurrentDuration(getTransitionAnimationScaleLocked()); 9184 9185 openingAppAnimator.thumbnail = surfaceControl; 9186 openingAppAnimator.thumbnailLayer = topOpeningLayer; 9187 openingAppAnimator.thumbnailAnimation = anim; 9188 openingAppAnimator.thumbnailX = mAppTransition.getStartingX(); 9189 openingAppAnimator.thumbnailY = mAppTransition.getStartingY(); 9190 } catch (OutOfResourcesException e) { 9191 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 9192 + " h=" + dirty.height(), e); 9193 openingAppAnimator.clearThumbnail(); 9194 } 9195 } 9196 9197 mAppTransition.postAnimationCallback(); 9198 mAppTransition.clear(); 9199 9200 mOpeningApps.clear(); 9201 mClosingApps.clear(); 9202 9203 // This has changed the visibility of windows, so perform 9204 // a new layout to get them all up-to-date. 9205 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 9206 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 9207 getDefaultDisplayContentLocked().layoutNeeded = true; 9208 9209 // TODO(multidisplay): IMEs are only supported on the default display. 9210 if (windows == getDefaultWindowListLocked() 9211 && !moveInputMethodWindowsIfNeededLocked(true)) { 9212 assignLayersLocked(windows); 9213 } 9214 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/); 9215 mFocusMayChange = false; 9216 } 9217 9218 return changes; 9219 } 9220 9221 /** 9222 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 9223 * @return bitmap indicating if another pass through layout must be made. 9224 */ 9225 private int handleAnimatingStoppedAndTransitionLocked() { 9226 int changes = 0; 9227 9228 mAppTransition.setIdle(); 9229 // Restore window app tokens to the ActivityManager views 9230 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 9231 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9232 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9233 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9234 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9235 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9236 tokens.get(tokenNdx).sendingToBottom = false; 9237 } 9238 } 9239 } 9240 rebuildAppWindowListLocked(); 9241 9242 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 9243 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9244 "Wallpaper layer changed: assigning layers + relayout"); 9245 moveInputMethodWindowsIfNeededLocked(true); 9246 mInnerFields.mWallpaperMayChange = true; 9247 // Since the window list has been rebuilt, focus might 9248 // have to be recomputed since the actual order of windows 9249 // might have changed again. 9250 mFocusMayChange = true; 9251 9252 return changes; 9253 } 9254 9255 private void updateResizingWindows(final WindowState w) { 9256 final WindowStateAnimator winAnimator = w.mWinAnimator; 9257 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 9258 w.setInsetsChanged(); 9259 boolean configChanged = w.isConfigChanged(); 9260 if (DEBUG_CONFIGURATION && configChanged) { 9261 Slog.v(TAG, "Win " + w + " config changed: " 9262 + mCurConfiguration); 9263 } 9264 if (localLOGV) Slog.v(TAG, "Resizing " + w 9265 + ": configChanged=" + configChanged 9266 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 9267 w.mLastFrame.set(w.mFrame); 9268 if (w.mContentInsetsChanged 9269 || w.mVisibleInsetsChanged 9270 || winAnimator.mSurfaceResized 9271 || configChanged) { 9272 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 9273 Slog.v(TAG, "Resize reasons for w=" + w + ": " 9274 + " contentInsetsChanged=" + w.mContentInsetsChanged 9275 + " " + w.mContentInsets.toShortString() 9276 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 9277 + " " + w.mVisibleInsets.toShortString() 9278 + " stableInsetsChanged=" + w.mStableInsetsChanged 9279 + " " + w.mStableInsets.toShortString() 9280 + " surfaceResized=" + winAnimator.mSurfaceResized 9281 + " configChanged=" + configChanged); 9282 } 9283 9284 w.mLastOverscanInsets.set(w.mOverscanInsets); 9285 w.mLastContentInsets.set(w.mContentInsets); 9286 w.mLastVisibleInsets.set(w.mVisibleInsets); 9287 w.mLastStableInsets.set(w.mStableInsets); 9288 makeWindowFreezingScreenIfNeededLocked(w); 9289 // If the orientation is changing, then we need to 9290 // hold off on unfreezing the display until this 9291 // window has been redrawn; to do that, we need 9292 // to go through the process of getting informed 9293 // by the application when it has finished drawing. 9294 if (w.mOrientationChanging) { 9295 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 9296 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 9297 + w + ", surface " + winAnimator.mSurfaceControl); 9298 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 9299 if (w.mAppToken != null) { 9300 w.mAppToken.allDrawn = false; 9301 w.mAppToken.deferClearAllDrawn = false; 9302 } 9303 } 9304 if (!mResizingWindows.contains(w)) { 9305 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 9306 "Resizing window " + w + " to " + winAnimator.mSurfaceW 9307 + "x" + winAnimator.mSurfaceH); 9308 mResizingWindows.add(w); 9309 } 9310 } else if (w.mOrientationChanging) { 9311 if (w.isDrawnLw()) { 9312 if (DEBUG_ORIENTATION) Slog.v(TAG, 9313 "Orientation not waiting for draw in " 9314 + w + ", surface " + winAnimator.mSurfaceControl); 9315 w.mOrientationChanging = false; 9316 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 9317 - mDisplayFreezeTime); 9318 } 9319 } 9320 } 9321 } 9322 9323 /** 9324 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 9325 * 9326 * @param w WindowState this method is applied to. 9327 * @param currentTime The time which animations use for calculating transitions. 9328 * @param innerDw Width of app window. 9329 * @param innerDh Height of app window. 9330 */ 9331 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 9332 final int innerDw, final int innerDh) { 9333 final WindowManager.LayoutParams attrs = w.mAttrs; 9334 final int attrFlags = attrs.flags; 9335 final boolean canBeSeen = w.isDisplayedLw(); 9336 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 9337 9338 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 9339 // This window completely covers everything behind it, 9340 // so we want to leave all of them as undimmed (for 9341 // performance reasons). 9342 mInnerFields.mObscured = true; 9343 } 9344 9345 if (w.mHasSurface) { 9346 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 9347 mInnerFields.mHoldScreen = w.mSession; 9348 } 9349 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 9350 && mInnerFields.mScreenBrightness < 0) { 9351 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 9352 } 9353 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 9354 && mInnerFields.mButtonBrightness < 0) { 9355 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 9356 } 9357 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 9358 && mInnerFields.mUserActivityTimeout < 0) { 9359 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 9360 } 9361 9362 final int type = attrs.type; 9363 if (canBeSeen 9364 && (type == TYPE_SYSTEM_DIALOG 9365 || type == TYPE_SYSTEM_ERROR 9366 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { 9367 mInnerFields.mSyswin = true; 9368 } 9369 9370 if (canBeSeen) { 9371 // This function assumes that the contents of the default display are 9372 // processed first before secondary displays. 9373 final DisplayContent displayContent = w.getDisplayContent(); 9374 if (displayContent != null && displayContent.isDefaultDisplay) { 9375 // While a dream or keyguard is showing, obscure ordinary application 9376 // content on secondary displays (by forcibly enabling mirroring unless 9377 // there is other content we want to show) but still allow opaque 9378 // keyguard dialogs to be shown. 9379 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 9380 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 9381 } 9382 mInnerFields.mDisplayHasContent = true; 9383 } else if (displayContent != null && 9384 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 9385 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 9386 // Allow full screen keyguard presentation dialogs to be seen. 9387 mInnerFields.mDisplayHasContent = true; 9388 } 9389 if (mInnerFields.mPreferredRefreshRate == 0 9390 && w.mAttrs.preferredRefreshRate != 0) { 9391 mInnerFields.mPreferredRefreshRate = w.mAttrs.preferredRefreshRate; 9392 } 9393 } 9394 } 9395 } 9396 9397 private void handleFlagDimBehind(WindowState w) { 9398 final WindowManager.LayoutParams attrs = w.mAttrs; 9399 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 9400 && w.isDisplayedLw() 9401 && !w.mExiting) { 9402 final WindowStateAnimator winAnimator = w.mWinAnimator; 9403 final TaskStack stack = w.getStack(); 9404 if (stack == null) { 9405 return; 9406 } 9407 stack.setDimmingTag(); 9408 if (!stack.isDimming(winAnimator)) { 9409 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 9410 stack.startDimmingIfNeeded(winAnimator); 9411 } 9412 } 9413 } 9414 9415 private void updateAllDrawnLocked(DisplayContent displayContent) { 9416 // See if any windows have been drawn, so they (and others 9417 // associated with them) can now be shown. 9418 ArrayList<TaskStack> stacks = displayContent.getStacks(); 9419 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9420 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9421 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9422 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9423 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9424 final AppWindowToken wtoken = tokens.get(tokenNdx); 9425 if (!wtoken.allDrawn) { 9426 int numInteresting = wtoken.numInterestingWindows; 9427 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 9428 if (DEBUG_VISIBILITY) Slog.v(TAG, 9429 "allDrawn: " + wtoken 9430 + " interesting=" + numInteresting 9431 + " drawn=" + wtoken.numDrawnWindows); 9432 wtoken.allDrawn = true; 9433 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9434 } 9435 } 9436 } 9437 } 9438 } 9439 } 9440 9441 // "Something has changed! Let's make it correct now." 9442 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9443 if (DEBUG_WINDOW_TRACE) { 9444 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9445 + Debug.getCallers(3)); 9446 } 9447 9448 final long currentTime = SystemClock.uptimeMillis(); 9449 9450 int i; 9451 boolean updateInputWindowsNeeded = false; 9452 9453 if (mFocusMayChange) { 9454 mFocusMayChange = false; 9455 updateInputWindowsNeeded = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9456 false /*updateInputWindows*/); 9457 } 9458 9459 // Initialize state of exiting tokens. 9460 final int numDisplays = mDisplayContents.size(); 9461 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9462 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9463 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9464 displayContent.mExitingTokens.get(i).hasVisible = false; 9465 } 9466 } 9467 9468 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9469 // Initialize state of exiting applications. 9470 final AppTokenList exitingAppTokens = 9471 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9472 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9473 exitingAppTokens.get(tokenNdx).hasVisible = false; 9474 } 9475 } 9476 9477 mInnerFields.mHoldScreen = null; 9478 mInnerFields.mScreenBrightness = -1; 9479 mInnerFields.mButtonBrightness = -1; 9480 mInnerFields.mUserActivityTimeout = -1; 9481 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9482 9483 mTransactionSequence++; 9484 9485 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9486 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9487 final int defaultDw = defaultInfo.logicalWidth; 9488 final int defaultDh = defaultInfo.logicalHeight; 9489 9490 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9491 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9492 SurfaceControl.openTransaction(); 9493 try { 9494 9495 if (mWatermark != null) { 9496 mWatermark.positionSurface(defaultDw, defaultDh); 9497 } 9498 if (mStrictModeFlash != null) { 9499 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9500 } 9501 if (mCircularDisplayMask != null) { 9502 mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation); 9503 } 9504 if (mEmulatorDisplayOverlay != null) { 9505 mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, mRotation); 9506 } 9507 9508 boolean focusDisplayed = false; 9509 9510 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9511 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9512 boolean updateAllDrawn = false; 9513 WindowList windows = displayContent.getWindowList(); 9514 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9515 final int displayId = displayContent.getDisplayId(); 9516 final int dw = displayInfo.logicalWidth; 9517 final int dh = displayInfo.logicalHeight; 9518 final int innerDw = displayInfo.appWidth; 9519 final int innerDh = displayInfo.appHeight; 9520 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9521 9522 // Reset for each display. 9523 mInnerFields.mDisplayHasContent = false; 9524 mInnerFields.mPreferredRefreshRate = 0; 9525 9526 int repeats = 0; 9527 do { 9528 repeats++; 9529 if (repeats > 6) { 9530 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9531 displayContent.layoutNeeded = false; 9532 break; 9533 } 9534 9535 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9536 displayContent.pendingLayoutChanges); 9537 9538 if ((displayContent.pendingLayoutChanges & 9539 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9540 (adjustWallpaperWindowsLocked() & 9541 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9542 assignLayersLocked(windows); 9543 displayContent.layoutNeeded = true; 9544 } 9545 9546 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9547 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9548 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9549 if (updateOrientationFromAppTokensLocked(true)) { 9550 displayContent.layoutNeeded = true; 9551 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9552 } 9553 } 9554 9555 if ((displayContent.pendingLayoutChanges 9556 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9557 displayContent.layoutNeeded = true; 9558 } 9559 9560 // FIRST LOOP: Perform a layout, if needed. 9561 if (repeats < 4) { 9562 performLayoutLockedInner(displayContent, repeats == 1, 9563 false /*updateInputWindows*/); 9564 } else { 9565 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9566 } 9567 9568 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9569 // it is animating. 9570 displayContent.pendingLayoutChanges = 0; 9571 9572 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9573 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9574 9575 if (isDefaultDisplay) { 9576 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9577 for (i = windows.size() - 1; i >= 0; i--) { 9578 WindowState w = windows.get(i); 9579 if (w.mHasSurface) { 9580 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9581 } 9582 } 9583 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9584 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9585 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9586 } 9587 } while (displayContent.pendingLayoutChanges != 0); 9588 9589 mInnerFields.mObscured = false; 9590 mInnerFields.mSyswin = false; 9591 displayContent.resetDimming(); 9592 9593 // Only used if default window 9594 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9595 9596 final int N = windows.size(); 9597 for (i=N-1; i>=0; i--) { 9598 WindowState w = windows.get(i); 9599 final TaskStack stack = w.getStack(); 9600 if (stack == null) { 9601 continue; 9602 } 9603 9604 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9605 9606 // Update effect. 9607 w.mObscured = mInnerFields.mObscured; 9608 if (!mInnerFields.mObscured) { 9609 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9610 } 9611 9612 if (!stack.testDimmingTag()) { 9613 handleFlagDimBehind(w); 9614 } 9615 9616 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9617 && w.isVisibleLw()) { 9618 // This is the wallpaper target and its obscured state 9619 // changed... make sure the current wallaper's visibility 9620 // has been updated accordingly. 9621 updateWallpaperVisibilityLocked(); 9622 } 9623 9624 final WindowStateAnimator winAnimator = w.mWinAnimator; 9625 9626 // If the window has moved due to its containing 9627 // content frame changing, then we'd like to animate 9628 // it. 9629 if (w.mHasSurface && w.shouldAnimateMove()) { 9630 // Frame has moved, containing content frame 9631 // has also moved, and we're not currently animating... 9632 // let's do something. 9633 Animation a = AnimationUtils.loadAnimation(mContext, 9634 com.android.internal.R.anim.window_move_from_decor); 9635 winAnimator.setAnimation(a); 9636 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9637 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9638 9639 //TODO (multidisplay): Accessibility supported only for the default display. 9640 if (mAccessibilityController != null 9641 && displayId == Display.DEFAULT_DISPLAY) { 9642 mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 9643 } 9644 9645 try { 9646 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9647 } catch (RemoteException e) { 9648 } 9649 } 9650 9651 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9652 w.mContentChanged = false; 9653 9654 // Moved from updateWindowsAndWallpaperLocked(). 9655 if (w.mHasSurface) { 9656 // Take care of the window being ready to display. 9657 final boolean committed = 9658 winAnimator.commitFinishDrawingLocked(currentTime); 9659 if (isDefaultDisplay && committed) { 9660 if (w.mAttrs.type == TYPE_DREAM) { 9661 // HACK: When a dream is shown, it may at that 9662 // point hide the lock screen. So we need to 9663 // redo the layout to let the phone window manager 9664 // make this happen. 9665 displayContent.pendingLayoutChanges |= 9666 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9667 if (DEBUG_LAYOUT_REPEATS) { 9668 debugLayoutRepeats( 9669 "dream and commitFinishDrawingLocked true", 9670 displayContent.pendingLayoutChanges); 9671 } 9672 } 9673 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9674 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9675 "First draw done in potential wallpaper target " + w); 9676 mInnerFields.mWallpaperMayChange = true; 9677 displayContent.pendingLayoutChanges |= 9678 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9679 if (DEBUG_LAYOUT_REPEATS) { 9680 debugLayoutRepeats( 9681 "wallpaper and commitFinishDrawingLocked true", 9682 displayContent.pendingLayoutChanges); 9683 } 9684 } 9685 } 9686 9687 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9688 9689 final AppWindowToken atoken = w.mAppToken; 9690 if (DEBUG_STARTING_WINDOW && atoken != null 9691 && w == atoken.startingWindow) { 9692 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9693 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9694 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9695 } 9696 if (atoken != null 9697 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9698 if (atoken.lastTransactionSequence != mTransactionSequence) { 9699 atoken.lastTransactionSequence = mTransactionSequence; 9700 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9701 atoken.startingDisplayed = false; 9702 } 9703 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9704 && !w.mExiting && !w.mDestroying) { 9705 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9706 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9707 + ", isAnimating=" + winAnimator.isAnimating()); 9708 if (!w.isDrawnLw()) { 9709 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9710 + " pv=" + w.mPolicyVisibility 9711 + " mDrawState=" + winAnimator.mDrawState 9712 + " ah=" + w.mAttachedHidden 9713 + " th=" + atoken.hiddenRequested 9714 + " a=" + winAnimator.mAnimating); 9715 } 9716 } 9717 if (w != atoken.startingWindow) { 9718 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9719 atoken.numInterestingWindows++; 9720 if (w.isDrawnLw()) { 9721 atoken.numDrawnWindows++; 9722 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9723 "tokenMayBeDrawn: " + atoken 9724 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9725 + " mAppFreezing=" + w.mAppFreezing); 9726 updateAllDrawn = true; 9727 } 9728 } 9729 } else if (w.isDrawnLw()) { 9730 atoken.startingDisplayed = true; 9731 } 9732 } 9733 } 9734 } 9735 9736 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9737 && w.isDisplayedLw()) { 9738 focusDisplayed = true; 9739 } 9740 9741 updateResizingWindows(w); 9742 } 9743 9744 mDisplayManagerInternal.setDisplayProperties(displayId, 9745 mInnerFields.mDisplayHasContent, mInnerFields.mPreferredRefreshRate, 9746 true /* inTraversal, must call performTraversalInTrans... below */); 9747 9748 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9749 9750 if (updateAllDrawn) { 9751 updateAllDrawnLocked(displayContent); 9752 } 9753 } 9754 9755 if (focusDisplayed) { 9756 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9757 } 9758 9759 // Give the display manager a chance to adjust properties 9760 // like display rotation if it needs to. 9761 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9762 9763 } catch (RuntimeException e) { 9764 Slog.wtf(TAG, "Unhandled exception in Window Manager", e); 9765 } finally { 9766 SurfaceControl.closeTransaction(); 9767 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9768 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9769 } 9770 9771 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9772 9773 // If we are ready to perform an app transition, check through 9774 // all of the app tokens to be shown and see if they are ready 9775 // to go. 9776 if (mAppTransition.isReady()) { 9777 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9778 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9779 defaultDisplay.pendingLayoutChanges); 9780 } 9781 9782 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9783 // We have finished the animation of an app transition. To do 9784 // this, we have delayed a lot of operations like showing and 9785 // hiding apps, moving apps in Z-order, etc. The app token list 9786 // reflects the correct Z-order, but the window list may now 9787 // be out of sync with it. So here we will just rebuild the 9788 // entire app window list. Fun! 9789 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9790 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9791 defaultDisplay.pendingLayoutChanges); 9792 } 9793 9794 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9795 && !mAppTransition.isReady()) { 9796 // At this point, there was a window with a wallpaper that 9797 // was force hiding other windows behind it, but now it 9798 // is going away. This may be simple -- just animate 9799 // away the wallpaper and its window -- or it may be 9800 // hard -- the wallpaper now needs to be shown behind 9801 // something that was hidden. 9802 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9803 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9804 defaultDisplay.pendingLayoutChanges); 9805 } 9806 mInnerFields.mWallpaperForceHidingChanged = false; 9807 9808 if (mInnerFields.mWallpaperMayChange) { 9809 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9810 defaultDisplay.pendingLayoutChanges |= 9811 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9812 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9813 defaultDisplay.pendingLayoutChanges); 9814 } 9815 9816 if (mFocusMayChange) { 9817 mFocusMayChange = false; 9818 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9819 false /*updateInputWindows*/)) { 9820 updateInputWindowsNeeded = true; 9821 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9822 } 9823 } 9824 9825 if (needsLayout()) { 9826 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9827 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9828 defaultDisplay.pendingLayoutChanges); 9829 } 9830 9831 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9832 WindowState win = mResizingWindows.get(i); 9833 if (win.mAppFreezing) { 9834 // Don't remove this window until rotation has completed. 9835 continue; 9836 } 9837 win.reportResized(); 9838 mResizingWindows.remove(i); 9839 } 9840 9841 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9842 "With display frozen, orientationChangeComplete=" 9843 + mInnerFields.mOrientationChangeComplete); 9844 if (mInnerFields.mOrientationChangeComplete) { 9845 if (mWindowsFreezingScreen) { 9846 mWindowsFreezingScreen = false; 9847 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9848 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9849 } 9850 stopFreezingDisplayLocked(); 9851 } 9852 9853 // Destroy the surface of any windows that are no longer visible. 9854 boolean wallpaperDestroyed = false; 9855 i = mDestroySurface.size(); 9856 if (i > 0) { 9857 do { 9858 i--; 9859 WindowState win = mDestroySurface.get(i); 9860 win.mDestroying = false; 9861 if (mInputMethodWindow == win) { 9862 mInputMethodWindow = null; 9863 } 9864 if (win == mWallpaperTarget) { 9865 wallpaperDestroyed = true; 9866 } 9867 win.mWinAnimator.destroySurfaceLocked(); 9868 } while (i > 0); 9869 mDestroySurface.clear(); 9870 } 9871 9872 // Time to remove any exiting tokens? 9873 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9874 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9875 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9876 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9877 WindowToken token = exitingTokens.get(i); 9878 if (!token.hasVisible) { 9879 exitingTokens.remove(i); 9880 if (token.windowType == TYPE_WALLPAPER) { 9881 mWallpaperTokens.remove(token); 9882 } 9883 } 9884 } 9885 } 9886 9887 // Time to remove any exiting applications? 9888 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9889 // Initialize state of exiting applications. 9890 final AppTokenList exitingAppTokens = 9891 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9892 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9893 AppWindowToken token = exitingAppTokens.get(i); 9894 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 9895 // Make sure there is no animation running on this token, 9896 // so any windows associated with it will be removed as 9897 // soon as their animations are complete 9898 token.mAppAnimator.clearAnimation(); 9899 token.mAppAnimator.animating = false; 9900 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9901 "performLayout: App token exiting now removed" + token); 9902 removeAppFromTaskLocked(token); 9903 exitingAppTokens.remove(i); 9904 } 9905 } 9906 } 9907 9908 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9909 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9910 try { 9911 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9912 } catch (RemoteException e) { 9913 } 9914 } 9915 mRelayoutWhileAnimating.clear(); 9916 } 9917 9918 if (wallpaperDestroyed) { 9919 defaultDisplay.pendingLayoutChanges |= 9920 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9921 defaultDisplay.layoutNeeded = true; 9922 } 9923 9924 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9925 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9926 if (displayContent.pendingLayoutChanges != 0) { 9927 displayContent.layoutNeeded = true; 9928 } 9929 } 9930 9931 // Finally update all input windows now that the window changes have stabilized. 9932 mInputMonitor.updateInputWindowsLw(true /*force*/); 9933 9934 setHoldScreenLocked(mInnerFields.mHoldScreen); 9935 if (!mDisplayFrozen) { 9936 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9937 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 9938 } else { 9939 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 9940 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9941 } 9942 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9943 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 9944 } else { 9945 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 9946 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9947 } 9948 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 9949 mInnerFields.mUserActivityTimeout); 9950 } 9951 9952 if (mTurnOnScreen) { 9953 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9954 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9955 mTurnOnScreen = false; 9956 } 9957 9958 if (mInnerFields.mUpdateRotation) { 9959 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9960 if (updateRotationUncheckedLocked(false)) { 9961 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9962 } else { 9963 mInnerFields.mUpdateRotation = false; 9964 } 9965 } 9966 9967 if (mWaitingForDrawnCallback != null || 9968 (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded && 9969 !mInnerFields.mUpdateRotation)) { 9970 checkDrawnWindowsLocked(); 9971 } 9972 9973 final int N = mPendingRemove.size(); 9974 if (N > 0) { 9975 if (mPendingRemoveTmp.length < N) { 9976 mPendingRemoveTmp = new WindowState[N+10]; 9977 } 9978 mPendingRemove.toArray(mPendingRemoveTmp); 9979 mPendingRemove.clear(); 9980 DisplayContentList displayList = new DisplayContentList(); 9981 for (i = 0; i < N; i++) { 9982 WindowState w = mPendingRemoveTmp[i]; 9983 removeWindowInnerLocked(w.mSession, w); 9984 final DisplayContent displayContent = w.getDisplayContent(); 9985 if (displayContent != null && !displayList.contains(displayContent)) { 9986 displayList.add(displayContent); 9987 } 9988 } 9989 9990 for (DisplayContent displayContent : displayList) { 9991 assignLayersLocked(displayContent.getWindowList()); 9992 displayContent.layoutNeeded = true; 9993 } 9994 } 9995 9996 // Remove all deferred displays stacks, tasks, and activities. 9997 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 9998 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 9999 } 10000 10001 if (updateInputWindowsNeeded) { 10002 mInputMonitor.updateInputWindowsLw(false /*force*/); 10003 } 10004 setFocusedStackFrame(); 10005 10006 // Check to see if we are now in a state where the screen should 10007 // be enabled, because the window obscured flags have changed. 10008 enableScreenIfNeededLocked(); 10009 10010 scheduleAnimationLocked(); 10011 10012 if (DEBUG_WINDOW_TRACE) { 10013 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 10014 + mAnimator.mAnimating); 10015 } 10016 } 10017 10018 private int toBrightnessOverride(float value) { 10019 return (int)(value * PowerManager.BRIGHTNESS_ON); 10020 } 10021 10022 void checkDrawnWindowsLocked() { 10023 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 10024 return; 10025 } 10026 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 10027 WindowState win = mWaitingForDrawn.get(j); 10028 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 10029 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 10030 " mHasSurface=" + win.mHasSurface + 10031 " drawState=" + win.mWinAnimator.mDrawState); 10032 if (win.mRemoved || !win.mHasSurface) { 10033 // Window has been removed; no draw will now happen, so stop waiting. 10034 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 10035 mWaitingForDrawn.remove(win); 10036 } else if (win.hasDrawnLw()) { 10037 // Window is now drawn (and shown). 10038 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 10039 mWaitingForDrawn.remove(win); 10040 } 10041 } 10042 if (mWaitingForDrawn.isEmpty()) { 10043 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 10044 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 10045 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 10046 } 10047 } 10048 10049 void setHoldScreenLocked(final Session newHoldScreen) { 10050 final boolean hold = newHoldScreen != null; 10051 10052 if (hold && mHoldingScreenOn != newHoldScreen) { 10053 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 10054 } 10055 mHoldingScreenOn = newHoldScreen; 10056 10057 final boolean state = mHoldingScreenWakeLock.isHeld(); 10058 if (hold != state) { 10059 if (hold) { 10060 mHoldingScreenWakeLock.acquire(); 10061 mPolicy.keepScreenOnStartedLw(); 10062 } else { 10063 mPolicy.keepScreenOnStoppedLw(); 10064 mHoldingScreenWakeLock.release(); 10065 } 10066 } 10067 } 10068 10069 void requestTraversal() { 10070 synchronized (mWindowMap) { 10071 requestTraversalLocked(); 10072 } 10073 } 10074 10075 void requestTraversalLocked() { 10076 if (!mTraversalScheduled) { 10077 mTraversalScheduled = true; 10078 mH.sendEmptyMessage(H.DO_TRAVERSAL); 10079 } 10080 } 10081 10082 /** Note that Locked in this case is on mLayoutToAnim */ 10083 void scheduleAnimationLocked() { 10084 if (!mAnimationScheduled) { 10085 mAnimationScheduled = true; 10086 mChoreographer.postCallback( 10087 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 10088 } 10089 } 10090 10091 private boolean needsLayout() { 10092 final int numDisplays = mDisplayContents.size(); 10093 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10094 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10095 if (displayContent.layoutNeeded) { 10096 return true; 10097 } 10098 } 10099 return false; 10100 } 10101 10102 boolean copyAnimToLayoutParamsLocked() { 10103 boolean doRequest = false; 10104 10105 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 10106 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 10107 mInnerFields.mUpdateRotation = true; 10108 doRequest = true; 10109 } 10110 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 10111 mInnerFields.mWallpaperMayChange = true; 10112 doRequest = true; 10113 } 10114 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 10115 mInnerFields.mWallpaperForceHidingChanged = true; 10116 doRequest = true; 10117 } 10118 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 10119 mInnerFields.mOrientationChangeComplete = false; 10120 } else { 10121 mInnerFields.mOrientationChangeComplete = true; 10122 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 10123 if (mWindowsFreezingScreen) { 10124 doRequest = true; 10125 } 10126 } 10127 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 10128 mTurnOnScreen = true; 10129 } 10130 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 10131 mInnerFields.mWallpaperActionPending = true; 10132 } 10133 10134 return doRequest; 10135 } 10136 10137 /** If a window that has an animation specifying a colored background and the current wallpaper 10138 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 10139 * suddenly disappear. */ 10140 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 10141 WindowList windows = winAnimator.mWin.getWindowList(); 10142 for (int i = windows.size() - 1; i >= 0; --i) { 10143 WindowState testWin = windows.get(i); 10144 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 10145 return testWin.mWinAnimator.mAnimLayer; 10146 } 10147 } 10148 return winAnimator.mAnimLayer; 10149 } 10150 10151 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 10152 boolean secure) { 10153 final SurfaceControl surface = winAnimator.mSurfaceControl; 10154 boolean leakedSurface = false; 10155 boolean killedApps = false; 10156 10157 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 10158 winAnimator.mSession.mPid, operation); 10159 10160 if (mForceRemoves == null) { 10161 mForceRemoves = new ArrayList<WindowState>(); 10162 } 10163 10164 long callingIdentity = Binder.clearCallingIdentity(); 10165 try { 10166 // There was some problem... first, do a sanity check of the 10167 // window list to make sure we haven't left any dangling surfaces 10168 // around. 10169 10170 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 10171 final int numDisplays = mDisplayContents.size(); 10172 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10173 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 10174 final int numWindows = windows.size(); 10175 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 10176 final WindowState ws = windows.get(winNdx); 10177 WindowStateAnimator wsa = ws.mWinAnimator; 10178 if (wsa.mSurfaceControl != null) { 10179 if (!mSessions.contains(wsa.mSession)) { 10180 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 10181 + ws + " surface=" + wsa.mSurfaceControl 10182 + " token=" + ws.mToken 10183 + " pid=" + ws.mSession.mPid 10184 + " uid=" + ws.mSession.mUid); 10185 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 10186 wsa.mSurfaceControl.destroy(); 10187 wsa.mSurfaceShown = false; 10188 wsa.mSurfaceControl = null; 10189 ws.mHasSurface = false; 10190 mForceRemoves.add(ws); 10191 leakedSurface = true; 10192 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 10193 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 10194 + ws + " surface=" + wsa.mSurfaceControl 10195 + " token=" + ws.mAppToken); 10196 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 10197 wsa.mSurfaceControl.destroy(); 10198 wsa.mSurfaceShown = false; 10199 wsa.mSurfaceControl = null; 10200 ws.mHasSurface = false; 10201 leakedSurface = true; 10202 } 10203 } 10204 } 10205 } 10206 10207 if (!leakedSurface) { 10208 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 10209 SparseIntArray pidCandidates = new SparseIntArray(); 10210 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10211 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 10212 final int numWindows = windows.size(); 10213 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 10214 final WindowState ws = windows.get(winNdx); 10215 if (mForceRemoves.contains(ws)) { 10216 continue; 10217 } 10218 WindowStateAnimator wsa = ws.mWinAnimator; 10219 if (wsa.mSurfaceControl != null) { 10220 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 10221 } 10222 } 10223 if (pidCandidates.size() > 0) { 10224 int[] pids = new int[pidCandidates.size()]; 10225 for (int i=0; i<pids.length; i++) { 10226 pids[i] = pidCandidates.keyAt(i); 10227 } 10228 try { 10229 if (mActivityManager.killPids(pids, "Free memory", secure)) { 10230 killedApps = true; 10231 } 10232 } catch (RemoteException e) { 10233 } 10234 } 10235 } 10236 } 10237 10238 if (leakedSurface || killedApps) { 10239 // We managed to reclaim some memory, so get rid of the trouble 10240 // surface and ask the app to request another one. 10241 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 10242 if (surface != null) { 10243 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 10244 "RECOVER DESTROY", null); 10245 surface.destroy(); 10246 winAnimator.mSurfaceShown = false; 10247 winAnimator.mSurfaceControl = null; 10248 winAnimator.mWin.mHasSurface = false; 10249 scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken); 10250 } 10251 10252 try { 10253 winAnimator.mWin.mClient.dispatchGetNewSurface(); 10254 } catch (RemoteException e) { 10255 } 10256 } 10257 } finally { 10258 Binder.restoreCallingIdentity(callingIdentity); 10259 } 10260 10261 return leakedSurface || killedApps; 10262 } 10263 10264 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 10265 WindowState newFocus = computeFocusedWindowLocked(); 10266 if (mCurrentFocus != newFocus) { 10267 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 10268 // This check makes sure that we don't already have the focus 10269 // change message pending. 10270 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 10271 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 10272 // TODO(multidisplay): Focused windows on default display only. 10273 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10274 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 10275 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 10276 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 10277 if (imWindowChanged) { 10278 displayContent.layoutNeeded = true; 10279 newFocus = computeFocusedWindowLocked(); 10280 } 10281 10282 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 10283 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 10284 final WindowState oldFocus = mCurrentFocus; 10285 mCurrentFocus = newFocus; 10286 mLosingFocus.remove(newFocus); 10287 10288 // TODO(multidisplay): Accessibilty supported only of default desiplay. 10289 if (mAccessibilityController != null 10290 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 10291 mAccessibilityController.onWindowFocusChangedLocked(); 10292 } 10293 10294 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 10295 10296 if (imWindowChanged && oldFocus != mInputMethodWindow) { 10297 // Focus of the input method window changed. Perform layout if needed. 10298 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 10299 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 10300 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 10301 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 10302 // Client will do the layout, but we need to assign layers 10303 // for handleNewWindowLocked() below. 10304 assignLayersLocked(displayContent.getWindowList()); 10305 } 10306 } 10307 10308 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 10309 // The change in focus caused us to need to do a layout. Okay. 10310 displayContent.layoutNeeded = true; 10311 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 10312 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 10313 } 10314 } 10315 10316 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 10317 // If we defer assigning layers, then the caller is responsible for 10318 // doing this part. 10319 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 10320 } 10321 10322 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 10323 return true; 10324 } 10325 return false; 10326 } 10327 10328 private WindowState computeFocusedWindowLocked() { 10329 if (mAnimator.mUniverseBackground != null 10330 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 10331 return mAnimator.mUniverseBackground.mWin; 10332 } 10333 10334 final int displayCount = mDisplayContents.size(); 10335 for (int i = 0; i < displayCount; i++) { 10336 final DisplayContent displayContent = mDisplayContents.valueAt(i); 10337 WindowState win = findFocusedWindowLocked(displayContent); 10338 if (win != null) { 10339 return win; 10340 } 10341 } 10342 return null; 10343 } 10344 10345 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 10346 final WindowList windows = displayContent.getWindowList(); 10347 for (int i = windows.size() - 1; i >= 0; i--) { 10348 final WindowState win = windows.get(i); 10349 10350 if (localLOGV || DEBUG_FOCUS) Slog.v( 10351 TAG, "Looking for focus: " + i 10352 + " = " + win 10353 + ", flags=" + win.mAttrs.flags 10354 + ", canReceive=" + win.canReceiveKeys()); 10355 10356 AppWindowToken wtoken = win.mAppToken; 10357 10358 // If this window's application has been removed, just skip it. 10359 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 10360 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 10361 + (wtoken.removed ? "removed" : "sendingToBottom")); 10362 continue; 10363 } 10364 10365 if (!win.canReceiveKeys()) { 10366 continue; 10367 } 10368 10369 // Descend through all of the app tokens and find the first that either matches 10370 // win.mAppToken (return win) or mFocusedApp (return null). 10371 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 10372 mFocusedApp != null) { 10373 ArrayList<Task> tasks = displayContent.getTasks(); 10374 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 10375 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 10376 int tokenNdx = tokens.size() - 1; 10377 for ( ; tokenNdx >= 0; --tokenNdx) { 10378 final AppWindowToken token = tokens.get(tokenNdx); 10379 if (wtoken == token) { 10380 break; 10381 } 10382 if (mFocusedApp == token) { 10383 // Whoops, we are below the focused app... no focus for you! 10384 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 10385 "findFocusedWindow: Reached focused app=" + mFocusedApp); 10386 return null; 10387 } 10388 } 10389 if (tokenNdx >= 0) { 10390 // Early exit from loop, must have found the matching token. 10391 break; 10392 } 10393 } 10394 } 10395 10396 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 10397 " = " + win); 10398 return win; 10399 } 10400 10401 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 10402 return null; 10403 } 10404 10405 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 10406 if (mDisplayFrozen) { 10407 return; 10408 } 10409 10410 if (!mDisplayReady || !mPolicy.isScreenOn()) { 10411 // No need to freeze the screen before the system is ready or if 10412 // the screen is off. 10413 return; 10414 } 10415 10416 mScreenFrozenLock.acquire(); 10417 10418 mDisplayFrozen = true; 10419 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 10420 mLastFinishedFreezeSource = null; 10421 10422 mInputMonitor.freezeInputDispatchingLw(); 10423 10424 // Clear the last input window -- that is just used for 10425 // clean transitions between IMEs, and if we are freezing 10426 // the screen then the whole world is changing behind the scenes. 10427 mPolicy.setLastInputMethodWindowLw(null, null); 10428 10429 if (mAppTransition.isTransitionSet()) { 10430 mAppTransition.freeze(); 10431 } 10432 10433 if (PROFILE_ORIENTATION) { 10434 File file = new File("/data/system/frozen"); 10435 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10436 } 10437 10438 if (CUSTOM_SCREEN_ROTATION) { 10439 mExitAnimId = exitAnim; 10440 mEnterAnimId = enterAnim; 10441 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10442 final int displayId = displayContent.getDisplayId(); 10443 ScreenRotationAnimation screenRotationAnimation = 10444 mAnimator.getScreenRotationAnimationLocked(displayId); 10445 if (screenRotationAnimation != null) { 10446 screenRotationAnimation.kill(); 10447 } 10448 10449 // Check whether the current screen contains any secure content. 10450 boolean isSecure = false; 10451 final WindowList windows = getDefaultWindowListLocked(); 10452 final int N = windows.size(); 10453 for (int i = 0; i < N; i++) { 10454 WindowState ws = windows.get(i); 10455 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10456 isSecure = true; 10457 break; 10458 } 10459 } 10460 10461 // TODO(multidisplay): rotation on main screen only. 10462 displayContent.updateDisplayInfo(); 10463 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10464 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10465 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10466 } 10467 } 10468 10469 private void stopFreezingDisplayLocked() { 10470 if (!mDisplayFrozen) { 10471 return; 10472 } 10473 10474 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10475 || mClientFreezingScreen) { 10476 if (DEBUG_ORIENTATION) Slog.d(TAG, 10477 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10478 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10479 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10480 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10481 return; 10482 } 10483 10484 mDisplayFrozen = false; 10485 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10486 StringBuilder sb = new StringBuilder(128); 10487 sb.append("Screen frozen for "); 10488 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10489 if (mLastFinishedFreezeSource != null) { 10490 sb.append(" due to "); 10491 sb.append(mLastFinishedFreezeSource); 10492 } 10493 Slog.i(TAG, sb.toString()); 10494 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10495 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10496 if (PROFILE_ORIENTATION) { 10497 Debug.stopMethodTracing(); 10498 } 10499 10500 boolean updateRotation = false; 10501 10502 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10503 final int displayId = displayContent.getDisplayId(); 10504 ScreenRotationAnimation screenRotationAnimation = 10505 mAnimator.getScreenRotationAnimationLocked(displayId); 10506 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10507 && screenRotationAnimation.hasScreenshot()) { 10508 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10509 // TODO(multidisplay): rotation on main screen only. 10510 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10511 // Get rotation animation again, with new top window 10512 boolean isDimming = displayContent.isDimming(); 10513 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10514 mExitAnimId = mEnterAnimId = 0; 10515 } 10516 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10517 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 10518 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10519 scheduleAnimationLocked(); 10520 } else { 10521 screenRotationAnimation.kill(); 10522 screenRotationAnimation = null; 10523 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10524 updateRotation = true; 10525 } 10526 } else { 10527 if (screenRotationAnimation != null) { 10528 screenRotationAnimation.kill(); 10529 screenRotationAnimation = null; 10530 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10531 } 10532 updateRotation = true; 10533 } 10534 10535 mInputMonitor.thawInputDispatchingLw(); 10536 10537 boolean configChanged; 10538 10539 // While the display is frozen we don't re-compute the orientation 10540 // to avoid inconsistent states. However, something interesting 10541 // could have actually changed during that time so re-evaluate it 10542 // now to catch that. 10543 configChanged = updateOrientationFromAppTokensLocked(false); 10544 10545 // A little kludge: a lot could have happened while the 10546 // display was frozen, so now that we are coming back we 10547 // do a gc so that any remote references the system 10548 // processes holds on others can be released if they are 10549 // no longer needed. 10550 mH.removeMessages(H.FORCE_GC); 10551 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10552 10553 mScreenFrozenLock.release(); 10554 10555 if (updateRotation) { 10556 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10557 configChanged |= updateRotationUncheckedLocked(false); 10558 } 10559 10560 if (configChanged) { 10561 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10562 } 10563 } 10564 10565 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10566 DisplayMetrics dm) { 10567 if (index < tokens.length) { 10568 String str = tokens[index]; 10569 if (str != null && str.length() > 0) { 10570 try { 10571 int val = Integer.parseInt(str); 10572 return val; 10573 } catch (Exception e) { 10574 } 10575 } 10576 } 10577 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10578 return defDps; 10579 } 10580 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10581 return val; 10582 } 10583 10584 void createWatermarkInTransaction() { 10585 if (mWatermark != null) { 10586 return; 10587 } 10588 10589 File file = new File("/system/etc/setup.conf"); 10590 FileInputStream in = null; 10591 DataInputStream ind = null; 10592 try { 10593 in = new FileInputStream(file); 10594 ind = new DataInputStream(in); 10595 String line = ind.readLine(); 10596 if (line != null) { 10597 String[] toks = line.split("%"); 10598 if (toks != null && toks.length > 0) { 10599 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10600 mRealDisplayMetrics, mFxSession, toks); 10601 } 10602 } 10603 } catch (FileNotFoundException e) { 10604 } catch (IOException e) { 10605 } finally { 10606 if (ind != null) { 10607 try { 10608 ind.close(); 10609 } catch (IOException e) { 10610 } 10611 } else if (in != null) { 10612 try { 10613 in.close(); 10614 } catch (IOException e) { 10615 } 10616 } 10617 } 10618 } 10619 10620 @Override 10621 public void statusBarVisibilityChanged(int visibility) { 10622 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10623 != PackageManager.PERMISSION_GRANTED) { 10624 throw new SecurityException("Caller does not hold permission " 10625 + android.Manifest.permission.STATUS_BAR); 10626 } 10627 10628 synchronized (mWindowMap) { 10629 mLastStatusBarVisibility = visibility; 10630 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10631 updateStatusBarVisibilityLocked(visibility); 10632 } 10633 } 10634 10635 // TOOD(multidisplay): StatusBar on multiple screens? 10636 void updateStatusBarVisibilityLocked(int visibility) { 10637 mInputManager.setSystemUiVisibility(visibility); 10638 final WindowList windows = getDefaultWindowListLocked(); 10639 final int N = windows.size(); 10640 for (int i = 0; i < N; i++) { 10641 WindowState ws = windows.get(i); 10642 try { 10643 int curValue = ws.mSystemUiVisibility; 10644 int diff = curValue ^ visibility; 10645 // We are only interested in differences of one of the 10646 // clearable flags... 10647 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10648 // ...if it has actually been cleared. 10649 diff &= ~visibility; 10650 int newValue = (curValue&~diff) | (visibility&diff); 10651 if (newValue != curValue) { 10652 ws.mSeq++; 10653 ws.mSystemUiVisibility = newValue; 10654 } 10655 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10656 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10657 visibility, newValue, diff); 10658 } 10659 } catch (RemoteException e) { 10660 // so sorry 10661 } 10662 } 10663 } 10664 10665 @Override 10666 public void reevaluateStatusBarVisibility() { 10667 synchronized (mWindowMap) { 10668 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10669 updateStatusBarVisibilityLocked(visibility); 10670 performLayoutAndPlaceSurfacesLocked(); 10671 } 10672 } 10673 10674 @Override 10675 public FakeWindow addFakeWindow(Looper looper, 10676 InputEventReceiver.Factory inputEventReceiverFactory, 10677 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10678 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10679 synchronized (mWindowMap) { 10680 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10681 name, windowType, 10682 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10683 hasFocus, touchFullscreen); 10684 int i=0; 10685 while (i<mFakeWindows.size()) { 10686 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10687 break; 10688 } 10689 } 10690 mFakeWindows.add(i, fw); 10691 mInputMonitor.updateInputWindowsLw(true); 10692 return fw; 10693 } 10694 } 10695 10696 boolean removeFakeWindowLocked(FakeWindow window) { 10697 synchronized (mWindowMap) { 10698 if (mFakeWindows.remove(window)) { 10699 mInputMonitor.updateInputWindowsLw(true); 10700 return true; 10701 } 10702 return false; 10703 } 10704 } 10705 10706 // It is assumed that this method is called only by InputMethodManagerService. 10707 public void saveLastInputMethodWindowForTransition() { 10708 synchronized (mWindowMap) { 10709 // TODO(multidisplay): Pass in the displayID. 10710 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10711 if (mInputMethodWindow != null) { 10712 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10713 } 10714 } 10715 } 10716 10717 public int getInputMethodWindowVisibleHeight() { 10718 synchronized (mWindowMap) { 10719 return mPolicy.getInputMethodWindowVisibleHeightLw(); 10720 } 10721 } 10722 10723 @Override 10724 public boolean hasNavigationBar() { 10725 return mPolicy.hasNavigationBar(); 10726 } 10727 10728 @Override 10729 public void lockNow(Bundle options) { 10730 mPolicy.lockNow(options); 10731 } 10732 10733 public void showRecentApps() { 10734 mPolicy.showRecentApps(); 10735 } 10736 10737 @Override 10738 public boolean isSafeModeEnabled() { 10739 return mSafeMode; 10740 } 10741 10742 @Override 10743 public boolean clearWindowContentFrameStats(IBinder token) { 10744 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10745 "clearWindowContentFrameStats()")) { 10746 throw new SecurityException("Requires FRAME_STATS permission"); 10747 } 10748 synchronized (mWindowMap) { 10749 WindowState windowState = mWindowMap.get(token); 10750 if (windowState == null) { 10751 return false; 10752 } 10753 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10754 if (surfaceControl == null) { 10755 return false; 10756 } 10757 return surfaceControl.clearContentFrameStats(); 10758 } 10759 } 10760 10761 @Override 10762 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 10763 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 10764 "getWindowContentFrameStats()")) { 10765 throw new SecurityException("Requires FRAME_STATS permission"); 10766 } 10767 synchronized (mWindowMap) { 10768 WindowState windowState = mWindowMap.get(token); 10769 if (windowState == null) { 10770 return null; 10771 } 10772 SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl; 10773 if (surfaceControl == null) { 10774 return null; 10775 } 10776 if (mTempWindowRenderStats == null) { 10777 mTempWindowRenderStats = new WindowContentFrameStats(); 10778 } 10779 WindowContentFrameStats stats = mTempWindowRenderStats; 10780 if (!surfaceControl.getContentFrameStats(stats)) { 10781 return null; 10782 } 10783 return stats; 10784 } 10785 } 10786 10787 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10788 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10789 mPolicy.dump(" ", pw, args); 10790 } 10791 10792 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10793 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10794 mAnimator.dumpLocked(pw, " ", dumpAll); 10795 } 10796 10797 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10798 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10799 if (mTokenMap.size() > 0) { 10800 pw.println(" All tokens:"); 10801 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10802 while (it.hasNext()) { 10803 WindowToken token = it.next(); 10804 pw.print(" "); pw.print(token); 10805 if (dumpAll) { 10806 pw.println(':'); 10807 token.dump(pw, " "); 10808 } else { 10809 pw.println(); 10810 } 10811 } 10812 } 10813 if (mWallpaperTokens.size() > 0) { 10814 pw.println(); 10815 pw.println(" Wallpaper tokens:"); 10816 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10817 WindowToken token = mWallpaperTokens.get(i); 10818 pw.print(" Wallpaper #"); pw.print(i); 10819 pw.print(' '); pw.print(token); 10820 if (dumpAll) { 10821 pw.println(':'); 10822 token.dump(pw, " "); 10823 } else { 10824 pw.println(); 10825 } 10826 } 10827 } 10828 if (mFinishedStarting.size() > 0) { 10829 pw.println(); 10830 pw.println(" Finishing start of application tokens:"); 10831 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10832 WindowToken token = mFinishedStarting.get(i); 10833 pw.print(" Finished Starting #"); pw.print(i); 10834 pw.print(' '); pw.print(token); 10835 if (dumpAll) { 10836 pw.println(':'); 10837 token.dump(pw, " "); 10838 } else { 10839 pw.println(); 10840 } 10841 } 10842 } 10843 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10844 pw.println(); 10845 if (mOpeningApps.size() > 0) { 10846 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10847 } 10848 if (mClosingApps.size() > 0) { 10849 pw.print(" mClosingApps="); pw.println(mClosingApps); 10850 } 10851 } 10852 } 10853 10854 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10855 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10856 for (int i=0; i<mSessions.size(); i++) { 10857 Session s = mSessions.valueAt(i); 10858 pw.print(" Session "); pw.print(s); pw.println(':'); 10859 s.dump(pw, " "); 10860 } 10861 } 10862 10863 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10864 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10865 if (mDisplayReady) { 10866 final int numDisplays = mDisplayContents.size(); 10867 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10868 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10869 displayContent.dump(" ", pw); 10870 } 10871 } else { 10872 pw.println(" NO DISPLAY"); 10873 } 10874 } 10875 10876 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10877 ArrayList<WindowState> windows) { 10878 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10879 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10880 } 10881 10882 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10883 ArrayList<WindowState> windows) { 10884 final int numDisplays = mDisplayContents.size(); 10885 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10886 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10887 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10888 final WindowState w = windowList.get(winNdx); 10889 if (windows == null || windows.contains(w)) { 10890 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10891 pw.print(w); pw.println(":"); 10892 w.dump(pw, " ", dumpAll || windows != null); 10893 } 10894 } 10895 } 10896 if (mInputMethodDialogs.size() > 0) { 10897 pw.println(); 10898 pw.println(" Input method dialogs:"); 10899 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10900 WindowState w = mInputMethodDialogs.get(i); 10901 if (windows == null || windows.contains(w)) { 10902 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10903 } 10904 } 10905 } 10906 if (mPendingRemove.size() > 0) { 10907 pw.println(); 10908 pw.println(" Remove pending for:"); 10909 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10910 WindowState w = mPendingRemove.get(i); 10911 if (windows == null || windows.contains(w)) { 10912 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10913 pw.print(w); 10914 if (dumpAll) { 10915 pw.println(":"); 10916 w.dump(pw, " ", true); 10917 } else { 10918 pw.println(); 10919 } 10920 } 10921 } 10922 } 10923 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10924 pw.println(); 10925 pw.println(" Windows force removing:"); 10926 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10927 WindowState w = mForceRemoves.get(i); 10928 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10929 pw.print(w); 10930 if (dumpAll) { 10931 pw.println(":"); 10932 w.dump(pw, " ", true); 10933 } else { 10934 pw.println(); 10935 } 10936 } 10937 } 10938 if (mDestroySurface.size() > 0) { 10939 pw.println(); 10940 pw.println(" Windows waiting to destroy their surface:"); 10941 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10942 WindowState w = mDestroySurface.get(i); 10943 if (windows == null || windows.contains(w)) { 10944 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10945 pw.print(w); 10946 if (dumpAll) { 10947 pw.println(":"); 10948 w.dump(pw, " ", true); 10949 } else { 10950 pw.println(); 10951 } 10952 } 10953 } 10954 } 10955 if (mLosingFocus.size() > 0) { 10956 pw.println(); 10957 pw.println(" Windows losing focus:"); 10958 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10959 WindowState w = mLosingFocus.get(i); 10960 if (windows == null || windows.contains(w)) { 10961 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10962 pw.print(w); 10963 if (dumpAll) { 10964 pw.println(":"); 10965 w.dump(pw, " ", true); 10966 } else { 10967 pw.println(); 10968 } 10969 } 10970 } 10971 } 10972 if (mResizingWindows.size() > 0) { 10973 pw.println(); 10974 pw.println(" Windows waiting to resize:"); 10975 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10976 WindowState w = mResizingWindows.get(i); 10977 if (windows == null || windows.contains(w)) { 10978 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10979 pw.print(w); 10980 if (dumpAll) { 10981 pw.println(":"); 10982 w.dump(pw, " ", true); 10983 } else { 10984 pw.println(); 10985 } 10986 } 10987 } 10988 } 10989 if (mWaitingForDrawn.size() > 0) { 10990 pw.println(); 10991 pw.println(" Clients waiting for these windows to be drawn:"); 10992 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10993 WindowState win = mWaitingForDrawn.get(i); 10994 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10995 } 10996 } 10997 pw.println(); 10998 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10999 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad); 11000 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 11001 if (mLastFocus != mCurrentFocus) { 11002 pw.print(" mLastFocus="); pw.println(mLastFocus); 11003 } 11004 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 11005 if (mInputMethodTarget != null) { 11006 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 11007 } 11008 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 11009 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 11010 pw.print(" mLastDisplayFreezeDuration="); 11011 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 11012 if ( mLastFinishedFreezeSource != null) { 11013 pw.print(" due to "); 11014 pw.print(mLastFinishedFreezeSource); 11015 } 11016 pw.println(); 11017 if (dumpAll) { 11018 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 11019 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 11020 if (mLastStatusBarVisibility != 0) { 11021 pw.print(" mLastStatusBarVisibility=0x"); 11022 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 11023 } 11024 if (mInputMethodWindow != null) { 11025 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 11026 } 11027 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 11028 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 11029 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 11030 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 11031 } 11032 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 11033 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 11034 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE 11035 || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 11036 pw.print(" mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX); 11037 pw.print(" mLastWallpaperDisplayOffsetY="); 11038 pw.println(mLastWallpaperDisplayOffsetY); 11039 } 11040 if (mInputMethodAnimLayerAdjustment != 0 || 11041 mWallpaperAnimLayerAdjustment != 0) { 11042 pw.print(" mInputMethodAnimLayerAdjustment="); 11043 pw.print(mInputMethodAnimLayerAdjustment); 11044 pw.print(" mWallpaperAnimLayerAdjustment="); 11045 pw.println(mWallpaperAnimLayerAdjustment); 11046 } 11047 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 11048 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 11049 if (needsLayout()) { 11050 pw.print(" layoutNeeded on displays="); 11051 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11052 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 11053 if (displayContent.layoutNeeded) { 11054 pw.print(displayContent.getDisplayId()); 11055 } 11056 } 11057 pw.println(); 11058 } 11059 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 11060 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 11061 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 11062 pw.print(" client="); pw.print(mClientFreezingScreen); 11063 pw.print(" apps="); pw.print(mAppsFreezingScreen); 11064 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 11065 pw.print(" mRotation="); pw.print(mRotation); 11066 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 11067 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 11068 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 11069 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 11070 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 11071 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 11072 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 11073 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 11074 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 11075 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 11076 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 11077 pw.println(" mLayoutToAnim:"); 11078 mAppTransition.dump(pw); 11079 } 11080 } 11081 11082 boolean dumpWindows(PrintWriter pw, String name, String[] args, 11083 int opti, boolean dumpAll) { 11084 WindowList windows = new WindowList(); 11085 if ("visible".equals(name)) { 11086 synchronized(mWindowMap) { 11087 final int numDisplays = mDisplayContents.size(); 11088 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11089 final WindowList windowList = 11090 mDisplayContents.valueAt(displayNdx).getWindowList(); 11091 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 11092 final WindowState w = windowList.get(winNdx); 11093 if (w.mWinAnimator.mSurfaceShown) { 11094 windows.add(w); 11095 } 11096 } 11097 } 11098 } 11099 } else { 11100 int objectId = 0; 11101 // See if this is an object ID. 11102 try { 11103 objectId = Integer.parseInt(name, 16); 11104 name = null; 11105 } catch (RuntimeException e) { 11106 } 11107 synchronized(mWindowMap) { 11108 final int numDisplays = mDisplayContents.size(); 11109 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 11110 final WindowList windowList = 11111 mDisplayContents.valueAt(displayNdx).getWindowList(); 11112 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 11113 final WindowState w = windowList.get(winNdx); 11114 if (name != null) { 11115 if (w.mAttrs.getTitle().toString().contains(name)) { 11116 windows.add(w); 11117 } 11118 } else if (System.identityHashCode(w) == objectId) { 11119 windows.add(w); 11120 } 11121 } 11122 } 11123 } 11124 } 11125 11126 if (windows.size() <= 0) { 11127 return false; 11128 } 11129 11130 synchronized(mWindowMap) { 11131 dumpWindowsLocked(pw, dumpAll, windows); 11132 } 11133 return true; 11134 } 11135 11136 void dumpLastANRLocked(PrintWriter pw) { 11137 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 11138 if (mLastANRState == null) { 11139 pw.println(" <no ANR has occurred since boot>"); 11140 } else { 11141 pw.println(mLastANRState); 11142 } 11143 } 11144 11145 /** 11146 * Saves information about the state of the window manager at 11147 * the time an ANR occurred before anything else in the system changes 11148 * in response. 11149 * 11150 * @param appWindowToken The application that ANR'd, may be null. 11151 * @param windowState The window that ANR'd, may be null. 11152 * @param reason The reason for the ANR, may be null. 11153 */ 11154 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 11155 String reason) { 11156 StringWriter sw = new StringWriter(); 11157 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 11158 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 11159 if (appWindowToken != null) { 11160 pw.println(" Application at fault: " + appWindowToken.stringName); 11161 } 11162 if (windowState != null) { 11163 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 11164 } 11165 if (reason != null) { 11166 pw.println(" Reason: " + reason); 11167 } 11168 pw.println(); 11169 dumpWindowsNoHeaderLocked(pw, true, null); 11170 pw.close(); 11171 mLastANRState = sw.toString(); 11172 } 11173 11174 @Override 11175 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 11176 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 11177 != PackageManager.PERMISSION_GRANTED) { 11178 pw.println("Permission Denial: can't dump WindowManager from from pid=" 11179 + Binder.getCallingPid() 11180 + ", uid=" + Binder.getCallingUid()); 11181 return; 11182 } 11183 11184 boolean dumpAll = false; 11185 11186 int opti = 0; 11187 while (opti < args.length) { 11188 String opt = args[opti]; 11189 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 11190 break; 11191 } 11192 opti++; 11193 if ("-a".equals(opt)) { 11194 dumpAll = true; 11195 } else if ("-h".equals(opt)) { 11196 pw.println("Window manager dump options:"); 11197 pw.println(" [-a] [-h] [cmd] ..."); 11198 pw.println(" cmd may be one of:"); 11199 pw.println(" l[astanr]: last ANR information"); 11200 pw.println(" p[policy]: policy state"); 11201 pw.println(" a[animator]: animator state"); 11202 pw.println(" s[essions]: active sessions"); 11203 pw.println(" surfaces: active surfaces (debugging enabled only)"); 11204 pw.println(" d[isplays]: active display contents"); 11205 pw.println(" t[okens]: token list"); 11206 pw.println(" w[indows]: window list"); 11207 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 11208 pw.println(" be a partial substring in a window name, a"); 11209 pw.println(" Window hex object identifier, or"); 11210 pw.println(" \"all\" for all windows, or"); 11211 pw.println(" \"visible\" for the visible windows."); 11212 pw.println(" -a: include all available server state."); 11213 return; 11214 } else { 11215 pw.println("Unknown argument: " + opt + "; use -h for help"); 11216 } 11217 } 11218 11219 // Is the caller requesting to dump a particular piece of data? 11220 if (opti < args.length) { 11221 String cmd = args[opti]; 11222 opti++; 11223 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 11224 synchronized(mWindowMap) { 11225 dumpLastANRLocked(pw); 11226 } 11227 return; 11228 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 11229 synchronized(mWindowMap) { 11230 dumpPolicyLocked(pw, args, true); 11231 } 11232 return; 11233 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 11234 synchronized(mWindowMap) { 11235 dumpAnimatorLocked(pw, args, true); 11236 } 11237 return; 11238 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 11239 synchronized(mWindowMap) { 11240 dumpSessionsLocked(pw, true); 11241 } 11242 return; 11243 } else if ("surfaces".equals(cmd)) { 11244 synchronized(mWindowMap) { 11245 WindowStateAnimator.SurfaceTrace.dumpAllSurfaces(pw, null); 11246 } 11247 return; 11248 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 11249 synchronized(mWindowMap) { 11250 dumpDisplayContentsLocked(pw, true); 11251 } 11252 return; 11253 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 11254 synchronized(mWindowMap) { 11255 dumpTokensLocked(pw, true); 11256 } 11257 return; 11258 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 11259 synchronized(mWindowMap) { 11260 dumpWindowsLocked(pw, true, null); 11261 } 11262 return; 11263 } else if ("all".equals(cmd) || "a".equals(cmd)) { 11264 synchronized(mWindowMap) { 11265 dumpWindowsLocked(pw, true, null); 11266 } 11267 return; 11268 } else { 11269 // Dumping a single name? 11270 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 11271 pw.println("Bad window command, or no windows match: " + cmd); 11272 pw.println("Use -h for help."); 11273 } 11274 return; 11275 } 11276 } 11277 11278 synchronized(mWindowMap) { 11279 pw.println(); 11280 if (dumpAll) { 11281 pw.println("-------------------------------------------------------------------------------"); 11282 } 11283 dumpLastANRLocked(pw); 11284 pw.println(); 11285 if (dumpAll) { 11286 pw.println("-------------------------------------------------------------------------------"); 11287 } 11288 dumpPolicyLocked(pw, args, dumpAll); 11289 pw.println(); 11290 if (dumpAll) { 11291 pw.println("-------------------------------------------------------------------------------"); 11292 } 11293 dumpAnimatorLocked(pw, args, dumpAll); 11294 pw.println(); 11295 if (dumpAll) { 11296 pw.println("-------------------------------------------------------------------------------"); 11297 } 11298 dumpSessionsLocked(pw, dumpAll); 11299 pw.println(); 11300 if (dumpAll) { 11301 pw.println("-------------------------------------------------------------------------------"); 11302 } 11303 WindowStateAnimator.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ? 11304 "-------------------------------------------------------------------------------" 11305 : null); 11306 pw.println(); 11307 if (dumpAll) { 11308 pw.println("-------------------------------------------------------------------------------"); 11309 } 11310 dumpDisplayContentsLocked(pw, dumpAll); 11311 pw.println(); 11312 if (dumpAll) { 11313 pw.println("-------------------------------------------------------------------------------"); 11314 } 11315 dumpTokensLocked(pw, dumpAll); 11316 pw.println(); 11317 if (dumpAll) { 11318 pw.println("-------------------------------------------------------------------------------"); 11319 } 11320 dumpWindowsLocked(pw, dumpAll, null); 11321 } 11322 } 11323 11324 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 11325 @Override 11326 public void monitor() { 11327 synchronized (mWindowMap) { } 11328 } 11329 11330 public interface OnHardKeyboardStatusChangeListener { 11331 public void onHardKeyboardStatusChange(boolean available); 11332 } 11333 11334 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 11335 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 11336 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 11337 Integer.toHexString(pendingLayoutChanges)); 11338 } 11339 } 11340 11341 private DisplayContent newDisplayContentLocked(final Display display) { 11342 DisplayContent displayContent = new DisplayContent(display, this); 11343 final int displayId = display.getDisplayId(); 11344 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 11345 mDisplayContents.put(displayId, displayContent); 11346 11347 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 11348 final Rect rect = new Rect(); 11349 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 11350 synchronized (displayContent.mDisplaySizeLock) { 11351 displayInfo.overscanLeft = rect.left; 11352 displayInfo.overscanTop = rect.top; 11353 displayInfo.overscanRight = rect.right; 11354 displayInfo.overscanBottom = rect.bottom; 11355 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 11356 displayId, displayInfo); 11357 } 11358 configureDisplayPolicyLocked(displayContent); 11359 11360 // TODO: Create an input channel for each display with touch capability. 11361 if (displayId == Display.DEFAULT_DISPLAY) { 11362 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 11363 registerPointerEventListener(displayContent.mTapDetector); 11364 } 11365 11366 return displayContent; 11367 } 11368 11369 public void createDisplayContentLocked(final Display display) { 11370 if (display == null) { 11371 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 11372 } 11373 getDisplayContentLocked(display.getDisplayId()); 11374 } 11375 11376 /** 11377 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 11378 * there is a Display for the displayId. 11379 * @param displayId The display the caller is interested in. 11380 * @return The DisplayContent associated with displayId or null if there is no Display for it. 11381 */ 11382 public DisplayContent getDisplayContentLocked(final int displayId) { 11383 DisplayContent displayContent = mDisplayContents.get(displayId); 11384 if (displayContent == null) { 11385 final Display display = mDisplayManager.getDisplay(displayId); 11386 if (display != null) { 11387 displayContent = newDisplayContentLocked(display); 11388 } 11389 } 11390 return displayContent; 11391 } 11392 11393 // There is an inherent assumption that this will never return null. 11394 public DisplayContent getDefaultDisplayContentLocked() { 11395 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 11396 } 11397 11398 public WindowList getDefaultWindowListLocked() { 11399 return getDefaultDisplayContentLocked().getWindowList(); 11400 } 11401 11402 public DisplayInfo getDefaultDisplayInfoLocked() { 11403 return getDefaultDisplayContentLocked().getDisplayInfo(); 11404 } 11405 11406 /** 11407 * Return the list of WindowStates associated on the passed display. 11408 * @param display The screen to return windows from. 11409 * @return The list of WindowStates on the screen, or null if the there is no screen. 11410 */ 11411 public WindowList getWindowListLocked(final Display display) { 11412 return getWindowListLocked(display.getDisplayId()); 11413 } 11414 11415 /** 11416 * Return the list of WindowStates associated on the passed display. 11417 * @param displayId The screen to return windows from. 11418 * @return The list of WindowStates on the screen, or null if the there is no screen. 11419 */ 11420 public WindowList getWindowListLocked(final int displayId) { 11421 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11422 return displayContent != null ? displayContent.getWindowList() : null; 11423 } 11424 11425 public void onDisplayAdded(int displayId) { 11426 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 11427 } 11428 11429 public void handleDisplayAdded(int displayId) { 11430 synchronized (mWindowMap) { 11431 final Display display = mDisplayManager.getDisplay(displayId); 11432 if (display != null) { 11433 createDisplayContentLocked(display); 11434 displayReady(displayId); 11435 } 11436 requestTraversalLocked(); 11437 } 11438 } 11439 11440 public void onDisplayRemoved(int displayId) { 11441 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 11442 } 11443 11444 private void handleDisplayRemovedLocked(int displayId) { 11445 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11446 if (displayContent != null) { 11447 if (displayContent.isAnimating()) { 11448 displayContent.mDeferredRemoval = true; 11449 return; 11450 } 11451 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 11452 mDisplayContents.delete(displayId); 11453 displayContent.close(); 11454 if (displayId == Display.DEFAULT_DISPLAY) { 11455 unregisterPointerEventListener(displayContent.mTapDetector); 11456 } 11457 } 11458 mAnimator.removeDisplayLocked(displayId); 11459 requestTraversalLocked(); 11460 } 11461 11462 public void onDisplayChanged(int displayId) { 11463 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 11464 } 11465 11466 private void handleDisplayChangedLocked(int displayId) { 11467 final DisplayContent displayContent = getDisplayContentLocked(displayId); 11468 if (displayContent != null) { 11469 displayContent.updateDisplayInfo(); 11470 } 11471 requestTraversalLocked(); 11472 } 11473 11474 @Override 11475 public Object getWindowManagerLock() { 11476 return mWindowMap; 11477 } 11478 11479 private final class LocalService extends WindowManagerInternal { 11480 @Override 11481 public void requestTraversalFromDisplayManager() { 11482 requestTraversal(); 11483 } 11484 11485 @Override 11486 public void setMagnificationSpec(MagnificationSpec spec) { 11487 synchronized (mWindowMap) { 11488 if (mAccessibilityController != null) { 11489 mAccessibilityController.setMagnificationSpecLocked(spec); 11490 } else { 11491 throw new IllegalStateException("Magnification callbacks not set!"); 11492 } 11493 } 11494 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11495 spec.recycle(); 11496 } 11497 } 11498 11499 @Override 11500 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11501 synchronized (mWindowMap) { 11502 WindowState windowState = mWindowMap.get(windowToken); 11503 if (windowState == null) { 11504 return null; 11505 } 11506 MagnificationSpec spec = null; 11507 if (mAccessibilityController != null) { 11508 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11509 } 11510 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11511 return null; 11512 } 11513 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11514 spec.scale *= windowState.mGlobalScale; 11515 return spec; 11516 } 11517 } 11518 11519 @Override 11520 public void setMagnificationCallbacks(MagnificationCallbacks callbacks) { 11521 synchronized (mWindowMap) { 11522 if (mAccessibilityController == null) { 11523 mAccessibilityController = new AccessibilityController( 11524 WindowManagerService.this); 11525 } 11526 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11527 if (!mAccessibilityController.hasCallbacksLocked()) { 11528 mAccessibilityController = null; 11529 } 11530 } 11531 } 11532 11533 @Override 11534 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11535 synchronized (mWindowMap) { 11536 if (mAccessibilityController == null) { 11537 mAccessibilityController = new AccessibilityController( 11538 WindowManagerService.this); 11539 } 11540 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11541 if (!mAccessibilityController.hasCallbacksLocked()) { 11542 mAccessibilityController = null; 11543 } 11544 } 11545 } 11546 11547 @Override 11548 public void setInputFilter(IInputFilter filter) { 11549 mInputManager.setInputFilter(filter); 11550 } 11551 11552 @Override 11553 public IBinder getFocusedWindowToken() { 11554 synchronized (mWindowMap) { 11555 WindowState windowState = getFocusedWindowLocked(); 11556 if (windowState != null) { 11557 return windowState.mClient.asBinder(); 11558 } 11559 return null; 11560 } 11561 } 11562 11563 @Override 11564 public boolean isKeyguardLocked() { 11565 return WindowManagerService.this.isKeyguardLocked(); 11566 } 11567 11568 @Override 11569 public void showGlobalActions() { 11570 WindowManagerService.this.showGlobalActions(); 11571 } 11572 11573 @Override 11574 public void getWindowFrame(IBinder token, Rect outBounds) { 11575 synchronized (mWindowMap) { 11576 WindowState windowState = mWindowMap.get(token); 11577 if (windowState != null) { 11578 outBounds.set(windowState.mFrame); 11579 } else { 11580 outBounds.setEmpty(); 11581 } 11582 } 11583 } 11584 11585 @Override 11586 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 11587 synchronized (mWindowMap) { 11588 mWaitingForDrawnCallback = callback; 11589 final WindowList windows = getDefaultWindowListLocked(); 11590 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11591 final WindowState win = windows.get(winNdx); 11592 if (win.isVisibleLw() 11593 && (win.mAppToken != null || mPolicy.isForceHiding(win.mAttrs))) { 11594 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 11595 // Force add to mResizingWindows. 11596 win.mLastContentInsets.set(-1, -1, -1, -1); 11597 mWaitingForDrawn.add(win); 11598 } 11599 } 11600 requestTraversalLocked(); 11601 } 11602 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11603 if (mWaitingForDrawn.isEmpty()) { 11604 callback.run(); 11605 } else { 11606 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11607 checkDrawnWindowsLocked(); 11608 } 11609 } 11610 } 11611} 11612