WindowManagerService.java revision 228742d2781c2c6b924e2c2dc0ac2a6b62e33e10
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 private 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 mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK)); 5560 } 5561 } 5562 5563 public void showCircularMask() { 5564 synchronized(mWindowMap) { 5565 5566 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5567 ">>> OPEN TRANSACTION showDisplayMask"); 5568 SurfaceControl.openTransaction(); 5569 try { 5570 // TODO(multi-display): support multiple displays 5571 if (mCircularDisplayMask == null) { 5572 mCircularDisplayMask = new CircularDisplayMask( 5573 getDefaultDisplayContentLocked().getDisplay(), 5574 mFxSession, 5575 mPolicy.windowTypeToLayerLw( 5576 WindowManager.LayoutParams.TYPE_POINTER) 5577 * TYPE_LAYER_MULTIPLIER + 10); 5578 } 5579 mCircularDisplayMask.setVisibility(true); 5580 } finally { 5581 SurfaceControl.closeTransaction(); 5582 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5583 "<<< CLOSE TRANSACTION showDisplayMask"); 5584 } 5585 } 5586 } 5587 5588 // TODO: more accounting of which pid(s) turned it on, keep count, 5589 // only allow disables from pids which have count on, etc. 5590 @Override 5591 public void showStrictModeViolation(boolean on) { 5592 int pid = Binder.getCallingPid(); 5593 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5594 } 5595 5596 private void showStrictModeViolation(int arg, int pid) { 5597 final boolean on = arg != 0; 5598 synchronized(mWindowMap) { 5599 // Ignoring requests to enable the red border from clients 5600 // which aren't on screen. (e.g. Broadcast Receivers in 5601 // the background..) 5602 if (on) { 5603 boolean isVisible = false; 5604 final int numDisplays = mDisplayContents.size(); 5605 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5606 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5607 final int numWindows = windows.size(); 5608 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5609 final WindowState ws = windows.get(winNdx); 5610 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5611 isVisible = true; 5612 break; 5613 } 5614 } 5615 } 5616 if (!isVisible) { 5617 return; 5618 } 5619 } 5620 5621 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5622 ">>> OPEN TRANSACTION showStrictModeViolation"); 5623 SurfaceControl.openTransaction(); 5624 try { 5625 // TODO(multi-display): support multiple displays 5626 if (mStrictModeFlash == null) { 5627 mStrictModeFlash = new StrictModeFlash( 5628 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5629 } 5630 mStrictModeFlash.setVisibility(on); 5631 } finally { 5632 SurfaceControl.closeTransaction(); 5633 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5634 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5635 } 5636 } 5637 } 5638 5639 @Override 5640 public void setStrictModeVisualIndicatorPreference(String value) { 5641 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5642 } 5643 5644 /** 5645 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5646 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5647 * of the target image. 5648 * 5649 * @param displayId the Display to take a screenshot of. 5650 * @param width the width of the target bitmap 5651 * @param height the height of the target bitmap 5652 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 5653 * will be the same config as the surface 5654 */ 5655 @Override 5656 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 5657 int height, boolean force565) { 5658 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5659 "screenshotApplications()")) { 5660 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5661 } 5662 5663 Bitmap rawss = null; 5664 5665 int maxLayer = 0; 5666 final Rect frame = new Rect(); 5667 5668 float scale = 0; 5669 int dw, dh; 5670 int rot = Surface.ROTATION_0; 5671 5672 boolean screenshotReady; 5673 int minLayer; 5674 if (appToken == null) { 5675 screenshotReady = true; 5676 minLayer = 0; 5677 } else { 5678 screenshotReady = false; 5679 minLayer = Integer.MAX_VALUE; 5680 } 5681 5682 int retryCount = 0; 5683 WindowState appWin = null; 5684 5685 do { 5686 if (retryCount++ > 0) { 5687 try { 5688 Thread.sleep(100); 5689 } catch (InterruptedException e) { 5690 } 5691 } 5692 synchronized(mWindowMap) { 5693 final DisplayContent displayContent = getDisplayContentLocked(displayId); 5694 if (displayContent == null) { 5695 return null; 5696 } 5697 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5698 dw = displayInfo.logicalWidth; 5699 dh = displayInfo.logicalHeight; 5700 5701 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) 5702 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 5703 aboveAppLayer += TYPE_LAYER_MULTIPLIER; 5704 5705 boolean isImeTarget = mInputMethodTarget != null 5706 && mInputMethodTarget.mAppToken != null 5707 && mInputMethodTarget.mAppToken.appToken != null 5708 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5709 5710 // Figure out the part of the screen that is actually the app. 5711 boolean including = false; 5712 appWin = null; 5713 final WindowList windows = displayContent.getWindowList(); 5714 final Rect stackBounds = new Rect(); 5715 for (int i = windows.size() - 1; i >= 0; i--) { 5716 WindowState ws = windows.get(i); 5717 if (!ws.mHasSurface) { 5718 continue; 5719 } 5720 if (ws.mLayer >= aboveAppLayer) { 5721 continue; 5722 } 5723 // When we will skip windows: when we are not including 5724 // ones behind a window we didn't skip, and we are actually 5725 // taking a screenshot of a specific app. 5726 if (!including && appToken != null) { 5727 // Also, we can possibly skip this window if it is not 5728 // an IME target or the application for the screenshot 5729 // is not the current IME target. 5730 if (!ws.mIsImWindow || !isImeTarget) { 5731 // And finally, this window is of no interest if it 5732 // is not associated with the screenshot app. 5733 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5734 continue; 5735 } 5736 appWin = ws; 5737 ws.getStackBounds(stackBounds); 5738 } 5739 } 5740 5741 // We keep on including windows until we go past a full-screen 5742 // window. 5743 including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); 5744 5745 final WindowStateAnimator winAnim = ws.mWinAnimator; 5746 if (maxLayer < winAnim.mSurfaceLayer) { 5747 maxLayer = winAnim.mSurfaceLayer; 5748 } 5749 if (minLayer > winAnim.mSurfaceLayer) { 5750 minLayer = winAnim.mSurfaceLayer; 5751 } 5752 5753 // Don't include wallpaper in bounds calculation 5754 if (!ws.mIsWallpaper) { 5755 final Rect wf = ws.mFrame; 5756 final Rect cr = ws.mContentInsets; 5757 int left = wf.left + cr.left; 5758 int top = wf.top + cr.top; 5759 int right = wf.right - cr.right; 5760 int bottom = wf.bottom - cr.bottom; 5761 frame.union(left, top, right, bottom); 5762 frame.intersect(stackBounds); 5763 } 5764 5765 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 5766 ws.isDisplayedLw()) { 5767 screenshotReady = true; 5768 } 5769 } 5770 5771 if (appToken != null && appWin == null) { 5772 // Can't find a window to snapshot. 5773 if (DEBUG_SCREENSHOT) Slog.i(TAG, 5774 "Screenshot: Couldn't find a surface matching " + appToken); 5775 return null; 5776 } 5777 if (!screenshotReady) { 5778 // Delay and hope that window gets drawn. 5779 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 5780 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 5781 continue; 5782 } 5783 5784 // Constrain frame to the screen size. 5785 frame.intersect(0, 0, dw, dh); 5786 5787 if (frame.isEmpty() || maxLayer == 0) { 5788 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5789 + ": returning null frame=" + frame.toShortString() + " maxLayer=" 5790 + maxLayer); 5791 return null; 5792 } 5793 5794 // The screenshot API does not apply the current screen rotation. 5795 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 5796 int fw = frame.width(); 5797 int fh = frame.height(); 5798 5799 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5800 // of thumbnail is the same as the screen (in landscape) or square. 5801 scale = Math.max(width / (float) fw, height / (float) fh); 5802 /* 5803 float targetWidthScale = width / (float) fw; 5804 float targetHeightScale = height / (float) fh; 5805 if (fw <= fh) { 5806 scale = targetWidthScale; 5807 // If aspect of thumbnail is the same as the screen (in landscape), 5808 // select the slightly larger value so we fill the entire bitmap 5809 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) { 5810 scale = targetHeightScale; 5811 } 5812 } else { 5813 scale = targetHeightScale; 5814 // If aspect of thumbnail is the same as the screen (in landscape), 5815 // select the slightly larger value so we fill the entire bitmap 5816 if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) { 5817 scale = targetWidthScale; 5818 } 5819 } 5820 */ 5821 5822 // The screen shot will contain the entire screen. 5823 dw = (int)(dw*scale); 5824 dh = (int)(dh*scale); 5825 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5826 int tmp = dw; 5827 dw = dh; 5828 dh = tmp; 5829 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5830 } 5831 if (DEBUG_SCREENSHOT) { 5832 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 5833 + maxLayer + " appToken=" + appToken); 5834 for (int i = 0; i < windows.size(); i++) { 5835 WindowState win = windows.get(i); 5836 Slog.i(TAG, win + ": " + win.mLayer 5837 + " animLayer=" + win.mWinAnimator.mAnimLayer 5838 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 5839 } 5840 } 5841 rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer); 5842 } 5843 } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); 5844 if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " + 5845 retryCount + " of " + appToken + " appWin=" + (appWin == null ? 5846 "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState))); 5847 5848 if (rawss == null) { 5849 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 5850 + ") to layer " + maxLayer); 5851 return null; 5852 } 5853 5854 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig()); 5855 frame.scale(scale); 5856 Matrix matrix = new Matrix(); 5857 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 5858 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left 5859 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top)); 5860 Canvas canvas = new Canvas(bm); 5861 canvas.drawColor(0xFF000000); 5862 canvas.drawBitmap(rawss, matrix, null); 5863 canvas.setBitmap(null); 5864 5865 if (DEBUG_SCREENSHOT) { 5866 // TEST IF IT's ALL BLACK 5867 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 5868 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 5869 boolean allBlack = true; 5870 final int firstColor = buffer[0]; 5871 for (int i = 0; i < buffer.length; i++) { 5872 if (buffer[i] != firstColor) { 5873 allBlack = false; 5874 break; 5875 } 5876 } 5877 if (allBlack) { 5878 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 5879 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 5880 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 5881 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 5882 } 5883 } 5884 5885 rawss.recycle(); 5886 return bm; 5887 } 5888 5889 /** 5890 * Freeze rotation changes. (Enable "rotation lock".) 5891 * Persists across reboots. 5892 * @param rotation The desired rotation to freeze to, or -1 to use the 5893 * current rotation. 5894 */ 5895 @Override 5896 public void freezeRotation(int rotation) { 5897 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5898 "freezeRotation()")) { 5899 throw new SecurityException("Requires SET_ORIENTATION permission"); 5900 } 5901 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5902 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5903 + "rotation constant."); 5904 } 5905 5906 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5907 5908 long origId = Binder.clearCallingIdentity(); 5909 try { 5910 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5911 rotation == -1 ? mRotation : rotation); 5912 } finally { 5913 Binder.restoreCallingIdentity(origId); 5914 } 5915 5916 updateRotationUnchecked(false, false); 5917 } 5918 5919 /** 5920 * Thaw rotation changes. (Disable "rotation lock".) 5921 * Persists across reboots. 5922 */ 5923 @Override 5924 public void thawRotation() { 5925 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5926 "thawRotation()")) { 5927 throw new SecurityException("Requires SET_ORIENTATION permission"); 5928 } 5929 5930 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5931 5932 long origId = Binder.clearCallingIdentity(); 5933 try { 5934 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 5935 777); // rot not used 5936 } finally { 5937 Binder.restoreCallingIdentity(origId); 5938 } 5939 5940 updateRotationUnchecked(false, false); 5941 } 5942 5943 /** 5944 * Recalculate the current rotation. 5945 * 5946 * Called by the window manager policy whenever the state of the system changes 5947 * such that the current rotation might need to be updated, such as when the 5948 * device is docked or rotated into a new posture. 5949 */ 5950 @Override 5951 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5952 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5953 } 5954 5955 /** 5956 * Temporarily pauses rotation changes until resumed. 5957 * 5958 * This can be used to prevent rotation changes from occurring while the user is 5959 * performing certain operations, such as drag and drop. 5960 * 5961 * This call nests and must be matched by an equal number of calls to 5962 * {@link #resumeRotationLocked}. 5963 */ 5964 void pauseRotationLocked() { 5965 mDeferredRotationPauseCount += 1; 5966 } 5967 5968 /** 5969 * Resumes normal rotation changes after being paused. 5970 */ 5971 void resumeRotationLocked() { 5972 if (mDeferredRotationPauseCount > 0) { 5973 mDeferredRotationPauseCount -= 1; 5974 if (mDeferredRotationPauseCount == 0) { 5975 boolean changed = updateRotationUncheckedLocked(false); 5976 if (changed) { 5977 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5978 } 5979 } 5980 } 5981 } 5982 5983 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 5984 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 5985 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 5986 5987 long origId = Binder.clearCallingIdentity(); 5988 boolean changed; 5989 synchronized(mWindowMap) { 5990 changed = updateRotationUncheckedLocked(false); 5991 if (!changed || forceRelayout) { 5992 getDefaultDisplayContentLocked().layoutNeeded = true; 5993 performLayoutAndPlaceSurfacesLocked(); 5994 } 5995 } 5996 5997 if (changed || alwaysSendConfiguration) { 5998 sendNewConfiguration(); 5999 } 6000 6001 Binder.restoreCallingIdentity(origId); 6002 } 6003 6004 // TODO(multidisplay): Rotate any display? 6005 /** 6006 * Updates the current rotation. 6007 * 6008 * Returns true if the rotation has been changed. In this case YOU 6009 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 6010 */ 6011 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 6012 if (mDeferredRotationPauseCount > 0) { 6013 // Rotation updates have been paused temporarily. Defer the update until 6014 // updates have been resumed. 6015 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 6016 return false; 6017 } 6018 6019 ScreenRotationAnimation screenRotationAnimation = 6020 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6021 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 6022 // Rotation updates cannot be performed while the previous rotation change 6023 // animation is still in progress. Skip this update. We will try updating 6024 // again after the animation is finished and the display is unfrozen. 6025 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 6026 return false; 6027 } 6028 6029 if (!mDisplayEnabled) { 6030 // No point choosing a rotation if the display is not enabled. 6031 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 6032 return false; 6033 } 6034 6035 // TODO: Implement forced rotation changes. 6036 // Set mAltOrientation to indicate that the application is receiving 6037 // an orientation that has different metrics than it expected. 6038 // eg. Portrait instead of Landscape. 6039 6040 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 6041 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 6042 mForcedAppOrientation, rotation); 6043 6044 if (DEBUG_ORIENTATION) { 6045 Slog.v(TAG, "Application requested orientation " 6046 + mForcedAppOrientation + ", got rotation " + rotation 6047 + " which has " + (altOrientation ? "incompatible" : "compatible") 6048 + " metrics"); 6049 } 6050 6051 if (mRotation == rotation && mAltOrientation == altOrientation) { 6052 // No change. 6053 return false; 6054 } 6055 6056 if (DEBUG_ORIENTATION) { 6057 Slog.v(TAG, 6058 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 6059 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 6060 + ", forceApp=" + mForcedAppOrientation); 6061 } 6062 6063 mRotation = rotation; 6064 mAltOrientation = altOrientation; 6065 mPolicy.setRotationLw(mRotation); 6066 6067 mWindowsFreezingScreen = true; 6068 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 6069 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 6070 mWaitingForConfig = true; 6071 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6072 displayContent.layoutNeeded = true; 6073 final int[] anim = new int[2]; 6074 if (displayContent.isDimming()) { 6075 anim[0] = anim[1] = 0; 6076 } else { 6077 mPolicy.selectRotationAnimationLw(anim); 6078 } 6079 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6080 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6081 screenRotationAnimation = 6082 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6083 6084 // We need to update our screen size information to match the new 6085 // rotation. Note that this is redundant with the later call to 6086 // sendNewConfiguration() that must be called after this function 6087 // returns... however we need to do the screen size part of that 6088 // before then so we have the correct size to use when initializing 6089 // the rotation animation for the new rotation. 6090 computeScreenConfigurationLocked(null); 6091 6092 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6093 if (!inTransaction) { 6094 if (SHOW_TRANSACTIONS) { 6095 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 6096 } 6097 SurfaceControl.openTransaction(); 6098 } 6099 try { 6100 // NOTE: We disable the rotation in the emulator because 6101 // it doesn't support hardware OpenGL emulation yet. 6102 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6103 && screenRotationAnimation.hasScreenshot()) { 6104 if (screenRotationAnimation.setRotationInTransaction( 6105 rotation, mFxSession, 6106 MAX_ANIMATION_DURATION, mTransitionAnimationScale, 6107 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6108 scheduleAnimationLocked(); 6109 } 6110 } 6111 6112 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6113 } finally { 6114 if (!inTransaction) { 6115 SurfaceControl.closeTransaction(); 6116 if (SHOW_LIGHT_TRANSACTIONS) { 6117 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6118 } 6119 } 6120 } 6121 6122 final WindowList windows = displayContent.getWindowList(); 6123 for (int i = windows.size() - 1; i >= 0; i--) { 6124 WindowState w = windows.get(i); 6125 if (w.mHasSurface) { 6126 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 6127 w.mOrientationChanging = true; 6128 mInnerFields.mOrientationChangeComplete = false; 6129 } 6130 w.mLastFreezeDuration = 0; 6131 } 6132 6133 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6134 try { 6135 mRotationWatchers.get(i).watcher.onRotationChanged(rotation); 6136 } catch (RemoteException e) { 6137 } 6138 } 6139 6140 //TODO (multidisplay): Magnification is supported only for the default display. 6141 if (mDisplayMagnifier != null 6142 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6143 mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 6144 } 6145 6146 return true; 6147 } 6148 6149 @Override 6150 public int getRotation() { 6151 return mRotation; 6152 } 6153 6154 @Override 6155 public boolean isRotationFrozen() { 6156 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6157 } 6158 6159 @Override 6160 public int watchRotation(IRotationWatcher watcher) { 6161 final IBinder watcherBinder = watcher.asBinder(); 6162 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6163 @Override 6164 public void binderDied() { 6165 synchronized (mWindowMap) { 6166 for (int i=0; i<mRotationWatchers.size(); i++) { 6167 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) { 6168 RotationWatcher removed = mRotationWatchers.remove(i); 6169 if (removed != null) { 6170 removed.watcher.asBinder().unlinkToDeath(this, 0); 6171 } 6172 i--; 6173 } 6174 } 6175 } 6176 } 6177 }; 6178 6179 synchronized (mWindowMap) { 6180 try { 6181 watcher.asBinder().linkToDeath(dr, 0); 6182 mRotationWatchers.add(new RotationWatcher(watcher, dr)); 6183 } catch (RemoteException e) { 6184 // Client died, no cleanup needed. 6185 } 6186 6187 return mRotation; 6188 } 6189 } 6190 6191 @Override 6192 public void removeRotationWatcher(IRotationWatcher watcher) { 6193 final IBinder watcherBinder = watcher.asBinder(); 6194 synchronized (mWindowMap) { 6195 for (int i=0; i<mRotationWatchers.size(); i++) { 6196 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 6197 if (watcherBinder == rotationWatcher.watcher.asBinder()) { 6198 RotationWatcher removed = mRotationWatchers.remove(i); 6199 if (removed != null) { 6200 removed.watcher.asBinder().unlinkToDeath(removed.dr, 0); 6201 i--; 6202 } 6203 } 6204 } 6205 } 6206 } 6207 6208 /** 6209 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6210 * theme attribute) on devices that feature a physical options menu key attempt to position 6211 * their menu panel window along the edge of the screen nearest the physical menu key. 6212 * This lowers the travel distance between invoking the menu panel and selecting 6213 * a menu option. 6214 * 6215 * This method helps control where that menu is placed. Its current implementation makes 6216 * assumptions about the menu key and its relationship to the screen based on whether 6217 * the device's natural orientation is portrait (width < height) or landscape. 6218 * 6219 * The menu key is assumed to be located along the bottom edge of natural-portrait 6220 * devices and along the right edge of natural-landscape devices. If these assumptions 6221 * do not hold for the target device, this method should be changed to reflect that. 6222 * 6223 * @return A {@link Gravity} value for placing the options menu window 6224 */ 6225 @Override 6226 public int getPreferredOptionsPanelGravity() { 6227 synchronized (mWindowMap) { 6228 final int rotation = getRotation(); 6229 6230 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6231 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6232 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6233 // On devices with a natural orientation of portrait 6234 switch (rotation) { 6235 default: 6236 case Surface.ROTATION_0: 6237 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6238 case Surface.ROTATION_90: 6239 return Gravity.RIGHT | Gravity.BOTTOM; 6240 case Surface.ROTATION_180: 6241 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6242 case Surface.ROTATION_270: 6243 return Gravity.START | Gravity.BOTTOM; 6244 } 6245 } 6246 6247 // On devices with a natural orientation of landscape 6248 switch (rotation) { 6249 default: 6250 case Surface.ROTATION_0: 6251 return Gravity.RIGHT | Gravity.BOTTOM; 6252 case Surface.ROTATION_90: 6253 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6254 case Surface.ROTATION_180: 6255 return Gravity.START | Gravity.BOTTOM; 6256 case Surface.ROTATION_270: 6257 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6258 } 6259 } 6260 } 6261 6262 /** 6263 * Starts the view server on the specified port. 6264 * 6265 * @param port The port to listener to. 6266 * 6267 * @return True if the server was successfully started, false otherwise. 6268 * 6269 * @see com.android.server.wm.ViewServer 6270 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6271 */ 6272 @Override 6273 public boolean startViewServer(int port) { 6274 if (isSystemSecure()) { 6275 return false; 6276 } 6277 6278 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6279 return false; 6280 } 6281 6282 if (port < 1024) { 6283 return false; 6284 } 6285 6286 if (mViewServer != null) { 6287 if (!mViewServer.isRunning()) { 6288 try { 6289 return mViewServer.start(); 6290 } catch (IOException e) { 6291 Slog.w(TAG, "View server did not start"); 6292 } 6293 } 6294 return false; 6295 } 6296 6297 try { 6298 mViewServer = new ViewServer(this, port); 6299 return mViewServer.start(); 6300 } catch (IOException e) { 6301 Slog.w(TAG, "View server did not start"); 6302 } 6303 return false; 6304 } 6305 6306 private boolean isSystemSecure() { 6307 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6308 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6309 } 6310 6311 /** 6312 * Stops the view server if it exists. 6313 * 6314 * @return True if the server stopped, false if it wasn't started or 6315 * couldn't be stopped. 6316 * 6317 * @see com.android.server.wm.ViewServer 6318 */ 6319 @Override 6320 public boolean stopViewServer() { 6321 if (isSystemSecure()) { 6322 return false; 6323 } 6324 6325 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6326 return false; 6327 } 6328 6329 if (mViewServer != null) { 6330 return mViewServer.stop(); 6331 } 6332 return false; 6333 } 6334 6335 /** 6336 * Indicates whether the view server is running. 6337 * 6338 * @return True if the server is running, false otherwise. 6339 * 6340 * @see com.android.server.wm.ViewServer 6341 */ 6342 @Override 6343 public boolean isViewServerRunning() { 6344 if (isSystemSecure()) { 6345 return false; 6346 } 6347 6348 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6349 return false; 6350 } 6351 6352 return mViewServer != null && mViewServer.isRunning(); 6353 } 6354 6355 /** 6356 * Lists all availble windows in the system. The listing is written in the 6357 * specified Socket's output stream with the following syntax: 6358 * windowHashCodeInHexadecimal windowName 6359 * Each line of the ouput represents a different window. 6360 * 6361 * @param client The remote client to send the listing to. 6362 * @return False if an error occured, true otherwise. 6363 */ 6364 boolean viewServerListWindows(Socket client) { 6365 if (isSystemSecure()) { 6366 return false; 6367 } 6368 6369 boolean result = true; 6370 6371 WindowList windows = new WindowList(); 6372 synchronized (mWindowMap) { 6373 //noinspection unchecked 6374 final int numDisplays = mDisplayContents.size(); 6375 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6376 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6377 windows.addAll(displayContent.getWindowList()); 6378 } 6379 } 6380 6381 BufferedWriter out = null; 6382 6383 // Any uncaught exception will crash the system process 6384 try { 6385 OutputStream clientStream = client.getOutputStream(); 6386 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6387 6388 final int count = windows.size(); 6389 for (int i = 0; i < count; i++) { 6390 final WindowState w = windows.get(i); 6391 out.write(Integer.toHexString(System.identityHashCode(w))); 6392 out.write(' '); 6393 out.append(w.mAttrs.getTitle()); 6394 out.write('\n'); 6395 } 6396 6397 out.write("DONE.\n"); 6398 out.flush(); 6399 } catch (Exception e) { 6400 result = false; 6401 } finally { 6402 if (out != null) { 6403 try { 6404 out.close(); 6405 } catch (IOException e) { 6406 result = false; 6407 } 6408 } 6409 } 6410 6411 return result; 6412 } 6413 6414 // TODO(multidisplay): Extend to multiple displays. 6415 /** 6416 * Returns the focused window in the following format: 6417 * windowHashCodeInHexadecimal windowName 6418 * 6419 * @param client The remote client to send the listing to. 6420 * @return False if an error occurred, true otherwise. 6421 */ 6422 boolean viewServerGetFocusedWindow(Socket client) { 6423 if (isSystemSecure()) { 6424 return false; 6425 } 6426 6427 boolean result = true; 6428 6429 WindowState focusedWindow = getFocusedWindow(); 6430 6431 BufferedWriter out = null; 6432 6433 // Any uncaught exception will crash the system process 6434 try { 6435 OutputStream clientStream = client.getOutputStream(); 6436 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6437 6438 if(focusedWindow != null) { 6439 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6440 out.write(' '); 6441 out.append(focusedWindow.mAttrs.getTitle()); 6442 } 6443 out.write('\n'); 6444 out.flush(); 6445 } catch (Exception e) { 6446 result = false; 6447 } finally { 6448 if (out != null) { 6449 try { 6450 out.close(); 6451 } catch (IOException e) { 6452 result = false; 6453 } 6454 } 6455 } 6456 6457 return result; 6458 } 6459 6460 /** 6461 * Sends a command to a target window. The result of the command, if any, will be 6462 * written in the output stream of the specified socket. 6463 * 6464 * The parameters must follow this syntax: 6465 * windowHashcode extra 6466 * 6467 * Where XX is the length in characeters of the windowTitle. 6468 * 6469 * The first parameter is the target window. The window with the specified hashcode 6470 * will be the target. If no target can be found, nothing happens. The extra parameters 6471 * will be delivered to the target window and as parameters to the command itself. 6472 * 6473 * @param client The remote client to sent the result, if any, to. 6474 * @param command The command to execute. 6475 * @param parameters The command parameters. 6476 * 6477 * @return True if the command was successfully delivered, false otherwise. This does 6478 * not indicate whether the command itself was successful. 6479 */ 6480 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6481 if (isSystemSecure()) { 6482 return false; 6483 } 6484 6485 boolean success = true; 6486 Parcel data = null; 6487 Parcel reply = null; 6488 6489 BufferedWriter out = null; 6490 6491 // Any uncaught exception will crash the system process 6492 try { 6493 // Find the hashcode of the window 6494 int index = parameters.indexOf(' '); 6495 if (index == -1) { 6496 index = parameters.length(); 6497 } 6498 final String code = parameters.substring(0, index); 6499 int hashCode = (int) Long.parseLong(code, 16); 6500 6501 // Extract the command's parameter after the window description 6502 if (index < parameters.length()) { 6503 parameters = parameters.substring(index + 1); 6504 } else { 6505 parameters = ""; 6506 } 6507 6508 final WindowState window = findWindow(hashCode); 6509 if (window == null) { 6510 return false; 6511 } 6512 6513 data = Parcel.obtain(); 6514 data.writeInterfaceToken("android.view.IWindow"); 6515 data.writeString(command); 6516 data.writeString(parameters); 6517 data.writeInt(1); 6518 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6519 6520 reply = Parcel.obtain(); 6521 6522 final IBinder binder = window.mClient.asBinder(); 6523 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6524 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6525 6526 reply.readException(); 6527 6528 if (!client.isOutputShutdown()) { 6529 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6530 out.write("DONE\n"); 6531 out.flush(); 6532 } 6533 6534 } catch (Exception e) { 6535 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6536 success = false; 6537 } finally { 6538 if (data != null) { 6539 data.recycle(); 6540 } 6541 if (reply != null) { 6542 reply.recycle(); 6543 } 6544 if (out != null) { 6545 try { 6546 out.close(); 6547 } catch (IOException e) { 6548 6549 } 6550 } 6551 } 6552 6553 return success; 6554 } 6555 6556 public void addWindowChangeListener(WindowChangeListener listener) { 6557 synchronized(mWindowMap) { 6558 mWindowChangeListeners.add(listener); 6559 } 6560 } 6561 6562 public void removeWindowChangeListener(WindowChangeListener listener) { 6563 synchronized(mWindowMap) { 6564 mWindowChangeListeners.remove(listener); 6565 } 6566 } 6567 6568 private void notifyWindowsChanged() { 6569 WindowChangeListener[] windowChangeListeners; 6570 synchronized(mWindowMap) { 6571 if(mWindowChangeListeners.isEmpty()) { 6572 return; 6573 } 6574 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6575 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6576 } 6577 int N = windowChangeListeners.length; 6578 for(int i = 0; i < N; i++) { 6579 windowChangeListeners[i].windowsChanged(); 6580 } 6581 } 6582 6583 private void notifyFocusChanged() { 6584 WindowChangeListener[] windowChangeListeners; 6585 synchronized(mWindowMap) { 6586 if(mWindowChangeListeners.isEmpty()) { 6587 return; 6588 } 6589 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6590 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6591 } 6592 int N = windowChangeListeners.length; 6593 for(int i = 0; i < N; i++) { 6594 windowChangeListeners[i].focusChanged(); 6595 } 6596 } 6597 6598 private WindowState findWindow(int hashCode) { 6599 if (hashCode == -1) { 6600 // TODO(multidisplay): Extend to multiple displays. 6601 return getFocusedWindow(); 6602 } 6603 6604 synchronized (mWindowMap) { 6605 final int numDisplays = mDisplayContents.size(); 6606 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6607 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6608 final int numWindows = windows.size(); 6609 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6610 final WindowState w = windows.get(winNdx); 6611 if (System.identityHashCode(w) == hashCode) { 6612 return w; 6613 } 6614 } 6615 } 6616 } 6617 6618 return null; 6619 } 6620 6621 /* 6622 * Instruct the Activity Manager to fetch the current configuration and broadcast 6623 * that to config-changed listeners if appropriate. 6624 */ 6625 void sendNewConfiguration() { 6626 try { 6627 mActivityManager.updateConfiguration(null); 6628 } catch (RemoteException e) { 6629 } 6630 } 6631 6632 public Configuration computeNewConfiguration() { 6633 synchronized (mWindowMap) { 6634 Configuration config = computeNewConfigurationLocked(); 6635 if (config == null && mWaitingForConfig) { 6636 // Nothing changed but we are waiting for something... stop that! 6637 mWaitingForConfig = false; 6638 mLastFinishedFreezeSource = "new-config"; 6639 performLayoutAndPlaceSurfacesLocked(); 6640 } 6641 return config; 6642 } 6643 } 6644 6645 Configuration computeNewConfigurationLocked() { 6646 Configuration config = new Configuration(); 6647 config.fontScale = 0; 6648 if (!computeScreenConfigurationLocked(config)) { 6649 return null; 6650 } 6651 return config; 6652 } 6653 6654 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6655 // TODO: Multidisplay: for now only use with default display. 6656 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6657 if (width < displayInfo.smallestNominalAppWidth) { 6658 displayInfo.smallestNominalAppWidth = width; 6659 } 6660 if (width > displayInfo.largestNominalAppWidth) { 6661 displayInfo.largestNominalAppWidth = width; 6662 } 6663 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6664 if (height < displayInfo.smallestNominalAppHeight) { 6665 displayInfo.smallestNominalAppHeight = height; 6666 } 6667 if (height > displayInfo.largestNominalAppHeight) { 6668 displayInfo.largestNominalAppHeight = height; 6669 } 6670 } 6671 6672 private int reduceConfigLayout(int curLayout, int rotation, float density, 6673 int dw, int dh) { 6674 // TODO: Multidisplay: for now only use with default display. 6675 // Get the app screen size at this rotation. 6676 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6677 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6678 6679 // Compute the screen layout size class for this rotation. 6680 int longSize = w; 6681 int shortSize = h; 6682 if (longSize < shortSize) { 6683 int tmp = longSize; 6684 longSize = shortSize; 6685 shortSize = tmp; 6686 } 6687 longSize = (int)(longSize/density); 6688 shortSize = (int)(shortSize/density); 6689 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6690 } 6691 6692 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6693 int dw, int dh, float density, Configuration outConfig) { 6694 // TODO: Multidisplay: for now only use with default display. 6695 6696 // We need to determine the smallest width that will occur under normal 6697 // operation. To this, start with the base screen size and compute the 6698 // width under the different possible rotations. We need to un-rotate 6699 // the current screen dimensions before doing this. 6700 int unrotDw, unrotDh; 6701 if (rotated) { 6702 unrotDw = dh; 6703 unrotDh = dw; 6704 } else { 6705 unrotDw = dw; 6706 unrotDh = dh; 6707 } 6708 displayInfo.smallestNominalAppWidth = 1<<30; 6709 displayInfo.smallestNominalAppHeight = 1<<30; 6710 displayInfo.largestNominalAppWidth = 0; 6711 displayInfo.largestNominalAppHeight = 0; 6712 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6713 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6714 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6715 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6716 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6717 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6718 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6719 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6720 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6721 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6722 outConfig.screenLayout = sl; 6723 } 6724 6725 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6726 int dw, int dh) { 6727 // TODO: Multidisplay: for now only use with default display. 6728 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6729 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6730 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6731 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6732 if (curSize == 0 || size < curSize) { 6733 curSize = size; 6734 } 6735 return curSize; 6736 } 6737 6738 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6739 // TODO: Multidisplay: for now only use with default display. 6740 mTmpDisplayMetrics.setTo(dm); 6741 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6742 final int unrotDw, unrotDh; 6743 if (rotated) { 6744 unrotDw = dh; 6745 unrotDh = dw; 6746 } else { 6747 unrotDw = dw; 6748 unrotDh = dh; 6749 } 6750 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6751 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6752 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6753 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6754 return sw; 6755 } 6756 6757 boolean computeScreenConfigurationLocked(Configuration config) { 6758 if (!mDisplayReady) { 6759 return false; 6760 } 6761 6762 // TODO(multidisplay): For now, apply Configuration to main screen only. 6763 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6764 6765 // Use the effective "visual" dimensions based on current rotation 6766 final boolean rotated = (mRotation == Surface.ROTATION_90 6767 || mRotation == Surface.ROTATION_270); 6768 final int realdw = rotated ? 6769 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6770 final int realdh = rotated ? 6771 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6772 int dw = realdw; 6773 int dh = realdh; 6774 6775 if (mAltOrientation) { 6776 if (realdw > realdh) { 6777 // Turn landscape into portrait. 6778 int maxw = (int)(realdh/1.3f); 6779 if (maxw < realdw) { 6780 dw = maxw; 6781 } 6782 } else { 6783 // Turn portrait into landscape. 6784 int maxh = (int)(realdw/1.3f); 6785 if (maxh < realdh) { 6786 dh = maxh; 6787 } 6788 } 6789 } 6790 6791 if (config != null) { 6792 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6793 Configuration.ORIENTATION_LANDSCAPE; 6794 } 6795 6796 // Update application display metrics. 6797 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6798 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6799 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6800 synchronized(displayContent.mDisplaySizeLock) { 6801 displayInfo.rotation = mRotation; 6802 displayInfo.logicalWidth = dw; 6803 displayInfo.logicalHeight = dh; 6804 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6805 displayInfo.appWidth = appWidth; 6806 displayInfo.appHeight = appHeight; 6807 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 6808 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 6809 displayInfo.getAppMetrics(mDisplayMetrics); 6810 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 6811 displayContent.getDisplayId(), displayInfo); 6812 } 6813 if (false) { 6814 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6815 } 6816 6817 final DisplayMetrics dm = mDisplayMetrics; 6818 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6819 mCompatDisplayMetrics); 6820 6821 if (config != null) { 6822 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6823 / dm.density); 6824 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6825 / dm.density); 6826 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6827 6828 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6829 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6830 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6831 config.densityDpi = displayContent.mBaseDisplayDensity; 6832 6833 // Update the configuration based on available input devices, lid switch, 6834 // and platform configuration. 6835 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6836 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6837 config.navigation = Configuration.NAVIGATION_NONAV; 6838 6839 int keyboardPresence = 0; 6840 int navigationPresence = 0; 6841 final InputDevice[] devices = mInputManager.getInputDevices(); 6842 final int len = devices.length; 6843 for (int i = 0; i < len; i++) { 6844 InputDevice device = devices[i]; 6845 if (!device.isVirtual()) { 6846 final int sources = device.getSources(); 6847 final int presenceFlag = device.isExternal() ? 6848 WindowManagerPolicy.PRESENCE_EXTERNAL : 6849 WindowManagerPolicy.PRESENCE_INTERNAL; 6850 6851 if (mIsTouchDevice) { 6852 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6853 InputDevice.SOURCE_TOUCHSCREEN) { 6854 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6855 } 6856 } else { 6857 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6858 } 6859 6860 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6861 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6862 navigationPresence |= presenceFlag; 6863 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6864 && config.navigation == Configuration.NAVIGATION_NONAV) { 6865 config.navigation = Configuration.NAVIGATION_DPAD; 6866 navigationPresence |= presenceFlag; 6867 } 6868 6869 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6870 config.keyboard = Configuration.KEYBOARD_QWERTY; 6871 keyboardPresence |= presenceFlag; 6872 } 6873 } 6874 } 6875 6876 // Determine whether a hard keyboard is available and enabled. 6877 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6878 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6879 mHardKeyboardAvailable = hardKeyboardAvailable; 6880 mHardKeyboardEnabled = hardKeyboardAvailable; 6881 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6882 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6883 } 6884 if (!mHardKeyboardEnabled) { 6885 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6886 } 6887 6888 // Let the policy update hidden states. 6889 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6890 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6891 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6892 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6893 } 6894 6895 return true; 6896 } 6897 6898 public boolean isHardKeyboardAvailable() { 6899 synchronized (mWindowMap) { 6900 return mHardKeyboardAvailable; 6901 } 6902 } 6903 6904 public boolean isHardKeyboardEnabled() { 6905 synchronized (mWindowMap) { 6906 return mHardKeyboardEnabled; 6907 } 6908 } 6909 6910 public void setHardKeyboardEnabled(boolean enabled) { 6911 synchronized (mWindowMap) { 6912 if (mHardKeyboardEnabled != enabled) { 6913 mHardKeyboardEnabled = enabled; 6914 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6915 } 6916 } 6917 } 6918 6919 public void setOnHardKeyboardStatusChangeListener( 6920 OnHardKeyboardStatusChangeListener listener) { 6921 synchronized (mWindowMap) { 6922 mHardKeyboardStatusChangeListener = listener; 6923 } 6924 } 6925 6926 void notifyHardKeyboardStatusChange() { 6927 final boolean available, enabled; 6928 final OnHardKeyboardStatusChangeListener listener; 6929 synchronized (mWindowMap) { 6930 listener = mHardKeyboardStatusChangeListener; 6931 available = mHardKeyboardAvailable; 6932 enabled = mHardKeyboardEnabled; 6933 } 6934 if (listener != null) { 6935 listener.onHardKeyboardStatusChange(available, enabled); 6936 } 6937 } 6938 6939 // ------------------------------------------------------------- 6940 // Drag and drop 6941 // ------------------------------------------------------------- 6942 6943 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6944 int flags, int width, int height, Surface outSurface) { 6945 if (DEBUG_DRAG) { 6946 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6947 + " flags=" + Integer.toHexString(flags) + " win=" + window 6948 + " asbinder=" + window.asBinder()); 6949 } 6950 6951 final int callerPid = Binder.getCallingPid(); 6952 final long origId = Binder.clearCallingIdentity(); 6953 IBinder token = null; 6954 6955 try { 6956 synchronized (mWindowMap) { 6957 try { 6958 if (mDragState == null) { 6959 // TODO(multi-display): support other displays 6960 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6961 final Display display = displayContent.getDisplay(); 6962 SurfaceControl surface = new SurfaceControl(session, "drag surface", 6963 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 6964 surface.setLayerStack(display.getLayerStack()); 6965 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6966 + surface + ": CREATE"); 6967 outSurface.copyFrom(surface); 6968 final IBinder winBinder = window.asBinder(); 6969 token = new Binder(); 6970 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6971 token = mDragState.mToken = new Binder(); 6972 6973 // 5 second timeout for this window to actually begin the drag 6974 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6975 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6976 mH.sendMessageDelayed(msg, 5000); 6977 } else { 6978 Slog.w(TAG, "Drag already in progress"); 6979 } 6980 } catch (OutOfResourcesException e) { 6981 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6982 if (mDragState != null) { 6983 mDragState.reset(); 6984 mDragState = null; 6985 } 6986 } 6987 } 6988 } finally { 6989 Binder.restoreCallingIdentity(origId); 6990 } 6991 6992 return token; 6993 } 6994 6995 // ------------------------------------------------------------- 6996 // Input Events and Focus Management 6997 // ------------------------------------------------------------- 6998 6999 final InputMonitor mInputMonitor = new InputMonitor(this); 7000 private boolean mEventDispatchingEnabled; 7001 7002 @Override 7003 public void pauseKeyDispatching(IBinder _token) { 7004 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7005 "pauseKeyDispatching()")) { 7006 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7007 } 7008 7009 synchronized (mWindowMap) { 7010 WindowToken token = mTokenMap.get(_token); 7011 if (token != null) { 7012 mInputMonitor.pauseDispatchingLw(token); 7013 } 7014 } 7015 } 7016 7017 @Override 7018 public void resumeKeyDispatching(IBinder _token) { 7019 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7020 "resumeKeyDispatching()")) { 7021 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7022 } 7023 7024 synchronized (mWindowMap) { 7025 WindowToken token = mTokenMap.get(_token); 7026 if (token != null) { 7027 mInputMonitor.resumeDispatchingLw(token); 7028 } 7029 } 7030 } 7031 7032 @Override 7033 public void setEventDispatching(boolean enabled) { 7034 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7035 "setEventDispatching()")) { 7036 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7037 } 7038 7039 synchronized (mWindowMap) { 7040 mEventDispatchingEnabled = enabled; 7041 if (mDisplayEnabled) { 7042 mInputMonitor.setEventDispatchingLw(enabled); 7043 } 7044 } 7045 } 7046 7047 @Override 7048 public IBinder getFocusedWindowToken() { 7049 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 7050 "getFocusedWindowToken()")) { 7051 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 7052 } 7053 synchronized (mWindowMap) { 7054 WindowState windowState = getFocusedWindowLocked(); 7055 if (windowState != null) { 7056 return windowState.mClient.asBinder(); 7057 } 7058 return null; 7059 } 7060 } 7061 7062 private WindowState getFocusedWindow() { 7063 synchronized (mWindowMap) { 7064 return getFocusedWindowLocked(); 7065 } 7066 } 7067 7068 private WindowState getFocusedWindowLocked() { 7069 return mCurrentFocus; 7070 } 7071 7072 public boolean detectSafeMode() { 7073 if (!mInputMonitor.waitForInputDevicesReady( 7074 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7075 Slog.w(TAG, "Devices still not ready after waiting " 7076 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7077 + " milliseconds before attempting to detect safe mode."); 7078 } 7079 7080 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7081 KeyEvent.KEYCODE_MENU); 7082 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7083 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7084 KeyEvent.KEYCODE_DPAD_CENTER); 7085 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7086 InputManagerService.BTN_MOUSE); 7087 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7088 KeyEvent.KEYCODE_VOLUME_DOWN); 7089 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7090 || volumeDownState > 0; 7091 try { 7092 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7093 mSafeMode = true; 7094 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7095 } 7096 } catch (IllegalArgumentException e) { 7097 } 7098 if (mSafeMode) { 7099 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7100 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7101 } else { 7102 Log.i(TAG, "SAFE MODE not enabled"); 7103 } 7104 mPolicy.setSafeMode(mSafeMode); 7105 return mSafeMode; 7106 } 7107 7108 public void displayReady() { 7109 displayReady(Display.DEFAULT_DISPLAY); 7110 7111 synchronized(mWindowMap) { 7112 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7113 readForcedDisplaySizeAndDensityLocked(displayContent); 7114 mDisplayReady = true; 7115 } 7116 7117 try { 7118 mActivityManager.updateConfiguration(null); 7119 } catch (RemoteException e) { 7120 } 7121 7122 synchronized(mWindowMap) { 7123 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7124 PackageManager.FEATURE_TOUCHSCREEN); 7125 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7126 } 7127 7128 try { 7129 mActivityManager.updateConfiguration(null); 7130 } catch (RemoteException e) { 7131 } 7132 } 7133 7134 private void displayReady(int displayId) { 7135 synchronized(mWindowMap) { 7136 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7137 if (displayContent != null) { 7138 mAnimator.addDisplayLocked(displayId); 7139 synchronized(displayContent.mDisplaySizeLock) { 7140 // Bootstrap the default logical display from the display manager. 7141 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7142 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); 7143 if (newDisplayInfo != null) { 7144 displayInfo.copyFrom(newDisplayInfo); 7145 } 7146 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7147 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7148 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7149 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7150 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7151 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7152 displayContent.mBaseDisplayRect.set(0, 0, 7153 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7154 } 7155 } 7156 } 7157 } 7158 7159 public void systemReady() { 7160 mPolicy.systemReady(); 7161 } 7162 7163 // ------------------------------------------------------------- 7164 // Async Handler 7165 // ------------------------------------------------------------- 7166 7167 final class H extends Handler { 7168 public static final int REPORT_FOCUS_CHANGE = 2; 7169 public static final int REPORT_LOSING_FOCUS = 3; 7170 public static final int DO_TRAVERSAL = 4; 7171 public static final int ADD_STARTING = 5; 7172 public static final int REMOVE_STARTING = 6; 7173 public static final int FINISHED_STARTING = 7; 7174 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7175 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7176 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7177 7178 public static final int APP_TRANSITION_TIMEOUT = 13; 7179 public static final int PERSIST_ANIMATION_SCALE = 14; 7180 public static final int FORCE_GC = 15; 7181 public static final int ENABLE_SCREEN = 16; 7182 public static final int APP_FREEZE_TIMEOUT = 17; 7183 public static final int SEND_NEW_CONFIGURATION = 18; 7184 public static final int REPORT_WINDOWS_CHANGE = 19; 7185 public static final int DRAG_START_TIMEOUT = 20; 7186 public static final int DRAG_END_TIMEOUT = 21; 7187 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7188 public static final int BOOT_TIMEOUT = 23; 7189 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7190 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7191 public static final int DO_ANIMATION_CALLBACK = 26; 7192 7193 public static final int DO_DISPLAY_ADDED = 27; 7194 public static final int DO_DISPLAY_REMOVED = 28; 7195 public static final int DO_DISPLAY_CHANGED = 29; 7196 7197 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7198 public static final int TAP_OUTSIDE_STACK = 31; 7199 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7200 7201 public static final int REMOVE_STARTING_TIMEOUT = 33; 7202 7203 public static final int SHOW_DISPLAY_MASK = 34; 7204 public static final int ALL_WINDOWS_DRAWN = 35; 7205 7206 @Override 7207 public void handleMessage(Message msg) { 7208 if (DEBUG_WINDOW_TRACE) { 7209 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7210 } 7211 switch (msg.what) { 7212 case REPORT_FOCUS_CHANGE: { 7213 WindowState lastFocus; 7214 WindowState newFocus; 7215 7216 synchronized(mWindowMap) { 7217 lastFocus = mLastFocus; 7218 newFocus = mCurrentFocus; 7219 if (lastFocus == newFocus) { 7220 // Focus is not changing, so nothing to do. 7221 return; 7222 } 7223 mLastFocus = newFocus; 7224 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7225 " to " + newFocus); 7226 if (newFocus != null && lastFocus != null 7227 && !newFocus.isDisplayedLw()) { 7228 //Slog.i(TAG, "Delaying loss of focus..."); 7229 mLosingFocus.add(lastFocus); 7230 lastFocus = null; 7231 } 7232 } 7233 7234 //System.out.println("Changing focus from " + lastFocus 7235 // + " to " + newFocus); 7236 if (newFocus != null) { 7237 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7238 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7239 notifyFocusChanged(); 7240 } 7241 7242 if (lastFocus != null) { 7243 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7244 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7245 } 7246 } break; 7247 7248 case REPORT_LOSING_FOCUS: { 7249 ArrayList<WindowState> losers; 7250 7251 synchronized(mWindowMap) { 7252 losers = mLosingFocus; 7253 mLosingFocus = new ArrayList<WindowState>(); 7254 } 7255 7256 final int N = losers.size(); 7257 for (int i=0; i<N; i++) { 7258 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7259 losers.get(i)); 7260 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7261 } 7262 } break; 7263 7264 case DO_TRAVERSAL: { 7265 synchronized(mWindowMap) { 7266 mTraversalScheduled = false; 7267 performLayoutAndPlaceSurfacesLocked(); 7268 } 7269 } break; 7270 7271 case ADD_STARTING: { 7272 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7273 final StartingData sd = wtoken.startingData; 7274 7275 if (sd == null) { 7276 // Animation has been canceled... do nothing. 7277 return; 7278 } 7279 7280 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7281 + wtoken + ": pkg=" + sd.pkg); 7282 7283 View view = null; 7284 try { 7285 view = mPolicy.addStartingWindow( 7286 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7287 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7288 } catch (Exception e) { 7289 Slog.w(TAG, "Exception when adding starting window", e); 7290 } 7291 7292 if (view != null) { 7293 boolean abort = false; 7294 7295 synchronized(mWindowMap) { 7296 if (wtoken.removed || wtoken.startingData == null) { 7297 // If the window was successfully added, then 7298 // we need to remove it. 7299 if (wtoken.startingWindow != null) { 7300 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7301 "Aborted starting " + wtoken 7302 + ": removed=" + wtoken.removed 7303 + " startingData=" + wtoken.startingData); 7304 removeStartingWindowTimeout(wtoken); 7305 wtoken.startingWindow = null; 7306 wtoken.startingData = null; 7307 abort = true; 7308 } 7309 } else { 7310 wtoken.startingView = view; 7311 } 7312 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7313 "Added starting " + wtoken 7314 + ": startingWindow=" 7315 + wtoken.startingWindow + " startingView=" 7316 + wtoken.startingView); 7317 } 7318 7319 if (abort) { 7320 try { 7321 mPolicy.removeStartingWindow(wtoken.token, view); 7322 } catch (Exception e) { 7323 Slog.w(TAG, "Exception when removing starting window", e); 7324 } 7325 } 7326 } 7327 } break; 7328 7329 case REMOVE_STARTING_TIMEOUT: { 7330 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7331 Slog.e(TAG, "Starting window " + wtoken + " timed out"); 7332 // Fall through. 7333 } 7334 case REMOVE_STARTING: { 7335 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7336 IBinder token = null; 7337 View view = null; 7338 synchronized (mWindowMap) { 7339 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7340 + wtoken + ": startingWindow=" 7341 + wtoken.startingWindow + " startingView=" 7342 + wtoken.startingView); 7343 if (wtoken.startingWindow != null) { 7344 view = wtoken.startingView; 7345 token = wtoken.token; 7346 wtoken.startingData = null; 7347 wtoken.startingView = null; 7348 wtoken.startingWindow = null; 7349 wtoken.startingDisplayed = false; 7350 } 7351 } 7352 if (view != null) { 7353 try { 7354 mPolicy.removeStartingWindow(token, view); 7355 } catch (Exception e) { 7356 Slog.w(TAG, "Exception when removing starting window", e); 7357 } 7358 } 7359 } break; 7360 7361 case FINISHED_STARTING: { 7362 IBinder token = null; 7363 View view = null; 7364 while (true) { 7365 synchronized (mWindowMap) { 7366 final int N = mFinishedStarting.size(); 7367 if (N <= 0) { 7368 break; 7369 } 7370 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7371 7372 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7373 "Finished starting " + wtoken 7374 + ": startingWindow=" + wtoken.startingWindow 7375 + " startingView=" + wtoken.startingView); 7376 7377 if (wtoken.startingWindow == null) { 7378 continue; 7379 } 7380 7381 view = wtoken.startingView; 7382 token = wtoken.token; 7383 wtoken.startingData = null; 7384 wtoken.startingView = null; 7385 wtoken.startingWindow = null; 7386 wtoken.startingDisplayed = false; 7387 } 7388 7389 try { 7390 mPolicy.removeStartingWindow(token, view); 7391 } catch (Exception e) { 7392 Slog.w(TAG, "Exception when removing starting window", e); 7393 } 7394 } 7395 } break; 7396 7397 case REPORT_APPLICATION_TOKEN_DRAWN: { 7398 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7399 7400 try { 7401 if (DEBUG_VISIBILITY) Slog.v( 7402 TAG, "Reporting drawn in " + wtoken); 7403 wtoken.appToken.windowsDrawn(); 7404 } catch (RemoteException ex) { 7405 } 7406 } break; 7407 7408 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7409 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7410 7411 boolean nowVisible = msg.arg1 != 0; 7412 boolean nowGone = msg.arg2 != 0; 7413 7414 try { 7415 if (DEBUG_VISIBILITY) Slog.v( 7416 TAG, "Reporting visible in " + wtoken 7417 + " visible=" + nowVisible 7418 + " gone=" + nowGone); 7419 if (nowVisible) { 7420 wtoken.appToken.windowsVisible(); 7421 } else { 7422 wtoken.appToken.windowsGone(); 7423 } 7424 } catch (RemoteException ex) { 7425 } 7426 } break; 7427 7428 case WINDOW_FREEZE_TIMEOUT: { 7429 // TODO(multidisplay): Can non-default displays rotate? 7430 synchronized (mWindowMap) { 7431 Slog.w(TAG, "Window freeze timeout expired."); 7432 final WindowList windows = getDefaultWindowListLocked(); 7433 int i = windows.size(); 7434 while (i > 0) { 7435 i--; 7436 WindowState w = windows.get(i); 7437 if (w.mOrientationChanging) { 7438 w.mOrientationChanging = false; 7439 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7440 - mDisplayFreezeTime); 7441 Slog.w(TAG, "Force clearing orientation change: " + w); 7442 } 7443 } 7444 performLayoutAndPlaceSurfacesLocked(); 7445 } 7446 break; 7447 } 7448 7449 case APP_TRANSITION_TIMEOUT: { 7450 synchronized (mWindowMap) { 7451 if (mAppTransition.isTransitionSet()) { 7452 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7453 mAppTransition.setTimeout(); 7454 performLayoutAndPlaceSurfacesLocked(); 7455 } 7456 } 7457 break; 7458 } 7459 7460 case PERSIST_ANIMATION_SCALE: { 7461 Settings.Global.putFloat(mContext.getContentResolver(), 7462 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 7463 Settings.Global.putFloat(mContext.getContentResolver(), 7464 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 7465 Settings.Global.putFloat(mContext.getContentResolver(), 7466 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 7467 break; 7468 } 7469 7470 case FORCE_GC: { 7471 synchronized (mWindowMap) { 7472 // Since we're holding both mWindowMap and mAnimator we don't need to 7473 // hold mAnimator.mLayoutToAnim. 7474 if (mAnimator.mAnimating || mAnimationScheduled) { 7475 // If we are animating, don't do the gc now but 7476 // delay a bit so we don't interrupt the animation. 7477 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7478 return; 7479 } 7480 // If we are currently rotating the display, it will 7481 // schedule a new message when done. 7482 if (mDisplayFrozen) { 7483 return; 7484 } 7485 } 7486 Runtime.getRuntime().gc(); 7487 break; 7488 } 7489 7490 case ENABLE_SCREEN: { 7491 performEnableScreen(); 7492 break; 7493 } 7494 7495 case APP_FREEZE_TIMEOUT: { 7496 synchronized (mWindowMap) { 7497 Slog.w(TAG, "App freeze timeout expired."); 7498 final int numStacks = mStackIdToStack.size(); 7499 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 7500 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 7501 final ArrayList<Task> tasks = stack.getTasks(); 7502 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7503 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7504 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7505 AppWindowToken tok = tokens.get(tokenNdx); 7506 if (tok.mAppAnimator.freezingScreen) { 7507 Slog.w(TAG, "Force clearing freeze: " + tok); 7508 unsetAppFreezingScreenLocked(tok, true, true); 7509 } 7510 } 7511 } 7512 } 7513 } 7514 break; 7515 } 7516 7517 case CLIENT_FREEZE_TIMEOUT: { 7518 synchronized (mWindowMap) { 7519 if (mClientFreezingScreen) { 7520 mClientFreezingScreen = false; 7521 mLastFinishedFreezeSource = "client-timeout"; 7522 stopFreezingDisplayLocked(); 7523 } 7524 } 7525 break; 7526 } 7527 7528 case SEND_NEW_CONFIGURATION: { 7529 removeMessages(SEND_NEW_CONFIGURATION); 7530 sendNewConfiguration(); 7531 break; 7532 } 7533 7534 case REPORT_WINDOWS_CHANGE: { 7535 if (mWindowsChanged) { 7536 synchronized (mWindowMap) { 7537 mWindowsChanged = false; 7538 } 7539 notifyWindowsChanged(); 7540 } 7541 break; 7542 } 7543 7544 case DRAG_START_TIMEOUT: { 7545 IBinder win = (IBinder)msg.obj; 7546 if (DEBUG_DRAG) { 7547 Slog.w(TAG, "Timeout starting drag by win " + win); 7548 } 7549 synchronized (mWindowMap) { 7550 // !!! TODO: ANR the app that has failed to start the drag in time 7551 if (mDragState != null) { 7552 mDragState.unregister(); 7553 mInputMonitor.updateInputWindowsLw(true /*force*/); 7554 mDragState.reset(); 7555 mDragState = null; 7556 } 7557 } 7558 break; 7559 } 7560 7561 case DRAG_END_TIMEOUT: { 7562 IBinder win = (IBinder)msg.obj; 7563 if (DEBUG_DRAG) { 7564 Slog.w(TAG, "Timeout ending drag to win " + win); 7565 } 7566 synchronized (mWindowMap) { 7567 // !!! TODO: ANR the drag-receiving app 7568 if (mDragState != null) { 7569 mDragState.mDragResult = false; 7570 mDragState.endDragLw(); 7571 } 7572 } 7573 break; 7574 } 7575 7576 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7577 notifyHardKeyboardStatusChange(); 7578 break; 7579 } 7580 7581 case BOOT_TIMEOUT: { 7582 performBootTimeout(); 7583 break; 7584 } 7585 7586 case WAITING_FOR_DRAWN_TIMEOUT: { 7587 IRemoteCallback callback = null; 7588 synchronized (mWindowMap) { 7589 Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 7590 mWaitingForDrawn.clear(); 7591 callback = mWaitingForDrawnCallback; 7592 mWaitingForDrawnCallback = null; 7593 } 7594 if (callback != null) { 7595 try { 7596 callback.sendResult(null); 7597 } catch (RemoteException e) { 7598 } 7599 } 7600 break; 7601 } 7602 7603 case SHOW_STRICT_MODE_VIOLATION: { 7604 showStrictModeViolation(msg.arg1, msg.arg2); 7605 break; 7606 } 7607 7608 case SHOW_DISPLAY_MASK: { 7609 showCircularMask(); 7610 break; 7611 } 7612 7613 case DO_ANIMATION_CALLBACK: { 7614 try { 7615 ((IRemoteCallback)msg.obj).sendResult(null); 7616 } catch (RemoteException e) { 7617 } 7618 break; 7619 } 7620 7621 case DO_DISPLAY_ADDED: 7622 handleDisplayAdded(msg.arg1); 7623 break; 7624 7625 case DO_DISPLAY_REMOVED: 7626 synchronized (mWindowMap) { 7627 handleDisplayRemovedLocked(msg.arg1); 7628 } 7629 break; 7630 7631 case DO_DISPLAY_CHANGED: 7632 synchronized (mWindowMap) { 7633 handleDisplayChangedLocked(msg.arg1); 7634 } 7635 break; 7636 7637 case TAP_OUTSIDE_STACK: { 7638 int stackId; 7639 synchronized (mWindowMap) { 7640 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7641 } 7642 if (stackId >= 0) { 7643 try { 7644 mActivityManager.setFocusedStack(stackId); 7645 } catch (RemoteException e) { 7646 } 7647 } 7648 } 7649 break; 7650 case NOTIFY_ACTIVITY_DRAWN: 7651 try { 7652 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7653 } catch (RemoteException e) { 7654 } 7655 break; 7656 case ALL_WINDOWS_DRAWN: { 7657 IRemoteCallback callback; 7658 synchronized (mWindowMap) { 7659 callback = mWaitingForDrawnCallback; 7660 mWaitingForDrawnCallback = null; 7661 } 7662 if (callback != null) { 7663 try { 7664 callback.sendResult(null); 7665 } catch (RemoteException e) { 7666 } 7667 } 7668 } 7669 } 7670 if (DEBUG_WINDOW_TRACE) { 7671 Slog.v(TAG, "handleMessage: exit"); 7672 } 7673 } 7674 } 7675 7676 // ------------------------------------------------------------- 7677 // IWindowManager API 7678 // ------------------------------------------------------------- 7679 7680 @Override 7681 public IWindowSession openSession(IInputMethodClient client, 7682 IInputContext inputContext) { 7683 if (client == null) throw new IllegalArgumentException("null client"); 7684 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7685 Session session = new Session(this, client, inputContext); 7686 return session; 7687 } 7688 7689 @Override 7690 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7691 synchronized (mWindowMap) { 7692 // The focus for the client is the window immediately below 7693 // where we would place the input method window. 7694 int idx = findDesiredInputMethodWindowIndexLocked(false); 7695 if (idx > 0) { 7696 // TODO(multidisplay): IMEs are only supported on the default display. 7697 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7698 if (DEBUG_INPUT_METHOD) { 7699 Slog.i(TAG, "Desired input method target: " + imFocus); 7700 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7701 Slog.i(TAG, "Last focus: " + mLastFocus); 7702 } 7703 if (imFocus != null) { 7704 // This may be a starting window, in which case we still want 7705 // to count it as okay. 7706 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7707 && imFocus.mAppToken != null) { 7708 // The client has definitely started, so it really should 7709 // have a window in this app token. Let's look for it. 7710 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7711 WindowState w = imFocus.mAppToken.windows.get(i); 7712 if (w != imFocus) { 7713 Log.i(TAG, "Switching to real app window: " + w); 7714 imFocus = w; 7715 break; 7716 } 7717 } 7718 } 7719 if (DEBUG_INPUT_METHOD) { 7720 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7721 if (imFocus.mSession.mClient != null) { 7722 Slog.i(TAG, "IM target client binder: " 7723 + imFocus.mSession.mClient.asBinder()); 7724 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7725 } 7726 } 7727 if (imFocus.mSession.mClient != null && 7728 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7729 return true; 7730 } 7731 } 7732 } 7733 7734 // Okay, how about this... what is the current focus? 7735 // It seems in some cases we may not have moved the IM 7736 // target window, such as when it was in a pop-up window, 7737 // so let's also look at the current focus. (An example: 7738 // go to Gmail, start searching so the keyboard goes up, 7739 // press home. Sometimes the IME won't go down.) 7740 // Would be nice to fix this more correctly, but it's 7741 // way at the end of a release, and this should be good enough. 7742 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7743 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7744 return true; 7745 } 7746 } 7747 return false; 7748 } 7749 7750 @Override 7751 public void getInitialDisplaySize(int displayId, Point size) { 7752 synchronized (mWindowMap) { 7753 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7754 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7755 synchronized(displayContent.mDisplaySizeLock) { 7756 size.x = displayContent.mInitialDisplayWidth; 7757 size.y = displayContent.mInitialDisplayHeight; 7758 } 7759 } 7760 } 7761 } 7762 7763 @Override 7764 public void getBaseDisplaySize(int displayId, Point size) { 7765 synchronized (mWindowMap) { 7766 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7767 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7768 synchronized(displayContent.mDisplaySizeLock) { 7769 size.x = displayContent.mBaseDisplayWidth; 7770 size.y = displayContent.mBaseDisplayHeight; 7771 } 7772 } 7773 } 7774 } 7775 7776 @Override 7777 public void setForcedDisplaySize(int displayId, int width, int height) { 7778 if (mContext.checkCallingOrSelfPermission( 7779 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7780 PackageManager.PERMISSION_GRANTED) { 7781 throw new SecurityException("Must hold permission " + 7782 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7783 } 7784 if (displayId != Display.DEFAULT_DISPLAY) { 7785 throw new IllegalArgumentException("Can only set the default display"); 7786 } 7787 final long ident = Binder.clearCallingIdentity(); 7788 try { 7789 synchronized(mWindowMap) { 7790 // Set some sort of reasonable bounds on the size of the display that we 7791 // will try to emulate. 7792 final int MIN_WIDTH = 200; 7793 final int MIN_HEIGHT = 200; 7794 final int MAX_SCALE = 2; 7795 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7796 if (displayContent != null) { 7797 width = Math.min(Math.max(width, MIN_WIDTH), 7798 displayContent.mInitialDisplayWidth * MAX_SCALE); 7799 height = Math.min(Math.max(height, MIN_HEIGHT), 7800 displayContent.mInitialDisplayHeight * MAX_SCALE); 7801 setForcedDisplaySizeLocked(displayContent, width, height); 7802 Settings.Global.putString(mContext.getContentResolver(), 7803 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7804 } 7805 } 7806 } finally { 7807 Binder.restoreCallingIdentity(ident); 7808 } 7809 } 7810 7811 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7812 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7813 Settings.Global.DISPLAY_SIZE_FORCED); 7814 if (sizeStr == null || sizeStr.length() == 0) { 7815 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7816 } 7817 if (sizeStr != null && sizeStr.length() > 0) { 7818 final int pos = sizeStr.indexOf(','); 7819 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7820 int width, height; 7821 try { 7822 width = Integer.parseInt(sizeStr.substring(0, pos)); 7823 height = Integer.parseInt(sizeStr.substring(pos+1)); 7824 synchronized(displayContent.mDisplaySizeLock) { 7825 if (displayContent.mBaseDisplayWidth != width 7826 || displayContent.mBaseDisplayHeight != height) { 7827 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7828 displayContent.mBaseDisplayWidth = width; 7829 displayContent.mBaseDisplayHeight = height; 7830 } 7831 } 7832 } catch (NumberFormatException ex) { 7833 } 7834 } 7835 } 7836 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7837 Settings.Global.DISPLAY_DENSITY_FORCED); 7838 if (densityStr == null || densityStr.length() == 0) { 7839 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7840 } 7841 if (densityStr != null && densityStr.length() > 0) { 7842 int density; 7843 try { 7844 density = Integer.parseInt(densityStr); 7845 synchronized(displayContent.mDisplaySizeLock) { 7846 if (displayContent.mBaseDisplayDensity != density) { 7847 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7848 displayContent.mBaseDisplayDensity = density; 7849 } 7850 } 7851 } catch (NumberFormatException ex) { 7852 } 7853 } 7854 } 7855 7856 // displayContent must not be null 7857 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7858 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7859 7860 synchronized(displayContent.mDisplaySizeLock) { 7861 displayContent.mBaseDisplayWidth = width; 7862 displayContent.mBaseDisplayHeight = height; 7863 } 7864 reconfigureDisplayLocked(displayContent); 7865 } 7866 7867 @Override 7868 public void clearForcedDisplaySize(int displayId) { 7869 if (mContext.checkCallingOrSelfPermission( 7870 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7871 PackageManager.PERMISSION_GRANTED) { 7872 throw new SecurityException("Must hold permission " + 7873 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7874 } 7875 if (displayId != Display.DEFAULT_DISPLAY) { 7876 throw new IllegalArgumentException("Can only set the default display"); 7877 } 7878 final long ident = Binder.clearCallingIdentity(); 7879 try { 7880 synchronized(mWindowMap) { 7881 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7882 if (displayContent != null) { 7883 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7884 displayContent.mInitialDisplayHeight); 7885 Settings.Global.putString(mContext.getContentResolver(), 7886 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7887 } 7888 } 7889 } finally { 7890 Binder.restoreCallingIdentity(ident); 7891 } 7892 } 7893 7894 @Override 7895 public int getInitialDisplayDensity(int displayId) { 7896 synchronized (mWindowMap) { 7897 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7898 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7899 synchronized(displayContent.mDisplaySizeLock) { 7900 return displayContent.mInitialDisplayDensity; 7901 } 7902 } 7903 } 7904 return -1; 7905 } 7906 7907 @Override 7908 public int getBaseDisplayDensity(int displayId) { 7909 synchronized (mWindowMap) { 7910 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7911 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7912 synchronized(displayContent.mDisplaySizeLock) { 7913 return displayContent.mBaseDisplayDensity; 7914 } 7915 } 7916 } 7917 return -1; 7918 } 7919 7920 @Override 7921 public void setForcedDisplayDensity(int displayId, int density) { 7922 if (mContext.checkCallingOrSelfPermission( 7923 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7924 PackageManager.PERMISSION_GRANTED) { 7925 throw new SecurityException("Must hold permission " + 7926 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7927 } 7928 if (displayId != Display.DEFAULT_DISPLAY) { 7929 throw new IllegalArgumentException("Can only set the default display"); 7930 } 7931 final long ident = Binder.clearCallingIdentity(); 7932 try { 7933 synchronized(mWindowMap) { 7934 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7935 if (displayContent != null) { 7936 setForcedDisplayDensityLocked(displayContent, density); 7937 Settings.Global.putString(mContext.getContentResolver(), 7938 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7939 } 7940 } 7941 } finally { 7942 Binder.restoreCallingIdentity(ident); 7943 } 7944 } 7945 7946 // displayContent must not be null 7947 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7948 Slog.i(TAG, "Using new display density: " + density); 7949 7950 synchronized(displayContent.mDisplaySizeLock) { 7951 displayContent.mBaseDisplayDensity = density; 7952 } 7953 reconfigureDisplayLocked(displayContent); 7954 } 7955 7956 @Override 7957 public void clearForcedDisplayDensity(int displayId) { 7958 if (mContext.checkCallingOrSelfPermission( 7959 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7960 PackageManager.PERMISSION_GRANTED) { 7961 throw new SecurityException("Must hold permission " + 7962 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7963 } 7964 if (displayId != Display.DEFAULT_DISPLAY) { 7965 throw new IllegalArgumentException("Can only set the default display"); 7966 } 7967 final long ident = Binder.clearCallingIdentity(); 7968 try { 7969 synchronized(mWindowMap) { 7970 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7971 if (displayContent != null) { 7972 setForcedDisplayDensityLocked(displayContent, 7973 displayContent.mInitialDisplayDensity); 7974 Settings.Global.putString(mContext.getContentResolver(), 7975 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7976 } 7977 } 7978 } finally { 7979 Binder.restoreCallingIdentity(ident); 7980 } 7981 } 7982 7983 // displayContent must not be null 7984 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7985 // TODO: Multidisplay: for now only use with default display. 7986 configureDisplayPolicyLocked(displayContent); 7987 displayContent.layoutNeeded = true; 7988 7989 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7990 mTempConfiguration.setToDefaults(); 7991 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7992 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7993 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7994 configChanged = true; 7995 } 7996 } 7997 7998 if (configChanged) { 7999 mWaitingForConfig = true; 8000 startFreezingDisplayLocked(false, 0, 0); 8001 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8002 } 8003 8004 performLayoutAndPlaceSurfacesLocked(); 8005 } 8006 8007 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8008 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8009 displayContent.mBaseDisplayWidth, 8010 displayContent.mBaseDisplayHeight, 8011 displayContent.mBaseDisplayDensity); 8012 8013 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8014 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8015 displayInfo.overscanLeft, displayInfo.overscanTop, 8016 displayInfo.overscanRight, displayInfo.overscanBottom); 8017 } 8018 8019 @Override 8020 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8021 if (mContext.checkCallingOrSelfPermission( 8022 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8023 PackageManager.PERMISSION_GRANTED) { 8024 throw new SecurityException("Must hold permission " + 8025 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8026 } 8027 final long ident = Binder.clearCallingIdentity(); 8028 try { 8029 synchronized(mWindowMap) { 8030 DisplayContent displayContent = getDisplayContentLocked(displayId); 8031 if (displayContent != null) { 8032 setOverscanLocked(displayContent, left, top, right, bottom); 8033 } 8034 } 8035 } finally { 8036 Binder.restoreCallingIdentity(ident); 8037 } 8038 } 8039 8040 private void setOverscanLocked(DisplayContent displayContent, 8041 int left, int top, int right, int bottom) { 8042 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8043 synchronized (displayContent.mDisplaySizeLock) { 8044 displayInfo.overscanLeft = left; 8045 displayInfo.overscanTop = top; 8046 displayInfo.overscanRight = right; 8047 displayInfo.overscanBottom = bottom; 8048 } 8049 8050 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 8051 mDisplaySettings.writeSettingsLocked(); 8052 8053 reconfigureDisplayLocked(displayContent); 8054 } 8055 8056 // ------------------------------------------------------------- 8057 // Internals 8058 // ------------------------------------------------------------- 8059 8060 final WindowState windowForClientLocked(Session session, IWindow client, 8061 boolean throwOnError) { 8062 return windowForClientLocked(session, client.asBinder(), throwOnError); 8063 } 8064 8065 final WindowState windowForClientLocked(Session session, IBinder client, 8066 boolean throwOnError) { 8067 WindowState win = mWindowMap.get(client); 8068 if (localLOGV) Slog.v( 8069 TAG, "Looking up client " + client + ": " + win); 8070 if (win == null) { 8071 RuntimeException ex = new IllegalArgumentException( 8072 "Requested window " + client + " does not exist"); 8073 if (throwOnError) { 8074 throw ex; 8075 } 8076 Slog.w(TAG, "Failed looking up window", ex); 8077 return null; 8078 } 8079 if (session != null && win.mSession != session) { 8080 RuntimeException ex = new IllegalArgumentException( 8081 "Requested window " + client + " is in session " + 8082 win.mSession + ", not " + session); 8083 if (throwOnError) { 8084 throw ex; 8085 } 8086 Slog.w(TAG, "Failed looking up window", ex); 8087 return null; 8088 } 8089 8090 return win; 8091 } 8092 8093 final void rebuildAppWindowListLocked() { 8094 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8095 } 8096 8097 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8098 final WindowList windows = displayContent.getWindowList(); 8099 int NW = windows.size(); 8100 int i; 8101 int lastBelow = -1; 8102 int numRemoved = 0; 8103 8104 if (mRebuildTmp.length < NW) { 8105 mRebuildTmp = new WindowState[NW+10]; 8106 } 8107 8108 // First remove all existing app windows. 8109 i=0; 8110 while (i < NW) { 8111 WindowState w = windows.get(i); 8112 if (w.mAppToken != null) { 8113 WindowState win = windows.remove(i); 8114 win.mRebuilding = true; 8115 mRebuildTmp[numRemoved] = win; 8116 mWindowsChanged = true; 8117 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8118 NW--; 8119 numRemoved++; 8120 continue; 8121 } else if (lastBelow == i-1) { 8122 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8123 lastBelow = i; 8124 } 8125 } 8126 i++; 8127 } 8128 8129 // Keep whatever windows were below the app windows still below, 8130 // by skipping them. 8131 lastBelow++; 8132 i = lastBelow; 8133 8134 // First add all of the exiting app tokens... these are no longer 8135 // in the main app list, but still have windows shown. We put them 8136 // in the back because now that the animation is over we no longer 8137 // will care about them. 8138 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8139 final int numStacks = stacks.size(); 8140 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8141 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8142 int NT = exitingAppTokens.size(); 8143 for (int j = 0; j < NT; j++) { 8144 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8145 } 8146 } 8147 8148 // And add in the still active app tokens in Z order. 8149 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8150 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8151 final int numTasks = tasks.size(); 8152 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8153 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8154 final int numTokens = tokens.size(); 8155 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8156 final AppWindowToken wtoken = tokens.get(tokenNdx); 8157 if (wtoken.mDeferRemoval) { 8158 continue; 8159 } 8160 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8161 } 8162 } 8163 } 8164 8165 i -= lastBelow; 8166 if (i != numRemoved) { 8167 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8168 numRemoved + " windows but added " + i, 8169 new RuntimeException("here").fillInStackTrace()); 8170 for (i=0; i<numRemoved; i++) { 8171 WindowState ws = mRebuildTmp[i]; 8172 if (ws.mRebuilding) { 8173 StringWriter sw = new StringWriter(); 8174 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8175 ws.dump(pw, "", true); 8176 pw.flush(); 8177 Slog.w(TAG, "This window was lost: " + ws); 8178 Slog.w(TAG, sw.toString()); 8179 ws.mWinAnimator.destroySurfaceLocked(); 8180 } 8181 } 8182 Slog.w(TAG, "Current app token list:"); 8183 dumpAppTokensLocked(); 8184 Slog.w(TAG, "Final window list:"); 8185 dumpWindowsLocked(); 8186 } 8187 } 8188 8189 private final void assignLayersLocked(WindowList windows) { 8190 int N = windows.size(); 8191 int curBaseLayer = 0; 8192 int curLayer = 0; 8193 int i; 8194 8195 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8196 new RuntimeException("here").fillInStackTrace()); 8197 8198 boolean anyLayerChanged = false; 8199 8200 for (i=0; i<N; i++) { 8201 final WindowState w = windows.get(i); 8202 final WindowStateAnimator winAnimator = w.mWinAnimator; 8203 boolean layerChanged = false; 8204 int oldLayer = w.mLayer; 8205 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8206 || (i > 0 && w.mIsWallpaper)) { 8207 curLayer += WINDOW_LAYER_MULTIPLIER; 8208 w.mLayer = curLayer; 8209 } else { 8210 curBaseLayer = curLayer = w.mBaseLayer; 8211 w.mLayer = curLayer; 8212 } 8213 if (w.mLayer != oldLayer) { 8214 layerChanged = true; 8215 anyLayerChanged = true; 8216 } 8217 final AppWindowToken wtoken = w.mAppToken; 8218 oldLayer = winAnimator.mAnimLayer; 8219 if (w.mTargetAppToken != null) { 8220 winAnimator.mAnimLayer = 8221 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8222 } else if (wtoken != null) { 8223 winAnimator.mAnimLayer = 8224 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8225 } else { 8226 winAnimator.mAnimLayer = w.mLayer; 8227 } 8228 if (w.mIsImWindow) { 8229 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8230 } else if (w.mIsWallpaper) { 8231 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8232 } 8233 if (winAnimator.mAnimLayer != oldLayer) { 8234 layerChanged = true; 8235 anyLayerChanged = true; 8236 } 8237 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8238 // Force an animation pass just to update the mDimLayer layer. 8239 scheduleAnimationLocked(); 8240 } 8241 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8242 + "mBase=" + w.mBaseLayer 8243 + " mLayer=" + w.mLayer 8244 + (wtoken == null ? 8245 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8246 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8247 //System.out.println( 8248 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8249 } 8250 8251 //TODO (multidisplay): Magnification is supported only for the default display. 8252 if (mDisplayMagnifier != null && anyLayerChanged 8253 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8254 mDisplayMagnifier.onWindowLayersChangedLocked(); 8255 } 8256 } 8257 8258 private final void performLayoutAndPlaceSurfacesLocked() { 8259 int loopCount = 6; 8260 do { 8261 mTraversalScheduled = false; 8262 performLayoutAndPlaceSurfacesLockedLoop(); 8263 mH.removeMessages(H.DO_TRAVERSAL); 8264 loopCount--; 8265 } while (mTraversalScheduled && loopCount > 0); 8266 mInnerFields.mWallpaperActionPending = false; 8267 } 8268 8269 private boolean mInLayout = false; 8270 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8271 if (mInLayout) { 8272 if (DEBUG) { 8273 throw new RuntimeException("Recursive call!"); 8274 } 8275 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8276 + Debug.getCallers(3)); 8277 return; 8278 } 8279 8280 if (mWaitingForConfig) { 8281 // Our configuration has changed (most likely rotation), but we 8282 // don't yet have the complete configuration to report to 8283 // applications. Don't do any window layout until we have it. 8284 return; 8285 } 8286 8287 if (!mDisplayReady) { 8288 // Not yet initialized, nothing to do. 8289 return; 8290 } 8291 8292 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8293 mInLayout = true; 8294 boolean recoveringMemory = false; 8295 8296 try { 8297 if (mForceRemoves != null) { 8298 recoveringMemory = true; 8299 // Wait a little bit for things to settle down, and off we go. 8300 for (int i=0; i<mForceRemoves.size(); i++) { 8301 WindowState ws = mForceRemoves.get(i); 8302 Slog.i(TAG, "Force removing: " + ws); 8303 removeWindowInnerLocked(ws.mSession, ws); 8304 } 8305 mForceRemoves = null; 8306 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8307 Object tmp = new Object(); 8308 synchronized (tmp) { 8309 try { 8310 tmp.wait(250); 8311 } catch (InterruptedException e) { 8312 } 8313 } 8314 } 8315 } catch (RuntimeException e) { 8316 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8317 } 8318 8319 try { 8320 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8321 8322 mInLayout = false; 8323 8324 if (needsLayout()) { 8325 if (++mLayoutRepeatCount < 6) { 8326 requestTraversalLocked(); 8327 } else { 8328 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8329 mLayoutRepeatCount = 0; 8330 } 8331 } else { 8332 mLayoutRepeatCount = 0; 8333 } 8334 8335 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8336 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8337 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8338 } 8339 } catch (RuntimeException e) { 8340 mInLayout = false; 8341 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8342 } 8343 8344 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8345 } 8346 8347 private final void performLayoutLockedInner(final DisplayContent displayContent, 8348 boolean initial, boolean updateInputWindows) { 8349 if (!displayContent.layoutNeeded) { 8350 return; 8351 } 8352 displayContent.layoutNeeded = false; 8353 WindowList windows = displayContent.getWindowList(); 8354 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8355 8356 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8357 final int dw = displayInfo.logicalWidth; 8358 final int dh = displayInfo.logicalHeight; 8359 8360 final int NFW = mFakeWindows.size(); 8361 for (int i=0; i<NFW; i++) { 8362 mFakeWindows.get(i).layout(dw, dh); 8363 } 8364 8365 final int N = windows.size(); 8366 int i; 8367 8368 if (DEBUG_LAYOUT) { 8369 Slog.v(TAG, "-------------------------------------"); 8370 Slog.v(TAG, "performLayout: needed=" 8371 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8372 } 8373 8374 WindowStateAnimator universeBackground = null; 8375 8376 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8377 if (isDefaultDisplay) { 8378 // Not needed on non-default displays. 8379 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8380 mScreenRect.set(0, 0, dw, dh); 8381 } 8382 8383 mPolicy.getContentRectLw(mTmpContentRect); 8384 displayContent.resize(mTmpContentRect); 8385 8386 int seq = mLayoutSeq+1; 8387 if (seq < 0) seq = 0; 8388 mLayoutSeq = seq; 8389 8390 boolean behindDream = false; 8391 8392 // First perform layout of any root windows (not attached 8393 // to another window). 8394 int topAttached = -1; 8395 for (i = N-1; i >= 0; i--) { 8396 final WindowState win = windows.get(i); 8397 8398 // Don't do layout of a window if it is not visible, or 8399 // soon won't be visible, to avoid wasting time and funky 8400 // changes while a window is animating away. 8401 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8402 || win.isGoneForLayoutLw(); 8403 8404 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8405 Slog.v(TAG, "1ST PASS " + win 8406 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8407 + " mLayoutAttached=" + win.mLayoutAttached 8408 + " screen changed=" + win.isConfigChanged()); 8409 final AppWindowToken atoken = win.mAppToken; 8410 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8411 + win.mViewVisibility + " mRelayoutCalled=" 8412 + win.mRelayoutCalled + " hidden=" 8413 + win.mRootToken.hidden + " hiddenRequested=" 8414 + (atoken != null && atoken.hiddenRequested) 8415 + " mAttachedHidden=" + win.mAttachedHidden); 8416 else Slog.v(TAG, " VIS: mViewVisibility=" 8417 + win.mViewVisibility + " mRelayoutCalled=" 8418 + win.mRelayoutCalled + " hidden=" 8419 + win.mRootToken.hidden + " hiddenRequested=" 8420 + (atoken != null && atoken.hiddenRequested) 8421 + " mAttachedHidden=" + win.mAttachedHidden); 8422 } 8423 8424 // If this view is GONE, then skip it -- keep the current 8425 // frame, and let the caller know so they can ignore it 8426 // if they want. (We do the normal layout for INVISIBLE 8427 // windows, since that means "perform layout as normal, 8428 // just don't display"). 8429 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8430 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8431 (win.mAttrs.type == TYPE_KEYGUARD || 8432 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8433 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8434 if (!win.mLayoutAttached) { 8435 if (initial) { 8436 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8437 win.mContentChanged = false; 8438 } 8439 if (win.mAttrs.type == TYPE_DREAM) { 8440 // Don't layout windows behind a dream, so that if it 8441 // does stuff like hide the status bar we won't get a 8442 // bad transition when it goes away. 8443 behindDream = true; 8444 } 8445 win.mLayoutNeeded = false; 8446 win.prelayout(); 8447 mPolicy.layoutWindowLw(win, win.mAttrs, null); 8448 win.mLayoutSeq = seq; 8449 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8450 + win.mFrame + " mContainingFrame=" 8451 + win.mContainingFrame + " mDisplayFrame=" 8452 + win.mDisplayFrame); 8453 } else { 8454 if (topAttached < 0) topAttached = i; 8455 } 8456 } 8457 if (win.mViewVisibility == View.VISIBLE 8458 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8459 && universeBackground == null) { 8460 universeBackground = win.mWinAnimator; 8461 } 8462 } 8463 8464 if (mAnimator.mUniverseBackground != universeBackground) { 8465 mFocusMayChange = true; 8466 mAnimator.mUniverseBackground = universeBackground; 8467 } 8468 8469 boolean attachedBehindDream = false; 8470 8471 // Now perform layout of attached windows, which usually 8472 // depend on the position of the window they are attached to. 8473 // XXX does not deal with windows that are attached to windows 8474 // that are themselves attached. 8475 for (i = topAttached; i >= 0; i--) { 8476 final WindowState win = windows.get(i); 8477 8478 if (win.mLayoutAttached) { 8479 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8480 + " mHaveFrame=" + win.mHaveFrame 8481 + " mViewVisibility=" + win.mViewVisibility 8482 + " mRelayoutCalled=" + win.mRelayoutCalled); 8483 // If this view is GONE, then skip it -- keep the current 8484 // frame, and let the caller know so they can ignore it 8485 // if they want. (We do the normal layout for INVISIBLE 8486 // windows, since that means "perform layout as normal, 8487 // just don't display"). 8488 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8489 continue; 8490 } 8491 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8492 || !win.mHaveFrame || win.mLayoutNeeded) { 8493 if (initial) { 8494 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8495 win.mContentChanged = false; 8496 } 8497 win.mLayoutNeeded = false; 8498 win.prelayout(); 8499 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 8500 win.mLayoutSeq = seq; 8501 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8502 + win.mFrame + " mContainingFrame=" 8503 + win.mContainingFrame + " mDisplayFrame=" 8504 + win.mDisplayFrame); 8505 } 8506 } else if (win.mAttrs.type == TYPE_DREAM) { 8507 // Don't layout windows behind a dream, so that if it 8508 // does stuff like hide the status bar we won't get a 8509 // bad transition when it goes away. 8510 attachedBehindDream = behindDream; 8511 } 8512 } 8513 8514 // Window frames may have changed. Tell the input dispatcher about it. 8515 mInputMonitor.setUpdateInputWindowsNeededLw(); 8516 if (updateInputWindows) { 8517 mInputMonitor.updateInputWindowsLw(false /*force*/); 8518 } 8519 8520 mPolicy.finishLayoutLw(); 8521 } 8522 8523 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8524 // If the screen is currently frozen or off, then keep 8525 // it frozen/off until this window draws at its new 8526 // orientation. 8527 if (!okToDisplay()) { 8528 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8529 w.mOrientationChanging = true; 8530 w.mLastFreezeDuration = 0; 8531 mInnerFields.mOrientationChangeComplete = false; 8532 if (!mWindowsFreezingScreen) { 8533 mWindowsFreezingScreen = true; 8534 // XXX should probably keep timeout from 8535 // when we first froze the display. 8536 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8537 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8538 WINDOW_FREEZE_TIMEOUT_DURATION); 8539 } 8540 } 8541 } 8542 8543 /** 8544 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8545 * @param windows List of windows on default display. 8546 * @return bitmap indicating if another pass through layout must be made. 8547 */ 8548 public int handleAppTransitionReadyLocked(WindowList windows) { 8549 int changes = 0; 8550 int i; 8551 int NN = mOpeningApps.size(); 8552 boolean goodToGo = true; 8553 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8554 "Checking " + NN + " opening apps (frozen=" 8555 + mDisplayFrozen + " timeout=" 8556 + mAppTransition.isTimeout() + ")..."); 8557 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8558 // If the display isn't frozen, wait to do anything until 8559 // all of the apps are ready. Otherwise just go because 8560 // we'll unfreeze the display when everyone is ready. 8561 for (i=0; i<NN && goodToGo; i++) { 8562 AppWindowToken wtoken = mOpeningApps.get(i); 8563 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8564 "Check opening app=" + wtoken + ": allDrawn=" 8565 + wtoken.allDrawn + " startingDisplayed=" 8566 + wtoken.startingDisplayed + " startingMoved=" 8567 + wtoken.startingMoved); 8568 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8569 && !wtoken.startingMoved) { 8570 goodToGo = false; 8571 } 8572 } 8573 } 8574 if (goodToGo) { 8575 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8576 int transit = mAppTransition.getAppTransition(); 8577 if (mSkipAppTransitionAnimation) { 8578 transit = AppTransition.TRANSIT_UNSET; 8579 } 8580 mAppTransition.goodToGo(); 8581 mStartingIconInTransition = false; 8582 mSkipAppTransitionAnimation = false; 8583 8584 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8585 8586 rebuildAppWindowListLocked(); 8587 8588 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8589 WindowState oldWallpaper = 8590 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8591 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8592 ? null : mWallpaperTarget; 8593 8594 mInnerFields.mWallpaperMayChange = false; 8595 8596 // The top-most window will supply the layout params, 8597 // and we will determine it below. 8598 LayoutParams animLp = null; 8599 int bestAnimLayer = -1; 8600 boolean fullscreenAnim = false; 8601 8602 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8603 "New wallpaper target=" + mWallpaperTarget 8604 + ", oldWallpaper=" + oldWallpaper 8605 + ", lower target=" + mLowerWallpaperTarget 8606 + ", upper target=" + mUpperWallpaperTarget); 8607 8608 boolean openingAppHasWallpaper = false; 8609 boolean closingAppHasWallpaper = false; 8610 final AppWindowToken lowerWallpaperAppToken; 8611 final AppWindowToken upperWallpaperAppToken; 8612 if (mLowerWallpaperTarget == null) { 8613 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8614 } else { 8615 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8616 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8617 } 8618 8619 // Do a first pass through the tokens for two 8620 // things: 8621 // (1) Determine if both the closing and opening 8622 // app token sets are wallpaper targets, in which 8623 // case special animations are needed 8624 // (since the wallpaper needs to stay static 8625 // behind them). 8626 // (2) Find the layout params of the top-most 8627 // application window in the tokens, which is 8628 // what will control the animation theme. 8629 final int NC = mClosingApps.size(); 8630 NN = NC + mOpeningApps.size(); 8631 for (i=0; i<NN; i++) { 8632 final AppWindowToken wtoken; 8633 if (i < NC) { 8634 wtoken = mClosingApps.get(i); 8635 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8636 closingAppHasWallpaper = true; 8637 } 8638 } else { 8639 wtoken = mOpeningApps.get(i - NC); 8640 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8641 openingAppHasWallpaper = true; 8642 } 8643 } 8644 8645 if (wtoken.appFullscreen) { 8646 WindowState ws = wtoken.findMainWindow(); 8647 if (ws != null) { 8648 animLp = ws.mAttrs; 8649 bestAnimLayer = ws.mLayer; 8650 fullscreenAnim = true; 8651 } 8652 } else if (!fullscreenAnim) { 8653 WindowState ws = wtoken.findMainWindow(); 8654 if (ws != null) { 8655 if (ws.mLayer > bestAnimLayer) { 8656 animLp = ws.mAttrs; 8657 bestAnimLayer = ws.mLayer; 8658 } 8659 } 8660 } 8661 } 8662 8663 mAnimateWallpaperWithTarget = false; 8664 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8665 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8666 switch (transit) { 8667 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8668 case AppTransition.TRANSIT_TASK_OPEN: 8669 case AppTransition.TRANSIT_TASK_TO_FRONT: 8670 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8671 break; 8672 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8673 case AppTransition.TRANSIT_TASK_CLOSE: 8674 case AppTransition.TRANSIT_TASK_TO_BACK: 8675 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8676 break; 8677 } 8678 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8679 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 8680 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8681 // We are transitioning from an activity with 8682 // a wallpaper to one without. 8683 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8684 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8685 "New transit away from wallpaper: " + transit); 8686 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8687 // We are transitioning from an activity without 8688 // a wallpaper to now showing the wallpaper 8689 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8690 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8691 "New transit into wallpaper: " + transit); 8692 } else { 8693 mAnimateWallpaperWithTarget = true; 8694 } 8695 8696 // If all closing windows are obscured, then there is 8697 // no need to do an animation. This is the case, for 8698 // example, when this transition is being done behind 8699 // the lock screen. 8700 if (!mPolicy.allowAppAnimationsLw()) { 8701 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8702 "Animations disallowed by keyguard or dream."); 8703 animLp = null; 8704 } 8705 8706 AppWindowToken topOpeningApp = null; 8707 int topOpeningLayer = 0; 8708 8709 NN = mOpeningApps.size(); 8710 for (i=0; i<NN; i++) { 8711 AppWindowToken wtoken = mOpeningApps.get(i); 8712 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8713 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8714 appAnimator.clearThumbnail(); 8715 wtoken.inPendingTransaction = false; 8716 appAnimator.animation = null; 8717 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 8718 wtoken.updateReportedVisibilityLocked(); 8719 wtoken.waitingToShow = false; 8720 8721 appAnimator.mAllAppWinAnimators.clear(); 8722 final int N = wtoken.allAppWindows.size(); 8723 for (int j = 0; j < N; j++) { 8724 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8725 } 8726 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8727 8728 if (animLp != null) { 8729 int layer = -1; 8730 for (int j=0; j<wtoken.windows.size(); j++) { 8731 WindowState win = wtoken.windows.get(j); 8732 if (win.mWinAnimator.mAnimLayer > layer) { 8733 layer = win.mWinAnimator.mAnimLayer; 8734 } 8735 } 8736 if (topOpeningApp == null || layer > topOpeningLayer) { 8737 topOpeningApp = wtoken; 8738 topOpeningLayer = layer; 8739 } 8740 } 8741 } 8742 NN = mClosingApps.size(); 8743 for (i=0; i<NN; i++) { 8744 AppWindowToken wtoken = mClosingApps.get(i); 8745 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 8746 wtoken.mAppAnimator.clearThumbnail(); 8747 wtoken.inPendingTransaction = false; 8748 wtoken.mAppAnimator.animation = null; 8749 setTokenVisibilityLocked(wtoken, animLp, false, transit, false); 8750 wtoken.updateReportedVisibilityLocked(); 8751 wtoken.waitingToHide = false; 8752 // Force the allDrawn flag, because we want to start 8753 // this guy's animations regardless of whether it's 8754 // gotten drawn. 8755 wtoken.allDrawn = true; 8756 wtoken.deferClearAllDrawn = false; 8757 } 8758 8759 AppWindowAnimator appAnimator = 8760 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8761 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8762 if (nextAppTransitionThumbnail != null && appAnimator != null 8763 && appAnimator.animation != null) { 8764 // This thumbnail animation is very special, we need to have 8765 // an extra surface with the thumbnail included with the animation. 8766 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8767 nextAppTransitionThumbnail.getHeight()); 8768 try { 8769 // TODO(multi-display): support other displays 8770 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8771 final Display display = displayContent.getDisplay(); 8772 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8773 "thumbnail anim", 8774 dirty.width(), dirty.height(), 8775 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8776 surfaceControl.setLayerStack(display.getLayerStack()); 8777 appAnimator.thumbnail = surfaceControl; 8778 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8779 Surface drawSurface = new Surface(); 8780 drawSurface.copyFrom(surfaceControl); 8781 Canvas c = drawSurface.lockCanvas(dirty); 8782 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8783 drawSurface.unlockCanvasAndPost(c); 8784 drawSurface.release(); 8785 appAnimator.thumbnailLayer = topOpeningLayer; 8786 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8787 Animation anim = mAppTransition.createThumbnailAnimationLocked( 8788 transit, true, true, displayInfo.appWidth, displayInfo.appHeight); 8789 appAnimator.thumbnailAnimation = anim; 8790 anim.restrictDuration(MAX_ANIMATION_DURATION); 8791 anim.scaleCurrentDuration(mTransitionAnimationScale); 8792 Point p = new Point(); 8793 mAppTransition.getStartingPoint(p); 8794 appAnimator.thumbnailX = p.x; 8795 appAnimator.thumbnailY = p.y; 8796 } catch (OutOfResourcesException e) { 8797 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 8798 + " h=" + dirty.height(), e); 8799 appAnimator.clearThumbnail(); 8800 } 8801 } 8802 8803 mAppTransition.postAnimationCallback(); 8804 mAppTransition.clear(); 8805 8806 mOpeningApps.clear(); 8807 mClosingApps.clear(); 8808 8809 // This has changed the visibility of windows, so perform 8810 // a new layout to get them all up-to-date. 8811 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8812 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8813 getDefaultDisplayContentLocked().layoutNeeded = true; 8814 8815 // TODO(multidisplay): IMEs are only supported on the default display. 8816 if (windows == getDefaultWindowListLocked() 8817 && !moveInputMethodWindowsIfNeededLocked(true)) { 8818 assignLayersLocked(windows); 8819 } 8820 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8821 mFocusMayChange = false; 8822 } 8823 8824 return changes; 8825 } 8826 8827 /** 8828 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8829 * @return bitmap indicating if another pass through layout must be made. 8830 */ 8831 private int handleAnimatingStoppedAndTransitionLocked() { 8832 int changes = 0; 8833 8834 mAppTransition.setIdle(); 8835 // Restore window app tokens to the ActivityManager views 8836 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 8837 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 8838 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8839 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8840 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8841 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8842 tokens.get(tokenNdx).sendingToBottom = false; 8843 } 8844 } 8845 } 8846 rebuildAppWindowListLocked(); 8847 8848 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8849 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8850 "Wallpaper layer changed: assigning layers + relayout"); 8851 moveInputMethodWindowsIfNeededLocked(true); 8852 mInnerFields.mWallpaperMayChange = true; 8853 // Since the window list has been rebuilt, focus might 8854 // have to be recomputed since the actual order of windows 8855 // might have changed again. 8856 mFocusMayChange = true; 8857 8858 return changes; 8859 } 8860 8861 private void updateResizingWindows(final WindowState w) { 8862 final WindowStateAnimator winAnimator = w.mWinAnimator; 8863 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8864 w.setInsetsChanged(); 8865 boolean configChanged = w.isConfigChanged(); 8866 if (DEBUG_CONFIGURATION && configChanged) { 8867 Slog.v(TAG, "Win " + w + " config changed: " 8868 + mCurConfiguration); 8869 } 8870 if (localLOGV) Slog.v(TAG, "Resizing " + w 8871 + ": configChanged=" + configChanged 8872 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8873 w.mLastFrame.set(w.mFrame); 8874 if (w.mContentInsetsChanged 8875 || w.mVisibleInsetsChanged 8876 || winAnimator.mSurfaceResized 8877 || configChanged) { 8878 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8879 Slog.v(TAG, "Resize reasons for w=" + w + ": " 8880 + " contentInsetsChanged=" + w.mContentInsetsChanged 8881 + " " + w.mContentInsets.toShortString() 8882 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8883 + " " + w.mVisibleInsets.toShortString() 8884 + " surfaceResized=" + winAnimator.mSurfaceResized 8885 + " configChanged=" + configChanged); 8886 } 8887 8888 w.mLastOverscanInsets.set(w.mOverscanInsets); 8889 w.mLastContentInsets.set(w.mContentInsets); 8890 w.mLastVisibleInsets.set(w.mVisibleInsets); 8891 makeWindowFreezingScreenIfNeededLocked(w); 8892 // If the orientation is changing, then we need to 8893 // hold off on unfreezing the display until this 8894 // window has been redrawn; to do that, we need 8895 // to go through the process of getting informed 8896 // by the application when it has finished drawing. 8897 if (w.mOrientationChanging) { 8898 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8899 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8900 + w + ", surface " + winAnimator.mSurfaceControl); 8901 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8902 if (w.mAppToken != null) { 8903 w.mAppToken.allDrawn = false; 8904 w.mAppToken.deferClearAllDrawn = false; 8905 } 8906 } 8907 if (!mResizingWindows.contains(w)) { 8908 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8909 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8910 + "x" + winAnimator.mSurfaceH); 8911 mResizingWindows.add(w); 8912 } 8913 } else if (w.mOrientationChanging) { 8914 if (w.isDrawnLw()) { 8915 if (DEBUG_ORIENTATION) Slog.v(TAG, 8916 "Orientation not waiting for draw in " 8917 + w + ", surface " + winAnimator.mSurfaceControl); 8918 w.mOrientationChanging = false; 8919 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8920 - mDisplayFreezeTime); 8921 } 8922 } 8923 } 8924 } 8925 8926 /** 8927 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8928 * 8929 * @param w WindowState this method is applied to. 8930 * @param currentTime The time which animations use for calculating transitions. 8931 * @param innerDw Width of app window. 8932 * @param innerDh Height of app window. 8933 */ 8934 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8935 final int innerDw, final int innerDh) { 8936 final WindowManager.LayoutParams attrs = w.mAttrs; 8937 final int attrFlags = attrs.flags; 8938 final boolean canBeSeen = w.isDisplayedLw(); 8939 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8940 8941 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8942 // This window completely covers everything behind it, 8943 // so we want to leave all of them as undimmed (for 8944 // performance reasons). 8945 mInnerFields.mObscured = true; 8946 } 8947 8948 if (w.mHasSurface) { 8949 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8950 mInnerFields.mHoldScreen = w.mSession; 8951 } 8952 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8953 && mInnerFields.mScreenBrightness < 0) { 8954 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8955 } 8956 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8957 && mInnerFields.mButtonBrightness < 0) { 8958 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8959 } 8960 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8961 && mInnerFields.mUserActivityTimeout < 0) { 8962 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8963 } 8964 8965 final int type = attrs.type; 8966 if (canBeSeen 8967 && (type == TYPE_SYSTEM_DIALOG 8968 || type == TYPE_RECENTS_OVERLAY 8969 || type == TYPE_KEYGUARD 8970 || type == TYPE_SYSTEM_ERROR)) { 8971 mInnerFields.mSyswin = true; 8972 } 8973 8974 if (canBeSeen) { 8975 // This function assumes that the contents of the default display are 8976 // processed first before secondary displays. 8977 final DisplayContent displayContent = w.getDisplayContent(); 8978 if (displayContent != null && displayContent.isDefaultDisplay) { 8979 // While a dream or keyguard is showing, obscure ordinary application 8980 // content on secondary displays (by forcibly enabling mirroring unless 8981 // there is other content we want to show) but still allow opaque 8982 // keyguard dialogs to be shown. 8983 if (type == TYPE_DREAM || type == TYPE_KEYGUARD) { 8984 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 8985 } 8986 mInnerFields.mDisplayHasContent = true; 8987 } else if (displayContent != null && 8988 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 8989 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 8990 // Allow full screen keyguard presentation dialogs to be seen. 8991 mInnerFields.mDisplayHasContent = true; 8992 } 8993 } 8994 } 8995 } 8996 8997 private void handleFlagDimBehind(WindowState w) { 8998 final WindowManager.LayoutParams attrs = w.mAttrs; 8999 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 9000 && w.isDisplayedLw() 9001 && !w.mExiting) { 9002 final WindowStateAnimator winAnimator = w.mWinAnimator; 9003 final TaskStack stack = w.getStack(); 9004 stack.setDimmingTag(); 9005 if (!stack.isDimming(winAnimator)) { 9006 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 9007 stack.startDimmingIfNeeded(winAnimator); 9008 } 9009 } 9010 } 9011 9012 private void updateAllDrawnLocked(DisplayContent displayContent) { 9013 // See if any windows have been drawn, so they (and others 9014 // associated with them) can now be shown. 9015 ArrayList<TaskStack> stacks = displayContent.getStacks(); 9016 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9017 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9018 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9019 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9020 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9021 final AppWindowToken wtoken = tokens.get(tokenNdx); 9022 if (!wtoken.allDrawn) { 9023 int numInteresting = wtoken.numInterestingWindows; 9024 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 9025 if (DEBUG_VISIBILITY) Slog.v(TAG, 9026 "allDrawn: " + wtoken 9027 + " interesting=" + numInteresting 9028 + " drawn=" + wtoken.numDrawnWindows); 9029 wtoken.allDrawn = true; 9030 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9031 } 9032 } 9033 } 9034 } 9035 } 9036 } 9037 9038 // "Something has changed! Let's make it correct now." 9039 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9040 if (DEBUG_WINDOW_TRACE) { 9041 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9042 + Debug.getCallers(3)); 9043 } 9044 9045 final long currentTime = SystemClock.uptimeMillis(); 9046 9047 int i; 9048 9049 if (mFocusMayChange) { 9050 mFocusMayChange = false; 9051 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9052 false /*updateInputWindows*/); 9053 } 9054 9055 // Initialize state of exiting tokens. 9056 final int numDisplays = mDisplayContents.size(); 9057 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9058 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9059 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9060 displayContent.mExitingTokens.get(i).hasVisible = false; 9061 } 9062 } 9063 9064 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9065 // Initialize state of exiting applications. 9066 final AppTokenList exitingAppTokens = 9067 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9068 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9069 exitingAppTokens.get(tokenNdx).hasVisible = false; 9070 } 9071 } 9072 9073 mInnerFields.mHoldScreen = null; 9074 mInnerFields.mScreenBrightness = -1; 9075 mInnerFields.mButtonBrightness = -1; 9076 mInnerFields.mUserActivityTimeout = -1; 9077 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9078 9079 mTransactionSequence++; 9080 9081 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9082 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9083 final int defaultDw = defaultInfo.logicalWidth; 9084 final int defaultDh = defaultInfo.logicalHeight; 9085 9086 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9087 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9088 SurfaceControl.openTransaction(); 9089 try { 9090 9091 if (mWatermark != null) { 9092 mWatermark.positionSurface(defaultDw, defaultDh); 9093 } 9094 if (mStrictModeFlash != null) { 9095 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9096 } 9097 if (mCircularDisplayMask != null) { 9098 mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation); 9099 } 9100 9101 boolean focusDisplayed = false; 9102 9103 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9104 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9105 boolean updateAllDrawn = false; 9106 WindowList windows = displayContent.getWindowList(); 9107 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9108 final int displayId = displayContent.getDisplayId(); 9109 final int dw = displayInfo.logicalWidth; 9110 final int dh = displayInfo.logicalHeight; 9111 final int innerDw = displayInfo.appWidth; 9112 final int innerDh = displayInfo.appHeight; 9113 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9114 9115 // Reset for each display. 9116 mInnerFields.mDisplayHasContent = false; 9117 9118 int repeats = 0; 9119 do { 9120 repeats++; 9121 if (repeats > 6) { 9122 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9123 displayContent.layoutNeeded = false; 9124 break; 9125 } 9126 9127 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9128 displayContent.pendingLayoutChanges); 9129 9130 if ((displayContent.pendingLayoutChanges & 9131 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9132 (adjustWallpaperWindowsLocked() & 9133 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9134 assignLayersLocked(windows); 9135 displayContent.layoutNeeded = true; 9136 } 9137 9138 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9139 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9140 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9141 if (updateOrientationFromAppTokensLocked(true)) { 9142 displayContent.layoutNeeded = true; 9143 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9144 } 9145 } 9146 9147 if ((displayContent.pendingLayoutChanges 9148 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9149 displayContent.layoutNeeded = true; 9150 } 9151 9152 // FIRST LOOP: Perform a layout, if needed. 9153 if (repeats < 4) { 9154 performLayoutLockedInner(displayContent, repeats == 1, 9155 false /*updateInputWindows*/); 9156 } else { 9157 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9158 } 9159 9160 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9161 // it is animating. 9162 displayContent.pendingLayoutChanges = 0; 9163 9164 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9165 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9166 9167 if (isDefaultDisplay) { 9168 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9169 for (i = windows.size() - 1; i >= 0; i--) { 9170 WindowState w = windows.get(i); 9171 if (w.mHasSurface) { 9172 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9173 } 9174 } 9175 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9176 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9177 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9178 } 9179 } while (displayContent.pendingLayoutChanges != 0); 9180 9181 mInnerFields.mObscured = false; 9182 mInnerFields.mSyswin = false; 9183 displayContent.resetDimming(); 9184 9185 // Only used if default window 9186 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9187 9188 final int N = windows.size(); 9189 for (i=N-1; i>=0; i--) { 9190 WindowState w = windows.get(i); 9191 final TaskStack stack = w.getStack(); 9192 if (stack == null) { 9193 continue; 9194 } 9195 9196 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9197 9198 // Update effect. 9199 w.mObscured = mInnerFields.mObscured; 9200 if (!mInnerFields.mObscured) { 9201 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9202 } 9203 9204 if (!stack.testDimmingTag()) { 9205 handleFlagDimBehind(w); 9206 } 9207 9208 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9209 && w.isVisibleLw()) { 9210 // This is the wallpaper target and its obscured state 9211 // changed... make sure the current wallaper's visibility 9212 // has been updated accordingly. 9213 updateWallpaperVisibilityLocked(); 9214 } 9215 9216 final WindowStateAnimator winAnimator = w.mWinAnimator; 9217 9218 // If the window has moved due to its containing 9219 // content frame changing, then we'd like to animate 9220 // it. 9221 if (w.mHasSurface && w.shouldAnimateMove()) { 9222 // Frame has moved, containing content frame 9223 // has also moved, and we're not currently animating... 9224 // let's do something. 9225 Animation a = AnimationUtils.loadAnimation(mContext, 9226 com.android.internal.R.anim.window_move_from_decor); 9227 winAnimator.setAnimation(a); 9228 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9229 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9230 try { 9231 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9232 } catch (RemoteException e) { 9233 } 9234 } 9235 9236 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9237 w.mContentChanged = false; 9238 9239 // Moved from updateWindowsAndWallpaperLocked(). 9240 if (w.mHasSurface) { 9241 // Take care of the window being ready to display. 9242 final boolean committed = 9243 winAnimator.commitFinishDrawingLocked(currentTime); 9244 if (isDefaultDisplay && committed) { 9245 if (w.mAttrs.type == TYPE_DREAM) { 9246 // HACK: When a dream is shown, it may at that 9247 // point hide the lock screen. So we need to 9248 // redo the layout to let the phone window manager 9249 // make this happen. 9250 displayContent.pendingLayoutChanges |= 9251 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9252 if (DEBUG_LAYOUT_REPEATS) { 9253 debugLayoutRepeats( 9254 "dream and commitFinishDrawingLocked true", 9255 displayContent.pendingLayoutChanges); 9256 } 9257 } 9258 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9259 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9260 "First draw done in potential wallpaper target " + w); 9261 mInnerFields.mWallpaperMayChange = true; 9262 displayContent.pendingLayoutChanges |= 9263 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9264 if (DEBUG_LAYOUT_REPEATS) { 9265 debugLayoutRepeats( 9266 "wallpaper and commitFinishDrawingLocked true", 9267 displayContent.pendingLayoutChanges); 9268 } 9269 } 9270 } 9271 9272 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9273 9274 final AppWindowToken atoken = w.mAppToken; 9275 if (DEBUG_STARTING_WINDOW && atoken != null 9276 && w == atoken.startingWindow) { 9277 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9278 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9279 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9280 } 9281 if (atoken != null 9282 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9283 if (atoken.lastTransactionSequence != mTransactionSequence) { 9284 atoken.lastTransactionSequence = mTransactionSequence; 9285 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9286 atoken.startingDisplayed = false; 9287 } 9288 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9289 && !w.mExiting && !w.mDestroying) { 9290 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9291 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9292 + ", isAnimating=" + winAnimator.isAnimating()); 9293 if (!w.isDrawnLw()) { 9294 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9295 + " pv=" + w.mPolicyVisibility 9296 + " mDrawState=" + winAnimator.mDrawState 9297 + " ah=" + w.mAttachedHidden 9298 + " th=" + atoken.hiddenRequested 9299 + " a=" + winAnimator.mAnimating); 9300 } 9301 } 9302 if (w != atoken.startingWindow) { 9303 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9304 atoken.numInterestingWindows++; 9305 if (w.isDrawnLw()) { 9306 atoken.numDrawnWindows++; 9307 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9308 "tokenMayBeDrawn: " + atoken 9309 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9310 + " mAppFreezing=" + w.mAppFreezing); 9311 updateAllDrawn = true; 9312 } 9313 } 9314 } else if (w.isDrawnLw()) { 9315 atoken.startingDisplayed = true; 9316 } 9317 } 9318 } 9319 } 9320 9321 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9322 && w.isDisplayedLw()) { 9323 focusDisplayed = true; 9324 } 9325 9326 updateResizingWindows(w); 9327 } 9328 9329 mDisplayManagerInternal.setDisplayHasContent(displayId, 9330 mInnerFields.mDisplayHasContent, 9331 true /* inTraversal, must call performTraversalInTrans... below */); 9332 9333 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9334 9335 if (updateAllDrawn) { 9336 updateAllDrawnLocked(displayContent); 9337 } 9338 } 9339 9340 if (focusDisplayed) { 9341 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9342 } 9343 9344 // Give the display manager a chance to adjust properties 9345 // like display rotation if it needs to. 9346 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9347 9348 } catch (RuntimeException e) { 9349 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9350 } finally { 9351 SurfaceControl.closeTransaction(); 9352 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9353 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9354 } 9355 9356 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9357 9358 // If we are ready to perform an app transition, check through 9359 // all of the app tokens to be shown and see if they are ready 9360 // to go. 9361 if (mAppTransition.isReady()) { 9362 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9363 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9364 defaultDisplay.pendingLayoutChanges); 9365 } 9366 9367 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9368 // We have finished the animation of an app transition. To do 9369 // this, we have delayed a lot of operations like showing and 9370 // hiding apps, moving apps in Z-order, etc. The app token list 9371 // reflects the correct Z-order, but the window list may now 9372 // be out of sync with it. So here we will just rebuild the 9373 // entire app window list. Fun! 9374 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9375 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9376 defaultDisplay.pendingLayoutChanges); 9377 } 9378 9379 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9380 && !mAppTransition.isReady()) { 9381 // At this point, there was a window with a wallpaper that 9382 // was force hiding other windows behind it, but now it 9383 // is going away. This may be simple -- just animate 9384 // away the wallpaper and its window -- or it may be 9385 // hard -- the wallpaper now needs to be shown behind 9386 // something that was hidden. 9387 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9388 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9389 defaultDisplay.pendingLayoutChanges); 9390 } 9391 mInnerFields.mWallpaperForceHidingChanged = false; 9392 9393 if (mInnerFields.mWallpaperMayChange) { 9394 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9395 defaultDisplay.pendingLayoutChanges |= 9396 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9397 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9398 defaultDisplay.pendingLayoutChanges); 9399 } 9400 9401 if (mFocusMayChange) { 9402 mFocusMayChange = false; 9403 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9404 false /*updateInputWindows*/)) { 9405 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9406 } 9407 } 9408 9409 if (needsLayout()) { 9410 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9411 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9412 defaultDisplay.pendingLayoutChanges); 9413 } 9414 9415 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9416 WindowState win = mResizingWindows.get(i); 9417 if (win.mAppFreezing) { 9418 // Don't remove this window until rotation has completed. 9419 continue; 9420 } 9421 win.reportResized(); 9422 mResizingWindows.remove(i); 9423 } 9424 9425 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9426 "With display frozen, orientationChangeComplete=" 9427 + mInnerFields.mOrientationChangeComplete); 9428 if (mInnerFields.mOrientationChangeComplete) { 9429 if (mWindowsFreezingScreen) { 9430 mWindowsFreezingScreen = false; 9431 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9432 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9433 } 9434 stopFreezingDisplayLocked(); 9435 } 9436 9437 // Destroy the surface of any windows that are no longer visible. 9438 boolean wallpaperDestroyed = false; 9439 i = mDestroySurface.size(); 9440 if (i > 0) { 9441 do { 9442 i--; 9443 WindowState win = mDestroySurface.get(i); 9444 win.mDestroying = false; 9445 if (mInputMethodWindow == win) { 9446 mInputMethodWindow = null; 9447 } 9448 if (win == mWallpaperTarget) { 9449 wallpaperDestroyed = true; 9450 } 9451 win.mWinAnimator.destroySurfaceLocked(); 9452 } while (i > 0); 9453 mDestroySurface.clear(); 9454 } 9455 9456 // Time to remove any exiting tokens? 9457 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9458 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9459 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9460 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9461 WindowToken token = exitingTokens.get(i); 9462 if (!token.hasVisible) { 9463 exitingTokens.remove(i); 9464 if (token.windowType == TYPE_WALLPAPER) { 9465 mWallpaperTokens.remove(token); 9466 } 9467 } 9468 } 9469 } 9470 9471 // Time to remove any exiting applications? 9472 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9473 // Initialize state of exiting applications. 9474 final AppTokenList exitingAppTokens = 9475 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9476 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9477 AppWindowToken token = exitingAppTokens.get(i); 9478 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 9479 // Make sure there is no animation running on this token, 9480 // so any windows associated with it will be removed as 9481 // soon as their animations are complete 9482 token.mAppAnimator.clearAnimation(); 9483 token.mAppAnimator.animating = false; 9484 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9485 "performLayout: App token exiting now removed" + token); 9486 removeAppFromTaskLocked(token); 9487 exitingAppTokens.remove(i); 9488 } 9489 } 9490 } 9491 9492 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9493 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9494 try { 9495 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9496 } catch (RemoteException e) { 9497 } 9498 } 9499 mRelayoutWhileAnimating.clear(); 9500 } 9501 9502 if (wallpaperDestroyed) { 9503 defaultDisplay.pendingLayoutChanges |= 9504 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9505 defaultDisplay.layoutNeeded = true; 9506 } 9507 9508 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9509 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9510 if (displayContent.pendingLayoutChanges != 0) { 9511 displayContent.layoutNeeded = true; 9512 } 9513 } 9514 9515 // Finally update all input windows now that the window changes have stabilized. 9516 mInputMonitor.updateInputWindowsLw(true /*force*/); 9517 9518 setHoldScreenLocked(mInnerFields.mHoldScreen); 9519 if (!mDisplayFrozen) { 9520 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9521 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 9522 } else { 9523 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 9524 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9525 } 9526 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9527 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 9528 } else { 9529 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 9530 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9531 } 9532 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 9533 mInnerFields.mUserActivityTimeout); 9534 } 9535 9536 if (mTurnOnScreen) { 9537 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9538 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9539 mTurnOnScreen = false; 9540 } 9541 9542 if (mInnerFields.mUpdateRotation) { 9543 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9544 if (updateRotationUncheckedLocked(false)) { 9545 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9546 } else { 9547 mInnerFields.mUpdateRotation = false; 9548 } 9549 } 9550 9551 if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded 9552 && !mInnerFields.mUpdateRotation) { 9553 checkDrawnWindowsLocked(); 9554 } 9555 9556 final int N = mPendingRemove.size(); 9557 if (N > 0) { 9558 if (mPendingRemoveTmp.length < N) { 9559 mPendingRemoveTmp = new WindowState[N+10]; 9560 } 9561 mPendingRemove.toArray(mPendingRemoveTmp); 9562 mPendingRemove.clear(); 9563 DisplayContentList displayList = new DisplayContentList(); 9564 for (i = 0; i < N; i++) { 9565 WindowState w = mPendingRemoveTmp[i]; 9566 removeWindowInnerLocked(w.mSession, w); 9567 final DisplayContent displayContent = w.getDisplayContent(); 9568 if (displayContent != null && !displayList.contains(displayContent)) { 9569 displayList.add(displayContent); 9570 } 9571 } 9572 9573 for (DisplayContent displayContent : displayList) { 9574 assignLayersLocked(displayContent.getWindowList()); 9575 displayContent.layoutNeeded = true; 9576 } 9577 } 9578 9579 // Remove all deferred displays stacks, tasks, and activities. 9580 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 9581 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 9582 } 9583 9584 setFocusedStackFrame(); 9585 9586 // Check to see if we are now in a state where the screen should 9587 // be enabled, because the window obscured flags have changed. 9588 enableScreenIfNeededLocked(); 9589 9590 scheduleAnimationLocked(); 9591 9592 if (DEBUG_WINDOW_TRACE) { 9593 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9594 + mAnimator.mAnimating); 9595 } 9596 } 9597 9598 private int toBrightnessOverride(float value) { 9599 return (int)(value * PowerManager.BRIGHTNESS_ON); 9600 } 9601 9602 void checkDrawnWindowsLocked() { 9603 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9604 return; 9605 } 9606 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9607 WindowState win = mWaitingForDrawn.get(j); 9608 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 9609 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9610 " mHasSurface=" + win.mHasSurface + 9611 " drawState=" + win.mWinAnimator.mDrawState); 9612 if (win.mRemoved || !win.mHasSurface) { 9613 // Window has been removed; no draw will now happen, so stop waiting. 9614 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 9615 mWaitingForDrawn.remove(win); 9616 } else if (win.hasDrawnLw()) { 9617 // Window is now drawn (and shown). 9618 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 9619 mWaitingForDrawn.remove(win); 9620 } 9621 } 9622 if (mWaitingForDrawn.isEmpty()) { 9623 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 9624 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9625 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9626 } 9627 } 9628 9629 void setHoldScreenLocked(final Session newHoldScreen) { 9630 final boolean hold = newHoldScreen != null; 9631 9632 if (hold && mHoldingScreenOn != newHoldScreen) { 9633 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9634 } 9635 mHoldingScreenOn = newHoldScreen; 9636 9637 final boolean state = mHoldingScreenWakeLock.isHeld(); 9638 if (hold != state) { 9639 if (hold) { 9640 mHoldingScreenWakeLock.acquire(); 9641 mPolicy.keepScreenOnStartedLw(); 9642 } else { 9643 mPolicy.keepScreenOnStoppedLw(); 9644 mHoldingScreenWakeLock.release(); 9645 } 9646 } 9647 } 9648 9649 void requestTraversal() { 9650 synchronized (mWindowMap) { 9651 requestTraversalLocked(); 9652 } 9653 } 9654 9655 void requestTraversalLocked() { 9656 if (!mTraversalScheduled) { 9657 mTraversalScheduled = true; 9658 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9659 } 9660 } 9661 9662 /** Note that Locked in this case is on mLayoutToAnim */ 9663 void scheduleAnimationLocked() { 9664 if (!mAnimationScheduled) { 9665 mAnimationScheduled = true; 9666 mChoreographer.postCallback( 9667 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9668 } 9669 } 9670 9671 private boolean needsLayout() { 9672 final int numDisplays = mDisplayContents.size(); 9673 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9674 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9675 if (displayContent.layoutNeeded) { 9676 return true; 9677 } 9678 } 9679 return false; 9680 } 9681 9682 boolean copyAnimToLayoutParamsLocked() { 9683 boolean doRequest = false; 9684 9685 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9686 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9687 mInnerFields.mUpdateRotation = true; 9688 doRequest = true; 9689 } 9690 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9691 mInnerFields.mWallpaperMayChange = true; 9692 doRequest = true; 9693 } 9694 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9695 mInnerFields.mWallpaperForceHidingChanged = true; 9696 doRequest = true; 9697 } 9698 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9699 mInnerFields.mOrientationChangeComplete = false; 9700 } else { 9701 mInnerFields.mOrientationChangeComplete = true; 9702 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9703 if (mWindowsFreezingScreen) { 9704 doRequest = true; 9705 } 9706 } 9707 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9708 mTurnOnScreen = true; 9709 } 9710 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9711 mInnerFields.mWallpaperActionPending = true; 9712 } 9713 9714 return doRequest; 9715 } 9716 9717 /** If a window that has an animation specifying a colored background and the current wallpaper 9718 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9719 * suddenly disappear. */ 9720 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9721 WindowList windows = winAnimator.mWin.getWindowList(); 9722 for (int i = windows.size() - 1; i >= 0; --i) { 9723 WindowState testWin = windows.get(i); 9724 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9725 return testWin.mWinAnimator.mAnimLayer; 9726 } 9727 } 9728 return winAnimator.mAnimLayer; 9729 } 9730 9731 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9732 boolean secure) { 9733 final SurfaceControl surface = winAnimator.mSurfaceControl; 9734 boolean leakedSurface = false; 9735 boolean killedApps = false; 9736 9737 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9738 winAnimator.mSession.mPid, operation); 9739 9740 if (mForceRemoves == null) { 9741 mForceRemoves = new ArrayList<WindowState>(); 9742 } 9743 9744 long callingIdentity = Binder.clearCallingIdentity(); 9745 try { 9746 // There was some problem... first, do a sanity check of the 9747 // window list to make sure we haven't left any dangling surfaces 9748 // around. 9749 9750 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9751 final int numDisplays = mDisplayContents.size(); 9752 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9753 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9754 final int numWindows = windows.size(); 9755 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9756 final WindowState ws = windows.get(winNdx); 9757 WindowStateAnimator wsa = ws.mWinAnimator; 9758 if (wsa.mSurfaceControl != null) { 9759 if (!mSessions.contains(wsa.mSession)) { 9760 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9761 + ws + " surface=" + wsa.mSurfaceControl 9762 + " token=" + ws.mToken 9763 + " pid=" + ws.mSession.mPid 9764 + " uid=" + ws.mSession.mUid); 9765 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9766 wsa.mSurfaceControl.destroy(); 9767 wsa.mSurfaceShown = false; 9768 wsa.mSurfaceControl = null; 9769 ws.mHasSurface = false; 9770 mForceRemoves.add(ws); 9771 leakedSurface = true; 9772 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9773 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9774 + ws + " surface=" + wsa.mSurfaceControl 9775 + " token=" + ws.mAppToken); 9776 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9777 wsa.mSurfaceControl.destroy(); 9778 wsa.mSurfaceShown = false; 9779 wsa.mSurfaceControl = null; 9780 ws.mHasSurface = false; 9781 leakedSurface = true; 9782 } 9783 } 9784 } 9785 } 9786 9787 if (!leakedSurface) { 9788 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9789 SparseIntArray pidCandidates = new SparseIntArray(); 9790 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9791 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9792 final int numWindows = windows.size(); 9793 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9794 final WindowState ws = windows.get(winNdx); 9795 if (mForceRemoves.contains(ws)) { 9796 continue; 9797 } 9798 WindowStateAnimator wsa = ws.mWinAnimator; 9799 if (wsa.mSurfaceControl != null) { 9800 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9801 } 9802 } 9803 if (pidCandidates.size() > 0) { 9804 int[] pids = new int[pidCandidates.size()]; 9805 for (int i=0; i<pids.length; i++) { 9806 pids[i] = pidCandidates.keyAt(i); 9807 } 9808 try { 9809 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9810 killedApps = true; 9811 } 9812 } catch (RemoteException e) { 9813 } 9814 } 9815 } 9816 } 9817 9818 if (leakedSurface || killedApps) { 9819 // We managed to reclaim some memory, so get rid of the trouble 9820 // surface and ask the app to request another one. 9821 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9822 if (surface != null) { 9823 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9824 "RECOVER DESTROY", null); 9825 surface.destroy(); 9826 winAnimator.mSurfaceShown = false; 9827 winAnimator.mSurfaceControl = null; 9828 winAnimator.mWin.mHasSurface = false; 9829 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken); 9830 } 9831 9832 try { 9833 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9834 } catch (RemoteException e) { 9835 } 9836 } 9837 } finally { 9838 Binder.restoreCallingIdentity(callingIdentity); 9839 } 9840 9841 return leakedSurface || killedApps; 9842 } 9843 9844 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9845 WindowState newFocus = computeFocusedWindowLocked(); 9846 if (mCurrentFocus != newFocus) { 9847 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9848 // This check makes sure that we don't already have the focus 9849 // change message pending. 9850 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9851 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9852 // TODO(multidisplay): Focused windows on default display only. 9853 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9854 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9855 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9856 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9857 if (imWindowChanged) { 9858 displayContent.layoutNeeded = true; 9859 newFocus = computeFocusedWindowLocked(); 9860 } 9861 9862 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 9863 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9864 final WindowState oldFocus = mCurrentFocus; 9865 mCurrentFocus = newFocus; 9866 mLosingFocus.remove(newFocus); 9867 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9868 9869 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9870 // Focus of the input method window changed. Perform layout if needed. 9871 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9872 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9873 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9874 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9875 // Client will do the layout, but we need to assign layers 9876 // for handleNewWindowLocked() below. 9877 assignLayersLocked(displayContent.getWindowList()); 9878 } 9879 } 9880 9881 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9882 // The change in focus caused us to need to do a layout. Okay. 9883 displayContent.layoutNeeded = true; 9884 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9885 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9886 } 9887 } 9888 9889 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9890 // If we defer assigning layers, then the caller is responsible for 9891 // doing this part. 9892 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9893 } 9894 9895 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9896 return true; 9897 } 9898 return false; 9899 } 9900 9901 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9902 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9903 } 9904 9905 private WindowState computeFocusedWindowLocked() { 9906 if (mAnimator.mUniverseBackground != null 9907 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9908 return mAnimator.mUniverseBackground.mWin; 9909 } 9910 9911 final int displayCount = mDisplayContents.size(); 9912 for (int i = 0; i < displayCount; i++) { 9913 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9914 WindowState win = findFocusedWindowLocked(displayContent); 9915 if (win != null) { 9916 return win; 9917 } 9918 } 9919 return null; 9920 } 9921 9922 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9923 final WindowList windows = displayContent.getWindowList(); 9924 for (int i = windows.size() - 1; i >= 0; i--) { 9925 final WindowState win = windows.get(i); 9926 9927 if (localLOGV || DEBUG_FOCUS) Slog.v( 9928 TAG, "Looking for focus: " + i 9929 + " = " + win 9930 + ", flags=" + win.mAttrs.flags 9931 + ", canReceive=" + win.canReceiveKeys()); 9932 9933 AppWindowToken wtoken = win.mAppToken; 9934 9935 // If this window's application has been removed, just skip it. 9936 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9937 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 9938 + (wtoken.removed ? "removed" : "sendingToBottom")); 9939 continue; 9940 } 9941 9942 if (!win.canReceiveKeys()) { 9943 continue; 9944 } 9945 9946 // Descend through all of the app tokens and find the first that either matches 9947 // win.mAppToken (return win) or mFocusedApp (return null). 9948 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 9949 mFocusedApp != null) { 9950 ArrayList<Task> tasks = displayContent.getTasks(); 9951 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9952 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9953 int tokenNdx = tokens.size() - 1; 9954 for ( ; tokenNdx >= 0; --tokenNdx) { 9955 final AppWindowToken token = tokens.get(tokenNdx); 9956 if (wtoken == token) { 9957 break; 9958 } 9959 if (mFocusedApp == token) { 9960 // Whoops, we are below the focused app... no focus for you! 9961 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 9962 "findFocusedWindow: Reached focused app=" + mFocusedApp); 9963 return null; 9964 } 9965 } 9966 if (tokenNdx >= 0) { 9967 // Early exit from loop, must have found the matching token. 9968 break; 9969 } 9970 } 9971 } 9972 9973 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 9974 " = " + win); 9975 return win; 9976 } 9977 9978 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 9979 return null; 9980 } 9981 9982 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 9983 if (mDisplayFrozen) { 9984 return; 9985 } 9986 9987 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 9988 // No need to freeze the screen before the system is ready or if 9989 // the screen is off. 9990 return; 9991 } 9992 9993 mScreenFrozenLock.acquire(); 9994 9995 mDisplayFrozen = true; 9996 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 9997 mLastFinishedFreezeSource = null; 9998 9999 mInputMonitor.freezeInputDispatchingLw(); 10000 10001 // Clear the last input window -- that is just used for 10002 // clean transitions between IMEs, and if we are freezing 10003 // the screen then the whole world is changing behind the scenes. 10004 mPolicy.setLastInputMethodWindowLw(null, null); 10005 10006 if (mAppTransition.isTransitionSet()) { 10007 mAppTransition.freeze(); 10008 } 10009 10010 if (PROFILE_ORIENTATION) { 10011 File file = new File("/data/system/frozen"); 10012 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10013 } 10014 10015 if (CUSTOM_SCREEN_ROTATION) { 10016 mExitAnimId = exitAnim; 10017 mEnterAnimId = enterAnim; 10018 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10019 final int displayId = displayContent.getDisplayId(); 10020 ScreenRotationAnimation screenRotationAnimation = 10021 mAnimator.getScreenRotationAnimationLocked(displayId); 10022 if (screenRotationAnimation != null) { 10023 screenRotationAnimation.kill(); 10024 } 10025 10026 // TODO(multidisplay): rotation on main screen only. 10027 displayContent.updateDisplayInfo(); 10028 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10029 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced()); 10030 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10031 } 10032 } 10033 10034 private void stopFreezingDisplayLocked() { 10035 if (!mDisplayFrozen) { 10036 return; 10037 } 10038 10039 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10040 || mClientFreezingScreen) { 10041 if (DEBUG_ORIENTATION) Slog.d(TAG, 10042 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10043 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10044 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10045 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10046 return; 10047 } 10048 10049 mDisplayFrozen = false; 10050 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10051 StringBuilder sb = new StringBuilder(128); 10052 sb.append("Screen frozen for "); 10053 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10054 if (mLastFinishedFreezeSource != null) { 10055 sb.append(" due to "); 10056 sb.append(mLastFinishedFreezeSource); 10057 } 10058 Slog.i(TAG, sb.toString()); 10059 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10060 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10061 if (PROFILE_ORIENTATION) { 10062 Debug.stopMethodTracing(); 10063 } 10064 10065 boolean updateRotation = false; 10066 10067 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10068 final int displayId = displayContent.getDisplayId(); 10069 ScreenRotationAnimation screenRotationAnimation = 10070 mAnimator.getScreenRotationAnimationLocked(displayId); 10071 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10072 && screenRotationAnimation.hasScreenshot()) { 10073 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10074 // TODO(multidisplay): rotation on main screen only. 10075 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10076 // Get rotation animation again, with new top window 10077 boolean isDimming = displayContent.isDimming(); 10078 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10079 mExitAnimId = mEnterAnimId = 0; 10080 } 10081 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10082 mTransitionAnimationScale, displayInfo.logicalWidth, 10083 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10084 scheduleAnimationLocked(); 10085 } else { 10086 screenRotationAnimation.kill(); 10087 screenRotationAnimation = null; 10088 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10089 updateRotation = true; 10090 } 10091 } else { 10092 if (screenRotationAnimation != null) { 10093 screenRotationAnimation.kill(); 10094 screenRotationAnimation = null; 10095 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10096 } 10097 updateRotation = true; 10098 } 10099 10100 mInputMonitor.thawInputDispatchingLw(); 10101 10102 boolean configChanged; 10103 10104 // While the display is frozen we don't re-compute the orientation 10105 // to avoid inconsistent states. However, something interesting 10106 // could have actually changed during that time so re-evaluate it 10107 // now to catch that. 10108 configChanged = updateOrientationFromAppTokensLocked(false); 10109 10110 // A little kludge: a lot could have happened while the 10111 // display was frozen, so now that we are coming back we 10112 // do a gc so that any remote references the system 10113 // processes holds on others can be released if they are 10114 // no longer needed. 10115 mH.removeMessages(H.FORCE_GC); 10116 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10117 10118 mScreenFrozenLock.release(); 10119 10120 if (updateRotation) { 10121 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10122 configChanged |= updateRotationUncheckedLocked(false); 10123 } 10124 10125 if (configChanged) { 10126 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10127 } 10128 } 10129 10130 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10131 DisplayMetrics dm) { 10132 if (index < tokens.length) { 10133 String str = tokens[index]; 10134 if (str != null && str.length() > 0) { 10135 try { 10136 int val = Integer.parseInt(str); 10137 return val; 10138 } catch (Exception e) { 10139 } 10140 } 10141 } 10142 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10143 return defDps; 10144 } 10145 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10146 return val; 10147 } 10148 10149 void createWatermarkInTransaction() { 10150 if (mWatermark != null) { 10151 return; 10152 } 10153 10154 File file = new File("/system/etc/setup.conf"); 10155 FileInputStream in = null; 10156 DataInputStream ind = null; 10157 try { 10158 in = new FileInputStream(file); 10159 ind = new DataInputStream(in); 10160 String line = ind.readLine(); 10161 if (line != null) { 10162 String[] toks = line.split("%"); 10163 if (toks != null && toks.length > 0) { 10164 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10165 mRealDisplayMetrics, mFxSession, toks); 10166 } 10167 } 10168 } catch (FileNotFoundException e) { 10169 } catch (IOException e) { 10170 } finally { 10171 if (ind != null) { 10172 try { 10173 ind.close(); 10174 } catch (IOException e) { 10175 } 10176 } else if (in != null) { 10177 try { 10178 in.close(); 10179 } catch (IOException e) { 10180 } 10181 } 10182 } 10183 } 10184 10185 @Override 10186 public void statusBarVisibilityChanged(int visibility) { 10187 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10188 != PackageManager.PERMISSION_GRANTED) { 10189 throw new SecurityException("Caller does not hold permission " 10190 + android.Manifest.permission.STATUS_BAR); 10191 } 10192 10193 synchronized (mWindowMap) { 10194 mLastStatusBarVisibility = visibility; 10195 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10196 updateStatusBarVisibilityLocked(visibility); 10197 } 10198 } 10199 10200 // TOOD(multidisplay): StatusBar on multiple screens? 10201 void updateStatusBarVisibilityLocked(int visibility) { 10202 mInputManager.setSystemUiVisibility(visibility); 10203 final WindowList windows = getDefaultWindowListLocked(); 10204 final int N = windows.size(); 10205 for (int i = 0; i < N; i++) { 10206 WindowState ws = windows.get(i); 10207 try { 10208 int curValue = ws.mSystemUiVisibility; 10209 int diff = curValue ^ visibility; 10210 // We are only interested in differences of one of the 10211 // clearable flags... 10212 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10213 // ...if it has actually been cleared. 10214 diff &= ~visibility; 10215 int newValue = (curValue&~diff) | (visibility&diff); 10216 if (newValue != curValue) { 10217 ws.mSeq++; 10218 ws.mSystemUiVisibility = newValue; 10219 } 10220 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10221 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10222 visibility, newValue, diff); 10223 } 10224 } catch (RemoteException e) { 10225 // so sorry 10226 } 10227 } 10228 } 10229 10230 @Override 10231 public void reevaluateStatusBarVisibility() { 10232 synchronized (mWindowMap) { 10233 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10234 updateStatusBarVisibilityLocked(visibility); 10235 performLayoutAndPlaceSurfacesLocked(); 10236 } 10237 } 10238 10239 @Override 10240 public FakeWindow addFakeWindow(Looper looper, 10241 InputEventReceiver.Factory inputEventReceiverFactory, 10242 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10243 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10244 synchronized (mWindowMap) { 10245 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10246 name, windowType, 10247 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10248 hasFocus, touchFullscreen); 10249 int i=0; 10250 while (i<mFakeWindows.size()) { 10251 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10252 break; 10253 } 10254 } 10255 mFakeWindows.add(i, fw); 10256 mInputMonitor.updateInputWindowsLw(true); 10257 return fw; 10258 } 10259 } 10260 10261 boolean removeFakeWindowLocked(FakeWindow window) { 10262 synchronized (mWindowMap) { 10263 if (mFakeWindows.remove(window)) { 10264 mInputMonitor.updateInputWindowsLw(true); 10265 return true; 10266 } 10267 return false; 10268 } 10269 } 10270 10271 // It is assumed that this method is called only by InputMethodManagerService. 10272 public void saveLastInputMethodWindowForTransition() { 10273 synchronized (mWindowMap) { 10274 // TODO(multidisplay): Pass in the displayID. 10275 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10276 if (mInputMethodWindow != null) { 10277 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10278 } 10279 } 10280 } 10281 10282 @Override 10283 public boolean hasNavigationBar() { 10284 return mPolicy.hasNavigationBar(); 10285 } 10286 10287 @Override 10288 public void lockNow(Bundle options) { 10289 mPolicy.lockNow(options); 10290 } 10291 10292 @Override 10293 public boolean isSafeModeEnabled() { 10294 return mSafeMode; 10295 } 10296 10297 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10298 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10299 mPolicy.dump(" ", pw, args); 10300 } 10301 10302 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10303 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10304 mAnimator.dumpLocked(pw, " ", dumpAll); 10305 } 10306 10307 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10308 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10309 if (mTokenMap.size() > 0) { 10310 pw.println(" All tokens:"); 10311 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10312 while (it.hasNext()) { 10313 WindowToken token = it.next(); 10314 pw.print(" "); pw.print(token); 10315 if (dumpAll) { 10316 pw.println(':'); 10317 token.dump(pw, " "); 10318 } else { 10319 pw.println(); 10320 } 10321 } 10322 } 10323 if (mWallpaperTokens.size() > 0) { 10324 pw.println(); 10325 pw.println(" Wallpaper tokens:"); 10326 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10327 WindowToken token = mWallpaperTokens.get(i); 10328 pw.print(" Wallpaper #"); pw.print(i); 10329 pw.print(' '); pw.print(token); 10330 if (dumpAll) { 10331 pw.println(':'); 10332 token.dump(pw, " "); 10333 } else { 10334 pw.println(); 10335 } 10336 } 10337 } 10338 if (mFinishedStarting.size() > 0) { 10339 pw.println(); 10340 pw.println(" Finishing start of application tokens:"); 10341 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10342 WindowToken token = mFinishedStarting.get(i); 10343 pw.print(" Finished Starting #"); pw.print(i); 10344 pw.print(' '); pw.print(token); 10345 if (dumpAll) { 10346 pw.println(':'); 10347 token.dump(pw, " "); 10348 } else { 10349 pw.println(); 10350 } 10351 } 10352 } 10353 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10354 pw.println(); 10355 if (mOpeningApps.size() > 0) { 10356 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10357 } 10358 if (mClosingApps.size() > 0) { 10359 pw.print(" mClosingApps="); pw.println(mClosingApps); 10360 } 10361 } 10362 } 10363 10364 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10365 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10366 if (mSessions.size() > 0) { 10367 Iterator<Session> it = mSessions.iterator(); 10368 while (it.hasNext()) { 10369 Session s = it.next(); 10370 pw.print(" Session "); pw.print(s); pw.println(':'); 10371 s.dump(pw, " "); 10372 } 10373 } 10374 } 10375 10376 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10377 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10378 if (mDisplayReady) { 10379 final int numDisplays = mDisplayContents.size(); 10380 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10381 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10382 displayContent.dump(" ", pw); 10383 } 10384 } else { 10385 pw.println(" NO DISPLAY"); 10386 } 10387 } 10388 10389 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10390 ArrayList<WindowState> windows) { 10391 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10392 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10393 } 10394 10395 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10396 ArrayList<WindowState> windows) { 10397 final int numDisplays = mDisplayContents.size(); 10398 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10399 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10400 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10401 final WindowState w = windowList.get(winNdx); 10402 if (windows == null || windows.contains(w)) { 10403 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10404 pw.print(w); pw.println(":"); 10405 w.dump(pw, " ", dumpAll || windows != null); 10406 } 10407 } 10408 } 10409 if (mInputMethodDialogs.size() > 0) { 10410 pw.println(); 10411 pw.println(" Input method dialogs:"); 10412 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10413 WindowState w = mInputMethodDialogs.get(i); 10414 if (windows == null || windows.contains(w)) { 10415 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10416 } 10417 } 10418 } 10419 if (mPendingRemove.size() > 0) { 10420 pw.println(); 10421 pw.println(" Remove pending for:"); 10422 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10423 WindowState w = mPendingRemove.get(i); 10424 if (windows == null || windows.contains(w)) { 10425 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10426 pw.print(w); 10427 if (dumpAll) { 10428 pw.println(":"); 10429 w.dump(pw, " ", true); 10430 } else { 10431 pw.println(); 10432 } 10433 } 10434 } 10435 } 10436 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10437 pw.println(); 10438 pw.println(" Windows force removing:"); 10439 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10440 WindowState w = mForceRemoves.get(i); 10441 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10442 pw.print(w); 10443 if (dumpAll) { 10444 pw.println(":"); 10445 w.dump(pw, " ", true); 10446 } else { 10447 pw.println(); 10448 } 10449 } 10450 } 10451 if (mDestroySurface.size() > 0) { 10452 pw.println(); 10453 pw.println(" Windows waiting to destroy their surface:"); 10454 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10455 WindowState w = mDestroySurface.get(i); 10456 if (windows == null || windows.contains(w)) { 10457 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10458 pw.print(w); 10459 if (dumpAll) { 10460 pw.println(":"); 10461 w.dump(pw, " ", true); 10462 } else { 10463 pw.println(); 10464 } 10465 } 10466 } 10467 } 10468 if (mLosingFocus.size() > 0) { 10469 pw.println(); 10470 pw.println(" Windows losing focus:"); 10471 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10472 WindowState w = mLosingFocus.get(i); 10473 if (windows == null || windows.contains(w)) { 10474 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10475 pw.print(w); 10476 if (dumpAll) { 10477 pw.println(":"); 10478 w.dump(pw, " ", true); 10479 } else { 10480 pw.println(); 10481 } 10482 } 10483 } 10484 } 10485 if (mResizingWindows.size() > 0) { 10486 pw.println(); 10487 pw.println(" Windows waiting to resize:"); 10488 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10489 WindowState w = mResizingWindows.get(i); 10490 if (windows == null || windows.contains(w)) { 10491 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10492 pw.print(w); 10493 if (dumpAll) { 10494 pw.println(":"); 10495 w.dump(pw, " ", true); 10496 } else { 10497 pw.println(); 10498 } 10499 } 10500 } 10501 } 10502 if (mWaitingForDrawn.size() > 0) { 10503 pw.println(); 10504 pw.println(" Clients waiting for these windows to be drawn:"); 10505 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10506 WindowState win = mWaitingForDrawn.get(i); 10507 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10508 } 10509 } 10510 pw.println(); 10511 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10512 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10513 if (mLastFocus != mCurrentFocus) { 10514 pw.print(" mLastFocus="); pw.println(mLastFocus); 10515 } 10516 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10517 if (mInputMethodTarget != null) { 10518 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10519 } 10520 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10521 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10522 pw.print(" mLastDisplayFreezeDuration="); 10523 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10524 if ( mLastFinishedFreezeSource != null) { 10525 pw.print(" due to "); 10526 pw.print(mLastFinishedFreezeSource); 10527 } 10528 pw.println(); 10529 if (dumpAll) { 10530 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10531 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10532 if (mLastStatusBarVisibility != 0) { 10533 pw.print(" mLastStatusBarVisibility=0x"); 10534 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10535 } 10536 if (mInputMethodWindow != null) { 10537 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10538 } 10539 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10540 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10541 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10542 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10543 } 10544 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10545 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10546 if (mInputMethodAnimLayerAdjustment != 0 || 10547 mWallpaperAnimLayerAdjustment != 0) { 10548 pw.print(" mInputMethodAnimLayerAdjustment="); 10549 pw.print(mInputMethodAnimLayerAdjustment); 10550 pw.print(" mWallpaperAnimLayerAdjustment="); 10551 pw.println(mWallpaperAnimLayerAdjustment); 10552 } 10553 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10554 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10555 if (needsLayout()) { 10556 pw.print(" layoutNeeded on displays="); 10557 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10558 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10559 if (displayContent.layoutNeeded) { 10560 pw.print(displayContent.getDisplayId()); 10561 } 10562 } 10563 pw.println(); 10564 } 10565 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10566 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10567 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10568 pw.print(" client="); pw.print(mClientFreezingScreen); 10569 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10570 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10571 pw.print(" mRotation="); pw.print(mRotation); 10572 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10573 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10574 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10575 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10576 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 10577 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 10578 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 10579 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10580 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10581 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10582 pw.println(" mLayoutToAnim:"); 10583 mAppTransition.dump(pw); 10584 } 10585 } 10586 10587 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10588 int opti, boolean dumpAll) { 10589 WindowList windows = new WindowList(); 10590 if ("visible".equals(name)) { 10591 synchronized(mWindowMap) { 10592 final int numDisplays = mDisplayContents.size(); 10593 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10594 final WindowList windowList = 10595 mDisplayContents.valueAt(displayNdx).getWindowList(); 10596 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10597 final WindowState w = windowList.get(winNdx); 10598 if (w.mWinAnimator.mSurfaceShown) { 10599 windows.add(w); 10600 } 10601 } 10602 } 10603 } 10604 } else { 10605 int objectId = 0; 10606 // See if this is an object ID. 10607 try { 10608 objectId = Integer.parseInt(name, 16); 10609 name = null; 10610 } catch (RuntimeException e) { 10611 } 10612 synchronized(mWindowMap) { 10613 final int numDisplays = mDisplayContents.size(); 10614 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10615 final WindowList windowList = 10616 mDisplayContents.valueAt(displayNdx).getWindowList(); 10617 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10618 final WindowState w = windowList.get(winNdx); 10619 if (name != null) { 10620 if (w.mAttrs.getTitle().toString().contains(name)) { 10621 windows.add(w); 10622 } 10623 } else if (System.identityHashCode(w) == objectId) { 10624 windows.add(w); 10625 } 10626 } 10627 } 10628 } 10629 } 10630 10631 if (windows.size() <= 0) { 10632 return false; 10633 } 10634 10635 synchronized(mWindowMap) { 10636 dumpWindowsLocked(pw, dumpAll, windows); 10637 } 10638 return true; 10639 } 10640 10641 void dumpLastANRLocked(PrintWriter pw) { 10642 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10643 if (mLastANRState == null) { 10644 pw.println(" <no ANR has occurred since boot>"); 10645 } else { 10646 pw.println(mLastANRState); 10647 } 10648 } 10649 10650 /** 10651 * Saves information about the state of the window manager at 10652 * the time an ANR occurred before anything else in the system changes 10653 * in response. 10654 * 10655 * @param appWindowToken The application that ANR'd, may be null. 10656 * @param windowState The window that ANR'd, may be null. 10657 * @param reason The reason for the ANR, may be null. 10658 */ 10659 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10660 String reason) { 10661 StringWriter sw = new StringWriter(); 10662 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10663 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10664 if (appWindowToken != null) { 10665 pw.println(" Application at fault: " + appWindowToken.stringName); 10666 } 10667 if (windowState != null) { 10668 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10669 } 10670 if (reason != null) { 10671 pw.println(" Reason: " + reason); 10672 } 10673 pw.println(); 10674 dumpWindowsNoHeaderLocked(pw, true, null); 10675 pw.close(); 10676 mLastANRState = sw.toString(); 10677 } 10678 10679 @Override 10680 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10681 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10682 != PackageManager.PERMISSION_GRANTED) { 10683 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10684 + Binder.getCallingPid() 10685 + ", uid=" + Binder.getCallingUid()); 10686 return; 10687 } 10688 10689 boolean dumpAll = false; 10690 10691 int opti = 0; 10692 while (opti < args.length) { 10693 String opt = args[opti]; 10694 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10695 break; 10696 } 10697 opti++; 10698 if ("-a".equals(opt)) { 10699 dumpAll = true; 10700 } else if ("-h".equals(opt)) { 10701 pw.println("Window manager dump options:"); 10702 pw.println(" [-a] [-h] [cmd] ..."); 10703 pw.println(" cmd may be one of:"); 10704 pw.println(" l[astanr]: last ANR information"); 10705 pw.println(" p[policy]: policy state"); 10706 pw.println(" a[animator]: animator state"); 10707 pw.println(" s[essions]: active sessions"); 10708 pw.println(" d[isplays]: active display contents"); 10709 pw.println(" t[okens]: token list"); 10710 pw.println(" w[indows]: window list"); 10711 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10712 pw.println(" be a partial substring in a window name, a"); 10713 pw.println(" Window hex object identifier, or"); 10714 pw.println(" \"all\" for all windows, or"); 10715 pw.println(" \"visible\" for the visible windows."); 10716 pw.println(" -a: include all available server state."); 10717 return; 10718 } else { 10719 pw.println("Unknown argument: " + opt + "; use -h for help"); 10720 } 10721 } 10722 10723 // Is the caller requesting to dump a particular piece of data? 10724 if (opti < args.length) { 10725 String cmd = args[opti]; 10726 opti++; 10727 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10728 synchronized(mWindowMap) { 10729 dumpLastANRLocked(pw); 10730 } 10731 return; 10732 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10733 synchronized(mWindowMap) { 10734 dumpPolicyLocked(pw, args, true); 10735 } 10736 return; 10737 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10738 synchronized(mWindowMap) { 10739 dumpAnimatorLocked(pw, args, true); 10740 } 10741 return; 10742 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10743 synchronized(mWindowMap) { 10744 dumpSessionsLocked(pw, true); 10745 } 10746 return; 10747 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10748 synchronized(mWindowMap) { 10749 dumpDisplayContentsLocked(pw, true); 10750 } 10751 return; 10752 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10753 synchronized(mWindowMap) { 10754 dumpTokensLocked(pw, true); 10755 } 10756 return; 10757 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10758 synchronized(mWindowMap) { 10759 dumpWindowsLocked(pw, true, null); 10760 } 10761 return; 10762 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10763 synchronized(mWindowMap) { 10764 dumpWindowsLocked(pw, true, null); 10765 } 10766 return; 10767 } else { 10768 // Dumping a single name? 10769 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10770 pw.println("Bad window command, or no windows match: " + cmd); 10771 pw.println("Use -h for help."); 10772 } 10773 return; 10774 } 10775 } 10776 10777 synchronized(mWindowMap) { 10778 pw.println(); 10779 if (dumpAll) { 10780 pw.println("-------------------------------------------------------------------------------"); 10781 } 10782 dumpLastANRLocked(pw); 10783 pw.println(); 10784 if (dumpAll) { 10785 pw.println("-------------------------------------------------------------------------------"); 10786 } 10787 dumpPolicyLocked(pw, args, dumpAll); 10788 pw.println(); 10789 if (dumpAll) { 10790 pw.println("-------------------------------------------------------------------------------"); 10791 } 10792 dumpAnimatorLocked(pw, args, dumpAll); 10793 pw.println(); 10794 if (dumpAll) { 10795 pw.println("-------------------------------------------------------------------------------"); 10796 } 10797 dumpSessionsLocked(pw, dumpAll); 10798 pw.println(); 10799 if (dumpAll) { 10800 pw.println("-------------------------------------------------------------------------------"); 10801 } 10802 dumpDisplayContentsLocked(pw, dumpAll); 10803 pw.println(); 10804 if (dumpAll) { 10805 pw.println("-------------------------------------------------------------------------------"); 10806 } 10807 dumpTokensLocked(pw, dumpAll); 10808 pw.println(); 10809 if (dumpAll) { 10810 pw.println("-------------------------------------------------------------------------------"); 10811 } 10812 dumpWindowsLocked(pw, dumpAll, null); 10813 } 10814 } 10815 10816 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10817 @Override 10818 public void monitor() { 10819 synchronized (mWindowMap) { } 10820 } 10821 10822 public interface OnHardKeyboardStatusChangeListener { 10823 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10824 } 10825 10826 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10827 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10828 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10829 Integer.toHexString(pendingLayoutChanges)); 10830 } 10831 } 10832 10833 private DisplayContent newDisplayContentLocked(final Display display) { 10834 DisplayContent displayContent = new DisplayContent(display, this); 10835 final int displayId = display.getDisplayId(); 10836 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 10837 mDisplayContents.put(displayId, displayContent); 10838 10839 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10840 final Rect rect = new Rect(); 10841 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 10842 synchronized (displayContent.mDisplaySizeLock) { 10843 displayInfo.overscanLeft = rect.left; 10844 displayInfo.overscanTop = rect.top; 10845 displayInfo.overscanRight = rect.right; 10846 displayInfo.overscanBottom = rect.bottom; 10847 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 10848 displayId, displayInfo); 10849 } 10850 configureDisplayPolicyLocked(displayContent); 10851 10852 // TODO: Create an input channel for each display with touch capability. 10853 if (displayId == Display.DEFAULT_DISPLAY) { 10854 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 10855 registerPointerEventListener(displayContent.mTapDetector); 10856 } 10857 10858 return displayContent; 10859 } 10860 10861 public void createDisplayContentLocked(final Display display) { 10862 if (display == null) { 10863 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10864 } 10865 getDisplayContentLocked(display.getDisplayId()); 10866 } 10867 10868 /** 10869 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10870 * there is a Display for the displayId. 10871 * @param displayId The display the caller is interested in. 10872 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10873 */ 10874 public DisplayContent getDisplayContentLocked(final int displayId) { 10875 DisplayContent displayContent = mDisplayContents.get(displayId); 10876 if (displayContent == null) { 10877 final Display display = mDisplayManager.getDisplay(displayId); 10878 if (display != null) { 10879 displayContent = newDisplayContentLocked(display); 10880 } 10881 } 10882 return displayContent; 10883 } 10884 10885 // There is an inherent assumption that this will never return null. 10886 public DisplayContent getDefaultDisplayContentLocked() { 10887 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10888 } 10889 10890 public WindowList getDefaultWindowListLocked() { 10891 return getDefaultDisplayContentLocked().getWindowList(); 10892 } 10893 10894 public DisplayInfo getDefaultDisplayInfoLocked() { 10895 return getDefaultDisplayContentLocked().getDisplayInfo(); 10896 } 10897 10898 /** 10899 * Return the list of WindowStates associated on the passed display. 10900 * @param display The screen to return windows from. 10901 * @return The list of WindowStates on the screen, or null if the there is no screen. 10902 */ 10903 public WindowList getWindowListLocked(final Display display) { 10904 return getWindowListLocked(display.getDisplayId()); 10905 } 10906 10907 /** 10908 * Return the list of WindowStates associated on the passed display. 10909 * @param displayId The screen to return windows from. 10910 * @return The list of WindowStates on the screen, or null if the there is no screen. 10911 */ 10912 public WindowList getWindowListLocked(final int displayId) { 10913 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10914 return displayContent != null ? displayContent.getWindowList() : null; 10915 } 10916 10917 public void onDisplayAdded(int displayId) { 10918 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10919 } 10920 10921 public void handleDisplayAdded(int displayId) { 10922 synchronized (mWindowMap) { 10923 final Display display = mDisplayManager.getDisplay(displayId); 10924 if (display != null) { 10925 createDisplayContentLocked(display); 10926 displayReady(displayId); 10927 } 10928 } 10929 } 10930 10931 public void onDisplayRemoved(int displayId) { 10932 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 10933 } 10934 10935 private void handleDisplayRemovedLocked(int displayId) { 10936 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10937 if (displayContent != null) { 10938 if (displayContent.isAnimating()) { 10939 displayContent.mDeferredRemoval = true; 10940 return; 10941 } 10942 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 10943 mDisplayContents.delete(displayId); 10944 displayContent.close(); 10945 if (displayId == Display.DEFAULT_DISPLAY) { 10946 unregisterPointerEventListener(displayContent.mTapDetector); 10947 } 10948 } 10949 mAnimator.removeDisplayLocked(displayId); 10950 } 10951 10952 public void onDisplayChanged(int displayId) { 10953 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 10954 } 10955 10956 private void handleDisplayChangedLocked(int displayId) { 10957 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10958 if (displayContent != null) { 10959 displayContent.updateDisplayInfo(); 10960 } 10961 } 10962 10963 @Override 10964 public Object getWindowManagerLock() { 10965 return mWindowMap; 10966 } 10967 10968 private final class LocalService extends WindowManagerInternal { 10969 @Override 10970 public void requestTraversalFromDisplayManager() { 10971 requestTraversal(); 10972 } 10973 10974 @Override 10975 public void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout) { 10976 synchronized (mWindowMap) { 10977 mWaitingForDrawnCallback = callback; 10978 final WindowList windows = getDefaultWindowListLocked(); 10979 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 10980 final WindowState win = windows.get(winNdx); 10981 if (win.mHasSurface) { 10982 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 10983 // Force add to mResizingWindows. 10984 win.mLastContentInsets.set(-1, -1, -1, -1); 10985 mWaitingForDrawn.add(win); 10986 } 10987 } 10988 requestTraversalLocked(); 10989 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 10990 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 10991 } 10992 checkDrawnWindowsLocked(); 10993 } 10994 } 10995} 10996