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