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