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