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