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