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