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