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 17 package com.android.server.wm; 18 19 import static android.view.WindowManager.LayoutParams.*; 20 21 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 22 import android.app.AppOpsManager; 23 import android.os.Build; 24 import android.os.SystemService; 25 import android.util.ArraySet; 26 import android.util.TimeUtils; 27 import android.view.IWindowId; 28 29 import android.view.IWindowSessionCallback; 30 import android.view.WindowContentFrameStats; 31 import com.android.internal.app.IBatteryStats; 32 import com.android.internal.policy.PolicyManager; 33 import com.android.internal.policy.impl.PhoneWindowManager; 34 import com.android.internal.util.FastPrintWriter; 35 import com.android.internal.view.IInputContext; 36 import com.android.internal.view.IInputMethodClient; 37 import com.android.internal.view.IInputMethodManager; 38 import com.android.internal.view.WindowManagerPolicyThread; 39 import com.android.server.AttributeCache; 40 import com.android.server.DisplayThread; 41 import com.android.server.EventLogTags; 42 import com.android.server.LocalServices; 43 import com.android.server.UiThread; 44 import com.android.server.Watchdog; 45 import com.android.server.am.BatteryStatsService; 46 import com.android.server.input.InputManagerService; 47 import com.android.server.power.ShutdownThread; 48 49 import android.Manifest; 50 import android.app.ActivityManagerNative; 51 import android.app.IActivityManager; 52 import android.app.StatusBarManager; 53 import android.app.admin.DevicePolicyManager; 54 import android.animation.ValueAnimator; 55 import android.content.BroadcastReceiver; 56 import android.content.ContentResolver; 57 import android.content.Context; 58 import android.content.Intent; 59 import android.content.IntentFilter; 60 import android.content.pm.ActivityInfo; 61 import android.content.pm.PackageManager; 62 import android.content.res.CompatibilityInfo; 63 import android.content.res.Configuration; 64 import android.database.ContentObserver; 65 import android.graphics.Bitmap; 66 import android.graphics.Bitmap.Config; 67 import android.graphics.Canvas; 68 import android.graphics.Matrix; 69 import android.graphics.PixelFormat; 70 import android.graphics.Point; 71 import android.graphics.Rect; 72 import android.graphics.RectF; 73 import android.graphics.Region; 74 import android.hardware.display.DisplayManager; 75 import android.hardware.display.DisplayManagerInternal; 76 import android.net.Uri; 77 import android.os.Binder; 78 import android.os.Bundle; 79 import android.os.Debug; 80 import android.os.Handler; 81 import android.os.IBinder; 82 import android.os.IRemoteCallback; 83 import android.os.Looper; 84 import android.os.Message; 85 import android.os.Parcel; 86 import android.os.ParcelFileDescriptor; 87 import android.os.PowerManager; 88 import android.os.PowerManagerInternal; 89 import android.os.Process; 90 import android.os.RemoteException; 91 import android.os.ServiceManager; 92 import android.os.StrictMode; 93 import android.os.SystemClock; 94 import android.os.SystemProperties; 95 import android.os.Trace; 96 import android.os.UserHandle; 97 import android.os.WorkSource; 98 import android.provider.Settings; 99 import android.util.DisplayMetrics; 100 import android.util.EventLog; 101 import android.util.Log; 102 import android.util.SparseArray; 103 import android.util.Pair; 104 import android.util.Slog; 105 import android.util.SparseIntArray; 106 import android.util.TypedValue; 107 import android.view.Choreographer; 108 import android.view.Display; 109 import android.view.DisplayInfo; 110 import android.view.Gravity; 111 import android.view.IApplicationToken; 112 import android.view.IInputFilter; 113 import android.view.IOnKeyguardExitResult; 114 import android.view.IRotationWatcher; 115 import android.view.IWindow; 116 import android.view.IWindowManager; 117 import android.view.IWindowSession; 118 import android.view.InputChannel; 119 import android.view.InputDevice; 120 import android.view.InputEvent; 121 import android.view.InputEventReceiver; 122 import android.view.KeyEvent; 123 import android.view.MagnificationSpec; 124 import android.view.MotionEvent; 125 import android.view.WindowManagerInternal; 126 import android.view.Surface.OutOfResourcesException; 127 import android.view.Surface; 128 import android.view.SurfaceControl; 129 import android.view.SurfaceSession; 130 import android.view.View; 131 import android.view.ViewTreeObserver; 132 import android.view.WindowManager; 133 import android.view.WindowManagerGlobal; 134 import android.view.WindowManagerPolicy; 135 import android.view.WindowManager.LayoutParams; 136 import android.view.WindowManagerPolicy.FakeWindow; 137 import android.view.WindowManagerPolicy.PointerEventListener; 138 import android.view.animation.Animation; 139 import android.view.animation.AnimationUtils; 140 import android.view.animation.Transformation; 141 142 import java.io.BufferedWriter; 143 import java.io.DataInputStream; 144 import java.io.File; 145 import java.io.FileDescriptor; 146 import java.io.FileInputStream; 147 import java.io.FileNotFoundException; 148 import java.io.IOException; 149 import java.io.OutputStream; 150 import java.io.OutputStreamWriter; 151 import java.io.PrintWriter; 152 import java.io.StringWriter; 153 import java.net.Socket; 154 import java.text.DateFormat; 155 import java.util.ArrayList; 156 import java.util.Date; 157 import java.util.HashMap; 158 import java.util.Iterator; 159 import java.util.List; 160 161 /** {@hide} */ 162 public class WindowManagerService extends IWindowManager.Stub 163 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { 164 static final String TAG = "WindowManager"; 165 static final boolean DEBUG = false; 166 static final boolean DEBUG_ADD_REMOVE = false; 167 static final boolean DEBUG_FOCUS = false; 168 static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false; 169 static final boolean DEBUG_ANIM = false; 170 static final boolean DEBUG_KEYGUARD = false; 171 static final boolean DEBUG_LAYOUT = false; 172 static final boolean DEBUG_RESIZE = false; 173 static final boolean DEBUG_LAYERS = false; 174 static final boolean DEBUG_INPUT = false; 175 static final boolean DEBUG_INPUT_METHOD = false; 176 static final boolean DEBUG_VISIBILITY = false; 177 static final boolean DEBUG_WINDOW_MOVEMENT = false; 178 static final boolean DEBUG_TOKEN_MOVEMENT = false; 179 static final boolean DEBUG_ORIENTATION = false; 180 static final boolean DEBUG_APP_ORIENTATION = false; 181 static final boolean DEBUG_CONFIGURATION = false; 182 static final boolean DEBUG_APP_TRANSITIONS = false; 183 static final boolean DEBUG_STARTING_WINDOW = false; 184 static final boolean DEBUG_REORDER = false; 185 static final boolean DEBUG_WALLPAPER = false; 186 static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER; 187 static final boolean DEBUG_DRAG = false; 188 static final boolean DEBUG_SCREEN_ON = false; 189 static final boolean DEBUG_SCREENSHOT = false; 190 static final boolean DEBUG_BOOT = false; 191 static final boolean DEBUG_LAYOUT_REPEATS = true; 192 static final boolean DEBUG_SURFACE_TRACE = false; 193 static final boolean DEBUG_WINDOW_TRACE = false; 194 static final boolean DEBUG_TASK_MOVEMENT = false; 195 static final boolean DEBUG_STACK = false; 196 static final boolean DEBUG_DISPLAY = false; 197 static final boolean SHOW_SURFACE_ALLOC = false; 198 static final boolean SHOW_TRANSACTIONS = false; 199 static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; 200 static final boolean HIDE_STACK_CRAWLS = true; 201 static final int LAYOUT_REPEAT_THRESHOLD = 4; 202 203 static final boolean PROFILE_ORIENTATION = false; 204 static final boolean localLOGV = DEBUG; 205 206 /** How much to multiply the policy's type layer, to reserve room 207 * for multiple windows of the same type and Z-ordering adjustment 208 * with TYPE_LAYER_OFFSET. */ 209 static final int TYPE_LAYER_MULTIPLIER = 10000; 210 211 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above 212 * or below others in the same layer. */ 213 static final int TYPE_LAYER_OFFSET = 1000; 214 215 /** How much to increment the layer for each window, to reserve room 216 * for effect surfaces between them. 217 */ 218 static final int WINDOW_LAYER_MULTIPLIER = 5; 219 220 /** 221 * Dim surface layer is immediately below target window. 222 */ 223 static final int LAYER_OFFSET_DIM = 1; 224 225 /** 226 * Blur surface layer is immediately below dim layer. 227 */ 228 static final int LAYER_OFFSET_BLUR = 2; 229 230 /** 231 * FocusedStackFrame layer is immediately above focused window. 232 */ 233 static final int LAYER_OFFSET_FOCUSED_STACK = 1; 234 235 /** 236 * Animation thumbnail is as far as possible below the window above 237 * the thumbnail (or in other words as far as possible above the window 238 * below it). 239 */ 240 static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1; 241 242 /** 243 * Layer at which to put the rotation freeze snapshot. 244 */ 245 static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1; 246 247 /** 248 * Layer at which to put the mask for emulated screen sizes. 249 */ 250 static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200; 251 252 /** The maximum length we will accept for a loaded animation duration: 253 * this is 10 seconds. 254 */ 255 static final int MAX_ANIMATION_DURATION = 10*1000; 256 257 /** Amount of time (in milliseconds) to animate the fade-in-out transition for 258 * compatible windows. 259 */ 260 static final int DEFAULT_FADE_IN_OUT_DURATION = 400; 261 262 /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ 263 static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; 264 265 /** Amount of time to allow a last ANR message to exist before freeing the memory. */ 266 static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours 267 /** 268 * If true, the window manager will do its own custom freezing and general 269 * management of the screen during rotation. 270 */ 271 static final boolean CUSTOM_SCREEN_ROTATION = true; 272 273 // Maximum number of milliseconds to wait for input devices to be enumerated before 274 // proceding with safe mode detection. 275 private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; 276 277 // Default input dispatching timeout in nanoseconds. 278 static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; 279 280 // Poll interval in milliseconds for watching boot animation finished. 281 private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; 282 283 // The name of the boot animation service in init.rc. 284 private static final String BOOT_ANIMATION_SERVICE = "bootanim"; 285 286 /** Minimum value for attachStack and resizeStack weight value */ 287 public static final float STACK_WEIGHT_MIN = 0.2f; 288 289 /** Maximum value for attachStack and resizeStack weight value */ 290 public static final float STACK_WEIGHT_MAX = 0.8f; 291 292 static final int UPDATE_FOCUS_NORMAL = 0; 293 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; 294 static final int UPDATE_FOCUS_PLACING_SURFACES = 2; 295 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; 296 297 private static final String SYSTEM_SECURE = "ro.secure"; 298 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; 299 300 private static final String DENSITY_OVERRIDE = "ro.config.density_override"; 301 private static final String SIZE_OVERRIDE = "ro.config.size_override"; 302 303 private static final int MAX_SCREENSHOT_RETRIES = 3; 304 305 // The flag describing a full screen app window (where the app takes care of drawing under the 306 // SystemUI bars) 307 private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN = 308 View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 309 310 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular"; 311 312 final private KeyguardDisableHandler mKeyguardDisableHandler; 313 314 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 315 @Override 316 public void onReceive(Context context, Intent intent) { 317 final String action = intent.getAction(); 318 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) { 319 mKeyguardDisableHandler.sendEmptyMessage( 320 KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED); 321 } 322 } 323 }; 324 325 /** 326 * Current user when multi-user is enabled. Don't show windows of 327 * non-current user. Also see mCurrentProfileIds. 328 */ 329 int mCurrentUserId; 330 /** 331 * Users that are profiles of the current user. These are also allowed to show windows 332 * on the current user. 333 */ 334 int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; 335 336 final Context mContext; 337 338 final boolean mHaveInputMethods; 339 340 final boolean mHasPermanentDpad; 341 342 final boolean mAllowBootMessages; 343 344 final boolean mLimitedAlphaCompositing; 345 346 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager(); 347 348 final IActivityManager mActivityManager; 349 350 final IBatteryStats mBatteryStats; 351 352 final AppOpsManager mAppOps; 353 354 final DisplaySettings mDisplaySettings; 355 356 /** 357 * All currently active sessions with clients. 358 */ 359 final ArraySet<Session> mSessions = new ArraySet<Session>(); 360 361 /** 362 * Mapping from an IWindow IBinder to the server's Window object. 363 * This is also used as the lock for all of our state. 364 * NOTE: Never call into methods that lock ActivityManagerService while holding this object. 365 */ 366 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>(); 367 368 /** 369 * Mapping from a token IBinder to a WindowToken object. 370 */ 371 final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>(); 372 373 /** 374 * List of window tokens that have finished starting their application, 375 * and now need to have the policy remove their windows. 376 */ 377 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>(); 378 379 /** 380 * Fake windows added to the window manager. Note: ordered from top to 381 * bottom, opposite of mWindows. 382 */ 383 final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>(); 384 385 /** 386 * Windows that are being resized. Used so we can tell the client about 387 * the resize after closing the transaction in which we resized the 388 * underlying surface. 389 */ 390 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>(); 391 392 /** 393 * Windows whose animations have ended and now must be removed. 394 */ 395 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>(); 396 397 /** 398 * Stacks whose animations have ended and whose tasks, apps, selves may now be removed. 399 */ 400 final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>(); 401 402 /** 403 * Used when processing mPendingRemove to avoid working on the original array. 404 */ 405 WindowState[] mPendingRemoveTmp = new WindowState[20]; 406 407 /** 408 * Windows whose surface should be destroyed. 409 */ 410 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>(); 411 412 /** 413 * Windows that have lost input focus and are waiting for the new 414 * focus window to be displayed before they are told about this. 415 */ 416 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>(); 417 418 /** 419 * This is set when we have run out of memory, and will either be an empty 420 * list or contain windows that need to be force removed. 421 */ 422 ArrayList<WindowState> mForceRemoves; 423 424 /** 425 * Windows that clients are waiting to have drawn. 426 */ 427 ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>(); 428 /** 429 * And the callback to make when they've all been drawn. 430 */ 431 Runnable mWaitingForDrawnCallback; 432 433 /** 434 * Windows that have called relayout() while we were running animations, 435 * so we need to tell when the animation is done. 436 */ 437 final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>(); 438 439 /** 440 * Used when rebuilding window list to keep track of windows that have 441 * been removed. 442 */ 443 WindowState[] mRebuildTmp = new WindowState[20]; 444 445 /** 446 * Stores for each user whether screencapture is disabled 447 * This array is essentially a cache for all userId for 448 * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled} 449 */ 450 SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<Boolean>(); 451 452 IInputMethodManager mInputMethodManager; 453 454 AccessibilityController mAccessibilityController; 455 456 final SurfaceSession mFxSession; 457 Watermark mWatermark; 458 StrictModeFlash mStrictModeFlash; 459 CircularDisplayMask mCircularDisplayMask; 460 EmulatorDisplayOverlay mEmulatorDisplayOverlay; 461 FocusedStackFrame mFocusedStackFrame; 462 463 int mFocusedStackLayer; 464 465 final float[] mTmpFloats = new float[9]; 466 final Rect mTmpContentRect = new Rect(); 467 468 boolean mDisplayReady; 469 boolean mSafeMode; 470 boolean mDisplayEnabled = false; 471 boolean mSystemBooted = false; 472 boolean mForceDisplayEnabled = false; 473 boolean mShowingBootMessages = false; 474 boolean mBootAnimationStopped = false; 475 476 String mLastANRState; 477 478 /** All DisplayContents in the world, kept here */ 479 SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2); 480 481 int mRotation = 0; 482 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 483 boolean mAltOrientation = false; 484 485 private boolean mKeyguardWaitingForActivityDrawn; 486 487 class RotationWatcher { 488 IRotationWatcher watcher; 489 IBinder.DeathRecipient deathRecipient; 490 RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) { 491 watcher = w; 492 deathRecipient = d; 493 } 494 } 495 ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>(); 496 int mDeferredRotationPauseCount; 497 498 int mSystemDecorLayer = 0; 499 final Rect mScreenRect = new Rect(); 500 501 boolean mTraversalScheduled = false; 502 boolean mDisplayFrozen = false; 503 long mDisplayFreezeTime = 0; 504 int mLastDisplayFreezeDuration = 0; 505 Object mLastFinishedFreezeSource = null; 506 boolean mWaitingForConfig = false; 507 boolean mWindowsFreezingScreen = false; 508 boolean mClientFreezingScreen = false; 509 int mAppsFreezingScreen = 0; 510 int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 511 512 int mLayoutSeq = 0; 513 514 int mLastStatusBarVisibility = 0; 515 516 // State while inside of layoutAndPlaceSurfacesLocked(). 517 boolean mFocusMayChange; 518 519 Configuration mCurConfiguration = new Configuration(); 520 521 // This is held as long as we have the screen frozen, to give us time to 522 // perform a rotation animation when turning off shows the lock screen which 523 // changes the orientation. 524 private final PowerManager.WakeLock mScreenFrozenLock; 525 526 final AppTransition mAppTransition; 527 boolean mStartingIconInTransition = false; 528 boolean mSkipAppTransitionAnimation = false; 529 530 final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>(); 531 final ArraySet<AppWindowToken> mClosingApps = new ArraySet<AppWindowToken>(); 532 533 boolean mIsTouchDevice; 534 535 final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 536 final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); 537 final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); 538 final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); 539 540 final H mH = new H(); 541 542 final Choreographer mChoreographer = Choreographer.getInstance(); 543 544 WindowState mCurrentFocus = null; 545 WindowState mLastFocus = null; 546 547 /** This just indicates the window the input method is on top of, not 548 * necessarily the window its input is going to. */ 549 WindowState mInputMethodTarget = null; 550 551 /** If true hold off on modifying the animation layer of mInputMethodTarget */ 552 boolean mInputMethodTargetWaitingAnim; 553 int mInputMethodAnimLayerAdjustment; 554 555 WindowState mInputMethodWindow = null; 556 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); 557 558 boolean mHardKeyboardAvailable; 559 boolean mShowImeWithHardKeyboard; 560 OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; 561 SettingsObserver mSettingsObserver; 562 563 private final class SettingsObserver extends ContentObserver { 564 private final Uri mShowImeWithHardKeyboardUri = 565 Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD); 566 567 private final Uri mDisplayInversionEnabledUri = 568 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 569 570 public SettingsObserver() { 571 super(new Handler()); 572 ContentResolver resolver = mContext.getContentResolver(); 573 resolver.registerContentObserver(mShowImeWithHardKeyboardUri, false, this); 574 resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this); 575 } 576 577 @Override 578 public void onChange(boolean selfChange, Uri uri) { 579 if (mShowImeWithHardKeyboardUri.equals(uri)) { 580 updateShowImeWithHardKeyboard(); 581 } else if (mDisplayInversionEnabledUri.equals(uri)) { 582 updateCircularDisplayMaskIfNeeded(); 583 } 584 } 585 } 586 587 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); 588 589 // If non-null, this is the currently visible window that is associated 590 // with the wallpaper. 591 WindowState mWallpaperTarget = null; 592 // If non-null, we are in the middle of animating from one wallpaper target 593 // to another, and this is the lower one in Z-order. 594 WindowState mLowerWallpaperTarget = null; 595 // If non-null, we are in the middle of animating from one wallpaper target 596 // to another, and this is the higher one in Z-order. 597 WindowState mUpperWallpaperTarget = null; 598 int mWallpaperAnimLayerAdjustment; 599 float mLastWallpaperX = -1; 600 float mLastWallpaperY = -1; 601 float mLastWallpaperXStep = -1; 602 float mLastWallpaperYStep = -1; 603 int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE; 604 int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE; 605 // This is set when we are waiting for a wallpaper to tell us it is done 606 // changing its scroll position. 607 WindowState mWaitingOnWallpaper; 608 // The last time we had a timeout when waiting for a wallpaper. 609 long mLastWallpaperTimeoutTime; 610 // We give a wallpaper up to 150ms to finish scrolling. 611 static final long WALLPAPER_TIMEOUT = 150; 612 // Time we wait after a timeout before trying to wait again. 613 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000; 614 boolean mAnimateWallpaperWithTarget; 615 616 AppWindowToken mFocusedApp = null; 617 618 PowerManager mPowerManager; 619 PowerManagerInternal mPowerManagerInternal; 620 621 float mWindowAnimationScaleSetting = 1.0f; 622 float mTransitionAnimationScaleSetting = 1.0f; 623 float mAnimatorDurationScaleSetting = 1.0f; 624 boolean mAnimationsDisabled = false; 625 626 final InputManagerService mInputManager; 627 final DisplayManagerInternal mDisplayManagerInternal; 628 final DisplayManager mDisplayManager; 629 630 // Who is holding the screen on. 631 Session mHoldingScreenOn; 632 PowerManager.WakeLock mHoldingScreenWakeLock; 633 634 boolean mTurnOnScreen; 635 636 // Whether or not a layout can cause a wake up when theater mode is enabled. 637 boolean mAllowTheaterModeWakeFromLayout; 638 639 DragState mDragState = null; 640 641 // For frozen screen animations. 642 int mExitAnimId, mEnterAnimId; 643 644 /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple 645 * methods. */ 646 class LayoutFields { 647 static final int SET_UPDATE_ROTATION = 1 << 0; 648 static final int SET_WALLPAPER_MAY_CHANGE = 1 << 1; 649 static final int SET_FORCE_HIDING_CHANGED = 1 << 2; 650 static final int SET_ORIENTATION_CHANGE_COMPLETE = 1 << 3; 651 static final int SET_TURN_ON_SCREEN = 1 << 4; 652 static final int SET_WALLPAPER_ACTION_PENDING = 1 << 5; 653 654 boolean mWallpaperForceHidingChanged = false; 655 boolean mWallpaperMayChange = false; 656 boolean mOrientationChangeComplete = true; 657 Object mLastWindowFreezeSource = null; 658 private Session mHoldScreen = null; 659 private boolean mObscured = false; 660 private boolean mSyswin = false; 661 private float mScreenBrightness = -1; 662 private float mButtonBrightness = -1; 663 private long mUserActivityTimeout = -1; 664 private boolean mUpdateRotation = false; 665 boolean mWallpaperActionPending = false; 666 667 // Set to true when the display contains content to show the user. 668 // When false, the display manager may choose to mirror or blank the display. 669 boolean mDisplayHasContent = false; 670 671 // Only set while traversing the default display based on its content. 672 // Affects the behavior of mirroring on secondary displays. 673 boolean mObscureApplicationContentOnSecondaryDisplays = false; 674 675 float mPreferredRefreshRate = 0; 676 } 677 final LayoutFields mInnerFields = new LayoutFields(); 678 679 boolean mAnimationScheduled; 680 681 /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this 682 * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */ 683 private int mTransactionSequence; 684 685 /** Only do a maximum of 6 repeated layouts. After that quit */ 686 private int mLayoutRepeatCount; 687 688 final WindowAnimator mAnimator; 689 690 SparseArray<Task> mTaskIdToTask = new SparseArray<Task>(); 691 692 /** All of the TaskStacks in the window manager, unordered. For an ordered list call 693 * DisplayContent.getStacks(). */ 694 SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>(); 695 696 private final PointerEventDispatcher mPointerEventDispatcher; 697 698 private WindowContentFrameStats mTempWindowRenderStats; 699 700 final class DragInputEventReceiver extends InputEventReceiver { 701 public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { 702 super(inputChannel, looper); 703 } 704 705 @Override 706 public void onInputEvent(InputEvent event) { 707 boolean handled = false; 708 try { 709 if (event instanceof MotionEvent 710 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 711 && mDragState != null) { 712 final MotionEvent motionEvent = (MotionEvent)event; 713 boolean endDrag = false; 714 final float newX = motionEvent.getRawX(); 715 final float newY = motionEvent.getRawY(); 716 717 switch (motionEvent.getAction()) { 718 case MotionEvent.ACTION_DOWN: { 719 if (DEBUG_DRAG) { 720 Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer"); 721 } 722 } break; 723 724 case MotionEvent.ACTION_MOVE: { 725 synchronized (mWindowMap) { 726 // move the surface and tell the involved window(s) where we are 727 mDragState.notifyMoveLw(newX, newY); 728 } 729 } break; 730 731 case MotionEvent.ACTION_UP: { 732 if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at " 733 + newX + "," + newY); 734 synchronized (mWindowMap) { 735 endDrag = mDragState.notifyDropLw(newX, newY); 736 } 737 } break; 738 739 case MotionEvent.ACTION_CANCEL: { 740 if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!"); 741 endDrag = true; 742 } break; 743 } 744 745 if (endDrag) { 746 if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state"); 747 // tell all the windows that the drag has ended 748 synchronized (mWindowMap) { 749 mDragState.endDragLw(); 750 } 751 } 752 753 handled = true; 754 } 755 } catch (Exception e) { 756 Slog.e(TAG, "Exception caught by drag handleMotion", e); 757 } finally { 758 finishInputEvent(event, handled); 759 } 760 } 761 } 762 763 /** 764 * Whether the UI is currently running in touch mode (not showing 765 * navigational focus because the user is directly pressing the screen). 766 */ 767 boolean mInTouchMode; 768 769 private ViewServer mViewServer; 770 private final ArrayList<WindowChangeListener> mWindowChangeListeners = 771 new ArrayList<WindowChangeListener>(); 772 private boolean mWindowsChanged = false; 773 774 public interface WindowChangeListener { 775 public void windowsChanged(); 776 public void focusChanged(); 777 } 778 779 final Configuration mTempConfiguration = new Configuration(); 780 781 // The desired scaling factor for compatible apps. 782 float mCompatibleScreenScale; 783 784 // If true, only the core apps and services are being launched because the device 785 // is in a special boot mode, such as being encrypted or waiting for a decryption password. 786 // For example, when this flag is true, there will be no wallpaper service. 787 final boolean mOnlyCore; 788 789 public static WindowManagerService main(final Context context, 790 final InputManagerService im, 791 final boolean haveInputMethods, final boolean showBootMsgs, 792 final boolean onlyCore) { 793 final WindowManagerService[] holder = new WindowManagerService[1]; 794 DisplayThread.getHandler().runWithScissors(new Runnable() { 795 @Override 796 public void run() { 797 holder[0] = new WindowManagerService(context, im, 798 haveInputMethods, showBootMsgs, onlyCore); 799 } 800 }, 0); 801 return holder[0]; 802 } 803 804 private void initPolicy() { 805 UiThread.getHandler().runWithScissors(new Runnable() { 806 @Override 807 public void run() { 808 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); 809 810 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); 811 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer() 812 * TYPE_LAYER_MULTIPLIER 813 + TYPE_LAYER_OFFSET; 814 } 815 }, 0); 816 } 817 818 private WindowManagerService(Context context, InputManagerService inputManager, 819 boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { 820 mContext = context; 821 mHaveInputMethods = haveInputMethods; 822 mAllowBootMessages = showBootMsgs; 823 mOnlyCore = onlyCore; 824 mLimitedAlphaCompositing = context.getResources().getBoolean( 825 com.android.internal.R.bool.config_sf_limitedAlpha); 826 mHasPermanentDpad = context.getResources().getBoolean( 827 com.android.internal.R.bool.config_hasPermanentDpad); 828 mInTouchMode = context.getResources().getBoolean( 829 com.android.internal.R.bool.config_defaultInTouchMode); 830 mInputManager = inputManager; // Must be before createDisplayContentLocked. 831 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 832 mDisplaySettings = new DisplaySettings(); 833 mDisplaySettings.readSettingsLocked(); 834 835 LocalServices.addService(WindowManagerPolicy.class, mPolicy); 836 837 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG)); 838 839 mFxSession = new SurfaceSession(); 840 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 841 Display[] displays = mDisplayManager.getDisplays(); 842 for (Display display : displays) { 843 createDisplayContentLocked(display); 844 } 845 846 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 847 848 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 849 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 850 mPowerManagerInternal.registerLowPowerModeObserver( 851 new PowerManagerInternal.LowPowerModeListener() { 852 @Override 853 public void onLowPowerModeChanged(boolean enabled) { 854 synchronized (mWindowMap) { 855 if (mAnimationsDisabled != enabled) { 856 mAnimationsDisabled = enabled; 857 dispatchNewAnimatorScaleLocked(null); 858 } 859 } 860 } 861 }); 862 mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled(); 863 mScreenFrozenLock = mPowerManager.newWakeLock( 864 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); 865 mScreenFrozenLock.setReferenceCounted(false); 866 867 mAppTransition = new AppTransition(context, mH); 868 869 mActivityManager = ActivityManagerNative.getDefault(); 870 mBatteryStats = BatteryStatsService.getService(); 871 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 872 AppOpsManager.OnOpChangedInternalListener opListener = 873 new AppOpsManager.OnOpChangedInternalListener() { 874 @Override public void onOpChanged(int op, String packageName) { 875 updateAppOpsState(); 876 } 877 }; 878 mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener); 879 mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener); 880 881 // Get persisted window scale setting 882 mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 883 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting); 884 mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(), 885 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting); 886 setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(), 887 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting)); 888 889 // Track changes to DevicePolicyManager state so we can enable/disable keyguard. 890 IntentFilter filter = new IntentFilter(); 891 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 892 mContext.registerReceiver(mBroadcastReceiver, filter); 893 894 mSettingsObserver = new SettingsObserver(); 895 updateShowImeWithHardKeyboard(); 896 897 mHoldingScreenWakeLock = mPowerManager.newWakeLock( 898 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG); 899 mHoldingScreenWakeLock.setReferenceCounted(false); 900 901 mAnimator = new WindowAnimator(this); 902 903 mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean( 904 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout); 905 906 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 907 initPolicy(); 908 909 // Add ourself to the Watchdog monitors. 910 Watchdog.getInstance().addMonitor(this); 911 912 SurfaceControl.openTransaction(); 913 try { 914 createWatermarkInTransaction(); 915 mFocusedStackFrame = new FocusedStackFrame( 916 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 917 } finally { 918 SurfaceControl.closeTransaction(); 919 } 920 921 updateCircularDisplayMaskIfNeeded(); 922 showEmulatorDisplayOverlayIfNeeded(); 923 } 924 925 public InputMonitor getInputMonitor() { 926 return mInputMonitor; 927 } 928 929 @Override 930 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 931 throws RemoteException { 932 try { 933 return super.onTransact(code, data, reply, flags); 934 } catch (RuntimeException e) { 935 // The window manager only throws security exceptions, so let's 936 // log all others. 937 if (!(e instanceof SecurityException)) { 938 Slog.wtf(TAG, "Window Manager Crash", e); 939 } 940 throw e; 941 } 942 } 943 944 private void placeWindowAfter(WindowState pos, WindowState window) { 945 final WindowList windows = pos.getWindowList(); 946 final int i = windows.indexOf(pos); 947 if (true || DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 948 TAG, "Adding window " + window + " at " 949 + (i+1) + " of " + windows.size() + " (after " + pos + ")"); 950 windows.add(i+1, window); 951 mWindowsChanged = true; 952 } 953 954 private void placeWindowBefore(WindowState pos, WindowState window) { 955 final WindowList windows = pos.getWindowList(); 956 int i = windows.indexOf(pos); 957 if (true || DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 958 TAG, "Adding window " + window + " at " 959 + i + " of " + windows.size() + " (before " + pos + ")"); 960 if (i < 0) { 961 Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows); 962 i = 0; 963 } 964 windows.add(i, window); 965 mWindowsChanged = true; 966 } 967 968 //This method finds out the index of a window that has the same app token as 969 //win. used for z ordering the windows in mWindows 970 private int findIdxBasedOnAppTokens(WindowState win) { 971 WindowList windows = win.getWindowList(); 972 for(int j = windows.size() - 1; j >= 0; j--) { 973 WindowState wentry = windows.get(j); 974 if(wentry.mAppToken == win.mAppToken) { 975 return j; 976 } 977 } 978 return -1; 979 } 980 981 /** 982 * Return the list of Windows from the passed token on the given Display. 983 * @param token The token with all the windows. 984 * @param displayContent The display we are interested in. 985 * @return List of windows from token that are on displayContent. 986 */ 987 WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) { 988 final WindowList windowList = new WindowList(); 989 final int count = token.windows.size(); 990 for (int i = 0; i < count; i++) { 991 final WindowState win = token.windows.get(i); 992 if (win.getDisplayContent() == displayContent) { 993 windowList.add(win); 994 } 995 } 996 return windowList; 997 } 998 999 /** 1000 * Recursive search through a WindowList and all of its windows' children. 1001 * @param targetWin The window to search for. 1002 * @param windows The list to search. 1003 * @return The index of win in windows or of the window that is an ancestor of win. 1004 */ 1005 private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) { 1006 for (int i = windows.size() - 1; i >= 0; i--) { 1007 final WindowState w = windows.get(i); 1008 if (w == targetWin) { 1009 return i; 1010 } 1011 if (!w.mChildWindows.isEmpty()) { 1012 if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) { 1013 return i; 1014 } 1015 } 1016 } 1017 return -1; 1018 } 1019 1020 private int addAppWindowToListLocked(final WindowState win) { 1021 final IWindow client = win.mClient; 1022 final WindowToken token = win.mToken; 1023 final DisplayContent displayContent = win.getDisplayContent(); 1024 if (displayContent == null) { 1025 // It doesn't matter this display is going away. 1026 return 0; 1027 } 1028 1029 final WindowList windows = win.getWindowList(); 1030 final int N = windows.size(); 1031 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1032 int tokenWindowsPos = 0; 1033 int windowListPos = tokenWindowList.size(); 1034 if (!tokenWindowList.isEmpty()) { 1035 // If this application has existing windows, we 1036 // simply place the new window on top of them... but 1037 // keep the starting window on top. 1038 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 1039 // Base windows go behind everything else. 1040 WindowState lowestWindow = tokenWindowList.get(0); 1041 placeWindowBefore(lowestWindow, win); 1042 tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows); 1043 } else { 1044 AppWindowToken atoken = win.mAppToken; 1045 WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 1046 if (atoken != null && lastWindow == atoken.startingWindow) { 1047 placeWindowBefore(lastWindow, win); 1048 tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows); 1049 } else { 1050 int newIdx = findIdxBasedOnAppTokens(win); 1051 //there is a window above this one associated with the same 1052 //apptoken note that the window could be a floating window 1053 //that was created later or a window at the top of the list of 1054 //windows associated with this token. 1055 if (true || DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1056 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + 1057 N); 1058 windows.add(newIdx + 1, win); 1059 if (newIdx < 0) { 1060 // No window from token found on win's display. 1061 tokenWindowsPos = 0; 1062 } else { 1063 tokenWindowsPos = indexOfWinInWindowList( 1064 windows.get(newIdx), token.windows) + 1; 1065 } 1066 mWindowsChanged = true; 1067 } 1068 } 1069 return tokenWindowsPos; 1070 } 1071 1072 // No windows from this token on this display 1073 if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder() 1074 + " (token=" + token + ")"); 1075 // Figure out where the window should go, based on the 1076 // order of applications. 1077 WindowState pos = null; 1078 1079 final ArrayList<Task> tasks = displayContent.getTasks(); 1080 int taskNdx; 1081 int tokenNdx = -1; 1082 for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1083 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1084 for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 1085 final AppWindowToken t = tokens.get(tokenNdx); 1086 if (t == token) { 1087 --tokenNdx; 1088 if (tokenNdx < 0) { 1089 --taskNdx; 1090 if (taskNdx >= 0) { 1091 tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1; 1092 } 1093 } 1094 break; 1095 } 1096 1097 // We haven't reached the token yet; if this token 1098 // is not going to the bottom and has windows on this display, we can 1099 // use it as an anchor for when we do reach the token. 1100 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1101 if (!t.sendingToBottom && tokenWindowList.size() > 0) { 1102 pos = tokenWindowList.get(0); 1103 } 1104 } 1105 if (tokenNdx >= 0) { 1106 // early exit 1107 break; 1108 } 1109 } 1110 1111 // We now know the index into the apps. If we found 1112 // an app window above, that gives us the position; else 1113 // we need to look some more. 1114 if (pos != null) { 1115 // Move behind any windows attached to this one. 1116 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1117 if (atoken != null) { 1118 tokenWindowList = 1119 getTokenWindowsOnDisplay(atoken, displayContent); 1120 final int NC = tokenWindowList.size(); 1121 if (NC > 0) { 1122 WindowState bottom = tokenWindowList.get(0); 1123 if (bottom.mSubLayer < 0) { 1124 pos = bottom; 1125 } 1126 } 1127 } 1128 placeWindowBefore(pos, win); 1129 return tokenWindowsPos; 1130 } 1131 1132 // Continue looking down until we find the first 1133 // token that has windows on this display. 1134 for ( ; taskNdx >= 0; --taskNdx) { 1135 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 1136 for ( ; tokenNdx >= 0; --tokenNdx) { 1137 final AppWindowToken t = tokens.get(tokenNdx); 1138 tokenWindowList = getTokenWindowsOnDisplay(t, displayContent); 1139 final int NW = tokenWindowList.size(); 1140 if (NW > 0) { 1141 pos = tokenWindowList.get(NW-1); 1142 break; 1143 } 1144 } 1145 if (tokenNdx >= 0) { 1146 // found 1147 break; 1148 } 1149 } 1150 1151 if (pos != null) { 1152 // Move in front of any windows attached to this 1153 // one. 1154 WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); 1155 if (atoken != null) { 1156 final int NC = atoken.windows.size(); 1157 if (NC > 0) { 1158 WindowState top = atoken.windows.get(NC-1); 1159 if (top.mSubLayer >= 0) { 1160 pos = top; 1161 } 1162 } 1163 } 1164 placeWindowAfter(pos, win); 1165 return tokenWindowsPos; 1166 } 1167 1168 // Just search for the start of this layer. 1169 final int myLayer = win.mBaseLayer; 1170 int i; 1171 for (i = N - 1; i >= 0; --i) { 1172 WindowState w = windows.get(i); 1173 if (w.mBaseLayer <= myLayer) { 1174 break; 1175 } 1176 } 1177 if (true || DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1178 "Based on layer: Adding window " + win + " at " + (i + 1) + " of " + N); 1179 windows.add(i + 1, win); 1180 mWindowsChanged = true; 1181 return tokenWindowsPos; 1182 } 1183 1184 private void addFreeWindowToListLocked(final WindowState win) { 1185 final WindowList windows = win.getWindowList(); 1186 1187 // Figure out where window should go, based on layer. 1188 final int myLayer = win.mBaseLayer; 1189 int i; 1190 for (i = windows.size() - 1; i >= 0; i--) { 1191 if (windows.get(i).mBaseLayer <= myLayer) { 1192 break; 1193 } 1194 } 1195 i++; 1196 if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, 1197 "Free window: Adding window " + win + " at " + i + " of " + windows.size()); 1198 windows.add(i, win); 1199 mWindowsChanged = true; 1200 } 1201 1202 private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) { 1203 final WindowToken token = win.mToken; 1204 final DisplayContent displayContent = win.getDisplayContent(); 1205 if (displayContent == null) { 1206 return; 1207 } 1208 final WindowState attached = win.mAttachedWindow; 1209 1210 WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent); 1211 1212 // Figure out this window's ordering relative to the window 1213 // it is attached to. 1214 final int NA = tokenWindowList.size(); 1215 final int sublayer = win.mSubLayer; 1216 int largestSublayer = Integer.MIN_VALUE; 1217 WindowState windowWithLargestSublayer = null; 1218 int i; 1219 for (i = 0; i < NA; i++) { 1220 WindowState w = tokenWindowList.get(i); 1221 final int wSublayer = w.mSubLayer; 1222 if (wSublayer >= largestSublayer) { 1223 largestSublayer = wSublayer; 1224 windowWithLargestSublayer = w; 1225 } 1226 if (sublayer < 0) { 1227 // For negative sublayers, we go below all windows 1228 // in the same sublayer. 1229 if (wSublayer >= sublayer) { 1230 if (addToToken) { 1231 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1232 token.windows.add(i, win); 1233 } 1234 placeWindowBefore(wSublayer >= 0 ? attached : w, win); 1235 break; 1236 } 1237 } else { 1238 // For positive sublayers, we go above all windows 1239 // in the same sublayer. 1240 if (wSublayer > sublayer) { 1241 if (addToToken) { 1242 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1243 token.windows.add(i, win); 1244 } 1245 placeWindowBefore(w, win); 1246 break; 1247 } 1248 } 1249 } 1250 if (i >= NA) { 1251 if (addToToken) { 1252 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1253 token.windows.add(win); 1254 } 1255 if (sublayer < 0) { 1256 placeWindowBefore(attached, win); 1257 } else { 1258 placeWindowAfter(largestSublayer >= 0 1259 ? windowWithLargestSublayer 1260 : attached, 1261 win); 1262 } 1263 } 1264 } 1265 1266 private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) { 1267 if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win + 1268 " Callers=" + Debug.getCallers(4)); 1269 if (win.mAttachedWindow == null) { 1270 final WindowToken token = win.mToken; 1271 int tokenWindowsPos = 0; 1272 if (token.appWindowToken != null) { 1273 tokenWindowsPos = addAppWindowToListLocked(win); 1274 } else { 1275 addFreeWindowToListLocked(win); 1276 } 1277 if (addToToken) { 1278 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); 1279 token.windows.add(tokenWindowsPos, win); 1280 } 1281 } else { 1282 addAttachedWindowToListLocked(win, addToToken); 1283 } 1284 1285 if (win.mAppToken != null && addToToken) { 1286 win.mAppToken.allAppWindows.add(win); 1287 } 1288 } 1289 1290 static boolean canBeImeTarget(WindowState w) { 1291 final int fl = w.mAttrs.flags 1292 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1293 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) 1294 || w.mAttrs.type == TYPE_APPLICATION_STARTING) { 1295 if (DEBUG_INPUT_METHOD) { 1296 Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1297 if (!w.isVisibleOrAdding()) { 1298 Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurfaceControl 1299 + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility 1300 + " policyVis=" + w.mPolicyVisibility 1301 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1302 + " attachHid=" + w.mAttachedHidden 1303 + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); 1304 if (w.mAppToken != null) { 1305 Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1306 } 1307 } 1308 } 1309 return w.isVisibleOrAdding(); 1310 } 1311 return false; 1312 } 1313 1314 /** 1315 * Dig through the WindowStates and find the one that the Input Method will target. 1316 * @param willMove 1317 * @return The index+1 in mWindows of the discovered target. 1318 */ 1319 int findDesiredInputMethodWindowIndexLocked(boolean willMove) { 1320 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1321 // same display. Or even when the current IME/target are not on the same screen as the next 1322 // IME/target. For now only look for input windows on the main screen. 1323 WindowList windows = getDefaultWindowListLocked(); 1324 WindowState w = null; 1325 int i; 1326 for (i = windows.size() - 1; i >= 0; --i) { 1327 WindowState win = windows.get(i); 1328 1329 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i 1330 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1331 if (canBeImeTarget(win)) { 1332 w = win; 1333 //Slog.i(TAG, "Putting input method here!"); 1334 1335 // Yet more tricksyness! If this window is a "starting" 1336 // window, we do actually want to be on top of it, but 1337 // it is not -really- where input will go. So if the caller 1338 // is not actually looking to move the IME, look down below 1339 // for a real window to target... 1340 if (!willMove 1341 && w.mAttrs.type == TYPE_APPLICATION_STARTING 1342 && i > 0) { 1343 WindowState wb = windows.get(i-1); 1344 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1345 i--; 1346 w = wb; 1347 } 1348 } 1349 break; 1350 } 1351 } 1352 1353 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1354 1355 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w); 1356 1357 // Now, a special case -- if the last target's window is in the 1358 // process of exiting, and is above the new target, keep on the 1359 // last target to avoid flicker. Consider for example a Dialog with 1360 // the IME shown: when the Dialog is dismissed, we want to keep 1361 // the IME above it until it is completely gone so it doesn't drop 1362 // behind the dialog or its full-screen scrim. 1363 final WindowState curTarget = mInputMethodTarget; 1364 if (curTarget != null 1365 && curTarget.isDisplayedLw() 1366 && curTarget.isClosing() 1367 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1368 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing"); 1369 return windows.indexOf(curTarget) + 1; 1370 } 1371 1372 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target=" 1373 + w + " willMove=" + willMove); 1374 1375 if (willMove && w != null) { 1376 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1377 if (token != null) { 1378 1379 // Now some fun for dealing with window animations that 1380 // modify the Z order. We need to look at all windows below 1381 // the current target that are in this app, finding the highest 1382 // visible one in layering. 1383 WindowState highestTarget = null; 1384 int highestPos = 0; 1385 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1386 WindowList curWindows = curTarget.getWindowList(); 1387 int pos = curWindows.indexOf(curTarget); 1388 while (pos >= 0) { 1389 WindowState win = curWindows.get(pos); 1390 if (win.mAppToken != token) { 1391 break; 1392 } 1393 if (!win.mRemoved) { 1394 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1395 highestTarget.mWinAnimator.mAnimLayer) { 1396 highestTarget = win; 1397 highestPos = pos; 1398 } 1399 } 1400 pos--; 1401 } 1402 } 1403 1404 if (highestTarget != null) { 1405 if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget 1406 + " animating=" + highestTarget.mWinAnimator.isAnimating() 1407 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1408 + " new layer=" + w.mWinAnimator.mAnimLayer); 1409 1410 if (mAppTransition.isTransitionSet()) { 1411 // If we are currently setting up for an animation, 1412 // hold everything until we can find out what will happen. 1413 mInputMethodTargetWaitingAnim = true; 1414 mInputMethodTarget = highestTarget; 1415 return highestPos + 1; 1416 } else if (highestTarget.mWinAnimator.isAnimating() && 1417 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1418 // If the window we are currently targeting is involved 1419 // with an animation, and it is on top of the next target 1420 // we will be over, then hold off on moving until 1421 // that is done. 1422 mInputMethodTargetWaitingAnim = true; 1423 mInputMethodTarget = highestTarget; 1424 return highestPos + 1; 1425 } 1426 } 1427 } 1428 } 1429 1430 //Slog.i(TAG, "Placing input method @" + (i+1)); 1431 if (w != null) { 1432 if (willMove) { 1433 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to " 1434 + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1435 mInputMethodTarget = w; 1436 mInputMethodTargetWaitingAnim = false; 1437 if (w.mAppToken != null) { 1438 setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment); 1439 } else { 1440 setInputMethodAnimLayerAdjustment(0); 1441 } 1442 } 1443 return i+1; 1444 } 1445 if (willMove) { 1446 if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null." 1447 + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4))); 1448 mInputMethodTarget = null; 1449 setInputMethodAnimLayerAdjustment(0); 1450 } 1451 return -1; 1452 } 1453 1454 void addInputMethodWindowToListLocked(WindowState win) { 1455 int pos = findDesiredInputMethodWindowIndexLocked(true); 1456 if (pos >= 0) { 1457 win.mTargetAppToken = mInputMethodTarget.mAppToken; 1458 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( 1459 TAG, "Adding input method window " + win + " at " + pos); 1460 // TODO(multidisplay): IMEs are only supported on the default display. 1461 getDefaultWindowListLocked().add(pos, win); 1462 mWindowsChanged = true; 1463 moveInputMethodDialogsLocked(pos+1); 1464 return; 1465 } 1466 win.mTargetAppToken = null; 1467 addWindowToListInOrderLocked(win, true); 1468 moveInputMethodDialogsLocked(pos); 1469 } 1470 1471 void setInputMethodAnimLayerAdjustment(int adj) { 1472 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj); 1473 mInputMethodAnimLayerAdjustment = adj; 1474 WindowState imw = mInputMethodWindow; 1475 if (imw != null) { 1476 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1477 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1478 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1479 int wi = imw.mChildWindows.size(); 1480 while (wi > 0) { 1481 wi--; 1482 WindowState cw = imw.mChildWindows.get(wi); 1483 cw.mWinAnimator.mAnimLayer = cw.mLayer + adj; 1484 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw 1485 + " anim layer: " + cw.mWinAnimator.mAnimLayer); 1486 } 1487 } 1488 int di = mInputMethodDialogs.size(); 1489 while (di > 0) { 1490 di --; 1491 imw = mInputMethodDialogs.get(di); 1492 imw.mWinAnimator.mAnimLayer = imw.mLayer + adj; 1493 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw 1494 + " anim layer: " + imw.mWinAnimator.mAnimLayer); 1495 } 1496 } 1497 1498 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { 1499 WindowList windows = win.getWindowList(); 1500 int wpos = windows.indexOf(win); 1501 if (wpos >= 0) { 1502 if (wpos < interestingPos) interestingPos--; 1503 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win); 1504 windows.remove(wpos); 1505 mWindowsChanged = true; 1506 int NC = win.mChildWindows.size(); 1507 while (NC > 0) { 1508 NC--; 1509 WindowState cw = win.mChildWindows.get(NC); 1510 int cpos = windows.indexOf(cw); 1511 if (cpos >= 0) { 1512 if (cpos < interestingPos) interestingPos--; 1513 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at " 1514 + cpos + ": " + cw); 1515 windows.remove(cpos); 1516 } 1517 } 1518 } 1519 return interestingPos; 1520 } 1521 1522 private void reAddWindowToListInOrderLocked(WindowState win) { 1523 addWindowToListInOrderLocked(win, false); 1524 // This is a hack to get all of the child windows added as well 1525 // at the right position. Child windows should be rare and 1526 // this case should be rare, so it shouldn't be that big a deal. 1527 WindowList windows = win.getWindowList(); 1528 int wpos = windows.indexOf(win); 1529 if (wpos >= 0) { 1530 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win); 1531 windows.remove(wpos); 1532 mWindowsChanged = true; 1533 reAddWindowLocked(wpos, win); 1534 } 1535 } 1536 1537 void logWindowList(final WindowList windows, String prefix) { 1538 int N = windows.size(); 1539 while (N > 0) { 1540 N--; 1541 Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N)); 1542 } 1543 } 1544 1545 void moveInputMethodDialogsLocked(int pos) { 1546 ArrayList<WindowState> dialogs = mInputMethodDialogs; 1547 1548 // TODO(multidisplay): IMEs are only supported on the default display. 1549 WindowList windows = getDefaultWindowListLocked(); 1550 final int N = dialogs.size(); 1551 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos); 1552 for (int i=0; i<N; i++) { 1553 pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); 1554 } 1555 if (DEBUG_INPUT_METHOD) { 1556 Slog.v(TAG, "Window list w/pos=" + pos); 1557 logWindowList(windows, " "); 1558 } 1559 1560 if (pos >= 0) { 1561 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; 1562 // Skip windows owned by the input method. 1563 if (mInputMethodWindow != null) { 1564 while (pos < windows.size()) { 1565 WindowState wp = windows.get(pos); 1566 if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) { 1567 pos++; 1568 continue; 1569 } 1570 break; 1571 } 1572 } 1573 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos); 1574 for (int i=0; i<N; i++) { 1575 WindowState win = dialogs.get(i); 1576 win.mTargetAppToken = targetAppToken; 1577 pos = reAddWindowLocked(pos, win); 1578 } 1579 if (DEBUG_INPUT_METHOD) { 1580 Slog.v(TAG, "Final window list:"); 1581 logWindowList(windows, " "); 1582 } 1583 return; 1584 } 1585 for (int i=0; i<N; i++) { 1586 WindowState win = dialogs.get(i); 1587 win.mTargetAppToken = null; 1588 reAddWindowToListInOrderLocked(win); 1589 if (DEBUG_INPUT_METHOD) { 1590 Slog.v(TAG, "No IM target, final list:"); 1591 logWindowList(windows, " "); 1592 } 1593 } 1594 } 1595 1596 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { 1597 final WindowState imWin = mInputMethodWindow; 1598 final int DN = mInputMethodDialogs.size(); 1599 if (imWin == null && DN == 0) { 1600 return false; 1601 } 1602 1603 // TODO(multidisplay): IMEs are only supported on the default display. 1604 WindowList windows = getDefaultWindowListLocked(); 1605 1606 int imPos = findDesiredInputMethodWindowIndexLocked(true); 1607 if (imPos >= 0) { 1608 // In this case, the input method windows are to be placed 1609 // immediately above the window they are targeting. 1610 1611 // First check to see if the input method windows are already 1612 // located here, and contiguous. 1613 final int N = windows.size(); 1614 WindowState firstImWin = imPos < N 1615 ? windows.get(imPos) : null; 1616 1617 // Figure out the actual input method window that should be 1618 // at the bottom of their stack. 1619 WindowState baseImWin = imWin != null 1620 ? imWin : mInputMethodDialogs.get(0); 1621 if (baseImWin.mChildWindows.size() > 0) { 1622 WindowState cw = baseImWin.mChildWindows.get(0); 1623 if (cw.mSubLayer < 0) baseImWin = cw; 1624 } 1625 1626 if (firstImWin == baseImWin) { 1627 // The windows haven't moved... but are they still contiguous? 1628 // First find the top IM window. 1629 int pos = imPos+1; 1630 while (pos < N) { 1631 if (!(windows.get(pos)).mIsImWindow) { 1632 break; 1633 } 1634 pos++; 1635 } 1636 pos++; 1637 // Now there should be no more input method windows above. 1638 while (pos < N) { 1639 if ((windows.get(pos)).mIsImWindow) { 1640 break; 1641 } 1642 pos++; 1643 } 1644 if (pos >= N) { 1645 // Z order is good. 1646 // The IM target window may be changed, so update the mTargetAppToken. 1647 if (imWin != null) { 1648 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1649 } 1650 return false; 1651 } 1652 } 1653 1654 if (imWin != null) { 1655 if (DEBUG_INPUT_METHOD) { 1656 Slog.v(TAG, "Moving IM from " + imPos); 1657 logWindowList(windows, " "); 1658 } 1659 imPos = tmpRemoveWindowLocked(imPos, imWin); 1660 if (DEBUG_INPUT_METHOD) { 1661 Slog.v(TAG, "List after removing with new pos " + imPos + ":"); 1662 logWindowList(windows, " "); 1663 } 1664 imWin.mTargetAppToken = mInputMethodTarget.mAppToken; 1665 reAddWindowLocked(imPos, imWin); 1666 if (DEBUG_INPUT_METHOD) { 1667 Slog.v(TAG, "List after moving IM to " + imPos + ":"); 1668 logWindowList(windows, " "); 1669 } 1670 if (DN > 0) moveInputMethodDialogsLocked(imPos+1); 1671 } else { 1672 moveInputMethodDialogsLocked(imPos); 1673 } 1674 1675 } else { 1676 // In this case, the input method windows go in a fixed layer, 1677 // because they aren't currently associated with a focus window. 1678 1679 if (imWin != null) { 1680 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos); 1681 tmpRemoveWindowLocked(0, imWin); 1682 imWin.mTargetAppToken = null; 1683 reAddWindowToListInOrderLocked(imWin); 1684 if (DEBUG_INPUT_METHOD) { 1685 Slog.v(TAG, "List with no IM target:"); 1686 logWindowList(windows, " "); 1687 } 1688 if (DN > 0) moveInputMethodDialogsLocked(-1); 1689 } else { 1690 moveInputMethodDialogsLocked(-1); 1691 } 1692 1693 } 1694 1695 if (needAssignLayers) { 1696 assignLayersLocked(windows); 1697 } 1698 1699 return true; 1700 } 1701 1702 final boolean isWallpaperVisible(WindowState wallpaperTarget) { 1703 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" 1704 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") 1705 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) 1706 ? wallpaperTarget.mAppToken.mAppAnimator.animation : null) 1707 + " upper=" + mUpperWallpaperTarget 1708 + " lower=" + mLowerWallpaperTarget); 1709 return (wallpaperTarget != null 1710 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null 1711 && wallpaperTarget.mAppToken.mAppAnimator.animation != null))) 1712 || mUpperWallpaperTarget != null 1713 || mLowerWallpaperTarget != null; 1714 } 1715 1716 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; 1717 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; 1718 1719 int adjustWallpaperWindowsLocked() { 1720 mInnerFields.mWallpaperMayChange = false; 1721 boolean targetChanged = false; 1722 1723 // TODO(multidisplay): Wallpapers on main screen only. 1724 final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo(); 1725 final int dw = displayInfo.logicalWidth; 1726 final int dh = displayInfo.logicalHeight; 1727 1728 // First find top-most window that has asked to be on top of the 1729 // wallpaper; all wallpapers go behind it. 1730 final WindowList windows = getDefaultWindowListLocked(); 1731 int N = windows.size(); 1732 WindowState w = null; 1733 WindowState foundW = null; 1734 int foundI = 0; 1735 WindowState topCurW = null; 1736 int topCurI = 0; 1737 int windowDetachedI = -1; 1738 int i = N; 1739 while (i > 0) { 1740 i--; 1741 w = windows.get(i); 1742 if ((w.mAttrs.type == TYPE_WALLPAPER)) { 1743 if (topCurW == null) { 1744 topCurW = w; 1745 topCurI = i; 1746 } 1747 continue; 1748 } 1749 topCurW = null; 1750 if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) { 1751 // If this window's app token is hidden and not animating, 1752 // it is of no interest to us. 1753 if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) { 1754 if (DEBUG_WALLPAPER) Slog.v(TAG, 1755 "Skipping hidden and not animating token: " + w); 1756 continue; 1757 } 1758 } 1759 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen=" 1760 + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState); 1761 1762 // If the app is executing an animation because the keyguard is going away, keep the 1763 // wallpaper during the animation so it doesn't flicker out. 1764 final boolean hasWallpaper = (w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 1765 || (w.mAppToken != null 1766 && w.mWinAnimator.mKeyguardGoingAwayAnimation); 1767 if (hasWallpaper && w.isOnScreen() 1768 && (mWallpaperTarget == w || w.isDrawFinishedLw())) { 1769 if (DEBUG_WALLPAPER) Slog.v(TAG, 1770 "Found wallpaper target: #" + i + "=" + w); 1771 foundW = w; 1772 foundI = i; 1773 if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) { 1774 // The current wallpaper target is animating, so we'll 1775 // look behind it for another possible target and figure 1776 // out what is going on below. 1777 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w 1778 + ": token animating, looking behind."); 1779 continue; 1780 } 1781 break; 1782 } else if (w == mAnimator.mWindowDetachedWallpaper) { 1783 windowDetachedI = i; 1784 } 1785 } 1786 1787 if (foundW == null && windowDetachedI >= 0) { 1788 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 1789 "Found animating detached wallpaper activity: #" + i + "=" + w); 1790 foundW = w; 1791 foundI = windowDetachedI; 1792 } 1793 1794 if (mWallpaperTarget != foundW 1795 && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) { 1796 if (DEBUG_WALLPAPER_LIGHT) { 1797 Slog.v(TAG, "New wallpaper target: " + foundW 1798 + " oldTarget: " + mWallpaperTarget); 1799 } 1800 1801 mLowerWallpaperTarget = null; 1802 mUpperWallpaperTarget = null; 1803 1804 WindowState oldW = mWallpaperTarget; 1805 mWallpaperTarget = foundW; 1806 targetChanged = true; 1807 1808 // Now what is happening... if the current and new targets are 1809 // animating, then we are in our super special mode! 1810 if (foundW != null && oldW != null) { 1811 boolean oldAnim = oldW.isAnimatingLw(); 1812 boolean foundAnim = foundW.isAnimatingLw(); 1813 if (DEBUG_WALLPAPER_LIGHT) { 1814 Slog.v(TAG, "New animation: " + foundAnim 1815 + " old animation: " + oldAnim); 1816 } 1817 if (foundAnim && oldAnim) { 1818 int oldI = windows.indexOf(oldW); 1819 if (DEBUG_WALLPAPER_LIGHT) { 1820 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI); 1821 } 1822 if (oldI >= 0) { 1823 if (DEBUG_WALLPAPER_LIGHT) { 1824 Slog.v(TAG, "Animating wallpapers: old#" + oldI 1825 + "=" + oldW + "; new#" + foundI 1826 + "=" + foundW); 1827 } 1828 1829 // Set the new target correctly. 1830 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) { 1831 if (DEBUG_WALLPAPER_LIGHT) { 1832 Slog.v(TAG, "Old wallpaper still the target."); 1833 } 1834 mWallpaperTarget = oldW; 1835 foundW = oldW; 1836 foundI = oldI; 1837 } 1838 // Now set the upper and lower wallpaper targets 1839 // correctly, and make sure that we are positioning 1840 // the wallpaper below the lower. 1841 else if (foundI > oldI) { 1842 // The new target is on top of the old one. 1843 if (DEBUG_WALLPAPER_LIGHT) { 1844 Slog.v(TAG, "Found target above old target."); 1845 } 1846 mUpperWallpaperTarget = foundW; 1847 mLowerWallpaperTarget = oldW; 1848 foundW = oldW; 1849 foundI = oldI; 1850 } else { 1851 // The new target is below the old one. 1852 if (DEBUG_WALLPAPER_LIGHT) { 1853 Slog.v(TAG, "Found target below old target."); 1854 } 1855 mUpperWallpaperTarget = oldW; 1856 mLowerWallpaperTarget = foundW; 1857 } 1858 } 1859 } 1860 } 1861 1862 } else if (mLowerWallpaperTarget != null) { 1863 // Is it time to stop animating? 1864 if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) { 1865 if (DEBUG_WALLPAPER_LIGHT) { 1866 Slog.v(TAG, "No longer animating wallpaper targets!"); 1867 } 1868 mLowerWallpaperTarget = null; 1869 mUpperWallpaperTarget = null; 1870 mWallpaperTarget = foundW; 1871 targetChanged = true; 1872 } 1873 } 1874 1875 boolean visible = foundW != null; 1876 if (visible) { 1877 // The window is visible to the compositor... but is it visible 1878 // to the user? That is what the wallpaper cares about. 1879 visible = isWallpaperVisible(foundW); 1880 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible); 1881 1882 // If the wallpaper target is animating, we may need to copy 1883 // its layer adjustment. Only do this if we are not transfering 1884 // between two wallpaper targets. 1885 mWallpaperAnimLayerAdjustment = 1886 (mLowerWallpaperTarget == null && foundW.mAppToken != null) 1887 ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0; 1888 1889 final int maxLayer = mPolicy.getMaxWallpaperLayer() 1890 * TYPE_LAYER_MULTIPLIER 1891 + TYPE_LAYER_OFFSET; 1892 1893 // Now w is the window we are supposed to be behind... but we 1894 // need to be sure to also be behind any of its attached windows, 1895 // AND any starting window associated with it, AND below the 1896 // maximum layer the policy allows for wallpapers. 1897 while (foundI > 0) { 1898 WindowState wb = windows.get(foundI-1); 1899 if (wb.mBaseLayer < maxLayer && 1900 wb.mAttachedWindow != foundW && 1901 (foundW.mAttachedWindow == null || 1902 wb.mAttachedWindow != foundW.mAttachedWindow) && 1903 (wb.mAttrs.type != TYPE_APPLICATION_STARTING || 1904 foundW.mToken == null || wb.mToken != foundW.mToken)) { 1905 // This window is not related to the previous one in any 1906 // interesting way, so stop here. 1907 break; 1908 } 1909 foundW = wb; 1910 foundI--; 1911 } 1912 } else { 1913 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target"); 1914 } 1915 1916 if (foundW == null && topCurW != null) { 1917 // There is no wallpaper target, so it goes at the bottom. 1918 // We will assume it is the same place as last time, if known. 1919 foundW = topCurW; 1920 foundI = topCurI+1; 1921 } else { 1922 // Okay i is the position immediately above the wallpaper. Look at 1923 // what is below it for later. 1924 foundW = foundI > 0 ? windows.get(foundI-1) : null; 1925 } 1926 1927 if (visible) { 1928 if (mWallpaperTarget.mWallpaperX >= 0) { 1929 mLastWallpaperX = mWallpaperTarget.mWallpaperX; 1930 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep; 1931 } 1932 if (mWallpaperTarget.mWallpaperY >= 0) { 1933 mLastWallpaperY = mWallpaperTarget.mWallpaperY; 1934 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep; 1935 } 1936 if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) { 1937 mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX; 1938 } 1939 if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 1940 mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY; 1941 } 1942 } 1943 1944 // Start stepping backwards from here, ensuring that our wallpaper windows 1945 // are correctly placed. 1946 int changed = 0; 1947 int curTokenIndex = mWallpaperTokens.size(); 1948 while (curTokenIndex > 0) { 1949 curTokenIndex--; 1950 WindowToken token = mWallpaperTokens.get(curTokenIndex); 1951 if (token.hidden == visible) { 1952 if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, 1953 "Wallpaper token " + token + " hidden=" + !visible); 1954 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED; 1955 token.hidden = !visible; 1956 // Need to do a layout to ensure the wallpaper now has the 1957 // correct size. 1958 getDefaultDisplayContentLocked().layoutNeeded = true; 1959 } 1960 1961 int curWallpaperIndex = token.windows.size(); 1962 while (curWallpaperIndex > 0) { 1963 curWallpaperIndex--; 1964 WindowState wallpaper = token.windows.get(curWallpaperIndex); 1965 1966 if (visible) { 1967 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 1968 } 1969 1970 // First, make sure the client has the current visibility 1971 // state. 1972 dispatchWallpaperVisibility(wallpaper, visible); 1973 1974 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; 1975 if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win " 1976 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 1977 1978 // First, if this window is at the current index, then all 1979 // is well. 1980 if (wallpaper == foundW) { 1981 foundI--; 1982 foundW = foundI > 0 1983 ? windows.get(foundI-1) : null; 1984 continue; 1985 } 1986 1987 // The window didn't match... the current wallpaper window, 1988 // wherever it is, is in the wrong place, so make sure it is 1989 // not in the list. 1990 int oldIndex = windows.indexOf(wallpaper); 1991 if (oldIndex >= 0) { 1992 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at " 1993 + oldIndex + ": " + wallpaper); 1994 windows.remove(oldIndex); 1995 mWindowsChanged = true; 1996 if (oldIndex < foundI) { 1997 foundI--; 1998 } 1999 } 2000 2001 // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost 2002 // layer. For keyguard over wallpaper put the wallpaper under the keyguard. 2003 int insertionIndex = 0; 2004 if (visible && foundW != null) { 2005 final int type = foundW.mAttrs.type; 2006 final int privateFlags = foundW.mAttrs.privateFlags; 2007 if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 2008 || type == TYPE_KEYGUARD_SCRIM) { 2009 insertionIndex = windows.indexOf(foundW); 2010 } 2011 } 2012 if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 2013 Slog.v(TAG, "Moving wallpaper " + wallpaper 2014 + " from " + oldIndex + " to " + insertionIndex); 2015 } 2016 2017 windows.add(insertionIndex, wallpaper); 2018 mWindowsChanged = true; 2019 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED; 2020 } 2021 } 2022 2023 /* 2024 final TaskStack targetStack = 2025 mWallpaperTarget == null ? null : mWallpaperTarget.getStack(); 2026 if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 && 2027 targetStack != null && !targetStack.isHomeStack()) { 2028 // If the wallpaper target is not on the home stack then make sure that all windows 2029 // from other non-home stacks are above the wallpaper. 2030 for (i = foundI - 1; i >= 0; --i) { 2031 WindowState win = windows.get(i); 2032 if (!win.isVisibleLw()) { 2033 continue; 2034 } 2035 final TaskStack winStack = win.getStack(); 2036 if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) { 2037 windows.remove(i); 2038 windows.add(foundI + 1, win); 2039 } 2040 } 2041 } 2042 */ 2043 2044 if (targetChanged && DEBUG_WALLPAPER_LIGHT) { 2045 Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget 2046 + " lower=" + mLowerWallpaperTarget + " upper=" 2047 + mUpperWallpaperTarget); 2048 } 2049 2050 return changed; 2051 } 2052 2053 void setWallpaperAnimLayerAdjustmentLocked(int adj) { 2054 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, 2055 "Setting wallpaper layer adj to " + adj); 2056 mWallpaperAnimLayerAdjustment = adj; 2057 int curTokenIndex = mWallpaperTokens.size(); 2058 while (curTokenIndex > 0) { 2059 curTokenIndex--; 2060 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2061 int curWallpaperIndex = token.windows.size(); 2062 while (curWallpaperIndex > 0) { 2063 curWallpaperIndex--; 2064 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2065 wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj; 2066 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win " 2067 + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); 2068 } 2069 } 2070 } 2071 2072 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh, 2073 boolean sync) { 2074 boolean changed = false; 2075 boolean rawChanged = false; 2076 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f; 2077 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f; 2078 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw; 2079 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0; 2080 if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) { 2081 offset += mLastWallpaperDisplayOffsetX; 2082 } 2083 changed = wallpaperWin.mXOffset != offset; 2084 if (changed) { 2085 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 2086 + wallpaperWin + " x: " + offset); 2087 wallpaperWin.mXOffset = offset; 2088 } 2089 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) { 2090 wallpaperWin.mWallpaperX = wpx; 2091 wallpaperWin.mWallpaperXStep = wpxs; 2092 rawChanged = true; 2093 } 2094 2095 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f; 2096 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f; 2097 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh; 2098 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0; 2099 if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 2100 offset += mLastWallpaperDisplayOffsetY; 2101 } 2102 if (wallpaperWin.mYOffset != offset) { 2103 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " 2104 + wallpaperWin + " y: " + offset); 2105 changed = true; 2106 wallpaperWin.mYOffset = offset; 2107 } 2108 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) { 2109 wallpaperWin.mWallpaperY = wpy; 2110 wallpaperWin.mWallpaperYStep = wpys; 2111 rawChanged = true; 2112 } 2113 2114 if (rawChanged && (wallpaperWin.mAttrs.privateFlags & 2115 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) { 2116 try { 2117 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset " 2118 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX 2119 + " y=" + wallpaperWin.mWallpaperY); 2120 if (sync) { 2121 mWaitingOnWallpaper = wallpaperWin; 2122 } 2123 wallpaperWin.mClient.dispatchWallpaperOffsets( 2124 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, 2125 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync); 2126 if (sync) { 2127 if (mWaitingOnWallpaper != null) { 2128 long start = SystemClock.uptimeMillis(); 2129 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) 2130 < start) { 2131 try { 2132 if (DEBUG_WALLPAPER) Slog.v(TAG, 2133 "Waiting for offset complete..."); 2134 mWindowMap.wait(WALLPAPER_TIMEOUT); 2135 } catch (InterruptedException e) { 2136 } 2137 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!"); 2138 if ((start+WALLPAPER_TIMEOUT) 2139 < SystemClock.uptimeMillis()) { 2140 Slog.i(TAG, "Timeout waiting for wallpaper to offset: " 2141 + wallpaperWin); 2142 mLastWallpaperTimeoutTime = start; 2143 } 2144 } 2145 mWaitingOnWallpaper = null; 2146 } 2147 } 2148 } catch (RemoteException e) { 2149 } 2150 } 2151 2152 return changed; 2153 } 2154 2155 void wallpaperOffsetsComplete(IBinder window) { 2156 synchronized (mWindowMap) { 2157 if (mWaitingOnWallpaper != null && 2158 mWaitingOnWallpaper.mClient.asBinder() == window) { 2159 mWaitingOnWallpaper = null; 2160 mWindowMap.notifyAll(); 2161 } 2162 } 2163 } 2164 2165 void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) { 2166 final DisplayContent displayContent = changingTarget.getDisplayContent(); 2167 if (displayContent == null) { 2168 return; 2169 } 2170 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2171 final int dw = displayInfo.logicalWidth; 2172 final int dh = displayInfo.logicalHeight; 2173 2174 WindowState target = mWallpaperTarget; 2175 if (target != null) { 2176 if (target.mWallpaperX >= 0) { 2177 mLastWallpaperX = target.mWallpaperX; 2178 } else if (changingTarget.mWallpaperX >= 0) { 2179 mLastWallpaperX = changingTarget.mWallpaperX; 2180 } 2181 if (target.mWallpaperY >= 0) { 2182 mLastWallpaperY = target.mWallpaperY; 2183 } else if (changingTarget.mWallpaperY >= 0) { 2184 mLastWallpaperY = changingTarget.mWallpaperY; 2185 } 2186 if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) { 2187 mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX; 2188 } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) { 2189 mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX; 2190 } 2191 if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 2192 mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY; 2193 } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) { 2194 mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY; 2195 } 2196 } 2197 2198 int curTokenIndex = mWallpaperTokens.size(); 2199 while (curTokenIndex > 0) { 2200 curTokenIndex--; 2201 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2202 int curWallpaperIndex = token.windows.size(); 2203 while (curWallpaperIndex > 0) { 2204 curWallpaperIndex--; 2205 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2206 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) { 2207 WindowStateAnimator winAnimator = wallpaper.mWinAnimator; 2208 winAnimator.computeShownFrameLocked(); 2209 // No need to lay out the windows - we can just set the wallpaper position 2210 // directly. 2211 winAnimator.setWallpaperOffset(wallpaper.mShownFrame); 2212 // We only want to be synchronous with one wallpaper. 2213 sync = false; 2214 } 2215 } 2216 } 2217 } 2218 2219 /** 2220 * Check wallpaper for visiblity change and notify window if so. 2221 * @param wallpaper The wallpaper to test and notify. 2222 * @param visible Current visibility. 2223 */ 2224 void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) { 2225 if (wallpaper.mWallpaperVisible != visible) { 2226 wallpaper.mWallpaperVisible = visible; 2227 try { 2228 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 2229 "Updating vis of wallpaper " + wallpaper 2230 + ": " + visible + " from:\n" + Debug.getCallers(4, " ")); 2231 wallpaper.mClient.dispatchAppVisibility(visible); 2232 } catch (RemoteException e) { 2233 } 2234 } 2235 } 2236 2237 void updateWallpaperVisibilityLocked() { 2238 final boolean visible = isWallpaperVisible(mWallpaperTarget); 2239 final DisplayContent displayContent = mWallpaperTarget.getDisplayContent(); 2240 if (displayContent == null) { 2241 return; 2242 } 2243 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2244 final int dw = displayInfo.logicalWidth; 2245 final int dh = displayInfo.logicalHeight; 2246 2247 int curTokenIndex = mWallpaperTokens.size(); 2248 while (curTokenIndex > 0) { 2249 curTokenIndex--; 2250 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2251 if (token.hidden == visible) { 2252 token.hidden = !visible; 2253 // Need to do a layout to ensure the wallpaper now has the 2254 // correct size. 2255 getDefaultDisplayContentLocked().layoutNeeded = true; 2256 } 2257 2258 int curWallpaperIndex = token.windows.size(); 2259 while (curWallpaperIndex > 0) { 2260 curWallpaperIndex--; 2261 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2262 if (visible) { 2263 updateWallpaperOffsetLocked(wallpaper, dw, dh, false); 2264 } 2265 2266 dispatchWallpaperVisibility(wallpaper, visible); 2267 } 2268 } 2269 } 2270 2271 public int addWindow(Session session, IWindow client, int seq, 2272 WindowManager.LayoutParams attrs, int viewVisibility, int displayId, 2273 Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel) { 2274 int[] appOp = new int[1]; 2275 int res = mPolicy.checkAddPermission(attrs, appOp); 2276 if (res != WindowManagerGlobal.ADD_OKAY) { 2277 return res; 2278 } 2279 2280 boolean reportNewConfig = false; 2281 WindowState attachedWindow = null; 2282 WindowState win = null; 2283 long origId; 2284 final int type = attrs.type; 2285 2286 synchronized(mWindowMap) { 2287 if (!mDisplayReady) { 2288 throw new IllegalStateException("Display has not been initialialized"); 2289 } 2290 2291 final DisplayContent displayContent = getDisplayContentLocked(displayId); 2292 if (displayContent == null) { 2293 Slog.w(TAG, "Attempted to add window to a display that does not exist: " 2294 + displayId + ". Aborting."); 2295 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2296 } 2297 if (!displayContent.hasAccess(session.mUid)) { 2298 Slog.w(TAG, "Attempted to add window to a display for which the application " 2299 + "does not have access: " + displayId + ". Aborting."); 2300 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2301 } 2302 2303 if (mWindowMap.containsKey(client.asBinder())) { 2304 Slog.w(TAG, "Window " + client + " is already added"); 2305 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 2306 } 2307 2308 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 2309 attachedWindow = windowForClientLocked(null, attrs.token, false); 2310 if (attachedWindow == null) { 2311 Slog.w(TAG, "Attempted to add window with token that is not a window: " 2312 + attrs.token + ". Aborting."); 2313 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2314 } 2315 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW 2316 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { 2317 Slog.w(TAG, "Attempted to add window with token that is a sub-window: " 2318 + attrs.token + ". Aborting."); 2319 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2320 } 2321 } 2322 2323 if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) { 2324 Slog.w(TAG, "Attempted to add private presentation window to a non-private display. Aborting."); 2325 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2326 } 2327 2328 boolean addToken = false; 2329 WindowToken token = mTokenMap.get(attrs.token); 2330 if (token == null) { 2331 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2332 Slog.w(TAG, "Attempted to add application window with unknown token " 2333 + attrs.token + ". Aborting."); 2334 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2335 } 2336 if (type == TYPE_INPUT_METHOD) { 2337 Slog.w(TAG, "Attempted to add input method window with unknown token " 2338 + attrs.token + ". Aborting."); 2339 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2340 } 2341 if (type == TYPE_VOICE_INTERACTION) { 2342 Slog.w(TAG, "Attempted to add voice interaction window with unknown token " 2343 + attrs.token + ". Aborting."); 2344 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2345 } 2346 if (type == TYPE_WALLPAPER) { 2347 Slog.w(TAG, "Attempted to add wallpaper window with unknown token " 2348 + attrs.token + ". Aborting."); 2349 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2350 } 2351 if (type == TYPE_DREAM) { 2352 Slog.w(TAG, "Attempted to add Dream window with unknown token " 2353 + attrs.token + ". Aborting."); 2354 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2355 } 2356 if (type == TYPE_ACCESSIBILITY_OVERLAY) { 2357 Slog.w(TAG, "Attempted to add Accessibility overlay window with unknown token " 2358 + attrs.token + ". Aborting."); 2359 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2360 } 2361 token = new WindowToken(this, attrs.token, -1, false); 2362 addToken = true; 2363 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2364 AppWindowToken atoken = token.appWindowToken; 2365 if (atoken == null) { 2366 Slog.w(TAG, "Attempted to add window with non-application token " 2367 + token + ". Aborting."); 2368 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 2369 } else if (atoken.removed) { 2370 Slog.w(TAG, "Attempted to add window with exiting application token " 2371 + token + ". Aborting."); 2372 return WindowManagerGlobal.ADD_APP_EXITING; 2373 } 2374 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { 2375 // No need for this guy! 2376 if (localLOGV) Slog.v( 2377 TAG, "**** NO NEED TO START: " + attrs.getTitle()); 2378 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; 2379 } 2380 } else if (type == TYPE_INPUT_METHOD) { 2381 if (token.windowType != TYPE_INPUT_METHOD) { 2382 Slog.w(TAG, "Attempted to add input method window with bad token " 2383 + attrs.token + ". Aborting."); 2384 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2385 } 2386 } else if (type == TYPE_VOICE_INTERACTION) { 2387 if (token.windowType != TYPE_VOICE_INTERACTION) { 2388 Slog.w(TAG, "Attempted to add voice interaction window with bad token " 2389 + attrs.token + ". Aborting."); 2390 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2391 } 2392 } else if (type == TYPE_WALLPAPER) { 2393 if (token.windowType != TYPE_WALLPAPER) { 2394 Slog.w(TAG, "Attempted to add wallpaper window with bad token " 2395 + attrs.token + ". Aborting."); 2396 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2397 } 2398 } else if (type == TYPE_DREAM) { 2399 if (token.windowType != TYPE_DREAM) { 2400 Slog.w(TAG, "Attempted to add Dream window with bad token " 2401 + attrs.token + ". Aborting."); 2402 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2403 } 2404 } else if (type == TYPE_ACCESSIBILITY_OVERLAY) { 2405 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) { 2406 Slog.w(TAG, "Attempted to add Accessibility overlay window with bad token " 2407 + attrs.token + ". Aborting."); 2408 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2409 } 2410 } else if (token.appWindowToken != null) { 2411 Slog.w(TAG, "Non-null appWindowToken for system window of type=" + type); 2412 // It is not valid to use an app token with other system types; we will 2413 // instead make a new token for it (as if null had been passed in for the token). 2414 attrs.token = null; 2415 token = new WindowToken(this, null, -1, false); 2416 addToken = true; 2417 } 2418 2419 win = new WindowState(this, session, client, token, 2420 attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent); 2421 if (win.mDeathRecipient == null) { 2422 // Client has apparently died, so there is no reason to 2423 // continue. 2424 Slog.w(TAG, "Adding window client " + client.asBinder() 2425 + " that is dead, aborting."); 2426 return WindowManagerGlobal.ADD_APP_EXITING; 2427 } 2428 2429 if (win.getDisplayContent() == null) { 2430 Slog.w(TAG, "Adding window to Display that has been removed."); 2431 return WindowManagerGlobal.ADD_INVALID_DISPLAY; 2432 } 2433 2434 mPolicy.adjustWindowParamsLw(win.mAttrs); 2435 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 2436 2437 res = mPolicy.prepareAddWindowLw(win, attrs); 2438 if (res != WindowManagerGlobal.ADD_OKAY) { 2439 return res; 2440 } 2441 2442 if (outInputChannel != null && (attrs.inputFeatures 2443 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { 2444 String name = win.makeInputChannelName(); 2445 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); 2446 win.setInputChannel(inputChannels[0]); 2447 inputChannels[1].transferTo(outInputChannel); 2448 2449 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); 2450 } 2451 2452 // From now on, no exceptions or errors allowed! 2453 2454 res = WindowManagerGlobal.ADD_OKAY; 2455 2456 origId = Binder.clearCallingIdentity(); 2457 2458 if (addToken) { 2459 mTokenMap.put(attrs.token, token); 2460 } 2461 win.attach(); 2462 mWindowMap.put(client.asBinder(), win); 2463 if (win.mAppOp != AppOpsManager.OP_NONE) { 2464 if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage()) 2465 != AppOpsManager.MODE_ALLOWED) { 2466 win.setAppOpVisibilityLw(false); 2467 } 2468 } 2469 2470 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { 2471 token.appWindowToken.startingWindow = win; 2472 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken 2473 + " startingWindow=" + win); 2474 } 2475 2476 boolean imMayMove = true; 2477 2478 if (type == TYPE_INPUT_METHOD) { 2479 win.mGivenInsetsPending = true; 2480 mInputMethodWindow = win; 2481 addInputMethodWindowToListLocked(win); 2482 imMayMove = false; 2483 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 2484 mInputMethodDialogs.add(win); 2485 addWindowToListInOrderLocked(win, true); 2486 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); 2487 imMayMove = false; 2488 } else { 2489 addWindowToListInOrderLocked(win, true); 2490 if (type == TYPE_WALLPAPER) { 2491 mLastWallpaperTimeoutTime = 0; 2492 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2493 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2494 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2495 } else if (mWallpaperTarget != null 2496 && mWallpaperTarget.mLayer >= win.mBaseLayer) { 2497 // If there is currently a wallpaper being shown, and 2498 // the base layer of the new window is below the current 2499 // layer of the target window, then adjust the wallpaper. 2500 // This is to avoid a new window being placed between the 2501 // wallpaper and its target. 2502 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2503 } 2504 } 2505 2506 final WindowStateAnimator winAnimator = win.mWinAnimator; 2507 winAnimator.mEnterAnimationPending = true; 2508 winAnimator.mEnteringAnimation = true; 2509 2510 if (displayContent.isDefaultDisplay) { 2511 mPolicy.getInsetHintLw(win.mAttrs, outContentInsets, outStableInsets); 2512 } else { 2513 outContentInsets.setEmpty(); 2514 outStableInsets.setEmpty(); 2515 } 2516 2517 if (mInTouchMode) { 2518 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2519 } 2520 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2521 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2522 } 2523 2524 mInputMonitor.setUpdateInputWindowsNeededLw(); 2525 2526 boolean focusChanged = false; 2527 if (win.canReceiveKeys()) { 2528 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2529 false /*updateInputWindows*/); 2530 if (focusChanged) { 2531 imMayMove = false; 2532 } 2533 } 2534 2535 if (imMayMove) { 2536 moveInputMethodWindowsIfNeededLocked(false); 2537 } 2538 2539 assignLayersLocked(displayContent.getWindowList()); 2540 // Don't do layout here, the window must call 2541 // relayout to be displayed, so we'll do it there. 2542 2543 if (focusChanged) { 2544 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/); 2545 } 2546 mInputMonitor.updateInputWindowsLw(false /*force*/); 2547 2548 if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG, "addWindow: New client " 2549 + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5)); 2550 2551 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2552 reportNewConfig = true; 2553 } 2554 } 2555 2556 if (reportNewConfig) { 2557 sendNewConfiguration(); 2558 } 2559 2560 Binder.restoreCallingIdentity(origId); 2561 2562 return res; 2563 } 2564 2565 /** 2566 * Returns whether screen capture is disabled for all windows of a specific user. 2567 */ 2568 boolean isScreenCaptureDisabledLocked(int userId) { 2569 Boolean disabled = mScreenCaptureDisabled.get(userId); 2570 if (disabled == null) { 2571 return false; 2572 } 2573 return disabled; 2574 } 2575 2576 /** 2577 * Set mScreenCaptureDisabled for specific user 2578 */ 2579 @Override 2580 public void setScreenCaptureDisabled(int userId, boolean disabled) { 2581 int callingUid = Binder.getCallingUid(); 2582 if (callingUid != Process.SYSTEM_UID) { 2583 throw new SecurityException("Only system can call setScreenCaptureDisabled."); 2584 } 2585 2586 synchronized(mWindowMap) { 2587 mScreenCaptureDisabled.put(userId, disabled); 2588 } 2589 } 2590 2591 public void removeWindow(Session session, IWindow client) { 2592 synchronized(mWindowMap) { 2593 WindowState win = windowForClientLocked(session, client, false); 2594 if (win == null) { 2595 return; 2596 } 2597 removeWindowLocked(session, win); 2598 } 2599 } 2600 2601 public void removeWindowLocked(Session session, WindowState win) { 2602 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2603 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win); 2604 } 2605 2606 if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v( 2607 TAG, "Remove " + win + " client=" 2608 + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) 2609 + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers=" 2610 + Debug.getCallers(4)); 2611 2612 final long origId = Binder.clearCallingIdentity(); 2613 2614 win.disposeInputChannel(); 2615 2616 if (DEBUG_APP_TRANSITIONS) Slog.v( 2617 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl 2618 + " mExiting=" + win.mExiting 2619 + " isAnimating=" + win.mWinAnimator.isAnimating() 2620 + " app-animation=" 2621 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2622 + " inPendingTransaction=" 2623 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2624 + " mDisplayFrozen=" + mDisplayFrozen); 2625 // Visibility of the removed window. Will be used later to update orientation later on. 2626 boolean wasVisible = false; 2627 // First, see if we need to run an animation. If we do, we have 2628 // to hold off on removing the window until the animation is done. 2629 // If the display is frozen, just remove immediately, since the 2630 // animation wouldn't be seen. 2631 if (win.mHasSurface && okToDisplay()) { 2632 // If we are not currently running the exit animation, we 2633 // need to see about starting one. 2634 wasVisible = win.isWinVisibleLw(); 2635 if (wasVisible) { 2636 2637 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2638 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2639 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2640 } 2641 // Try starting an animation. 2642 if (win.mWinAnimator.applyAnimationLocked(transit, false)) { 2643 win.mExiting = true; 2644 } 2645 //TODO (multidisplay): Magnification is supported only for the default display. 2646 if (mAccessibilityController != null 2647 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 2648 mAccessibilityController.onWindowTransitionLocked(win, transit); 2649 } 2650 } 2651 if (win.mExiting || win.mWinAnimator.isAnimating()) { 2652 // The exit animation is running... wait for it! 2653 //Slog.i(TAG, "*** Running exit animation..."); 2654 win.mExiting = true; 2655 win.mRemoveOnExit = true; 2656 final DisplayContent displayContent = win.getDisplayContent(); 2657 if (displayContent != null) { 2658 displayContent.layoutNeeded = true; 2659 } 2660 final boolean focusChanged = updateFocusedWindowLocked( 2661 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 2662 performLayoutAndPlaceSurfacesLocked(); 2663 if (win.mAppToken != null) { 2664 win.mAppToken.updateReportedVisibilityLocked(); 2665 } 2666 if (focusChanged) { 2667 mInputMonitor.updateInputWindowsLw(false /*force*/); 2668 } 2669 //dump(); 2670 Binder.restoreCallingIdentity(origId); 2671 return; 2672 } 2673 } 2674 2675 removeWindowInnerLocked(session, win); 2676 // Removing a visible window will effect the computed orientation 2677 // So just update orientation if needed. 2678 if (wasVisible && updateOrientationFromAppTokensLocked(false)) { 2679 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2680 } 2681 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2682 Binder.restoreCallingIdentity(origId); 2683 } 2684 2685 void removeWindowInnerLocked(Session session, WindowState win) { 2686 if (win.mRemoved) { 2687 // Nothing to do. 2688 return; 2689 } 2690 2691 for (int i=win.mChildWindows.size()-1; i>=0; i--) { 2692 WindowState cwin = win.mChildWindows.get(i); 2693 Slog.w(TAG, "Force-removing child win " + cwin + " from container " 2694 + win); 2695 removeWindowInnerLocked(cwin.mSession, cwin); 2696 } 2697 2698 win.mRemoved = true; 2699 2700 if (mInputMethodTarget == win) { 2701 moveInputMethodWindowsIfNeededLocked(false); 2702 } 2703 2704 if (false) { 2705 RuntimeException e = new RuntimeException("here"); 2706 e.fillInStackTrace(); 2707 Slog.w(TAG, "Removing window " + win, e); 2708 } 2709 2710 mPolicy.removeWindowLw(win); 2711 win.removeLocked(); 2712 2713 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); 2714 mWindowMap.remove(win.mClient.asBinder()); 2715 if (win.mAppOp != AppOpsManager.OP_NONE) { 2716 mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage()); 2717 } 2718 2719 mPendingRemove.remove(win); 2720 mResizingWindows.remove(win); 2721 mWindowsChanged = true; 2722 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win); 2723 2724 if (mInputMethodWindow == win) { 2725 mInputMethodWindow = null; 2726 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { 2727 mInputMethodDialogs.remove(win); 2728 } 2729 2730 final WindowToken token = win.mToken; 2731 final AppWindowToken atoken = win.mAppToken; 2732 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token); 2733 token.windows.remove(win); 2734 if (atoken != null) { 2735 atoken.allAppWindows.remove(win); 2736 } 2737 if (localLOGV) Slog.v( 2738 TAG, "**** Removing window " + win + ": count=" 2739 + token.windows.size()); 2740 if (token.windows.size() == 0) { 2741 if (!token.explicit) { 2742 mTokenMap.remove(token.token); 2743 } else if (atoken != null) { 2744 atoken.firstWindowDrawn = false; 2745 } 2746 } 2747 2748 if (atoken != null) { 2749 if (atoken.startingWindow == win) { 2750 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Notify removed startingWindow " + win); 2751 scheduleRemoveStartingWindowLocked(atoken); 2752 } else 2753 if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) { 2754 // If this is the last window and we had requested a starting 2755 // transition window, well there is no point now. 2756 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow"); 2757 atoken.startingData = null; 2758 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) { 2759 // If this is the last window except for a starting transition 2760 // window, we need to get rid of the starting transition. 2761 scheduleRemoveStartingWindowLocked(atoken); 2762 } 2763 } 2764 2765 if (win.mAttrs.type == TYPE_WALLPAPER) { 2766 mLastWallpaperTimeoutTime = 0; 2767 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2768 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2769 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2770 getDefaultDisplayContentLocked().pendingLayoutChanges |= 2771 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 2772 } 2773 2774 final WindowList windows = win.getWindowList(); 2775 if (windows != null) { 2776 windows.remove(win); 2777 if (!mInLayout) { 2778 assignLayersLocked(windows); 2779 final DisplayContent displayContent = win.getDisplayContent(); 2780 if (displayContent != null) { 2781 displayContent.layoutNeeded = true; 2782 } 2783 performLayoutAndPlaceSurfacesLocked(); 2784 if (win.mAppToken != null) { 2785 win.mAppToken.updateReportedVisibilityLocked(); 2786 } 2787 } 2788 } 2789 2790 mInputMonitor.updateInputWindowsLw(true /*force*/); 2791 } 2792 2793 public void updateAppOpsState() { 2794 synchronized(mWindowMap) { 2795 final int numDisplays = mDisplayContents.size(); 2796 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 2797 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 2798 final int numWindows = windows.size(); 2799 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 2800 final WindowState win = windows.get(winNdx); 2801 if (win.mAppOp != AppOpsManager.OP_NONE) { 2802 final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(), 2803 win.getOwningPackage()); 2804 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED); 2805 } 2806 } 2807 } 2808 } 2809 } 2810 2811 static void logSurface(WindowState w, String msg, RuntimeException where) { 2812 String str = " SURFACE " + msg + ": " + w; 2813 if (where != null) { 2814 Slog.i(TAG, str, where); 2815 } else { 2816 Slog.i(TAG, str); 2817 } 2818 } 2819 2820 static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) { 2821 String str = " SURFACE " + s + ": " + msg + " / " + title; 2822 if (where != null) { 2823 Slog.i(TAG, str, where); 2824 } else { 2825 Slog.i(TAG, str); 2826 } 2827 } 2828 2829 void setTransparentRegionWindow(Session session, IWindow client, Region region) { 2830 long origId = Binder.clearCallingIdentity(); 2831 try { 2832 synchronized (mWindowMap) { 2833 WindowState w = windowForClientLocked(session, client, false); 2834 if ((w != null) && w.mHasSurface) { 2835 w.mWinAnimator.setTransparentRegionHintLocked(region); 2836 } 2837 } 2838 } finally { 2839 Binder.restoreCallingIdentity(origId); 2840 } 2841 } 2842 2843 void setInsetsWindow(Session session, IWindow client, 2844 int touchableInsets, Rect contentInsets, 2845 Rect visibleInsets, Region touchableRegion) { 2846 long origId = Binder.clearCallingIdentity(); 2847 try { 2848 synchronized (mWindowMap) { 2849 WindowState w = windowForClientLocked(session, client, false); 2850 if (w != null) { 2851 w.mGivenInsetsPending = false; 2852 w.mGivenContentInsets.set(contentInsets); 2853 w.mGivenVisibleInsets.set(visibleInsets); 2854 w.mGivenTouchableRegion.set(touchableRegion); 2855 w.mTouchableInsets = touchableInsets; 2856 if (w.mGlobalScale != 1) { 2857 w.mGivenContentInsets.scale(w.mGlobalScale); 2858 w.mGivenVisibleInsets.scale(w.mGlobalScale); 2859 w.mGivenTouchableRegion.scale(w.mGlobalScale); 2860 } 2861 final DisplayContent displayContent = w.getDisplayContent(); 2862 if (displayContent != null) { 2863 displayContent.layoutNeeded = true; 2864 } 2865 performLayoutAndPlaceSurfacesLocked(); 2866 } 2867 } 2868 } finally { 2869 Binder.restoreCallingIdentity(origId); 2870 } 2871 } 2872 2873 public void getWindowDisplayFrame(Session session, IWindow client, 2874 Rect outDisplayFrame) { 2875 synchronized(mWindowMap) { 2876 WindowState win = windowForClientLocked(session, client, false); 2877 if (win == null) { 2878 outDisplayFrame.setEmpty(); 2879 return; 2880 } 2881 outDisplayFrame.set(win.mDisplayFrame); 2882 } 2883 } 2884 2885 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y, 2886 float xStep, float yStep) { 2887 if (window.mWallpaperX != x || window.mWallpaperY != y) { 2888 window.mWallpaperX = x; 2889 window.mWallpaperY = y; 2890 window.mWallpaperXStep = xStep; 2891 window.mWallpaperYStep = yStep; 2892 updateWallpaperOffsetLocked(window, true); 2893 } 2894 } 2895 2896 void wallpaperCommandComplete(IBinder window, Bundle result) { 2897 synchronized (mWindowMap) { 2898 if (mWaitingOnWallpaper != null && 2899 mWaitingOnWallpaper.mClient.asBinder() == window) { 2900 mWaitingOnWallpaper = null; 2901 mWindowMap.notifyAll(); 2902 } 2903 } 2904 } 2905 2906 public void setWindowWallpaperDisplayOffsetLocked(WindowState window, int x, int y) { 2907 if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) { 2908 window.mWallpaperDisplayOffsetX = x; 2909 window.mWallpaperDisplayOffsetY = y; 2910 updateWallpaperOffsetLocked(window, true); 2911 } 2912 } 2913 2914 public Bundle sendWindowWallpaperCommandLocked(WindowState window, 2915 String action, int x, int y, int z, Bundle extras, boolean sync) { 2916 if (window == mWallpaperTarget || window == mLowerWallpaperTarget 2917 || window == mUpperWallpaperTarget) { 2918 boolean doWait = sync; 2919 int curTokenIndex = mWallpaperTokens.size(); 2920 while (curTokenIndex > 0) { 2921 curTokenIndex--; 2922 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2923 int curWallpaperIndex = token.windows.size(); 2924 while (curWallpaperIndex > 0) { 2925 curWallpaperIndex--; 2926 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2927 try { 2928 wallpaper.mClient.dispatchWallpaperCommand(action, 2929 x, y, z, extras, sync); 2930 // We only want to be synchronous with one wallpaper. 2931 sync = false; 2932 } catch (RemoteException e) { 2933 } 2934 } 2935 } 2936 2937 if (doWait) { 2938 // XXX Need to wait for result. 2939 } 2940 } 2941 2942 return null; 2943 } 2944 2945 public void setUniverseTransformLocked(WindowState window, float alpha, 2946 float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) { 2947 Transformation transform = window.mWinAnimator.mUniverseTransform; 2948 transform.setAlpha(alpha); 2949 Matrix matrix = transform.getMatrix(); 2950 matrix.getValues(mTmpFloats); 2951 mTmpFloats[Matrix.MTRANS_X] = offx; 2952 mTmpFloats[Matrix.MTRANS_Y] = offy; 2953 mTmpFloats[Matrix.MSCALE_X] = dsdx; 2954 mTmpFloats[Matrix.MSKEW_Y] = dtdx; 2955 mTmpFloats[Matrix.MSKEW_X] = dsdy; 2956 mTmpFloats[Matrix.MSCALE_Y] = dtdy; 2957 matrix.setValues(mTmpFloats); 2958 final DisplayContent displayContent = window.getDisplayContent(); 2959 if (displayContent == null) { 2960 return; 2961 } 2962 2963 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2964 final RectF dispRect = new RectF(0, 0, 2965 displayInfo.logicalWidth, displayInfo.logicalHeight); 2966 matrix.mapRect(dispRect); 2967 window.mGivenTouchableRegion.set(0, 0, 2968 displayInfo.logicalWidth, displayInfo.logicalHeight); 2969 window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, 2970 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); 2971 window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; 2972 displayContent.layoutNeeded = true; 2973 performLayoutAndPlaceSurfacesLocked(); 2974 } 2975 2976 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 2977 synchronized (mWindowMap) { 2978 if (mAccessibilityController != null) { 2979 WindowState window = mWindowMap.get(token); 2980 //TODO (multidisplay): Magnification is supported only for the default display. 2981 if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 2982 mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle); 2983 } 2984 } 2985 } 2986 } 2987 2988 public IWindowId getWindowId(IBinder token) { 2989 synchronized (mWindowMap) { 2990 WindowState window = mWindowMap.get(token); 2991 return window != null ? window.mWindowId : null; 2992 } 2993 } 2994 2995 public int relayoutWindow(Session session, IWindow client, int seq, 2996 WindowManager.LayoutParams attrs, int requestedWidth, 2997 int requestedHeight, int viewVisibility, int flags, 2998 Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, 2999 Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig, 3000 Surface outSurface) { 3001 boolean toBeDisplayed = false; 3002 boolean inTouchMode; 3003 boolean configChanged; 3004 boolean surfaceChanged = false; 3005 boolean animating; 3006 boolean hasStatusBarPermission = 3007 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 3008 == PackageManager.PERMISSION_GRANTED; 3009 3010 long origId = Binder.clearCallingIdentity(); 3011 3012 synchronized(mWindowMap) { 3013 WindowState win = windowForClientLocked(session, client, false); 3014 if (win == null) { 3015 return 0; 3016 } 3017 WindowStateAnimator winAnimator = win.mWinAnimator; 3018 if (viewVisibility != View.GONE && (win.mRequestedWidth != requestedWidth 3019 || win.mRequestedHeight != requestedHeight)) { 3020 win.mLayoutNeeded = true; 3021 win.mRequestedWidth = requestedWidth; 3022 win.mRequestedHeight = requestedHeight; 3023 } 3024 3025 if (attrs != null) { 3026 mPolicy.adjustWindowParamsLw(attrs); 3027 } 3028 3029 // if they don't have the permission, mask out the status bar bits 3030 int systemUiVisibility = 0; 3031 if (attrs != null) { 3032 systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility); 3033 if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) { 3034 if (!hasStatusBarPermission) { 3035 systemUiVisibility &= ~StatusBarManager.DISABLE_MASK; 3036 } 3037 } 3038 } 3039 3040 if (attrs != null && seq == win.mSeq) { 3041 win.mSystemUiVisibility = systemUiVisibility; 3042 } 3043 3044 winAnimator.mSurfaceDestroyDeferred = 3045 (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0; 3046 3047 int attrChanges = 0; 3048 int flagChanges = 0; 3049 if (attrs != null) { 3050 if (win.mAttrs.type != attrs.type) { 3051 throw new IllegalArgumentException( 3052 "Window type can not be changed after the window is added."); 3053 } 3054 flagChanges = win.mAttrs.flags ^= attrs.flags; 3055 attrChanges = win.mAttrs.copyFrom(attrs); 3056 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED 3057 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) { 3058 win.mLayoutNeeded = true; 3059 } 3060 } 3061 3062 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility 3063 + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs); 3064 3065 win.mEnforceSizeCompat = 3066 (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0; 3067 3068 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { 3069 winAnimator.mAlpha = attrs.alpha; 3070 } 3071 3072 final boolean scaledWindow = 3073 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0); 3074 3075 if (scaledWindow) { 3076 // requested{Width|Height} Surface's physical size 3077 // attrs.{width|height} Size on screen 3078 win.mHScale = (attrs.width != requestedWidth) ? 3079 (attrs.width / (float)requestedWidth) : 1.0f; 3080 win.mVScale = (attrs.height != requestedHeight) ? 3081 (attrs.height / (float)requestedHeight) : 1.0f; 3082 } else { 3083 win.mHScale = win.mVScale = 1; 3084 } 3085 3086 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0; 3087 3088 final boolean isDefaultDisplay = win.isDefaultDisplay(); 3089 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility 3090 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0) 3091 || (!win.mRelayoutCalled)); 3092 3093 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility 3094 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0; 3095 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0; 3096 3097 win.mRelayoutCalled = true; 3098 final int oldVisibility = win.mViewVisibility; 3099 win.mViewVisibility = viewVisibility; 3100 if (DEBUG_SCREEN_ON) { 3101 RuntimeException stack = new RuntimeException(); 3102 stack.fillInStackTrace(); 3103 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility 3104 + " newVis=" + viewVisibility, stack); 3105 } 3106 if (viewVisibility == View.VISIBLE && 3107 (win.mAppToken == null || !win.mAppToken.clientHidden)) { 3108 toBeDisplayed = !win.isVisibleLw(); 3109 if (win.mExiting) { 3110 winAnimator.cancelExitAnimationForNextAnimationLocked(); 3111 win.mExiting = false; 3112 } 3113 if (win.mDestroying) { 3114 win.mDestroying = false; 3115 mDestroySurface.remove(win); 3116 } 3117 if (oldVisibility == View.GONE) { 3118 winAnimator.mEnterAnimationPending = true; 3119 } 3120 winAnimator.mEnteringAnimation = true; 3121 if (toBeDisplayed) { 3122 if (win.isDrawnLw() && okToDisplay()) { 3123 winAnimator.applyEnterAnimationLocked(); 3124 } 3125 if ((win.mAttrs.flags 3126 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) { 3127 if (DEBUG_VISIBILITY) Slog.v(TAG, 3128 "Relayout window turning screen on: " + win); 3129 win.mTurnOnScreen = true; 3130 } 3131 if (win.isConfigChanged()) { 3132 if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win 3133 + " visible with new config: " + mCurConfiguration); 3134 outConfig.setTo(mCurConfiguration); 3135 } 3136 } 3137 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) { 3138 // To change the format, we need to re-build the surface. 3139 winAnimator.destroySurfaceLocked(); 3140 toBeDisplayed = true; 3141 surfaceChanged = true; 3142 } 3143 try { 3144 if (!win.mHasSurface) { 3145 surfaceChanged = true; 3146 } 3147 SurfaceControl surfaceControl = winAnimator.createSurfaceLocked(); 3148 if (surfaceControl != null) { 3149 outSurface.copyFrom(surfaceControl); 3150 if (SHOW_TRANSACTIONS) Slog.i(TAG, 3151 " OUT SURFACE " + outSurface + ": copied"); 3152 } else { 3153 // For some reason there isn't a surface. Clear the 3154 // caller's object so they see the same state. 3155 outSurface.release(); 3156 } 3157 } catch (Exception e) { 3158 mInputMonitor.updateInputWindowsLw(true /*force*/); 3159 3160 Slog.w(TAG, "Exception thrown when creating surface for client " 3161 + client + " (" + win.mAttrs.getTitle() + ")", 3162 e); 3163 Binder.restoreCallingIdentity(origId); 3164 return 0; 3165 } 3166 if (toBeDisplayed) { 3167 focusMayChange = isDefaultDisplay; 3168 } 3169 if (win.mAttrs.type == TYPE_INPUT_METHOD 3170 && mInputMethodWindow == null) { 3171 mInputMethodWindow = win; 3172 imMayMove = true; 3173 } 3174 if (win.mAttrs.type == TYPE_BASE_APPLICATION 3175 && win.mAppToken != null 3176 && win.mAppToken.startingWindow != null) { 3177 // Special handling of starting window over the base 3178 // window of the app: propagate lock screen flags to it, 3179 // to provide the correct semantics while starting. 3180 final int mask = 3181 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 3182 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 3183 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 3184 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs; 3185 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask); 3186 } 3187 } else { 3188 winAnimator.mEnterAnimationPending = false; 3189 winAnimator.mEnteringAnimation = false; 3190 if (winAnimator.mSurfaceControl != null) { 3191 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win 3192 + ": mExiting=" + win.mExiting); 3193 // If we are not currently running the exit animation, we 3194 // need to see about starting one. 3195 if (!win.mExiting) { 3196 surfaceChanged = true; 3197 // Try starting an animation; if there isn't one, we 3198 // can destroy the surface right away. 3199 int transit = WindowManagerPolicy.TRANSIT_EXIT; 3200 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 3201 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 3202 } 3203 if (win.isWinVisibleLw() && 3204 winAnimator.applyAnimationLocked(transit, false)) { 3205 focusMayChange = isDefaultDisplay; 3206 win.mExiting = true; 3207 } else if (win.mWinAnimator.isAnimating()) { 3208 // Currently in a hide animation... turn this into 3209 // an exit. 3210 win.mExiting = true; 3211 } else if (win == mWallpaperTarget) { 3212 // If the wallpaper is currently behind this 3213 // window, we need to change both of them inside 3214 // of a transaction to avoid artifacts. 3215 win.mExiting = true; 3216 win.mWinAnimator.mAnimating = true; 3217 } else { 3218 if (mInputMethodWindow == win) { 3219 mInputMethodWindow = null; 3220 } 3221 winAnimator.destroySurfaceLocked(); 3222 } 3223 //TODO (multidisplay): Magnification is supported only for the default 3224 if (mAccessibilityController != null 3225 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 3226 mAccessibilityController.onWindowTransitionLocked(win, transit); 3227 } 3228 } 3229 } 3230 3231 outSurface.release(); 3232 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win); 3233 } 3234 3235 if (focusMayChange) { 3236 //System.out.println("Focus may change: " + win.mAttrs.getTitle()); 3237 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 3238 false /*updateInputWindows*/)) { 3239 imMayMove = false; 3240 } 3241 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus); 3242 } 3243 3244 // updateFocusedWindowLocked() already assigned layers so we only need to 3245 // reassign them at this point if the IM window state gets shuffled 3246 if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) { 3247 // Little hack here -- we -should- be able to rely on the 3248 // function to return true if the IME has moved and needs 3249 // its layer recomputed. However, if the IME was hidden 3250 // and isn't actually moved in the list, its layer may be 3251 // out of data so we make sure to recompute it. 3252 assignLayersLocked(win.getWindowList()); 3253 } 3254 3255 if (wallpaperMayMove) { 3256 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3257 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3258 } 3259 3260 final DisplayContent displayContent = win.getDisplayContent(); 3261 if (displayContent != null) { 3262 displayContent.layoutNeeded = true; 3263 } 3264 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; 3265 configChanged = updateOrientationFromAppTokensLocked(false); 3266 performLayoutAndPlaceSurfacesLocked(); 3267 if (toBeDisplayed && win.mIsWallpaper) { 3268 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3269 updateWallpaperOffsetLocked(win, 3270 displayInfo.logicalWidth, displayInfo.logicalHeight, false); 3271 } 3272 if (win.mAppToken != null) { 3273 win.mAppToken.updateReportedVisibilityLocked(); 3274 } 3275 outFrame.set(win.mCompatFrame); 3276 outOverscanInsets.set(win.mOverscanInsets); 3277 outContentInsets.set(win.mContentInsets); 3278 outVisibleInsets.set(win.mVisibleInsets); 3279 outStableInsets.set(win.mStableInsets); 3280 if (localLOGV) Slog.v( 3281 TAG, "Relayout given client " + client.asBinder() 3282 + ", requestedWidth=" + requestedWidth 3283 + ", requestedHeight=" + requestedHeight 3284 + ", viewVisibility=" + viewVisibility 3285 + "\nRelayout returning frame=" + outFrame 3286 + ", surface=" + outSurface); 3287 3288 if (localLOGV || DEBUG_FOCUS) Slog.v( 3289 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange); 3290 3291 inTouchMode = mInTouchMode; 3292 animating = mAnimator.mAnimating && win.mWinAnimator.isAnimating(); 3293 if (animating && !mRelayoutWhileAnimating.contains(win)) { 3294 mRelayoutWhileAnimating.add(win); 3295 } 3296 3297 mInputMonitor.updateInputWindowsLw(true /*force*/); 3298 3299 if (DEBUG_LAYOUT) { 3300 Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString()); 3301 } 3302 } 3303 3304 if (configChanged) { 3305 sendNewConfiguration(); 3306 } 3307 3308 Binder.restoreCallingIdentity(origId); 3309 3310 return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0) 3311 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0) 3312 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0) 3313 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0); 3314 } 3315 3316 public void performDeferredDestroyWindow(Session session, IWindow client) { 3317 long origId = Binder.clearCallingIdentity(); 3318 3319 try { 3320 synchronized (mWindowMap) { 3321 WindowState win = windowForClientLocked(session, client, false); 3322 if (win == null) { 3323 return; 3324 } 3325 win.mWinAnimator.destroyDeferredSurfaceLocked(); 3326 } 3327 } finally { 3328 Binder.restoreCallingIdentity(origId); 3329 } 3330 } 3331 3332 public boolean outOfMemoryWindow(Session session, IWindow client) { 3333 long origId = Binder.clearCallingIdentity(); 3334 3335 try { 3336 synchronized (mWindowMap) { 3337 WindowState win = windowForClientLocked(session, client, false); 3338 if (win == null) { 3339 return false; 3340 } 3341 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false); 3342 } 3343 } finally { 3344 Binder.restoreCallingIdentity(origId); 3345 } 3346 } 3347 3348 public void finishDrawingWindow(Session session, IWindow client) { 3349 final long origId = Binder.clearCallingIdentity(); 3350 try { 3351 synchronized (mWindowMap) { 3352 WindowState win = windowForClientLocked(session, client, false); 3353 if (win != null && win.mWinAnimator.finishDrawingLocked()) { 3354 if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 3355 getDefaultDisplayContentLocked().pendingLayoutChanges |= 3356 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 3357 } 3358 final DisplayContent displayContent = win.getDisplayContent(); 3359 if (displayContent != null) { 3360 displayContent.layoutNeeded = true; 3361 } 3362 requestTraversalLocked(); 3363 } 3364 } 3365 } finally { 3366 Binder.restoreCallingIdentity(origId); 3367 } 3368 } 3369 3370 private boolean applyAnimationLocked(AppWindowToken atoken, 3371 WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { 3372 // Only apply an animation if the display isn't frozen. If it is 3373 // frozen, there is no reason to animate and it can cause strange 3374 // artifacts when we unfreeze the display if some different animation 3375 // is running. 3376 if (okToDisplay()) { 3377 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3378 final int width = displayInfo.appWidth; 3379 final int height = displayInfo.appHeight; 3380 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken=" 3381 + atoken); 3382 3383 // Determine the visible rect to calculate the thumbnail clip 3384 WindowState win = atoken.findMainWindow(); 3385 Rect containingFrame = new Rect(0, 0, width, height); 3386 Rect contentInsets = new Rect(); 3387 boolean isFullScreen = true; 3388 if (win != null) { 3389 if (win.mContainingFrame != null) { 3390 containingFrame.set(win.mContainingFrame); 3391 } 3392 if (win.mContentInsets != null) { 3393 contentInsets.set(win.mContentInsets); 3394 } 3395 isFullScreen = 3396 ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) == 3397 SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) || 3398 ((win.mAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0); 3399 } 3400 3401 if (atoken.mLaunchTaskBehind) { 3402 // Differentiate the two animations. This one which is briefly on the screen 3403 // gets the !enter animation, and the other activity which remains on the 3404 // screen gets the enter animation. Both appear in the mOpeningApps set. 3405 enter = false; 3406 } 3407 Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height, 3408 mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen, 3409 isVoiceInteraction); 3410 if (a != null) { 3411 if (DEBUG_ANIM) { 3412 RuntimeException e = null; 3413 if (!HIDE_STACK_CRAWLS) { 3414 e = new RuntimeException(); 3415 e.fillInStackTrace(); 3416 } 3417 Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e); 3418 } 3419 atoken.mAppAnimator.setAnimation(a, width, height); 3420 } 3421 } else { 3422 atoken.mAppAnimator.clearAnimation(); 3423 } 3424 3425 return atoken.mAppAnimator.animation != null; 3426 } 3427 3428 // ------------------------------------------------------------- 3429 // Application Window Tokens 3430 // ------------------------------------------------------------- 3431 3432 public void validateAppTokens(int stackId, List<TaskGroup> tasks) { 3433 synchronized (mWindowMap) { 3434 int t = tasks.size() - 1; 3435 if (t < 0) { 3436 Slog.w(TAG, "validateAppTokens: empty task list"); 3437 return; 3438 } 3439 3440 TaskGroup task = tasks.get(0); 3441 int taskId = task.taskId; 3442 Task targetTask = mTaskIdToTask.get(taskId); 3443 DisplayContent displayContent = targetTask.getDisplayContent(); 3444 if (displayContent == null) { 3445 Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId); 3446 return; 3447 } 3448 3449 final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks(); 3450 int taskNdx; 3451 for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) { 3452 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens; 3453 task = tasks.get(t); 3454 List<IApplicationToken> tokens = task.tokens; 3455 3456 DisplayContent lastDisplayContent = displayContent; 3457 displayContent = mTaskIdToTask.get(taskId).getDisplayContent(); 3458 if (displayContent != lastDisplayContent) { 3459 Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!"); 3460 return; 3461 } 3462 3463 int tokenNdx; 3464 int v; 3465 for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1; 3466 tokenNdx >= 0 && v >= 0; ) { 3467 final AppWindowToken atoken = localTokens.get(tokenNdx); 3468 if (atoken.removed) { 3469 --tokenNdx; 3470 continue; 3471 } 3472 if (tokens.get(v) != atoken.token) { 3473 break; 3474 } 3475 --tokenNdx; 3476 v--; 3477 } 3478 3479 if (tokenNdx >= 0 || v >= 0) { 3480 break; 3481 } 3482 } 3483 3484 if (taskNdx >= 0 || t >= 0) { 3485 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks); 3486 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks); 3487 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4)); 3488 } 3489 } 3490 } 3491 3492 public void validateStackOrder(Integer[] remoteStackIds) { 3493 // TODO: 3494 } 3495 3496 boolean checkCallingPermission(String permission, String func) { 3497 // Quick check: if the calling permission is me, it's all okay. 3498 if (Binder.getCallingPid() == Process.myPid()) { 3499 return true; 3500 } 3501 3502 if (mContext.checkCallingPermission(permission) 3503 == PackageManager.PERMISSION_GRANTED) { 3504 return true; 3505 } 3506 String msg = "Permission Denial: " + func + " from pid=" 3507 + Binder.getCallingPid() 3508 + ", uid=" + Binder.getCallingUid() 3509 + " requires " + permission; 3510 Slog.w(TAG, msg); 3511 return false; 3512 } 3513 3514 boolean okToDisplay() { 3515 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn(); 3516 } 3517 3518 AppWindowToken findAppWindowToken(IBinder token) { 3519 WindowToken wtoken = mTokenMap.get(token); 3520 if (wtoken == null) { 3521 return null; 3522 } 3523 return wtoken.appWindowToken; 3524 } 3525 3526 @Override 3527 public void addWindowToken(IBinder token, int type) { 3528 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3529 "addWindowToken()")) { 3530 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3531 } 3532 3533 synchronized(mWindowMap) { 3534 WindowToken wtoken = mTokenMap.get(token); 3535 if (wtoken != null) { 3536 Slog.w(TAG, "Attempted to add existing input method token: " + token); 3537 return; 3538 } 3539 wtoken = new WindowToken(this, token, type, true); 3540 mTokenMap.put(token, wtoken); 3541 if (type == TYPE_WALLPAPER) { 3542 mWallpaperTokens.add(wtoken); 3543 } 3544 } 3545 } 3546 3547 @Override 3548 public void removeWindowToken(IBinder token) { 3549 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3550 "removeWindowToken()")) { 3551 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3552 } 3553 3554 final long origId = Binder.clearCallingIdentity(); 3555 synchronized(mWindowMap) { 3556 DisplayContent displayContent = null; 3557 WindowToken wtoken = mTokenMap.remove(token); 3558 if (wtoken != null) { 3559 boolean delayed = false; 3560 if (!wtoken.hidden) { 3561 final int N = wtoken.windows.size(); 3562 boolean changed = false; 3563 3564 for (int i=0; i<N; i++) { 3565 WindowState win = wtoken.windows.get(i); 3566 displayContent = win.getDisplayContent(); 3567 3568 if (win.mWinAnimator.isAnimating()) { 3569 delayed = true; 3570 } 3571 3572 if (win.isVisibleNow()) { 3573 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, 3574 false); 3575 //TODO (multidisplay): Magnification is supported only for the default 3576 if (mAccessibilityController != null && win.isDefaultDisplay()) { 3577 mAccessibilityController.onWindowTransitionLocked(win, 3578 WindowManagerPolicy.TRANSIT_EXIT); 3579 } 3580 changed = true; 3581 if (displayContent != null) { 3582 displayContent.layoutNeeded = true; 3583 } 3584 } 3585 } 3586 3587 wtoken.hidden = true; 3588 3589 if (changed) { 3590 performLayoutAndPlaceSurfacesLocked(); 3591 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 3592 false /*updateInputWindows*/); 3593 } 3594 3595 if (delayed) { 3596 if (displayContent != null) { 3597 displayContent.mExitingTokens.add(wtoken); 3598 } 3599 } else if (wtoken.windowType == TYPE_WALLPAPER) { 3600 mWallpaperTokens.remove(wtoken); 3601 } 3602 } 3603 3604 mInputMonitor.updateInputWindowsLw(true /*force*/); 3605 } else { 3606 Slog.w(TAG, "Attempted to remove non-existing token: " + token); 3607 } 3608 } 3609 Binder.restoreCallingIdentity(origId); 3610 } 3611 3612 private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) { 3613 if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId 3614 + " atoken=" + atoken); 3615 final TaskStack stack = mStackIdToStack.get(stackId); 3616 if (stack == null) { 3617 throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); 3618 } 3619 EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId); 3620 Task task = new Task(atoken, stack, userId); 3621 mTaskIdToTask.put(taskId, task); 3622 stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */); 3623 return task; 3624 } 3625 3626 @Override 3627 public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, 3628 int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId, 3629 int configChanges, boolean voiceInteraction, boolean launchTaskBehind) { 3630 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3631 "addAppToken()")) { 3632 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3633 } 3634 3635 // Get the dispatching timeout here while we are not holding any locks so that it 3636 // can be cached by the AppWindowToken. The timeout value is used later by the 3637 // input dispatcher in code that does hold locks. If we did not cache the value 3638 // here we would run the chance of introducing a deadlock between the window manager 3639 // (which holds locks while updating the input dispatcher state) and the activity manager 3640 // (which holds locks while querying the application token). 3641 long inputDispatchingTimeoutNanos; 3642 try { 3643 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; 3644 } catch (RemoteException ex) { 3645 Slog.w(TAG, "Could not get dispatching timeout.", ex); 3646 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 3647 } 3648 3649 synchronized(mWindowMap) { 3650 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3651 if (atoken != null) { 3652 Slog.w(TAG, "Attempted to add existing app token: " + token); 3653 return; 3654 } 3655 atoken = new AppWindowToken(this, token, voiceInteraction); 3656 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; 3657 atoken.groupId = taskId; 3658 atoken.appFullscreen = fullscreen; 3659 atoken.showWhenLocked = showWhenLocked; 3660 atoken.requestedOrientation = requestedOrientation; 3661 atoken.layoutConfigChanges = (configChanges & 3662 (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0; 3663 atoken.mLaunchTaskBehind = launchTaskBehind; 3664 if (true || DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken 3665 + " to stack=" + stackId + " task=" + taskId + " at " + addPos); 3666 3667 Task task = mTaskIdToTask.get(taskId); 3668 if (task == null) { 3669 createTask(taskId, stackId, userId, atoken); 3670 } else { 3671 task.addAppToken(addPos, atoken); 3672 } 3673 3674 mTokenMap.put(token.asBinder(), atoken); 3675 3676 // Application tokens start out hidden. 3677 atoken.hidden = true; 3678 atoken.hiddenRequested = true; 3679 3680 //dump(); 3681 } 3682 } 3683 3684 @Override 3685 public void setAppGroupId(IBinder token, int groupId) { 3686 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3687 "setAppGroupId()")) { 3688 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3689 } 3690 3691 synchronized(mWindowMap) { 3692 final AppWindowToken atoken = findAppWindowToken(token); 3693 if (atoken == null) { 3694 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); 3695 return; 3696 } 3697 final Task oldTask = mTaskIdToTask.get(atoken.groupId); 3698 oldTask.removeAppToken(atoken); 3699 3700 atoken.groupId = groupId; 3701 Task newTask = mTaskIdToTask.get(groupId); 3702 if (newTask == null) { 3703 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken); 3704 } else { 3705 newTask.mAppTokens.add(atoken); 3706 } 3707 } 3708 } 3709 3710 public int getOrientationFromWindowsLocked() { 3711 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 3712 // If the display is frozen, some activities may be in the middle 3713 // of restarting, and thus have removed their old window. If the 3714 // window has the flag to hide the lock screen, then the lock screen 3715 // can re-appear and inflict its own orientation on us. Keep the 3716 // orientation stable until this all settles down. 3717 return mLastWindowForcedOrientation; 3718 } 3719 3720 // TODO(multidisplay): Change to the correct display. 3721 final WindowList windows = getDefaultWindowListLocked(); 3722 int pos = windows.size() - 1; 3723 while (pos >= 0) { 3724 WindowState win = windows.get(pos); 3725 pos--; 3726 if (win.mAppToken != null) { 3727 // We hit an application window. so the orientation will be determined by the 3728 // app window. No point in continuing further. 3729 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3730 } 3731 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) { 3732 continue; 3733 } 3734 int req = win.mAttrs.screenOrientation; 3735 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) || 3736 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){ 3737 continue; 3738 } 3739 3740 if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req); 3741 return (mLastWindowForcedOrientation=req); 3742 } 3743 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3744 } 3745 3746 public int getOrientationFromAppTokensLocked() { 3747 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3748 boolean findingBehind = false; 3749 boolean lastFullscreen = false; 3750 // TODO: Multi win