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