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