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