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