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