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