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