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