WindowManagerService.java revision 4661e816e7997cab865f1b456b2dab924bcdbcda
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 (transferStartingWindow(transferFrom, wtoken)) { 3944 return; 3945 } 3946 3947 // There is no existing starting window, and the caller doesn't 3948 // want us to create one, so that's it! 3949 if (!createIfNeeded) { 3950 return; 3951 } 3952 3953 // If this is a translucent window, then don't 3954 // show a starting window -- the current effect (a full-screen 3955 // opaque starting window that fades away to the real contents 3956 // when it is ready) does not work for this. 3957 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Checking theme of starting window: 0x" 3958 + Integer.toHexString(theme)); 3959 if (theme != 0) { 3960 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 3961 com.android.internal.R.styleable.Window, mCurrentUserId); 3962 if (ent == null) { 3963 // Whoops! App doesn't exist. Um. Okay. We'll just 3964 // pretend like we didn't see that. 3965 return; 3966 } 3967 final boolean windowIsTranslucent = ent.array.getBoolean( 3968 com.android.internal.R.styleable.Window_windowIsTranslucent, false); 3969 final boolean windowIsFloating = ent.array.getBoolean( 3970 com.android.internal.R.styleable.Window_windowIsFloating, false); 3971 final boolean windowShowWallpaper = ent.array.getBoolean( 3972 com.android.internal.R.styleable.Window_windowShowWallpaper, false); 3973 final boolean windowDisableStarting = ent.array.getBoolean( 3974 com.android.internal.R.styleable.Window_windowDisablePreview, false); 3975 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Translucent=" + windowIsTranslucent 3976 + " Floating=" + windowIsFloating 3977 + " ShowWallpaper=" + windowShowWallpaper); 3978 if (windowIsTranslucent) { 3979 return; 3980 } 3981 if (windowIsFloating || windowDisableStarting) { 3982 return; 3983 } 3984 if (windowShowWallpaper) { 3985 if (mWallpaperControllerLocked.getWallpaperTarget() == null) { 3986 // If this theme is requesting a wallpaper, and the wallpaper 3987 // is not curently visible, then this effectively serves as 3988 // an opaque window and our starting window transition animation 3989 // can still work. We just need to make sure the starting window 3990 // is also showing the wallpaper. 3991 windowFlags |= FLAG_SHOW_WALLPAPER; 3992 } else { 3993 return; 3994 } 3995 } 3996 } 3997 3998 if (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 return screenshotApplicationsInner(appToken, displayId, width, height, false, frameScale); 6025 } 6026 6027 Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height, 6028 boolean includeFullDisplay, float frameScale) { 6029 final DisplayContent displayContent; 6030 synchronized(mWindowMap) { 6031 displayContent = getDisplayContentLocked(displayId); 6032 if (displayContent == null) { 6033 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 6034 + ": returning null. No Display for displayId=" + displayId); 6035 return null; 6036 } 6037 } 6038 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6039 int dw = displayInfo.logicalWidth; 6040 int dh = displayInfo.logicalHeight; 6041 if (dw == 0 || dh == 0) { 6042 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 6043 + ": returning null. logical widthxheight=" + dw + "x" + dh); 6044 return null; 6045 } 6046 6047 Bitmap bm = null; 6048 6049 int maxLayer = 0; 6050 final Rect frame = new Rect(); 6051 final Rect stackBounds = new Rect(); 6052 6053 boolean screenshotReady; 6054 int minLayer; 6055 if (appToken == null) { 6056 screenshotReady = true; 6057 minLayer = 0; 6058 } else { 6059 screenshotReady = false; 6060 minLayer = Integer.MAX_VALUE; 6061 } 6062 6063 WindowState appWin = null; 6064 6065 boolean appIsImTarget; 6066 synchronized(mWindowMap) { 6067 appIsImTarget = mInputMethodTarget != null 6068 && mInputMethodTarget.mAppToken != null 6069 && mInputMethodTarget.mAppToken.appToken != null 6070 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 6071 } 6072 6073 final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1) 6074 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 6075 6076 synchronized(mWindowMap) { 6077 // Figure out the part of the screen that is actually the app. 6078 appWin = null; 6079 final WindowList windows = displayContent.getWindowList(); 6080 for (int i = windows.size() - 1; i >= 0; i--) { 6081 WindowState ws = windows.get(i); 6082 if (!ws.mHasSurface) { 6083 continue; 6084 } 6085 if (ws.mLayer >= aboveAppLayer) { 6086 continue; 6087 } 6088 if (ws.mIsImWindow) { 6089 if (!appIsImTarget) { 6090 continue; 6091 } 6092 } else if (ws.mIsWallpaper) { 6093 if (appWin == null) { 6094 // We have not ran across the target window yet, so it is probably 6095 // behind the wallpaper. This can happen when the keyguard is up and 6096 // all windows are moved behind the wallpaper. We don't want to 6097 // include the wallpaper layer in the screenshot as it will coverup 6098 // the layer of the target window. 6099 continue; 6100 } 6101 // Fall through. The target window is in front of the wallpaper. For this 6102 // case we want to include the wallpaper layer in the screenshot because 6103 // the target window might have some transparent areas. 6104 } else if (appToken != null) { 6105 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 6106 // This app window is of no interest if it is not associated with the 6107 // screenshot app. 6108 continue; 6109 } 6110 appWin = ws; 6111 } 6112 6113 // Include this window. 6114 6115 final WindowStateAnimator winAnim = ws.mWinAnimator; 6116 int layer = winAnim.mSurfaceController.getLayer(); 6117 if (maxLayer < layer) { 6118 maxLayer = layer; 6119 } 6120 if (minLayer > layer) { 6121 minLayer = layer; 6122 } 6123 6124 // Don't include wallpaper in bounds calculation 6125 if (!includeFullDisplay && !ws.mIsWallpaper) { 6126 final Rect wf = ws.mFrame; 6127 final Rect cr = ws.mContentInsets; 6128 int left = wf.left + cr.left; 6129 int top = wf.top + cr.top; 6130 int right = wf.right - cr.right; 6131 int bottom = wf.bottom - cr.bottom; 6132 frame.union(left, top, right, bottom); 6133 ws.getVisibleBounds(stackBounds); 6134 if (!Rect.intersects(frame, stackBounds)) { 6135 // Set frame empty if there's no intersection. 6136 frame.setEmpty(); 6137 } 6138 } 6139 6140 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 6141 ws.isDisplayedLw() && winAnim.getShown()) { 6142 screenshotReady = true; 6143 } 6144 6145 if (ws.isObscuringFullscreen(displayInfo)){ 6146 break; 6147 } 6148 } 6149 6150 if (appToken != null && appWin == null) { 6151 // Can't find a window to snapshot. 6152 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, 6153 "Screenshot: Couldn't find a surface matching " + appToken); 6154 return null; 6155 } 6156 6157 if (!screenshotReady) { 6158 Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken + 6159 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + 6160 appWin.mWinAnimator.mDrawState))); 6161 return null; 6162 } 6163 6164 // Screenshot is ready to be taken. Everything from here below will continue 6165 // through the bottom of the loop and return a value. We only stay in the loop 6166 // because we don't want to release the mWindowMap lock until the screenshot is 6167 // taken. 6168 6169 if (maxLayer == 0) { 6170 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 6171 + ": returning null maxLayer=" + maxLayer); 6172 return null; 6173 } 6174 6175 if (!includeFullDisplay) { 6176 // Constrain frame to the screen size. 6177 if (!frame.intersect(0, 0, dw, dh)) { 6178 frame.setEmpty(); 6179 } 6180 } else { 6181 // Caller just wants entire display. 6182 frame.set(0, 0, dw, dh); 6183 } 6184 if (frame.isEmpty()) { 6185 return null; 6186 } 6187 6188 if (width < 0) { 6189 width = (int) (frame.width() * frameScale); 6190 } 6191 if (height < 0) { 6192 height = (int) (frame.height() * frameScale); 6193 } 6194 6195 // Tell surface flinger what part of the image to crop. Take the top 6196 // right part of the application, and crop the larger dimension to fit. 6197 Rect crop = new Rect(frame); 6198 if (width / (float) frame.width() < height / (float) frame.height()) { 6199 int cropWidth = (int)((float)width / (float)height * frame.height()); 6200 crop.right = crop.left + cropWidth; 6201 } else { 6202 int cropHeight = (int)((float)height / (float)width * frame.width()); 6203 crop.bottom = crop.top + cropHeight; 6204 } 6205 6206 // The screenshot API does not apply the current screen rotation. 6207 int rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 6208 6209 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 6210 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 6211 } 6212 6213 // Surfaceflinger is not aware of orientation, so convert our logical 6214 // crop to surfaceflinger's portrait orientation. 6215 convertCropForSurfaceFlinger(crop, rot, dw, dh); 6216 6217 if (DEBUG_SCREENSHOT) { 6218 Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 6219 + maxLayer + " appToken=" + appToken); 6220 for (int i = 0; i < windows.size(); i++) { 6221 WindowState win = windows.get(i); 6222 Slog.i(TAG_WM, win + ": " + win.mLayer 6223 + " animLayer=" + win.mWinAnimator.mAnimLayer 6224 + " surfaceLayer=" + win.mWinAnimator.mSurfaceController.getLayer()); 6225 } 6226 } 6227 6228 ScreenRotationAnimation screenRotationAnimation = 6229 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6230 final boolean inRotation = screenRotationAnimation != null && 6231 screenRotationAnimation.isAnimating(); 6232 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, 6233 "Taking screenshot while rotating"); 6234 6235 bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer, 6236 inRotation, rot); 6237 if (bm == null) { 6238 Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh 6239 + ") to layer " + maxLayer); 6240 return null; 6241 } 6242 } 6243 6244 if (DEBUG_SCREENSHOT) { 6245 // TEST IF IT's ALL BLACK 6246 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 6247 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 6248 boolean allBlack = true; 6249 final int firstColor = buffer[0]; 6250 for (int i = 0; i < buffer.length; i++) { 6251 if (buffer[i] != firstColor) { 6252 allBlack = false; 6253 break; 6254 } 6255 } 6256 if (allBlack) { 6257 Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" + 6258 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 6259 (appWin != null ? 6260 appWin.mWinAnimator.mSurfaceController.getLayer() : "null") + 6261 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 6262 } 6263 } 6264 6265 // Create a copy of the screenshot that is immutable and backed in ashmem. 6266 // This greatly reduces the overhead of passing the bitmap between processes. 6267 Bitmap ret = bm.createAshmemBitmap(); 6268 bm.recycle(); 6269 return ret; 6270 } 6271 6272 /** 6273 * Freeze rotation changes. (Enable "rotation lock".) 6274 * Persists across reboots. 6275 * @param rotation The desired rotation to freeze to, or -1 to use the 6276 * current rotation. 6277 */ 6278 @Override 6279 public void freezeRotation(int rotation) { 6280 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 6281 "freezeRotation()")) { 6282 throw new SecurityException("Requires SET_ORIENTATION permission"); 6283 } 6284 if (rotation < -1 || rotation > Surface.ROTATION_270) { 6285 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 6286 + "rotation constant."); 6287 } 6288 6289 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation=" + mRotation); 6290 6291 long origId = Binder.clearCallingIdentity(); 6292 try { 6293 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 6294 rotation == -1 ? mRotation : rotation); 6295 } finally { 6296 Binder.restoreCallingIdentity(origId); 6297 } 6298 6299 updateRotationUnchecked(false, false); 6300 } 6301 6302 /** 6303 * Thaw rotation changes. (Disable "rotation lock".) 6304 * Persists across reboots. 6305 */ 6306 @Override 6307 public void thawRotation() { 6308 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 6309 "thawRotation()")) { 6310 throw new SecurityException("Requires SET_ORIENTATION permission"); 6311 } 6312 6313 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "thawRotation: mRotation=" + mRotation); 6314 6315 long origId = Binder.clearCallingIdentity(); 6316 try { 6317 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 6318 777); // rot not used 6319 } finally { 6320 Binder.restoreCallingIdentity(origId); 6321 } 6322 6323 updateRotationUnchecked(false, false); 6324 } 6325 6326 /** 6327 * Recalculate the current rotation. 6328 * 6329 * Called by the window manager policy whenever the state of the system changes 6330 * such that the current rotation might need to be updated, such as when the 6331 * device is docked or rotated into a new posture. 6332 */ 6333 @Override 6334 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 6335 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 6336 } 6337 6338 /** 6339 * Temporarily pauses rotation changes until resumed. 6340 * 6341 * This can be used to prevent rotation changes from occurring while the user is 6342 * performing certain operations, such as drag and drop. 6343 * 6344 * This call nests and must be matched by an equal number of calls to 6345 * {@link #resumeRotationLocked}. 6346 */ 6347 void pauseRotationLocked() { 6348 mDeferredRotationPauseCount += 1; 6349 } 6350 6351 /** 6352 * Resumes normal rotation changes after being paused. 6353 */ 6354 void resumeRotationLocked() { 6355 if (mDeferredRotationPauseCount > 0) { 6356 mDeferredRotationPauseCount -= 1; 6357 if (mDeferredRotationPauseCount == 0) { 6358 boolean changed = updateRotationUncheckedLocked(false); 6359 if (changed) { 6360 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6361 } 6362 } 6363 } 6364 } 6365 6366 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 6367 if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked(" 6368 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 6369 6370 long origId = Binder.clearCallingIdentity(); 6371 boolean changed; 6372 synchronized(mWindowMap) { 6373 changed = updateRotationUncheckedLocked(false); 6374 if (!changed || forceRelayout) { 6375 getDefaultDisplayContentLocked().layoutNeeded = true; 6376 mWindowPlacerLocked.performSurfacePlacement(); 6377 } 6378 } 6379 6380 if (changed || alwaysSendConfiguration) { 6381 sendNewConfiguration(); 6382 } 6383 6384 Binder.restoreCallingIdentity(origId); 6385 } 6386 6387 // TODO(multidisplay): Rotate any display? 6388 /** 6389 * Updates the current rotation. 6390 * 6391 * Returns true if the rotation has been changed. In this case YOU 6392 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 6393 */ 6394 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 6395 if (mDeferredRotationPauseCount > 0) { 6396 // Rotation updates have been paused temporarily. Defer the update until 6397 // updates have been resumed. 6398 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused."); 6399 return false; 6400 } 6401 6402 ScreenRotationAnimation screenRotationAnimation = 6403 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6404 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 6405 // Rotation updates cannot be performed while the previous rotation change 6406 // animation is still in progress. Skip this update. We will try updating 6407 // again after the animation is finished and the display is unfrozen. 6408 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress."); 6409 return false; 6410 } 6411 6412 if (!mDisplayEnabled) { 6413 // No point choosing a rotation if the display is not enabled. 6414 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled."); 6415 return false; 6416 } 6417 6418 // TODO: Implement forced rotation changes. 6419 // Set mAltOrientation to indicate that the application is receiving 6420 // an orientation that has different metrics than it expected. 6421 // eg. Portrait instead of Landscape. 6422 6423 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 6424 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 6425 mForcedAppOrientation, rotation); 6426 6427 if (DEBUG_ORIENTATION) { 6428 Slog.v(TAG_WM, "Application requested orientation " 6429 + mForcedAppOrientation + ", got rotation " + rotation 6430 + " which has " + (altOrientation ? "incompatible" : "compatible") 6431 + " metrics"); 6432 } 6433 6434 if (mRotation == rotation && mAltOrientation == altOrientation) { 6435 // No change. 6436 return false; 6437 } 6438 6439 if (DEBUG_ORIENTATION) { 6440 Slog.v(TAG_WM, 6441 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 6442 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 6443 + ", forceApp=" + mForcedAppOrientation); 6444 } 6445 6446 mRotation = rotation; 6447 mAltOrientation = altOrientation; 6448 mPolicy.setRotationLw(mRotation); 6449 6450 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; 6451 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 6452 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 6453 mWaitingForConfig = true; 6454 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6455 displayContent.layoutNeeded = true; 6456 final int[] anim = new int[2]; 6457 if (displayContent.isDimming()) { 6458 anim[0] = anim[1] = 0; 6459 } else { 6460 mPolicy.selectRotationAnimationLw(anim); 6461 } 6462 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6463 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6464 screenRotationAnimation = 6465 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6466 6467 // We need to update our screen size information to match the new rotation. If the rotation 6468 // has actually changed then this method will return true and, according to the comment at 6469 // the top of the method, the caller is obligated to call computeNewConfigurationLocked(). 6470 // By updating the Display info here it will be available to 6471 // computeScreenConfigurationLocked later. 6472 updateDisplayAndOrientationLocked(mCurConfiguration.uiMode); 6473 6474 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6475 if (!inTransaction) { 6476 if (SHOW_TRANSACTIONS) { 6477 Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked"); 6478 } 6479 SurfaceControl.openTransaction(); 6480 } 6481 try { 6482 // NOTE: We disable the rotation in the emulator because 6483 // it doesn't support hardware OpenGL emulation yet. 6484 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6485 && screenRotationAnimation.hasScreenshot()) { 6486 if (screenRotationAnimation.setRotationInTransaction( 6487 rotation, mFxSession, 6488 MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), 6489 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6490 scheduleAnimationLocked(); 6491 } 6492 } 6493 6494 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6495 } finally { 6496 if (!inTransaction) { 6497 SurfaceControl.closeTransaction(); 6498 if (SHOW_LIGHT_TRANSACTIONS) { 6499 Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6500 } 6501 } 6502 } 6503 6504 final WindowList windows = displayContent.getWindowList(); 6505 for (int i = windows.size() - 1; i >= 0; i--) { 6506 WindowState w = windows.get(i); 6507 // Discard surface after orientation change, these can't be reused. 6508 if (w.mAppToken != null) { 6509 w.mAppToken.destroySavedSurfaces(); 6510 } 6511 if (w.mHasSurface) { 6512 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w); 6513 w.mOrientationChanging = true; 6514 mWindowPlacerLocked.mOrientationChangeComplete = false; 6515 } 6516 w.mLastFreezeDuration = 0; 6517 } 6518 6519 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6520 try { 6521 mRotationWatchers.get(i).watcher.onRotationChanged(rotation); 6522 } catch (RemoteException e) { 6523 } 6524 } 6525 6526 //TODO (multidisplay): Magnification is supported only for the default display. 6527 // Announce rotation only if we will not animate as we already have the 6528 // windows in final state. Otherwise, we make this call at the rotation end. 6529 if (screenRotationAnimation == null && mAccessibilityController != null 6530 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6531 mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), 6532 rotation); 6533 } 6534 6535 return true; 6536 } 6537 6538 @Override 6539 public int getRotation() { 6540 return mRotation; 6541 } 6542 6543 @Override 6544 public boolean isRotationFrozen() { 6545 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6546 } 6547 6548 @Override 6549 public int watchRotation(IRotationWatcher watcher) { 6550 final IBinder watcherBinder = watcher.asBinder(); 6551 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6552 @Override 6553 public void binderDied() { 6554 synchronized (mWindowMap) { 6555 for (int i=0; i<mRotationWatchers.size(); i++) { 6556 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) { 6557 RotationWatcher removed = mRotationWatchers.remove(i); 6558 IBinder binder = removed.watcher.asBinder(); 6559 if (binder != null) { 6560 binder.unlinkToDeath(this, 0); 6561 } 6562 i--; 6563 } 6564 } 6565 } 6566 } 6567 }; 6568 6569 synchronized (mWindowMap) { 6570 try { 6571 watcher.asBinder().linkToDeath(dr, 0); 6572 mRotationWatchers.add(new RotationWatcher(watcher, dr)); 6573 } catch (RemoteException e) { 6574 // Client died, no cleanup needed. 6575 } 6576 6577 return mRotation; 6578 } 6579 } 6580 6581 @Override 6582 public void removeRotationWatcher(IRotationWatcher watcher) { 6583 final IBinder watcherBinder = watcher.asBinder(); 6584 synchronized (mWindowMap) { 6585 for (int i=0; i<mRotationWatchers.size(); i++) { 6586 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 6587 if (watcherBinder == rotationWatcher.watcher.asBinder()) { 6588 RotationWatcher removed = mRotationWatchers.remove(i); 6589 IBinder binder = removed.watcher.asBinder(); 6590 if (binder != null) { 6591 binder.unlinkToDeath(removed.deathRecipient, 0); 6592 } 6593 i--; 6594 } 6595 } 6596 } 6597 } 6598 6599 /** 6600 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6601 * theme attribute) on devices that feature a physical options menu key attempt to position 6602 * their menu panel window along the edge of the screen nearest the physical menu key. 6603 * This lowers the travel distance between invoking the menu panel and selecting 6604 * a menu option. 6605 * 6606 * This method helps control where that menu is placed. Its current implementation makes 6607 * assumptions about the menu key and its relationship to the screen based on whether 6608 * the device's natural orientation is portrait (width < height) or landscape. 6609 * 6610 * The menu key is assumed to be located along the bottom edge of natural-portrait 6611 * devices and along the right edge of natural-landscape devices. If these assumptions 6612 * do not hold for the target device, this method should be changed to reflect that. 6613 * 6614 * @return A {@link Gravity} value for placing the options menu window 6615 */ 6616 @Override 6617 public int getPreferredOptionsPanelGravity() { 6618 synchronized (mWindowMap) { 6619 final int rotation = getRotation(); 6620 6621 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6622 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6623 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6624 // On devices with a natural orientation of portrait 6625 switch (rotation) { 6626 default: 6627 case Surface.ROTATION_0: 6628 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6629 case Surface.ROTATION_90: 6630 return Gravity.RIGHT | Gravity.BOTTOM; 6631 case Surface.ROTATION_180: 6632 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6633 case Surface.ROTATION_270: 6634 return Gravity.START | Gravity.BOTTOM; 6635 } 6636 } 6637 6638 // On devices with a natural orientation of landscape 6639 switch (rotation) { 6640 default: 6641 case Surface.ROTATION_0: 6642 return Gravity.RIGHT | Gravity.BOTTOM; 6643 case Surface.ROTATION_90: 6644 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6645 case Surface.ROTATION_180: 6646 return Gravity.START | Gravity.BOTTOM; 6647 case Surface.ROTATION_270: 6648 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6649 } 6650 } 6651 } 6652 6653 /** 6654 * Starts the view server on the specified port. 6655 * 6656 * @param port The port to listener to. 6657 * 6658 * @return True if the server was successfully started, false otherwise. 6659 * 6660 * @see com.android.server.wm.ViewServer 6661 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6662 */ 6663 @Override 6664 public boolean startViewServer(int port) { 6665 if (isSystemSecure()) { 6666 return false; 6667 } 6668 6669 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6670 return false; 6671 } 6672 6673 if (port < 1024) { 6674 return false; 6675 } 6676 6677 if (mViewServer != null) { 6678 if (!mViewServer.isRunning()) { 6679 try { 6680 return mViewServer.start(); 6681 } catch (IOException e) { 6682 Slog.w(TAG_WM, "View server did not start"); 6683 } 6684 } 6685 return false; 6686 } 6687 6688 try { 6689 mViewServer = new ViewServer(this, port); 6690 return mViewServer.start(); 6691 } catch (IOException e) { 6692 Slog.w(TAG_WM, "View server did not start"); 6693 } 6694 return false; 6695 } 6696 6697 private boolean isSystemSecure() { 6698 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6699 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6700 } 6701 6702 /** 6703 * Stops the view server if it exists. 6704 * 6705 * @return True if the server stopped, false if it wasn't started or 6706 * couldn't be stopped. 6707 * 6708 * @see com.android.server.wm.ViewServer 6709 */ 6710 @Override 6711 public boolean stopViewServer() { 6712 if (isSystemSecure()) { 6713 return false; 6714 } 6715 6716 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6717 return false; 6718 } 6719 6720 if (mViewServer != null) { 6721 return mViewServer.stop(); 6722 } 6723 return false; 6724 } 6725 6726 /** 6727 * Indicates whether the view server is running. 6728 * 6729 * @return True if the server is running, false otherwise. 6730 * 6731 * @see com.android.server.wm.ViewServer 6732 */ 6733 @Override 6734 public boolean isViewServerRunning() { 6735 if (isSystemSecure()) { 6736 return false; 6737 } 6738 6739 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6740 return false; 6741 } 6742 6743 return mViewServer != null && mViewServer.isRunning(); 6744 } 6745 6746 /** 6747 * Lists all availble windows in the system. The listing is written in the 6748 * specified Socket's output stream with the following syntax: 6749 * windowHashCodeInHexadecimal windowName 6750 * Each line of the ouput represents a different window. 6751 * 6752 * @param client The remote client to send the listing to. 6753 * @return False if an error occured, true otherwise. 6754 */ 6755 boolean viewServerListWindows(Socket client) { 6756 if (isSystemSecure()) { 6757 return false; 6758 } 6759 6760 boolean result = true; 6761 6762 WindowList windows = new WindowList(); 6763 synchronized (mWindowMap) { 6764 //noinspection unchecked 6765 final int numDisplays = mDisplayContents.size(); 6766 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6767 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6768 windows.addAll(displayContent.getWindowList()); 6769 } 6770 } 6771 6772 BufferedWriter out = null; 6773 6774 // Any uncaught exception will crash the system process 6775 try { 6776 OutputStream clientStream = client.getOutputStream(); 6777 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6778 6779 final int count = windows.size(); 6780 for (int i = 0; i < count; i++) { 6781 final WindowState w = windows.get(i); 6782 out.write(Integer.toHexString(System.identityHashCode(w))); 6783 out.write(' '); 6784 out.append(w.mAttrs.getTitle()); 6785 out.write('\n'); 6786 } 6787 6788 out.write("DONE.\n"); 6789 out.flush(); 6790 } catch (Exception e) { 6791 result = false; 6792 } finally { 6793 if (out != null) { 6794 try { 6795 out.close(); 6796 } catch (IOException e) { 6797 result = false; 6798 } 6799 } 6800 } 6801 6802 return result; 6803 } 6804 6805 // TODO(multidisplay): Extend to multiple displays. 6806 /** 6807 * Returns the focused window in the following format: 6808 * windowHashCodeInHexadecimal windowName 6809 * 6810 * @param client The remote client to send the listing to. 6811 * @return False if an error occurred, true otherwise. 6812 */ 6813 boolean viewServerGetFocusedWindow(Socket client) { 6814 if (isSystemSecure()) { 6815 return false; 6816 } 6817 6818 boolean result = true; 6819 6820 WindowState focusedWindow = getFocusedWindow(); 6821 6822 BufferedWriter out = null; 6823 6824 // Any uncaught exception will crash the system process 6825 try { 6826 OutputStream clientStream = client.getOutputStream(); 6827 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6828 6829 if(focusedWindow != null) { 6830 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6831 out.write(' '); 6832 out.append(focusedWindow.mAttrs.getTitle()); 6833 } 6834 out.write('\n'); 6835 out.flush(); 6836 } catch (Exception e) { 6837 result = false; 6838 } finally { 6839 if (out != null) { 6840 try { 6841 out.close(); 6842 } catch (IOException e) { 6843 result = false; 6844 } 6845 } 6846 } 6847 6848 return result; 6849 } 6850 6851 /** 6852 * Sends a command to a target window. The result of the command, if any, will be 6853 * written in the output stream of the specified socket. 6854 * 6855 * The parameters must follow this syntax: 6856 * windowHashcode extra 6857 * 6858 * Where XX is the length in characeters of the windowTitle. 6859 * 6860 * The first parameter is the target window. The window with the specified hashcode 6861 * will be the target. If no target can be found, nothing happens. The extra parameters 6862 * will be delivered to the target window and as parameters to the command itself. 6863 * 6864 * @param client The remote client to sent the result, if any, to. 6865 * @param command The command to execute. 6866 * @param parameters The command parameters. 6867 * 6868 * @return True if the command was successfully delivered, false otherwise. This does 6869 * not indicate whether the command itself was successful. 6870 */ 6871 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6872 if (isSystemSecure()) { 6873 return false; 6874 } 6875 6876 boolean success = true; 6877 Parcel data = null; 6878 Parcel reply = null; 6879 6880 BufferedWriter out = null; 6881 6882 // Any uncaught exception will crash the system process 6883 try { 6884 // Find the hashcode of the window 6885 int index = parameters.indexOf(' '); 6886 if (index == -1) { 6887 index = parameters.length(); 6888 } 6889 final String code = parameters.substring(0, index); 6890 int hashCode = (int) Long.parseLong(code, 16); 6891 6892 // Extract the command's parameter after the window description 6893 if (index < parameters.length()) { 6894 parameters = parameters.substring(index + 1); 6895 } else { 6896 parameters = ""; 6897 } 6898 6899 final WindowState window = findWindow(hashCode); 6900 if (window == null) { 6901 return false; 6902 } 6903 6904 data = Parcel.obtain(); 6905 data.writeInterfaceToken("android.view.IWindow"); 6906 data.writeString(command); 6907 data.writeString(parameters); 6908 data.writeInt(1); 6909 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6910 6911 reply = Parcel.obtain(); 6912 6913 final IBinder binder = window.mClient.asBinder(); 6914 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6915 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6916 6917 reply.readException(); 6918 6919 if (!client.isOutputShutdown()) { 6920 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6921 out.write("DONE\n"); 6922 out.flush(); 6923 } 6924 6925 } catch (Exception e) { 6926 Slog.w(TAG_WM, "Could not send command " + command + " with parameters " + parameters, e); 6927 success = false; 6928 } finally { 6929 if (data != null) { 6930 data.recycle(); 6931 } 6932 if (reply != null) { 6933 reply.recycle(); 6934 } 6935 if (out != null) { 6936 try { 6937 out.close(); 6938 } catch (IOException e) { 6939 6940 } 6941 } 6942 } 6943 6944 return success; 6945 } 6946 6947 public void addWindowChangeListener(WindowChangeListener listener) { 6948 synchronized(mWindowMap) { 6949 mWindowChangeListeners.add(listener); 6950 } 6951 } 6952 6953 public void removeWindowChangeListener(WindowChangeListener listener) { 6954 synchronized(mWindowMap) { 6955 mWindowChangeListeners.remove(listener); 6956 } 6957 } 6958 6959 private void notifyWindowsChanged() { 6960 WindowChangeListener[] windowChangeListeners; 6961 synchronized(mWindowMap) { 6962 if(mWindowChangeListeners.isEmpty()) { 6963 return; 6964 } 6965 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6966 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6967 } 6968 int N = windowChangeListeners.length; 6969 for(int i = 0; i < N; i++) { 6970 windowChangeListeners[i].windowsChanged(); 6971 } 6972 } 6973 6974 private void notifyFocusChanged() { 6975 WindowChangeListener[] windowChangeListeners; 6976 synchronized(mWindowMap) { 6977 if(mWindowChangeListeners.isEmpty()) { 6978 return; 6979 } 6980 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6981 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6982 } 6983 int N = windowChangeListeners.length; 6984 for(int i = 0; i < N; i++) { 6985 windowChangeListeners[i].focusChanged(); 6986 } 6987 } 6988 6989 private WindowState findWindow(int hashCode) { 6990 if (hashCode == -1) { 6991 // TODO(multidisplay): Extend to multiple displays. 6992 return getFocusedWindow(); 6993 } 6994 6995 synchronized (mWindowMap) { 6996 final int numDisplays = mDisplayContents.size(); 6997 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6998 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6999 final int numWindows = windows.size(); 7000 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 7001 final WindowState w = windows.get(winNdx); 7002 if (System.identityHashCode(w) == hashCode) { 7003 return w; 7004 } 7005 } 7006 } 7007 } 7008 7009 return null; 7010 } 7011 7012 /* 7013 * Instruct the Activity Manager to fetch the current configuration and broadcast 7014 * that to config-changed listeners if appropriate. 7015 */ 7016 void sendNewConfiguration() { 7017 try { 7018 mActivityManager.updateConfiguration(null); 7019 } catch (RemoteException e) { 7020 } 7021 } 7022 7023 public Configuration computeNewConfiguration() { 7024 synchronized (mWindowMap) { 7025 return computeNewConfigurationLocked(); 7026 } 7027 } 7028 7029 private Configuration computeNewConfigurationLocked() { 7030 if (!mDisplayReady) { 7031 return null; 7032 } 7033 Configuration config = new Configuration(); 7034 config.fontScale = 0; 7035 computeScreenConfigurationLocked(config); 7036 return config; 7037 } 7038 7039 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int uiMode, 7040 int dw, int dh) { 7041 // TODO: Multidisplay: for now only use with default display. 7042 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode); 7043 if (width < displayInfo.smallestNominalAppWidth) { 7044 displayInfo.smallestNominalAppWidth = width; 7045 } 7046 if (width > displayInfo.largestNominalAppWidth) { 7047 displayInfo.largestNominalAppWidth = width; 7048 } 7049 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode); 7050 if (height < displayInfo.smallestNominalAppHeight) { 7051 displayInfo.smallestNominalAppHeight = height; 7052 } 7053 if (height > displayInfo.largestNominalAppHeight) { 7054 displayInfo.largestNominalAppHeight = height; 7055 } 7056 } 7057 7058 private int reduceConfigLayout(int curLayout, int rotation, float density, 7059 int dw, int dh, int uiMode) { 7060 // TODO: Multidisplay: for now only use with default display. 7061 // Get the app screen size at this rotation. 7062 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode); 7063 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode); 7064 7065 // Compute the screen layout size class for this rotation. 7066 int longSize = w; 7067 int shortSize = h; 7068 if (longSize < shortSize) { 7069 int tmp = longSize; 7070 longSize = shortSize; 7071 shortSize = tmp; 7072 } 7073 longSize = (int)(longSize/density); 7074 shortSize = (int)(shortSize/density); 7075 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 7076 } 7077 7078 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 7079 int uiMode, int dw, int dh, float density, Configuration outConfig) { 7080 // TODO: Multidisplay: for now only use with default display. 7081 7082 // We need to determine the smallest width that will occur under normal 7083 // operation. To this, start with the base screen size and compute the 7084 // width under the different possible rotations. We need to un-rotate 7085 // the current screen dimensions before doing this. 7086 int unrotDw, unrotDh; 7087 if (rotated) { 7088 unrotDw = dh; 7089 unrotDh = dw; 7090 } else { 7091 unrotDw = dw; 7092 unrotDh = dh; 7093 } 7094 displayInfo.smallestNominalAppWidth = 1<<30; 7095 displayInfo.smallestNominalAppHeight = 1<<30; 7096 displayInfo.largestNominalAppWidth = 0; 7097 displayInfo.largestNominalAppHeight = 0; 7098 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, uiMode, unrotDw, unrotDh); 7099 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw); 7100 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh); 7101 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw); 7102 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 7103 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode); 7104 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode); 7105 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode); 7106 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode); 7107 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 7108 outConfig.screenLayout = sl; 7109 } 7110 7111 private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode, 7112 DisplayMetrics dm, int dw, int dh) { 7113 // TODO: Multidisplay: for now only use with default display. 7114 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode); 7115 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode); 7116 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 7117 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 7118 if (curSize == 0 || size < curSize) { 7119 curSize = size; 7120 } 7121 return curSize; 7122 } 7123 7124 private int computeCompatSmallestWidth(boolean rotated, int uiMode, DisplayMetrics dm, int dw, int dh) { 7125 // TODO: Multidisplay: for now only use with default display. 7126 mTmpDisplayMetrics.setTo(dm); 7127 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 7128 final int unrotDw, unrotDh; 7129 if (rotated) { 7130 unrotDw = dh; 7131 unrotDh = dw; 7132 } else { 7133 unrotDw = dw; 7134 unrotDh = dh; 7135 } 7136 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh); 7137 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw); 7138 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh); 7139 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw); 7140 return sw; 7141 } 7142 7143 /** Do not call if mDisplayReady == false */ 7144 DisplayInfo updateDisplayAndOrientationLocked(int uiMode) { 7145 // TODO(multidisplay): For now, apply Configuration to main screen only. 7146 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7147 7148 // Use the effective "visual" dimensions based on current rotation 7149 final boolean rotated = (mRotation == Surface.ROTATION_90 7150 || mRotation == Surface.ROTATION_270); 7151 final int realdw = rotated ? 7152 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 7153 final int realdh = rotated ? 7154 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 7155 int dw = realdw; 7156 int dh = realdh; 7157 7158 if (mAltOrientation) { 7159 if (realdw > realdh) { 7160 // Turn landscape into portrait. 7161 int maxw = (int)(realdh/1.3f); 7162 if (maxw < realdw) { 7163 dw = maxw; 7164 } 7165 } else { 7166 // Turn portrait into landscape. 7167 int maxh = (int)(realdw/1.3f); 7168 if (maxh < realdh) { 7169 dh = maxh; 7170 } 7171 } 7172 } 7173 7174 // Update application display metrics. 7175 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode); 7176 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode); 7177 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7178 displayInfo.rotation = mRotation; 7179 displayInfo.logicalWidth = dw; 7180 displayInfo.logicalHeight = dh; 7181 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 7182 displayInfo.appWidth = appWidth; 7183 displayInfo.appHeight = appHeight; 7184 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 7185 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 7186 displayInfo.getAppMetrics(mDisplayMetrics); 7187 if (displayContent.mDisplayScalingDisabled) { 7188 displayInfo.flags |= Display.FLAG_SCALING_DISABLED; 7189 } else { 7190 displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED; 7191 } 7192 7193 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 7194 displayContent.getDisplayId(), displayInfo); 7195 7196 displayContent.mBaseDisplayRect.set(0, 0, dw, dh); 7197 if (false) { 7198 Slog.i(TAG_WM, "Set app display size: " + appWidth + " x " + appHeight); 7199 } 7200 7201 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics, 7202 mCompatDisplayMetrics); 7203 return displayInfo; 7204 } 7205 7206 /** Do not call if mDisplayReady == false */ 7207 void computeScreenConfigurationLocked(Configuration config) { 7208 final DisplayInfo displayInfo = updateDisplayAndOrientationLocked( 7209 config.uiMode); 7210 7211 final int dw = displayInfo.logicalWidth; 7212 final int dh = displayInfo.logicalHeight; 7213 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 7214 Configuration.ORIENTATION_LANDSCAPE; 7215 config.screenWidthDp = 7216 (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation, config.uiMode) / 7217 mDisplayMetrics.density); 7218 config.screenHeightDp = 7219 (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation, config.uiMode) / 7220 mDisplayMetrics.density); 7221 final boolean rotated = (mRotation == Surface.ROTATION_90 7222 || mRotation == Surface.ROTATION_270); 7223 7224 computeSizeRangesAndScreenLayout(displayInfo, rotated, config.uiMode, dw, dh, 7225 mDisplayMetrics.density, config); 7226 7227 config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK) 7228 | ((displayInfo.flags & Display.FLAG_ROUND) != 0 7229 ? Configuration.SCREENLAYOUT_ROUND_YES 7230 : Configuration.SCREENLAYOUT_ROUND_NO); 7231 7232 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 7233 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 7234 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, 7235 mDisplayMetrics, dw, dh); 7236 config.densityDpi = displayInfo.logicalDensityDpi; 7237 7238 // Update the configuration based on available input devices, lid switch, 7239 // and platform configuration. 7240 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 7241 config.keyboard = Configuration.KEYBOARD_NOKEYS; 7242 config.navigation = Configuration.NAVIGATION_NONAV; 7243 7244 int keyboardPresence = 0; 7245 int navigationPresence = 0; 7246 final InputDevice[] devices = mInputManager.getInputDevices(); 7247 final int len = devices.length; 7248 for (int i = 0; i < len; i++) { 7249 InputDevice device = devices[i]; 7250 if (!device.isVirtual()) { 7251 final int sources = device.getSources(); 7252 final int presenceFlag = device.isExternal() ? 7253 WindowManagerPolicy.PRESENCE_EXTERNAL : 7254 WindowManagerPolicy.PRESENCE_INTERNAL; 7255 7256 if (mIsTouchDevice) { 7257 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 7258 InputDevice.SOURCE_TOUCHSCREEN) { 7259 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 7260 } 7261 } else { 7262 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 7263 } 7264 7265 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 7266 config.navigation = Configuration.NAVIGATION_TRACKBALL; 7267 navigationPresence |= presenceFlag; 7268 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 7269 && config.navigation == Configuration.NAVIGATION_NONAV) { 7270 config.navigation = Configuration.NAVIGATION_DPAD; 7271 navigationPresence |= presenceFlag; 7272 } 7273 7274 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 7275 config.keyboard = Configuration.KEYBOARD_QWERTY; 7276 keyboardPresence |= presenceFlag; 7277 } 7278 } 7279 } 7280 7281 if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) { 7282 config.navigation = Configuration.NAVIGATION_DPAD; 7283 navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL; 7284 } 7285 7286 // Determine whether a hard keyboard is available and enabled. 7287 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 7288 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 7289 mHardKeyboardAvailable = hardKeyboardAvailable; 7290 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 7291 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 7292 } 7293 7294 // Let the policy update hidden states. 7295 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 7296 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 7297 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 7298 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 7299 } 7300 7301 void notifyHardKeyboardStatusChange() { 7302 final boolean available; 7303 final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener; 7304 synchronized (mWindowMap) { 7305 listener = mHardKeyboardStatusChangeListener; 7306 available = mHardKeyboardAvailable; 7307 } 7308 if (listener != null) { 7309 listener.onHardKeyboardStatusChange(available); 7310 } 7311 } 7312 7313 boolean startMovingTask(IWindow window, float startX, float startY) { 7314 WindowState win = null; 7315 synchronized (mWindowMap) { 7316 win = windowForClientLocked(null, window, false); 7317 // win shouldn't be null here, pass it down to startPositioningLocked 7318 // to get warning if it's null. 7319 if (!startPositioningLocked(win, false /*resize*/, startX, startY)) { 7320 return false; 7321 } 7322 } 7323 try { 7324 mActivityManager.setFocusedTask(win.getTask().mTaskId); 7325 } catch(RemoteException e) {} 7326 return true; 7327 } 7328 7329 private void startScrollingTask(DisplayContent displayContent, int startX, int startY) { 7330 if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, 7331 "startScrollingTask: " + "{" + startX + ", " + startY + "}"); 7332 7333 Task task = null; 7334 synchronized (mWindowMap) { 7335 int taskId = displayContent.taskIdFromPoint(startX, startY); 7336 if (taskId >= 0) { 7337 task = mTaskIdToTask.get(taskId); 7338 } 7339 if (task == null || !task.isDockedInEffect() || !startPositioningLocked( 7340 task.getTopVisibleAppMainWindow(), false /*resize*/, startX, startY)) { 7341 return; 7342 } 7343 } 7344 try { 7345 mActivityManager.setFocusedTask(task.mTaskId); 7346 } catch(RemoteException e) {} 7347 } 7348 7349 private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) { 7350 int taskId = -1; 7351 synchronized (mWindowMap) { 7352 final Task task = displayContent.findTaskForControlPoint(x, y); 7353 if (task != null) { 7354 if (!startPositioningLocked( 7355 task.getTopVisibleAppMainWindow(), true /*resize*/, x, y)) { 7356 return; 7357 } 7358 taskId = task.mTaskId; 7359 } else { 7360 taskId = displayContent.taskIdFromPoint(x, y); 7361 } 7362 } 7363 if (taskId >= 0) { 7364 try { 7365 mActivityManager.setFocusedTask(taskId); 7366 } catch(RemoteException e) {} 7367 } 7368 } 7369 7370 private boolean startPositioningLocked( 7371 WindowState win, boolean resize, float startX, float startY) { 7372 if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "startPositioningLocked: " 7373 + "win=" + win + ", resize=" + resize + ", {" + startX + ", " + startY + "}"); 7374 7375 if (win == null || win.getAppToken() == null) { 7376 Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win); 7377 return false; 7378 } 7379 if (win.mInputChannel == null) { 7380 Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, " 7381 + " probably being removed"); 7382 return false; 7383 } 7384 7385 final DisplayContent displayContent = win.getDisplayContent(); 7386 if (displayContent == null) { 7387 Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win); 7388 return false; 7389 } 7390 7391 Display display = displayContent.getDisplay(); 7392 mTaskPositioner = new TaskPositioner(this); 7393 mTaskPositioner.register(display); 7394 mInputMonitor.updateInputWindowsLw(true /*force*/); 7395 7396 // We need to grab the touch focus so that the touch events during the 7397 // resizing/scrolling are not sent to the app. 'win' is the main window 7398 // of the app, it may not have focus since there might be other windows 7399 // on top (eg. a dialog window). 7400 WindowState transferFocusFromWin = win; 7401 if (mCurrentFocus != null && mCurrentFocus != win 7402 && mCurrentFocus.mAppToken == win.mAppToken) { 7403 transferFocusFromWin = mCurrentFocus; 7404 } 7405 if (!mInputManager.transferTouchFocus( 7406 transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) { 7407 Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus"); 7408 mTaskPositioner.unregister(); 7409 mTaskPositioner = null; 7410 mInputMonitor.updateInputWindowsLw(true /*force*/); 7411 return false; 7412 } 7413 7414 mTaskPositioner.startDragLocked(win, resize, startX, startY); 7415 return true; 7416 } 7417 7418 private void finishPositioning() { 7419 if (DEBUG_TASK_POSITIONING) { 7420 Slog.d(TAG_WM, "finishPositioning"); 7421 } 7422 synchronized (mWindowMap) { 7423 if (mTaskPositioner != null) { 7424 mTaskPositioner.unregister(); 7425 mTaskPositioner = null; 7426 mInputMonitor.updateInputWindowsLw(true /*force*/); 7427 } 7428 } 7429 } 7430 7431 private void adjustForImeIfNeeded(final DisplayContent displayContent) { 7432 final WindowState imeWin = mInputMethodWindow; 7433 final TaskStack focusedStack = 7434 mCurrentFocus != null ? mCurrentFocus.getStack() : null; 7435 final boolean dockVisible = isStackVisibleLocked(DOCKED_STACK_ID); 7436 if (imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw() 7437 && dockVisible 7438 && focusedStack != null 7439 && focusedStack.getDockSide() == DOCKED_BOTTOM){ 7440 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 7441 for (int i = stacks.size() - 1; i >= 0; --i) { 7442 final TaskStack stack = stacks.get(i); 7443 if (stack.isVisibleLocked()) { 7444 stack.setAdjustedForIme(imeWin); 7445 } 7446 } 7447 displayContent.mDividerControllerLocked.setAdjustedForIme(true, true); 7448 } else { 7449 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 7450 for (int i = stacks.size() - 1; i >= 0; --i) { 7451 final TaskStack stack = stacks.get(i); 7452 stack.resetAdjustedForIme(!dockVisible); 7453 } 7454 displayContent.mDividerControllerLocked.setAdjustedForIme(false, dockVisible); 7455 } 7456 } 7457 7458 // ------------------------------------------------------------- 7459 // Drag and drop 7460 // ------------------------------------------------------------- 7461 7462 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 7463 int flags, int width, int height, Surface outSurface) { 7464 if (DEBUG_DRAG) { 7465 Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height 7466 + " flags=" + Integer.toHexString(flags) + " win=" + window 7467 + " asbinder=" + window.asBinder()); 7468 } 7469 7470 final int callerPid = Binder.getCallingPid(); 7471 final int callerUid = Binder.getCallingUid(); 7472 final long origId = Binder.clearCallingIdentity(); 7473 IBinder token = null; 7474 7475 try { 7476 synchronized (mWindowMap) { 7477 try { 7478 if (mDragState == null) { 7479 // TODO(multi-display): support other displays 7480 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7481 final Display display = displayContent.getDisplay(); 7482 7483 SurfaceControl surface = new SurfaceControl(session, "drag surface", 7484 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 7485 surface.setLayerStack(display.getLayerStack()); 7486 float alpha = 1; 7487 if ((flags & View.DRAG_FLAG_OPAQUE) == 0) { 7488 alpha = DRAG_SHADOW_ALPHA_TRANSPARENT; 7489 } 7490 surface.setAlpha(alpha); 7491 7492 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG " 7493 + surface + ": CREATE"); 7494 outSurface.copyFrom(surface); 7495 final IBinder winBinder = window.asBinder(); 7496 token = new Binder(); 7497 mDragState = new DragState(this, token, surface, flags, winBinder); 7498 mDragState.mPid = callerPid; 7499 mDragState.mUid = callerUid; 7500 mDragState.mOriginalAlpha = alpha; 7501 token = mDragState.mToken = new Binder(); 7502 7503 // 5 second timeout for this window to actually begin the drag 7504 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 7505 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 7506 mH.sendMessageDelayed(msg, 5000); 7507 } else { 7508 Slog.w(TAG_WM, "Drag already in progress"); 7509 } 7510 } catch (OutOfResourcesException e) { 7511 Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e); 7512 if (mDragState != null) { 7513 mDragState.reset(); 7514 mDragState = null; 7515 } 7516 } 7517 } 7518 } finally { 7519 Binder.restoreCallingIdentity(origId); 7520 } 7521 7522 return token; 7523 } 7524 7525 // ------------------------------------------------------------- 7526 // Input Events and Focus Management 7527 // ------------------------------------------------------------- 7528 7529 final InputMonitor mInputMonitor = new InputMonitor(this); 7530 private boolean mEventDispatchingEnabled; 7531 7532 @Override 7533 public void pauseKeyDispatching(IBinder _token) { 7534 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7535 "pauseKeyDispatching()")) { 7536 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7537 } 7538 7539 synchronized (mWindowMap) { 7540 WindowToken token = mTokenMap.get(_token); 7541 if (token != null) { 7542 mInputMonitor.pauseDispatchingLw(token); 7543 } 7544 } 7545 } 7546 7547 @Override 7548 public void resumeKeyDispatching(IBinder _token) { 7549 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7550 "resumeKeyDispatching()")) { 7551 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7552 } 7553 7554 synchronized (mWindowMap) { 7555 WindowToken token = mTokenMap.get(_token); 7556 if (token != null) { 7557 mInputMonitor.resumeDispatchingLw(token); 7558 } 7559 } 7560 } 7561 7562 @Override 7563 public void setEventDispatching(boolean enabled) { 7564 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7565 "setEventDispatching()")) { 7566 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7567 } 7568 7569 synchronized (mWindowMap) { 7570 mEventDispatchingEnabled = enabled; 7571 if (mDisplayEnabled) { 7572 mInputMonitor.setEventDispatchingLw(enabled); 7573 } 7574 } 7575 } 7576 7577 private WindowState getFocusedWindow() { 7578 synchronized (mWindowMap) { 7579 return getFocusedWindowLocked(); 7580 } 7581 } 7582 7583 private WindowState getFocusedWindowLocked() { 7584 return mCurrentFocus; 7585 } 7586 7587 private void showAuditSafeModeNotification() { 7588 PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, 7589 new Intent(Intent.ACTION_VIEW, 7590 Uri.parse("https://support.google.com/nexus/answer/2852139")), 0); 7591 7592 String title = mContext.getString(R.string.audit_safemode_notification); 7593 7594 Notification notification = new Notification.Builder(mContext) 7595 .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning) 7596 .setWhen(0) 7597 .setOngoing(true) 7598 .setTicker(title) 7599 .setLocalOnly(true) 7600 .setPriority(Notification.PRIORITY_HIGH) 7601 .setVisibility(Notification.VISIBILITY_PUBLIC) 7602 .setColor(mContext.getColor( 7603 com.android.internal.R.color.system_notification_accent_color)) 7604 .setContentTitle(title) 7605 .setContentText(mContext.getString(R.string.audit_safemode_notification_details)) 7606 .setContentIntent(pendingIntent) 7607 .build(); 7608 7609 NotificationManager notificationManager = (NotificationManager) mContext 7610 .getSystemService(Context.NOTIFICATION_SERVICE); 7611 7612 notificationManager.notifyAsUser(null, R.string.audit_safemode_notification, notification, 7613 UserHandle.ALL); 7614 } 7615 7616 public boolean detectSafeMode() { 7617 if (!mInputMonitor.waitForInputDevicesReady( 7618 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7619 Slog.w(TAG_WM, "Devices still not ready after waiting " 7620 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7621 + " milliseconds before attempting to detect safe mode."); 7622 } 7623 7624 if (Settings.Global.getInt( 7625 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) { 7626 return false; 7627 } 7628 7629 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7630 KeyEvent.KEYCODE_MENU); 7631 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7632 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7633 KeyEvent.KEYCODE_DPAD_CENTER); 7634 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7635 InputManagerService.BTN_MOUSE); 7636 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7637 KeyEvent.KEYCODE_VOLUME_DOWN); 7638 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7639 || volumeDownState > 0; 7640 try { 7641 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0 7642 || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) { 7643 int auditSafeMode = SystemProperties.getInt(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, 0); 7644 7645 if (auditSafeMode == 0) { 7646 mSafeMode = true; 7647 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7648 } else { 7649 // stay in safe mode until we have updated to a newer build 7650 int buildDate = SystemProperties.getInt(PROPERTY_BUILD_DATE_UTC, 0); 7651 7652 if (auditSafeMode >= buildDate) { 7653 mSafeMode = true; 7654 showAuditSafeModeNotification(); 7655 } else { 7656 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7657 SystemProperties.set(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, ""); 7658 } 7659 } 7660 } 7661 } catch (IllegalArgumentException e) { 7662 } 7663 if (mSafeMode) { 7664 Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7665 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7666 SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1"); 7667 } else { 7668 Log.i(TAG_WM, "SAFE MODE not enabled"); 7669 } 7670 mPolicy.setSafeMode(mSafeMode); 7671 return mSafeMode; 7672 } 7673 7674 public void displayReady() { 7675 for (Display display : mDisplays) { 7676 displayReady(display.getDisplayId()); 7677 } 7678 7679 synchronized(mWindowMap) { 7680 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7681 readForcedDisplayPropertiesLocked(displayContent); 7682 mDisplayReady = true; 7683 } 7684 7685 try { 7686 mActivityManager.updateConfiguration(null); 7687 } catch (RemoteException e) { 7688 } 7689 7690 synchronized(mWindowMap) { 7691 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7692 PackageManager.FEATURE_TOUCHSCREEN); 7693 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7694 } 7695 7696 try { 7697 mActivityManager.updateConfiguration(null); 7698 } catch (RemoteException e) { 7699 } 7700 7701 updateCircularDisplayMaskIfNeeded(); 7702 } 7703 7704 private void displayReady(int displayId) { 7705 synchronized(mWindowMap) { 7706 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7707 if (displayContent != null) { 7708 mAnimator.addDisplayLocked(displayId); 7709 displayContent.initializeDisplayBaseInfo(); 7710 if (displayContent.mTapDetector != null) { 7711 displayContent.mTapDetector.init(); 7712 } 7713 } 7714 } 7715 } 7716 7717 public void systemReady() { 7718 mPolicy.systemReady(); 7719 } 7720 7721 // ------------------------------------------------------------- 7722 // Async Handler 7723 // ------------------------------------------------------------- 7724 7725 final class H extends Handler { 7726 public static final int REPORT_FOCUS_CHANGE = 2; 7727 public static final int REPORT_LOSING_FOCUS = 3; 7728 public static final int DO_TRAVERSAL = 4; 7729 public static final int ADD_STARTING = 5; 7730 public static final int REMOVE_STARTING = 6; 7731 public static final int FINISHED_STARTING = 7; 7732 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7733 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7734 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7735 7736 public static final int APP_TRANSITION_TIMEOUT = 13; 7737 public static final int PERSIST_ANIMATION_SCALE = 14; 7738 public static final int FORCE_GC = 15; 7739 public static final int ENABLE_SCREEN = 16; 7740 public static final int APP_FREEZE_TIMEOUT = 17; 7741 public static final int SEND_NEW_CONFIGURATION = 18; 7742 public static final int REPORT_WINDOWS_CHANGE = 19; 7743 public static final int DRAG_START_TIMEOUT = 20; 7744 public static final int DRAG_END_TIMEOUT = 21; 7745 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7746 public static final int BOOT_TIMEOUT = 23; 7747 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7748 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7749 public static final int DO_ANIMATION_CALLBACK = 26; 7750 7751 public static final int DO_DISPLAY_ADDED = 27; 7752 public static final int DO_DISPLAY_REMOVED = 28; 7753 public static final int DO_DISPLAY_CHANGED = 29; 7754 7755 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7756 public static final int TAP_OUTSIDE_TASK = 31; 7757 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7758 7759 public static final int ALL_WINDOWS_DRAWN = 33; 7760 7761 public static final int NEW_ANIMATOR_SCALE = 34; 7762 7763 public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35; 7764 public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36; 7765 7766 public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37; 7767 public static final int RESET_ANR_MESSAGE = 38; 7768 public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39; 7769 7770 public static final int FINISH_TASK_POSITIONING = 40; 7771 7772 public static final int UPDATE_DOCKED_STACK_DIVIDER = 41; 7773 7774 public static final int RESIZE_STACK = 42; 7775 public static final int RESIZE_TASK = 43; 7776 7777 public static final int TWO_FINGER_SCROLL_START = 44; 7778 7779 public static final int WINDOW_REPLACEMENT_TIMEOUT = 46; 7780 7781 public static final int NOTIFY_APP_TRANSITION_STARTING = 47; 7782 public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48; 7783 public static final int NOTIFY_APP_TRANSITION_FINISHED = 49; 7784 public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50; 7785 7786 public static final int UPDATE_ANIMATION_SCALE = 51; 7787 7788 /** 7789 * Used to denote that an integer field in a message will not be used. 7790 */ 7791 public static final int UNUSED = 0; 7792 7793 @Override 7794 public void handleMessage(Message msg) { 7795 if (DEBUG_WINDOW_TRACE) { 7796 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what); 7797 } 7798 switch (msg.what) { 7799 case REPORT_FOCUS_CHANGE: { 7800 WindowState lastFocus; 7801 WindowState newFocus; 7802 7803 AccessibilityController accessibilityController = null; 7804 7805 synchronized(mWindowMap) { 7806 // TODO(multidisplay): Accessibility supported only of default desiplay. 7807 if (mAccessibilityController != null && getDefaultDisplayContentLocked() 7808 .getDisplayId() == Display.DEFAULT_DISPLAY) { 7809 accessibilityController = mAccessibilityController; 7810 } 7811 7812 lastFocus = mLastFocus; 7813 newFocus = mCurrentFocus; 7814 if (lastFocus == newFocus) { 7815 // Focus is not changing, so nothing to do. 7816 return; 7817 } 7818 mLastFocus = newFocus; 7819 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus + 7820 " to " + newFocus); 7821 if (newFocus != null && lastFocus != null 7822 && !newFocus.isDisplayedLw()) { 7823 //Slog.i(TAG_WM, "Delaying loss of focus..."); 7824 mLosingFocus.add(lastFocus); 7825 lastFocus = null; 7826 } 7827 } 7828 7829 // First notify the accessibility manager for the change so it has 7830 // the windows before the newly focused one starts firing eventgs. 7831 if (accessibilityController != null) { 7832 accessibilityController.onWindowFocusChangedNotLocked(); 7833 } 7834 7835 //System.out.println("Changing focus from " + lastFocus 7836 // + " to " + newFocus); 7837 if (newFocus != null) { 7838 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus); 7839 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7840 notifyFocusChanged(); 7841 } 7842 7843 if (lastFocus != null) { 7844 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus); 7845 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7846 } 7847 } break; 7848 7849 case REPORT_LOSING_FOCUS: { 7850 ArrayList<WindowState> losers; 7851 7852 synchronized(mWindowMap) { 7853 losers = mLosingFocus; 7854 mLosingFocus = new ArrayList<WindowState>(); 7855 } 7856 7857 final int N = losers.size(); 7858 for (int i=0; i<N; i++) { 7859 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " + 7860 losers.get(i)); 7861 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7862 } 7863 } break; 7864 7865 case DO_TRAVERSAL: { 7866 synchronized(mWindowMap) { 7867 mWindowPlacerLocked.performSurfacePlacement(); 7868 } 7869 } break; 7870 7871 case ADD_STARTING: { 7872 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7873 final StartingData sd = wtoken.startingData; 7874 7875 if (sd == null) { 7876 // Animation has been canceled... do nothing. 7877 return; 7878 } 7879 7880 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting " 7881 + wtoken + ": pkg=" + sd.pkg); 7882 7883 View view = null; 7884 try { 7885 view = mPolicy.addStartingWindow( 7886 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7887 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7888 } catch (Exception e) { 7889 Slog.w(TAG_WM, "Exception when adding starting window", e); 7890 } 7891 7892 if (view != null) { 7893 boolean abort = false; 7894 7895 synchronized(mWindowMap) { 7896 if (wtoken.removed || wtoken.startingData == null) { 7897 // If the window was successfully added, then 7898 // we need to remove it. 7899 if (wtoken.startingWindow != null) { 7900 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, 7901 "Aborted starting " + wtoken 7902 + ": removed=" + wtoken.removed 7903 + " startingData=" + wtoken.startingData); 7904 wtoken.startingWindow = null; 7905 wtoken.startingData = null; 7906 abort = true; 7907 } 7908 } else { 7909 wtoken.startingView = view; 7910 } 7911 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM, 7912 "Added starting " + wtoken 7913 + ": startingWindow=" 7914 + wtoken.startingWindow + " startingView=" 7915 + wtoken.startingView); 7916 } 7917 7918 if (abort) { 7919 try { 7920 mPolicy.removeStartingWindow(wtoken.token, view); 7921 } catch (Exception e) { 7922 Slog.w(TAG_WM, "Exception when removing starting window", e); 7923 } 7924 } 7925 } 7926 } break; 7927 7928 case REMOVE_STARTING: { 7929 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7930 IBinder token = null; 7931 View view = null; 7932 synchronized (mWindowMap) { 7933 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting " 7934 + wtoken + ": startingWindow=" 7935 + wtoken.startingWindow + " startingView=" 7936 + wtoken.startingView); 7937 if (wtoken.startingWindow != null) { 7938 view = wtoken.startingView; 7939 token = wtoken.token; 7940 wtoken.startingData = null; 7941 wtoken.startingView = null; 7942 wtoken.startingWindow = null; 7943 wtoken.startingDisplayed = false; 7944 } 7945 } 7946 if (view != null) { 7947 try { 7948 mPolicy.removeStartingWindow(token, view); 7949 } catch (Exception e) { 7950 Slog.w(TAG_WM, "Exception when removing starting window", e); 7951 } 7952 } 7953 } break; 7954 7955 case FINISHED_STARTING: { 7956 IBinder token = null; 7957 View view = null; 7958 while (true) { 7959 synchronized (mWindowMap) { 7960 final int N = mFinishedStarting.size(); 7961 if (N <= 0) { 7962 break; 7963 } 7964 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7965 7966 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, 7967 "Finished starting " + wtoken 7968 + ": startingWindow=" + wtoken.startingWindow 7969 + " startingView=" + wtoken.startingView); 7970 7971 if (wtoken.startingWindow == null) { 7972 continue; 7973 } 7974 7975 view = wtoken.startingView; 7976 token = wtoken.token; 7977 wtoken.startingData = null; 7978 wtoken.startingView = null; 7979 wtoken.startingWindow = null; 7980 wtoken.startingDisplayed = false; 7981 } 7982 7983 try { 7984 mPolicy.removeStartingWindow(token, view); 7985 } catch (Exception e) { 7986 Slog.w(TAG_WM, "Exception when removing starting window", e); 7987 } 7988 } 7989 } break; 7990 7991 case REPORT_APPLICATION_TOKEN_DRAWN: { 7992 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7993 7994 try { 7995 if (DEBUG_VISIBILITY) Slog.v( 7996 TAG_WM, "Reporting drawn in " + wtoken); 7997 wtoken.appToken.windowsDrawn(); 7998 } catch (RemoteException ex) { 7999 } 8000 } break; 8001 8002 case REPORT_APPLICATION_TOKEN_WINDOWS: { 8003 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 8004 8005 boolean nowVisible = msg.arg1 != 0; 8006 boolean nowGone = msg.arg2 != 0; 8007 8008 try { 8009 if (DEBUG_VISIBILITY) Slog.v( 8010 TAG_WM, "Reporting visible in " + wtoken 8011 + " visible=" + nowVisible 8012 + " gone=" + nowGone); 8013 if (nowVisible) { 8014 wtoken.appToken.windowsVisible(); 8015 } else { 8016 wtoken.appToken.windowsGone(); 8017 } 8018 } catch (RemoteException ex) { 8019 } 8020 } break; 8021 8022 case WINDOW_FREEZE_TIMEOUT: { 8023 // TODO(multidisplay): Can non-default displays rotate? 8024 synchronized (mWindowMap) { 8025 Slog.w(TAG_WM, "Window freeze timeout expired."); 8026 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 8027 final WindowList windows = getDefaultWindowListLocked(); 8028 int i = windows.size(); 8029 while (i > 0) { 8030 i--; 8031 WindowState w = windows.get(i); 8032 if (w.mOrientationChanging) { 8033 w.mOrientationChanging = false; 8034 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8035 - mDisplayFreezeTime); 8036 Slog.w(TAG_WM, "Force clearing orientation change: " + w); 8037 } 8038 } 8039 mWindowPlacerLocked.performSurfacePlacement(); 8040 } 8041 break; 8042 } 8043 8044 case APP_TRANSITION_TIMEOUT: { 8045 synchronized (mWindowMap) { 8046 if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty() 8047 || !mClosingApps.isEmpty()) { 8048 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT." 8049 + " isTransitionSet()=" + mAppTransition.isTransitionSet() 8050 + " mOpeningApps.size()=" + mOpeningApps.size() 8051 + " mClosingApps.size()=" + mClosingApps.size()); 8052 mAppTransition.setTimeout(); 8053 mWindowPlacerLocked.performSurfacePlacement(); 8054 } 8055 } 8056 break; 8057 } 8058 8059 case PERSIST_ANIMATION_SCALE: { 8060 Settings.Global.putFloat(mContext.getContentResolver(), 8061 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 8062 Settings.Global.putFloat(mContext.getContentResolver(), 8063 Settings.Global.TRANSITION_ANIMATION_SCALE, 8064 mTransitionAnimationScaleSetting); 8065 Settings.Global.putFloat(mContext.getContentResolver(), 8066 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 8067 break; 8068 } 8069 8070 case UPDATE_ANIMATION_SCALE: { 8071 @UpdateAnimationScaleMode 8072 final int mode = msg.arg1; 8073 switch (mode) { 8074 case WINDOW_ANIMATION_SCALE: { 8075 mWindowAnimationScaleSetting = Settings.Global.getFloat( 8076 mContext.getContentResolver(), 8077 Settings.Global.WINDOW_ANIMATION_SCALE, 8078 mWindowAnimationScaleSetting); 8079 break; 8080 } 8081 case TRANSITION_ANIMATION_SCALE: { 8082 mTransitionAnimationScaleSetting = Settings.Global.getFloat( 8083 mContext.getContentResolver(), 8084 Settings.Global.TRANSITION_ANIMATION_SCALE, 8085 mTransitionAnimationScaleSetting); 8086 break; 8087 } 8088 case ANIMATION_DURATION_SCALE: { 8089 mAnimatorDurationScaleSetting = Settings.Global.getFloat( 8090 mContext.getContentResolver(), 8091 Settings.Global.ANIMATOR_DURATION_SCALE, 8092 mAnimatorDurationScaleSetting); 8093 dispatchNewAnimatorScaleLocked(null); 8094 break; 8095 } 8096 } 8097 break; 8098 } 8099 8100 case FORCE_GC: { 8101 synchronized (mWindowMap) { 8102 // Since we're holding both mWindowMap and mAnimator we don't need to 8103 // hold mAnimator.mLayoutToAnim. 8104 if (mAnimator.isAnimating() || mAnimationScheduled) { 8105 // If we are animating, don't do the gc now but 8106 // delay a bit so we don't interrupt the animation. 8107 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 8108 return; 8109 } 8110 // If we are currently rotating the display, it will 8111 // schedule a new message when done. 8112 if (mDisplayFrozen) { 8113 return; 8114 } 8115 } 8116 Runtime.getRuntime().gc(); 8117 break; 8118 } 8119 8120 case ENABLE_SCREEN: { 8121 performEnableScreen(); 8122 break; 8123 } 8124 8125 case APP_FREEZE_TIMEOUT: { 8126 synchronized (mWindowMap) { 8127 Slog.w(TAG_WM, "App freeze timeout expired."); 8128 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 8129 final int numStacks = mStackIdToStack.size(); 8130 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8131 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 8132 final ArrayList<Task> tasks = stack.getTasks(); 8133 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8134 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8135 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8136 AppWindowToken tok = tokens.get(tokenNdx); 8137 if (tok.mAppAnimator.freezingScreen) { 8138 Slog.w(TAG_WM, "Force clearing freeze: " + tok); 8139 unsetAppFreezingScreenLocked(tok, true, true); 8140 } 8141 } 8142 } 8143 } 8144 } 8145 break; 8146 } 8147 8148 case CLIENT_FREEZE_TIMEOUT: { 8149 synchronized (mWindowMap) { 8150 if (mClientFreezingScreen) { 8151 mClientFreezingScreen = false; 8152 mLastFinishedFreezeSource = "client-timeout"; 8153 stopFreezingDisplayLocked(); 8154 } 8155 } 8156 break; 8157 } 8158 8159 case SEND_NEW_CONFIGURATION: { 8160 removeMessages(SEND_NEW_CONFIGURATION); 8161 sendNewConfiguration(); 8162 break; 8163 } 8164 8165 case REPORT_WINDOWS_CHANGE: { 8166 if (mWindowsChanged) { 8167 synchronized (mWindowMap) { 8168 mWindowsChanged = false; 8169 } 8170 notifyWindowsChanged(); 8171 } 8172 break; 8173 } 8174 8175 case DRAG_START_TIMEOUT: { 8176 IBinder win = (IBinder)msg.obj; 8177 if (DEBUG_DRAG) { 8178 Slog.w(TAG_WM, "Timeout starting drag by win " + win); 8179 } 8180 synchronized (mWindowMap) { 8181 // !!! TODO: ANR the app that has failed to start the drag in time 8182 if (mDragState != null) { 8183 mDragState.unregister(); 8184 mInputMonitor.updateInputWindowsLw(true /*force*/); 8185 mDragState.reset(); 8186 mDragState = null; 8187 } 8188 } 8189 break; 8190 } 8191 8192 case DRAG_END_TIMEOUT: { 8193 IBinder win = (IBinder)msg.obj; 8194 if (DEBUG_DRAG) { 8195 Slog.w(TAG_WM, "Timeout ending drag to win " + win); 8196 } 8197 synchronized (mWindowMap) { 8198 // !!! TODO: ANR the drag-receiving app 8199 if (mDragState != null) { 8200 mDragState.mDragResult = false; 8201 mDragState.endDragLw(); 8202 } 8203 } 8204 break; 8205 } 8206 8207 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 8208 notifyHardKeyboardStatusChange(); 8209 break; 8210 } 8211 8212 case BOOT_TIMEOUT: { 8213 performBootTimeout(); 8214 break; 8215 } 8216 8217 case WAITING_FOR_DRAWN_TIMEOUT: { 8218 Runnable callback = null; 8219 synchronized (mWindowMap) { 8220 Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 8221 mWaitingForDrawn.clear(); 8222 callback = mWaitingForDrawnCallback; 8223 mWaitingForDrawnCallback = null; 8224 } 8225 if (callback != null) { 8226 callback.run(); 8227 } 8228 break; 8229 } 8230 8231 case SHOW_STRICT_MODE_VIOLATION: { 8232 showStrictModeViolation(msg.arg1, msg.arg2); 8233 break; 8234 } 8235 8236 case SHOW_CIRCULAR_DISPLAY_MASK: { 8237 showCircularMask(msg.arg1 == 1); 8238 break; 8239 } 8240 8241 case SHOW_EMULATOR_DISPLAY_OVERLAY: { 8242 showEmulatorDisplayOverlay(); 8243 break; 8244 } 8245 8246 case DO_ANIMATION_CALLBACK: { 8247 try { 8248 ((IRemoteCallback)msg.obj).sendResult(null); 8249 } catch (RemoteException e) { 8250 } 8251 break; 8252 } 8253 8254 case DO_DISPLAY_ADDED: 8255 handleDisplayAdded(msg.arg1); 8256 break; 8257 8258 case DO_DISPLAY_REMOVED: 8259 synchronized (mWindowMap) { 8260 handleDisplayRemovedLocked(msg.arg1); 8261 } 8262 break; 8263 8264 case DO_DISPLAY_CHANGED: 8265 synchronized (mWindowMap) { 8266 handleDisplayChangedLocked(msg.arg1); 8267 } 8268 break; 8269 8270 case TWO_FINGER_SCROLL_START: { 8271 startScrollingTask((DisplayContent)msg.obj, msg.arg1, msg.arg2); 8272 } 8273 break; 8274 8275 case TAP_OUTSIDE_TASK: { 8276 handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2); 8277 } 8278 break; 8279 8280 case FINISH_TASK_POSITIONING: { 8281 finishPositioning(); 8282 } 8283 break; 8284 8285 case NOTIFY_ACTIVITY_DRAWN: 8286 try { 8287 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 8288 } catch (RemoteException e) { 8289 } 8290 break; 8291 case ALL_WINDOWS_DRAWN: { 8292 Runnable callback; 8293 synchronized (mWindowMap) { 8294 callback = mWaitingForDrawnCallback; 8295 mWaitingForDrawnCallback = null; 8296 } 8297 if (callback != null) { 8298 callback.run(); 8299 } 8300 } 8301 case NEW_ANIMATOR_SCALE: { 8302 float scale = getCurrentAnimatorScale(); 8303 ValueAnimator.setDurationScale(scale); 8304 Session session = (Session)msg.obj; 8305 if (session != null) { 8306 try { 8307 session.mCallback.onAnimatorScaleChanged(scale); 8308 } catch (RemoteException e) { 8309 } 8310 } else { 8311 ArrayList<IWindowSessionCallback> callbacks 8312 = new ArrayList<IWindowSessionCallback>(); 8313 synchronized (mWindowMap) { 8314 for (int i=0; i<mSessions.size(); i++) { 8315 callbacks.add(mSessions.valueAt(i).mCallback); 8316 } 8317 8318 } 8319 for (int i=0; i<callbacks.size(); i++) { 8320 try { 8321 callbacks.get(i).onAnimatorScaleChanged(scale); 8322 } catch (RemoteException e) { 8323 } 8324 } 8325 } 8326 } 8327 break; 8328 case CHECK_IF_BOOT_ANIMATION_FINISHED: { 8329 final boolean bootAnimationComplete; 8330 synchronized (mWindowMap) { 8331 if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:"); 8332 bootAnimationComplete = checkBootAnimationCompleteLocked(); 8333 } 8334 if (bootAnimationComplete) { 8335 performEnableScreen(); 8336 } 8337 } 8338 break; 8339 case RESET_ANR_MESSAGE: { 8340 synchronized (mWindowMap) { 8341 mLastANRState = null; 8342 } 8343 } 8344 break; 8345 case WALLPAPER_DRAW_PENDING_TIMEOUT: { 8346 synchronized (mWindowMap) { 8347 if (mWallpaperControllerLocked.processWallpaperDrawPendingTimeout()) { 8348 mWindowPlacerLocked.performSurfacePlacement(); 8349 } 8350 } 8351 } 8352 case UPDATE_DOCKED_STACK_DIVIDER: { 8353 synchronized (mWindowMap) { 8354 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8355 displayContent.getDockedDividerController().reevaluateVisibility(false); 8356 adjustForImeIfNeeded(displayContent); 8357 } 8358 } 8359 break; 8360 case RESIZE_TASK: { 8361 try { 8362 mActivityManager.resizeTask(msg.arg1, (Rect) msg.obj, msg.arg2); 8363 } catch (RemoteException e) { 8364 // This will not happen since we are in the same process. 8365 } 8366 } 8367 break; 8368 case RESIZE_STACK: { 8369 try { 8370 mActivityManager.resizeStack( 8371 msg.arg1, (Rect) msg.obj, msg.arg2 == 1, false, false, -1); 8372 } catch (RemoteException e) { 8373 // This will not happen since we are in the same process. 8374 } 8375 } 8376 break; 8377 case WINDOW_REPLACEMENT_TIMEOUT: { 8378 final AppWindowToken token = (AppWindowToken) msg.obj; 8379 synchronized (mWindowMap) { 8380 token.clearTimedoutReplacesLocked(); 8381 } 8382 } 8383 case NOTIFY_APP_TRANSITION_STARTING: { 8384 mAmInternal.notifyAppTransitionStarting(msg.arg1); 8385 } 8386 break; 8387 case NOTIFY_APP_TRANSITION_CANCELLED: { 8388 mAmInternal.notifyAppTransitionCancelled(); 8389 } 8390 break; 8391 case NOTIFY_APP_TRANSITION_FINISHED: { 8392 mAmInternal.notifyAppTransitionFinished(); 8393 } 8394 break; 8395 case NOTIFY_STARTING_WINDOW_DRAWN: { 8396 mAmInternal.notifyStartingWindowDrawn(); 8397 } 8398 break; 8399 } 8400 if (DEBUG_WINDOW_TRACE) { 8401 Slog.v(TAG_WM, "handleMessage: exit"); 8402 } 8403 } 8404 } 8405 8406 void destroyPreservedSurfaceLocked() { 8407 for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) { 8408 final WindowState w = mDestroyPreservedSurface.get(i); 8409 w.mWinAnimator.destroyPreservedSurfaceLocked(); 8410 } 8411 mDestroyPreservedSurface.clear(); 8412 } 8413 // ------------------------------------------------------------- 8414 // IWindowManager API 8415 // ------------------------------------------------------------- 8416 8417 @Override 8418 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 8419 IInputContext inputContext) { 8420 if (client == null) throw new IllegalArgumentException("null client"); 8421 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 8422 Session session = new Session(this, callback, client, inputContext); 8423 return session; 8424 } 8425 8426 @Override 8427 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 8428 synchronized (mWindowMap) { 8429 // The focus for the client is the window immediately below 8430 // where we would place the input method window. 8431 int idx = findDesiredInputMethodWindowIndexLocked(false); 8432 if (idx > 0) { 8433 // TODO(multidisplay): IMEs are only supported on the default display. 8434 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 8435 if (DEBUG_INPUT_METHOD) { 8436 Slog.i(TAG_WM, "Desired input method target: " + imFocus); 8437 Slog.i(TAG_WM, "Current focus: " + mCurrentFocus); 8438 Slog.i(TAG_WM, "Last focus: " + mLastFocus); 8439 } 8440 if (imFocus != null) { 8441 // This may be a starting window, in which case we still want 8442 // to count it as okay. 8443 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 8444 && imFocus.mAppToken != null) { 8445 // The client has definitely started, so it really should 8446 // have a window in this app token. Let's look for it. 8447 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 8448 WindowState w = imFocus.mAppToken.windows.get(i); 8449 if (w != imFocus) { 8450 Log.i(TAG_WM, "Switching to real app window: " + w); 8451 imFocus = w; 8452 break; 8453 } 8454 } 8455 } 8456 if (DEBUG_INPUT_METHOD) { 8457 Slog.i(TAG_WM, "IM target client: " + imFocus.mSession.mClient); 8458 if (imFocus.mSession.mClient != null) { 8459 Slog.i(TAG_WM, "IM target client binder: " 8460 + imFocus.mSession.mClient.asBinder()); 8461 Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder()); 8462 } 8463 } 8464 if (imFocus.mSession.mClient != null && 8465 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 8466 return true; 8467 } 8468 } 8469 } 8470 8471 // Okay, how about this... what is the current focus? 8472 // It seems in some cases we may not have moved the IM 8473 // target window, such as when it was in a pop-up window, 8474 // so let's also look at the current focus. (An example: 8475 // go to Gmail, start searching so the keyboard goes up, 8476 // press home. Sometimes the IME won't go down.) 8477 // Would be nice to fix this more correctly, but it's 8478 // way at the end of a release, and this should be good enough. 8479 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 8480 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 8481 return true; 8482 } 8483 } 8484 return false; 8485 } 8486 8487 @Override 8488 public void getInitialDisplaySize(int displayId, Point size) { 8489 synchronized (mWindowMap) { 8490 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8491 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8492 size.x = displayContent.mInitialDisplayWidth; 8493 size.y = displayContent.mInitialDisplayHeight; 8494 } 8495 } 8496 } 8497 8498 @Override 8499 public void getBaseDisplaySize(int displayId, Point size) { 8500 synchronized (mWindowMap) { 8501 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8502 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8503 size.x = displayContent.mBaseDisplayWidth; 8504 size.y = displayContent.mBaseDisplayHeight; 8505 } 8506 } 8507 } 8508 8509 @Override 8510 public void setForcedDisplaySize(int displayId, int width, int height) { 8511 if (mContext.checkCallingOrSelfPermission( 8512 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8513 PackageManager.PERMISSION_GRANTED) { 8514 throw new SecurityException("Must hold permission " + 8515 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8516 } 8517 if (displayId != Display.DEFAULT_DISPLAY) { 8518 throw new IllegalArgumentException("Can only set the default display"); 8519 } 8520 final long ident = Binder.clearCallingIdentity(); 8521 try { 8522 synchronized(mWindowMap) { 8523 // Set some sort of reasonable bounds on the size of the display that we 8524 // will try to emulate. 8525 final int MIN_WIDTH = 200; 8526 final int MIN_HEIGHT = 200; 8527 final int MAX_SCALE = 2; 8528 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8529 if (displayContent != null) { 8530 width = Math.min(Math.max(width, MIN_WIDTH), 8531 displayContent.mInitialDisplayWidth * MAX_SCALE); 8532 height = Math.min(Math.max(height, MIN_HEIGHT), 8533 displayContent.mInitialDisplayHeight * MAX_SCALE); 8534 setForcedDisplaySizeLocked(displayContent, width, height); 8535 Settings.Global.putString(mContext.getContentResolver(), 8536 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 8537 } 8538 } 8539 } finally { 8540 Binder.restoreCallingIdentity(ident); 8541 } 8542 } 8543 8544 @Override 8545 public void setForcedDisplayScalingMode(int displayId, int mode) { 8546 if (mContext.checkCallingOrSelfPermission( 8547 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8548 PackageManager.PERMISSION_GRANTED) { 8549 throw new SecurityException("Must hold permission " + 8550 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8551 } 8552 if (displayId != Display.DEFAULT_DISPLAY) { 8553 throw new IllegalArgumentException("Can only set the default display"); 8554 } 8555 final long ident = Binder.clearCallingIdentity(); 8556 try { 8557 synchronized(mWindowMap) { 8558 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8559 if (displayContent != null) { 8560 if (mode < 0 || mode > 1) { 8561 mode = 0; 8562 } 8563 setForcedDisplayScalingModeLocked(displayContent, mode); 8564 Settings.Global.putInt(mContext.getContentResolver(), 8565 Settings.Global.DISPLAY_SCALING_FORCE, mode); 8566 } 8567 } 8568 } finally { 8569 Binder.restoreCallingIdentity(ident); 8570 } 8571 } 8572 8573 private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) { 8574 Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off")); 8575 displayContent.mDisplayScalingDisabled = (mode != 0); 8576 reconfigureDisplayLocked(displayContent); 8577 } 8578 8579 private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) { 8580 // Display size. 8581 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 8582 Settings.Global.DISPLAY_SIZE_FORCED); 8583 if (sizeStr == null || sizeStr.length() == 0) { 8584 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 8585 } 8586 if (sizeStr != null && sizeStr.length() > 0) { 8587 final int pos = sizeStr.indexOf(','); 8588 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 8589 int width, height; 8590 try { 8591 width = Integer.parseInt(sizeStr.substring(0, pos)); 8592 height = Integer.parseInt(sizeStr.substring(pos+1)); 8593 if (displayContent.mBaseDisplayWidth != width 8594 || displayContent.mBaseDisplayHeight != height) { 8595 Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height); 8596 displayContent.mBaseDisplayWidth = width; 8597 displayContent.mBaseDisplayHeight = height; 8598 } 8599 } catch (NumberFormatException ex) { 8600 } 8601 } 8602 } 8603 8604 // Display density. 8605 final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId); 8606 if (density != 0) { 8607 displayContent.mBaseDisplayDensity = density; 8608 } 8609 8610 // Display scaling mode. 8611 int mode = Settings.Global.getInt(mContext.getContentResolver(), 8612 Settings.Global.DISPLAY_SCALING_FORCE, 0); 8613 if (mode != 0) { 8614 Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED"); 8615 displayContent.mDisplayScalingDisabled = true; 8616 } 8617 } 8618 8619 // displayContent must not be null 8620 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 8621 Slog.i(TAG_WM, "Using new display size: " + width + "x" + height); 8622 displayContent.mBaseDisplayWidth = width; 8623 displayContent.mBaseDisplayHeight = height; 8624 reconfigureDisplayLocked(displayContent); 8625 } 8626 8627 @Override 8628 public void clearForcedDisplaySize(int displayId) { 8629 if (mContext.checkCallingOrSelfPermission( 8630 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8631 PackageManager.PERMISSION_GRANTED) { 8632 throw new SecurityException("Must hold permission " + 8633 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8634 } 8635 if (displayId != Display.DEFAULT_DISPLAY) { 8636 throw new IllegalArgumentException("Can only set the default display"); 8637 } 8638 final long ident = Binder.clearCallingIdentity(); 8639 try { 8640 synchronized(mWindowMap) { 8641 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8642 if (displayContent != null) { 8643 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 8644 displayContent.mInitialDisplayHeight); 8645 Settings.Global.putString(mContext.getContentResolver(), 8646 Settings.Global.DISPLAY_SIZE_FORCED, ""); 8647 } 8648 } 8649 } finally { 8650 Binder.restoreCallingIdentity(ident); 8651 } 8652 } 8653 8654 @Override 8655 public int getInitialDisplayDensity(int displayId) { 8656 synchronized (mWindowMap) { 8657 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8658 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8659 return displayContent.mInitialDisplayDensity; 8660 } 8661 } 8662 return -1; 8663 } 8664 8665 @Override 8666 public int getBaseDisplayDensity(int displayId) { 8667 synchronized (mWindowMap) { 8668 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8669 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8670 return displayContent.mBaseDisplayDensity; 8671 } 8672 } 8673 return -1; 8674 } 8675 8676 @Override 8677 public void setForcedDisplayDensity(int displayId, int density) { 8678 if (mContext.checkCallingOrSelfPermission( 8679 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8680 PackageManager.PERMISSION_GRANTED) { 8681 throw new SecurityException("Must hold permission " + 8682 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8683 } 8684 if (displayId != Display.DEFAULT_DISPLAY) { 8685 throw new IllegalArgumentException("Can only set the default display"); 8686 } 8687 final long ident = Binder.clearCallingIdentity(); 8688 try { 8689 synchronized(mWindowMap) { 8690 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8691 if (displayContent != null) { 8692 setForcedDisplayDensityLocked(displayContent, density); 8693 Settings.Secure.putStringForUser(mContext.getContentResolver(), 8694 Settings.Secure.DISPLAY_DENSITY_FORCED, 8695 Integer.toString(density), mCurrentUserId); 8696 } 8697 } 8698 } finally { 8699 Binder.restoreCallingIdentity(ident); 8700 } 8701 } 8702 8703 @Override 8704 public void clearForcedDisplayDensity(int displayId) { 8705 if (mContext.checkCallingOrSelfPermission( 8706 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8707 PackageManager.PERMISSION_GRANTED) { 8708 throw new SecurityException("Must hold permission " + 8709 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8710 } 8711 if (displayId != Display.DEFAULT_DISPLAY) { 8712 throw new IllegalArgumentException("Can only set the default display"); 8713 } 8714 final long ident = Binder.clearCallingIdentity(); 8715 try { 8716 synchronized(mWindowMap) { 8717 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8718 if (displayContent != null) { 8719 setForcedDisplayDensityLocked(displayContent, 8720 displayContent.mInitialDisplayDensity); 8721 Settings.Secure.putStringForUser(mContext.getContentResolver(), 8722 Settings.Secure.DISPLAY_DENSITY_FORCED, "", mCurrentUserId); 8723 } 8724 } 8725 } finally { 8726 Binder.restoreCallingIdentity(ident); 8727 } 8728 } 8729 8730 /** 8731 * @param userId the ID of the user 8732 * @return the forced display density for the specified user, if set, or 8733 * {@code 0} if not set 8734 */ 8735 private int getForcedDisplayDensityForUserLocked(int userId) { 8736 String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(), 8737 Settings.Secure.DISPLAY_DENSITY_FORCED, userId); 8738 if (densityStr == null || densityStr.length() == 0) { 8739 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 8740 } 8741 if (densityStr != null && densityStr.length() > 0) { 8742 try { 8743 return Integer.parseInt(densityStr); 8744 } catch (NumberFormatException ex) { 8745 } 8746 } 8747 return 0; 8748 } 8749 8750 /** 8751 * Forces the given display to the use the specified density. 8752 * 8753 * @param displayContent the display to modify 8754 * @param density the density in DPI to use 8755 */ 8756 private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent, 8757 int density) { 8758 displayContent.mBaseDisplayDensity = density; 8759 reconfigureDisplayLocked(displayContent); 8760 } 8761 8762 // displayContent must not be null 8763 private void reconfigureDisplayLocked(DisplayContent displayContent) { 8764 // TODO: Multidisplay: for now only use with default display. 8765 if (!mDisplayReady) { 8766 return; 8767 } 8768 configureDisplayPolicyLocked(displayContent); 8769 displayContent.layoutNeeded = true; 8770 8771 boolean configChanged = updateOrientationFromAppTokensLocked(false); 8772 mTempConfiguration.setToDefaults(); 8773 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 8774 mTempConfiguration.uiMode = mCurConfiguration.uiMode; 8775 computeScreenConfigurationLocked(mTempConfiguration); 8776 configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0; 8777 8778 if (configChanged) { 8779 mWaitingForConfig = true; 8780 startFreezingDisplayLocked(false, 0, 0); 8781 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8782 } 8783 8784 mWindowPlacerLocked.performSurfacePlacement(); 8785 } 8786 8787 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8788 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8789 displayContent.mBaseDisplayWidth, 8790 displayContent.mBaseDisplayHeight, 8791 displayContent.mBaseDisplayDensity); 8792 8793 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8794 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8795 displayInfo.overscanLeft, displayInfo.overscanTop, 8796 displayInfo.overscanRight, displayInfo.overscanBottom); 8797 } 8798 8799 @Override 8800 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8801 if (mContext.checkCallingOrSelfPermission( 8802 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8803 PackageManager.PERMISSION_GRANTED) { 8804 throw new SecurityException("Must hold permission " + 8805 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8806 } 8807 final long ident = Binder.clearCallingIdentity(); 8808 try { 8809 synchronized(mWindowMap) { 8810 DisplayContent displayContent = getDisplayContentLocked(displayId); 8811 if (displayContent != null) { 8812 setOverscanLocked(displayContent, left, top, right, bottom); 8813 } 8814 } 8815 } finally { 8816 Binder.restoreCallingIdentity(ident); 8817 } 8818 } 8819 8820 private void setOverscanLocked(DisplayContent displayContent, 8821 int left, int top, int right, int bottom) { 8822 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8823 displayInfo.overscanLeft = left; 8824 displayInfo.overscanTop = top; 8825 displayInfo.overscanRight = right; 8826 displayInfo.overscanBottom = bottom; 8827 8828 mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top, 8829 right, bottom); 8830 mDisplaySettings.writeSettingsLocked(); 8831 8832 reconfigureDisplayLocked(displayContent); 8833 } 8834 8835 // ------------------------------------------------------------- 8836 // Internals 8837 // ------------------------------------------------------------- 8838 8839 final WindowState windowForClientLocked(Session session, IWindow client, 8840 boolean throwOnError) { 8841 return windowForClientLocked(session, client.asBinder(), throwOnError); 8842 } 8843 8844 final WindowState windowForClientLocked(Session session, IBinder client, 8845 boolean throwOnError) { 8846 WindowState win = mWindowMap.get(client); 8847 if (localLOGV) Slog.v( 8848 TAG_WM, "Looking up client " + client + ": " + win); 8849 if (win == null) { 8850 RuntimeException ex = new IllegalArgumentException( 8851 "Requested window " + client + " does not exist"); 8852 if (throwOnError) { 8853 throw ex; 8854 } 8855 Slog.w(TAG_WM, "Failed looking up window", ex); 8856 return null; 8857 } 8858 if (session != null && win.mSession != session) { 8859 RuntimeException ex = new IllegalArgumentException( 8860 "Requested window " + client + " is in session " + 8861 win.mSession + ", not " + session); 8862 if (throwOnError) { 8863 throw ex; 8864 } 8865 Slog.w(TAG_WM, "Failed looking up window", ex); 8866 return null; 8867 } 8868 8869 return win; 8870 } 8871 8872 final void rebuildAppWindowListLocked() { 8873 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8874 } 8875 8876 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8877 final WindowList windows = displayContent.getWindowList(); 8878 int NW = windows.size(); 8879 int i; 8880 int lastBelow = -1; 8881 int numRemoved = 0; 8882 8883 if (mRebuildTmp.length < NW) { 8884 mRebuildTmp = new WindowState[NW+10]; 8885 } 8886 8887 // First remove all existing app windows. 8888 i=0; 8889 while (i < NW) { 8890 WindowState w = windows.get(i); 8891 if (w.mAppToken != null) { 8892 WindowState win = windows.remove(i); 8893 win.mRebuilding = true; 8894 mRebuildTmp[numRemoved] = win; 8895 mWindowsChanged = true; 8896 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win); 8897 NW--; 8898 numRemoved++; 8899 continue; 8900 } else if (lastBelow == i-1) { 8901 if (w.mAttrs.type == TYPE_WALLPAPER) { 8902 lastBelow = i; 8903 } 8904 } 8905 i++; 8906 } 8907 8908 // Keep whatever windows were below the app windows still below, 8909 // by skipping them. 8910 lastBelow++; 8911 i = lastBelow; 8912 8913 // First add all of the exiting app tokens... these are no longer 8914 // in the main app list, but still have windows shown. We put them 8915 // in the back because now that the animation is over we no longer 8916 // will care about them. 8917 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8918 final int numStacks = stacks.size(); 8919 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8920 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8921 int NT = exitingAppTokens.size(); 8922 for (int j = 0; j < NT; j++) { 8923 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8924 } 8925 } 8926 8927 // And add in the still active app tokens in Z order. 8928 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8929 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8930 final int numTasks = tasks.size(); 8931 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8932 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8933 final int numTokens = tokens.size(); 8934 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8935 final AppWindowToken wtoken = tokens.get(tokenNdx); 8936 if (wtoken.mIsExiting && !wtoken.waitingForReplacement()) { 8937 continue; 8938 } 8939 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8940 } 8941 } 8942 } 8943 8944 i -= lastBelow; 8945 if (i != numRemoved) { 8946 displayContent.layoutNeeded = true; 8947 Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed " 8948 + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() " 8949 + " callers=" + Debug.getCallers(10)); 8950 for (i = 0; i < numRemoved; i++) { 8951 WindowState ws = mRebuildTmp[i]; 8952 if (ws.mRebuilding) { 8953 StringWriter sw = new StringWriter(); 8954 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8955 ws.dump(pw, "", true); 8956 pw.flush(); 8957 Slog.w(TAG_WM, "This window was lost: " + ws); 8958 Slog.w(TAG_WM, sw.toString()); 8959 ws.mWinAnimator.destroySurfaceLocked(); 8960 } 8961 } 8962 Slog.w(TAG_WM, "Current app token list:"); 8963 dumpAppTokensLocked(); 8964 Slog.w(TAG_WM, "Final window list:"); 8965 dumpWindowsLocked(); 8966 } 8967 Arrays.fill(mRebuildTmp, null); 8968 } 8969 8970 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8971 // If the screen is currently frozen or off, then keep 8972 // it frozen/off until this window draws at its new 8973 // orientation. 8974 if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { 8975 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w); 8976 w.mOrientationChanging = true; 8977 w.mLastFreezeDuration = 0; 8978 mWindowPlacerLocked.mOrientationChangeComplete = false; 8979 if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) { 8980 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; 8981 // XXX should probably keep timeout from 8982 // when we first froze the display. 8983 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8984 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8985 WINDOW_FREEZE_TIMEOUT_DURATION); 8986 } 8987 } 8988 } 8989 8990 /** 8991 * @return bitmap indicating if another pass through layout must be made. 8992 */ 8993 int handleAnimatingStoppedAndTransitionLocked() { 8994 int changes = 0; 8995 8996 mAppTransition.setIdle(); 8997 8998 for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) { 8999 final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i); 9000 mAppTransition.notifyAppTransitionFinishedLocked(token); 9001 } 9002 mNoAnimationNotifyOnTransitionFinished.clear(); 9003 9004 mWallpaperControllerLocked.hideDeferredWallpapersIfNeeded(); 9005 9006 // Restore window app tokens to the ActivityManager views 9007 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 9008 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9009 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9010 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9011 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9012 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9013 tokens.get(tokenNdx).sendingToBottom = false; 9014 } 9015 } 9016 } 9017 rebuildAppWindowListLocked(); 9018 9019 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 9020 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM, 9021 "Wallpaper layer changed: assigning layers + relayout"); 9022 moveInputMethodWindowsIfNeededLocked(true); 9023 mWindowPlacerLocked.mWallpaperMayChange = true; 9024 // Since the window list has been rebuilt, focus might 9025 // have to be recomputed since the actual order of windows 9026 // might have changed again. 9027 mFocusMayChange = true; 9028 9029 return changes; 9030 } 9031 9032 void updateResizingWindows(final WindowState w) { 9033 final WindowStateAnimator winAnimator = w.mWinAnimator; 9034 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 9035 w.setInsetsChanged(); 9036 boolean configChanged = w.isConfigChanged(); 9037 if (DEBUG_CONFIGURATION && configChanged) { 9038 Slog.v(TAG_WM, "Win " + w + " config changed: " 9039 + mCurConfiguration); 9040 } 9041 final boolean dragResizingChanged = w.isDragResizeChanged() 9042 && !w.isDragResizingChangeReported(); 9043 if (localLOGV) Slog.v(TAG_WM, "Resizing " + w 9044 + ": configChanged=" + configChanged 9045 + " dragResizingChanged=" + dragResizingChanged 9046 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 9047 w.mLastFrame.set(w.mFrame); 9048 if (w.mContentInsetsChanged 9049 || w.mVisibleInsetsChanged 9050 || winAnimator.mSurfaceResized 9051 || w.mOutsetsChanged 9052 || configChanged 9053 || dragResizingChanged 9054 || w.mResizedWhileNotDragResizing) { 9055 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 9056 Slog.v(TAG_WM, "Resize reasons for w=" + w + ": " 9057 + " contentInsetsChanged=" + w.mContentInsetsChanged 9058 + " " + w.mContentInsets.toShortString() 9059 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 9060 + " " + w.mVisibleInsets.toShortString() 9061 + " stableInsetsChanged=" + w.mStableInsetsChanged 9062 + " " + w.mStableInsets.toShortString() 9063 + " outsetsChanged=" + w.mOutsetsChanged 9064 + " " + w.mOutsets.toShortString() 9065 + " surfaceResized=" + winAnimator.mSurfaceResized 9066 + " configChanged=" + configChanged 9067 + " dragResizingChanged=" + dragResizingChanged); 9068 } 9069 9070 // If it's a dead window left on screen, and the configuration changed, 9071 // there is nothing we can do about it. Remove the window now. 9072 if (w.mAppToken != null && w.mAppDied) { 9073 w.mAppToken.removeAllDeadWindows(); 9074 return; 9075 } 9076 9077 w.mLastOverscanInsets.set(w.mOverscanInsets); 9078 w.mLastContentInsets.set(w.mContentInsets); 9079 w.mLastVisibleInsets.set(w.mVisibleInsets); 9080 w.mLastStableInsets.set(w.mStableInsets); 9081 w.mLastOutsets.set(w.mOutsets); 9082 makeWindowFreezingScreenIfNeededLocked(w); 9083 // If the orientation is changing, or we're starting or ending 9084 // a drag resizing action, then we need to hold off on unfreezing 9085 // the display until this window has been redrawn; to do that, 9086 // we need to go through the process of getting informed by the 9087 // application when it has finished drawing. 9088 if (w.mOrientationChanging || dragResizingChanged 9089 || w.mResizedWhileNotDragResizing) { 9090 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) { 9091 Slog.v(TAG_WM, "Orientation or resize start waiting for draw" 9092 + ", mDrawState=DRAW_PENDING in " + w 9093 + ", surfaceController " + winAnimator.mSurfaceController); 9094 } 9095 winAnimator.mDrawState = DRAW_PENDING; 9096 if (w.mAppToken != null) { 9097 w.mAppToken.allDrawn = false; 9098 w.mAppToken.deferClearAllDrawn = false; 9099 } 9100 } 9101 if (!mResizingWindows.contains(w)) { 9102 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM, 9103 "Resizing window " + w); 9104 mResizingWindows.add(w); 9105 } 9106 } else if (w.mOrientationChanging) { 9107 if (w.isDrawnLw()) { 9108 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 9109 "Orientation not waiting for draw in " 9110 + w + ", surfaceController " + winAnimator.mSurfaceController); 9111 w.mOrientationChanging = false; 9112 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 9113 - mDisplayFreezeTime); 9114 } 9115 } 9116 } 9117 } 9118 9119 void checkDrawnWindowsLocked() { 9120 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9121 return; 9122 } 9123 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9124 WindowState win = mWaitingForDrawn.get(j); 9125 if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win + 9126 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9127 " mHasSurface=" + win.mHasSurface + 9128 " drawState=" + win.mWinAnimator.mDrawState); 9129 if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) { 9130 // Window has been removed or hidden; no draw will now happen, so stop waiting. 9131 if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win); 9132 mWaitingForDrawn.remove(win); 9133 } else if (win.hasDrawnLw()) { 9134 // Window is now drawn (and shown). 9135 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win); 9136 mWaitingForDrawn.remove(win); 9137 } 9138 } 9139 if (mWaitingForDrawn.isEmpty()) { 9140 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!"); 9141 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9142 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9143 } 9144 } 9145 9146 void setHoldScreenLocked(final Session newHoldScreen) { 9147 final boolean hold = newHoldScreen != null; 9148 9149 if (hold && mHoldingScreenOn != newHoldScreen) { 9150 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9151 } 9152 mHoldingScreenOn = newHoldScreen; 9153 9154 final boolean state = mHoldingScreenWakeLock.isHeld(); 9155 if (hold != state) { 9156 if (hold) { 9157 mHoldingScreenWakeLock.acquire(); 9158 mPolicy.keepScreenOnStartedLw(); 9159 } else { 9160 mPolicy.keepScreenOnStoppedLw(); 9161 mHoldingScreenWakeLock.release(); 9162 } 9163 } 9164 } 9165 9166 void requestTraversal() { 9167 synchronized (mWindowMap) { 9168 mWindowPlacerLocked.requestTraversal(); 9169 } 9170 } 9171 9172 /** Note that Locked in this case is on mLayoutToAnim */ 9173 void scheduleAnimationLocked() { 9174 if (!mAnimationScheduled) { 9175 mAnimationScheduled = true; 9176 mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback); 9177 } 9178 } 9179 9180 boolean needsLayout() { 9181 final int numDisplays = mDisplayContents.size(); 9182 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9183 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9184 if (displayContent.layoutNeeded) { 9185 return true; 9186 } 9187 } 9188 return false; 9189 } 9190 9191 /** If a window that has an animation specifying a colored background and the current wallpaper 9192 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9193 * suddenly disappear. */ 9194 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9195 WindowList windows = winAnimator.mWin.getWindowList(); 9196 for (int i = windows.size() - 1; i >= 0; --i) { 9197 WindowState testWin = windows.get(i); 9198 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9199 return testWin.mWinAnimator.mAnimLayer; 9200 } 9201 } 9202 return winAnimator.mAnimLayer; 9203 } 9204 9205 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9206 boolean secure) { 9207 final WindowSurfaceController surfaceController = winAnimator.mSurfaceController; 9208 boolean leakedSurface = false; 9209 boolean killedApps = false; 9210 9211 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9212 winAnimator.mSession.mPid, operation); 9213 9214 final long callingIdentity = Binder.clearCallingIdentity(); 9215 try { 9216 // There was some problem... first, do a sanity check of the window list to make sure 9217 // we haven't left any dangling surfaces around. 9218 9219 Slog.i(TAG_WM, "Out of memory for surface! Looking for leaks..."); 9220 final int numDisplays = mDisplayContents.size(); 9221 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9222 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9223 final int numWindows = windows.size(); 9224 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9225 final WindowState ws = windows.get(winNdx); 9226 final WindowStateAnimator wsa = ws.mWinAnimator; 9227 if (wsa.mSurfaceController == null) { 9228 continue; 9229 } 9230 if (!mSessions.contains(wsa.mSession)) { 9231 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): " 9232 + ws + " surface=" + wsa.mSurfaceController 9233 + " token=" + ws.mToken 9234 + " pid=" + ws.mSession.mPid 9235 + " uid=" + ws.mSession.mUid); 9236 wsa.destroySurface(); 9237 mForceRemoves.add(ws); 9238 leakedSurface = true; 9239 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9240 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " 9241 + ws + " surface=" + wsa.mSurfaceController 9242 + " token=" + ws.mAppToken 9243 + " saved=" + ws.mAppToken.hasSavedSurface()); 9244 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false); 9245 wsa.destroySurface(); 9246 leakedSurface = true; 9247 } 9248 } 9249 } 9250 9251 if (!leakedSurface) { 9252 Slog.w(TAG_WM, "No leaked surfaces; killing applicatons!"); 9253 SparseIntArray pidCandidates = new SparseIntArray(); 9254 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9255 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9256 final int numWindows = windows.size(); 9257 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9258 final WindowState ws = windows.get(winNdx); 9259 if (mForceRemoves.contains(ws)) { 9260 continue; 9261 } 9262 WindowStateAnimator wsa = ws.mWinAnimator; 9263 if (wsa.mSurfaceController != null) { 9264 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9265 } 9266 } 9267 if (pidCandidates.size() > 0) { 9268 int[] pids = new int[pidCandidates.size()]; 9269 for (int i=0; i<pids.length; i++) { 9270 pids[i] = pidCandidates.keyAt(i); 9271 } 9272 try { 9273 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9274 killedApps = true; 9275 } 9276 } catch (RemoteException e) { 9277 } 9278 } 9279 } 9280 } 9281 9282 if (leakedSurface || killedApps) { 9283 // We managed to reclaim some memory, so get rid of the trouble 9284 // surface and ask the app to request another one. 9285 Slog.w(TAG_WM, "Looks like we have reclaimed some memory, clearing surface for retry."); 9286 if (surfaceController != null) { 9287 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9288 "RECOVER DESTROY", false); 9289 winAnimator.destroySurface(); 9290 scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken); 9291 } 9292 9293 try { 9294 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9295 } catch (RemoteException e) { 9296 } 9297 } 9298 } finally { 9299 Binder.restoreCallingIdentity(callingIdentity); 9300 } 9301 9302 return leakedSurface || killedApps; 9303 } 9304 9305 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9306 WindowState newFocus = computeFocusedWindowLocked(); 9307 if (mCurrentFocus != newFocus) { 9308 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9309 // This check makes sure that we don't already have the focus 9310 // change message pending. 9311 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9312 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9313 // TODO(multidisplay): Focused windows on default display only. 9314 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9315 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9316 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9317 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9318 if (imWindowChanged) { 9319 displayContent.layoutNeeded = true; 9320 newFocus = computeFocusedWindowLocked(); 9321 } 9322 9323 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " + 9324 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9325 final WindowState oldFocus = mCurrentFocus; 9326 mCurrentFocus = newFocus; 9327 mLosingFocus.remove(newFocus); 9328 9329 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9330 9331 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9332 // Focus of the input method window changed. Perform layout if needed. 9333 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9334 mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/, 9335 updateInputWindows); 9336 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9337 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9338 // Client will do the layout, but we need to assign layers 9339 // for handleNewWindowLocked() below. 9340 mLayersController.assignLayersLocked(displayContent.getWindowList()); 9341 } 9342 } 9343 9344 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9345 // The change in focus caused us to need to do a layout. Okay. 9346 displayContent.layoutNeeded = true; 9347 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9348 mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/, 9349 updateInputWindows); 9350 } 9351 } 9352 9353 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9354 // If we defer assigning layers, then the caller is responsible for 9355 // doing this part. 9356 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9357 } 9358 9359 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9360 return true; 9361 } 9362 return false; 9363 } 9364 9365 private WindowState computeFocusedWindowLocked() { 9366 final int displayCount = mDisplayContents.size(); 9367 for (int i = 0; i < displayCount; i++) { 9368 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9369 WindowState win = findFocusedWindowLocked(displayContent); 9370 if (win != null) { 9371 return win; 9372 } 9373 } 9374 return null; 9375 } 9376 9377 WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9378 final WindowList windows = displayContent.getWindowList(); 9379 for (int i = windows.size() - 1; i >= 0; i--) { 9380 final WindowState win = windows.get(i); 9381 9382 if (localLOGV || DEBUG_FOCUS) Slog.v( 9383 TAG_WM, "Looking for focus: " + i 9384 + " = " + win 9385 + ", flags=" + win.mAttrs.flags 9386 + ", canReceive=" + win.canReceiveKeys()); 9387 9388 if (!win.canReceiveKeys()) { 9389 continue; 9390 } 9391 9392 AppWindowToken wtoken = win.mAppToken; 9393 9394 // If this window's application has been removed, just skip it. 9395 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9396 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because " 9397 + (wtoken.removed ? "removed" : "sendingToBottom")); 9398 continue; 9399 } 9400 9401 // Descend through all of the app tokens and find the first that either matches 9402 // win.mAppToken (return win) or mFocusedApp (return null). 9403 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 9404 mFocusedApp != null) { 9405 ArrayList<Task> tasks = displayContent.getTasks(); 9406 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9407 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9408 int tokenNdx = tokens.size() - 1; 9409 for ( ; tokenNdx >= 0; --tokenNdx) { 9410 final AppWindowToken token = tokens.get(tokenNdx); 9411 if (wtoken == token) { 9412 break; 9413 } 9414 if (mFocusedApp == token && token.windowsAreFocusable()) { 9415 // Whoops, we are below the focused app whose windows are focusable... 9416 // No focus for you!!! 9417 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, 9418 "findFocusedWindow: Reached focused app=" + mFocusedApp); 9419 return null; 9420 } 9421 } 9422 if (tokenNdx >= 0) { 9423 // Early exit from loop, must have found the matching token. 9424 break; 9425 } 9426 } 9427 } 9428 9429 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + i + 9430 " = " + win); 9431 return win; 9432 } 9433 9434 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows."); 9435 return null; 9436 } 9437 9438 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 9439 if (mDisplayFrozen) { 9440 return; 9441 } 9442 9443 if (!mDisplayReady || !mPolicy.isScreenOn()) { 9444 // No need to freeze the screen before the system is ready or if 9445 // the screen is off. 9446 return; 9447 } 9448 9449 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 9450 "startFreezingDisplayLocked: inTransaction=" + inTransaction 9451 + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim 9452 + " called by " + Debug.getCallers(8)); 9453 mScreenFrozenLock.acquire(); 9454 9455 mDisplayFrozen = true; 9456 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 9457 mLastFinishedFreezeSource = null; 9458 9459 mInputMonitor.freezeInputDispatchingLw(); 9460 9461 // Clear the last input window -- that is just used for 9462 // clean transitions between IMEs, and if we are freezing 9463 // the screen then the whole world is changing behind the scenes. 9464 mPolicy.setLastInputMethodWindowLw(null, null); 9465 9466 if (mAppTransition.isTransitionSet()) { 9467 mAppTransition.freeze(); 9468 } 9469 9470 if (PROFILE_ORIENTATION) { 9471 File file = new File("/data/system/frozen"); 9472 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9473 } 9474 9475 if (CUSTOM_SCREEN_ROTATION) { 9476 mExitAnimId = exitAnim; 9477 mEnterAnimId = enterAnim; 9478 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9479 final int displayId = displayContent.getDisplayId(); 9480 ScreenRotationAnimation screenRotationAnimation = 9481 mAnimator.getScreenRotationAnimationLocked(displayId); 9482 if (screenRotationAnimation != null) { 9483 screenRotationAnimation.kill(); 9484 } 9485 9486 // Check whether the current screen contains any secure content. 9487 boolean isSecure = false; 9488 final WindowList windows = getDefaultWindowListLocked(); 9489 final int N = windows.size(); 9490 for (int i = 0; i < N; i++) { 9491 WindowState ws = windows.get(i); 9492 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 9493 isSecure = true; 9494 break; 9495 } 9496 } 9497 9498 // TODO(multidisplay): rotation on main screen only. 9499 displayContent.updateDisplayInfo(); 9500 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 9501 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 9502 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9503 } 9504 } 9505 9506 void stopFreezingDisplayLocked() { 9507 if (!mDisplayFrozen) { 9508 return; 9509 } 9510 9511 if (mWaitingForConfig || mAppsFreezingScreen > 0 9512 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE 9513 || mClientFreezingScreen || !mOpeningApps.isEmpty()) { 9514 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 9515 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 9516 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 9517 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 9518 + ", mClientFreezingScreen=" + mClientFreezingScreen 9519 + ", mOpeningApps.size()=" + mOpeningApps.size()); 9520 return; 9521 } 9522 9523 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 9524 "stopFreezingDisplayLocked: Unfreezing now"); 9525 9526 mDisplayFrozen = false; 9527 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 9528 StringBuilder sb = new StringBuilder(128); 9529 sb.append("Screen frozen for "); 9530 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 9531 if (mLastFinishedFreezeSource != null) { 9532 sb.append(" due to "); 9533 sb.append(mLastFinishedFreezeSource); 9534 } 9535 Slog.i(TAG_WM, sb.toString()); 9536 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9537 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 9538 if (PROFILE_ORIENTATION) { 9539 Debug.stopMethodTracing(); 9540 } 9541 9542 boolean updateRotation = false; 9543 9544 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9545 final int displayId = displayContent.getDisplayId(); 9546 ScreenRotationAnimation screenRotationAnimation = 9547 mAnimator.getScreenRotationAnimationLocked(displayId); 9548 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 9549 && screenRotationAnimation.hasScreenshot()) { 9550 if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation"); 9551 // TODO(multidisplay): rotation on main screen only. 9552 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9553 // Get rotation animation again, with new top window 9554 boolean isDimming = displayContent.isDimming(); 9555 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 9556 mExitAnimId = mEnterAnimId = 0; 9557 } 9558 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 9559 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 9560 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 9561 scheduleAnimationLocked(); 9562 } else { 9563 screenRotationAnimation.kill(); 9564 mAnimator.setScreenRotationAnimationLocked(displayId, null); 9565 updateRotation = true; 9566 } 9567 } else { 9568 if (screenRotationAnimation != null) { 9569 screenRotationAnimation.kill(); 9570 mAnimator.setScreenRotationAnimationLocked(displayId, null); 9571 } 9572 updateRotation = true; 9573 } 9574 9575 mInputMonitor.thawInputDispatchingLw(); 9576 9577 boolean configChanged; 9578 9579 // While the display is frozen we don't re-compute the orientation 9580 // to avoid inconsistent states. However, something interesting 9581 // could have actually changed during that time so re-evaluate it 9582 // now to catch that. 9583 configChanged = updateOrientationFromAppTokensLocked(false); 9584 9585 // A little kludge: a lot could have happened while the 9586 // display was frozen, so now that we are coming back we 9587 // do a gc so that any remote references the system 9588 // processes holds on others can be released if they are 9589 // no longer needed. 9590 mH.removeMessages(H.FORCE_GC); 9591 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 9592 9593 mScreenFrozenLock.release(); 9594 9595 if (updateRotation) { 9596 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation"); 9597 configChanged |= updateRotationUncheckedLocked(false); 9598 } 9599 9600 if (configChanged) { 9601 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9602 } 9603 } 9604 9605 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 9606 DisplayMetrics dm) { 9607 if (index < tokens.length) { 9608 String str = tokens[index]; 9609 if (str != null && str.length() > 0) { 9610 try { 9611 int val = Integer.parseInt(str); 9612 return val; 9613 } catch (Exception e) { 9614 } 9615 } 9616 } 9617 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 9618 return defDps; 9619 } 9620 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 9621 return val; 9622 } 9623 9624 void createWatermarkInTransaction() { 9625 if (mWatermark != null) { 9626 return; 9627 } 9628 9629 File file = new File("/system/etc/setup.conf"); 9630 FileInputStream in = null; 9631 DataInputStream ind = null; 9632 try { 9633 in = new FileInputStream(file); 9634 ind = new DataInputStream(in); 9635 String line = ind.readLine(); 9636 if (line != null) { 9637 String[] toks = line.split("%"); 9638 if (toks != null && toks.length > 0) { 9639 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 9640 mRealDisplayMetrics, mFxSession, toks); 9641 } 9642 } 9643 } catch (FileNotFoundException e) { 9644 } catch (IOException e) { 9645 } finally { 9646 if (ind != null) { 9647 try { 9648 ind.close(); 9649 } catch (IOException e) { 9650 } 9651 } else if (in != null) { 9652 try { 9653 in.close(); 9654 } catch (IOException e) { 9655 } 9656 } 9657 } 9658 } 9659 9660 @Override 9661 public void statusBarVisibilityChanged(int visibility) { 9662 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 9663 != PackageManager.PERMISSION_GRANTED) { 9664 throw new SecurityException("Caller does not hold permission " 9665 + android.Manifest.permission.STATUS_BAR); 9666 } 9667 9668 synchronized (mWindowMap) { 9669 mLastStatusBarVisibility = visibility; 9670 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 9671 updateStatusBarVisibilityLocked(visibility); 9672 } 9673 } 9674 9675 // TOOD(multidisplay): StatusBar on multiple screens? 9676 boolean updateStatusBarVisibilityLocked(int visibility) { 9677 if (mLastDispatchedSystemUiVisibility == visibility) { 9678 return false; 9679 } 9680 final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility) 9681 // We are only interested in differences of one of the 9682 // clearable flags... 9683 & View.SYSTEM_UI_CLEARABLE_FLAGS 9684 // ...if it has actually been cleared. 9685 & ~visibility; 9686 9687 mLastDispatchedSystemUiVisibility = visibility; 9688 mInputManager.setSystemUiVisibility(visibility); 9689 final WindowList windows = getDefaultWindowListLocked(); 9690 final int N = windows.size(); 9691 for (int i = 0; i < N; i++) { 9692 WindowState ws = windows.get(i); 9693 try { 9694 int curValue = ws.mSystemUiVisibility; 9695 int diff = (curValue ^ visibility) & globalDiff; 9696 int newValue = (curValue&~diff) | (visibility&diff); 9697 if (newValue != curValue) { 9698 ws.mSeq++; 9699 ws.mSystemUiVisibility = newValue; 9700 } 9701 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 9702 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 9703 visibility, newValue, diff); 9704 } 9705 } catch (RemoteException e) { 9706 // so sorry 9707 } 9708 } 9709 return true; 9710 } 9711 9712 @Override 9713 public void reevaluateStatusBarVisibility() { 9714 synchronized (mWindowMap) { 9715 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 9716 if (updateStatusBarVisibilityLocked(visibility)) { 9717 mWindowPlacerLocked.requestTraversal(); 9718 } 9719 } 9720 } 9721 9722 private static final class HideNavInputConsumer extends InputConsumerImpl 9723 implements WindowManagerPolicy.InputConsumer { 9724 private final InputEventReceiver mInputEventReceiver; 9725 9726 HideNavInputConsumer(WindowManagerService service, Looper looper, 9727 InputEventReceiver.Factory inputEventReceiverFactory) { 9728 super(service, "input consumer", null); 9729 mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver( 9730 mClientChannel, looper); 9731 } 9732 9733 @Override 9734 public void dismiss() { 9735 if (mService.removeInputConsumer()) { 9736 synchronized (mService.mWindowMap) { 9737 mInputEventReceiver.dispose(); 9738 disposeChannelsLw(); 9739 } 9740 } 9741 } 9742 } 9743 9744 @Override 9745 public WindowManagerPolicy.InputConsumer addInputConsumer(Looper looper, 9746 InputEventReceiver.Factory inputEventReceiverFactory) { 9747 synchronized (mWindowMap) { 9748 HideNavInputConsumer inputConsumerImpl = new HideNavInputConsumer( 9749 this, looper, inputEventReceiverFactory); 9750 mInputConsumer = inputConsumerImpl; 9751 mInputMonitor.updateInputWindowsLw(true); 9752 return inputConsumerImpl; 9753 } 9754 } 9755 9756 boolean removeInputConsumer() { 9757 synchronized (mWindowMap) { 9758 if (mInputConsumer != null) { 9759 mInputConsumer = null; 9760 mInputMonitor.updateInputWindowsLw(true); 9761 return true; 9762 } 9763 return false; 9764 } 9765 } 9766 9767 public void createWallpaperInputConsumer(InputChannel inputChannel) { 9768 synchronized (mWindowMap) { 9769 mWallpaperInputConsumer = new InputConsumerImpl(this, "wallpaper input", inputChannel); 9770 mWallpaperInputConsumer.mWindowHandle.hasWallpaper = true; 9771 mInputMonitor.updateInputWindowsLw(true); 9772 } 9773 } 9774 9775 public void removeWallpaperInputConsumer() { 9776 synchronized (mWindowMap) { 9777 if (mWallpaperInputConsumer != null) { 9778 mWallpaperInputConsumer.disposeChannelsLw(); 9779 mWallpaperInputConsumer = null; 9780 mInputMonitor.updateInputWindowsLw(true); 9781 } 9782 } 9783 } 9784 9785 @Override 9786 public boolean hasNavigationBar() { 9787 return mPolicy.hasNavigationBar(); 9788 } 9789 9790 @Override 9791 public void lockNow(Bundle options) { 9792 mPolicy.lockNow(options); 9793 } 9794 9795 public void showRecentApps() { 9796 mPolicy.showRecentApps(); 9797 } 9798 9799 @Override 9800 public boolean isSafeModeEnabled() { 9801 return mSafeMode; 9802 } 9803 9804 @Override 9805 public boolean clearWindowContentFrameStats(IBinder token) { 9806 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 9807 "clearWindowContentFrameStats()")) { 9808 throw new SecurityException("Requires FRAME_STATS permission"); 9809 } 9810 synchronized (mWindowMap) { 9811 WindowState windowState = mWindowMap.get(token); 9812 if (windowState == null) { 9813 return false; 9814 } 9815 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController; 9816 if (surfaceController == null) { 9817 return false; 9818 } 9819 return surfaceController.clearWindowContentFrameStats(); 9820 } 9821 } 9822 9823 @Override 9824 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 9825 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 9826 "getWindowContentFrameStats()")) { 9827 throw new SecurityException("Requires FRAME_STATS permission"); 9828 } 9829 synchronized (mWindowMap) { 9830 WindowState windowState = mWindowMap.get(token); 9831 if (windowState == null) { 9832 return null; 9833 } 9834 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController; 9835 if (surfaceController == null) { 9836 return null; 9837 } 9838 if (mTempWindowRenderStats == null) { 9839 mTempWindowRenderStats = new WindowContentFrameStats(); 9840 } 9841 WindowContentFrameStats stats = mTempWindowRenderStats; 9842 if (!surfaceController.getWindowContentFrameStats(stats)) { 9843 return null; 9844 } 9845 return stats; 9846 } 9847 } 9848 9849 public void notifyAppRelaunching(IBinder token) { 9850 synchronized (mWindowMap) { 9851 AppWindowToken appWindow = findAppWindowToken(token); 9852 if (appWindow != null) { 9853 appWindow.startRelaunching(); 9854 } 9855 } 9856 } 9857 9858 public void notifyAppRelaunchingFinished(IBinder token) { 9859 synchronized (mWindowMap) { 9860 AppWindowToken appWindow = findAppWindowToken(token); 9861 if (appWindow != null) { 9862 appWindow.finishRelaunching(); 9863 } 9864 } 9865 } 9866 9867 @Override 9868 public int getDockedDividerInsetsLw() { 9869 return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets(); 9870 } 9871 9872 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 9873 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 9874 mPolicy.dump(" ", pw, args); 9875 } 9876 9877 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 9878 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 9879 mAnimator.dumpLocked(pw, " ", dumpAll); 9880 } 9881 9882 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 9883 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 9884 if (!mTokenMap.isEmpty()) { 9885 pw.println(" All tokens:"); 9886 Iterator<WindowToken> it = mTokenMap.values().iterator(); 9887 while (it.hasNext()) { 9888 WindowToken token = it.next(); 9889 pw.print(" "); pw.print(token); 9890 if (dumpAll) { 9891 pw.println(':'); 9892 token.dump(pw, " "); 9893 } else { 9894 pw.println(); 9895 } 9896 } 9897 } 9898 mWallpaperControllerLocked.dumpTokens(pw, " ", dumpAll); 9899 if (!mFinishedStarting.isEmpty()) { 9900 pw.println(); 9901 pw.println(" Finishing start of application tokens:"); 9902 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 9903 WindowToken token = mFinishedStarting.get(i); 9904 pw.print(" Finished Starting #"); pw.print(i); 9905 pw.print(' '); pw.print(token); 9906 if (dumpAll) { 9907 pw.println(':'); 9908 token.dump(pw, " "); 9909 } else { 9910 pw.println(); 9911 } 9912 } 9913 } 9914 if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) { 9915 pw.println(); 9916 if (mOpeningApps.size() > 0) { 9917 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 9918 } 9919 if (mClosingApps.size() > 0) { 9920 pw.print(" mClosingApps="); pw.println(mClosingApps); 9921 } 9922 } 9923 } 9924 9925 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 9926 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 9927 for (int i=0; i<mSessions.size(); i++) { 9928 Session s = mSessions.valueAt(i); 9929 pw.print(" Session "); pw.print(s); pw.println(':'); 9930 s.dump(pw, " "); 9931 } 9932 } 9933 9934 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 9935 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 9936 if (mDisplayReady) { 9937 final int numDisplays = mDisplayContents.size(); 9938 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9939 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9940 displayContent.dump(" ", pw); 9941 } 9942 } else { 9943 pw.println(" NO DISPLAY"); 9944 } 9945 } 9946 9947 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 9948 ArrayList<WindowState> windows) { 9949 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 9950 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 9951 } 9952 9953 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 9954 ArrayList<WindowState> windows) { 9955 final int numDisplays = mDisplayContents.size(); 9956 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9957 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 9958 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 9959 final WindowState w = windowList.get(winNdx); 9960 if (windows == null || windows.contains(w)) { 9961 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 9962 pw.print(w); pw.println(":"); 9963 w.dump(pw, " ", dumpAll || windows != null); 9964 } 9965 } 9966 } 9967 if (mInputMethodDialogs.size() > 0) { 9968 pw.println(); 9969 pw.println(" Input method dialogs:"); 9970 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 9971 WindowState w = mInputMethodDialogs.get(i); 9972 if (windows == null || windows.contains(w)) { 9973 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 9974 } 9975 } 9976 } 9977 if (mPendingRemove.size() > 0) { 9978 pw.println(); 9979 pw.println(" Remove pending for:"); 9980 for (int i=mPendingRemove.size()-1; i>=0; i--) { 9981 WindowState w = mPendingRemove.get(i); 9982 if (windows == null || windows.contains(w)) { 9983 pw.print(" Remove #"); pw.print(i); pw.print(' '); 9984 pw.print(w); 9985 if (dumpAll) { 9986 pw.println(":"); 9987 w.dump(pw, " ", true); 9988 } else { 9989 pw.println(); 9990 } 9991 } 9992 } 9993 } 9994 if (mForceRemoves != null && mForceRemoves.size() > 0) { 9995 pw.println(); 9996 pw.println(" Windows force removing:"); 9997 for (int i=mForceRemoves.size()-1; i>=0; i--) { 9998 WindowState w = mForceRemoves.get(i); 9999 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10000 pw.print(w); 10001 if (dumpAll) { 10002 pw.println(":"); 10003 w.dump(pw, " ", true); 10004 } else { 10005 pw.println(); 10006 } 10007 } 10008 } 10009 if (mDestroySurface.size() > 0) { 10010 pw.println(); 10011 pw.println(" Windows waiting to destroy their surface:"); 10012 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10013 WindowState w = mDestroySurface.get(i); 10014 if (windows == null || windows.contains(w)) { 10015 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10016 pw.print(w); 10017 if (dumpAll) { 10018 pw.println(":"); 10019 w.dump(pw, " ", true); 10020 } else { 10021 pw.println(); 10022 } 10023 } 10024 } 10025 } 10026 if (mLosingFocus.size() > 0) { 10027 pw.println(); 10028 pw.println(" Windows losing focus:"); 10029 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10030 WindowState w = mLosingFocus.get(i); 10031 if (windows == null || windows.contains(w)) { 10032 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10033 pw.print(w); 10034 if (dumpAll) { 10035 pw.println(":"); 10036 w.dump(pw, " ", true); 10037 } else { 10038 pw.println(); 10039 } 10040 } 10041 } 10042 } 10043 if (mResizingWindows.size() > 0) { 10044 pw.println(); 10045 pw.println(" Windows waiting to resize:"); 10046 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10047 WindowState w = mResizingWindows.get(i); 10048 if (windows == null || windows.contains(w)) { 10049 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10050 pw.print(w); 10051 if (dumpAll) { 10052 pw.println(":"); 10053 w.dump(pw, " ", true); 10054 } else { 10055 pw.println(); 10056 } 10057 } 10058 } 10059 } 10060 if (mWaitingForDrawn.size() > 0) { 10061 pw.println(); 10062 pw.println(" Clients waiting for these windows to be drawn:"); 10063 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10064 WindowState win = mWaitingForDrawn.get(i); 10065 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10066 } 10067 } 10068 pw.println(); 10069 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10070 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad); 10071 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10072 if (mLastFocus != mCurrentFocus) { 10073 pw.print(" mLastFocus="); pw.println(mLastFocus); 10074 } 10075 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10076 if (mInputMethodTarget != null) { 10077 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10078 } 10079 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10080 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10081 pw.print(" mLastDisplayFreezeDuration="); 10082 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10083 if ( mLastFinishedFreezeSource != null) { 10084 pw.print(" due to "); 10085 pw.print(mLastFinishedFreezeSource); 10086 } 10087 pw.println(); 10088 10089 mInputMonitor.dump(pw, " "); 10090 10091 if (dumpAll) { 10092 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10093 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10094 if (mLastStatusBarVisibility != 0) { 10095 pw.print(" mLastStatusBarVisibility=0x"); 10096 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10097 } 10098 if (mInputMethodWindow != null) { 10099 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10100 } 10101 mWindowPlacerLocked.dump(pw, " "); 10102 mWallpaperControllerLocked.dump(pw, " "); 10103 mLayersController.dump(pw, " "); 10104 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10105 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10106 if (needsLayout()) { 10107 pw.print(" layoutNeeded on displays="); 10108 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10109 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10110 if (displayContent.layoutNeeded) { 10111 pw.print(displayContent.getDisplayId()); 10112 } 10113 } 10114 pw.println(); 10115 } 10116 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10117 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10118 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10119 pw.print(" client="); pw.print(mClientFreezingScreen); 10120 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10121 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10122 pw.print(" mRotation="); pw.print(mRotation); 10123 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10124 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10125 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10126 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10127 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 10128 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 10129 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 10130 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 10131 pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation); 10132 pw.println(" mLayoutToAnim:"); 10133 mAppTransition.dump(pw, " "); 10134 } 10135 } 10136 10137 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10138 int opti, boolean dumpAll) { 10139 WindowList windows = new WindowList(); 10140 if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) { 10141 final boolean appsOnly = name.contains("apps"); 10142 final boolean visibleOnly = name.contains("visible"); 10143 synchronized(mWindowMap) { 10144 if (appsOnly) { 10145 dumpDisplayContentsLocked(pw, true); 10146 } 10147 10148 final int numDisplays = mDisplayContents.size(); 10149 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10150 final WindowList windowList = 10151 mDisplayContents.valueAt(displayNdx).getWindowList(); 10152 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10153 final WindowState w = windowList.get(winNdx); 10154 if ((!visibleOnly || w.mWinAnimator.getShown()) 10155 && (!appsOnly || w.mAppToken != null)) { 10156 windows.add(w); 10157 } 10158 } 10159 } 10160 } 10161 } else { 10162 int objectId = 0; 10163 // See if this is an object ID. 10164 try { 10165 objectId = Integer.parseInt(name, 16); 10166 name = null; 10167 } catch (RuntimeException e) { 10168 } 10169 synchronized(mWindowMap) { 10170 final int numDisplays = mDisplayContents.size(); 10171 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10172 final WindowList windowList = 10173 mDisplayContents.valueAt(displayNdx).getWindowList(); 10174 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10175 final WindowState w = windowList.get(winNdx); 10176 if (name != null) { 10177 if (w.mAttrs.getTitle().toString().contains(name)) { 10178 windows.add(w); 10179 } 10180 } else if (System.identityHashCode(w) == objectId) { 10181 windows.add(w); 10182 } 10183 } 10184 } 10185 } 10186 } 10187 10188 if (windows.size() <= 0) { 10189 return false; 10190 } 10191 10192 synchronized(mWindowMap) { 10193 dumpWindowsLocked(pw, dumpAll, windows); 10194 } 10195 return true; 10196 } 10197 10198 void dumpLastANRLocked(PrintWriter pw) { 10199 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10200 if (mLastANRState == null) { 10201 pw.println(" <no ANR has occurred since boot>"); 10202 } else { 10203 pw.println(mLastANRState); 10204 } 10205 } 10206 10207 /** 10208 * Saves information about the state of the window manager at 10209 * the time an ANR occurred before anything else in the system changes 10210 * in response. 10211 * 10212 * @param appWindowToken The application that ANR'd, may be null. 10213 * @param windowState The window that ANR'd, may be null. 10214 * @param reason The reason for the ANR, may be null. 10215 */ 10216 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10217 String reason) { 10218 StringWriter sw = new StringWriter(); 10219 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10220 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10221 if (appWindowToken != null) { 10222 pw.println(" Application at fault: " + appWindowToken.stringName); 10223 } 10224 if (windowState != null) { 10225 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10226 } 10227 if (reason != null) { 10228 pw.println(" Reason: " + reason); 10229 } 10230 pw.println(); 10231 dumpWindowsNoHeaderLocked(pw, true, null); 10232 pw.println(); 10233 pw.println("Last ANR continued"); 10234 dumpDisplayContentsLocked(pw, true); 10235 pw.close(); 10236 mLastANRState = sw.toString(); 10237 10238 mH.removeMessages(H.RESET_ANR_MESSAGE); 10239 mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS); 10240 } 10241 10242 @Override 10243 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10244 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10245 != PackageManager.PERMISSION_GRANTED) { 10246 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10247 + Binder.getCallingPid() 10248 + ", uid=" + Binder.getCallingUid()); 10249 return; 10250 } 10251 10252 boolean dumpAll = false; 10253 10254 int opti = 0; 10255 while (opti < args.length) { 10256 String opt = args[opti]; 10257 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10258 break; 10259 } 10260 opti++; 10261 if ("-a".equals(opt)) { 10262 dumpAll = true; 10263 } else if ("-h".equals(opt)) { 10264 pw.println("Window manager dump options:"); 10265 pw.println(" [-a] [-h] [cmd] ..."); 10266 pw.println(" cmd may be one of:"); 10267 pw.println(" l[astanr]: last ANR information"); 10268 pw.println(" p[policy]: policy state"); 10269 pw.println(" a[animator]: animator state"); 10270 pw.println(" s[essions]: active sessions"); 10271 pw.println(" surfaces: active surfaces (debugging enabled only)"); 10272 pw.println(" d[isplays]: active display contents"); 10273 pw.println(" t[okens]: token list"); 10274 pw.println(" w[indows]: window list"); 10275 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10276 pw.println(" be a partial substring in a window name, a"); 10277 pw.println(" Window hex object identifier, or"); 10278 pw.println(" \"all\" for all windows, or"); 10279 pw.println(" \"visible\" for the visible windows."); 10280 pw.println(" \"visible-apps\" for the visible app windows."); 10281 pw.println(" -a: include all available server state."); 10282 return; 10283 } else { 10284 pw.println("Unknown argument: " + opt + "; use -h for help"); 10285 } 10286 } 10287 10288 // Is the caller requesting to dump a particular piece of data? 10289 if (opti < args.length) { 10290 String cmd = args[opti]; 10291 opti++; 10292 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10293 synchronized(mWindowMap) { 10294 dumpLastANRLocked(pw); 10295 } 10296 return; 10297 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10298 synchronized(mWindowMap) { 10299 dumpPolicyLocked(pw, args, true); 10300 } 10301 return; 10302 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10303 synchronized(mWindowMap) { 10304 dumpAnimatorLocked(pw, args, true); 10305 } 10306 return; 10307 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10308 synchronized(mWindowMap) { 10309 dumpSessionsLocked(pw, true); 10310 } 10311 return; 10312 } else if ("surfaces".equals(cmd)) { 10313 synchronized(mWindowMap) { 10314 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null); 10315 } 10316 return; 10317 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10318 synchronized(mWindowMap) { 10319 dumpDisplayContentsLocked(pw, true); 10320 } 10321 return; 10322 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10323 synchronized(mWindowMap) { 10324 dumpTokensLocked(pw, true); 10325 } 10326 return; 10327 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10328 synchronized(mWindowMap) { 10329 dumpWindowsLocked(pw, true, null); 10330 } 10331 return; 10332 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10333 synchronized(mWindowMap) { 10334 dumpWindowsLocked(pw, true, null); 10335 } 10336 return; 10337 } else { 10338 // Dumping a single name? 10339 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10340 pw.println("Bad window command, or no windows match: " + cmd); 10341 pw.println("Use -h for help."); 10342 } 10343 return; 10344 } 10345 } 10346 10347 synchronized(mWindowMap) { 10348 pw.println(); 10349 if (dumpAll) { 10350 pw.println("-------------------------------------------------------------------------------"); 10351 } 10352 dumpLastANRLocked(pw); 10353 pw.println(); 10354 if (dumpAll) { 10355 pw.println("-------------------------------------------------------------------------------"); 10356 } 10357 dumpPolicyLocked(pw, args, dumpAll); 10358 pw.println(); 10359 if (dumpAll) { 10360 pw.println("-------------------------------------------------------------------------------"); 10361 } 10362 dumpAnimatorLocked(pw, args, dumpAll); 10363 pw.println(); 10364 if (dumpAll) { 10365 pw.println("-------------------------------------------------------------------------------"); 10366 } 10367 dumpSessionsLocked(pw, dumpAll); 10368 pw.println(); 10369 if (dumpAll) { 10370 pw.println("-------------------------------------------------------------------------------"); 10371 } 10372 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ? 10373 "-------------------------------------------------------------------------------" 10374 : null); 10375 pw.println(); 10376 if (dumpAll) { 10377 pw.println("-------------------------------------------------------------------------------"); 10378 } 10379 dumpDisplayContentsLocked(pw, dumpAll); 10380 pw.println(); 10381 if (dumpAll) { 10382 pw.println("-------------------------------------------------------------------------------"); 10383 } 10384 dumpTokensLocked(pw, dumpAll); 10385 pw.println(); 10386 if (dumpAll) { 10387 pw.println("-------------------------------------------------------------------------------"); 10388 } 10389 dumpWindowsLocked(pw, dumpAll, null); 10390 } 10391 } 10392 10393 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10394 @Override 10395 public void monitor() { 10396 synchronized (mWindowMap) { } 10397 } 10398 10399 private DisplayContent newDisplayContentLocked(final Display display) { 10400 DisplayContent displayContent = new DisplayContent(display, this); 10401 final int displayId = display.getDisplayId(); 10402 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display); 10403 mDisplayContents.put(displayId, displayContent); 10404 10405 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10406 final Rect rect = new Rect(); 10407 mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect); 10408 displayInfo.overscanLeft = rect.left; 10409 displayInfo.overscanTop = rect.top; 10410 displayInfo.overscanRight = rect.right; 10411 displayInfo.overscanBottom = rect.bottom; 10412 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId, displayInfo); 10413 configureDisplayPolicyLocked(displayContent); 10414 10415 // TODO: Create an input channel for each display with touch capability. 10416 if (displayId == Display.DEFAULT_DISPLAY) { 10417 displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent); 10418 registerPointerEventListener(displayContent.mTapDetector); 10419 registerPointerEventListener(mMousePositionTracker); 10420 } 10421 10422 return displayContent; 10423 } 10424 10425 public void createDisplayContentLocked(final Display display) { 10426 if (display == null) { 10427 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10428 } 10429 getDisplayContentLocked(display.getDisplayId()); 10430 } 10431 10432 /** 10433 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10434 * there is a Display for the displayId. 10435 * @param displayId The display the caller is interested in. 10436 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10437 */ 10438 public DisplayContent getDisplayContentLocked(final int displayId) { 10439 DisplayContent displayContent = mDisplayContents.get(displayId); 10440 if (displayContent == null) { 10441 final Display display = mDisplayManager.getDisplay(displayId); 10442 if (display != null) { 10443 displayContent = newDisplayContentLocked(display); 10444 } 10445 } 10446 return displayContent; 10447 } 10448 10449 // There is an inherent assumption that this will never return null. 10450 public DisplayContent getDefaultDisplayContentLocked() { 10451 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10452 } 10453 10454 public WindowList getDefaultWindowListLocked() { 10455 return getDefaultDisplayContentLocked().getWindowList(); 10456 } 10457 10458 public DisplayInfo getDefaultDisplayInfoLocked() { 10459 return getDefaultDisplayContentLocked().getDisplayInfo(); 10460 } 10461 10462 /** 10463 * Return the list of WindowStates associated on the passed display. 10464 * @param display The screen to return windows from. 10465 * @return The list of WindowStates on the screen, or null if the there is no screen. 10466 */ 10467 public WindowList getWindowListLocked(final Display display) { 10468 return getWindowListLocked(display.getDisplayId()); 10469 } 10470 10471 /** 10472 * Return the list of WindowStates associated on the passed display. 10473 * @param displayId The screen to return windows from. 10474 * @return The list of WindowStates on the screen, or null if the there is no screen. 10475 */ 10476 public WindowList getWindowListLocked(final int displayId) { 10477 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10478 return displayContent != null ? displayContent.getWindowList() : null; 10479 } 10480 10481 public void onDisplayAdded(int displayId) { 10482 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10483 } 10484 10485 public void handleDisplayAdded(int displayId) { 10486 synchronized (mWindowMap) { 10487 final Display display = mDisplayManager.getDisplay(displayId); 10488 if (display != null) { 10489 createDisplayContentLocked(display); 10490 displayReady(displayId); 10491 } 10492 mWindowPlacerLocked.requestTraversal(); 10493 } 10494 } 10495 10496 public void onDisplayRemoved(int displayId) { 10497 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 10498 } 10499 10500 private void handleDisplayRemovedLocked(int displayId) { 10501 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10502 if (displayContent != null) { 10503 if (displayContent.isAnimating()) { 10504 displayContent.mDeferredRemoval = true; 10505 return; 10506 } 10507 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + displayContent); 10508 mDisplayContents.delete(displayId); 10509 displayContent.close(); 10510 if (displayId == Display.DEFAULT_DISPLAY) { 10511 unregisterPointerEventListener(displayContent.mTapDetector); 10512 unregisterPointerEventListener(mMousePositionTracker); 10513 } 10514 } 10515 mAnimator.removeDisplayLocked(displayId); 10516 mWindowPlacerLocked.requestTraversal(); 10517 } 10518 10519 public void onDisplayChanged(int displayId) { 10520 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 10521 } 10522 10523 private void handleDisplayChangedLocked(int displayId) { 10524 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10525 if (displayContent != null) { 10526 displayContent.updateDisplayInfo(); 10527 } 10528 mWindowPlacerLocked.requestTraversal(); 10529 } 10530 10531 @Override 10532 public Object getWindowManagerLock() { 10533 return mWindowMap; 10534 } 10535 10536 /** 10537 * Hint to a token that its activity will relaunch, which will trigger removal and addition of 10538 * a window. 10539 * @param token Application token for which the activity will be relaunched. 10540 */ 10541 public void setReplacingWindow(IBinder token, boolean animate) { 10542 AppWindowToken appWindowToken = null; 10543 synchronized (mWindowMap) { 10544 appWindowToken = findAppWindowToken(token); 10545 if (appWindowToken == null || !appWindowToken.isVisible()) { 10546 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token " 10547 + token); 10548 return; 10549 } 10550 appWindowToken.setReplacingWindows(animate); 10551 } 10552 } 10553 10554 /** 10555 * Hint to a token that its children will be replaced across activity relaunch. 10556 * The children would otherwise be removed shortly following this as the 10557 * activity is torn down. 10558 * @param token Application token for which the activity will be relaunched. 10559 */ 10560 public void setReplacingChildren(IBinder token) { 10561 AppWindowToken appWindowToken = null; 10562 synchronized (mWindowMap) { 10563 appWindowToken = findAppWindowToken(token); 10564 if (appWindowToken == null || !appWindowToken.isVisible()) { 10565 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token " 10566 + token); 10567 return; 10568 } 10569 10570 appWindowToken.setReplacingChildren(); 10571 scheduleClearReplacingWindowIfNeeded(token, true /* replacing */); 10572 } 10573 } 10574 10575 /** 10576 * If we're replacing the window, schedule a timer to clear the replaced window 10577 * after a timeout, in case the replacing window is not coming. 10578 * 10579 * If we're not replacing the window, clear the replace window settings of the app. 10580 * 10581 * @param token Application token for the activity whose window might be replaced. 10582 * @param replacing Whether the window is being replaced or not. 10583 */ 10584 public void scheduleClearReplacingWindowIfNeeded(IBinder token, boolean replacing) { 10585 AppWindowToken appWindowToken = null; 10586 synchronized (mWindowMap) { 10587 appWindowToken = findAppWindowToken(token); 10588 if (appWindowToken == null) { 10589 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token " 10590 + token); 10591 return; 10592 } 10593 if (replacing) { 10594 mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT); 10595 mH.sendMessageDelayed( 10596 mH.obtainMessage(H.WINDOW_REPLACEMENT_TIMEOUT, appWindowToken), 10597 WINDOW_REPLACEMENT_TIMEOUT_DURATION); 10598 } else { 10599 appWindowToken.resetReplacingWindows(); 10600 } 10601 } 10602 } 10603 10604 @Override 10605 public int getDockedStackSide() { 10606 synchronized (mWindowMap) { 10607 final TaskStack dockedStack = getDefaultDisplayContentLocked() 10608 .getDockedStackVisibleForUserLocked(); 10609 return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(); 10610 } 10611 } 10612 10613 @Override 10614 public void setDockedStackResizing(boolean resizing) { 10615 synchronized (mWindowMap) { 10616 getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing); 10617 requestTraversal(); 10618 } 10619 } 10620 10621 @Override 10622 public void setDockedStackDividerTouchRegion(Rect touchRegion) { 10623 synchronized (mWindowMap) { 10624 getDefaultDisplayContentLocked().getDockedDividerController() 10625 .setTouchRegion(touchRegion); 10626 setFocusTaskRegionLocked(); 10627 } 10628 } 10629 10630 @Override 10631 public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) { 10632 synchronized (mWindowMap) { 10633 getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer( 10634 visible, targetStackId, alpha); 10635 } 10636 } 10637 10638 public void animateResizePinnedStack(final Rect bounds, final int animationDuration) { 10639 synchronized (mWindowMap) { 10640 final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID); 10641 if (stack == null) { 10642 Slog.w(TAG, "animateResizePinnedStack: stackId " + PINNED_STACK_ID + " not found."); 10643 return; 10644 } 10645 final Rect originalBounds = new Rect(); 10646 stack.getBounds(originalBounds); 10647 UiThread.getHandler().post(new Runnable() { 10648 @Override 10649 public void run() { 10650 mBoundsAnimationController.animateBounds( 10651 stack, originalBounds, bounds, animationDuration); 10652 } 10653 }); 10654 } 10655 } 10656 10657 public void setTaskResizeable(int taskId, int resizeMode) { 10658 synchronized (mWindowMap) { 10659 final Task task = mTaskIdToTask.get(taskId); 10660 if (task != null) { 10661 task.setResizeable(resizeMode); 10662 } 10663 } 10664 } 10665 10666 public void setForceResizableTasks(boolean forceResizableTasks) { 10667 synchronized (mWindowMap) { 10668 mForceResizableTasks = forceResizableTasks; 10669 } 10670 } 10671 10672 static int dipToPixel(int dip, DisplayMetrics displayMetrics) { 10673 return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics); 10674 } 10675 10676 @Override 10677 public void registerDockedStackListener(IDockedStackListener listener) { 10678 if (!checkCallingPermission(android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS, 10679 "registerDockedStackListener()")) { 10680 return; 10681 } 10682 // TODO(multi-display): The listener is registered on the default display only. 10683 getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener( 10684 listener); 10685 } 10686 10687 @Override 10688 public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) { 10689 try { 10690 WindowState focusedWindow = getFocusedWindow(); 10691 if (focusedWindow != null && focusedWindow.mClient != null) { 10692 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId); 10693 } 10694 } catch (RemoteException e) { 10695 } 10696 } 10697 10698 @Override 10699 public void getStableInsets(Rect outInsets) throws RemoteException { 10700 synchronized (mWindowMap) { 10701 getStableInsetsLocked(outInsets); 10702 } 10703 } 10704 10705 void getStableInsetsLocked(Rect outInsets) { 10706 final DisplayInfo di = getDefaultDisplayInfoLocked(); 10707 mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets); 10708 } 10709 10710 private void getNonDecorInsetsLocked(Rect outInsets) { 10711 final DisplayInfo di = getDefaultDisplayInfoLocked(); 10712 mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets); 10713 } 10714 10715 /** 10716 * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable 10717 * inset areas. 10718 * 10719 * @param inOutBounds The inOutBounds to subtract the stable inset areas from. 10720 */ 10721 public void subtractStableInsets(Rect inOutBounds) { 10722 synchronized (mWindowMap) { 10723 getStableInsetsLocked(mTmpRect2); 10724 final DisplayInfo di = getDefaultDisplayInfoLocked(); 10725 mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight); 10726 mTmpRect.inset(mTmpRect2); 10727 inOutBounds.intersect(mTmpRect); 10728 } 10729 } 10730 10731 /** 10732 * Intersects the specified {@code inOutBounds} with the display frame that excludes 10733 * areas that could never be removed in Honeycomb. See 10734 * {@link WindowManagerPolicy#getNonDecorInsetsLw}. 10735 * 10736 * @param inOutBounds The inOutBounds to subtract the inset areas from. 10737 */ 10738 public void subtractNonDecorInsets(Rect inOutBounds) { 10739 synchronized (mWindowMap) { 10740 getNonDecorInsetsLocked(mTmpRect2); 10741 final DisplayInfo di = getDefaultDisplayInfoLocked(); 10742 mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight); 10743 mTmpRect.inset(mTmpRect2); 10744 inOutBounds.intersect(mTmpRect); 10745 } 10746 } 10747 10748 private MousePositionTracker mMousePositionTracker = new MousePositionTracker(); 10749 10750 private static class MousePositionTracker implements PointerEventListener { 10751 private boolean mLatestEventWasMouse; 10752 private float mLatestMouseX; 10753 private float mLatestMouseY; 10754 10755 void updatePosition(float x, float y) { 10756 synchronized (this) { 10757 mLatestEventWasMouse = true; 10758 mLatestMouseX = x; 10759 mLatestMouseY = y; 10760 } 10761 } 10762 10763 @Override 10764 public void onPointerEvent(MotionEvent motionEvent) { 10765 if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) { 10766 updatePosition(motionEvent.getRawX(), motionEvent.getRawY()); 10767 } else { 10768 synchronized (this) { 10769 mLatestEventWasMouse = false; 10770 } 10771 } 10772 } 10773 }; 10774 10775 void updatePointerIcon(IWindow client) { 10776 float mouseX, mouseY; 10777 10778 synchronized(mMousePositionTracker) { 10779 if (!mMousePositionTracker.mLatestEventWasMouse) { 10780 return; 10781 } 10782 mouseX = mMousePositionTracker.mLatestMouseX; 10783 mouseY = mMousePositionTracker.mLatestMouseY; 10784 } 10785 10786 synchronized (mWindowMap) { 10787 if (mDragState != null) { 10788 // Drag cursor overrides the app cursor. 10789 return; 10790 } 10791 WindowState callingWin = windowForClientLocked(null, client, false); 10792 if (callingWin == null) { 10793 Slog.w(TAG_WM, "Bad requesting window " + client); 10794 return; 10795 } 10796 final DisplayContent displayContent = callingWin.getDisplayContent(); 10797 if (displayContent == null) { 10798 return; 10799 } 10800 WindowState windowUnderPointer = 10801 displayContent.getTouchableWinAtPointLocked(mouseX, mouseY); 10802 if (windowUnderPointer != callingWin) { 10803 return; 10804 } 10805 try { 10806 windowUnderPointer.mClient.updatePointerIcon( 10807 windowUnderPointer.translateToWindowX(mouseX), 10808 windowUnderPointer.translateToWindowY(mouseY)); 10809 } catch (RemoteException e) { 10810 Slog.w(TAG_WM, "unable to update pointer icon"); 10811 } 10812 } 10813 } 10814 10815 void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) { 10816 // Mouse position tracker has not been getting updates while dragging, update it now. 10817 mMousePositionTracker.updatePosition(latestX, latestY); 10818 10819 WindowState windowUnderPointer = 10820 displayContent.getTouchableWinAtPointLocked(latestX, latestY); 10821 if (windowUnderPointer != null) { 10822 try { 10823 windowUnderPointer.mClient.updatePointerIcon( 10824 windowUnderPointer.translateToWindowX(latestX), 10825 windowUnderPointer.translateToWindowY(latestY)); 10826 } catch (RemoteException e) { 10827 Slog.w(TAG_WM, "unable to restore pointer icon"); 10828 } 10829 } else { 10830 InputManager.getInstance().setPointerIconShape(PointerIcon.STYLE_DEFAULT); 10831 } 10832 } 10833 10834 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver) 10835 throws RemoteException { 10836 if (!checkCallingPermission(Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS, 10837 "registerShortcutKey")) { 10838 throw new SecurityException( 10839 "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission"); 10840 } 10841 mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver); 10842 } 10843 10844 private final class LocalService extends WindowManagerInternal { 10845 @Override 10846 public void requestTraversalFromDisplayManager() { 10847 requestTraversal(); 10848 } 10849 10850 @Override 10851 public void setMagnificationSpec(MagnificationSpec spec) { 10852 synchronized (mWindowMap) { 10853 if (mAccessibilityController != null) { 10854 mAccessibilityController.setMagnificationSpecLocked(spec); 10855 } else { 10856 throw new IllegalStateException("Magnification callbacks not set!"); 10857 } 10858 } 10859 if (Binder.getCallingPid() != android.os.Process.myPid()) { 10860 spec.recycle(); 10861 } 10862 } 10863 10864 @Override 10865 public void getMagnificationRegions(@NonNull Region outMagnified, 10866 @NonNull Region outAvailable) { 10867 synchronized (mWindowMap) { 10868 if (mAccessibilityController != null) { 10869 mAccessibilityController.getMagnificationRegionsLocked( 10870 outMagnified, outAvailable); 10871 } else { 10872 throw new IllegalStateException("Magnification callbacks not set!"); 10873 } 10874 } 10875 } 10876 10877 @Override 10878 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 10879 synchronized (mWindowMap) { 10880 WindowState windowState = mWindowMap.get(windowToken); 10881 if (windowState == null) { 10882 return null; 10883 } 10884 MagnificationSpec spec = null; 10885 if (mAccessibilityController != null) { 10886 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 10887 } 10888 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 10889 return null; 10890 } 10891 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 10892 spec.scale *= windowState.mGlobalScale; 10893 return spec; 10894 } 10895 } 10896 10897 @Override 10898 public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) { 10899 synchronized (mWindowMap) { 10900 if (mAccessibilityController == null) { 10901 mAccessibilityController = new AccessibilityController( 10902 WindowManagerService.this); 10903 } 10904 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 10905 if (!mAccessibilityController.hasCallbacksLocked()) { 10906 mAccessibilityController = null; 10907 } 10908 } 10909 } 10910 10911 @Override 10912 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 10913 synchronized (mWindowMap) { 10914 if (mAccessibilityController == null) { 10915 mAccessibilityController = new AccessibilityController( 10916 WindowManagerService.this); 10917 } 10918 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 10919 if (!mAccessibilityController.hasCallbacksLocked()) { 10920 mAccessibilityController = null; 10921 } 10922 } 10923 } 10924 10925 @Override 10926 public void setInputFilter(IInputFilter filter) { 10927 mInputManager.setInputFilter(filter); 10928 } 10929 10930 @Override 10931 public IBinder getFocusedWindowToken() { 10932 synchronized (mWindowMap) { 10933 WindowState windowState = getFocusedWindowLocked(); 10934 if (windowState != null) { 10935 return windowState.mClient.asBinder(); 10936 } 10937 return null; 10938 } 10939 } 10940 10941 @Override 10942 public boolean isKeyguardLocked() { 10943 return WindowManagerService.this.isKeyguardLocked(); 10944 } 10945 10946 @Override 10947 public void showGlobalActions() { 10948 WindowManagerService.this.showGlobalActions(); 10949 } 10950 10951 @Override 10952 public void getWindowFrame(IBinder token, Rect outBounds) { 10953 synchronized (mWindowMap) { 10954 WindowState windowState = mWindowMap.get(token); 10955 if (windowState != null) { 10956 outBounds.set(windowState.mFrame); 10957 } else { 10958 outBounds.setEmpty(); 10959 } 10960 } 10961 } 10962 10963 @Override 10964 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 10965 boolean allWindowsDrawn = false; 10966 synchronized (mWindowMap) { 10967 mWaitingForDrawnCallback = callback; 10968 final WindowList windows = getDefaultWindowListLocked(); 10969 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 10970 final WindowState win = windows.get(winNdx); 10971 final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs); 10972 if (win.isVisibleLw() 10973 && (win.mAppToken != null || isForceHiding)) { 10974 win.mWinAnimator.mDrawState = DRAW_PENDING; 10975 // Force add to mResizingWindows. 10976 win.mLastContentInsets.set(-1, -1, -1, -1); 10977 mWaitingForDrawn.add(win); 10978 10979 // No need to wait for the windows below Keyguard. 10980 if (isForceHiding) { 10981 break; 10982 } 10983 } 10984 } 10985 mWindowPlacerLocked.requestTraversal(); 10986 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 10987 if (mWaitingForDrawn.isEmpty()) { 10988 allWindowsDrawn = true; 10989 } else { 10990 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 10991 checkDrawnWindowsLocked(); 10992 } 10993 } 10994 if (allWindowsDrawn) { 10995 callback.run(); 10996 } 10997 } 10998 10999 @Override 11000 public void addWindowToken(IBinder token, int type) { 11001 WindowManagerService.this.addWindowToken(token, type); 11002 } 11003 11004 @Override 11005 public void removeWindowToken(IBinder token, boolean removeWindows) { 11006 synchronized(mWindowMap) { 11007 if (removeWindows) { 11008 WindowToken wtoken = mTokenMap.remove(token); 11009 if (wtoken != null) { 11010 wtoken.removeAllWindows(); 11011 } 11012 } 11013 WindowManagerService.this.removeWindowToken(token); 11014 } 11015 } 11016 11017 @Override 11018 public void registerAppTransitionListener(AppTransitionListener listener) { 11019 synchronized (mWindowMap) { 11020 mAppTransition.registerListenerLocked(listener); 11021 } 11022 } 11023 11024 @Override 11025 public int getInputMethodWindowVisibleHeight() { 11026 synchronized (mWindowMap) { 11027 return mPolicy.getInputMethodWindowVisibleHeightLw(); 11028 } 11029 } 11030 11031 @Override 11032 public void saveLastInputMethodWindowForTransition() { 11033 synchronized (mWindowMap) { 11034 if (mInputMethodWindow != null) { 11035 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 11036 } 11037 } 11038 } 11039 11040 @Override 11041 public boolean isHardKeyboardAvailable() { 11042 synchronized (mWindowMap) { 11043 return mHardKeyboardAvailable; 11044 } 11045 } 11046 11047 @Override 11048 public void setOnHardKeyboardStatusChangeListener( 11049 OnHardKeyboardStatusChangeListener listener) { 11050 synchronized (mWindowMap) { 11051 mHardKeyboardStatusChangeListener = listener; 11052 } 11053 } 11054 11055 @Override 11056 public boolean isStackVisible(int stackId) { 11057 synchronized (mWindowMap) { 11058 return WindowManagerService.this.isStackVisibleLocked(stackId); 11059 } 11060 } 11061 11062 @Override 11063 public boolean isDockedDividerResizing() { 11064 synchronized (mWindowMap) { 11065 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing(); 11066 } 11067 } 11068 } 11069} 11070