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