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