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