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