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