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