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