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