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