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