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