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