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