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