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