WindowManagerService.java revision 19d9a8f47625319406f593d4ec71de0c8df1fcfe
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.clearAllDrawn(); 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 flag 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.clearAllDrawn(); 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 wtoken.setVisibleBeforeClientHidden(); 4427 } else if (visible) { 4428 if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) { 4429 // Add the app mOpeningApps if transition is unset but ready. This means 4430 // we're doing a screen freeze, and the unfreeze will wait for all opening 4431 // apps to be ready. 4432 mOpeningApps.add(wtoken); 4433 } 4434 wtoken.startingMoved = false; 4435 // If the token is currently hidden (should be the common case), or has been 4436 // stopped, then we need to set up to wait for its windows to be ready. 4437 if (wtoken.hidden || wtoken.mAppStopped) { 4438 wtoken.clearAllDrawn(); 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 final int imeHeight = mPolicy.getInputMethodWindowVisibleHeightLw(); 7539 final boolean imeHeightChanged = imeVisible && 7540 imeHeight != displayContent.mDividerControllerLocked.getImeHeightAdjustedFor(); 7541 7542 // The divider could be adjusted for IME position, or be thinner than usual, 7543 // or both. There are three possible cases: 7544 // - If IME is visible, and focus is on top, divider is not moved for IME but thinner. 7545 // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner. 7546 // - If IME is not visible, divider is not moved and is normal width. 7547 7548 if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) { 7549 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 7550 for (int i = stacks.size() - 1; i >= 0; --i) { 7551 final TaskStack stack = stacks.get(i); 7552 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM; 7553 if (stack.isVisibleLocked() && (imeOnBottom || isDockedOnBottom)) { 7554 stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged); 7555 } else { 7556 stack.resetAdjustedForIme(false); 7557 } 7558 } 7559 displayContent.mDividerControllerLocked.setAdjustedForIme( 7560 imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight); 7561 } else { 7562 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 7563 for (int i = stacks.size() - 1; i >= 0; --i) { 7564 final TaskStack stack = stacks.get(i); 7565 stack.resetAdjustedForIme(!dockVisible); 7566 } 7567 displayContent.mDividerControllerLocked.setAdjustedForIme( 7568 false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight); 7569 } 7570 } 7571 7572 // ------------------------------------------------------------- 7573 // Drag and drop 7574 // ------------------------------------------------------------- 7575 7576 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 7577 int flags, int width, int height, Surface outSurface) { 7578 if (DEBUG_DRAG) { 7579 Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height 7580 + " flags=" + Integer.toHexString(flags) + " win=" + window 7581 + " asbinder=" + window.asBinder()); 7582 } 7583 7584 final int callerPid = Binder.getCallingPid(); 7585 final int callerUid = Binder.getCallingUid(); 7586 final long origId = Binder.clearCallingIdentity(); 7587 IBinder token = null; 7588 7589 try { 7590 synchronized (mWindowMap) { 7591 try { 7592 if (mDragState == null) { 7593 // TODO(multi-display): support other displays 7594 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7595 final Display display = displayContent.getDisplay(); 7596 7597 SurfaceControl surface = new SurfaceControl(session, "drag surface", 7598 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 7599 surface.setLayerStack(display.getLayerStack()); 7600 float alpha = 1; 7601 if ((flags & View.DRAG_FLAG_OPAQUE) == 0) { 7602 alpha = DRAG_SHADOW_ALPHA_TRANSPARENT; 7603 } 7604 surface.setAlpha(alpha); 7605 7606 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG " 7607 + surface + ": CREATE"); 7608 outSurface.copyFrom(surface); 7609 final IBinder winBinder = window.asBinder(); 7610 token = new Binder(); 7611 mDragState = new DragState(this, token, surface, flags, winBinder); 7612 mDragState.mPid = callerPid; 7613 mDragState.mUid = callerUid; 7614 mDragState.mOriginalAlpha = alpha; 7615 token = mDragState.mToken = new Binder(); 7616 7617 // 5 second timeout for this window to actually begin the drag 7618 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 7619 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 7620 mH.sendMessageDelayed(msg, 5000); 7621 } else { 7622 Slog.w(TAG_WM, "Drag already in progress"); 7623 } 7624 } catch (OutOfResourcesException e) { 7625 Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e); 7626 if (mDragState != null) { 7627 mDragState.reset(); 7628 mDragState = null; 7629 } 7630 } 7631 } 7632 } finally { 7633 Binder.restoreCallingIdentity(origId); 7634 } 7635 7636 return token; 7637 } 7638 7639 // ------------------------------------------------------------- 7640 // Input Events and Focus Management 7641 // ------------------------------------------------------------- 7642 7643 final InputMonitor mInputMonitor = new InputMonitor(this); 7644 private boolean mEventDispatchingEnabled; 7645 7646 @Override 7647 public void pauseKeyDispatching(IBinder _token) { 7648 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7649 "pauseKeyDispatching()")) { 7650 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7651 } 7652 7653 synchronized (mWindowMap) { 7654 WindowToken token = mTokenMap.get(_token); 7655 if (token != null) { 7656 mInputMonitor.pauseDispatchingLw(token); 7657 } 7658 } 7659 } 7660 7661 @Override 7662 public void resumeKeyDispatching(IBinder _token) { 7663 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7664 "resumeKeyDispatching()")) { 7665 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7666 } 7667 7668 synchronized (mWindowMap) { 7669 WindowToken token = mTokenMap.get(_token); 7670 if (token != null) { 7671 mInputMonitor.resumeDispatchingLw(token); 7672 } 7673 } 7674 } 7675 7676 @Override 7677 public void setEventDispatching(boolean enabled) { 7678 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7679 "setEventDispatching()")) { 7680 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7681 } 7682 7683 synchronized (mWindowMap) { 7684 mEventDispatchingEnabled = enabled; 7685 if (mDisplayEnabled) { 7686 mInputMonitor.setEventDispatchingLw(enabled); 7687 } 7688 } 7689 } 7690 7691 private WindowState getFocusedWindow() { 7692 synchronized (mWindowMap) { 7693 return getFocusedWindowLocked(); 7694 } 7695 } 7696 7697 private WindowState getFocusedWindowLocked() { 7698 return mCurrentFocus; 7699 } 7700 7701 TaskStack getImeTargetStackLocked() { 7702 // Don't use WindowState.getStack() because it returns home stack for system windows. 7703 Task imeTask = mInputMethodTarget != null ? mInputMethodTarget.getTask() : null; 7704 return imeTask != null ? imeTask.mStack : null; 7705 } 7706 7707 private void showAuditSafeModeNotification() { 7708 PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, 7709 new Intent(Intent.ACTION_VIEW, 7710 Uri.parse("https://support.google.com/nexus/answer/2852139")), 0); 7711 7712 String title = mContext.getString(R.string.audit_safemode_notification); 7713 7714 Notification notification = new Notification.Builder(mContext) 7715 .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning) 7716 .setWhen(0) 7717 .setOngoing(true) 7718 .setTicker(title) 7719 .setLocalOnly(true) 7720 .setPriority(Notification.PRIORITY_HIGH) 7721 .setVisibility(Notification.VISIBILITY_PUBLIC) 7722 .setColor(mContext.getColor( 7723 com.android.internal.R.color.system_notification_accent_color)) 7724 .setContentTitle(title) 7725 .setContentText(mContext.getString(R.string.audit_safemode_notification_details)) 7726 .setContentIntent(pendingIntent) 7727 .build(); 7728 7729 NotificationManager notificationManager = (NotificationManager) mContext 7730 .getSystemService(Context.NOTIFICATION_SERVICE); 7731 7732 notificationManager.notifyAsUser(null, R.string.audit_safemode_notification, notification, 7733 UserHandle.ALL); 7734 } 7735 7736 public boolean detectSafeMode() { 7737 if (!mInputMonitor.waitForInputDevicesReady( 7738 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7739 Slog.w(TAG_WM, "Devices still not ready after waiting " 7740 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7741 + " milliseconds before attempting to detect safe mode."); 7742 } 7743 7744 if (Settings.Global.getInt( 7745 mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) { 7746 return false; 7747 } 7748 7749 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7750 KeyEvent.KEYCODE_MENU); 7751 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7752 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7753 KeyEvent.KEYCODE_DPAD_CENTER); 7754 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7755 InputManagerService.BTN_MOUSE); 7756 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7757 KeyEvent.KEYCODE_VOLUME_DOWN); 7758 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7759 || volumeDownState > 0; 7760 try { 7761 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0 7762 || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) { 7763 int auditSafeMode = SystemProperties.getInt(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, 0); 7764 7765 if (auditSafeMode == 0) { 7766 mSafeMode = true; 7767 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7768 } else { 7769 // stay in safe mode until we have updated to a newer build 7770 int buildDate = SystemProperties.getInt(PROPERTY_BUILD_DATE_UTC, 0); 7771 7772 if (auditSafeMode >= buildDate) { 7773 mSafeMode = true; 7774 showAuditSafeModeNotification(); 7775 } else { 7776 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7777 SystemProperties.set(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, ""); 7778 } 7779 } 7780 } 7781 } catch (IllegalArgumentException e) { 7782 } 7783 if (mSafeMode) { 7784 Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7785 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7786 SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1"); 7787 } else { 7788 Log.i(TAG_WM, "SAFE MODE not enabled"); 7789 } 7790 mPolicy.setSafeMode(mSafeMode); 7791 return mSafeMode; 7792 } 7793 7794 public void displayReady() { 7795 for (Display display : mDisplays) { 7796 displayReady(display.getDisplayId()); 7797 } 7798 7799 synchronized(mWindowMap) { 7800 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7801 readForcedDisplayPropertiesLocked(displayContent); 7802 mDisplayReady = true; 7803 } 7804 7805 try { 7806 mActivityManager.updateConfiguration(null); 7807 } catch (RemoteException e) { 7808 } 7809 7810 synchronized(mWindowMap) { 7811 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7812 PackageManager.FEATURE_TOUCHSCREEN); 7813 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7814 } 7815 7816 try { 7817 mActivityManager.updateConfiguration(null); 7818 } catch (RemoteException e) { 7819 } 7820 7821 updateCircularDisplayMaskIfNeeded(); 7822 } 7823 7824 private void displayReady(int displayId) { 7825 synchronized(mWindowMap) { 7826 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7827 if (displayContent != null) { 7828 mAnimator.addDisplayLocked(displayId); 7829 displayContent.initializeDisplayBaseInfo(); 7830 if (displayContent.mTapDetector != null) { 7831 displayContent.mTapDetector.init(); 7832 } 7833 } 7834 } 7835 } 7836 7837 public void systemReady() { 7838 mPolicy.systemReady(); 7839 } 7840 7841 // ------------------------------------------------------------- 7842 // Async Handler 7843 // ------------------------------------------------------------- 7844 7845 final class H extends Handler { 7846 public static final int REPORT_FOCUS_CHANGE = 2; 7847 public static final int REPORT_LOSING_FOCUS = 3; 7848 public static final int DO_TRAVERSAL = 4; 7849 public static final int ADD_STARTING = 5; 7850 public static final int REMOVE_STARTING = 6; 7851 public static final int FINISHED_STARTING = 7; 7852 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7853 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7854 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7855 7856 public static final int APP_TRANSITION_TIMEOUT = 13; 7857 public static final int PERSIST_ANIMATION_SCALE = 14; 7858 public static final int FORCE_GC = 15; 7859 public static final int ENABLE_SCREEN = 16; 7860 public static final int APP_FREEZE_TIMEOUT = 17; 7861 public static final int SEND_NEW_CONFIGURATION = 18; 7862 public static final int REPORT_WINDOWS_CHANGE = 19; 7863 public static final int DRAG_START_TIMEOUT = 20; 7864 public static final int DRAG_END_TIMEOUT = 21; 7865 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7866 public static final int BOOT_TIMEOUT = 23; 7867 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7868 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7869 public static final int DO_ANIMATION_CALLBACK = 26; 7870 7871 public static final int DO_DISPLAY_ADDED = 27; 7872 public static final int DO_DISPLAY_REMOVED = 28; 7873 public static final int DO_DISPLAY_CHANGED = 29; 7874 7875 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7876 public static final int TAP_OUTSIDE_TASK = 31; 7877 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7878 7879 public static final int ALL_WINDOWS_DRAWN = 33; 7880 7881 public static final int NEW_ANIMATOR_SCALE = 34; 7882 7883 public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35; 7884 public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36; 7885 7886 public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37; 7887 public static final int RESET_ANR_MESSAGE = 38; 7888 public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39; 7889 7890 public static final int FINISH_TASK_POSITIONING = 40; 7891 7892 public static final int UPDATE_DOCKED_STACK_DIVIDER = 41; 7893 7894 public static final int RESIZE_STACK = 42; 7895 public static final int RESIZE_TASK = 43; 7896 7897 public static final int TWO_FINGER_SCROLL_START = 44; 7898 7899 public static final int WINDOW_REPLACEMENT_TIMEOUT = 46; 7900 7901 public static final int NOTIFY_APP_TRANSITION_STARTING = 47; 7902 public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48; 7903 public static final int NOTIFY_APP_TRANSITION_FINISHED = 49; 7904 public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50; 7905 public static final int UPDATE_ANIMATION_SCALE = 51; 7906 public static final int WINDOW_REMOVE_TIMEOUT = 52; 7907 7908 public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53; 7909 7910 /** 7911 * Used to denote that an integer field in a message will not be used. 7912 */ 7913 public static final int UNUSED = 0; 7914 7915 @Override 7916 public void handleMessage(Message msg) { 7917 if (DEBUG_WINDOW_TRACE) { 7918 Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what); 7919 } 7920 switch (msg.what) { 7921 case REPORT_FOCUS_CHANGE: { 7922 WindowState lastFocus; 7923 WindowState newFocus; 7924 7925 AccessibilityController accessibilityController = null; 7926 7927 synchronized(mWindowMap) { 7928 // TODO(multidisplay): Accessibility supported only of default desiplay. 7929 if (mAccessibilityController != null && getDefaultDisplayContentLocked() 7930 .getDisplayId() == Display.DEFAULT_DISPLAY) { 7931 accessibilityController = mAccessibilityController; 7932 } 7933 7934 lastFocus = mLastFocus; 7935 newFocus = mCurrentFocus; 7936 if (lastFocus == newFocus) { 7937 // Focus is not changing, so nothing to do. 7938 return; 7939 } 7940 mLastFocus = newFocus; 7941 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus + 7942 " to " + newFocus); 7943 if (newFocus != null && lastFocus != null 7944 && !newFocus.isDisplayedLw()) { 7945 //Slog.i(TAG_WM, "Delaying loss of focus..."); 7946 mLosingFocus.add(lastFocus); 7947 lastFocus = null; 7948 } 7949 } 7950 7951 // First notify the accessibility manager for the change so it has 7952 // the windows before the newly focused one starts firing eventgs. 7953 if (accessibilityController != null) { 7954 accessibilityController.onWindowFocusChangedNotLocked(); 7955 } 7956 7957 //System.out.println("Changing focus from " + lastFocus 7958 // + " to " + newFocus); 7959 if (newFocus != null) { 7960 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus); 7961 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7962 notifyFocusChanged(); 7963 } 7964 7965 if (lastFocus != null) { 7966 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus); 7967 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7968 } 7969 } break; 7970 7971 case REPORT_LOSING_FOCUS: { 7972 ArrayList<WindowState> losers; 7973 7974 synchronized(mWindowMap) { 7975 losers = mLosingFocus; 7976 mLosingFocus = new ArrayList<WindowState>(); 7977 } 7978 7979 final int N = losers.size(); 7980 for (int i=0; i<N; i++) { 7981 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " + 7982 losers.get(i)); 7983 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7984 } 7985 } break; 7986 7987 case DO_TRAVERSAL: { 7988 synchronized(mWindowMap) { 7989 mWindowPlacerLocked.performSurfacePlacement(); 7990 } 7991 } break; 7992 7993 case ADD_STARTING: { 7994 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7995 final StartingData sd = wtoken.startingData; 7996 7997 if (sd == null) { 7998 // Animation has been canceled... do nothing. 7999 return; 8000 } 8001 8002 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting " 8003 + wtoken + ": pkg=" + sd.pkg); 8004 8005 View view = null; 8006 try { 8007 final Configuration overrideConfig = wtoken != null && wtoken.mTask != null 8008 ? wtoken.mTask.mOverrideConfig : null; 8009 view = mPolicy.addStartingWindow(wtoken.token, sd.pkg, sd.theme, 8010 sd.compatInfo, sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, 8011 sd.windowFlags, overrideConfig); 8012 } catch (Exception e) { 8013 Slog.w(TAG_WM, "Exception when adding starting window", e); 8014 } 8015 8016 if (view != null) { 8017 boolean abort = false; 8018 8019 synchronized(mWindowMap) { 8020 if (wtoken.removed || wtoken.startingData == null) { 8021 // If the window was successfully added, then 8022 // we need to remove it. 8023 if (wtoken.startingWindow != null) { 8024 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, 8025 "Aborted starting " + wtoken 8026 + ": removed=" + wtoken.removed 8027 + " startingData=" + wtoken.startingData); 8028 wtoken.startingWindow = null; 8029 wtoken.startingData = null; 8030 abort = true; 8031 } 8032 } else { 8033 wtoken.startingView = view; 8034 } 8035 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM, 8036 "Added starting " + wtoken 8037 + ": startingWindow=" 8038 + wtoken.startingWindow + " startingView=" 8039 + wtoken.startingView); 8040 } 8041 8042 if (abort) { 8043 try { 8044 mPolicy.removeStartingWindow(wtoken.token, view); 8045 } catch (Exception e) { 8046 Slog.w(TAG_WM, "Exception when removing starting window", e); 8047 } 8048 } 8049 } 8050 } break; 8051 8052 case REMOVE_STARTING: { 8053 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 8054 IBinder token = null; 8055 View view = null; 8056 synchronized (mWindowMap) { 8057 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting " 8058 + wtoken + ": startingWindow=" 8059 + wtoken.startingWindow + " startingView=" 8060 + wtoken.startingView); 8061 if (wtoken.startingWindow != null) { 8062 view = wtoken.startingView; 8063 token = wtoken.token; 8064 wtoken.startingData = null; 8065 wtoken.startingView = null; 8066 wtoken.startingWindow = null; 8067 wtoken.startingDisplayed = false; 8068 } 8069 } 8070 if (view != null) { 8071 try { 8072 mPolicy.removeStartingWindow(token, view); 8073 } catch (Exception e) { 8074 Slog.w(TAG_WM, "Exception when removing starting window", e); 8075 } 8076 } 8077 } break; 8078 8079 case FINISHED_STARTING: { 8080 IBinder token = null; 8081 View view = null; 8082 while (true) { 8083 synchronized (mWindowMap) { 8084 final int N = mFinishedStarting.size(); 8085 if (N <= 0) { 8086 break; 8087 } 8088 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 8089 8090 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, 8091 "Finished starting " + wtoken 8092 + ": startingWindow=" + wtoken.startingWindow 8093 + " startingView=" + wtoken.startingView); 8094 8095 if (wtoken.startingWindow == null) { 8096 continue; 8097 } 8098 8099 view = wtoken.startingView; 8100 token = wtoken.token; 8101 wtoken.startingData = null; 8102 wtoken.startingView = null; 8103 wtoken.startingWindow = null; 8104 wtoken.startingDisplayed = false; 8105 } 8106 8107 try { 8108 mPolicy.removeStartingWindow(token, view); 8109 } catch (Exception e) { 8110 Slog.w(TAG_WM, "Exception when removing starting window", e); 8111 } 8112 } 8113 } break; 8114 8115 case REPORT_APPLICATION_TOKEN_DRAWN: { 8116 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 8117 8118 try { 8119 if (DEBUG_VISIBILITY) Slog.v( 8120 TAG_WM, "Reporting drawn in " + wtoken); 8121 wtoken.appToken.windowsDrawn(); 8122 } catch (RemoteException ex) { 8123 } 8124 } break; 8125 8126 case REPORT_APPLICATION_TOKEN_WINDOWS: { 8127 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 8128 8129 boolean nowVisible = msg.arg1 != 0; 8130 boolean nowGone = msg.arg2 != 0; 8131 8132 try { 8133 if (DEBUG_VISIBILITY) Slog.v( 8134 TAG_WM, "Reporting visible in " + wtoken 8135 + " visible=" + nowVisible 8136 + " gone=" + nowGone); 8137 if (nowVisible) { 8138 wtoken.appToken.windowsVisible(); 8139 } else { 8140 wtoken.appToken.windowsGone(); 8141 } 8142 } catch (RemoteException ex) { 8143 } 8144 } break; 8145 8146 case WINDOW_FREEZE_TIMEOUT: { 8147 // TODO(multidisplay): Can non-default displays rotate? 8148 synchronized (mWindowMap) { 8149 Slog.w(TAG_WM, "Window freeze timeout expired."); 8150 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 8151 final WindowList windows = getDefaultWindowListLocked(); 8152 int i = windows.size(); 8153 while (i > 0) { 8154 i--; 8155 WindowState w = windows.get(i); 8156 if (w.mOrientationChanging) { 8157 w.mOrientationChanging = false; 8158 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8159 - mDisplayFreezeTime); 8160 Slog.w(TAG_WM, "Force clearing orientation change: " + w); 8161 } 8162 } 8163 mWindowPlacerLocked.performSurfacePlacement(); 8164 } 8165 break; 8166 } 8167 8168 case APP_TRANSITION_TIMEOUT: { 8169 synchronized (mWindowMap) { 8170 if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty() 8171 || !mClosingApps.isEmpty()) { 8172 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "*** APP TRANSITION TIMEOUT." 8173 + " isTransitionSet()=" + mAppTransition.isTransitionSet() 8174 + " mOpeningApps.size()=" + mOpeningApps.size() 8175 + " mClosingApps.size()=" + mClosingApps.size()); 8176 mAppTransition.setTimeout(); 8177 mWindowPlacerLocked.performSurfacePlacement(); 8178 } 8179 } 8180 break; 8181 } 8182 8183 case PERSIST_ANIMATION_SCALE: { 8184 Settings.Global.putFloat(mContext.getContentResolver(), 8185 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 8186 Settings.Global.putFloat(mContext.getContentResolver(), 8187 Settings.Global.TRANSITION_ANIMATION_SCALE, 8188 mTransitionAnimationScaleSetting); 8189 Settings.Global.putFloat(mContext.getContentResolver(), 8190 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting); 8191 break; 8192 } 8193 8194 case UPDATE_ANIMATION_SCALE: { 8195 @UpdateAnimationScaleMode 8196 final int mode = msg.arg1; 8197 switch (mode) { 8198 case WINDOW_ANIMATION_SCALE: { 8199 mWindowAnimationScaleSetting = Settings.Global.getFloat( 8200 mContext.getContentResolver(), 8201 Settings.Global.WINDOW_ANIMATION_SCALE, 8202 mWindowAnimationScaleSetting); 8203 break; 8204 } 8205 case TRANSITION_ANIMATION_SCALE: { 8206 mTransitionAnimationScaleSetting = Settings.Global.getFloat( 8207 mContext.getContentResolver(), 8208 Settings.Global.TRANSITION_ANIMATION_SCALE, 8209 mTransitionAnimationScaleSetting); 8210 break; 8211 } 8212 case ANIMATION_DURATION_SCALE: { 8213 mAnimatorDurationScaleSetting = Settings.Global.getFloat( 8214 mContext.getContentResolver(), 8215 Settings.Global.ANIMATOR_DURATION_SCALE, 8216 mAnimatorDurationScaleSetting); 8217 dispatchNewAnimatorScaleLocked(null); 8218 break; 8219 } 8220 } 8221 break; 8222 } 8223 8224 case FORCE_GC: { 8225 synchronized (mWindowMap) { 8226 // Since we're holding both mWindowMap and mAnimator we don't need to 8227 // hold mAnimator.mLayoutToAnim. 8228 if (mAnimator.isAnimating() || mAnimationScheduled) { 8229 // If we are animating, don't do the gc now but 8230 // delay a bit so we don't interrupt the animation. 8231 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 8232 return; 8233 } 8234 // If we are currently rotating the display, it will 8235 // schedule a new message when done. 8236 if (mDisplayFrozen) { 8237 return; 8238 } 8239 } 8240 Runtime.getRuntime().gc(); 8241 break; 8242 } 8243 8244 case ENABLE_SCREEN: { 8245 performEnableScreen(); 8246 break; 8247 } 8248 8249 case APP_FREEZE_TIMEOUT: { 8250 synchronized (mWindowMap) { 8251 Slog.w(TAG_WM, "App freeze timeout expired."); 8252 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 8253 final int numStacks = mStackIdToStack.size(); 8254 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8255 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 8256 final ArrayList<Task> tasks = stack.getTasks(); 8257 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8258 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8259 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8260 AppWindowToken tok = tokens.get(tokenNdx); 8261 if (tok.mAppAnimator.freezingScreen) { 8262 Slog.w(TAG_WM, "Force clearing freeze: " + tok); 8263 unsetAppFreezingScreenLocked(tok, true, true); 8264 } 8265 } 8266 } 8267 } 8268 } 8269 break; 8270 } 8271 8272 case CLIENT_FREEZE_TIMEOUT: { 8273 synchronized (mWindowMap) { 8274 if (mClientFreezingScreen) { 8275 mClientFreezingScreen = false; 8276 mLastFinishedFreezeSource = "client-timeout"; 8277 stopFreezingDisplayLocked(); 8278 } 8279 } 8280 break; 8281 } 8282 8283 case SEND_NEW_CONFIGURATION: { 8284 removeMessages(SEND_NEW_CONFIGURATION); 8285 sendNewConfiguration(); 8286 break; 8287 } 8288 8289 case REPORT_WINDOWS_CHANGE: { 8290 if (mWindowsChanged) { 8291 synchronized (mWindowMap) { 8292 mWindowsChanged = false; 8293 } 8294 notifyWindowsChanged(); 8295 } 8296 break; 8297 } 8298 8299 case DRAG_START_TIMEOUT: { 8300 IBinder win = (IBinder)msg.obj; 8301 if (DEBUG_DRAG) { 8302 Slog.w(TAG_WM, "Timeout starting drag by win " + win); 8303 } 8304 synchronized (mWindowMap) { 8305 // !!! TODO: ANR the app that has failed to start the drag in time 8306 if (mDragState != null) { 8307 mDragState.unregister(); 8308 mInputMonitor.updateInputWindowsLw(true /*force*/); 8309 mDragState.reset(); 8310 mDragState = null; 8311 } 8312 } 8313 break; 8314 } 8315 8316 case DRAG_END_TIMEOUT: { 8317 IBinder win = (IBinder)msg.obj; 8318 if (DEBUG_DRAG) { 8319 Slog.w(TAG_WM, "Timeout ending drag to win " + win); 8320 } 8321 synchronized (mWindowMap) { 8322 // !!! TODO: ANR the drag-receiving app 8323 if (mDragState != null) { 8324 mDragState.mDragResult = false; 8325 mDragState.endDragLw(); 8326 } 8327 } 8328 break; 8329 } 8330 8331 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 8332 notifyHardKeyboardStatusChange(); 8333 break; 8334 } 8335 8336 case BOOT_TIMEOUT: { 8337 performBootTimeout(); 8338 break; 8339 } 8340 8341 case WAITING_FOR_DRAWN_TIMEOUT: { 8342 Runnable callback = null; 8343 synchronized (mWindowMap) { 8344 Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 8345 mWaitingForDrawn.clear(); 8346 callback = mWaitingForDrawnCallback; 8347 mWaitingForDrawnCallback = null; 8348 } 8349 if (callback != null) { 8350 callback.run(); 8351 } 8352 break; 8353 } 8354 8355 case SHOW_STRICT_MODE_VIOLATION: { 8356 showStrictModeViolation(msg.arg1, msg.arg2); 8357 break; 8358 } 8359 8360 case SHOW_CIRCULAR_DISPLAY_MASK: { 8361 showCircularMask(msg.arg1 == 1); 8362 break; 8363 } 8364 8365 case SHOW_EMULATOR_DISPLAY_OVERLAY: { 8366 showEmulatorDisplayOverlay(); 8367 break; 8368 } 8369 8370 case DO_ANIMATION_CALLBACK: { 8371 try { 8372 ((IRemoteCallback)msg.obj).sendResult(null); 8373 } catch (RemoteException e) { 8374 } 8375 break; 8376 } 8377 8378 case DO_DISPLAY_ADDED: 8379 handleDisplayAdded(msg.arg1); 8380 break; 8381 8382 case DO_DISPLAY_REMOVED: 8383 synchronized (mWindowMap) { 8384 handleDisplayRemovedLocked(msg.arg1); 8385 } 8386 break; 8387 8388 case DO_DISPLAY_CHANGED: 8389 synchronized (mWindowMap) { 8390 handleDisplayChangedLocked(msg.arg1); 8391 } 8392 break; 8393 8394 case TWO_FINGER_SCROLL_START: { 8395 startScrollingTask((DisplayContent)msg.obj, msg.arg1, msg.arg2); 8396 } 8397 break; 8398 8399 case TAP_OUTSIDE_TASK: { 8400 handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2); 8401 } 8402 break; 8403 8404 case FINISH_TASK_POSITIONING: { 8405 finishPositioning(); 8406 } 8407 break; 8408 8409 case NOTIFY_ACTIVITY_DRAWN: 8410 try { 8411 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 8412 } catch (RemoteException e) { 8413 } 8414 break; 8415 case ALL_WINDOWS_DRAWN: { 8416 Runnable callback; 8417 synchronized (mWindowMap) { 8418 callback = mWaitingForDrawnCallback; 8419 mWaitingForDrawnCallback = null; 8420 } 8421 if (callback != null) { 8422 callback.run(); 8423 } 8424 } 8425 case NEW_ANIMATOR_SCALE: { 8426 float scale = getCurrentAnimatorScale(); 8427 ValueAnimator.setDurationScale(scale); 8428 Session session = (Session)msg.obj; 8429 if (session != null) { 8430 try { 8431 session.mCallback.onAnimatorScaleChanged(scale); 8432 } catch (RemoteException e) { 8433 } 8434 } else { 8435 ArrayList<IWindowSessionCallback> callbacks 8436 = new ArrayList<IWindowSessionCallback>(); 8437 synchronized (mWindowMap) { 8438 for (int i=0; i<mSessions.size(); i++) { 8439 callbacks.add(mSessions.valueAt(i).mCallback); 8440 } 8441 8442 } 8443 for (int i=0; i<callbacks.size(); i++) { 8444 try { 8445 callbacks.get(i).onAnimatorScaleChanged(scale); 8446 } catch (RemoteException e) { 8447 } 8448 } 8449 } 8450 } 8451 break; 8452 case CHECK_IF_BOOT_ANIMATION_FINISHED: { 8453 final boolean bootAnimationComplete; 8454 synchronized (mWindowMap) { 8455 if (DEBUG_BOOT) Slog.i(TAG_WM, "CHECK_IF_BOOT_ANIMATION_FINISHED:"); 8456 bootAnimationComplete = checkBootAnimationCompleteLocked(); 8457 } 8458 if (bootAnimationComplete) { 8459 performEnableScreen(); 8460 } 8461 } 8462 break; 8463 case RESET_ANR_MESSAGE: { 8464 synchronized (mWindowMap) { 8465 mLastANRState = null; 8466 } 8467 } 8468 break; 8469 case WALLPAPER_DRAW_PENDING_TIMEOUT: { 8470 synchronized (mWindowMap) { 8471 if (mWallpaperControllerLocked.processWallpaperDrawPendingTimeout()) { 8472 mWindowPlacerLocked.performSurfacePlacement(); 8473 } 8474 } 8475 } 8476 case UPDATE_DOCKED_STACK_DIVIDER: { 8477 synchronized (mWindowMap) { 8478 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8479 displayContent.getDockedDividerController().reevaluateVisibility(false); 8480 adjustForImeIfNeeded(displayContent); 8481 } 8482 } 8483 break; 8484 case RESIZE_TASK: { 8485 try { 8486 mActivityManager.resizeTask(msg.arg1, (Rect) msg.obj, msg.arg2); 8487 } catch (RemoteException e) { 8488 // This will not happen since we are in the same process. 8489 } 8490 } 8491 break; 8492 case RESIZE_STACK: { 8493 try { 8494 mActivityManager.resizeStack( 8495 msg.arg1, (Rect) msg.obj, msg.arg2 == 1, false, false, -1); 8496 } catch (RemoteException e) { 8497 // This will not happen since we are in the same process. 8498 } 8499 } 8500 break; 8501 case WINDOW_REPLACEMENT_TIMEOUT: { 8502 final AppWindowToken token = (AppWindowToken) msg.obj; 8503 synchronized (mWindowMap) { 8504 token.clearTimedoutReplacesLocked(); 8505 } 8506 } 8507 case NOTIFY_APP_TRANSITION_STARTING: { 8508 mAmInternal.notifyAppTransitionStarting(msg.arg1); 8509 } 8510 break; 8511 case NOTIFY_APP_TRANSITION_CANCELLED: { 8512 mAmInternal.notifyAppTransitionCancelled(); 8513 } 8514 break; 8515 case NOTIFY_APP_TRANSITION_FINISHED: { 8516 mAmInternal.notifyAppTransitionFinished(); 8517 } 8518 break; 8519 case NOTIFY_STARTING_WINDOW_DRAWN: { 8520 mAmInternal.notifyStartingWindowDrawn(); 8521 } 8522 break; 8523 case WINDOW_REMOVE_TIMEOUT: { 8524 final WindowState window = (WindowState) msg.obj; 8525 synchronized(mWindowMap) { 8526 // It's counterintuitive that we check that "mWindowRemovalAllowed" 8527 // is false. But in fact if it's true, it means a remove has already 8528 // been requested and we better just not do anything. 8529 if (!window.mRemoved && !window.mWindowRemovalAllowed) { 8530 removeWindowLocked(window); 8531 } 8532 } 8533 } 8534 break; 8535 case NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED: { 8536 mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1); 8537 } 8538 break; 8539 } 8540 if (DEBUG_WINDOW_TRACE) { 8541 Slog.v(TAG_WM, "handleMessage: exit"); 8542 } 8543 } 8544 } 8545 8546 void destroyPreservedSurfaceLocked() { 8547 for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) { 8548 final WindowState w = mDestroyPreservedSurface.get(i); 8549 w.mWinAnimator.destroyPreservedSurfaceLocked(); 8550 } 8551 mDestroyPreservedSurface.clear(); 8552 } 8553 // ------------------------------------------------------------- 8554 // IWindowManager API 8555 // ------------------------------------------------------------- 8556 8557 @Override 8558 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, 8559 IInputContext inputContext) { 8560 if (client == null) throw new IllegalArgumentException("null client"); 8561 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 8562 Session session = new Session(this, callback, client, inputContext); 8563 return session; 8564 } 8565 8566 @Override 8567 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 8568 synchronized (mWindowMap) { 8569 // The focus for the client is the window immediately below 8570 // where we would place the input method window. 8571 int idx = findDesiredInputMethodWindowIndexLocked(false); 8572 if (idx > 0) { 8573 // TODO(multidisplay): IMEs are only supported on the default display. 8574 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 8575 if (DEBUG_INPUT_METHOD) { 8576 Slog.i(TAG_WM, "Desired input method target: " + imFocus); 8577 Slog.i(TAG_WM, "Current focus: " + mCurrentFocus); 8578 Slog.i(TAG_WM, "Last focus: " + mLastFocus); 8579 } 8580 if (imFocus != null) { 8581 // This may be a starting window, in which case we still want 8582 // to count it as okay. 8583 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 8584 && imFocus.mAppToken != null) { 8585 // The client has definitely started, so it really should 8586 // have a window in this app token. Let's look for it. 8587 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 8588 WindowState w = imFocus.mAppToken.windows.get(i); 8589 if (w != imFocus) { 8590 Log.i(TAG_WM, "Switching to real app window: " + w); 8591 imFocus = w; 8592 break; 8593 } 8594 } 8595 } 8596 if (DEBUG_INPUT_METHOD) { 8597 Slog.i(TAG_WM, "IM target client: " + imFocus.mSession.mClient); 8598 if (imFocus.mSession.mClient != null) { 8599 Slog.i(TAG_WM, "IM target client binder: " 8600 + imFocus.mSession.mClient.asBinder()); 8601 Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder()); 8602 } 8603 } 8604 if (imFocus.mSession.mClient != null && 8605 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 8606 return true; 8607 } 8608 } 8609 } 8610 8611 // Okay, how about this... what is the current focus? 8612 // It seems in some cases we may not have moved the IM 8613 // target window, such as when it was in a pop-up window, 8614 // so let's also look at the current focus. (An example: 8615 // go to Gmail, start searching so the keyboard goes up, 8616 // press home. Sometimes the IME won't go down.) 8617 // Would be nice to fix this more correctly, but it's 8618 // way at the end of a release, and this should be good enough. 8619 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 8620 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 8621 return true; 8622 } 8623 } 8624 return false; 8625 } 8626 8627 @Override 8628 public void getInitialDisplaySize(int displayId, Point size) { 8629 synchronized (mWindowMap) { 8630 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8631 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8632 size.x = displayContent.mInitialDisplayWidth; 8633 size.y = displayContent.mInitialDisplayHeight; 8634 } 8635 } 8636 } 8637 8638 @Override 8639 public void getBaseDisplaySize(int displayId, Point size) { 8640 synchronized (mWindowMap) { 8641 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8642 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8643 size.x = displayContent.mBaseDisplayWidth; 8644 size.y = displayContent.mBaseDisplayHeight; 8645 } 8646 } 8647 } 8648 8649 @Override 8650 public void setForcedDisplaySize(int displayId, int width, int height) { 8651 if (mContext.checkCallingOrSelfPermission( 8652 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8653 PackageManager.PERMISSION_GRANTED) { 8654 throw new SecurityException("Must hold permission " + 8655 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8656 } 8657 if (displayId != Display.DEFAULT_DISPLAY) { 8658 throw new IllegalArgumentException("Can only set the default display"); 8659 } 8660 final long ident = Binder.clearCallingIdentity(); 8661 try { 8662 synchronized(mWindowMap) { 8663 // Set some sort of reasonable bounds on the size of the display that we 8664 // will try to emulate. 8665 final int MIN_WIDTH = 200; 8666 final int MIN_HEIGHT = 200; 8667 final int MAX_SCALE = 2; 8668 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8669 if (displayContent != null) { 8670 width = Math.min(Math.max(width, MIN_WIDTH), 8671 displayContent.mInitialDisplayWidth * MAX_SCALE); 8672 height = Math.min(Math.max(height, MIN_HEIGHT), 8673 displayContent.mInitialDisplayHeight * MAX_SCALE); 8674 setForcedDisplaySizeLocked(displayContent, width, height); 8675 Settings.Global.putString(mContext.getContentResolver(), 8676 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 8677 } 8678 } 8679 } finally { 8680 Binder.restoreCallingIdentity(ident); 8681 } 8682 } 8683 8684 @Override 8685 public void setForcedDisplayScalingMode(int displayId, int mode) { 8686 if (mContext.checkCallingOrSelfPermission( 8687 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8688 PackageManager.PERMISSION_GRANTED) { 8689 throw new SecurityException("Must hold permission " + 8690 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8691 } 8692 if (displayId != Display.DEFAULT_DISPLAY) { 8693 throw new IllegalArgumentException("Can only set the default display"); 8694 } 8695 final long ident = Binder.clearCallingIdentity(); 8696 try { 8697 synchronized(mWindowMap) { 8698 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8699 if (displayContent != null) { 8700 if (mode < 0 || mode > 1) { 8701 mode = 0; 8702 } 8703 setForcedDisplayScalingModeLocked(displayContent, mode); 8704 Settings.Global.putInt(mContext.getContentResolver(), 8705 Settings.Global.DISPLAY_SCALING_FORCE, mode); 8706 } 8707 } 8708 } finally { 8709 Binder.restoreCallingIdentity(ident); 8710 } 8711 } 8712 8713 private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) { 8714 Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off")); 8715 displayContent.mDisplayScalingDisabled = (mode != 0); 8716 reconfigureDisplayLocked(displayContent); 8717 } 8718 8719 private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) { 8720 // Display size. 8721 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 8722 Settings.Global.DISPLAY_SIZE_FORCED); 8723 if (sizeStr == null || sizeStr.length() == 0) { 8724 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 8725 } 8726 if (sizeStr != null && sizeStr.length() > 0) { 8727 final int pos = sizeStr.indexOf(','); 8728 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 8729 int width, height; 8730 try { 8731 width = Integer.parseInt(sizeStr.substring(0, pos)); 8732 height = Integer.parseInt(sizeStr.substring(pos+1)); 8733 if (displayContent.mBaseDisplayWidth != width 8734 || displayContent.mBaseDisplayHeight != height) { 8735 Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height); 8736 displayContent.mBaseDisplayWidth = width; 8737 displayContent.mBaseDisplayHeight = height; 8738 } 8739 } catch (NumberFormatException ex) { 8740 } 8741 } 8742 } 8743 8744 // Display density. 8745 final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId); 8746 if (density != 0) { 8747 displayContent.mBaseDisplayDensity = density; 8748 } 8749 8750 // Display scaling mode. 8751 int mode = Settings.Global.getInt(mContext.getContentResolver(), 8752 Settings.Global.DISPLAY_SCALING_FORCE, 0); 8753 if (mode != 0) { 8754 Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED"); 8755 displayContent.mDisplayScalingDisabled = true; 8756 } 8757 } 8758 8759 // displayContent must not be null 8760 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 8761 Slog.i(TAG_WM, "Using new display size: " + width + "x" + height); 8762 displayContent.mBaseDisplayWidth = width; 8763 displayContent.mBaseDisplayHeight = height; 8764 reconfigureDisplayLocked(displayContent); 8765 } 8766 8767 @Override 8768 public void clearForcedDisplaySize(int displayId) { 8769 if (mContext.checkCallingOrSelfPermission( 8770 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8771 PackageManager.PERMISSION_GRANTED) { 8772 throw new SecurityException("Must hold permission " + 8773 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8774 } 8775 if (displayId != Display.DEFAULT_DISPLAY) { 8776 throw new IllegalArgumentException("Can only set the default display"); 8777 } 8778 final long ident = Binder.clearCallingIdentity(); 8779 try { 8780 synchronized(mWindowMap) { 8781 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8782 if (displayContent != null) { 8783 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 8784 displayContent.mInitialDisplayHeight); 8785 Settings.Global.putString(mContext.getContentResolver(), 8786 Settings.Global.DISPLAY_SIZE_FORCED, ""); 8787 } 8788 } 8789 } finally { 8790 Binder.restoreCallingIdentity(ident); 8791 } 8792 } 8793 8794 @Override 8795 public int getInitialDisplayDensity(int displayId) { 8796 synchronized (mWindowMap) { 8797 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8798 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8799 return displayContent.mInitialDisplayDensity; 8800 } 8801 } 8802 return -1; 8803 } 8804 8805 @Override 8806 public int getBaseDisplayDensity(int displayId) { 8807 synchronized (mWindowMap) { 8808 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8809 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 8810 return displayContent.mBaseDisplayDensity; 8811 } 8812 } 8813 return -1; 8814 } 8815 8816 @Override 8817 public void setForcedDisplayDensity(int displayId, int density) { 8818 if (mContext.checkCallingOrSelfPermission( 8819 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8820 PackageManager.PERMISSION_GRANTED) { 8821 throw new SecurityException("Must hold permission " + 8822 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8823 } 8824 if (displayId != Display.DEFAULT_DISPLAY) { 8825 throw new IllegalArgumentException("Can only set the default display"); 8826 } 8827 final long ident = Binder.clearCallingIdentity(); 8828 try { 8829 synchronized(mWindowMap) { 8830 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8831 if (displayContent != null) { 8832 setForcedDisplayDensityLocked(displayContent, density); 8833 Settings.Secure.putStringForUser(mContext.getContentResolver(), 8834 Settings.Secure.DISPLAY_DENSITY_FORCED, 8835 Integer.toString(density), mCurrentUserId); 8836 } 8837 } 8838 } finally { 8839 Binder.restoreCallingIdentity(ident); 8840 } 8841 } 8842 8843 @Override 8844 public void clearForcedDisplayDensity(int displayId) { 8845 if (mContext.checkCallingOrSelfPermission( 8846 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8847 PackageManager.PERMISSION_GRANTED) { 8848 throw new SecurityException("Must hold permission " + 8849 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8850 } 8851 if (displayId != Display.DEFAULT_DISPLAY) { 8852 throw new IllegalArgumentException("Can only set the default display"); 8853 } 8854 final long ident = Binder.clearCallingIdentity(); 8855 try { 8856 synchronized(mWindowMap) { 8857 final DisplayContent displayContent = getDisplayContentLocked(displayId); 8858 if (displayContent != null) { 8859 setForcedDisplayDensityLocked(displayContent, 8860 displayContent.mInitialDisplayDensity); 8861 Settings.Secure.putStringForUser(mContext.getContentResolver(), 8862 Settings.Secure.DISPLAY_DENSITY_FORCED, "", mCurrentUserId); 8863 } 8864 } 8865 } finally { 8866 Binder.restoreCallingIdentity(ident); 8867 } 8868 } 8869 8870 /** 8871 * @param userId the ID of the user 8872 * @return the forced display density for the specified user, if set, or 8873 * {@code 0} if not set 8874 */ 8875 private int getForcedDisplayDensityForUserLocked(int userId) { 8876 String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(), 8877 Settings.Secure.DISPLAY_DENSITY_FORCED, userId); 8878 if (densityStr == null || densityStr.length() == 0) { 8879 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 8880 } 8881 if (densityStr != null && densityStr.length() > 0) { 8882 try { 8883 return Integer.parseInt(densityStr); 8884 } catch (NumberFormatException ex) { 8885 } 8886 } 8887 return 0; 8888 } 8889 8890 /** 8891 * Forces the given display to the use the specified density. 8892 * 8893 * @param displayContent the display to modify 8894 * @param density the density in DPI to use 8895 */ 8896 private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent, 8897 int density) { 8898 displayContent.mBaseDisplayDensity = density; 8899 reconfigureDisplayLocked(displayContent); 8900 } 8901 8902 // displayContent must not be null 8903 private void reconfigureDisplayLocked(DisplayContent displayContent) { 8904 // TODO: Multidisplay: for now only use with default display. 8905 if (!mDisplayReady) { 8906 return; 8907 } 8908 configureDisplayPolicyLocked(displayContent); 8909 displayContent.layoutNeeded = true; 8910 8911 boolean configChanged = updateOrientationFromAppTokensLocked(false); 8912 mTempConfiguration.setToDefaults(); 8913 mTempConfiguration.updateFrom(mCurConfiguration); 8914 computeScreenConfigurationLocked(mTempConfiguration); 8915 configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0; 8916 8917 if (configChanged) { 8918 mWaitingForConfig = true; 8919 startFreezingDisplayLocked(false, 0, 0); 8920 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8921 if (!mReconfigureOnConfigurationChanged.contains(displayContent)) { 8922 mReconfigureOnConfigurationChanged.add(displayContent); 8923 } 8924 } 8925 8926 mWindowPlacerLocked.performSurfacePlacement(); 8927 } 8928 8929 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8930 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8931 displayContent.mBaseDisplayWidth, 8932 displayContent.mBaseDisplayHeight, 8933 displayContent.mBaseDisplayDensity); 8934 8935 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8936 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8937 displayInfo.overscanLeft, displayInfo.overscanTop, 8938 displayInfo.overscanRight, displayInfo.overscanBottom); 8939 } 8940 8941 @Override 8942 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8943 if (mContext.checkCallingOrSelfPermission( 8944 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8945 PackageManager.PERMISSION_GRANTED) { 8946 throw new SecurityException("Must hold permission " + 8947 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8948 } 8949 final long ident = Binder.clearCallingIdentity(); 8950 try { 8951 synchronized(mWindowMap) { 8952 DisplayContent displayContent = getDisplayContentLocked(displayId); 8953 if (displayContent != null) { 8954 setOverscanLocked(displayContent, left, top, right, bottom); 8955 } 8956 } 8957 } finally { 8958 Binder.restoreCallingIdentity(ident); 8959 } 8960 } 8961 8962 private void setOverscanLocked(DisplayContent displayContent, 8963 int left, int top, int right, int bottom) { 8964 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8965 displayInfo.overscanLeft = left; 8966 displayInfo.overscanTop = top; 8967 displayInfo.overscanRight = right; 8968 displayInfo.overscanBottom = bottom; 8969 8970 mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top, 8971 right, bottom); 8972 mDisplaySettings.writeSettingsLocked(); 8973 8974 reconfigureDisplayLocked(displayContent); 8975 } 8976 8977 // ------------------------------------------------------------- 8978 // Internals 8979 // ------------------------------------------------------------- 8980 8981 final WindowState windowForClientLocked(Session session, IWindow client, 8982 boolean throwOnError) { 8983 return windowForClientLocked(session, client.asBinder(), throwOnError); 8984 } 8985 8986 final WindowState windowForClientLocked(Session session, IBinder client, 8987 boolean throwOnError) { 8988 WindowState win = mWindowMap.get(client); 8989 if (localLOGV) Slog.v( 8990 TAG_WM, "Looking up client " + client + ": " + win); 8991 if (win == null) { 8992 RuntimeException ex = new IllegalArgumentException( 8993 "Requested window " + client + " does not exist"); 8994 if (throwOnError) { 8995 throw ex; 8996 } 8997 Slog.w(TAG_WM, "Failed looking up window", ex); 8998 return null; 8999 } 9000 if (session != null && win.mSession != session) { 9001 RuntimeException ex = new IllegalArgumentException( 9002 "Requested window " + client + " is in session " + 9003 win.mSession + ", not " + session); 9004 if (throwOnError) { 9005 throw ex; 9006 } 9007 Slog.w(TAG_WM, "Failed looking up window", ex); 9008 return null; 9009 } 9010 9011 return win; 9012 } 9013 9014 final void rebuildAppWindowListLocked() { 9015 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 9016 } 9017 9018 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 9019 final WindowList windows = displayContent.getWindowList(); 9020 int NW = windows.size(); 9021 int i; 9022 int lastBelow = -1; 9023 int numRemoved = 0; 9024 9025 if (mRebuildTmp.length < NW) { 9026 mRebuildTmp = new WindowState[NW+10]; 9027 } 9028 9029 // First remove all existing app windows. 9030 i=0; 9031 while (i < NW) { 9032 WindowState w = windows.get(i); 9033 if (w.mAppToken != null) { 9034 WindowState win = windows.remove(i); 9035 win.mRebuilding = true; 9036 mRebuildTmp[numRemoved] = win; 9037 mWindowsChanged = true; 9038 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win); 9039 NW--; 9040 numRemoved++; 9041 continue; 9042 } else if (lastBelow == i-1) { 9043 if (w.mAttrs.type == TYPE_WALLPAPER) { 9044 lastBelow = i; 9045 } 9046 } 9047 i++; 9048 } 9049 9050 // Keep whatever windows were below the app windows still below, 9051 // by skipping them. 9052 lastBelow++; 9053 i = lastBelow; 9054 9055 // First add all of the exiting app tokens... these are no longer 9056 // in the main app list, but still have windows shown. We put them 9057 // in the back because now that the animation is over we no longer 9058 // will care about them. 9059 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 9060 final int numStacks = stacks.size(); 9061 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 9062 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 9063 int NT = exitingAppTokens.size(); 9064 for (int j = 0; j < NT; j++) { 9065 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 9066 } 9067 } 9068 9069 // And add in the still active app tokens in Z order. 9070 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 9071 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9072 final int numTasks = tasks.size(); 9073 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 9074 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9075 final int numTokens = tokens.size(); 9076 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 9077 final AppWindowToken wtoken = tokens.get(tokenNdx); 9078 if (wtoken.mIsExiting && !wtoken.waitingForReplacement()) { 9079 continue; 9080 } 9081 i = reAddAppWindowsLocked(displayContent, i, wtoken); 9082 } 9083 } 9084 } 9085 9086 i -= lastBelow; 9087 if (i != numRemoved) { 9088 displayContent.layoutNeeded = true; 9089 Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed " 9090 + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() " 9091 + " callers=" + Debug.getCallers(10)); 9092 for (i = 0; i < numRemoved; i++) { 9093 WindowState ws = mRebuildTmp[i]; 9094 if (ws.mRebuilding) { 9095 StringWriter sw = new StringWriter(); 9096 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 9097 ws.dump(pw, "", true); 9098 pw.flush(); 9099 Slog.w(TAG_WM, "This window was lost: " + ws); 9100 Slog.w(TAG_WM, sw.toString()); 9101 ws.mWinAnimator.destroySurfaceLocked(); 9102 } 9103 } 9104 Slog.w(TAG_WM, "Current app token list:"); 9105 dumpAppTokensLocked(); 9106 Slog.w(TAG_WM, "Final window list:"); 9107 dumpWindowsLocked(); 9108 } 9109 Arrays.fill(mRebuildTmp, null); 9110 } 9111 9112 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 9113 // If the screen is currently frozen or off, then keep 9114 // it frozen/off until this window draws at its new 9115 // orientation. 9116 if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { 9117 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w); 9118 w.mOrientationChanging = true; 9119 w.mLastFreezeDuration = 0; 9120 mWindowPlacerLocked.mOrientationChangeComplete = false; 9121 if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) { 9122 mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; 9123 // XXX should probably keep timeout from 9124 // when we first froze the display. 9125 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9126 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 9127 WINDOW_FREEZE_TIMEOUT_DURATION); 9128 } 9129 } 9130 } 9131 9132 /** 9133 * @return bitmap indicating if another pass through layout must be made. 9134 */ 9135 int handleAnimatingStoppedAndTransitionLocked() { 9136 int changes = 0; 9137 9138 mAppTransition.setIdle(); 9139 9140 for (int i = mNoAnimationNotifyOnTransitionFinished.size() - 1; i >= 0; i--) { 9141 final IBinder token = mNoAnimationNotifyOnTransitionFinished.get(i); 9142 mAppTransition.notifyAppTransitionFinishedLocked(token); 9143 } 9144 mNoAnimationNotifyOnTransitionFinished.clear(); 9145 9146 mWallpaperControllerLocked.hideDeferredWallpapersIfNeeded(); 9147 9148 // Restore window app tokens to the ActivityManager views 9149 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 9150 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9151 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9152 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9153 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9154 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9155 tokens.get(tokenNdx).sendingToBottom = false; 9156 } 9157 } 9158 } 9159 rebuildAppWindowListLocked(); 9160 9161 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 9162 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM, 9163 "Wallpaper layer changed: assigning layers + relayout"); 9164 moveInputMethodWindowsIfNeededLocked(true); 9165 mWindowPlacerLocked.mWallpaperMayChange = true; 9166 // Since the window list has been rebuilt, focus might 9167 // have to be recomputed since the actual order of windows 9168 // might have changed again. 9169 mFocusMayChange = true; 9170 9171 return changes; 9172 } 9173 9174 void updateResizingWindows(final WindowState w) { 9175 final WindowStateAnimator winAnimator = w.mWinAnimator; 9176 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq && !w.isGoneForLayoutLw()) { 9177 w.setInsetsChanged(); 9178 boolean configChanged = w.isConfigChanged(); 9179 if (DEBUG_CONFIGURATION && configChanged) { 9180 Slog.v(TAG_WM, "Win " + w + " config changed: " 9181 + mCurConfiguration); 9182 } 9183 final boolean dragResizingChanged = w.isDragResizeChanged() 9184 && !w.isDragResizingChangeReported(); 9185 if (localLOGV) Slog.v(TAG_WM, "Resizing " + w 9186 + ": configChanged=" + configChanged 9187 + " dragResizingChanged=" + dragResizingChanged 9188 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 9189 w.mLastFrame.set(w.mFrame); 9190 if (w.mContentInsetsChanged 9191 || w.mVisibleInsetsChanged 9192 || winAnimator.mSurfaceResized 9193 || w.mOutsetsChanged 9194 || configChanged 9195 || dragResizingChanged 9196 || w.mResizedWhileNotDragResizing) { 9197 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 9198 Slog.v(TAG_WM, "Resize reasons for w=" + w + ": " 9199 + " contentInsetsChanged=" + w.mContentInsetsChanged 9200 + " " + w.mContentInsets.toShortString() 9201 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 9202 + " " + w.mVisibleInsets.toShortString() 9203 + " stableInsetsChanged=" + w.mStableInsetsChanged 9204 + " " + w.mStableInsets.toShortString() 9205 + " outsetsChanged=" + w.mOutsetsChanged 9206 + " " + w.mOutsets.toShortString() 9207 + " surfaceResized=" + winAnimator.mSurfaceResized 9208 + " configChanged=" + configChanged 9209 + " dragResizingChanged=" + dragResizingChanged 9210 + " resizedWhileNotDragResizing=" + w.mResizedWhileNotDragResizing); 9211 } 9212 9213 // If it's a dead window left on screen, and the configuration changed, 9214 // there is nothing we can do about it. Remove the window now. 9215 if (w.mAppToken != null && w.mAppDied) { 9216 w.mAppToken.removeAllDeadWindows(); 9217 return; 9218 } 9219 9220 w.mLastOverscanInsets.set(w.mOverscanInsets); 9221 w.mLastContentInsets.set(w.mContentInsets); 9222 w.mLastVisibleInsets.set(w.mVisibleInsets); 9223 w.mLastStableInsets.set(w.mStableInsets); 9224 w.mLastOutsets.set(w.mOutsets); 9225 makeWindowFreezingScreenIfNeededLocked(w); 9226 // If the orientation is changing, or we're starting or ending 9227 // a drag resizing action, then we need to hold off on unfreezing 9228 // the display until this window has been redrawn; to do that, 9229 // we need to go through the process of getting informed by the 9230 // application when it has finished drawing. 9231 if (w.mOrientationChanging || dragResizingChanged 9232 || w.mResizedWhileNotDragResizing) { 9233 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) { 9234 Slog.v(TAG_WM, "Orientation or resize start waiting for draw" 9235 + ", mDrawState=DRAW_PENDING in " + w 9236 + ", surfaceController " + winAnimator.mSurfaceController); 9237 } 9238 winAnimator.mDrawState = DRAW_PENDING; 9239 if (w.mAppToken != null) { 9240 w.mAppToken.clearAllDrawn(); 9241 } 9242 } 9243 if (!mResizingWindows.contains(w)) { 9244 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM, 9245 "Resizing window " + w); 9246 mResizingWindows.add(w); 9247 } 9248 } else if (w.mOrientationChanging) { 9249 if (w.isDrawnLw()) { 9250 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 9251 "Orientation not waiting for draw in " 9252 + w + ", surfaceController " + winAnimator.mSurfaceController); 9253 w.mOrientationChanging = false; 9254 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 9255 - mDisplayFreezeTime); 9256 } 9257 } 9258 } 9259 } 9260 9261 void checkDrawnWindowsLocked() { 9262 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9263 return; 9264 } 9265 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9266 WindowState win = mWaitingForDrawn.get(j); 9267 if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win + 9268 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9269 " mHasSurface=" + win.mHasSurface + 9270 " drawState=" + win.mWinAnimator.mDrawState); 9271 if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) { 9272 // Window has been removed or hidden; no draw will now happen, so stop waiting. 9273 if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win); 9274 mWaitingForDrawn.remove(win); 9275 } else if (win.hasDrawnLw()) { 9276 // Window is now drawn (and shown). 9277 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win); 9278 mWaitingForDrawn.remove(win); 9279 } 9280 } 9281 if (mWaitingForDrawn.isEmpty()) { 9282 if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!"); 9283 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9284 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9285 } 9286 } 9287 9288 void setHoldScreenLocked(final Session newHoldScreen) { 9289 final boolean hold = newHoldScreen != null; 9290 9291 if (hold && mHoldingScreenOn != newHoldScreen) { 9292 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9293 } 9294 mHoldingScreenOn = newHoldScreen; 9295 9296 final boolean state = mHoldingScreenWakeLock.isHeld(); 9297 if (hold != state) { 9298 if (hold) { 9299 if (DEBUG_KEEP_SCREEN_ON) { 9300 Slog.d(TAG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to " + 9301 mWindowPlacerLocked.mHoldScreenWindow); 9302 } 9303 mLastWakeLockHoldingWindow = mWindowPlacerLocked.mHoldScreenWindow; 9304 mLastWakeLockObscuringWindow = null; 9305 mHoldingScreenWakeLock.acquire(); 9306 mPolicy.keepScreenOnStartedLw(); 9307 } else { 9308 if (DEBUG_KEEP_SCREEN_ON) { 9309 Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by " + 9310 mWindowPlacerLocked.mObsuringWindow); 9311 } 9312 mLastWakeLockHoldingWindow = null; 9313 mLastWakeLockObscuringWindow = mWindowPlacerLocked.mObsuringWindow; 9314 mPolicy.keepScreenOnStoppedLw(); 9315 mHoldingScreenWakeLock.release(); 9316 } 9317 } 9318 } 9319 9320 void requestTraversal() { 9321 synchronized (mWindowMap) { 9322 mWindowPlacerLocked.requestTraversal(); 9323 } 9324 } 9325 9326 /** Note that Locked in this case is on mLayoutToAnim */ 9327 void scheduleAnimationLocked() { 9328 if (!mAnimationScheduled) { 9329 mAnimationScheduled = true; 9330 mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback); 9331 } 9332 } 9333 9334 boolean needsLayout() { 9335 final int numDisplays = mDisplayContents.size(); 9336 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9337 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9338 if (displayContent.layoutNeeded) { 9339 return true; 9340 } 9341 } 9342 return false; 9343 } 9344 9345 /** If a window that has an animation specifying a colored background and the current wallpaper 9346 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9347 * suddenly disappear. */ 9348 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9349 WindowList windows = winAnimator.mWin.getWindowList(); 9350 for (int i = windows.size() - 1; i >= 0; --i) { 9351 WindowState testWin = windows.get(i); 9352 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9353 return testWin.mWinAnimator.mAnimLayer; 9354 } 9355 } 9356 return winAnimator.mAnimLayer; 9357 } 9358 9359 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9360 boolean secure) { 9361 final WindowSurfaceController surfaceController = winAnimator.mSurfaceController; 9362 boolean leakedSurface = false; 9363 boolean killedApps = false; 9364 9365 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9366 winAnimator.mSession.mPid, operation); 9367 9368 final long callingIdentity = Binder.clearCallingIdentity(); 9369 try { 9370 // There was some problem... first, do a sanity check of the window list to make sure 9371 // we haven't left any dangling surfaces around. 9372 9373 Slog.i(TAG_WM, "Out of memory for surface! Looking for leaks..."); 9374 final int numDisplays = mDisplayContents.size(); 9375 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9376 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9377 final int numWindows = windows.size(); 9378 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9379 final WindowState ws = windows.get(winNdx); 9380 final WindowStateAnimator wsa = ws.mWinAnimator; 9381 if (wsa.mSurfaceController == null) { 9382 continue; 9383 } 9384 if (!mSessions.contains(wsa.mSession)) { 9385 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): " 9386 + ws + " surface=" + wsa.mSurfaceController 9387 + " token=" + ws.mToken 9388 + " pid=" + ws.mSession.mPid 9389 + " uid=" + ws.mSession.mUid); 9390 wsa.destroySurface(); 9391 mForceRemoves.add(ws); 9392 leakedSurface = true; 9393 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9394 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " 9395 + ws + " surface=" + wsa.mSurfaceController 9396 + " token=" + ws.mAppToken 9397 + " saved=" + ws.hasSavedSurface()); 9398 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false); 9399 wsa.destroySurface(); 9400 leakedSurface = true; 9401 } 9402 } 9403 } 9404 9405 if (!leakedSurface) { 9406 Slog.w(TAG_WM, "No leaked surfaces; killing applicatons!"); 9407 SparseIntArray pidCandidates = new SparseIntArray(); 9408 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9409 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9410 final int numWindows = windows.size(); 9411 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9412 final WindowState ws = windows.get(winNdx); 9413 if (mForceRemoves.contains(ws)) { 9414 continue; 9415 } 9416 WindowStateAnimator wsa = ws.mWinAnimator; 9417 if (wsa.mSurfaceController != null) { 9418 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9419 } 9420 } 9421 if (pidCandidates.size() > 0) { 9422 int[] pids = new int[pidCandidates.size()]; 9423 for (int i=0; i<pids.length; i++) { 9424 pids[i] = pidCandidates.keyAt(i); 9425 } 9426 try { 9427 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9428 killedApps = true; 9429 } 9430 } catch (RemoteException e) { 9431 } 9432 } 9433 } 9434 } 9435 9436 if (leakedSurface || killedApps) { 9437 // We managed to reclaim some memory, so get rid of the trouble 9438 // surface and ask the app to request another one. 9439 Slog.w(TAG_WM, "Looks like we have reclaimed some memory, clearing surface for retry."); 9440 if (surfaceController != null) { 9441 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9442 "RECOVER DESTROY", false); 9443 winAnimator.destroySurface(); 9444 scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken); 9445 } 9446 9447 try { 9448 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9449 } catch (RemoteException e) { 9450 } 9451 } 9452 } finally { 9453 Binder.restoreCallingIdentity(callingIdentity); 9454 } 9455 9456 return leakedSurface || killedApps; 9457 } 9458 9459 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9460 WindowState newFocus = computeFocusedWindowLocked(); 9461 if (mCurrentFocus != newFocus) { 9462 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9463 // This check makes sure that we don't already have the focus 9464 // change message pending. 9465 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9466 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9467 // TODO(multidisplay): Focused windows on default display only. 9468 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9469 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9470 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9471 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9472 if (imWindowChanged) { 9473 displayContent.layoutNeeded = true; 9474 newFocus = computeFocusedWindowLocked(); 9475 } 9476 9477 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG_WM, "Changing focus from " + 9478 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9479 final WindowState oldFocus = mCurrentFocus; 9480 mCurrentFocus = newFocus; 9481 mLosingFocus.remove(newFocus); 9482 9483 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9484 9485 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9486 // Focus of the input method window changed. Perform layout if needed. 9487 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9488 mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/, 9489 updateInputWindows); 9490 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9491 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9492 // Client will do the layout, but we need to assign layers 9493 // for handleNewWindowLocked() below. 9494 mLayersController.assignLayersLocked(displayContent.getWindowList()); 9495 } 9496 } 9497 9498 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9499 // The change in focus caused us to need to do a layout. Okay. 9500 displayContent.layoutNeeded = true; 9501 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9502 mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/, 9503 updateInputWindows); 9504 } 9505 } 9506 9507 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9508 // If we defer assigning layers, then the caller is responsible for 9509 // doing this part. 9510 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9511 } 9512 9513 adjustForImeIfNeeded(displayContent); 9514 9515 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9516 return true; 9517 } 9518 return false; 9519 } 9520 9521 private WindowState computeFocusedWindowLocked() { 9522 final int displayCount = mDisplayContents.size(); 9523 for (int i = 0; i < displayCount; i++) { 9524 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9525 WindowState win = findFocusedWindowLocked(displayContent); 9526 if (win != null) { 9527 return win; 9528 } 9529 } 9530 return null; 9531 } 9532 9533 WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9534 final WindowList windows = displayContent.getWindowList(); 9535 for (int i = windows.size() - 1; i >= 0; i--) { 9536 final WindowState win = windows.get(i); 9537 9538 if (localLOGV || DEBUG_FOCUS) Slog.v( 9539 TAG_WM, "Looking for focus: " + i 9540 + " = " + win 9541 + ", flags=" + win.mAttrs.flags 9542 + ", canReceive=" + win.canReceiveKeys()); 9543 9544 if (!win.canReceiveKeys()) { 9545 continue; 9546 } 9547 9548 AppWindowToken wtoken = win.mAppToken; 9549 9550 // If this window's application has been removed, just skip it. 9551 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9552 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because " 9553 + (wtoken.removed ? "removed" : "sendingToBottom")); 9554 continue; 9555 } 9556 9557 // Descend through all of the app tokens and find the first that either matches 9558 // win.mAppToken (return win) or mFocusedApp (return null). 9559 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 9560 mFocusedApp != null) { 9561 ArrayList<Task> tasks = displayContent.getTasks(); 9562 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9563 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9564 int tokenNdx = tokens.size() - 1; 9565 for ( ; tokenNdx >= 0; --tokenNdx) { 9566 final AppWindowToken token = tokens.get(tokenNdx); 9567 if (wtoken == token) { 9568 break; 9569 } 9570 if (mFocusedApp == token && token.windowsAreFocusable()) { 9571 // Whoops, we are below the focused app whose windows are focusable... 9572 // No focus for you!!! 9573 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, 9574 "findFocusedWindow: Reached focused app=" + mFocusedApp); 9575 return null; 9576 } 9577 } 9578 if (tokenNdx >= 0) { 9579 // Early exit from loop, must have found the matching token. 9580 break; 9581 } 9582 } 9583 } 9584 9585 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + i + 9586 " = " + win); 9587 return win; 9588 } 9589 9590 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows."); 9591 return null; 9592 } 9593 9594 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 9595 if (mDisplayFrozen) { 9596 return; 9597 } 9598 9599 if (!mDisplayReady || !mPolicy.isScreenOn()) { 9600 // No need to freeze the screen before the system is ready or if 9601 // the screen is off. 9602 return; 9603 } 9604 9605 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 9606 "startFreezingDisplayLocked: inTransaction=" + inTransaction 9607 + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim 9608 + " called by " + Debug.getCallers(8)); 9609 mScreenFrozenLock.acquire(); 9610 9611 mDisplayFrozen = true; 9612 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 9613 mLastFinishedFreezeSource = null; 9614 9615 mInputMonitor.freezeInputDispatchingLw(); 9616 9617 // Clear the last input window -- that is just used for 9618 // clean transitions between IMEs, and if we are freezing 9619 // the screen then the whole world is changing behind the scenes. 9620 mPolicy.setLastInputMethodWindowLw(null, null); 9621 9622 if (mAppTransition.isTransitionSet()) { 9623 mAppTransition.freeze(); 9624 } 9625 9626 if (PROFILE_ORIENTATION) { 9627 File file = new File("/data/system/frozen"); 9628 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9629 } 9630 9631 if (CUSTOM_SCREEN_ROTATION) { 9632 mExitAnimId = exitAnim; 9633 mEnterAnimId = enterAnim; 9634 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9635 final int displayId = displayContent.getDisplayId(); 9636 ScreenRotationAnimation screenRotationAnimation = 9637 mAnimator.getScreenRotationAnimationLocked(displayId); 9638 if (screenRotationAnimation != null) { 9639 screenRotationAnimation.kill(); 9640 } 9641 9642 // Check whether the current screen contains any secure content. 9643 boolean isSecure = false; 9644 final WindowList windows = getDefaultWindowListLocked(); 9645 final int N = windows.size(); 9646 for (int i = 0; i < N; i++) { 9647 WindowState ws = windows.get(i); 9648 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 9649 isSecure = true; 9650 break; 9651 } 9652 } 9653 9654 // TODO(multidisplay): rotation on main screen only. 9655 displayContent.updateDisplayInfo(); 9656 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 9657 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 9658 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 9659 } 9660 } 9661 9662 void stopFreezingDisplayLocked() { 9663 if (!mDisplayFrozen) { 9664 return; 9665 } 9666 9667 if (mWaitingForConfig || mAppsFreezingScreen > 0 9668 || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE 9669 || mClientFreezingScreen || !mOpeningApps.isEmpty()) { 9670 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 9671 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 9672 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 9673 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 9674 + ", mClientFreezingScreen=" + mClientFreezingScreen 9675 + ", mOpeningApps.size()=" + mOpeningApps.size()); 9676 return; 9677 } 9678 9679 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, 9680 "stopFreezingDisplayLocked: Unfreezing now"); 9681 9682 mDisplayFrozen = false; 9683 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 9684 StringBuilder sb = new StringBuilder(128); 9685 sb.append("Screen frozen for "); 9686 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 9687 if (mLastFinishedFreezeSource != null) { 9688 sb.append(" due to "); 9689 sb.append(mLastFinishedFreezeSource); 9690 } 9691 Slog.i(TAG_WM, sb.toString()); 9692 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9693 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 9694 if (PROFILE_ORIENTATION) { 9695 Debug.stopMethodTracing(); 9696 } 9697 9698 boolean updateRotation = false; 9699 9700 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9701 final int displayId = displayContent.getDisplayId(); 9702 ScreenRotationAnimation screenRotationAnimation = 9703 mAnimator.getScreenRotationAnimationLocked(displayId); 9704 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 9705 && screenRotationAnimation.hasScreenshot()) { 9706 if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation"); 9707 // TODO(multidisplay): rotation on main screen only. 9708 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9709 // Get rotation animation again, with new top window 9710 boolean isDimming = displayContent.isDimming(); 9711 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 9712 mExitAnimId = mEnterAnimId = 0; 9713 } 9714 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 9715 getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, 9716 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 9717 scheduleAnimationLocked(); 9718 } else { 9719 screenRotationAnimation.kill(); 9720 mAnimator.setScreenRotationAnimationLocked(displayId, null); 9721 updateRotation = true; 9722 } 9723 } else { 9724 if (screenRotationAnimation != null) { 9725 screenRotationAnimation.kill(); 9726 mAnimator.setScreenRotationAnimationLocked(displayId, null); 9727 } 9728 updateRotation = true; 9729 } 9730 9731 mInputMonitor.thawInputDispatchingLw(); 9732 9733 boolean configChanged; 9734 9735 // While the display is frozen we don't re-compute the orientation 9736 // to avoid inconsistent states. However, something interesting 9737 // could have actually changed during that time so re-evaluate it 9738 // now to catch that. 9739 configChanged = updateOrientationFromAppTokensLocked(false); 9740 9741 // A little kludge: a lot could have happened while the 9742 // display was frozen, so now that we are coming back we 9743 // do a gc so that any remote references the system 9744 // processes holds on others can be released if they are 9745 // no longer needed. 9746 mH.removeMessages(H.FORCE_GC); 9747 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 9748 9749 mScreenFrozenLock.release(); 9750 9751 if (updateRotation) { 9752 if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation"); 9753 configChanged |= updateRotationUncheckedLocked(false); 9754 } 9755 9756 if (configChanged) { 9757 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9758 } 9759 } 9760 9761 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 9762 DisplayMetrics dm) { 9763 if (index < tokens.length) { 9764 String str = tokens[index]; 9765 if (str != null && str.length() > 0) { 9766 try { 9767 int val = Integer.parseInt(str); 9768 return val; 9769 } catch (Exception e) { 9770 } 9771 } 9772 } 9773 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 9774 return defDps; 9775 } 9776 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 9777 return val; 9778 } 9779 9780 void createWatermarkInTransaction() { 9781 if (mWatermark != null) { 9782 return; 9783 } 9784 9785 File file = new File("/system/etc/setup.conf"); 9786 FileInputStream in = null; 9787 DataInputStream ind = null; 9788 try { 9789 in = new FileInputStream(file); 9790 ind = new DataInputStream(in); 9791 String line = ind.readLine(); 9792 if (line != null) { 9793 String[] toks = line.split("%"); 9794 if (toks != null && toks.length > 0) { 9795 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 9796 mRealDisplayMetrics, mFxSession, toks); 9797 } 9798 } 9799 } catch (FileNotFoundException e) { 9800 } catch (IOException e) { 9801 } finally { 9802 if (ind != null) { 9803 try { 9804 ind.close(); 9805 } catch (IOException e) { 9806 } 9807 } else if (in != null) { 9808 try { 9809 in.close(); 9810 } catch (IOException e) { 9811 } 9812 } 9813 } 9814 } 9815 9816 @Override 9817 public void statusBarVisibilityChanged(int visibility) { 9818 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 9819 != PackageManager.PERMISSION_GRANTED) { 9820 throw new SecurityException("Caller does not hold permission " 9821 + android.Manifest.permission.STATUS_BAR); 9822 } 9823 9824 synchronized (mWindowMap) { 9825 mLastStatusBarVisibility = visibility; 9826 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 9827 updateStatusBarVisibilityLocked(visibility); 9828 } 9829 } 9830 9831 // TOOD(multidisplay): StatusBar on multiple screens? 9832 boolean updateStatusBarVisibilityLocked(int visibility) { 9833 if (mLastDispatchedSystemUiVisibility == visibility) { 9834 return false; 9835 } 9836 final int globalDiff = (visibility ^ mLastDispatchedSystemUiVisibility) 9837 // We are only interested in differences of one of the 9838 // clearable flags... 9839 & View.SYSTEM_UI_CLEARABLE_FLAGS 9840 // ...if it has actually been cleared. 9841 & ~visibility; 9842 9843 mLastDispatchedSystemUiVisibility = visibility; 9844 mInputManager.setSystemUiVisibility(visibility); 9845 final WindowList windows = getDefaultWindowListLocked(); 9846 final int N = windows.size(); 9847 for (int i = 0; i < N; i++) { 9848 WindowState ws = windows.get(i); 9849 try { 9850 int curValue = ws.mSystemUiVisibility; 9851 int diff = (curValue ^ visibility) & globalDiff; 9852 int newValue = (curValue&~diff) | (visibility&diff); 9853 if (newValue != curValue) { 9854 ws.mSeq++; 9855 ws.mSystemUiVisibility = newValue; 9856 } 9857 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 9858 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 9859 visibility, newValue, diff); 9860 } 9861 } catch (RemoteException e) { 9862 // so sorry 9863 } 9864 } 9865 return true; 9866 } 9867 9868 @Override 9869 public void reevaluateStatusBarVisibility() { 9870 synchronized (mWindowMap) { 9871 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 9872 if (updateStatusBarVisibilityLocked(visibility)) { 9873 mWindowPlacerLocked.requestTraversal(); 9874 } 9875 } 9876 } 9877 9878 private static final class HideNavInputConsumer extends InputConsumerImpl 9879 implements WindowManagerPolicy.InputConsumer { 9880 private final InputEventReceiver mInputEventReceiver; 9881 9882 HideNavInputConsumer(WindowManagerService service, Looper looper, 9883 InputEventReceiver.Factory inputEventReceiverFactory) { 9884 super(service, "input consumer", null); 9885 mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver( 9886 mClientChannel, looper); 9887 } 9888 9889 @Override 9890 public void dismiss() { 9891 if (mService.removeInputConsumer()) { 9892 synchronized (mService.mWindowMap) { 9893 mInputEventReceiver.dispose(); 9894 disposeChannelsLw(); 9895 } 9896 } 9897 } 9898 } 9899 9900 @Override 9901 public WindowManagerPolicy.InputConsumer addInputConsumer(Looper looper, 9902 InputEventReceiver.Factory inputEventReceiverFactory) { 9903 synchronized (mWindowMap) { 9904 HideNavInputConsumer inputConsumerImpl = new HideNavInputConsumer( 9905 this, looper, inputEventReceiverFactory); 9906 mInputConsumer = inputConsumerImpl; 9907 mInputMonitor.updateInputWindowsLw(true); 9908 return inputConsumerImpl; 9909 } 9910 } 9911 9912 boolean removeInputConsumer() { 9913 synchronized (mWindowMap) { 9914 if (mInputConsumer != null) { 9915 mInputConsumer = null; 9916 mInputMonitor.updateInputWindowsLw(true); 9917 return true; 9918 } 9919 return false; 9920 } 9921 } 9922 9923 public void createWallpaperInputConsumer(InputChannel inputChannel) { 9924 synchronized (mWindowMap) { 9925 mWallpaperInputConsumer = new InputConsumerImpl(this, "wallpaper input", inputChannel); 9926 mWallpaperInputConsumer.mWindowHandle.hasWallpaper = true; 9927 mInputMonitor.updateInputWindowsLw(true); 9928 } 9929 } 9930 9931 public void removeWallpaperInputConsumer() { 9932 synchronized (mWindowMap) { 9933 if (mWallpaperInputConsumer != null) { 9934 mWallpaperInputConsumer.disposeChannelsLw(); 9935 mWallpaperInputConsumer = null; 9936 mInputMonitor.updateInputWindowsLw(true); 9937 } 9938 } 9939 } 9940 9941 @Override 9942 public boolean hasNavigationBar() { 9943 return mPolicy.hasNavigationBar(); 9944 } 9945 9946 @Override 9947 public void lockNow(Bundle options) { 9948 mPolicy.lockNow(options); 9949 } 9950 9951 public void showRecentApps(boolean fromHome) { 9952 mPolicy.showRecentApps(fromHome); 9953 } 9954 9955 @Override 9956 public boolean isSafeModeEnabled() { 9957 return mSafeMode; 9958 } 9959 9960 @Override 9961 public boolean clearWindowContentFrameStats(IBinder token) { 9962 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 9963 "clearWindowContentFrameStats()")) { 9964 throw new SecurityException("Requires FRAME_STATS permission"); 9965 } 9966 synchronized (mWindowMap) { 9967 WindowState windowState = mWindowMap.get(token); 9968 if (windowState == null) { 9969 return false; 9970 } 9971 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController; 9972 if (surfaceController == null) { 9973 return false; 9974 } 9975 return surfaceController.clearWindowContentFrameStats(); 9976 } 9977 } 9978 9979 @Override 9980 public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { 9981 if (!checkCallingPermission(Manifest.permission.FRAME_STATS, 9982 "getWindowContentFrameStats()")) { 9983 throw new SecurityException("Requires FRAME_STATS permission"); 9984 } 9985 synchronized (mWindowMap) { 9986 WindowState windowState = mWindowMap.get(token); 9987 if (windowState == null) { 9988 return null; 9989 } 9990 WindowSurfaceController surfaceController = windowState.mWinAnimator.mSurfaceController; 9991 if (surfaceController == null) { 9992 return null; 9993 } 9994 if (mTempWindowRenderStats == null) { 9995 mTempWindowRenderStats = new WindowContentFrameStats(); 9996 } 9997 WindowContentFrameStats stats = mTempWindowRenderStats; 9998 if (!surfaceController.getWindowContentFrameStats(stats)) { 9999 return null; 10000 } 10001 return stats; 10002 } 10003 } 10004 10005 public void notifyAppRelaunching(IBinder token) { 10006 synchronized (mWindowMap) { 10007 AppWindowToken appWindow = findAppWindowToken(token); 10008 if (appWindow != null) { 10009 appWindow.startRelaunching(); 10010 } 10011 } 10012 } 10013 10014 public void notifyAppRelaunchingFinished(IBinder token) { 10015 synchronized (mWindowMap) { 10016 AppWindowToken appWindow = findAppWindowToken(token); 10017 if (appWindow != null) { 10018 appWindow.finishRelaunching(); 10019 } 10020 } 10021 } 10022 10023 @Override 10024 public int getDockedDividerInsetsLw() { 10025 return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets(); 10026 } 10027 10028 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10029 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10030 mPolicy.dump(" ", pw, args); 10031 } 10032 10033 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10034 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10035 mAnimator.dumpLocked(pw, " ", dumpAll); 10036 } 10037 10038 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10039 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10040 if (!mTokenMap.isEmpty()) { 10041 pw.println(" All tokens:"); 10042 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10043 while (it.hasNext()) { 10044 WindowToken token = it.next(); 10045 pw.print(" "); pw.print(token); 10046 if (dumpAll) { 10047 pw.println(':'); 10048 token.dump(pw, " "); 10049 } else { 10050 pw.println(); 10051 } 10052 } 10053 } 10054 mWallpaperControllerLocked.dumpTokens(pw, " ", dumpAll); 10055 if (!mFinishedStarting.isEmpty()) { 10056 pw.println(); 10057 pw.println(" Finishing start of application tokens:"); 10058 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10059 WindowToken token = mFinishedStarting.get(i); 10060 pw.print(" Finished Starting #"); pw.print(i); 10061 pw.print(' '); pw.print(token); 10062 if (dumpAll) { 10063 pw.println(':'); 10064 token.dump(pw, " "); 10065 } else { 10066 pw.println(); 10067 } 10068 } 10069 } 10070 if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) { 10071 pw.println(); 10072 if (mOpeningApps.size() > 0) { 10073 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10074 } 10075 if (mClosingApps.size() > 0) { 10076 pw.print(" mClosingApps="); pw.println(mClosingApps); 10077 } 10078 } 10079 } 10080 10081 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10082 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10083 for (int i=0; i<mSessions.size(); i++) { 10084 Session s = mSessions.valueAt(i); 10085 pw.print(" Session "); pw.print(s); pw.println(':'); 10086 s.dump(pw, " "); 10087 } 10088 } 10089 10090 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10091 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10092 if (mDisplayReady) { 10093 final int numDisplays = mDisplayContents.size(); 10094 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10095 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10096 displayContent.dump(" ", pw); 10097 } 10098 } else { 10099 pw.println(" NO DISPLAY"); 10100 } 10101 } 10102 10103 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10104 ArrayList<WindowState> windows) { 10105 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10106 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10107 } 10108 10109 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10110 ArrayList<WindowState> windows) { 10111 final int numDisplays = mDisplayContents.size(); 10112 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10113 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10114 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10115 final WindowState w = windowList.get(winNdx); 10116 if (windows == null || windows.contains(w)) { 10117 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10118 pw.print(w); pw.println(":"); 10119 w.dump(pw, " ", dumpAll || windows != null); 10120 } 10121 } 10122 } 10123 if (mInputMethodDialogs.size() > 0) { 10124 pw.println(); 10125 pw.println(" Input method dialogs:"); 10126 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10127 WindowState w = mInputMethodDialogs.get(i); 10128 if (windows == null || windows.contains(w)) { 10129 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10130 } 10131 } 10132 } 10133 if (mPendingRemove.size() > 0) { 10134 pw.println(); 10135 pw.println(" Remove pending for:"); 10136 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10137 WindowState w = mPendingRemove.get(i); 10138 if (windows == null || windows.contains(w)) { 10139 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10140 pw.print(w); 10141 if (dumpAll) { 10142 pw.println(":"); 10143 w.dump(pw, " ", true); 10144 } else { 10145 pw.println(); 10146 } 10147 } 10148 } 10149 } 10150 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10151 pw.println(); 10152 pw.println(" Windows force removing:"); 10153 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10154 WindowState w = mForceRemoves.get(i); 10155 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10156 pw.print(w); 10157 if (dumpAll) { 10158 pw.println(":"); 10159 w.dump(pw, " ", true); 10160 } else { 10161 pw.println(); 10162 } 10163 } 10164 } 10165 if (mDestroySurface.size() > 0) { 10166 pw.println(); 10167 pw.println(" Windows waiting to destroy their surface:"); 10168 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10169 WindowState w = mDestroySurface.get(i); 10170 if (windows == null || windows.contains(w)) { 10171 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10172 pw.print(w); 10173 if (dumpAll) { 10174 pw.println(":"); 10175 w.dump(pw, " ", true); 10176 } else { 10177 pw.println(); 10178 } 10179 } 10180 } 10181 } 10182 if (mLosingFocus.size() > 0) { 10183 pw.println(); 10184 pw.println(" Windows losing focus:"); 10185 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10186 WindowState w = mLosingFocus.get(i); 10187 if (windows == null || windows.contains(w)) { 10188 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10189 pw.print(w); 10190 if (dumpAll) { 10191 pw.println(":"); 10192 w.dump(pw, " ", true); 10193 } else { 10194 pw.println(); 10195 } 10196 } 10197 } 10198 } 10199 if (mResizingWindows.size() > 0) { 10200 pw.println(); 10201 pw.println(" Windows waiting to resize:"); 10202 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10203 WindowState w = mResizingWindows.get(i); 10204 if (windows == null || windows.contains(w)) { 10205 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10206 pw.print(w); 10207 if (dumpAll) { 10208 pw.println(":"); 10209 w.dump(pw, " ", true); 10210 } else { 10211 pw.println(); 10212 } 10213 } 10214 } 10215 } 10216 if (mWaitingForDrawn.size() > 0) { 10217 pw.println(); 10218 pw.println(" Clients waiting for these windows to be drawn:"); 10219 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10220 WindowState win = mWaitingForDrawn.get(i); 10221 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10222 } 10223 } 10224 pw.println(); 10225 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10226 pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad); 10227 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10228 if (mLastFocus != mCurrentFocus) { 10229 pw.print(" mLastFocus="); pw.println(mLastFocus); 10230 } 10231 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10232 if (mInputMethodTarget != null) { 10233 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10234 } 10235 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10236 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10237 pw.print(" mLastDisplayFreezeDuration="); 10238 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10239 if ( mLastFinishedFreezeSource != null) { 10240 pw.print(" due to "); 10241 pw.print(mLastFinishedFreezeSource); 10242 } 10243 pw.println(); 10244 pw.print(" mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow); 10245 pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow); 10246 pw.println(); 10247 10248 mInputMonitor.dump(pw, " "); 10249 10250 if (dumpAll) { 10251 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10252 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10253 if (mLastStatusBarVisibility != 0) { 10254 pw.print(" mLastStatusBarVisibility=0x"); 10255 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10256 } 10257 if (mInputMethodWindow != null) { 10258 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10259 } 10260 mWindowPlacerLocked.dump(pw, " "); 10261 mWallpaperControllerLocked.dump(pw, " "); 10262 mLayersController.dump(pw, " "); 10263 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10264 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10265 if (needsLayout()) { 10266 pw.print(" layoutNeeded on displays="); 10267 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10268 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10269 if (displayContent.layoutNeeded) { 10270 pw.print(displayContent.getDisplayId()); 10271 } 10272 } 10273 pw.println(); 10274 } 10275 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10276 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10277 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10278 pw.print(" client="); pw.print(mClientFreezingScreen); 10279 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10280 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10281 pw.print(" mRotation="); pw.print(mRotation); 10282 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10283 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10284 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10285 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10286 pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled); 10287 pw.print(" window="); pw.print(mWindowAnimationScaleSetting); 10288 pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); 10289 pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); 10290 pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation); 10291 pw.println(" mLayoutToAnim:"); 10292 mAppTransition.dump(pw, " "); 10293 } 10294 } 10295 10296 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10297 int opti, boolean dumpAll) { 10298 WindowList windows = new WindowList(); 10299 if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) { 10300 final boolean appsOnly = name.contains("apps"); 10301 final boolean visibleOnly = name.contains("visible"); 10302 synchronized(mWindowMap) { 10303 if (appsOnly) { 10304 dumpDisplayContentsLocked(pw, true); 10305 } 10306 10307 final int numDisplays = mDisplayContents.size(); 10308 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10309 final WindowList windowList = 10310 mDisplayContents.valueAt(displayNdx).getWindowList(); 10311 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10312 final WindowState w = windowList.get(winNdx); 10313 if ((!visibleOnly || w.mWinAnimator.getShown()) 10314 && (!appsOnly || w.mAppToken != null)) { 10315 windows.add(w); 10316 } 10317 } 10318 } 10319 } 10320 } else { 10321 int objectId = 0; 10322 // See if this is an object ID. 10323 try { 10324 objectId = Integer.parseInt(name, 16); 10325 name = null; 10326 } catch (RuntimeException e) { 10327 } 10328 synchronized(mWindowMap) { 10329 final int numDisplays = mDisplayContents.size(); 10330 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10331 final WindowList windowList = 10332 mDisplayContents.valueAt(displayNdx).getWindowList(); 10333 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10334 final WindowState w = windowList.get(winNdx); 10335 if (name != null) { 10336 if (w.mAttrs.getTitle().toString().contains(name)) { 10337 windows.add(w); 10338 } 10339 } else if (System.identityHashCode(w) == objectId) { 10340 windows.add(w); 10341 } 10342 } 10343 } 10344 } 10345 } 10346 10347 if (windows.size() <= 0) { 10348 return false; 10349 } 10350 10351 synchronized(mWindowMap) { 10352 dumpWindowsLocked(pw, dumpAll, windows); 10353 } 10354 return true; 10355 } 10356 10357 void dumpLastANRLocked(PrintWriter pw) { 10358 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10359 if (mLastANRState == null) { 10360 pw.println(" <no ANR has occurred since boot>"); 10361 } else { 10362 pw.println(mLastANRState); 10363 } 10364 } 10365 10366 /** 10367 * Saves information about the state of the window manager at 10368 * the time an ANR occurred before anything else in the system changes 10369 * in response. 10370 * 10371 * @param appWindowToken The application that ANR'd, may be null. 10372 * @param windowState The window that ANR'd, may be null. 10373 * @param reason The reason for the ANR, may be null. 10374 */ 10375 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10376 String reason) { 10377 StringWriter sw = new StringWriter(); 10378 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10379 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10380 if (appWindowToken != null) { 10381 pw.println(" Application at fault: " + appWindowToken.stringName); 10382 } 10383 if (windowState != null) { 10384 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10385 } 10386 if (reason != null) { 10387 pw.println(" Reason: " + reason); 10388 } 10389 pw.println(); 10390 dumpWindowsNoHeaderLocked(pw, true, null); 10391 pw.println(); 10392 pw.println("Last ANR continued"); 10393 dumpDisplayContentsLocked(pw, true); 10394 pw.close(); 10395 mLastANRState = sw.toString(); 10396 10397 mH.removeMessages(H.RESET_ANR_MESSAGE); 10398 mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS); 10399 } 10400 10401 @Override 10402 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10403 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10404 != PackageManager.PERMISSION_GRANTED) { 10405 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10406 + Binder.getCallingPid() 10407 + ", uid=" + Binder.getCallingUid()); 10408 return; 10409 } 10410 10411 boolean dumpAll = false; 10412 10413 int opti = 0; 10414 while (opti < args.length) { 10415 String opt = args[opti]; 10416 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10417 break; 10418 } 10419 opti++; 10420 if ("-a".equals(opt)) { 10421 dumpAll = true; 10422 } else if ("-h".equals(opt)) { 10423 pw.println("Window manager dump options:"); 10424 pw.println(" [-a] [-h] [cmd] ..."); 10425 pw.println(" cmd may be one of:"); 10426 pw.println(" l[astanr]: last ANR information"); 10427 pw.println(" p[policy]: policy state"); 10428 pw.println(" a[animator]: animator state"); 10429 pw.println(" s[essions]: active sessions"); 10430 pw.println(" surfaces: active surfaces (debugging enabled only)"); 10431 pw.println(" d[isplays]: active display contents"); 10432 pw.println(" t[okens]: token list"); 10433 pw.println(" w[indows]: window list"); 10434 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10435 pw.println(" be a partial substring in a window name, a"); 10436 pw.println(" Window hex object identifier, or"); 10437 pw.println(" \"all\" for all windows, or"); 10438 pw.println(" \"visible\" for the visible windows."); 10439 pw.println(" \"visible-apps\" for the visible app windows."); 10440 pw.println(" -a: include all available server state."); 10441 return; 10442 } else { 10443 pw.println("Unknown argument: " + opt + "; use -h for help"); 10444 } 10445 } 10446 10447 // Is the caller requesting to dump a particular piece of data? 10448 if (opti < args.length) { 10449 String cmd = args[opti]; 10450 opti++; 10451 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10452 synchronized(mWindowMap) { 10453 dumpLastANRLocked(pw); 10454 } 10455 return; 10456 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10457 synchronized(mWindowMap) { 10458 dumpPolicyLocked(pw, args, true); 10459 } 10460 return; 10461 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10462 synchronized(mWindowMap) { 10463 dumpAnimatorLocked(pw, args, true); 10464 } 10465 return; 10466 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10467 synchronized(mWindowMap) { 10468 dumpSessionsLocked(pw, true); 10469 } 10470 return; 10471 } else if ("surfaces".equals(cmd)) { 10472 synchronized(mWindowMap) { 10473 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null); 10474 } 10475 return; 10476 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10477 synchronized(mWindowMap) { 10478 dumpDisplayContentsLocked(pw, true); 10479 } 10480 return; 10481 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10482 synchronized(mWindowMap) { 10483 dumpTokensLocked(pw, true); 10484 } 10485 return; 10486 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10487 synchronized(mWindowMap) { 10488 dumpWindowsLocked(pw, true, null); 10489 } 10490 return; 10491 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10492 synchronized(mWindowMap) { 10493 dumpWindowsLocked(pw, true, null); 10494 } 10495 return; 10496 } else { 10497 // Dumping a single name? 10498 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10499 pw.println("Bad window command, or no windows match: " + cmd); 10500 pw.println("Use -h for help."); 10501 } 10502 return; 10503 } 10504 } 10505 10506 synchronized(mWindowMap) { 10507 pw.println(); 10508 if (dumpAll) { 10509 pw.println("-------------------------------------------------------------------------------"); 10510 } 10511 dumpLastANRLocked(pw); 10512 pw.println(); 10513 if (dumpAll) { 10514 pw.println("-------------------------------------------------------------------------------"); 10515 } 10516 dumpPolicyLocked(pw, args, dumpAll); 10517 pw.println(); 10518 if (dumpAll) { 10519 pw.println("-------------------------------------------------------------------------------"); 10520 } 10521 dumpAnimatorLocked(pw, args, dumpAll); 10522 pw.println(); 10523 if (dumpAll) { 10524 pw.println("-------------------------------------------------------------------------------"); 10525 } 10526 dumpSessionsLocked(pw, dumpAll); 10527 pw.println(); 10528 if (dumpAll) { 10529 pw.println("-------------------------------------------------------------------------------"); 10530 } 10531 WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ? 10532 "-------------------------------------------------------------------------------" 10533 : null); 10534 pw.println(); 10535 if (dumpAll) { 10536 pw.println("-------------------------------------------------------------------------------"); 10537 } 10538 dumpDisplayContentsLocked(pw, dumpAll); 10539 pw.println(); 10540 if (dumpAll) { 10541 pw.println("-------------------------------------------------------------------------------"); 10542 } 10543 dumpTokensLocked(pw, dumpAll); 10544 pw.println(); 10545 if (dumpAll) { 10546 pw.println("-------------------------------------------------------------------------------"); 10547 } 10548 dumpWindowsLocked(pw, dumpAll, null); 10549 } 10550 } 10551 10552 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10553 @Override 10554 public void monitor() { 10555 synchronized (mWindowMap) { } 10556 } 10557 10558 private DisplayContent newDisplayContentLocked(final Display display) { 10559 DisplayContent displayContent = new DisplayContent(display, this); 10560 final int displayId = display.getDisplayId(); 10561 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display); 10562 mDisplayContents.put(displayId, displayContent); 10563 10564 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10565 final Rect rect = new Rect(); 10566 mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect); 10567 displayInfo.overscanLeft = rect.left; 10568 displayInfo.overscanTop = rect.top; 10569 displayInfo.overscanRight = rect.right; 10570 displayInfo.overscanBottom = rect.bottom; 10571 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId, displayInfo); 10572 configureDisplayPolicyLocked(displayContent); 10573 10574 // TODO: Create an input channel for each display with touch capability. 10575 if (displayId == Display.DEFAULT_DISPLAY) { 10576 displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent); 10577 registerPointerEventListener(displayContent.mTapDetector); 10578 registerPointerEventListener(mMousePositionTracker); 10579 } 10580 10581 return displayContent; 10582 } 10583 10584 public void createDisplayContentLocked(final Display display) { 10585 if (display == null) { 10586 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10587 } 10588 getDisplayContentLocked(display.getDisplayId()); 10589 } 10590 10591 /** 10592 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10593 * there is a Display for the displayId. 10594 * @param displayId The display the caller is interested in. 10595 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10596 */ 10597 public DisplayContent getDisplayContentLocked(final int displayId) { 10598 DisplayContent displayContent = mDisplayContents.get(displayId); 10599 if (displayContent == null) { 10600 final Display display = mDisplayManager.getDisplay(displayId); 10601 if (display != null) { 10602 displayContent = newDisplayContentLocked(display); 10603 } 10604 } 10605 return displayContent; 10606 } 10607 10608 // There is an inherent assumption that this will never return null. 10609 public DisplayContent getDefaultDisplayContentLocked() { 10610 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10611 } 10612 10613 public WindowList getDefaultWindowListLocked() { 10614 return getDefaultDisplayContentLocked().getWindowList(); 10615 } 10616 10617 public DisplayInfo getDefaultDisplayInfoLocked() { 10618 return getDefaultDisplayContentLocked().getDisplayInfo(); 10619 } 10620 10621 /** 10622 * Return the list of WindowStates associated on the passed display. 10623 * @param display The screen to return windows from. 10624 * @return The list of WindowStates on the screen, or null if the there is no screen. 10625 */ 10626 public WindowList getWindowListLocked(final Display display) { 10627 return getWindowListLocked(display.getDisplayId()); 10628 } 10629 10630 /** 10631 * Return the list of WindowStates associated on the passed display. 10632 * @param displayId The screen to return windows from. 10633 * @return The list of WindowStates on the screen, or null if the there is no screen. 10634 */ 10635 public WindowList getWindowListLocked(final int displayId) { 10636 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10637 return displayContent != null ? displayContent.getWindowList() : null; 10638 } 10639 10640 public void onDisplayAdded(int displayId) { 10641 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10642 } 10643 10644 public void handleDisplayAdded(int displayId) { 10645 synchronized (mWindowMap) { 10646 final Display display = mDisplayManager.getDisplay(displayId); 10647 if (display != null) { 10648 createDisplayContentLocked(display); 10649 displayReady(displayId); 10650 } 10651 mWindowPlacerLocked.requestTraversal(); 10652 } 10653 } 10654 10655 public void onDisplayRemoved(int displayId) { 10656 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 10657 } 10658 10659 private void handleDisplayRemovedLocked(int displayId) { 10660 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10661 if (displayContent != null) { 10662 if (displayContent.isAnimating()) { 10663 displayContent.mDeferredRemoval = true; 10664 return; 10665 } 10666 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + displayContent); 10667 mDisplayContents.delete(displayId); 10668 displayContent.close(); 10669 if (displayId == Display.DEFAULT_DISPLAY) { 10670 unregisterPointerEventListener(displayContent.mTapDetector); 10671 unregisterPointerEventListener(mMousePositionTracker); 10672 } 10673 } 10674 mAnimator.removeDisplayLocked(displayId); 10675 mWindowPlacerLocked.requestTraversal(); 10676 } 10677 10678 public void onDisplayChanged(int displayId) { 10679 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 10680 } 10681 10682 private void handleDisplayChangedLocked(int displayId) { 10683 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10684 if (displayContent != null) { 10685 displayContent.updateDisplayInfo(); 10686 } 10687 mWindowPlacerLocked.requestTraversal(); 10688 } 10689 10690 @Override 10691 public Object getWindowManagerLock() { 10692 return mWindowMap; 10693 } 10694 10695 /** 10696 * Hint to a token that its activity will relaunch, which will trigger removal and addition of 10697 * a window. 10698 * @param token Application token for which the activity will be relaunched. 10699 */ 10700 public void setReplacingWindow(IBinder token, boolean animate) { 10701 AppWindowToken appWindowToken = null; 10702 synchronized (mWindowMap) { 10703 appWindowToken = findAppWindowToken(token); 10704 if (appWindowToken == null || !appWindowToken.isVisible()) { 10705 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token " 10706 + token); 10707 return; 10708 } 10709 appWindowToken.setReplacingWindows(animate); 10710 } 10711 } 10712 10713 /** 10714 * Hint to a token that its windows will be replaced across activity relaunch. 10715 * The windows would otherwise be removed shortly following this as the 10716 * activity is torn down. 10717 * @param token Application token for which the activity will be relaunched. 10718 * @param childrenOnly Whether to mark only child windows for replacement 10719 * (for the case where main windows are being preserved/ 10720 * reused rather than replaced). 10721 * 10722 */ 10723 public void setReplacingWindows(IBinder token, boolean childrenOnly) { 10724 AppWindowToken appWindowToken = null; 10725 synchronized (mWindowMap) { 10726 appWindowToken = findAppWindowToken(token); 10727 if (appWindowToken == null || !appWindowToken.isVisible()) { 10728 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token " 10729 + token); 10730 return; 10731 } 10732 10733 if (childrenOnly) { 10734 appWindowToken.setReplacingChildren(); 10735 } else { 10736 appWindowToken.setReplacingWindows(false /* animate */); 10737 } 10738 10739 scheduleClearReplacingWindowIfNeeded(token, true /* replacing */); 10740 } 10741 } 10742 10743 /** 10744 * If we're replacing the window, schedule a timer to clear the replaced window 10745 * after a timeout, in case the replacing window is not coming. 10746 * 10747 * If we're not replacing the window, clear the replace window settings of the app. 10748 * 10749 * @param token Application token for the activity whose window might be replaced. 10750 * @param replacing Whether the window is being replaced or not. 10751 */ 10752 public void scheduleClearReplacingWindowIfNeeded(IBinder token, boolean replacing) { 10753 AppWindowToken appWindowToken = null; 10754 synchronized (mWindowMap) { 10755 appWindowToken = findAppWindowToken(token); 10756 if (appWindowToken == null) { 10757 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token " 10758 + token); 10759 return; 10760 } 10761 if (replacing) { 10762 mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT); 10763 mH.sendMessageDelayed( 10764 mH.obtainMessage(H.WINDOW_REPLACEMENT_TIMEOUT, appWindowToken), 10765 WINDOW_REPLACEMENT_TIMEOUT_DURATION); 10766 } else { 10767 appWindowToken.resetReplacingWindows(); 10768 } 10769 } 10770 } 10771 10772 @Override 10773 public int getDockedStackSide() { 10774 synchronized (mWindowMap) { 10775 final TaskStack dockedStack = getDefaultDisplayContentLocked() 10776 .getDockedStackVisibleForUserLocked(); 10777 return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(); 10778 } 10779 } 10780 10781 @Override 10782 public void setDockedStackResizing(boolean resizing) { 10783 synchronized (mWindowMap) { 10784 getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing); 10785 requestTraversal(); 10786 } 10787 } 10788 10789 @Override 10790 public void setDockedStackDividerTouchRegion(Rect touchRegion) { 10791 synchronized (mWindowMap) { 10792 getDefaultDisplayContentLocked().getDockedDividerController() 10793 .setTouchRegion(touchRegion); 10794 setFocusTaskRegionLocked(); 10795 } 10796 } 10797 10798 @Override 10799 public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) { 10800 synchronized (mWindowMap) { 10801 getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer( 10802 visible, targetStackId, alpha); 10803 } 10804 } 10805 10806 public void animateResizePinnedStack(final Rect bounds, final int animationDuration) { 10807 synchronized (mWindowMap) { 10808 final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID); 10809 if (stack == null) { 10810 Slog.w(TAG, "animateResizePinnedStack: stackId " + PINNED_STACK_ID + " not found."); 10811 return; 10812 } 10813 final Rect originalBounds = new Rect(); 10814 stack.getBounds(originalBounds); 10815 UiThread.getHandler().post(new Runnable() { 10816 @Override 10817 public void run() { 10818 mBoundsAnimationController.animateBounds( 10819 stack, originalBounds, bounds, animationDuration); 10820 } 10821 }); 10822 } 10823 } 10824 10825 public void setTaskResizeable(int taskId, int resizeMode) { 10826 synchronized (mWindowMap) { 10827 final Task task = mTaskIdToTask.get(taskId); 10828 if (task != null) { 10829 task.setResizeable(resizeMode); 10830 } 10831 } 10832 } 10833 10834 public void setForceResizableTasks(boolean forceResizableTasks) { 10835 synchronized (mWindowMap) { 10836 mForceResizableTasks = forceResizableTasks; 10837 } 10838 } 10839 10840 static int dipToPixel(int dip, DisplayMetrics displayMetrics) { 10841 return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics); 10842 } 10843 10844 @Override 10845 public void registerDockedStackListener(IDockedStackListener listener) { 10846 if (!checkCallingPermission(android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS, 10847 "registerDockedStackListener()")) { 10848 return; 10849 } 10850 // TODO(multi-display): The listener is registered on the default display only. 10851 getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener( 10852 listener); 10853 } 10854 10855 @Override 10856 public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) { 10857 try { 10858 WindowState focusedWindow = getFocusedWindow(); 10859 if (focusedWindow != null && focusedWindow.mClient != null) { 10860 getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId); 10861 } 10862 } catch (RemoteException e) { 10863 } 10864 } 10865 10866 @Override 10867 public void getStableInsets(Rect outInsets) throws RemoteException { 10868 synchronized (mWindowMap) { 10869 getStableInsetsLocked(outInsets); 10870 } 10871 } 10872 10873 void getStableInsetsLocked(Rect outInsets) { 10874 final DisplayInfo di = getDefaultDisplayInfoLocked(); 10875 mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets); 10876 } 10877 10878 private void getNonDecorInsetsLocked(Rect outInsets) { 10879 final DisplayInfo di = getDefaultDisplayInfoLocked(); 10880 mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets); 10881 } 10882 10883 /** 10884 * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable 10885 * inset areas. 10886 * 10887 * @param inOutBounds The inOutBounds to subtract the stable inset areas from. 10888 */ 10889 public void subtractStableInsets(Rect inOutBounds) { 10890 synchronized (mWindowMap) { 10891 getStableInsetsLocked(mTmpRect2); 10892 final DisplayInfo di = getDefaultDisplayInfoLocked(); 10893 mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight); 10894 mTmpRect.inset(mTmpRect2); 10895 inOutBounds.intersect(mTmpRect); 10896 } 10897 } 10898 10899 /** 10900 * Intersects the specified {@code inOutBounds} with the display frame that excludes 10901 * areas that could never be removed in Honeycomb. See 10902 * {@link WindowManagerPolicy#getNonDecorInsetsLw}. 10903 * 10904 * @param inOutBounds The inOutBounds to subtract the inset areas from. 10905 */ 10906 public void subtractNonDecorInsets(Rect inOutBounds) { 10907 synchronized (mWindowMap) { 10908 getNonDecorInsetsLocked(mTmpRect2); 10909 final DisplayInfo di = getDefaultDisplayInfoLocked(); 10910 mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight); 10911 mTmpRect.inset(mTmpRect2); 10912 inOutBounds.intersect(mTmpRect); 10913 } 10914 } 10915 10916 private MousePositionTracker mMousePositionTracker = new MousePositionTracker(); 10917 10918 private static class MousePositionTracker implements PointerEventListener { 10919 private boolean mLatestEventWasMouse; 10920 private float mLatestMouseX; 10921 private float mLatestMouseY; 10922 10923 void updatePosition(float x, float y) { 10924 synchronized (this) { 10925 mLatestEventWasMouse = true; 10926 mLatestMouseX = x; 10927 mLatestMouseY = y; 10928 } 10929 } 10930 10931 @Override 10932 public void onPointerEvent(MotionEvent motionEvent) { 10933 if (motionEvent.isFromSource(InputDevice.SOURCE_MOUSE)) { 10934 updatePosition(motionEvent.getRawX(), motionEvent.getRawY()); 10935 } else { 10936 synchronized (this) { 10937 mLatestEventWasMouse = false; 10938 } 10939 } 10940 } 10941 }; 10942 10943 void updatePointerIcon(IWindow client) { 10944 float mouseX, mouseY; 10945 10946 synchronized(mMousePositionTracker) { 10947 if (!mMousePositionTracker.mLatestEventWasMouse) { 10948 return; 10949 } 10950 mouseX = mMousePositionTracker.mLatestMouseX; 10951 mouseY = mMousePositionTracker.mLatestMouseY; 10952 } 10953 10954 synchronized (mWindowMap) { 10955 if (mDragState != null) { 10956 // Drag cursor overrides the app cursor. 10957 return; 10958 } 10959 WindowState callingWin = windowForClientLocked(null, client, false); 10960 if (callingWin == null) { 10961 Slog.w(TAG_WM, "Bad requesting window " + client); 10962 return; 10963 } 10964 final DisplayContent displayContent = callingWin.getDisplayContent(); 10965 if (displayContent == null) { 10966 return; 10967 } 10968 WindowState windowUnderPointer = 10969 displayContent.getTouchableWinAtPointLocked(mouseX, mouseY); 10970 if (windowUnderPointer != callingWin) { 10971 return; 10972 } 10973 try { 10974 windowUnderPointer.mClient.updatePointerIcon( 10975 windowUnderPointer.translateToWindowX(mouseX), 10976 windowUnderPointer.translateToWindowY(mouseY)); 10977 } catch (RemoteException e) { 10978 Slog.w(TAG_WM, "unable to update pointer icon"); 10979 } 10980 } 10981 } 10982 10983 void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) { 10984 // Mouse position tracker has not been getting updates while dragging, update it now. 10985 mMousePositionTracker.updatePosition(latestX, latestY); 10986 10987 WindowState windowUnderPointer = 10988 displayContent.getTouchableWinAtPointLocked(latestX, latestY); 10989 if (windowUnderPointer != null) { 10990 try { 10991 windowUnderPointer.mClient.updatePointerIcon( 10992 windowUnderPointer.translateToWindowX(latestX), 10993 windowUnderPointer.translateToWindowY(latestY)); 10994 } catch (RemoteException e) { 10995 Slog.w(TAG_WM, "unable to restore pointer icon"); 10996 } 10997 } else { 10998 InputManager.getInstance().setPointerIconShape(PointerIcon.STYLE_DEFAULT); 10999 } 11000 } 11001 11002 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver) 11003 throws RemoteException { 11004 if (!checkCallingPermission(Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS, 11005 "registerShortcutKey")) { 11006 throw new SecurityException( 11007 "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission"); 11008 } 11009 mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver); 11010 } 11011 11012 private final class LocalService extends WindowManagerInternal { 11013 @Override 11014 public void requestTraversalFromDisplayManager() { 11015 requestTraversal(); 11016 } 11017 11018 @Override 11019 public void setMagnificationSpec(MagnificationSpec spec) { 11020 synchronized (mWindowMap) { 11021 if (mAccessibilityController != null) { 11022 mAccessibilityController.setMagnificationSpecLocked(spec); 11023 } else { 11024 throw new IllegalStateException("Magnification callbacks not set!"); 11025 } 11026 } 11027 if (Binder.getCallingPid() != android.os.Process.myPid()) { 11028 spec.recycle(); 11029 } 11030 } 11031 11032 @Override 11033 public void getMagnificationRegion(@NonNull Region magnificationRegion) { 11034 synchronized (mWindowMap) { 11035 if (mAccessibilityController != null) { 11036 mAccessibilityController.getMagnificationRegionLocked(magnificationRegion); 11037 } else { 11038 throw new IllegalStateException("Magnification callbacks not set!"); 11039 } 11040 } 11041 } 11042 11043 @Override 11044 public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { 11045 synchronized (mWindowMap) { 11046 WindowState windowState = mWindowMap.get(windowToken); 11047 if (windowState == null) { 11048 return null; 11049 } 11050 MagnificationSpec spec = null; 11051 if (mAccessibilityController != null) { 11052 spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState); 11053 } 11054 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { 11055 return null; 11056 } 11057 spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec); 11058 spec.scale *= windowState.mGlobalScale; 11059 return spec; 11060 } 11061 } 11062 11063 @Override 11064 public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) { 11065 synchronized (mWindowMap) { 11066 if (mAccessibilityController == null) { 11067 mAccessibilityController = new AccessibilityController( 11068 WindowManagerService.this); 11069 } 11070 mAccessibilityController.setMagnificationCallbacksLocked(callbacks); 11071 if (!mAccessibilityController.hasCallbacksLocked()) { 11072 mAccessibilityController = null; 11073 } 11074 } 11075 } 11076 11077 @Override 11078 public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) { 11079 synchronized (mWindowMap) { 11080 if (mAccessibilityController == null) { 11081 mAccessibilityController = new AccessibilityController( 11082 WindowManagerService.this); 11083 } 11084 mAccessibilityController.setWindowsForAccessibilityCallback(callback); 11085 if (!mAccessibilityController.hasCallbacksLocked()) { 11086 mAccessibilityController = null; 11087 } 11088 } 11089 } 11090 11091 @Override 11092 public void setInputFilter(IInputFilter filter) { 11093 mInputManager.setInputFilter(filter); 11094 } 11095 11096 @Override 11097 public IBinder getFocusedWindowToken() { 11098 synchronized (mWindowMap) { 11099 WindowState windowState = getFocusedWindowLocked(); 11100 if (windowState != null) { 11101 return windowState.mClient.asBinder(); 11102 } 11103 return null; 11104 } 11105 } 11106 11107 @Override 11108 public boolean isKeyguardLocked() { 11109 return WindowManagerService.this.isKeyguardLocked(); 11110 } 11111 11112 @Override 11113 public void showGlobalActions() { 11114 WindowManagerService.this.showGlobalActions(); 11115 } 11116 11117 @Override 11118 public void getWindowFrame(IBinder token, Rect outBounds) { 11119 synchronized (mWindowMap) { 11120 WindowState windowState = mWindowMap.get(token); 11121 if (windowState != null) { 11122 outBounds.set(windowState.mFrame); 11123 } else { 11124 outBounds.setEmpty(); 11125 } 11126 } 11127 } 11128 11129 @Override 11130 public void waitForAllWindowsDrawn(Runnable callback, long timeout) { 11131 boolean allWindowsDrawn = false; 11132 synchronized (mWindowMap) { 11133 mWaitingForDrawnCallback = callback; 11134 final WindowList windows = getDefaultWindowListLocked(); 11135 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 11136 final WindowState win = windows.get(winNdx); 11137 final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs); 11138 if (win.isVisibleLw() 11139 && (win.mAppToken != null || isForceHiding)) { 11140 win.mWinAnimator.mDrawState = DRAW_PENDING; 11141 // Force add to mResizingWindows. 11142 win.mLastContentInsets.set(-1, -1, -1, -1); 11143 mWaitingForDrawn.add(win); 11144 11145 // No need to wait for the windows below Keyguard. 11146 if (isForceHiding) { 11147 break; 11148 } 11149 } 11150 } 11151 mWindowPlacerLocked.requestTraversal(); 11152 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11153 if (mWaitingForDrawn.isEmpty()) { 11154 allWindowsDrawn = true; 11155 } else { 11156 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11157 checkDrawnWindowsLocked(); 11158 } 11159 } 11160 if (allWindowsDrawn) { 11161 callback.run(); 11162 } 11163 } 11164 11165 @Override 11166 public void addWindowToken(IBinder token, int type) { 11167 WindowManagerService.this.addWindowToken(token, type); 11168 } 11169 11170 @Override 11171 public void removeWindowToken(IBinder token, boolean removeWindows) { 11172 synchronized(mWindowMap) { 11173 if (removeWindows) { 11174 WindowToken wtoken = mTokenMap.remove(token); 11175 if (wtoken != null) { 11176 wtoken.removeAllWindows(); 11177 } 11178 } 11179 WindowManagerService.this.removeWindowToken(token); 11180 } 11181 } 11182 11183 @Override 11184 public void registerAppTransitionListener(AppTransitionListener listener) { 11185 synchronized (mWindowMap) { 11186 mAppTransition.registerListenerLocked(listener); 11187 } 11188 } 11189 11190 @Override 11191 public int getInputMethodWindowVisibleHeight() { 11192 synchronized (mWindowMap) { 11193 return mPolicy.getInputMethodWindowVisibleHeightLw(); 11194 } 11195 } 11196 11197 @Override 11198 public void saveLastInputMethodWindowForTransition() { 11199 synchronized (mWindowMap) { 11200 if (mInputMethodWindow != null) { 11201 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 11202 } 11203 } 11204 } 11205 11206 @Override 11207 public boolean isHardKeyboardAvailable() { 11208 synchronized (mWindowMap) { 11209 return mHardKeyboardAvailable; 11210 } 11211 } 11212 11213 @Override 11214 public void setOnHardKeyboardStatusChangeListener( 11215 OnHardKeyboardStatusChangeListener listener) { 11216 synchronized (mWindowMap) { 11217 mHardKeyboardStatusChangeListener = listener; 11218 } 11219 } 11220 11221 @Override 11222 public boolean isStackVisible(int stackId) { 11223 synchronized (mWindowMap) { 11224 return WindowManagerService.this.isStackVisibleLocked(stackId); 11225 } 11226 } 11227 11228 @Override 11229 public boolean isDockedDividerResizing() { 11230 synchronized (mWindowMap) { 11231 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing(); 11232 } 11233 } 11234 } 11235} 11236