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