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