WindowManagerService.java revision 22af5b842869abff5418263e6fb0b4b925077629
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 } else { 3550 newTask.mAppTokens.add(atoken); 3551 } 3552 } 3553 } 3554 3555 public int getOrientationFromWindowsLocked() { 3556 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 3557 // If the display is frozen, some activities may be in the middle 3558 // of restarting, and thus have removed their old window. If the 3559 // window has the flag to hide the lock screen, then the lock screen 3560 // can re-appear and inflict its own orientation on us. Keep the 3561 // orientation stable until this all settles down. 3562 return mLastWindowForcedOrientation; 3563 } 3564 3565 // TODO(multidisplay): Change to the correct display. 3566 final WindowList windows = getDefaultWindowListLocked(); 3567 int pos = windows.size() - 1; 3568 while (pos >= 0) { 3569 WindowState win = windows.get(pos); 3570 pos--; 3571 if (win.mAppToken != null) { 3572 // We hit an application window. so the orientation will be determined by the 3573 // app window. No point in continuing further. 3574 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3575 } 3576 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) { 3577 continue; 3578 } 3579 int req = win.mAttrs.screenOrientation; 3580 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) || 3581 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){ 3582 continue; 3583 } 3584 3585 if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req); 3586 return (mLastWindowForcedOrientation=req); 3587 } 3588 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3589 } 3590 3591 public int getOrientationFromAppTokensLocked() { 3592 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3593 boolean findingBehind = false; 3594 boolean lastFullscreen = false; 3595 // TODO: Multi window. 3596 DisplayContent displayContent = getDefaultDisplayContentLocked(); 3597 final ArrayList<Task> tasks = displayContent.getTasks(); 3598 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 3599 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 3600 final int firstToken = tokens.size() - 1; 3601 for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) { 3602 final AppWindowToken atoken = tokens.get(tokenNdx); 3603 3604 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken); 3605 3606 // if we're about to tear down this window and not seek for 3607 // the behind activity, don't use it for orientation 3608 if (!findingBehind 3609 && (!atoken.hidden && atoken.hiddenRequested)) { 3610 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3611 + " -- going to hide"); 3612 continue; 3613 } 3614 3615 if (tokenNdx == firstToken) { 3616 // If we have hit a new Task, and the bottom 3617 // of the previous group didn't explicitly say to use 3618 // the orientation behind it, and the last app was 3619 // full screen, then we'll stick with the 3620 // user's orientation. 3621 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND 3622 && lastFullscreen) { 3623 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3624 + " -- end of group, return " + lastOrientation); 3625 return lastOrientation; 3626 } 3627 } 3628 3629 // We ignore any hidden applications on the top. 3630 if (atoken.hiddenRequested || atoken.willBeHidden) { 3631 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3632 + " -- hidden on top"); 3633 continue; 3634 } 3635 3636 if (tokenNdx == 0) { 3637 // Last token in this task. 3638 lastOrientation = atoken.requestedOrientation; 3639 } 3640 3641 int or = atoken.requestedOrientation; 3642 // If this application is fullscreen, and didn't explicitly say 3643 // to use the orientation behind it, then just take whatever 3644 // orientation it has and ignores whatever is under it. 3645 lastFullscreen = atoken.appFullscreen; 3646 if (lastFullscreen 3647 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3648 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3649 + " -- full screen, return " + or); 3650 return or; 3651 } 3652 // If this application has requested an explicit orientation, 3653 // then use it. 3654 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 3655 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3656 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3657 + " -- explicitly set, return " + or); 3658 return or; 3659 } 3660 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND); 3661 } 3662 } 3663 if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation"); 3664 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3665 } 3666 3667 @Override 3668 public Configuration updateOrientationFromAppTokens( 3669 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3670 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3671 "updateOrientationFromAppTokens()")) { 3672 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3673 } 3674 3675 Configuration config = null; 3676 long ident = Binder.clearCallingIdentity(); 3677 3678 synchronized(mWindowMap) { 3679 config = updateOrientationFromAppTokensLocked(currentConfig, 3680 freezeThisOneIfNeeded); 3681 } 3682 3683 Binder.restoreCallingIdentity(ident); 3684 return config; 3685 } 3686 3687 private Configuration updateOrientationFromAppTokensLocked( 3688 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3689 Configuration config = null; 3690 3691 if (updateOrientationFromAppTokensLocked(false)) { 3692 if (freezeThisOneIfNeeded != null) { 3693 AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded); 3694 if (atoken != null) { 3695 startAppFreezingScreenLocked(atoken); 3696 } 3697 } 3698 config = computeNewConfigurationLocked(); 3699 3700 } else if (currentConfig != null) { 3701 // No obvious action we need to take, but if our current 3702 // state mismatches the activity manager's, update it, 3703 // disregarding font scale, which should remain set to 3704 // the value of the previous configuration. 3705 mTempConfiguration.setToDefaults(); 3706 mTempConfiguration.fontScale = currentConfig.fontScale; 3707 if (computeScreenConfigurationLocked(mTempConfiguration)) { 3708 if (currentConfig.diff(mTempConfiguration) != 0) { 3709 mWaitingForConfig = true; 3710 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 3711 displayContent.layoutNeeded = true; 3712 int anim[] = new int[2]; 3713 if (displayContent.isDimming()) { 3714 anim[0] = anim[1] = 0; 3715 } else { 3716 mPolicy.selectRotationAnimationLw(anim); 3717 } 3718 startFreezingDisplayLocked(false, anim[0], anim[1]); 3719 config = new Configuration(mTempConfiguration); 3720 } 3721 } 3722 } 3723 3724 return config; 3725 } 3726 3727 /* 3728 * Determine the new desired orientation of the display, returning 3729 * a non-null new Configuration if it has changed from the current 3730 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL 3731 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE 3732 * SCREEN. This will typically be done for you if you call 3733 * sendNewConfiguration(). 3734 * 3735 * The orientation is computed from non-application windows first. If none of 3736 * the non-application windows specify orientation, the orientation is computed from 3737 * application tokens. 3738 * @see android.view.IWindowManager#updateOrientationFromAppTokens( 3739 * android.os.IBinder) 3740 */ 3741 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) { 3742 long ident = Binder.clearCallingIdentity(); 3743 try { 3744 int req = getOrientationFromWindowsLocked(); 3745 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { 3746 req = getOrientationFromAppTokensLocked(); 3747 } 3748 3749 if (req != mForcedAppOrientation) { 3750 mForcedAppOrientation = req; 3751 //send a message to Policy indicating orientation change to take 3752 //action like disabling/enabling sensors etc., 3753 mPolicy.setCurrentOrientationLw(req); 3754 if (updateRotationUncheckedLocked(inTransaction)) { 3755 // changed 3756 return true; 3757 } 3758 } 3759 3760 return false; 3761 } finally { 3762 Binder.restoreCallingIdentity(ident); 3763 } 3764 } 3765 3766 @Override 3767 public void setNewConfiguration(Configuration config) { 3768 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3769 "setNewConfiguration()")) { 3770 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3771 } 3772 3773 synchronized(mWindowMap) { 3774 mCurConfiguration = new Configuration(config); 3775 if (mWaitingForConfig) { 3776 mWaitingForConfig = false; 3777 mLastFinishedFreezeSource = "new-config"; 3778 } 3779 performLayoutAndPlaceSurfacesLocked(); 3780 } 3781 } 3782 3783 @Override 3784 public void setAppOrientation(IApplicationToken token, int requestedOrientation) { 3785 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3786 "setAppOrientation()")) { 3787 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3788 } 3789 3790 synchronized(mWindowMap) { 3791 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3792 if (atoken == null) { 3793 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token); 3794 return; 3795 } 3796 3797 atoken.requestedOrientation = requestedOrientation; 3798 } 3799 } 3800 3801 @Override 3802 public int getAppOrientation(IApplicationToken token) { 3803 synchronized(mWindowMap) { 3804 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 3805 if (wtoken == null) { 3806 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3807 } 3808 3809 return wtoken.requestedOrientation; 3810 } 3811 } 3812 3813 /** Call while in a Surface transaction. */ 3814 void setFocusedStackLayer() { 3815 mFocusedStackLayer = 0; 3816 if (mFocusedApp != null) { 3817 final WindowList windows = mFocusedApp.allAppWindows; 3818 for (int i = windows.size() - 1; i >= 0; --i) { 3819 final WindowState win = windows.get(i); 3820 final int animLayer = win.mWinAnimator.mAnimLayer; 3821 if (win.mAttachedWindow == null && win.isVisibleLw() && 3822 animLayer > mFocusedStackLayer) { 3823 mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK; 3824 } 3825 } 3826 } 3827 if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" + 3828 mFocusedStackLayer); 3829 mFocusedStackFrame.setLayer(mFocusedStackLayer); 3830 } 3831 3832 void setFocusedStackFrame() { 3833 final TaskStack stack; 3834 if (mFocusedApp != null) { 3835 Task task = mTaskIdToTask.get(mFocusedApp.groupId); 3836 stack = task.mStack; 3837 final DisplayContent displayContent = task.getDisplayContent(); 3838 if (displayContent != null) { 3839 displayContent.setTouchExcludeRegion(stack); 3840 } 3841 } else { 3842 stack = null; 3843 } 3844 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame"); 3845 SurfaceControl.openTransaction(); 3846 try { 3847 if (stack == null) { 3848 mFocusedStackFrame.setVisibility(false); 3849 } else { 3850 mFocusedStackFrame.setBounds(stack); 3851 final boolean multipleStacks = !stack.isFullscreen(); 3852 mFocusedStackFrame.setVisibility(multipleStacks); 3853 } 3854 } finally { 3855 SurfaceControl.closeTransaction(); 3856 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame"); 3857 } 3858 } 3859 3860 @Override 3861 public void setFocusedApp(IBinder token, boolean moveFocusNow) { 3862 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3863 "setFocusedApp()")) { 3864 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3865 } 3866 3867 synchronized(mWindowMap) { 3868 final AppWindowToken newFocus; 3869 if (token == null) { 3870 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); 3871 newFocus = null; 3872 } else { 3873 newFocus = findAppWindowToken(token); 3874 if (newFocus == null) { 3875 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); 3876 } 3877 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus 3878 + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow); 3879 } 3880 3881 final boolean changed = mFocusedApp != newFocus; 3882 if (changed) { 3883 mFocusedApp = newFocus; 3884 mInputMonitor.setFocusedAppLw(null); 3885 } 3886 3887 if (moveFocusNow && changed) { 3888 final long origId = Binder.clearCallingIdentity(); 3889 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 3890 Binder.restoreCallingIdentity(origId); 3891 } 3892 } 3893 } 3894 3895 @Override 3896 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { 3897 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3898 "prepareAppTransition()")) { 3899 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3900 } 3901 3902 synchronized(mWindowMap) { 3903 if (DEBUG_APP_TRANSITIONS) Slog.v( 3904 TAG, "Prepare app transition: transit=" + transit 3905 + " " + mAppTransition 3906 + " alwaysKeepCurrent=" + alwaysKeepCurrent 3907 + " Callers=" + Debug.getCallers(3)); 3908 if (okToDisplay()) { 3909 if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) { 3910 mAppTransition.setAppTransition(transit); 3911 } else if (!alwaysKeepCurrent) { 3912 if (transit == AppTransition.TRANSIT_TASK_OPEN 3913 && mAppTransition.isTransitionEqual( 3914 AppTransition.TRANSIT_TASK_CLOSE)) { 3915 // Opening a new task always supersedes a close for the anim. 3916 mAppTransition.setAppTransition(transit); 3917 } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN 3918 && mAppTransition.isTransitionEqual( 3919 AppTransition.TRANSIT_ACTIVITY_CLOSE)) { 3920 // Opening a new activity always supersedes a close for the anim. 3921 mAppTransition.setAppTransition(transit); 3922 } 3923 } 3924 mAppTransition.prepare(); 3925 mStartingIconInTransition = false; 3926 mSkipAppTransitionAnimation = false; 3927 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 3928 mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000); 3929 } 3930 } 3931 } 3932 3933 @Override 3934 public int getPendingAppTransition() { 3935 return mAppTransition.getAppTransition(); 3936 } 3937 3938 @Override 3939 public void overridePendingAppTransition(String packageName, 3940 int enterAnim, int exitAnim, IRemoteCallback startedCallback) { 3941 synchronized(mWindowMap) { 3942 mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim, 3943 startedCallback); 3944 } 3945 } 3946 3947 @Override 3948 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 3949 int startHeight) { 3950 synchronized(mWindowMap) { 3951 mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth, 3952 startHeight); 3953 } 3954 } 3955 3956 @Override 3957 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, 3958 int startY, IRemoteCallback startedCallback, boolean scaleUp) { 3959 synchronized(mWindowMap) { 3960 mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY, 3961 startedCallback, scaleUp); 3962 } 3963 } 3964 3965 @Override 3966 public void executeAppTransition() { 3967 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3968 "executeAppTransition()")) { 3969 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3970 } 3971 3972 synchronized(mWindowMap) { 3973 if (DEBUG_APP_TRANSITIONS) { 3974 RuntimeException e = new RuntimeException("here"); 3975 e.fillInStackTrace(); 3976 Slog.w(TAG, "Execute app transition: " + mAppTransition, e); 3977 } 3978 if (mAppTransition.isTransitionSet()) { 3979 mAppTransition.setReady(); 3980 final long origId = Binder.clearCallingIdentity(); 3981 performLayoutAndPlaceSurfacesLocked(); 3982 Binder.restoreCallingIdentity(origId); 3983 } 3984 } 3985 } 3986 3987 @Override 3988 public void setAppStartingWindow(IBinder token, String pkg, 3989 int theme, CompatibilityInfo compatInfo, 3990 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, 3991 int windowFlags, IBinder transferFrom, boolean createIfNeeded) { 3992 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3993 "setAppStartingWindow()")) { 3994 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3995 } 3996 3997 synchronized(mWindowMap) { 3998 if (DEBUG_STARTING_WINDOW) Slog.v( 3999 TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg 4000 + " transferFrom=" + transferFrom); 4001 4002 AppWindowToken wtoken = findAppWindowToken(token); 4003 if (wtoken == null) { 4004 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token); 4005 return; 4006 } 4007 4008 // If the display is frozen, we won't do anything until the 4009 // actual window is displayed so there is no reason to put in 4010 // the starting window. 4011 if (!okToDisplay()) { 4012 return; 4013 } 4014 4015 if (wtoken.startingData != null) { 4016 return; 4017 } 4018 4019 if (transferFrom != null) { 4020 AppWindowToken ttoken = findAppWindowToken(transferFrom); 4021 if (ttoken != null) { 4022 WindowState startingWindow = ttoken.startingWindow; 4023 if (startingWindow != null) { 4024 if (mStartingIconInTransition) { 4025 // In this case, the starting icon has already 4026 // been displayed, so start letting windows get 4027 // shown immediately without any more transitions. 4028 mSkipAppTransitionAnimation = true; 4029 } 4030 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4031 "Moving existing starting " + startingWindow + " from " + ttoken 4032 + " to " + wtoken); 4033 final long origId = Binder.clearCallingIdentity(); 4034 4035 // Transfer the starting window over to the new 4036 // token. 4037 wtoken.startingData = ttoken.startingData; 4038 wtoken.startingView = ttoken.startingView; 4039 wtoken.startingDisplayed = ttoken.startingDisplayed; 4040 ttoken.startingDisplayed = false; 4041 wtoken.startingWindow = startingWindow; 4042 wtoken.reportedVisible = ttoken.reportedVisible; 4043 ttoken.startingData = null; 4044 ttoken.startingView = null; 4045 ttoken.startingWindow = null; 4046 ttoken.startingMoved = true; 4047 startingWindow.mToken = wtoken; 4048 startingWindow.mRootToken = wtoken; 4049 startingWindow.mAppToken = wtoken; 4050 startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator; 4051 4052 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { 4053 Slog.v(TAG, "Removing starting window: " + startingWindow); 4054 } 4055 removeStartingWindowTimeout(ttoken); 4056 startingWindow.getWindowList().remove(startingWindow); 4057 mWindowsChanged = true; 4058 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 4059 "Removing starting " + startingWindow + " from " + ttoken); 4060 ttoken.windows.remove(startingWindow); 4061 ttoken.allAppWindows.remove(startingWindow); 4062 addWindowToListInOrderLocked(startingWindow, true); 4063 4064 // Propagate other interesting state between the 4065 // tokens. If the old token is displayed, we should 4066 // immediately force the new one to be displayed. If 4067 // it is animating, we need to move that animation to 4068 // the new one. 4069 if (ttoken.allDrawn) { 4070 wtoken.allDrawn = true; 4071 wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn; 4072 } 4073 if (ttoken.firstWindowDrawn) { 4074 wtoken.firstWindowDrawn = true; 4075 } 4076 if (!ttoken.hidden) { 4077 wtoken.hidden = false; 4078 wtoken.hiddenRequested = false; 4079 wtoken.willBeHidden = false; 4080 } 4081 if (wtoken.clientHidden != ttoken.clientHidden) { 4082 wtoken.clientHidden = ttoken.clientHidden; 4083 wtoken.sendAppVisibilityToClients(); 4084 } 4085 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4086 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4087 if (tAppAnimator.animation != null) { 4088 wAppAnimator.animation = tAppAnimator.animation; 4089 wAppAnimator.animating = tAppAnimator.animating; 4090 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; 4091 tAppAnimator.animation = null; 4092 tAppAnimator.animLayerAdjustment = 0; 4093 wAppAnimator.updateLayers(); 4094 tAppAnimator.updateLayers(); 4095 } 4096 4097 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4098 true /*updateInputWindows*/); 4099 getDefaultDisplayContentLocked().layoutNeeded = true; 4100 performLayoutAndPlaceSurfacesLocked(); 4101 Binder.restoreCallingIdentity(origId); 4102 return; 4103 } else if (ttoken.startingData != null) { 4104 // The previous app was getting ready to show a 4105 // starting window, but hasn't yet done so. Steal it! 4106 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4107 "Moving pending starting from " + ttoken 4108 + " to " + wtoken); 4109 wtoken.startingData = ttoken.startingData; 4110 ttoken.startingData = null; 4111 ttoken.startingMoved = true; 4112 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4113 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4114 // want to process the message ASAP, before any other queued 4115 // messages. 4116 mH.sendMessageAtFrontOfQueue(m); 4117 return; 4118 } 4119 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4120 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4121 if (tAppAnimator.thumbnail != null) { 4122 // The old token is animating with a thumbnail, transfer 4123 // that to the new token. 4124 if (wAppAnimator.thumbnail != null) { 4125 wAppAnimator.thumbnail.destroy(); 4126 } 4127 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 4128 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX; 4129 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY; 4130 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 4131 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 4132 tAppAnimator.thumbnail = null; 4133 } 4134 } 4135 } 4136 4137 // There is no existing starting window, and the caller doesn't 4138 // want us to create one, so that's it! 4139 if (!createIfNeeded) { 4140 return; 4141 } 4142 4143 // If this is a translucent window, then don't 4144 // show a starting window -- the current effect (a full-screen 4145 // opaque starting window that fades away to the real contents 4146 // when it is ready) does not work for this. 4147 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x" 4148 + Integer.toHexString(theme)); 4149 if (theme != 0) { 4150 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 4151 com.android.internal.R.styleable.Window, mCurrentUserId); 4152 if (ent == null) { 4153 // Whoops! App doesn't exist. Um. Okay. We'll just 4154 // pretend like we didn't see that. 4155 return; 4156 } 4157 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent=" 4158 + ent.array.getBoolean( 4159 com.android.internal.R.styleable.Window_windowIsTranslucent, false) 4160 + " Floating=" 4161 + ent.array.getBoolean( 4162 com.android.internal.R.styleable.Window_windowIsFloating, false) 4163 + " ShowWallpaper=" 4164 + ent.array.getBoolean( 4165 com.android.internal.R.styleable.Window_windowShowWallpaper, false)); 4166 if (ent.array.getBoolean( 4167 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { 4168 return; 4169 } 4170 if (ent.array.getBoolean( 4171 com.android.internal.R.styleable.Window_windowIsFloating, false)) { 4172 return; 4173 } 4174 if (ent.array.getBoolean( 4175 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { 4176 if (mWallpaperTarget == null) { 4177 // If this theme is requesting a wallpaper, and the wallpaper 4178 // is not curently visible, then this effectively serves as 4179 // an opaque window and our starting window transition animation 4180 // can still work. We just need to make sure the starting window 4181 // is also showing the wallpaper. 4182 windowFlags |= FLAG_SHOW_WALLPAPER; 4183 } else { 4184 return; 4185 } 4186 } 4187 } 4188 4189 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); 4190 mStartingIconInTransition = true; 4191 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, 4192 labelRes, icon, logo, windowFlags); 4193 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4194 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4195 // want to process the message ASAP, before any other queued 4196 // messages. 4197 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING"); 4198 mH.sendMessageAtFrontOfQueue(m); 4199 } 4200 } 4201 4202 @Override 4203 public void setAppWillBeHidden(IBinder token) { 4204 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4205 "setAppWillBeHidden()")) { 4206 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4207 } 4208 4209 AppWindowToken wtoken; 4210 4211 synchronized(mWindowMap) { 4212 wtoken = findAppWindowToken(token); 4213 if (wtoken == null) { 4214 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token); 4215 return; 4216 } 4217 wtoken.willBeHidden = true; 4218 } 4219 } 4220 4221 public void setAppFullscreen(IBinder token, boolean toOpaque) { 4222 AppWindowToken atoken = findAppWindowToken(token); 4223 if (atoken != null) { 4224 atoken.appFullscreen = toOpaque; 4225 // When making translucent, wait until windows below have been drawn. 4226 if (toOpaque) { 4227 // Making opaque so do it now. 4228 setWindowOpaque(token, true); 4229 } 4230 requestTraversal(); 4231 } 4232 } 4233 4234 public void setWindowOpaque(IBinder token, boolean isOpaque) { 4235 AppWindowToken wtoken = findAppWindowToken(token); 4236 if (wtoken != null) { 4237 WindowState win = wtoken.findMainWindow(); 4238 if (win != null) { 4239 win.mWinAnimator.setOpaque(isOpaque); 4240 } 4241 } 4242 } 4243 4244 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4245 boolean visible, int transit, boolean performLayout) { 4246 boolean delayed = false; 4247 4248 if (wtoken.clientHidden == visible) { 4249 wtoken.clientHidden = !visible; 4250 wtoken.sendAppVisibilityToClients(); 4251 } 4252 4253 wtoken.willBeHidden = false; 4254 if (wtoken.hidden == visible) { 4255 boolean changed = false; 4256 if (DEBUG_APP_TRANSITIONS) Slog.v( 4257 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4258 + " performLayout=" + performLayout); 4259 4260 boolean runningAppAnimation = false; 4261 4262 if (transit != AppTransition.TRANSIT_UNSET) { 4263 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4264 wtoken.mAppAnimator.animation = null; 4265 } 4266 if (applyAnimationLocked(wtoken, lp, transit, visible)) { 4267 delayed = runningAppAnimation = true; 4268 } 4269 WindowState window = wtoken.findMainWindow(); 4270 //TODO (multidisplay): Magnification is supported only for the default display. 4271 if (window != null && mDisplayMagnifier != null 4272 && window.getDisplayId() == Display.DEFAULT_DISPLAY) { 4273 mDisplayMagnifier.onAppWindowTransitionLocked(window, transit); 4274 } 4275 changed = true; 4276 } 4277 4278 final int N = wtoken.allAppWindows.size(); 4279 for (int i=0; i<N; i++) { 4280 WindowState win = wtoken.allAppWindows.get(i); 4281 if (win == wtoken.startingWindow) { 4282 continue; 4283 } 4284 4285 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); 4286 //win.dump(" "); 4287 if (visible) { 4288 if (!win.isVisibleNow()) { 4289 if (!runningAppAnimation) { 4290 win.mWinAnimator.applyAnimationLocked( 4291 WindowManagerPolicy.TRANSIT_ENTER, true); 4292 //TODO (multidisplay): Magnification is supported only for the default 4293 if (mDisplayMagnifier != null 4294 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4295 mDisplayMagnifier.onWindowTransitionLocked(win, 4296 WindowManagerPolicy.TRANSIT_ENTER); 4297 } 4298 } 4299 changed = true; 4300 final DisplayContent displayContent = win.getDisplayContent(); 4301 if (displayContent != null) { 4302 displayContent.layoutNeeded = true; 4303 } 4304 } 4305 } else if (win.isVisibleNow()) { 4306 if (!runningAppAnimation) { 4307 win.mWinAnimator.applyAnimationLocked( 4308 WindowManagerPolicy.TRANSIT_EXIT, false); 4309 //TODO (multidisplay): Magnification is supported only for the default 4310 if (mDisplayMagnifier != null 4311 && win.getDisplayId() == Display.DEFAULT_DISPLAY) { 4312 mDisplayMagnifier.onWindowTransitionLocked(win, 4313 WindowManagerPolicy.TRANSIT_EXIT); 4314 } 4315 } 4316 changed = true; 4317 final DisplayContent displayContent = win.getDisplayContent(); 4318 if (displayContent != null) { 4319 displayContent.layoutNeeded = true; 4320 } 4321 } 4322 } 4323 4324 wtoken.hidden = wtoken.hiddenRequested = !visible; 4325 if (!visible) { 4326 unsetAppFreezingScreenLocked(wtoken, true, true); 4327 } else { 4328 // If we are being set visible, and the starting window is 4329 // not yet displayed, then make sure it doesn't get displayed. 4330 WindowState swin = wtoken.startingWindow; 4331 if (swin != null && !swin.isDrawnLw()) { 4332 swin.mPolicyVisibility = false; 4333 swin.mPolicyVisibilityAfterAnim = false; 4334 } 4335 } 4336 4337 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken 4338 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4339 + wtoken.hiddenRequested); 4340 4341 if (changed) { 4342 mInputMonitor.setUpdateInputWindowsNeededLw(); 4343 if (performLayout) { 4344 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4345 false /*updateInputWindows*/); 4346 performLayoutAndPlaceSurfacesLocked(); 4347 } 4348 mInputMonitor.updateInputWindowsLw(false /*force*/); 4349 } 4350 } 4351 4352 if (wtoken.mAppAnimator.animation != null) { 4353 delayed = true; 4354 } 4355 4356 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4357 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { 4358 delayed = true; 4359 } 4360 } 4361 4362 return delayed; 4363 } 4364 4365 @Override 4366 public void setAppVisibility(IBinder token, boolean visible) { 4367 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4368 "setAppVisibility()")) { 4369 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4370 } 4371 4372 AppWindowToken wtoken; 4373 4374 synchronized(mWindowMap) { 4375 wtoken = findAppWindowToken(token); 4376 if (wtoken == null) { 4377 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); 4378 return; 4379 } 4380 4381 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) { 4382 RuntimeException e = null; 4383 if (!HIDE_STACK_CRAWLS) { 4384 e = new RuntimeException(); 4385 e.fillInStackTrace(); 4386 } 4387 Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible 4388 + "): " + mAppTransition 4389 + " hidden=" + wtoken.hidden 4390 + " hiddenRequested=" + wtoken.hiddenRequested, e); 4391 } 4392 4393 // If we are preparing an app transition, then delay changing 4394 // the visibility of this token until we execute that transition. 4395 if (okToDisplay() && mAppTransition.isTransitionSet()) { 4396 wtoken.hiddenRequested = !visible; 4397 4398 if (!wtoken.startingDisplayed) { 4399 if (DEBUG_APP_TRANSITIONS) Slog.v( 4400 TAG, "Setting dummy animation on: " + wtoken); 4401 wtoken.mAppAnimator.setDummyAnimation(); 4402 } 4403 mOpeningApps.remove(wtoken); 4404 mClosingApps.remove(wtoken); 4405 wtoken.waitingToShow = wtoken.waitingToHide = false; 4406 wtoken.inPendingTransaction = true; 4407 if (visible) { 4408 mOpeningApps.add(wtoken); 4409 wtoken.startingMoved = false; 4410 4411 // If the token is currently hidden (should be the 4412 // common case), then we need to set up to wait for 4413 // its windows to be ready. 4414 if (wtoken.hidden) { 4415 wtoken.allDrawn = false; 4416 wtoken.deferClearAllDrawn = false; 4417 wtoken.waitingToShow = true; 4418 4419 if (wtoken.clientHidden) { 4420 // In the case where we are making an app visible 4421 // but holding off for a transition, we still need 4422 // to tell the client to make its windows visible so 4423 // they get drawn. Otherwise, we will wait on 4424 // performing the transition until all windows have 4425 // been drawn, they never will be, and we are sad. 4426 wtoken.clientHidden = false; 4427 wtoken.sendAppVisibilityToClients(); 4428 } 4429 } 4430 } else { 4431 mClosingApps.add(wtoken); 4432 4433 // If the token is currently visible (should be the 4434 // common case), then set up to wait for it to be hidden. 4435 if (!wtoken.hidden) { 4436 wtoken.waitingToHide = true; 4437 } 4438 } 4439 return; 4440 } 4441 4442 final long origId = Binder.clearCallingIdentity(); 4443 setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET, 4444 true); 4445 wtoken.updateReportedVisibilityLocked(); 4446 Binder.restoreCallingIdentity(origId); 4447 } 4448 } 4449 4450 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4451 boolean unfreezeSurfaceNow, boolean force) { 4452 if (wtoken.mAppAnimator.freezingScreen) { 4453 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken 4454 + " force=" + force); 4455 final int N = wtoken.allAppWindows.size(); 4456 boolean unfrozeWindows = false; 4457 for (int i=0; i<N; i++) { 4458 WindowState w = wtoken.allAppWindows.get(i); 4459 if (w.mAppFreezing) { 4460 w.mAppFreezing = false; 4461 if (w.mHasSurface && !w.mOrientationChanging) { 4462 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); 4463 w.mOrientationChanging = true; 4464 mInnerFields.mOrientationChangeComplete = false; 4465 } 4466 w.mLastFreezeDuration = 0; 4467 unfrozeWindows = true; 4468 final DisplayContent displayContent = w.getDisplayContent(); 4469 if (displayContent != null) { 4470 displayContent.layoutNeeded = true; 4471 } 4472 } 4473 } 4474 if (force || unfrozeWindows) { 4475 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); 4476 wtoken.mAppAnimator.freezingScreen = false; 4477 wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime() 4478 - mDisplayFreezeTime); 4479 mAppsFreezingScreen--; 4480 mLastFinishedFreezeSource = wtoken; 4481 } 4482 if (unfreezeSurfaceNow) { 4483 if (unfrozeWindows) { 4484 performLayoutAndPlaceSurfacesLocked(); 4485 } 4486 stopFreezingDisplayLocked(); 4487 } 4488 } 4489 } 4490 4491 private void startAppFreezingScreenLocked(AppWindowToken wtoken) { 4492 if (DEBUG_ORIENTATION) { 4493 RuntimeException e = null; 4494 if (!HIDE_STACK_CRAWLS) { 4495 e = new RuntimeException(); 4496 e.fillInStackTrace(); 4497 } 4498 Slog.i(TAG, "Set freezing of " + wtoken.appToken 4499 + ": hidden=" + wtoken.hidden + " freezing=" 4500 + wtoken.mAppAnimator.freezingScreen, e); 4501 } 4502 if (!wtoken.hiddenRequested) { 4503 if (!wtoken.mAppAnimator.freezingScreen) { 4504 wtoken.mAppAnimator.freezingScreen = true; 4505 wtoken.mAppAnimator.lastFreezeDuration = 0; 4506 mAppsFreezingScreen++; 4507 if (mAppsFreezingScreen == 1) { 4508 startFreezingDisplayLocked(false, 0, 0); 4509 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4510 mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000); 4511 } 4512 } 4513 final int N = wtoken.allAppWindows.size(); 4514 for (int i=0; i<N; i++) { 4515 WindowState w = wtoken.allAppWindows.get(i); 4516 w.mAppFreezing = true; 4517 } 4518 } 4519 } 4520 4521 @Override 4522 public void startAppFreezingScreen(IBinder token, int configChanges) { 4523 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4524 "setAppFreezingScreen()")) { 4525 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4526 } 4527 4528 synchronized(mWindowMap) { 4529 if (configChanges == 0 && okToDisplay()) { 4530 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); 4531 return; 4532 } 4533 4534 AppWindowToken wtoken = findAppWindowToken(token); 4535 if (wtoken == null || wtoken.appToken == null) { 4536 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); 4537 return; 4538 } 4539 final long origId = Binder.clearCallingIdentity(); 4540 startAppFreezingScreenLocked(wtoken); 4541 Binder.restoreCallingIdentity(origId); 4542 } 4543 } 4544 4545 @Override 4546 public void stopAppFreezingScreen(IBinder token, boolean force) { 4547 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4548 "setAppFreezingScreen()")) { 4549 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4550 } 4551 4552 synchronized(mWindowMap) { 4553 AppWindowToken wtoken = findAppWindowToken(token); 4554 if (wtoken == null || wtoken.appToken == null) { 4555 return; 4556 } 4557 final long origId = Binder.clearCallingIdentity(); 4558 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token 4559 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4560 unsetAppFreezingScreenLocked(wtoken, true, force); 4561 Binder.restoreCallingIdentity(origId); 4562 } 4563 } 4564 4565 void removeAppFromTaskLocked(AppWindowToken wtoken) { 4566 final Task task = mTaskIdToTask.get(wtoken.groupId); 4567 if (task != null) { 4568 if (!task.removeAppToken(wtoken)) { 4569 Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found."); 4570 } 4571 } 4572 } 4573 4574 @Override 4575 public void removeAppToken(IBinder token) { 4576 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4577 "removeAppToken()")) { 4578 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4579 } 4580 4581 AppWindowToken wtoken = null; 4582 AppWindowToken startingToken = null; 4583 boolean delayed = false; 4584 4585 final long origId = Binder.clearCallingIdentity(); 4586 synchronized(mWindowMap) { 4587 WindowToken basewtoken = mTokenMap.remove(token); 4588 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4589 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); 4590 delayed = setTokenVisibilityLocked(wtoken, null, false, 4591 AppTransition.TRANSIT_UNSET, true); 4592 wtoken.inPendingTransaction = false; 4593 mOpeningApps.remove(wtoken); 4594 wtoken.waitingToShow = false; 4595 if (mClosingApps.contains(wtoken)) { 4596 delayed = true; 4597 } else if (mAppTransition.isTransitionSet()) { 4598 mClosingApps.add(wtoken); 4599 wtoken.waitingToHide = true; 4600 delayed = true; 4601 } 4602 if (DEBUG_APP_TRANSITIONS) Slog.v( 4603 TAG, "Removing app " + wtoken + " delayed=" + delayed 4604 + " animation=" + wtoken.mAppAnimator.animation 4605 + " animating=" + wtoken.mAppAnimator.animating); 4606 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " 4607 + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); 4608 final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack; 4609 if (delayed) { 4610 // set the token aside because it has an active animation to be finished 4611 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4612 "removeAppToken make exiting: " + wtoken); 4613 stack.mExitingAppTokens.add(wtoken); 4614 wtoken.mDeferRemoval = true; 4615 } else { 4616 // Make sure there is no animation running on this token, 4617 // so any windows associated with it will be removed as 4618 // soon as their animations are complete 4619 wtoken.mAppAnimator.clearAnimation(); 4620 wtoken.mAppAnimator.animating = false; 4621 removeAppFromTaskLocked(wtoken); 4622 } 4623 4624 wtoken.removed = true; 4625 if (wtoken.startingData != null) { 4626 startingToken = wtoken; 4627 } 4628 unsetAppFreezingScreenLocked(wtoken, true, true); 4629 if (mFocusedApp == wtoken) { 4630 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken); 4631 mFocusedApp = null; 4632 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4633 mInputMonitor.setFocusedAppLw(null); 4634 } 4635 } else { 4636 Slog.w(TAG, "Attempted to remove non-existing app token: " + token); 4637 } 4638 4639 if (!delayed && wtoken != null) { 4640 wtoken.updateReportedVisibilityLocked(); 4641 } 4642 } 4643 Binder.restoreCallingIdentity(origId); 4644 4645 // Will only remove if startingToken non null. 4646 scheduleRemoveStartingWindow(startingToken); 4647 } 4648 4649 void removeStartingWindowTimeout(AppWindowToken wtoken) { 4650 if (wtoken != null) { 4651 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4652 ": Remove starting window timeout " + wtoken + (wtoken != null ? 4653 " startingWindow=" + wtoken.startingWindow : "")); 4654 mH.removeMessages(H.REMOVE_STARTING_TIMEOUT, wtoken); 4655 } 4656 } 4657 4658 void scheduleRemoveStartingWindow(AppWindowToken wtoken) { 4659 if (wtoken != null && wtoken.startingWindow != null) { 4660 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) + 4661 ": Schedule remove starting " + wtoken + (wtoken != null ? 4662 " startingWindow=" + wtoken.startingWindow : "")); 4663 removeStartingWindowTimeout(wtoken); 4664 Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken); 4665 mH.sendMessage(m); 4666 } 4667 } 4668 4669 private boolean tmpRemoveAppWindowsLocked(WindowToken token) { 4670 WindowList windows = token.windows; 4671 final int NW = windows.size(); 4672 if (NW > 0) { 4673 mWindowsChanged = true; 4674 } 4675 for (int i = 0; i < NW; i++) { 4676 WindowState win = windows.get(i); 4677 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); 4678 win.getWindowList().remove(win); 4679 int j = win.mChildWindows.size(); 4680 while (j > 0) { 4681 j--; 4682 WindowState cwin = win.mChildWindows.get(j); 4683 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 4684 "Tmp removing child window " + cwin); 4685 cwin.getWindowList().remove(cwin); 4686 } 4687 } 4688 return NW > 0; 4689 } 4690 4691 void dumpAppTokensLocked() { 4692 final int numStacks = mStackIdToStack.size(); 4693 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 4694 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 4695 Slog.v(TAG, " Stack #" + stack.mStackId + " tasks from bottom to top:"); 4696 final ArrayList<Task> tasks = stack.getTasks(); 4697 final int numTasks = tasks.size(); 4698 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4699 final Task task = tasks.get(taskNdx); 4700 Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:"); 4701 AppTokenList tokens = task.mAppTokens; 4702 final int numTokens = tokens.size(); 4703 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4704 Slog.v(TAG, " activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token); 4705 } 4706 } 4707 } 4708 } 4709 4710 void dumpWindowsLocked() { 4711 final int numDisplays = mDisplayContents.size(); 4712 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 4713 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 4714 Slog.v(TAG, " Display #" + displayContent.getDisplayId()); 4715 final WindowList windows = displayContent.getWindowList(); 4716 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4717 Slog.v(TAG, " #" + winNdx + ": " + windows.get(winNdx)); 4718 } 4719 } 4720 } 4721 4722 private int findAppWindowInsertionPointLocked(AppWindowToken target) { 4723 final int taskId = target.groupId; 4724 Task targetTask = mTaskIdToTask.get(taskId); 4725 if (targetTask == null) { 4726 Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId=" 4727 + taskId); 4728 return 0; 4729 } 4730 DisplayContent displayContent = targetTask.getDisplayContent(); 4731 if (displayContent == null) { 4732 Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target); 4733 return 0; 4734 } 4735 final WindowList windows = displayContent.getWindowList(); 4736 final int NW = windows.size(); 4737 4738 boolean found = false; 4739 final ArrayList<Task> tasks = displayContent.getTasks(); 4740 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 4741 final Task task = tasks.get(taskNdx); 4742 if (!found && task.taskId != taskId) { 4743 continue; 4744 } 4745 AppTokenList tokens = task.mAppTokens; 4746 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4747 final AppWindowToken wtoken = tokens.get(tokenNdx); 4748 if (!found && wtoken == target) { 4749 found = true; 4750 } 4751 if (found) { 4752 // Find the first app token below the new position that has 4753 // a window displayed. 4754 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token); 4755 if (wtoken.sendingToBottom) { 4756 if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom"); 4757 continue; 4758 } 4759 for (int i = wtoken.windows.size() - 1; i >= 0; --i) { 4760 WindowState win = wtoken.windows.get(i); 4761 for (int j = win.mChildWindows.size() - 1; j >= 0; --j) { 4762 WindowState cwin = win.mChildWindows.get(j); 4763 if (cwin.mSubLayer >= 0) { 4764 for (int pos = NW - 1; pos >= 0; pos--) { 4765 if (windows.get(pos) == cwin) { 4766 if (DEBUG_REORDER) Slog.v(TAG, 4767 "Found child win @" + (pos + 1)); 4768 return pos + 1; 4769 } 4770 } 4771 } 4772 } 4773 for (int pos = NW - 1; pos >= 0; pos--) { 4774 if (windows.get(pos) == win) { 4775 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1)); 4776 return pos + 1; 4777 } 4778 } 4779 } 4780 } 4781 } 4782 } 4783 // Never put an app window underneath wallpaper. 4784 for (int pos = NW - 1; pos >= 0; pos--) { 4785 if (windows.get(pos).mIsWallpaper) { 4786 if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos); 4787 return pos + 1; 4788 } 4789 } 4790 return 0; 4791 } 4792 4793 private final int reAddWindowLocked(int index, WindowState win) { 4794 final WindowList windows = win.getWindowList(); 4795 final int NCW = win.mChildWindows.size(); 4796 boolean added = false; 4797 for (int j=0; j<NCW; j++) { 4798 WindowState cwin = win.mChildWindows.get(j); 4799 if (!added && cwin.mSubLayer >= 0) { 4800 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " 4801 + index + ": " + cwin); 4802 win.mRebuilding = false; 4803 windows.add(index, win); 4804 index++; 4805 added = true; 4806 } 4807 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4808 + index + ": " + cwin); 4809 cwin.mRebuilding = false; 4810 windows.add(index, cwin); 4811 index++; 4812 } 4813 if (!added) { 4814 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4815 + index + ": " + win); 4816 win.mRebuilding = false; 4817 windows.add(index, win); 4818 index++; 4819 } 4820 mWindowsChanged = true; 4821 return index; 4822 } 4823 4824 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index, 4825 WindowToken token) { 4826 final int NW = token.windows.size(); 4827 for (int i=0; i<NW; i++) { 4828 final WindowState win = token.windows.get(i); 4829 final DisplayContent winDisplayContent = win.getDisplayContent(); 4830 if (winDisplayContent == displayContent || winDisplayContent == null) { 4831 win.mDisplayContent = displayContent; 4832 index = reAddWindowLocked(index, win); 4833 } 4834 } 4835 return index; 4836 } 4837 4838 void tmpRemoveTaskWindowsLocked(Task task) { 4839 AppTokenList tokens = task.mAppTokens; 4840 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 4841 tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); 4842 } 4843 } 4844 4845 void moveStackWindowsLocked(DisplayContent displayContent) { 4846 // First remove all of the windows from the list. 4847 final ArrayList<Task> tasks = displayContent.getTasks(); 4848 final int numTasks = tasks.size(); 4849 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4850 tmpRemoveTaskWindowsLocked(tasks.get(taskNdx)); 4851 } 4852 4853 // And now add them back at the correct place. 4854 // Where to start adding? 4855 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 4856 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 4857 int pos = findAppWindowInsertionPointLocked(tokens.get(0)); 4858 final int numTokens = tokens.size(); 4859 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 4860 final AppWindowToken wtoken = tokens.get(tokenNdx); 4861 if (wtoken != null) { 4862 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 4863 if (newPos != pos) { 4864 displayContent.layoutNeeded = true; 4865 } 4866 pos = newPos; 4867 } 4868 } 4869 } 4870 4871 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4872 false /*updateInputWindows*/)) { 4873 assignLayersLocked(displayContent.getWindowList()); 4874 } 4875 4876 mInputMonitor.setUpdateInputWindowsNeededLw(); 4877 performLayoutAndPlaceSurfacesLocked(); 4878 mInputMonitor.updateInputWindowsLw(false /*force*/); 4879 4880 //dump(); 4881 } 4882 4883 public void moveTaskToTop(int taskId) { 4884 final long origId = Binder.clearCallingIdentity(); 4885 try { 4886 synchronized(mWindowMap) { 4887 Task task = mTaskIdToTask.get(taskId); 4888 if (task == null) { 4889 // Normal behavior, addAppToken will be called next and task will be created. 4890 return; 4891 } 4892 final TaskStack stack = task.mStack; 4893 final DisplayContent displayContent = task.getDisplayContent(); 4894 displayContent.moveStack(stack, true); 4895 if (displayContent.isDefaultDisplay) { 4896 final TaskStack homeStack = displayContent.getHomeStack(); 4897 if (homeStack != stack) { 4898 // When a non-home stack moves to the top, the home stack moves to the 4899 // bottom. 4900 displayContent.moveStack(homeStack, false); 4901 } 4902 } 4903 stack.moveTaskToTop(task); 4904 } 4905 } finally { 4906 Binder.restoreCallingIdentity(origId); 4907 } 4908 } 4909 4910 public void moveTaskToBottom(int taskId) { 4911 final long origId = Binder.clearCallingIdentity(); 4912 try { 4913 synchronized(mWindowMap) { 4914 Task task = mTaskIdToTask.get(taskId); 4915 if (task == null) { 4916 Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId 4917 + " not found in mTaskIdToTask"); 4918 return; 4919 } 4920 final TaskStack stack = task.mStack; 4921 stack.moveTaskToBottom(task); 4922 moveStackWindowsLocked(stack.getDisplayContent()); 4923 } 4924 } finally { 4925 Binder.restoreCallingIdentity(origId); 4926 } 4927 } 4928 4929 /** 4930 * Create a new TaskStack and place it on a DisplayContent. 4931 * @param stackId The unique identifier of the new stack. 4932 * @param displayId The unique identifier of the DisplayContent. 4933 */ 4934 public void attachStack(int stackId, int displayId) { 4935 final long origId = Binder.clearCallingIdentity(); 4936 try { 4937 synchronized (mWindowMap) { 4938 final DisplayContent displayContent = mDisplayContents.get(displayId); 4939 if (displayContent != null) { 4940 TaskStack stack = mStackIdToStack.get(stackId); 4941 if (stack == null) { 4942 if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId); 4943 stack = new TaskStack(this, stackId); 4944 mStackIdToStack.put(stackId, stack); 4945 } 4946 stack.attachDisplayContent(displayContent); 4947 displayContent.attachStack(stack); 4948 moveStackWindowsLocked(displayContent); 4949 final WindowList windows = displayContent.getWindowList(); 4950 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 4951 windows.get(winNdx).reportResized(); 4952 } 4953 } 4954 } 4955 } finally { 4956 Binder.restoreCallingIdentity(origId); 4957 } 4958 } 4959 4960 void detachStackLocked(DisplayContent displayContent, TaskStack stack) { 4961 displayContent.detachStack(stack); 4962 stack.detachDisplay(); 4963 } 4964 4965 public void detachStack(int stackId) { 4966 synchronized (mWindowMap) { 4967 TaskStack stack = mStackIdToStack.get(stackId); 4968 if (stack != null) { 4969 final DisplayContent displayContent = stack.getDisplayContent(); 4970 if (displayContent != null) { 4971 if (stack.isAnimating()) { 4972 stack.mDeferDetach = true; 4973 return; 4974 } 4975 detachStackLocked(displayContent, stack); 4976 } 4977 } 4978 } 4979 } 4980 4981 public void removeStack(int stackId) { 4982 mStackIdToStack.remove(stackId); 4983 } 4984 4985 void removeTaskLocked(Task task) { 4986 final int taskId = task.taskId; 4987 final TaskStack stack = task.mStack; 4988 if (stack.isAnimating()) { 4989 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId); 4990 task.mDeferRemoval = true; 4991 return; 4992 } 4993 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId); 4994 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); 4995 task.mDeferRemoval = false; 4996 task.mStack.removeTask(task); 4997 mTaskIdToTask.delete(task.taskId); 4998 } 4999 5000 public void removeTask(int taskId) { 5001 synchronized (mWindowMap) { 5002 Task task = mTaskIdToTask.get(taskId); 5003 if (task == null) { 5004 if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); 5005 return; 5006 } 5007 removeTaskLocked(task); 5008 } 5009 } 5010 5011 public void addTask(int taskId, int stackId, boolean toTop) { 5012 synchronized (mWindowMap) { 5013 if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId 5014 + " to " + (toTop ? "top" : "bottom")); 5015 Task task = mTaskIdToTask.get(taskId); 5016 if (task == null) { 5017 return; 5018 } 5019 TaskStack stack = mStackIdToStack.get(stackId); 5020 stack.addTask(task, toTop); 5021 final DisplayContent displayContent = stack.getDisplayContent(); 5022 displayContent.layoutNeeded = true; 5023 performLayoutAndPlaceSurfacesLocked(); 5024 } 5025 } 5026 5027 public void resizeStack(int stackId, Rect bounds) { 5028 synchronized (mWindowMap) { 5029 final TaskStack stack = mStackIdToStack.get(stackId); 5030 if (stack == null) { 5031 throw new IllegalArgumentException("resizeStack: stackId " + stackId 5032 + " not found."); 5033 } 5034 if (stack.setBounds(bounds)) { 5035 stack.resizeWindows(); 5036 stack.getDisplayContent().layoutNeeded = true; 5037 performLayoutAndPlaceSurfacesLocked(); 5038 } 5039 } 5040 } 5041 5042 public void getStackBounds(int stackId, Rect bounds) { 5043 final TaskStack stack = mStackIdToStack.get(stackId); 5044 if (stack != null) { 5045 stack.getBounds(bounds); 5046 return; 5047 } 5048 bounds.setEmpty(); 5049 } 5050 5051 // ------------------------------------------------------------- 5052 // Misc IWindowSession methods 5053 // ------------------------------------------------------------- 5054 5055 @Override 5056 public void startFreezingScreen(int exitAnim, int enterAnim) { 5057 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5058 "startFreezingScreen()")) { 5059 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5060 } 5061 5062 synchronized(mWindowMap) { 5063 if (!mClientFreezingScreen) { 5064 mClientFreezingScreen = true; 5065 final long origId = Binder.clearCallingIdentity(); 5066 try { 5067 startFreezingDisplayLocked(false, exitAnim, enterAnim); 5068 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 5069 mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); 5070 } finally { 5071 Binder.restoreCallingIdentity(origId); 5072 } 5073 } 5074 } 5075 } 5076 5077 @Override 5078 public void stopFreezingScreen() { 5079 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5080 "stopFreezingScreen()")) { 5081 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5082 } 5083 5084 synchronized(mWindowMap) { 5085 if (mClientFreezingScreen) { 5086 mClientFreezingScreen = false; 5087 mLastFinishedFreezeSource = "client"; 5088 final long origId = Binder.clearCallingIdentity(); 5089 try { 5090 stopFreezingDisplayLocked(); 5091 } finally { 5092 Binder.restoreCallingIdentity(origId); 5093 } 5094 } 5095 } 5096 } 5097 5098 @Override 5099 public void disableKeyguard(IBinder token, String tag) { 5100 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5101 != PackageManager.PERMISSION_GRANTED) { 5102 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5103 } 5104 5105 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5106 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 5107 } 5108 5109 @Override 5110 public void reenableKeyguard(IBinder token) { 5111 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5112 != PackageManager.PERMISSION_GRANTED) { 5113 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5114 } 5115 5116 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5117 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 5118 } 5119 5120 /** 5121 * @see android.app.KeyguardManager#exitKeyguardSecurely 5122 */ 5123 @Override 5124 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5125 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5126 != PackageManager.PERMISSION_GRANTED) { 5127 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5128 } 5129 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5130 @Override 5131 public void onKeyguardExitResult(boolean success) { 5132 try { 5133 callback.onKeyguardExitResult(success); 5134 } catch (RemoteException e) { 5135 // Client has died, we don't care. 5136 } 5137 } 5138 }); 5139 } 5140 5141 @Override 5142 public boolean inKeyguardRestrictedInputMode() { 5143 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5144 } 5145 5146 @Override 5147 public boolean isKeyguardLocked() { 5148 return mPolicy.isKeyguardLocked(); 5149 } 5150 5151 @Override 5152 public boolean isKeyguardSecure() { 5153 return mPolicy.isKeyguardSecure(); 5154 } 5155 5156 @Override 5157 public void dismissKeyguard() { 5158 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5159 != PackageManager.PERMISSION_GRANTED) { 5160 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5161 } 5162 synchronized(mWindowMap) { 5163 mPolicy.dismissKeyguardLw(); 5164 } 5165 } 5166 5167 @Override 5168 public void closeSystemDialogs(String reason) { 5169 synchronized(mWindowMap) { 5170 final int numDisplays = mDisplayContents.size(); 5171 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5172 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5173 final int numWindows = windows.size(); 5174 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5175 final WindowState w = windows.get(winNdx); 5176 if (w.mHasSurface) { 5177 try { 5178 w.mClient.closeSystemDialogs(reason); 5179 } catch (RemoteException e) { 5180 } 5181 } 5182 } 5183 } 5184 } 5185 } 5186 5187 static float fixScale(float scale) { 5188 if (scale < 0) scale = 0; 5189 else if (scale > 20) scale = 20; 5190 return Math.abs(scale); 5191 } 5192 5193 @Override 5194 public void setAnimationScale(int which, float scale) { 5195 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5196 "setAnimationScale()")) { 5197 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5198 } 5199 5200 scale = fixScale(scale); 5201 switch (which) { 5202 case 0: mWindowAnimationScale = scale; break; 5203 case 1: mTransitionAnimationScale = scale; break; 5204 case 2: mAnimatorDurationScale = scale; break; 5205 } 5206 5207 // Persist setting 5208 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5209 } 5210 5211 @Override 5212 public void setAnimationScales(float[] scales) { 5213 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5214 "setAnimationScale()")) { 5215 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5216 } 5217 5218 if (scales != null) { 5219 if (scales.length >= 1) { 5220 mWindowAnimationScale = fixScale(scales[0]); 5221 } 5222 if (scales.length >= 2) { 5223 mTransitionAnimationScale = fixScale(scales[1]); 5224 } 5225 if (scales.length >= 3) { 5226 setAnimatorDurationScale(fixScale(scales[2])); 5227 } 5228 } 5229 5230 // Persist setting 5231 mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE); 5232 } 5233 5234 private void setAnimatorDurationScale(float scale) { 5235 mAnimatorDurationScale = scale; 5236 ValueAnimator.setDurationScale(scale); 5237 } 5238 5239 @Override 5240 public float getAnimationScale(int which) { 5241 switch (which) { 5242 case 0: return mWindowAnimationScale; 5243 case 1: return mTransitionAnimationScale; 5244 case 2: return mAnimatorDurationScale; 5245 } 5246 return 0; 5247 } 5248 5249 @Override 5250 public float[] getAnimationScales() { 5251 return new float[] { mWindowAnimationScale, mTransitionAnimationScale, 5252 mAnimatorDurationScale }; 5253 } 5254 5255 @Override 5256 public void registerPointerEventListener(PointerEventListener listener) { 5257 mPointerEventDispatcher.registerInputEventListener(listener); 5258 } 5259 5260 @Override 5261 public void unregisterPointerEventListener(PointerEventListener listener) { 5262 mPointerEventDispatcher.unregisterInputEventListener(listener); 5263 } 5264 5265 // Called by window manager policy. Not exposed externally. 5266 @Override 5267 public int getLidState() { 5268 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5269 InputManagerService.SW_LID); 5270 if (sw > 0) { 5271 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5272 return LID_CLOSED; 5273 } else if (sw == 0) { 5274 // Switch state: AKEY_STATE_UP. 5275 return LID_OPEN; 5276 } else { 5277 // Switch state: AKEY_STATE_UNKNOWN. 5278 return LID_ABSENT; 5279 } 5280 } 5281 5282 // Called by window manager policy. Not exposed externally. 5283 @Override 5284 public void switchKeyboardLayout(int deviceId, int direction) { 5285 mInputManager.switchKeyboardLayout(deviceId, direction); 5286 } 5287 5288 // Called by window manager policy. Not exposed externally. 5289 @Override 5290 public void shutdown(boolean confirm) { 5291 ShutdownThread.shutdown(mContext, confirm); 5292 } 5293 5294 // Called by window manager policy. Not exposed externally. 5295 @Override 5296 public void rebootSafeMode(boolean confirm) { 5297 ShutdownThread.rebootSafeMode(mContext, confirm); 5298 } 5299 5300 @Override 5301 public void setInputFilter(IInputFilter filter) { 5302 if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) { 5303 throw new SecurityException("Requires FILTER_EVENTS permission"); 5304 } 5305 mInputManager.setInputFilter(filter); 5306 } 5307 5308 @Override 5309 public void setTouchExplorationEnabled(boolean enabled) { 5310 mPolicy.setTouchExplorationEnabled(enabled); 5311 } 5312 5313 public void setCurrentUser(final int newUserId) { 5314 synchronized (mWindowMap) { 5315 int oldUserId = mCurrentUserId; 5316 mCurrentUserId = newUserId; 5317 mAppTransition.setCurrentUser(newUserId); 5318 mPolicy.setCurrentUserLw(newUserId); 5319 5320 // Hide windows that should not be seen by the new user. 5321 final int numDisplays = mDisplayContents.size(); 5322 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5323 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 5324 displayContent.switchUserStacks(newUserId); 5325 rebuildAppWindowListLocked(displayContent); 5326 } 5327 performLayoutAndPlaceSurfacesLocked(); 5328 } 5329 } 5330 5331 public void enableScreenAfterBoot() { 5332 synchronized(mWindowMap) { 5333 if (DEBUG_BOOT) { 5334 RuntimeException here = new RuntimeException("here"); 5335 here.fillInStackTrace(); 5336 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5337 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5338 + " mShowingBootMessages=" + mShowingBootMessages 5339 + " mSystemBooted=" + mSystemBooted, here); 5340 } 5341 if (mSystemBooted) { 5342 return; 5343 } 5344 mSystemBooted = true; 5345 hideBootMessagesLocked(); 5346 // If the screen still doesn't come up after 30 seconds, give 5347 // up and turn it on. 5348 mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000); 5349 } 5350 5351 mPolicy.systemBooted(); 5352 5353 performEnableScreen(); 5354 } 5355 5356 void enableScreenIfNeededLocked() { 5357 if (DEBUG_BOOT) { 5358 RuntimeException here = new RuntimeException("here"); 5359 here.fillInStackTrace(); 5360 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5361 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5362 + " mShowingBootMessages=" + mShowingBootMessages 5363 + " mSystemBooted=" + mSystemBooted, here); 5364 } 5365 if (mDisplayEnabled) { 5366 return; 5367 } 5368 if (!mSystemBooted && !mShowingBootMessages) { 5369 return; 5370 } 5371 mH.sendEmptyMessage(H.ENABLE_SCREEN); 5372 } 5373 5374 public void performBootTimeout() { 5375 synchronized(mWindowMap) { 5376 if (mDisplayEnabled) { 5377 return; 5378 } 5379 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5380 mForceDisplayEnabled = true; 5381 } 5382 performEnableScreen(); 5383 } 5384 5385 public void performEnableScreen() { 5386 synchronized(mWindowMap) { 5387 if (DEBUG_BOOT) { 5388 RuntimeException here = new RuntimeException("here"); 5389 here.fillInStackTrace(); 5390 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5391 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5392 + " mShowingBootMessages=" + mShowingBootMessages 5393 + " mSystemBooted=" + mSystemBooted 5394 + " mOnlyCore=" + mOnlyCore, here); 5395 } 5396 if (mDisplayEnabled) { 5397 return; 5398 } 5399 if (!mSystemBooted && !mShowingBootMessages) { 5400 return; 5401 } 5402 5403 if (!mForceDisplayEnabled) { 5404 // Don't enable the screen until all existing windows 5405 // have been drawn. 5406 boolean haveBootMsg = false; 5407 boolean haveApp = false; 5408 // if the wallpaper service is disabled on the device, we're never going to have 5409 // wallpaper, don't bother waiting for it 5410 boolean haveWallpaper = false; 5411 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5412 com.android.internal.R.bool.config_enableWallpaperService) 5413 && !mOnlyCore; 5414 boolean haveKeyguard = true; 5415 // TODO(multidisplay): Expand to all displays? 5416 final WindowList windows = getDefaultWindowListLocked(); 5417 final int N = windows.size(); 5418 for (int i=0; i<N; i++) { 5419 WindowState w = windows.get(i); 5420 if (w.mAttrs.type == TYPE_KEYGUARD) { 5421 // Only if there is a keyguard attached to the window manager 5422 // will we consider ourselves as having a keyguard. If it 5423 // isn't attached, we don't know if it wants to be shown or 5424 // hidden. If it is attached, we will say we have a keyguard 5425 // if the window doesn't want to be visible, because in that 5426 // case it explicitly doesn't want to be shown so we should 5427 // not delay turning the screen on for it. 5428 boolean vis = w.mViewVisibility == View.VISIBLE 5429 && w.mPolicyVisibility; 5430 haveKeyguard = !vis; 5431 } 5432 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5433 return; 5434 } 5435 if (w.isDrawnLw()) { 5436 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5437 haveBootMsg = true; 5438 } else if (w.mAttrs.type == TYPE_APPLICATION) { 5439 haveApp = true; 5440 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5441 haveWallpaper = true; 5442 } else if (w.mAttrs.type == TYPE_KEYGUARD) { 5443 haveKeyguard = true; 5444 } 5445 } 5446 } 5447 5448 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5449 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5450 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5451 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5452 + " haveKeyguard=" + haveKeyguard); 5453 } 5454 5455 // If we are turning on the screen to show the boot message, 5456 // don't do it until the boot message is actually displayed. 5457 if (!mSystemBooted && !haveBootMsg) { 5458 return; 5459 } 5460 5461 // If we are turning on the screen after the boot is completed 5462 // normally, don't do so until we have the application and 5463 // wallpaper. 5464 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5465 (wallpaperEnabled && !haveWallpaper))) { 5466 return; 5467 } 5468 } 5469 5470 mDisplayEnabled = true; 5471 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5472 if (false) { 5473 StringWriter sw = new StringWriter(); 5474 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 5475 this.dump(null, pw, null); 5476 pw.flush(); 5477 Slog.i(TAG, sw.toString()); 5478 } 5479 try { 5480 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5481 if (surfaceFlinger != null) { 5482 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5483 Parcel data = Parcel.obtain(); 5484 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5485 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5486 data, null, 0); 5487 data.recycle(); 5488 } 5489 } catch (RemoteException ex) { 5490 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5491 } 5492 5493 // Enable input dispatch. 5494 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5495 } 5496 5497 mPolicy.enableScreenAfterBoot(); 5498 5499 // Make sure the last requested orientation has been applied. 5500 updateRotationUnchecked(false, false); 5501 } 5502 5503 public void showBootMessage(final CharSequence msg, final boolean always) { 5504 boolean first = false; 5505 synchronized(mWindowMap) { 5506 if (DEBUG_BOOT) { 5507 RuntimeException here = new RuntimeException("here"); 5508 here.fillInStackTrace(); 5509 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5510 + " mAllowBootMessages=" + mAllowBootMessages 5511 + " mShowingBootMessages=" + mShowingBootMessages 5512 + " mSystemBooted=" + mSystemBooted, here); 5513 } 5514 if (!mAllowBootMessages) { 5515 return; 5516 } 5517 if (!mShowingBootMessages) { 5518 if (!always) { 5519 return; 5520 } 5521 first = true; 5522 } 5523 if (mSystemBooted) { 5524 return; 5525 } 5526 mShowingBootMessages = true; 5527 mPolicy.showBootMessage(msg, always); 5528 } 5529 if (first) { 5530 performEnableScreen(); 5531 } 5532 } 5533 5534 public void hideBootMessagesLocked() { 5535 if (DEBUG_BOOT) { 5536 RuntimeException here = new RuntimeException("here"); 5537 here.fillInStackTrace(); 5538 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5539 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5540 + " mShowingBootMessages=" + mShowingBootMessages 5541 + " mSystemBooted=" + mSystemBooted, here); 5542 } 5543 if (mShowingBootMessages) { 5544 mShowingBootMessages = false; 5545 mPolicy.hideBootMessages(); 5546 } 5547 } 5548 5549 @Override 5550 public void setInTouchMode(boolean mode) { 5551 synchronized(mWindowMap) { 5552 mInTouchMode = mode; 5553 } 5554 } 5555 5556 public void showCircularDisplayMaskIfNeeded() { 5557 // we're fullscreen and not hosted in an ActivityView 5558 if (mContext.getResources().getBoolean( 5559 com.android.internal.R.bool.config_windowIsRound)) { 5560 mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK)); 5561 } 5562 } 5563 5564 public void showCircularMask() { 5565 synchronized(mWindowMap) { 5566 5567 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5568 ">>> OPEN TRANSACTION showDisplayMask"); 5569 SurfaceControl.openTransaction(); 5570 try { 5571 // TODO(multi-display): support multiple displays 5572 if (mCircularDisplayMask == null) { 5573 mCircularDisplayMask = new CircularDisplayMask( 5574 getDefaultDisplayContentLocked().getDisplay(), 5575 mFxSession, 5576 mPolicy.windowTypeToLayerLw( 5577 WindowManager.LayoutParams.TYPE_POINTER) 5578 * TYPE_LAYER_MULTIPLIER + 10); 5579 } 5580 mCircularDisplayMask.setVisibility(true); 5581 } finally { 5582 SurfaceControl.closeTransaction(); 5583 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5584 "<<< CLOSE TRANSACTION showDisplayMask"); 5585 } 5586 } 5587 } 5588 5589 // TODO: more accounting of which pid(s) turned it on, keep count, 5590 // only allow disables from pids which have count on, etc. 5591 @Override 5592 public void showStrictModeViolation(boolean on) { 5593 int pid = Binder.getCallingPid(); 5594 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5595 } 5596 5597 private void showStrictModeViolation(int arg, int pid) { 5598 final boolean on = arg != 0; 5599 synchronized(mWindowMap) { 5600 // Ignoring requests to enable the red border from clients 5601 // which aren't on screen. (e.g. Broadcast Receivers in 5602 // the background..) 5603 if (on) { 5604 boolean isVisible = false; 5605 final int numDisplays = mDisplayContents.size(); 5606 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 5607 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 5608 final int numWindows = windows.size(); 5609 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 5610 final WindowState ws = windows.get(winNdx); 5611 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5612 isVisible = true; 5613 break; 5614 } 5615 } 5616 } 5617 if (!isVisible) { 5618 return; 5619 } 5620 } 5621 5622 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5623 ">>> OPEN TRANSACTION showStrictModeViolation"); 5624 SurfaceControl.openTransaction(); 5625 try { 5626 // TODO(multi-display): support multiple displays 5627 if (mStrictModeFlash == null) { 5628 mStrictModeFlash = new StrictModeFlash( 5629 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5630 } 5631 mStrictModeFlash.setVisibility(on); 5632 } finally { 5633 SurfaceControl.closeTransaction(); 5634 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5635 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5636 } 5637 } 5638 } 5639 5640 @Override 5641 public void setStrictModeVisualIndicatorPreference(String value) { 5642 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5643 } 5644 5645 /** 5646 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5647 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5648 * of the target image. 5649 * 5650 * @param displayId the Display to take a screenshot of. 5651 * @param width the width of the target bitmap 5652 * @param height the height of the target bitmap 5653 * @param force565 if true the returned bitmap will be RGB_565, otherwise it 5654 * will be the same config as the surface 5655 */ 5656 @Override 5657 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, 5658 int height, boolean force565) { 5659 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5660 "screenshotApplications()")) { 5661 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5662 } 5663 5664 Bitmap rawss = null; 5665 5666 int maxLayer = 0; 5667 final Rect frame = new Rect(); 5668 5669 float scale = 0; 5670 int dw, dh; 5671 int rot = Surface.ROTATION_0; 5672 5673 boolean screenshotReady; 5674 int minLayer; 5675 if (appToken == null) { 5676 screenshotReady = true; 5677 minLayer = 0; 5678 } else { 5679 screenshotReady = false; 5680 minLayer = Integer.MAX_VALUE; 5681 } 5682 5683 int retryCount = 0; 5684 WindowState appWin = null; 5685 5686 do { 5687 if (retryCount++ > 0) { 5688 try { 5689 Thread.sleep(100); 5690 } catch (InterruptedException e) { 5691 } 5692 } 5693 synchronized(mWindowMap) { 5694 final DisplayContent displayContent = getDisplayContentLocked(displayId); 5695 if (displayContent == null) { 5696 return null; 5697 } 5698 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 5699 dw = displayInfo.logicalWidth; 5700 dh = displayInfo.logicalHeight; 5701 5702 int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) 5703 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 5704 aboveAppLayer += TYPE_LAYER_MULTIPLIER; 5705 5706 boolean isImeTarget = mInputMethodTarget != null 5707 && mInputMethodTarget.mAppToken != null 5708 && mInputMethodTarget.mAppToken.appToken != null 5709 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5710 5711 // Figure out the part of the screen that is actually the app. 5712 boolean including = false; 5713 appWin = null; 5714 final WindowList windows = displayContent.getWindowList(); 5715 final Rect stackBounds = new Rect(); 5716 for (int i = windows.size() - 1; i >= 0; i--) { 5717 WindowState ws = windows.get(i); 5718 if (!ws.mHasSurface) { 5719 continue; 5720 } 5721 if (ws.mLayer >= aboveAppLayer) { 5722 continue; 5723 } 5724 // When we will skip windows: when we are not including 5725 // ones behind a window we didn't skip, and we are actually 5726 // taking a screenshot of a specific app. 5727 if (!including && appToken != null) { 5728 // Also, we can possibly skip this window if it is not 5729 // an IME target or the application for the screenshot 5730 // is not the current IME target. 5731 if (!ws.mIsImWindow || !isImeTarget) { 5732 // And finally, this window is of no interest if it 5733 // is not associated with the screenshot app. 5734 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5735 continue; 5736 } 5737 appWin = ws; 5738 ws.getStackBounds(stackBounds); 5739 } 5740 } 5741 5742 // We keep on including windows until we go past a full-screen 5743 // window. 5744 including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); 5745 5746 final WindowStateAnimator winAnim = ws.mWinAnimator; 5747 if (maxLayer < winAnim.mSurfaceLayer) { 5748 maxLayer = winAnim.mSurfaceLayer; 5749 } 5750 if (minLayer > winAnim.mSurfaceLayer) { 5751 minLayer = winAnim.mSurfaceLayer; 5752 } 5753 5754 // Don't include wallpaper in bounds calculation 5755 if (!ws.mIsWallpaper) { 5756 final Rect wf = ws.mFrame; 5757 final Rect cr = ws.mContentInsets; 5758 int left = wf.left + cr.left; 5759 int top = wf.top + cr.top; 5760 int right = wf.right - cr.right; 5761 int bottom = wf.bottom - cr.bottom; 5762 frame.union(left, top, right, bottom); 5763 frame.intersect(stackBounds); 5764 } 5765 5766 if (ws.mAppToken != null && ws.mAppToken.token == appToken && 5767 ws.isDisplayedLw()) { 5768 screenshotReady = true; 5769 } 5770 } 5771 5772 if (appToken != null && appWin == null) { 5773 // Can't find a window to snapshot. 5774 if (DEBUG_SCREENSHOT) Slog.i(TAG, 5775 "Screenshot: Couldn't find a surface matching " + appToken); 5776 return null; 5777 } 5778 if (!screenshotReady) { 5779 // Delay and hope that window gets drawn. 5780 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken 5781 + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); 5782 continue; 5783 } 5784 5785 // Constrain frame to the screen size. 5786 frame.intersect(0, 0, dw, dh); 5787 5788 if (frame.isEmpty() || maxLayer == 0) { 5789 if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken 5790 + ": returning null frame=" + frame.toShortString() + " maxLayer=" 5791 + maxLayer); 5792 return null; 5793 } 5794 5795 // The screenshot API does not apply the current screen rotation. 5796 rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); 5797 int fw = frame.width(); 5798 int fh = frame.height(); 5799 5800 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5801 // of thumbnail is the same as the screen (in landscape) or square. 5802 scale = Math.max(width / (float) fw, height / (float) fh); 5803 /* 5804 float targetWidthScale = width / (float) fw; 5805 float targetHeightScale = height / (float) fh; 5806 if (fw <= fh) { 5807 scale = targetWidthScale; 5808 // If aspect of thumbnail is the same as the screen (in landscape), 5809 // select the slightly larger value so we fill the entire bitmap 5810 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) { 5811 scale = targetHeightScale; 5812 } 5813 } else { 5814 scale = targetHeightScale; 5815 // If aspect of thumbnail is the same as the screen (in landscape), 5816 // select the slightly larger value so we fill the entire bitmap 5817 if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) { 5818 scale = targetWidthScale; 5819 } 5820 } 5821 */ 5822 5823 // The screen shot will contain the entire screen. 5824 dw = (int)(dw*scale); 5825 dh = (int)(dh*scale); 5826 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5827 int tmp = dw; 5828 dw = dh; 5829 dh = tmp; 5830 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5831 } 5832 if (DEBUG_SCREENSHOT) { 5833 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 5834 + maxLayer + " appToken=" + appToken); 5835 for (int i = 0; i < windows.size(); i++) { 5836 WindowState win = windows.get(i); 5837 Slog.i(TAG, win + ": " + win.mLayer 5838 + " animLayer=" + win.mWinAnimator.mAnimLayer 5839 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); 5840 } 5841 } 5842 rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer); 5843 } 5844 } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); 5845 if (retryCount > MAX_SCREENSHOT_RETRIES) Slog.i(TAG, "Screenshot max retries " + 5846 retryCount + " of " + appToken + " appWin=" + (appWin == null ? 5847 "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState))); 5848 5849 if (rawss == null) { 5850 Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh 5851 + ") to layer " + maxLayer); 5852 return null; 5853 } 5854 5855 Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig()); 5856 frame.scale(scale); 5857 Matrix matrix = new Matrix(); 5858 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 5859 // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left 5860 matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top)); 5861 Canvas canvas = new Canvas(bm); 5862 canvas.drawColor(0xFF000000); 5863 canvas.drawBitmap(rawss, matrix, null); 5864 canvas.setBitmap(null); 5865 5866 if (DEBUG_SCREENSHOT) { 5867 // TEST IF IT's ALL BLACK 5868 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 5869 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 5870 boolean allBlack = true; 5871 final int firstColor = buffer[0]; 5872 for (int i = 0; i < buffer.length; i++) { 5873 if (buffer[i] != firstColor) { 5874 allBlack = false; 5875 break; 5876 } 5877 } 5878 if (allBlack) { 5879 Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" + 5880 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 5881 (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") + 5882 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 5883 } 5884 } 5885 5886 rawss.recycle(); 5887 return bm; 5888 } 5889 5890 /** 5891 * Freeze rotation changes. (Enable "rotation lock".) 5892 * Persists across reboots. 5893 * @param rotation The desired rotation to freeze to, or -1 to use the 5894 * current rotation. 5895 */ 5896 @Override 5897 public void freezeRotation(int rotation) { 5898 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5899 "freezeRotation()")) { 5900 throw new SecurityException("Requires SET_ORIENTATION permission"); 5901 } 5902 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5903 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5904 + "rotation constant."); 5905 } 5906 5907 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5908 5909 long origId = Binder.clearCallingIdentity(); 5910 try { 5911 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5912 rotation == -1 ? mRotation : rotation); 5913 } finally { 5914 Binder.restoreCallingIdentity(origId); 5915 } 5916 5917 updateRotationUnchecked(false, false); 5918 } 5919 5920 /** 5921 * Thaw rotation changes. (Disable "rotation lock".) 5922 * Persists across reboots. 5923 */ 5924 @Override 5925 public void thawRotation() { 5926 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5927 "thawRotation()")) { 5928 throw new SecurityException("Requires SET_ORIENTATION permission"); 5929 } 5930 5931 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5932 5933 long origId = Binder.clearCallingIdentity(); 5934 try { 5935 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 5936 777); // rot not used 5937 } finally { 5938 Binder.restoreCallingIdentity(origId); 5939 } 5940 5941 updateRotationUnchecked(false, false); 5942 } 5943 5944 /** 5945 * Recalculate the current rotation. 5946 * 5947 * Called by the window manager policy whenever the state of the system changes 5948 * such that the current rotation might need to be updated, such as when the 5949 * device is docked or rotated into a new posture. 5950 */ 5951 @Override 5952 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5953 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5954 } 5955 5956 /** 5957 * Temporarily pauses rotation changes until resumed. 5958 * 5959 * This can be used to prevent rotation changes from occurring while the user is 5960 * performing certain operations, such as drag and drop. 5961 * 5962 * This call nests and must be matched by an equal number of calls to 5963 * {@link #resumeRotationLocked}. 5964 */ 5965 void pauseRotationLocked() { 5966 mDeferredRotationPauseCount += 1; 5967 } 5968 5969 /** 5970 * Resumes normal rotation changes after being paused. 5971 */ 5972 void resumeRotationLocked() { 5973 if (mDeferredRotationPauseCount > 0) { 5974 mDeferredRotationPauseCount -= 1; 5975 if (mDeferredRotationPauseCount == 0) { 5976 boolean changed = updateRotationUncheckedLocked(false); 5977 if (changed) { 5978 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5979 } 5980 } 5981 } 5982 } 5983 5984 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 5985 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 5986 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 5987 5988 long origId = Binder.clearCallingIdentity(); 5989 boolean changed; 5990 synchronized(mWindowMap) { 5991 changed = updateRotationUncheckedLocked(false); 5992 if (!changed || forceRelayout) { 5993 getDefaultDisplayContentLocked().layoutNeeded = true; 5994 performLayoutAndPlaceSurfacesLocked(); 5995 } 5996 } 5997 5998 if (changed || alwaysSendConfiguration) { 5999 sendNewConfiguration(); 6000 } 6001 6002 Binder.restoreCallingIdentity(origId); 6003 } 6004 6005 // TODO(multidisplay): Rotate any display? 6006 /** 6007 * Updates the current rotation. 6008 * 6009 * Returns true if the rotation has been changed. In this case YOU 6010 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 6011 */ 6012 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 6013 if (mDeferredRotationPauseCount > 0) { 6014 // Rotation updates have been paused temporarily. Defer the update until 6015 // updates have been resumed. 6016 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 6017 return false; 6018 } 6019 6020 ScreenRotationAnimation screenRotationAnimation = 6021 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6022 if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { 6023 // Rotation updates cannot be performed while the previous rotation change 6024 // animation is still in progress. Skip this update. We will try updating 6025 // again after the animation is finished and the display is unfrozen. 6026 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 6027 return false; 6028 } 6029 6030 if (!mDisplayEnabled) { 6031 // No point choosing a rotation if the display is not enabled. 6032 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 6033 return false; 6034 } 6035 6036 // TODO: Implement forced rotation changes. 6037 // Set mAltOrientation to indicate that the application is receiving 6038 // an orientation that has different metrics than it expected. 6039 // eg. Portrait instead of Landscape. 6040 6041 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 6042 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 6043 mForcedAppOrientation, rotation); 6044 6045 if (DEBUG_ORIENTATION) { 6046 Slog.v(TAG, "Application requested orientation " 6047 + mForcedAppOrientation + ", got rotation " + rotation 6048 + " which has " + (altOrientation ? "incompatible" : "compatible") 6049 + " metrics"); 6050 } 6051 6052 if (mRotation == rotation && mAltOrientation == altOrientation) { 6053 // No change. 6054 return false; 6055 } 6056 6057 if (DEBUG_ORIENTATION) { 6058 Slog.v(TAG, 6059 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 6060 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 6061 + ", forceApp=" + mForcedAppOrientation); 6062 } 6063 6064 mRotation = rotation; 6065 mAltOrientation = altOrientation; 6066 mPolicy.setRotationLw(mRotation); 6067 6068 mWindowsFreezingScreen = true; 6069 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 6070 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION); 6071 mWaitingForConfig = true; 6072 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6073 displayContent.layoutNeeded = true; 6074 final int[] anim = new int[2]; 6075 if (displayContent.isDimming()) { 6076 anim[0] = anim[1] = 0; 6077 } else { 6078 mPolicy.selectRotationAnimationLw(anim); 6079 } 6080 startFreezingDisplayLocked(inTransaction, anim[0], anim[1]); 6081 // startFreezingDisplayLocked can reset the ScreenRotationAnimation. 6082 screenRotationAnimation = 6083 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 6084 6085 // We need to update our screen size information to match the new 6086 // rotation. Note that this is redundant with the later call to 6087 // sendNewConfiguration() that must be called after this function 6088 // returns... however we need to do the screen size part of that 6089 // before then so we have the correct size to use when initializing 6090 // the rotation animation for the new rotation. 6091 computeScreenConfigurationLocked(null); 6092 6093 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6094 if (!inTransaction) { 6095 if (SHOW_TRANSACTIONS) { 6096 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); 6097 } 6098 SurfaceControl.openTransaction(); 6099 } 6100 try { 6101 // NOTE: We disable the rotation in the emulator because 6102 // it doesn't support hardware OpenGL emulation yet. 6103 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 6104 && screenRotationAnimation.hasScreenshot()) { 6105 if (screenRotationAnimation.setRotationInTransaction( 6106 rotation, mFxSession, 6107 MAX_ANIMATION_DURATION, mTransitionAnimationScale, 6108 displayInfo.logicalWidth, displayInfo.logicalHeight)) { 6109 scheduleAnimationLocked(); 6110 } 6111 } 6112 6113 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 6114 } finally { 6115 if (!inTransaction) { 6116 SurfaceControl.closeTransaction(); 6117 if (SHOW_LIGHT_TRANSACTIONS) { 6118 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); 6119 } 6120 } 6121 } 6122 6123 final WindowList windows = displayContent.getWindowList(); 6124 for (int i = windows.size() - 1; i >= 0; i--) { 6125 WindowState w = windows.get(i); 6126 if (w.mHasSurface) { 6127 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 6128 w.mOrientationChanging = true; 6129 mInnerFields.mOrientationChangeComplete = false; 6130 } 6131 w.mLastFreezeDuration = 0; 6132 } 6133 6134 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 6135 try { 6136 mRotationWatchers.get(i).watcher.onRotationChanged(rotation); 6137 } catch (RemoteException e) { 6138 } 6139 } 6140 6141 //TODO (multidisplay): Magnification is supported only for the default display. 6142 if (mDisplayMagnifier != null 6143 && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { 6144 mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); 6145 } 6146 6147 return true; 6148 } 6149 6150 @Override 6151 public int getRotation() { 6152 return mRotation; 6153 } 6154 6155 @Override 6156 public boolean isRotationFrozen() { 6157 return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED; 6158 } 6159 6160 @Override 6161 public int watchRotation(IRotationWatcher watcher) { 6162 final IBinder watcherBinder = watcher.asBinder(); 6163 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 6164 @Override 6165 public void binderDied() { 6166 synchronized (mWindowMap) { 6167 for (int i=0; i<mRotationWatchers.size(); i++) { 6168 if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) { 6169 RotationWatcher removed = mRotationWatchers.remove(i); 6170 if (removed != null) { 6171 removed.watcher.asBinder().unlinkToDeath(this, 0); 6172 } 6173 i--; 6174 } 6175 } 6176 } 6177 } 6178 }; 6179 6180 synchronized (mWindowMap) { 6181 try { 6182 watcher.asBinder().linkToDeath(dr, 0); 6183 mRotationWatchers.add(new RotationWatcher(watcher, dr)); 6184 } catch (RemoteException e) { 6185 // Client died, no cleanup needed. 6186 } 6187 6188 return mRotation; 6189 } 6190 } 6191 6192 @Override 6193 public void removeRotationWatcher(IRotationWatcher watcher) { 6194 final IBinder watcherBinder = watcher.asBinder(); 6195 synchronized (mWindowMap) { 6196 for (int i=0; i<mRotationWatchers.size(); i++) { 6197 RotationWatcher rotationWatcher = mRotationWatchers.get(i); 6198 if (watcherBinder == rotationWatcher.watcher.asBinder()) { 6199 RotationWatcher removed = mRotationWatchers.remove(i); 6200 if (removed != null) { 6201 removed.watcher.asBinder().unlinkToDeath(removed.dr, 0); 6202 i--; 6203 } 6204 } 6205 } 6206 } 6207 } 6208 6209 /** 6210 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 6211 * theme attribute) on devices that feature a physical options menu key attempt to position 6212 * their menu panel window along the edge of the screen nearest the physical menu key. 6213 * This lowers the travel distance between invoking the menu panel and selecting 6214 * a menu option. 6215 * 6216 * This method helps control where that menu is placed. Its current implementation makes 6217 * assumptions about the menu key and its relationship to the screen based on whether 6218 * the device's natural orientation is portrait (width < height) or landscape. 6219 * 6220 * The menu key is assumed to be located along the bottom edge of natural-portrait 6221 * devices and along the right edge of natural-landscape devices. If these assumptions 6222 * do not hold for the target device, this method should be changed to reflect that. 6223 * 6224 * @return A {@link Gravity} value for placing the options menu window 6225 */ 6226 @Override 6227 public int getPreferredOptionsPanelGravity() { 6228 synchronized (mWindowMap) { 6229 final int rotation = getRotation(); 6230 6231 // TODO(multidisplay): Assume that such devices physical keys are on the main screen. 6232 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6233 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 6234 // On devices with a natural orientation of portrait 6235 switch (rotation) { 6236 default: 6237 case Surface.ROTATION_0: 6238 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6239 case Surface.ROTATION_90: 6240 return Gravity.RIGHT | Gravity.BOTTOM; 6241 case Surface.ROTATION_180: 6242 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6243 case Surface.ROTATION_270: 6244 return Gravity.START | Gravity.BOTTOM; 6245 } 6246 } 6247 6248 // On devices with a natural orientation of landscape 6249 switch (rotation) { 6250 default: 6251 case Surface.ROTATION_0: 6252 return Gravity.RIGHT | Gravity.BOTTOM; 6253 case Surface.ROTATION_90: 6254 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6255 case Surface.ROTATION_180: 6256 return Gravity.START | Gravity.BOTTOM; 6257 case Surface.ROTATION_270: 6258 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 6259 } 6260 } 6261 } 6262 6263 /** 6264 * Starts the view server on the specified port. 6265 * 6266 * @param port The port to listener to. 6267 * 6268 * @return True if the server was successfully started, false otherwise. 6269 * 6270 * @see com.android.server.wm.ViewServer 6271 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 6272 */ 6273 @Override 6274 public boolean startViewServer(int port) { 6275 if (isSystemSecure()) { 6276 return false; 6277 } 6278 6279 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 6280 return false; 6281 } 6282 6283 if (port < 1024) { 6284 return false; 6285 } 6286 6287 if (mViewServer != null) { 6288 if (!mViewServer.isRunning()) { 6289 try { 6290 return mViewServer.start(); 6291 } catch (IOException e) { 6292 Slog.w(TAG, "View server did not start"); 6293 } 6294 } 6295 return false; 6296 } 6297 6298 try { 6299 mViewServer = new ViewServer(this, port); 6300 return mViewServer.start(); 6301 } catch (IOException e) { 6302 Slog.w(TAG, "View server did not start"); 6303 } 6304 return false; 6305 } 6306 6307 private boolean isSystemSecure() { 6308 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 6309 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 6310 } 6311 6312 /** 6313 * Stops the view server if it exists. 6314 * 6315 * @return True if the server stopped, false if it wasn't started or 6316 * couldn't be stopped. 6317 * 6318 * @see com.android.server.wm.ViewServer 6319 */ 6320 @Override 6321 public boolean stopViewServer() { 6322 if (isSystemSecure()) { 6323 return false; 6324 } 6325 6326 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 6327 return false; 6328 } 6329 6330 if (mViewServer != null) { 6331 return mViewServer.stop(); 6332 } 6333 return false; 6334 } 6335 6336 /** 6337 * Indicates whether the view server is running. 6338 * 6339 * @return True if the server is running, false otherwise. 6340 * 6341 * @see com.android.server.wm.ViewServer 6342 */ 6343 @Override 6344 public boolean isViewServerRunning() { 6345 if (isSystemSecure()) { 6346 return false; 6347 } 6348 6349 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6350 return false; 6351 } 6352 6353 return mViewServer != null && mViewServer.isRunning(); 6354 } 6355 6356 /** 6357 * Lists all availble windows in the system. The listing is written in the 6358 * specified Socket's output stream with the following syntax: 6359 * windowHashCodeInHexadecimal windowName 6360 * Each line of the ouput represents a different window. 6361 * 6362 * @param client The remote client to send the listing to. 6363 * @return False if an error occured, true otherwise. 6364 */ 6365 boolean viewServerListWindows(Socket client) { 6366 if (isSystemSecure()) { 6367 return false; 6368 } 6369 6370 boolean result = true; 6371 6372 WindowList windows = new WindowList(); 6373 synchronized (mWindowMap) { 6374 //noinspection unchecked 6375 final int numDisplays = mDisplayContents.size(); 6376 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6377 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 6378 windows.addAll(displayContent.getWindowList()); 6379 } 6380 } 6381 6382 BufferedWriter out = null; 6383 6384 // Any uncaught exception will crash the system process 6385 try { 6386 OutputStream clientStream = client.getOutputStream(); 6387 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6388 6389 final int count = windows.size(); 6390 for (int i = 0; i < count; i++) { 6391 final WindowState w = windows.get(i); 6392 out.write(Integer.toHexString(System.identityHashCode(w))); 6393 out.write(' '); 6394 out.append(w.mAttrs.getTitle()); 6395 out.write('\n'); 6396 } 6397 6398 out.write("DONE.\n"); 6399 out.flush(); 6400 } catch (Exception e) { 6401 result = false; 6402 } finally { 6403 if (out != null) { 6404 try { 6405 out.close(); 6406 } catch (IOException e) { 6407 result = false; 6408 } 6409 } 6410 } 6411 6412 return result; 6413 } 6414 6415 // TODO(multidisplay): Extend to multiple displays. 6416 /** 6417 * Returns the focused window in the following format: 6418 * windowHashCodeInHexadecimal windowName 6419 * 6420 * @param client The remote client to send the listing to. 6421 * @return False if an error occurred, true otherwise. 6422 */ 6423 boolean viewServerGetFocusedWindow(Socket client) { 6424 if (isSystemSecure()) { 6425 return false; 6426 } 6427 6428 boolean result = true; 6429 6430 WindowState focusedWindow = getFocusedWindow(); 6431 6432 BufferedWriter out = null; 6433 6434 // Any uncaught exception will crash the system process 6435 try { 6436 OutputStream clientStream = client.getOutputStream(); 6437 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6438 6439 if(focusedWindow != null) { 6440 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6441 out.write(' '); 6442 out.append(focusedWindow.mAttrs.getTitle()); 6443 } 6444 out.write('\n'); 6445 out.flush(); 6446 } catch (Exception e) { 6447 result = false; 6448 } finally { 6449 if (out != null) { 6450 try { 6451 out.close(); 6452 } catch (IOException e) { 6453 result = false; 6454 } 6455 } 6456 } 6457 6458 return result; 6459 } 6460 6461 /** 6462 * Sends a command to a target window. The result of the command, if any, will be 6463 * written in the output stream of the specified socket. 6464 * 6465 * The parameters must follow this syntax: 6466 * windowHashcode extra 6467 * 6468 * Where XX is the length in characeters of the windowTitle. 6469 * 6470 * The first parameter is the target window. The window with the specified hashcode 6471 * will be the target. If no target can be found, nothing happens. The extra parameters 6472 * will be delivered to the target window and as parameters to the command itself. 6473 * 6474 * @param client The remote client to sent the result, if any, to. 6475 * @param command The command to execute. 6476 * @param parameters The command parameters. 6477 * 6478 * @return True if the command was successfully delivered, false otherwise. This does 6479 * not indicate whether the command itself was successful. 6480 */ 6481 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6482 if (isSystemSecure()) { 6483 return false; 6484 } 6485 6486 boolean success = true; 6487 Parcel data = null; 6488 Parcel reply = null; 6489 6490 BufferedWriter out = null; 6491 6492 // Any uncaught exception will crash the system process 6493 try { 6494 // Find the hashcode of the window 6495 int index = parameters.indexOf(' '); 6496 if (index == -1) { 6497 index = parameters.length(); 6498 } 6499 final String code = parameters.substring(0, index); 6500 int hashCode = (int) Long.parseLong(code, 16); 6501 6502 // Extract the command's parameter after the window description 6503 if (index < parameters.length()) { 6504 parameters = parameters.substring(index + 1); 6505 } else { 6506 parameters = ""; 6507 } 6508 6509 final WindowState window = findWindow(hashCode); 6510 if (window == null) { 6511 return false; 6512 } 6513 6514 data = Parcel.obtain(); 6515 data.writeInterfaceToken("android.view.IWindow"); 6516 data.writeString(command); 6517 data.writeString(parameters); 6518 data.writeInt(1); 6519 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6520 6521 reply = Parcel.obtain(); 6522 6523 final IBinder binder = window.mClient.asBinder(); 6524 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6525 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6526 6527 reply.readException(); 6528 6529 if (!client.isOutputShutdown()) { 6530 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6531 out.write("DONE\n"); 6532 out.flush(); 6533 } 6534 6535 } catch (Exception e) { 6536 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6537 success = false; 6538 } finally { 6539 if (data != null) { 6540 data.recycle(); 6541 } 6542 if (reply != null) { 6543 reply.recycle(); 6544 } 6545 if (out != null) { 6546 try { 6547 out.close(); 6548 } catch (IOException e) { 6549 6550 } 6551 } 6552 } 6553 6554 return success; 6555 } 6556 6557 public void addWindowChangeListener(WindowChangeListener listener) { 6558 synchronized(mWindowMap) { 6559 mWindowChangeListeners.add(listener); 6560 } 6561 } 6562 6563 public void removeWindowChangeListener(WindowChangeListener listener) { 6564 synchronized(mWindowMap) { 6565 mWindowChangeListeners.remove(listener); 6566 } 6567 } 6568 6569 private void notifyWindowsChanged() { 6570 WindowChangeListener[] windowChangeListeners; 6571 synchronized(mWindowMap) { 6572 if(mWindowChangeListeners.isEmpty()) { 6573 return; 6574 } 6575 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6576 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6577 } 6578 int N = windowChangeListeners.length; 6579 for(int i = 0; i < N; i++) { 6580 windowChangeListeners[i].windowsChanged(); 6581 } 6582 } 6583 6584 private void notifyFocusChanged() { 6585 WindowChangeListener[] windowChangeListeners; 6586 synchronized(mWindowMap) { 6587 if(mWindowChangeListeners.isEmpty()) { 6588 return; 6589 } 6590 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6591 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6592 } 6593 int N = windowChangeListeners.length; 6594 for(int i = 0; i < N; i++) { 6595 windowChangeListeners[i].focusChanged(); 6596 } 6597 } 6598 6599 private WindowState findWindow(int hashCode) { 6600 if (hashCode == -1) { 6601 // TODO(multidisplay): Extend to multiple displays. 6602 return getFocusedWindow(); 6603 } 6604 6605 synchronized (mWindowMap) { 6606 final int numDisplays = mDisplayContents.size(); 6607 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 6608 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 6609 final int numWindows = windows.size(); 6610 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 6611 final WindowState w = windows.get(winNdx); 6612 if (System.identityHashCode(w) == hashCode) { 6613 return w; 6614 } 6615 } 6616 } 6617 } 6618 6619 return null; 6620 } 6621 6622 /* 6623 * Instruct the Activity Manager to fetch the current configuration and broadcast 6624 * that to config-changed listeners if appropriate. 6625 */ 6626 void sendNewConfiguration() { 6627 try { 6628 mActivityManager.updateConfiguration(null); 6629 } catch (RemoteException e) { 6630 } 6631 } 6632 6633 public Configuration computeNewConfiguration() { 6634 synchronized (mWindowMap) { 6635 Configuration config = computeNewConfigurationLocked(); 6636 if (config == null && mWaitingForConfig) { 6637 // Nothing changed but we are waiting for something... stop that! 6638 mWaitingForConfig = false; 6639 mLastFinishedFreezeSource = "new-config"; 6640 performLayoutAndPlaceSurfacesLocked(); 6641 } 6642 return config; 6643 } 6644 } 6645 6646 Configuration computeNewConfigurationLocked() { 6647 Configuration config = new Configuration(); 6648 config.fontScale = 0; 6649 if (!computeScreenConfigurationLocked(config)) { 6650 return null; 6651 } 6652 return config; 6653 } 6654 6655 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6656 // TODO: Multidisplay: for now only use with default display. 6657 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6658 if (width < displayInfo.smallestNominalAppWidth) { 6659 displayInfo.smallestNominalAppWidth = width; 6660 } 6661 if (width > displayInfo.largestNominalAppWidth) { 6662 displayInfo.largestNominalAppWidth = width; 6663 } 6664 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6665 if (height < displayInfo.smallestNominalAppHeight) { 6666 displayInfo.smallestNominalAppHeight = height; 6667 } 6668 if (height > displayInfo.largestNominalAppHeight) { 6669 displayInfo.largestNominalAppHeight = height; 6670 } 6671 } 6672 6673 private int reduceConfigLayout(int curLayout, int rotation, float density, 6674 int dw, int dh) { 6675 // TODO: Multidisplay: for now only use with default display. 6676 // Get the app screen size at this rotation. 6677 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6678 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6679 6680 // Compute the screen layout size class for this rotation. 6681 int longSize = w; 6682 int shortSize = h; 6683 if (longSize < shortSize) { 6684 int tmp = longSize; 6685 longSize = shortSize; 6686 shortSize = tmp; 6687 } 6688 longSize = (int)(longSize/density); 6689 shortSize = (int)(shortSize/density); 6690 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6691 } 6692 6693 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6694 int dw, int dh, float density, Configuration outConfig) { 6695 // TODO: Multidisplay: for now only use with default display. 6696 6697 // We need to determine the smallest width that will occur under normal 6698 // operation. To this, start with the base screen size and compute the 6699 // width under the different possible rotations. We need to un-rotate 6700 // the current screen dimensions before doing this. 6701 int unrotDw, unrotDh; 6702 if (rotated) { 6703 unrotDw = dh; 6704 unrotDh = dw; 6705 } else { 6706 unrotDw = dw; 6707 unrotDh = dh; 6708 } 6709 displayInfo.smallestNominalAppWidth = 1<<30; 6710 displayInfo.smallestNominalAppHeight = 1<<30; 6711 displayInfo.largestNominalAppWidth = 0; 6712 displayInfo.largestNominalAppHeight = 0; 6713 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6714 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6715 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6716 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6717 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6718 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6719 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6720 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6721 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6722 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6723 outConfig.screenLayout = sl; 6724 } 6725 6726 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6727 int dw, int dh) { 6728 // TODO: Multidisplay: for now only use with default display. 6729 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6730 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6731 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6732 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6733 if (curSize == 0 || size < curSize) { 6734 curSize = size; 6735 } 6736 return curSize; 6737 } 6738 6739 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6740 // TODO: Multidisplay: for now only use with default display. 6741 mTmpDisplayMetrics.setTo(dm); 6742 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6743 final int unrotDw, unrotDh; 6744 if (rotated) { 6745 unrotDw = dh; 6746 unrotDh = dw; 6747 } else { 6748 unrotDw = dw; 6749 unrotDh = dh; 6750 } 6751 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6752 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6753 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6754 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6755 return sw; 6756 } 6757 6758 boolean computeScreenConfigurationLocked(Configuration config) { 6759 if (!mDisplayReady) { 6760 return false; 6761 } 6762 6763 // TODO(multidisplay): For now, apply Configuration to main screen only. 6764 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6765 6766 // Use the effective "visual" dimensions based on current rotation 6767 final boolean rotated = (mRotation == Surface.ROTATION_90 6768 || mRotation == Surface.ROTATION_270); 6769 final int realdw = rotated ? 6770 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6771 final int realdh = rotated ? 6772 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6773 int dw = realdw; 6774 int dh = realdh; 6775 6776 if (mAltOrientation) { 6777 if (realdw > realdh) { 6778 // Turn landscape into portrait. 6779 int maxw = (int)(realdh/1.3f); 6780 if (maxw < realdw) { 6781 dw = maxw; 6782 } 6783 } else { 6784 // Turn portrait into landscape. 6785 int maxh = (int)(realdw/1.3f); 6786 if (maxh < realdh) { 6787 dh = maxh; 6788 } 6789 } 6790 } 6791 6792 if (config != null) { 6793 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6794 Configuration.ORIENTATION_LANDSCAPE; 6795 } 6796 6797 // Update application display metrics. 6798 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6799 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6800 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6801 synchronized(displayContent.mDisplaySizeLock) { 6802 displayInfo.rotation = mRotation; 6803 displayInfo.logicalWidth = dw; 6804 displayInfo.logicalHeight = dh; 6805 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6806 displayInfo.appWidth = appWidth; 6807 displayInfo.appHeight = appHeight; 6808 displayInfo.getLogicalMetrics(mRealDisplayMetrics, 6809 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 6810 displayInfo.getAppMetrics(mDisplayMetrics); 6811 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 6812 displayContent.getDisplayId(), displayInfo); 6813 } 6814 if (false) { 6815 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6816 } 6817 6818 final DisplayMetrics dm = mDisplayMetrics; 6819 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6820 mCompatDisplayMetrics); 6821 6822 if (config != null) { 6823 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6824 / dm.density); 6825 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6826 / dm.density); 6827 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6828 6829 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6830 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6831 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6832 config.densityDpi = displayContent.mBaseDisplayDensity; 6833 6834 // Update the configuration based on available input devices, lid switch, 6835 // and platform configuration. 6836 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6837 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6838 config.navigation = Configuration.NAVIGATION_NONAV; 6839 6840 int keyboardPresence = 0; 6841 int navigationPresence = 0; 6842 final InputDevice[] devices = mInputManager.getInputDevices(); 6843 final int len = devices.length; 6844 for (int i = 0; i < len; i++) { 6845 InputDevice device = devices[i]; 6846 if (!device.isVirtual()) { 6847 final int sources = device.getSources(); 6848 final int presenceFlag = device.isExternal() ? 6849 WindowManagerPolicy.PRESENCE_EXTERNAL : 6850 WindowManagerPolicy.PRESENCE_INTERNAL; 6851 6852 if (mIsTouchDevice) { 6853 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6854 InputDevice.SOURCE_TOUCHSCREEN) { 6855 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6856 } 6857 } else { 6858 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6859 } 6860 6861 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6862 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6863 navigationPresence |= presenceFlag; 6864 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6865 && config.navigation == Configuration.NAVIGATION_NONAV) { 6866 config.navigation = Configuration.NAVIGATION_DPAD; 6867 navigationPresence |= presenceFlag; 6868 } 6869 6870 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6871 config.keyboard = Configuration.KEYBOARD_QWERTY; 6872 keyboardPresence |= presenceFlag; 6873 } 6874 } 6875 } 6876 6877 // Determine whether a hard keyboard is available and enabled. 6878 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6879 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6880 mHardKeyboardAvailable = hardKeyboardAvailable; 6881 mHardKeyboardEnabled = hardKeyboardAvailable; 6882 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6883 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6884 } 6885 if (!mHardKeyboardEnabled) { 6886 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6887 } 6888 6889 // Let the policy update hidden states. 6890 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6891 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6892 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6893 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6894 } 6895 6896 return true; 6897 } 6898 6899 public boolean isHardKeyboardAvailable() { 6900 synchronized (mWindowMap) { 6901 return mHardKeyboardAvailable; 6902 } 6903 } 6904 6905 public boolean isHardKeyboardEnabled() { 6906 synchronized (mWindowMap) { 6907 return mHardKeyboardEnabled; 6908 } 6909 } 6910 6911 public void setHardKeyboardEnabled(boolean enabled) { 6912 synchronized (mWindowMap) { 6913 if (mHardKeyboardEnabled != enabled) { 6914 mHardKeyboardEnabled = enabled; 6915 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6916 } 6917 } 6918 } 6919 6920 public void setOnHardKeyboardStatusChangeListener( 6921 OnHardKeyboardStatusChangeListener listener) { 6922 synchronized (mWindowMap) { 6923 mHardKeyboardStatusChangeListener = listener; 6924 } 6925 } 6926 6927 void notifyHardKeyboardStatusChange() { 6928 final boolean available, enabled; 6929 final OnHardKeyboardStatusChangeListener listener; 6930 synchronized (mWindowMap) { 6931 listener = mHardKeyboardStatusChangeListener; 6932 available = mHardKeyboardAvailable; 6933 enabled = mHardKeyboardEnabled; 6934 } 6935 if (listener != null) { 6936 listener.onHardKeyboardStatusChange(available, enabled); 6937 } 6938 } 6939 6940 // ------------------------------------------------------------- 6941 // Drag and drop 6942 // ------------------------------------------------------------- 6943 6944 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6945 int flags, int width, int height, Surface outSurface) { 6946 if (DEBUG_DRAG) { 6947 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6948 + " flags=" + Integer.toHexString(flags) + " win=" + window 6949 + " asbinder=" + window.asBinder()); 6950 } 6951 6952 final int callerPid = Binder.getCallingPid(); 6953 final long origId = Binder.clearCallingIdentity(); 6954 IBinder token = null; 6955 6956 try { 6957 synchronized (mWindowMap) { 6958 try { 6959 if (mDragState == null) { 6960 // TODO(multi-display): support other displays 6961 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6962 final Display display = displayContent.getDisplay(); 6963 SurfaceControl surface = new SurfaceControl(session, "drag surface", 6964 width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 6965 surface.setLayerStack(display.getLayerStack()); 6966 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6967 + surface + ": CREATE"); 6968 outSurface.copyFrom(surface); 6969 final IBinder winBinder = window.asBinder(); 6970 token = new Binder(); 6971 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6972 token = mDragState.mToken = new Binder(); 6973 6974 // 5 second timeout for this window to actually begin the drag 6975 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6976 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6977 mH.sendMessageDelayed(msg, 5000); 6978 } else { 6979 Slog.w(TAG, "Drag already in progress"); 6980 } 6981 } catch (OutOfResourcesException e) { 6982 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6983 if (mDragState != null) { 6984 mDragState.reset(); 6985 mDragState = null; 6986 } 6987 } 6988 } 6989 } finally { 6990 Binder.restoreCallingIdentity(origId); 6991 } 6992 6993 return token; 6994 } 6995 6996 // ------------------------------------------------------------- 6997 // Input Events and Focus Management 6998 // ------------------------------------------------------------- 6999 7000 final InputMonitor mInputMonitor = new InputMonitor(this); 7001 private boolean mEventDispatchingEnabled; 7002 7003 @Override 7004 public void pauseKeyDispatching(IBinder _token) { 7005 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7006 "pauseKeyDispatching()")) { 7007 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7008 } 7009 7010 synchronized (mWindowMap) { 7011 WindowToken token = mTokenMap.get(_token); 7012 if (token != null) { 7013 mInputMonitor.pauseDispatchingLw(token); 7014 } 7015 } 7016 } 7017 7018 @Override 7019 public void resumeKeyDispatching(IBinder _token) { 7020 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7021 "resumeKeyDispatching()")) { 7022 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7023 } 7024 7025 synchronized (mWindowMap) { 7026 WindowToken token = mTokenMap.get(_token); 7027 if (token != null) { 7028 mInputMonitor.resumeDispatchingLw(token); 7029 } 7030 } 7031 } 7032 7033 @Override 7034 public void setEventDispatching(boolean enabled) { 7035 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7036 "setEventDispatching()")) { 7037 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7038 } 7039 7040 synchronized (mWindowMap) { 7041 mEventDispatchingEnabled = enabled; 7042 if (mDisplayEnabled) { 7043 mInputMonitor.setEventDispatchingLw(enabled); 7044 } 7045 } 7046 } 7047 7048 @Override 7049 public IBinder getFocusedWindowToken() { 7050 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 7051 "getFocusedWindowToken()")) { 7052 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 7053 } 7054 synchronized (mWindowMap) { 7055 WindowState windowState = getFocusedWindowLocked(); 7056 if (windowState != null) { 7057 return windowState.mClient.asBinder(); 7058 } 7059 return null; 7060 } 7061 } 7062 7063 private WindowState getFocusedWindow() { 7064 synchronized (mWindowMap) { 7065 return getFocusedWindowLocked(); 7066 } 7067 } 7068 7069 private WindowState getFocusedWindowLocked() { 7070 return mCurrentFocus; 7071 } 7072 7073 public boolean detectSafeMode() { 7074 if (!mInputMonitor.waitForInputDevicesReady( 7075 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7076 Slog.w(TAG, "Devices still not ready after waiting " 7077 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7078 + " milliseconds before attempting to detect safe mode."); 7079 } 7080 7081 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7082 KeyEvent.KEYCODE_MENU); 7083 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7084 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7085 KeyEvent.KEYCODE_DPAD_CENTER); 7086 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7087 InputManagerService.BTN_MOUSE); 7088 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7089 KeyEvent.KEYCODE_VOLUME_DOWN); 7090 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7091 || volumeDownState > 0; 7092 try { 7093 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7094 mSafeMode = true; 7095 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7096 } 7097 } catch (IllegalArgumentException e) { 7098 } 7099 if (mSafeMode) { 7100 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7101 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7102 } else { 7103 Log.i(TAG, "SAFE MODE not enabled"); 7104 } 7105 mPolicy.setSafeMode(mSafeMode); 7106 return mSafeMode; 7107 } 7108 7109 public void displayReady() { 7110 displayReady(Display.DEFAULT_DISPLAY); 7111 7112 synchronized(mWindowMap) { 7113 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7114 readForcedDisplaySizeAndDensityLocked(displayContent); 7115 mDisplayReady = true; 7116 } 7117 7118 try { 7119 mActivityManager.updateConfiguration(null); 7120 } catch (RemoteException e) { 7121 } 7122 7123 synchronized(mWindowMap) { 7124 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7125 PackageManager.FEATURE_TOUCHSCREEN); 7126 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 7127 } 7128 7129 try { 7130 mActivityManager.updateConfiguration(null); 7131 } catch (RemoteException e) { 7132 } 7133 } 7134 7135 private void displayReady(int displayId) { 7136 synchronized(mWindowMap) { 7137 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7138 if (displayContent != null) { 7139 mAnimator.addDisplayLocked(displayId); 7140 synchronized(displayContent.mDisplaySizeLock) { 7141 // Bootstrap the default logical display from the display manager. 7142 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7143 DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); 7144 if (newDisplayInfo != null) { 7145 displayInfo.copyFrom(newDisplayInfo); 7146 } 7147 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7148 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7149 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7150 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7151 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7152 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7153 displayContent.mBaseDisplayRect.set(0, 0, 7154 displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); 7155 } 7156 } 7157 } 7158 } 7159 7160 public void systemReady() { 7161 mPolicy.systemReady(); 7162 } 7163 7164 // ------------------------------------------------------------- 7165 // Async Handler 7166 // ------------------------------------------------------------- 7167 7168 final class H extends Handler { 7169 public static final int REPORT_FOCUS_CHANGE = 2; 7170 public static final int REPORT_LOSING_FOCUS = 3; 7171 public static final int DO_TRAVERSAL = 4; 7172 public static final int ADD_STARTING = 5; 7173 public static final int REMOVE_STARTING = 6; 7174 public static final int FINISHED_STARTING = 7; 7175 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7176 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7177 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7178 7179 public static final int APP_TRANSITION_TIMEOUT = 13; 7180 public static final int PERSIST_ANIMATION_SCALE = 14; 7181 public static final int FORCE_GC = 15; 7182 public static final int ENABLE_SCREEN = 16; 7183 public static final int APP_FREEZE_TIMEOUT = 17; 7184 public static final int SEND_NEW_CONFIGURATION = 18; 7185 public static final int REPORT_WINDOWS_CHANGE = 19; 7186 public static final int DRAG_START_TIMEOUT = 20; 7187 public static final int DRAG_END_TIMEOUT = 21; 7188 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7189 public static final int BOOT_TIMEOUT = 23; 7190 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7191 public static final int SHOW_STRICT_MODE_VIOLATION = 25; 7192 public static final int DO_ANIMATION_CALLBACK = 26; 7193 7194 public static final int DO_DISPLAY_ADDED = 27; 7195 public static final int DO_DISPLAY_REMOVED = 28; 7196 public static final int DO_DISPLAY_CHANGED = 29; 7197 7198 public static final int CLIENT_FREEZE_TIMEOUT = 30; 7199 public static final int TAP_OUTSIDE_STACK = 31; 7200 public static final int NOTIFY_ACTIVITY_DRAWN = 32; 7201 7202 public static final int REMOVE_STARTING_TIMEOUT = 33; 7203 7204 public static final int SHOW_DISPLAY_MASK = 34; 7205 public static final int ALL_WINDOWS_DRAWN = 35; 7206 7207 @Override 7208 public void handleMessage(Message msg) { 7209 if (DEBUG_WINDOW_TRACE) { 7210 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7211 } 7212 switch (msg.what) { 7213 case REPORT_FOCUS_CHANGE: { 7214 WindowState lastFocus; 7215 WindowState newFocus; 7216 7217 synchronized(mWindowMap) { 7218 lastFocus = mLastFocus; 7219 newFocus = mCurrentFocus; 7220 if (lastFocus == newFocus) { 7221 // Focus is not changing, so nothing to do. 7222 return; 7223 } 7224 mLastFocus = newFocus; 7225 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus + 7226 " to " + newFocus); 7227 if (newFocus != null && lastFocus != null 7228 && !newFocus.isDisplayedLw()) { 7229 //Slog.i(TAG, "Delaying loss of focus..."); 7230 mLosingFocus.add(lastFocus); 7231 lastFocus = null; 7232 } 7233 } 7234 7235 //System.out.println("Changing focus from " + lastFocus 7236 // + " to " + newFocus); 7237 if (newFocus != null) { 7238 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus); 7239 newFocus.reportFocusChangedSerialized(true, mInTouchMode); 7240 notifyFocusChanged(); 7241 } 7242 7243 if (lastFocus != null) { 7244 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus); 7245 lastFocus.reportFocusChangedSerialized(false, mInTouchMode); 7246 } 7247 } break; 7248 7249 case REPORT_LOSING_FOCUS: { 7250 ArrayList<WindowState> losers; 7251 7252 synchronized(mWindowMap) { 7253 losers = mLosingFocus; 7254 mLosingFocus = new ArrayList<WindowState>(); 7255 } 7256 7257 final int N = losers.size(); 7258 for (int i=0; i<N; i++) { 7259 if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " + 7260 losers.get(i)); 7261 losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); 7262 } 7263 } break; 7264 7265 case DO_TRAVERSAL: { 7266 synchronized(mWindowMap) { 7267 mTraversalScheduled = false; 7268 performLayoutAndPlaceSurfacesLocked(); 7269 } 7270 } break; 7271 7272 case ADD_STARTING: { 7273 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7274 final StartingData sd = wtoken.startingData; 7275 7276 if (sd == null) { 7277 // Animation has been canceled... do nothing. 7278 return; 7279 } 7280 7281 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7282 + wtoken + ": pkg=" + sd.pkg); 7283 7284 View view = null; 7285 try { 7286 view = mPolicy.addStartingWindow( 7287 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7288 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags); 7289 } catch (Exception e) { 7290 Slog.w(TAG, "Exception when adding starting window", e); 7291 } 7292 7293 if (view != null) { 7294 boolean abort = false; 7295 7296 synchronized(mWindowMap) { 7297 if (wtoken.removed || wtoken.startingData == null) { 7298 // If the window was successfully added, then 7299 // we need to remove it. 7300 if (wtoken.startingWindow != null) { 7301 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7302 "Aborted starting " + wtoken 7303 + ": removed=" + wtoken.removed 7304 + " startingData=" + wtoken.startingData); 7305 removeStartingWindowTimeout(wtoken); 7306 wtoken.startingWindow = null; 7307 wtoken.startingData = null; 7308 abort = true; 7309 } 7310 } else { 7311 wtoken.startingView = view; 7312 } 7313 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7314 "Added starting " + wtoken 7315 + ": startingWindow=" 7316 + wtoken.startingWindow + " startingView=" 7317 + wtoken.startingView); 7318 } 7319 7320 if (abort) { 7321 try { 7322 mPolicy.removeStartingWindow(wtoken.token, view); 7323 } catch (Exception e) { 7324 Slog.w(TAG, "Exception when removing starting window", e); 7325 } 7326 } 7327 } 7328 } break; 7329 7330 case REMOVE_STARTING_TIMEOUT: { 7331 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7332 Slog.e(TAG, "Starting window " + wtoken + " timed out"); 7333 // Fall through. 7334 } 7335 case REMOVE_STARTING: { 7336 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7337 IBinder token = null; 7338 View view = null; 7339 synchronized (mWindowMap) { 7340 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7341 + wtoken + ": startingWindow=" 7342 + wtoken.startingWindow + " startingView=" 7343 + wtoken.startingView); 7344 if (wtoken.startingWindow != null) { 7345 view = wtoken.startingView; 7346 token = wtoken.token; 7347 wtoken.startingData = null; 7348 wtoken.startingView = null; 7349 wtoken.startingWindow = null; 7350 wtoken.startingDisplayed = false; 7351 } 7352 } 7353 if (view != null) { 7354 try { 7355 mPolicy.removeStartingWindow(token, view); 7356 } catch (Exception e) { 7357 Slog.w(TAG, "Exception when removing starting window", e); 7358 } 7359 } 7360 } break; 7361 7362 case FINISHED_STARTING: { 7363 IBinder token = null; 7364 View view = null; 7365 while (true) { 7366 synchronized (mWindowMap) { 7367 final int N = mFinishedStarting.size(); 7368 if (N <= 0) { 7369 break; 7370 } 7371 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7372 7373 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7374 "Finished starting " + wtoken 7375 + ": startingWindow=" + wtoken.startingWindow 7376 + " startingView=" + wtoken.startingView); 7377 7378 if (wtoken.startingWindow == null) { 7379 continue; 7380 } 7381 7382 view = wtoken.startingView; 7383 token = wtoken.token; 7384 wtoken.startingData = null; 7385 wtoken.startingView = null; 7386 wtoken.startingWindow = null; 7387 wtoken.startingDisplayed = false; 7388 } 7389 7390 try { 7391 mPolicy.removeStartingWindow(token, view); 7392 } catch (Exception e) { 7393 Slog.w(TAG, "Exception when removing starting window", e); 7394 } 7395 } 7396 } break; 7397 7398 case REPORT_APPLICATION_TOKEN_DRAWN: { 7399 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7400 7401 try { 7402 if (DEBUG_VISIBILITY) Slog.v( 7403 TAG, "Reporting drawn in " + wtoken); 7404 wtoken.appToken.windowsDrawn(); 7405 } catch (RemoteException ex) { 7406 } 7407 } break; 7408 7409 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7410 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7411 7412 boolean nowVisible = msg.arg1 != 0; 7413 boolean nowGone = msg.arg2 != 0; 7414 7415 try { 7416 if (DEBUG_VISIBILITY) Slog.v( 7417 TAG, "Reporting visible in " + wtoken 7418 + " visible=" + nowVisible 7419 + " gone=" + nowGone); 7420 if (nowVisible) { 7421 wtoken.appToken.windowsVisible(); 7422 } else { 7423 wtoken.appToken.windowsGone(); 7424 } 7425 } catch (RemoteException ex) { 7426 } 7427 } break; 7428 7429 case WINDOW_FREEZE_TIMEOUT: { 7430 // TODO(multidisplay): Can non-default displays rotate? 7431 synchronized (mWindowMap) { 7432 Slog.w(TAG, "Window freeze timeout expired."); 7433 final WindowList windows = getDefaultWindowListLocked(); 7434 int i = windows.size(); 7435 while (i > 0) { 7436 i--; 7437 WindowState w = windows.get(i); 7438 if (w.mOrientationChanging) { 7439 w.mOrientationChanging = false; 7440 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 7441 - mDisplayFreezeTime); 7442 Slog.w(TAG, "Force clearing orientation change: " + w); 7443 } 7444 } 7445 performLayoutAndPlaceSurfacesLocked(); 7446 } 7447 break; 7448 } 7449 7450 case APP_TRANSITION_TIMEOUT: { 7451 synchronized (mWindowMap) { 7452 if (mAppTransition.isTransitionSet()) { 7453 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT"); 7454 mAppTransition.setTimeout(); 7455 performLayoutAndPlaceSurfacesLocked(); 7456 } 7457 } 7458 break; 7459 } 7460 7461 case PERSIST_ANIMATION_SCALE: { 7462 Settings.Global.putFloat(mContext.getContentResolver(), 7463 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 7464 Settings.Global.putFloat(mContext.getContentResolver(), 7465 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 7466 Settings.Global.putFloat(mContext.getContentResolver(), 7467 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 7468 break; 7469 } 7470 7471 case FORCE_GC: { 7472 synchronized (mWindowMap) { 7473 // Since we're holding both mWindowMap and mAnimator we don't need to 7474 // hold mAnimator.mLayoutToAnim. 7475 if (mAnimator.mAnimating || mAnimationScheduled) { 7476 // If we are animating, don't do the gc now but 7477 // delay a bit so we don't interrupt the animation. 7478 sendEmptyMessageDelayed(H.FORCE_GC, 2000); 7479 return; 7480 } 7481 // If we are currently rotating the display, it will 7482 // schedule a new message when done. 7483 if (mDisplayFrozen) { 7484 return; 7485 } 7486 } 7487 Runtime.getRuntime().gc(); 7488 break; 7489 } 7490 7491 case ENABLE_SCREEN: { 7492 performEnableScreen(); 7493 break; 7494 } 7495 7496 case APP_FREEZE_TIMEOUT: { 7497 synchronized (mWindowMap) { 7498 Slog.w(TAG, "App freeze timeout expired."); 7499 final int numStacks = mStackIdToStack.size(); 7500 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 7501 final TaskStack stack = mStackIdToStack.valueAt(stackNdx); 7502 final ArrayList<Task> tasks = stack.getTasks(); 7503 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 7504 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 7505 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 7506 AppWindowToken tok = tokens.get(tokenNdx); 7507 if (tok.mAppAnimator.freezingScreen) { 7508 Slog.w(TAG, "Force clearing freeze: " + tok); 7509 unsetAppFreezingScreenLocked(tok, true, true); 7510 } 7511 } 7512 } 7513 } 7514 } 7515 break; 7516 } 7517 7518 case CLIENT_FREEZE_TIMEOUT: { 7519 synchronized (mWindowMap) { 7520 if (mClientFreezingScreen) { 7521 mClientFreezingScreen = false; 7522 mLastFinishedFreezeSource = "client-timeout"; 7523 stopFreezingDisplayLocked(); 7524 } 7525 } 7526 break; 7527 } 7528 7529 case SEND_NEW_CONFIGURATION: { 7530 removeMessages(SEND_NEW_CONFIGURATION); 7531 sendNewConfiguration(); 7532 break; 7533 } 7534 7535 case REPORT_WINDOWS_CHANGE: { 7536 if (mWindowsChanged) { 7537 synchronized (mWindowMap) { 7538 mWindowsChanged = false; 7539 } 7540 notifyWindowsChanged(); 7541 } 7542 break; 7543 } 7544 7545 case DRAG_START_TIMEOUT: { 7546 IBinder win = (IBinder)msg.obj; 7547 if (DEBUG_DRAG) { 7548 Slog.w(TAG, "Timeout starting drag by win " + win); 7549 } 7550 synchronized (mWindowMap) { 7551 // !!! TODO: ANR the app that has failed to start the drag in time 7552 if (mDragState != null) { 7553 mDragState.unregister(); 7554 mInputMonitor.updateInputWindowsLw(true /*force*/); 7555 mDragState.reset(); 7556 mDragState = null; 7557 } 7558 } 7559 break; 7560 } 7561 7562 case DRAG_END_TIMEOUT: { 7563 IBinder win = (IBinder)msg.obj; 7564 if (DEBUG_DRAG) { 7565 Slog.w(TAG, "Timeout ending drag to win " + win); 7566 } 7567 synchronized (mWindowMap) { 7568 // !!! TODO: ANR the drag-receiving app 7569 if (mDragState != null) { 7570 mDragState.mDragResult = false; 7571 mDragState.endDragLw(); 7572 } 7573 } 7574 break; 7575 } 7576 7577 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7578 notifyHardKeyboardStatusChange(); 7579 break; 7580 } 7581 7582 case BOOT_TIMEOUT: { 7583 performBootTimeout(); 7584 break; 7585 } 7586 7587 case WAITING_FOR_DRAWN_TIMEOUT: { 7588 IRemoteCallback callback = null; 7589 synchronized (mWindowMap) { 7590 Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn); 7591 mWaitingForDrawn.clear(); 7592 callback = mWaitingForDrawnCallback; 7593 mWaitingForDrawnCallback = null; 7594 } 7595 if (callback != null) { 7596 try { 7597 callback.sendResult(null); 7598 } catch (RemoteException e) { 7599 } 7600 } 7601 break; 7602 } 7603 7604 case SHOW_STRICT_MODE_VIOLATION: { 7605 showStrictModeViolation(msg.arg1, msg.arg2); 7606 break; 7607 } 7608 7609 case SHOW_DISPLAY_MASK: { 7610 showCircularMask(); 7611 break; 7612 } 7613 7614 case DO_ANIMATION_CALLBACK: { 7615 try { 7616 ((IRemoteCallback)msg.obj).sendResult(null); 7617 } catch (RemoteException e) { 7618 } 7619 break; 7620 } 7621 7622 case DO_DISPLAY_ADDED: 7623 handleDisplayAdded(msg.arg1); 7624 break; 7625 7626 case DO_DISPLAY_REMOVED: 7627 synchronized (mWindowMap) { 7628 handleDisplayRemovedLocked(msg.arg1); 7629 } 7630 break; 7631 7632 case DO_DISPLAY_CHANGED: 7633 synchronized (mWindowMap) { 7634 handleDisplayChangedLocked(msg.arg1); 7635 } 7636 break; 7637 7638 case TAP_OUTSIDE_STACK: { 7639 int stackId; 7640 synchronized (mWindowMap) { 7641 stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); 7642 } 7643 if (stackId >= 0) { 7644 try { 7645 mActivityManager.setFocusedStack(stackId); 7646 } catch (RemoteException e) { 7647 } 7648 } 7649 } 7650 break; 7651 case NOTIFY_ACTIVITY_DRAWN: 7652 try { 7653 mActivityManager.notifyActivityDrawn((IBinder) msg.obj); 7654 } catch (RemoteException e) { 7655 } 7656 break; 7657 case ALL_WINDOWS_DRAWN: { 7658 IRemoteCallback callback; 7659 synchronized (mWindowMap) { 7660 callback = mWaitingForDrawnCallback; 7661 mWaitingForDrawnCallback = null; 7662 } 7663 if (callback != null) { 7664 try { 7665 callback.sendResult(null); 7666 } catch (RemoteException e) { 7667 } 7668 } 7669 } 7670 } 7671 if (DEBUG_WINDOW_TRACE) { 7672 Slog.v(TAG, "handleMessage: exit"); 7673 } 7674 } 7675 } 7676 7677 // ------------------------------------------------------------- 7678 // IWindowManager API 7679 // ------------------------------------------------------------- 7680 7681 @Override 7682 public IWindowSession openSession(IInputMethodClient client, 7683 IInputContext inputContext) { 7684 if (client == null) throw new IllegalArgumentException("null client"); 7685 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7686 Session session = new Session(this, client, inputContext); 7687 return session; 7688 } 7689 7690 @Override 7691 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7692 synchronized (mWindowMap) { 7693 // The focus for the client is the window immediately below 7694 // where we would place the input method window. 7695 int idx = findDesiredInputMethodWindowIndexLocked(false); 7696 if (idx > 0) { 7697 // TODO(multidisplay): IMEs are only supported on the default display. 7698 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7699 if (DEBUG_INPUT_METHOD) { 7700 Slog.i(TAG, "Desired input method target: " + imFocus); 7701 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7702 Slog.i(TAG, "Last focus: " + mLastFocus); 7703 } 7704 if (imFocus != null) { 7705 // This may be a starting window, in which case we still want 7706 // to count it as okay. 7707 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7708 && imFocus.mAppToken != null) { 7709 // The client has definitely started, so it really should 7710 // have a window in this app token. Let's look for it. 7711 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7712 WindowState w = imFocus.mAppToken.windows.get(i); 7713 if (w != imFocus) { 7714 Log.i(TAG, "Switching to real app window: " + w); 7715 imFocus = w; 7716 break; 7717 } 7718 } 7719 } 7720 if (DEBUG_INPUT_METHOD) { 7721 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7722 if (imFocus.mSession.mClient != null) { 7723 Slog.i(TAG, "IM target client binder: " 7724 + imFocus.mSession.mClient.asBinder()); 7725 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7726 } 7727 } 7728 if (imFocus.mSession.mClient != null && 7729 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7730 return true; 7731 } 7732 } 7733 } 7734 7735 // Okay, how about this... what is the current focus? 7736 // It seems in some cases we may not have moved the IM 7737 // target window, such as when it was in a pop-up window, 7738 // so let's also look at the current focus. (An example: 7739 // go to Gmail, start searching so the keyboard goes up, 7740 // press home. Sometimes the IME won't go down.) 7741 // Would be nice to fix this more correctly, but it's 7742 // way at the end of a release, and this should be good enough. 7743 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7744 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7745 return true; 7746 } 7747 } 7748 return false; 7749 } 7750 7751 @Override 7752 public void getInitialDisplaySize(int displayId, Point size) { 7753 synchronized (mWindowMap) { 7754 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7755 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7756 synchronized(displayContent.mDisplaySizeLock) { 7757 size.x = displayContent.mInitialDisplayWidth; 7758 size.y = displayContent.mInitialDisplayHeight; 7759 } 7760 } 7761 } 7762 } 7763 7764 @Override 7765 public void getBaseDisplaySize(int displayId, Point size) { 7766 synchronized (mWindowMap) { 7767 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7768 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7769 synchronized(displayContent.mDisplaySizeLock) { 7770 size.x = displayContent.mBaseDisplayWidth; 7771 size.y = displayContent.mBaseDisplayHeight; 7772 } 7773 } 7774 } 7775 } 7776 7777 @Override 7778 public void setForcedDisplaySize(int displayId, int width, int height) { 7779 if (mContext.checkCallingOrSelfPermission( 7780 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7781 PackageManager.PERMISSION_GRANTED) { 7782 throw new SecurityException("Must hold permission " + 7783 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7784 } 7785 if (displayId != Display.DEFAULT_DISPLAY) { 7786 throw new IllegalArgumentException("Can only set the default display"); 7787 } 7788 final long ident = Binder.clearCallingIdentity(); 7789 try { 7790 synchronized(mWindowMap) { 7791 // Set some sort of reasonable bounds on the size of the display that we 7792 // will try to emulate. 7793 final int MIN_WIDTH = 200; 7794 final int MIN_HEIGHT = 200; 7795 final int MAX_SCALE = 2; 7796 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7797 if (displayContent != null) { 7798 width = Math.min(Math.max(width, MIN_WIDTH), 7799 displayContent.mInitialDisplayWidth * MAX_SCALE); 7800 height = Math.min(Math.max(height, MIN_HEIGHT), 7801 displayContent.mInitialDisplayHeight * MAX_SCALE); 7802 setForcedDisplaySizeLocked(displayContent, width, height); 7803 Settings.Global.putString(mContext.getContentResolver(), 7804 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7805 } 7806 } 7807 } finally { 7808 Binder.restoreCallingIdentity(ident); 7809 } 7810 } 7811 7812 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7813 String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7814 Settings.Global.DISPLAY_SIZE_FORCED); 7815 if (sizeStr == null || sizeStr.length() == 0) { 7816 sizeStr = SystemProperties.get(SIZE_OVERRIDE, null); 7817 } 7818 if (sizeStr != null && sizeStr.length() > 0) { 7819 final int pos = sizeStr.indexOf(','); 7820 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7821 int width, height; 7822 try { 7823 width = Integer.parseInt(sizeStr.substring(0, pos)); 7824 height = Integer.parseInt(sizeStr.substring(pos+1)); 7825 synchronized(displayContent.mDisplaySizeLock) { 7826 if (displayContent.mBaseDisplayWidth != width 7827 || displayContent.mBaseDisplayHeight != height) { 7828 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7829 displayContent.mBaseDisplayWidth = width; 7830 displayContent.mBaseDisplayHeight = height; 7831 } 7832 } 7833 } catch (NumberFormatException ex) { 7834 } 7835 } 7836 } 7837 String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7838 Settings.Global.DISPLAY_DENSITY_FORCED); 7839 if (densityStr == null || densityStr.length() == 0) { 7840 densityStr = SystemProperties.get(DENSITY_OVERRIDE, null); 7841 } 7842 if (densityStr != null && densityStr.length() > 0) { 7843 int density; 7844 try { 7845 density = Integer.parseInt(densityStr); 7846 synchronized(displayContent.mDisplaySizeLock) { 7847 if (displayContent.mBaseDisplayDensity != density) { 7848 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7849 displayContent.mBaseDisplayDensity = density; 7850 } 7851 } 7852 } catch (NumberFormatException ex) { 7853 } 7854 } 7855 } 7856 7857 // displayContent must not be null 7858 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7859 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7860 7861 synchronized(displayContent.mDisplaySizeLock) { 7862 displayContent.mBaseDisplayWidth = width; 7863 displayContent.mBaseDisplayHeight = height; 7864 } 7865 reconfigureDisplayLocked(displayContent); 7866 } 7867 7868 @Override 7869 public void clearForcedDisplaySize(int displayId) { 7870 if (mContext.checkCallingOrSelfPermission( 7871 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7872 PackageManager.PERMISSION_GRANTED) { 7873 throw new SecurityException("Must hold permission " + 7874 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7875 } 7876 if (displayId != Display.DEFAULT_DISPLAY) { 7877 throw new IllegalArgumentException("Can only set the default display"); 7878 } 7879 final long ident = Binder.clearCallingIdentity(); 7880 try { 7881 synchronized(mWindowMap) { 7882 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7883 if (displayContent != null) { 7884 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7885 displayContent.mInitialDisplayHeight); 7886 Settings.Global.putString(mContext.getContentResolver(), 7887 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7888 } 7889 } 7890 } finally { 7891 Binder.restoreCallingIdentity(ident); 7892 } 7893 } 7894 7895 @Override 7896 public int getInitialDisplayDensity(int displayId) { 7897 synchronized (mWindowMap) { 7898 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7899 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7900 synchronized(displayContent.mDisplaySizeLock) { 7901 return displayContent.mInitialDisplayDensity; 7902 } 7903 } 7904 } 7905 return -1; 7906 } 7907 7908 @Override 7909 public int getBaseDisplayDensity(int displayId) { 7910 synchronized (mWindowMap) { 7911 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7912 if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) { 7913 synchronized(displayContent.mDisplaySizeLock) { 7914 return displayContent.mBaseDisplayDensity; 7915 } 7916 } 7917 } 7918 return -1; 7919 } 7920 7921 @Override 7922 public void setForcedDisplayDensity(int displayId, int density) { 7923 if (mContext.checkCallingOrSelfPermission( 7924 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7925 PackageManager.PERMISSION_GRANTED) { 7926 throw new SecurityException("Must hold permission " + 7927 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7928 } 7929 if (displayId != Display.DEFAULT_DISPLAY) { 7930 throw new IllegalArgumentException("Can only set the default display"); 7931 } 7932 final long ident = Binder.clearCallingIdentity(); 7933 try { 7934 synchronized(mWindowMap) { 7935 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7936 if (displayContent != null) { 7937 setForcedDisplayDensityLocked(displayContent, density); 7938 Settings.Global.putString(mContext.getContentResolver(), 7939 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7940 } 7941 } 7942 } finally { 7943 Binder.restoreCallingIdentity(ident); 7944 } 7945 } 7946 7947 // displayContent must not be null 7948 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7949 Slog.i(TAG, "Using new display density: " + density); 7950 7951 synchronized(displayContent.mDisplaySizeLock) { 7952 displayContent.mBaseDisplayDensity = density; 7953 } 7954 reconfigureDisplayLocked(displayContent); 7955 } 7956 7957 @Override 7958 public void clearForcedDisplayDensity(int displayId) { 7959 if (mContext.checkCallingOrSelfPermission( 7960 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 7961 PackageManager.PERMISSION_GRANTED) { 7962 throw new SecurityException("Must hold permission " + 7963 android.Manifest.permission.WRITE_SECURE_SETTINGS); 7964 } 7965 if (displayId != Display.DEFAULT_DISPLAY) { 7966 throw new IllegalArgumentException("Can only set the default display"); 7967 } 7968 final long ident = Binder.clearCallingIdentity(); 7969 try { 7970 synchronized(mWindowMap) { 7971 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7972 if (displayContent != null) { 7973 setForcedDisplayDensityLocked(displayContent, 7974 displayContent.mInitialDisplayDensity); 7975 Settings.Global.putString(mContext.getContentResolver(), 7976 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7977 } 7978 } 7979 } finally { 7980 Binder.restoreCallingIdentity(ident); 7981 } 7982 } 7983 7984 // displayContent must not be null 7985 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7986 // TODO: Multidisplay: for now only use with default display. 7987 configureDisplayPolicyLocked(displayContent); 7988 displayContent.layoutNeeded = true; 7989 7990 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7991 mTempConfiguration.setToDefaults(); 7992 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7993 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7994 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7995 configChanged = true; 7996 } 7997 } 7998 7999 if (configChanged) { 8000 mWaitingForConfig = true; 8001 startFreezingDisplayLocked(false, 0, 0); 8002 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8003 } 8004 8005 performLayoutAndPlaceSurfacesLocked(); 8006 } 8007 8008 private void configureDisplayPolicyLocked(DisplayContent displayContent) { 8009 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 8010 displayContent.mBaseDisplayWidth, 8011 displayContent.mBaseDisplayHeight, 8012 displayContent.mBaseDisplayDensity); 8013 8014 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8015 mPolicy.setDisplayOverscan(displayContent.getDisplay(), 8016 displayInfo.overscanLeft, displayInfo.overscanTop, 8017 displayInfo.overscanRight, displayInfo.overscanBottom); 8018 } 8019 8020 @Override 8021 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 8022 if (mContext.checkCallingOrSelfPermission( 8023 android.Manifest.permission.WRITE_SECURE_SETTINGS) != 8024 PackageManager.PERMISSION_GRANTED) { 8025 throw new SecurityException("Must hold permission " + 8026 android.Manifest.permission.WRITE_SECURE_SETTINGS); 8027 } 8028 final long ident = Binder.clearCallingIdentity(); 8029 try { 8030 synchronized(mWindowMap) { 8031 DisplayContent displayContent = getDisplayContentLocked(displayId); 8032 if (displayContent != null) { 8033 setOverscanLocked(displayContent, left, top, right, bottom); 8034 } 8035 } 8036 } finally { 8037 Binder.restoreCallingIdentity(ident); 8038 } 8039 } 8040 8041 private void setOverscanLocked(DisplayContent displayContent, 8042 int left, int top, int right, int bottom) { 8043 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8044 synchronized (displayContent.mDisplaySizeLock) { 8045 displayInfo.overscanLeft = left; 8046 displayInfo.overscanTop = top; 8047 displayInfo.overscanRight = right; 8048 displayInfo.overscanBottom = bottom; 8049 } 8050 8051 mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom); 8052 mDisplaySettings.writeSettingsLocked(); 8053 8054 reconfigureDisplayLocked(displayContent); 8055 } 8056 8057 // ------------------------------------------------------------- 8058 // Internals 8059 // ------------------------------------------------------------- 8060 8061 final WindowState windowForClientLocked(Session session, IWindow client, 8062 boolean throwOnError) { 8063 return windowForClientLocked(session, client.asBinder(), throwOnError); 8064 } 8065 8066 final WindowState windowForClientLocked(Session session, IBinder client, 8067 boolean throwOnError) { 8068 WindowState win = mWindowMap.get(client); 8069 if (localLOGV) Slog.v( 8070 TAG, "Looking up client " + client + ": " + win); 8071 if (win == null) { 8072 RuntimeException ex = new IllegalArgumentException( 8073 "Requested window " + client + " does not exist"); 8074 if (throwOnError) { 8075 throw ex; 8076 } 8077 Slog.w(TAG, "Failed looking up window", ex); 8078 return null; 8079 } 8080 if (session != null && win.mSession != session) { 8081 RuntimeException ex = new IllegalArgumentException( 8082 "Requested window " + client + " is in session " + 8083 win.mSession + ", not " + session); 8084 if (throwOnError) { 8085 throw ex; 8086 } 8087 Slog.w(TAG, "Failed looking up window", ex); 8088 return null; 8089 } 8090 8091 return win; 8092 } 8093 8094 final void rebuildAppWindowListLocked() { 8095 rebuildAppWindowListLocked(getDefaultDisplayContentLocked()); 8096 } 8097 8098 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8099 final WindowList windows = displayContent.getWindowList(); 8100 int NW = windows.size(); 8101 int i; 8102 int lastBelow = -1; 8103 int numRemoved = 0; 8104 8105 if (mRebuildTmp.length < NW) { 8106 mRebuildTmp = new WindowState[NW+10]; 8107 } 8108 8109 // First remove all existing app windows. 8110 i=0; 8111 while (i < NW) { 8112 WindowState w = windows.get(i); 8113 if (w.mAppToken != null) { 8114 WindowState win = windows.remove(i); 8115 win.mRebuilding = true; 8116 mRebuildTmp[numRemoved] = win; 8117 mWindowsChanged = true; 8118 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win); 8119 NW--; 8120 numRemoved++; 8121 continue; 8122 } else if (lastBelow == i-1) { 8123 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8124 lastBelow = i; 8125 } 8126 } 8127 i++; 8128 } 8129 8130 // Keep whatever windows were below the app windows still below, 8131 // by skipping them. 8132 lastBelow++; 8133 i = lastBelow; 8134 8135 // First add all of the exiting app tokens... these are no longer 8136 // in the main app list, but still have windows shown. We put them 8137 // in the back because now that the animation is over we no longer 8138 // will care about them. 8139 final ArrayList<TaskStack> stacks = displayContent.getStacks(); 8140 final int numStacks = stacks.size(); 8141 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8142 AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens; 8143 int NT = exitingAppTokens.size(); 8144 for (int j = 0; j < NT; j++) { 8145 i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j)); 8146 } 8147 } 8148 8149 // And add in the still active app tokens in Z order. 8150 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 8151 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8152 final int numTasks = tasks.size(); 8153 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 8154 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8155 final int numTokens = tokens.size(); 8156 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { 8157 final AppWindowToken wtoken = tokens.get(tokenNdx); 8158 if (wtoken.mDeferRemoval) { 8159 continue; 8160 } 8161 i = reAddAppWindowsLocked(displayContent, i, wtoken); 8162 } 8163 } 8164 } 8165 8166 i -= lastBelow; 8167 if (i != numRemoved) { 8168 Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + 8169 numRemoved + " windows but added " + i, 8170 new RuntimeException("here").fillInStackTrace()); 8171 for (i=0; i<numRemoved; i++) { 8172 WindowState ws = mRebuildTmp[i]; 8173 if (ws.mRebuilding) { 8174 StringWriter sw = new StringWriter(); 8175 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 8176 ws.dump(pw, "", true); 8177 pw.flush(); 8178 Slog.w(TAG, "This window was lost: " + ws); 8179 Slog.w(TAG, sw.toString()); 8180 ws.mWinAnimator.destroySurfaceLocked(); 8181 } 8182 } 8183 Slog.w(TAG, "Current app token list:"); 8184 dumpAppTokensLocked(); 8185 Slog.w(TAG, "Final window list:"); 8186 dumpWindowsLocked(); 8187 } 8188 } 8189 8190 private final void assignLayersLocked(WindowList windows) { 8191 int N = windows.size(); 8192 int curBaseLayer = 0; 8193 int curLayer = 0; 8194 int i; 8195 8196 if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows, 8197 new RuntimeException("here").fillInStackTrace()); 8198 8199 boolean anyLayerChanged = false; 8200 8201 for (i=0; i<N; i++) { 8202 final WindowState w = windows.get(i); 8203 final WindowStateAnimator winAnimator = w.mWinAnimator; 8204 boolean layerChanged = false; 8205 int oldLayer = w.mLayer; 8206 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8207 || (i > 0 && w.mIsWallpaper)) { 8208 curLayer += WINDOW_LAYER_MULTIPLIER; 8209 w.mLayer = curLayer; 8210 } else { 8211 curBaseLayer = curLayer = w.mBaseLayer; 8212 w.mLayer = curLayer; 8213 } 8214 if (w.mLayer != oldLayer) { 8215 layerChanged = true; 8216 anyLayerChanged = true; 8217 } 8218 final AppWindowToken wtoken = w.mAppToken; 8219 oldLayer = winAnimator.mAnimLayer; 8220 if (w.mTargetAppToken != null) { 8221 winAnimator.mAnimLayer = 8222 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8223 } else if (wtoken != null) { 8224 winAnimator.mAnimLayer = 8225 w.mLayer + wtoken.mAppAnimator.animLayerAdjustment; 8226 } else { 8227 winAnimator.mAnimLayer = w.mLayer; 8228 } 8229 if (w.mIsImWindow) { 8230 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8231 } else if (w.mIsWallpaper) { 8232 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8233 } 8234 if (winAnimator.mAnimLayer != oldLayer) { 8235 layerChanged = true; 8236 anyLayerChanged = true; 8237 } 8238 if (layerChanged && w.getStack().isDimming(winAnimator)) { 8239 // Force an animation pass just to update the mDimLayer layer. 8240 scheduleAnimationLocked(); 8241 } 8242 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8243 + "mBase=" + w.mBaseLayer 8244 + " mLayer=" + w.mLayer 8245 + (wtoken == null ? 8246 "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment) 8247 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8248 //System.out.println( 8249 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8250 } 8251 8252 //TODO (multidisplay): Magnification is supported only for the default display. 8253 if (mDisplayMagnifier != null && anyLayerChanged 8254 && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) { 8255 mDisplayMagnifier.onWindowLayersChangedLocked(); 8256 } 8257 } 8258 8259 private final void performLayoutAndPlaceSurfacesLocked() { 8260 int loopCount = 6; 8261 do { 8262 mTraversalScheduled = false; 8263 performLayoutAndPlaceSurfacesLockedLoop(); 8264 mH.removeMessages(H.DO_TRAVERSAL); 8265 loopCount--; 8266 } while (mTraversalScheduled && loopCount > 0); 8267 mInnerFields.mWallpaperActionPending = false; 8268 } 8269 8270 private boolean mInLayout = false; 8271 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8272 if (mInLayout) { 8273 if (DEBUG) { 8274 throw new RuntimeException("Recursive call!"); 8275 } 8276 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8277 + Debug.getCallers(3)); 8278 return; 8279 } 8280 8281 if (mWaitingForConfig) { 8282 // Our configuration has changed (most likely rotation), but we 8283 // don't yet have the complete configuration to report to 8284 // applications. Don't do any window layout until we have it. 8285 return; 8286 } 8287 8288 if (!mDisplayReady) { 8289 // Not yet initialized, nothing to do. 8290 return; 8291 } 8292 8293 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8294 mInLayout = true; 8295 boolean recoveringMemory = false; 8296 8297 try { 8298 if (mForceRemoves != null) { 8299 recoveringMemory = true; 8300 // Wait a little bit for things to settle down, and off we go. 8301 for (int i=0; i<mForceRemoves.size(); i++) { 8302 WindowState ws = mForceRemoves.get(i); 8303 Slog.i(TAG, "Force removing: " + ws); 8304 removeWindowInnerLocked(ws.mSession, ws); 8305 } 8306 mForceRemoves = null; 8307 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8308 Object tmp = new Object(); 8309 synchronized (tmp) { 8310 try { 8311 tmp.wait(250); 8312 } catch (InterruptedException e) { 8313 } 8314 } 8315 } 8316 } catch (RuntimeException e) { 8317 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8318 } 8319 8320 try { 8321 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8322 8323 mInLayout = false; 8324 8325 if (needsLayout()) { 8326 if (++mLayoutRepeatCount < 6) { 8327 requestTraversalLocked(); 8328 } else { 8329 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8330 mLayoutRepeatCount = 0; 8331 } 8332 } else { 8333 mLayoutRepeatCount = 0; 8334 } 8335 8336 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8337 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8338 mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE); 8339 } 8340 } catch (RuntimeException e) { 8341 mInLayout = false; 8342 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8343 } 8344 8345 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8346 } 8347 8348 private final void performLayoutLockedInner(final DisplayContent displayContent, 8349 boolean initial, boolean updateInputWindows) { 8350 if (!displayContent.layoutNeeded) { 8351 return; 8352 } 8353 displayContent.layoutNeeded = false; 8354 WindowList windows = displayContent.getWindowList(); 8355 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8356 8357 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8358 final int dw = displayInfo.logicalWidth; 8359 final int dh = displayInfo.logicalHeight; 8360 8361 final int NFW = mFakeWindows.size(); 8362 for (int i=0; i<NFW; i++) { 8363 mFakeWindows.get(i).layout(dw, dh); 8364 } 8365 8366 final int N = windows.size(); 8367 int i; 8368 8369 if (DEBUG_LAYOUT) { 8370 Slog.v(TAG, "-------------------------------------"); 8371 Slog.v(TAG, "performLayout: needed=" 8372 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8373 } 8374 8375 WindowStateAnimator universeBackground = null; 8376 8377 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8378 if (isDefaultDisplay) { 8379 // Not needed on non-default displays. 8380 mSystemDecorLayer = mPolicy.getSystemDecorLayerLw(); 8381 mScreenRect.set(0, 0, dw, dh); 8382 } 8383 8384 mPolicy.getContentRectLw(mTmpContentRect); 8385 displayContent.resize(mTmpContentRect); 8386 8387 int seq = mLayoutSeq+1; 8388 if (seq < 0) seq = 0; 8389 mLayoutSeq = seq; 8390 8391 boolean behindDream = false; 8392 8393 // First perform layout of any root windows (not attached 8394 // to another window). 8395 int topAttached = -1; 8396 for (i = N-1; i >= 0; i--) { 8397 final WindowState win = windows.get(i); 8398 8399 // Don't do layout of a window if it is not visible, or 8400 // soon won't be visible, to avoid wasting time and funky 8401 // changes while a window is animating away. 8402 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8403 || win.isGoneForLayoutLw(); 8404 8405 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8406 Slog.v(TAG, "1ST PASS " + win 8407 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8408 + " mLayoutAttached=" + win.mLayoutAttached 8409 + " screen changed=" + win.isConfigChanged()); 8410 final AppWindowToken atoken = win.mAppToken; 8411 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8412 + win.mViewVisibility + " mRelayoutCalled=" 8413 + win.mRelayoutCalled + " hidden=" 8414 + win.mRootToken.hidden + " hiddenRequested=" 8415 + (atoken != null && atoken.hiddenRequested) 8416 + " mAttachedHidden=" + win.mAttachedHidden); 8417 else Slog.v(TAG, " VIS: mViewVisibility=" 8418 + win.mViewVisibility + " mRelayoutCalled=" 8419 + win.mRelayoutCalled + " hidden=" 8420 + win.mRootToken.hidden + " hiddenRequested=" 8421 + (atoken != null && atoken.hiddenRequested) 8422 + " mAttachedHidden=" + win.mAttachedHidden); 8423 } 8424 8425 // If this view is GONE, then skip it -- keep the current 8426 // frame, and let the caller know so they can ignore it 8427 // if they want. (We do the normal layout for INVISIBLE 8428 // windows, since that means "perform layout as normal, 8429 // just don't display"). 8430 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8431 || ((win.isConfigChanged() || win.setInsetsChanged()) && 8432 (win.mAttrs.type == TYPE_KEYGUARD || 8433 win.mAppToken != null && win.mAppToken.layoutConfigChanges)) 8434 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8435 if (!win.mLayoutAttached) { 8436 if (initial) { 8437 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8438 win.mContentChanged = false; 8439 } 8440 if (win.mAttrs.type == TYPE_DREAM) { 8441 // Don't layout windows behind a dream, so that if it 8442 // does stuff like hide the status bar we won't get a 8443 // bad transition when it goes away. 8444 behindDream = true; 8445 } 8446 win.mLayoutNeeded = false; 8447 win.prelayout(); 8448 mPolicy.layoutWindowLw(win, win.mAttrs, null); 8449 win.mLayoutSeq = seq; 8450 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8451 + win.mFrame + " mContainingFrame=" 8452 + win.mContainingFrame + " mDisplayFrame=" 8453 + win.mDisplayFrame); 8454 } else { 8455 if (topAttached < 0) topAttached = i; 8456 } 8457 } 8458 if (win.mViewVisibility == View.VISIBLE 8459 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8460 && universeBackground == null) { 8461 universeBackground = win.mWinAnimator; 8462 } 8463 } 8464 8465 if (mAnimator.mUniverseBackground != universeBackground) { 8466 mFocusMayChange = true; 8467 mAnimator.mUniverseBackground = universeBackground; 8468 } 8469 8470 boolean attachedBehindDream = false; 8471 8472 // Now perform layout of attached windows, which usually 8473 // depend on the position of the window they are attached to. 8474 // XXX does not deal with windows that are attached to windows 8475 // that are themselves attached. 8476 for (i = topAttached; i >= 0; i--) { 8477 final WindowState win = windows.get(i); 8478 8479 if (win.mLayoutAttached) { 8480 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8481 + " mHaveFrame=" + win.mHaveFrame 8482 + " mViewVisibility=" + win.mViewVisibility 8483 + " mRelayoutCalled=" + win.mRelayoutCalled); 8484 // If this view is GONE, then skip it -- keep the current 8485 // frame, and let the caller know so they can ignore it 8486 // if they want. (We do the normal layout for INVISIBLE 8487 // windows, since that means "perform layout as normal, 8488 // just don't display"). 8489 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8490 continue; 8491 } 8492 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8493 || !win.mHaveFrame || win.mLayoutNeeded) { 8494 if (initial) { 8495 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8496 win.mContentChanged = false; 8497 } 8498 win.mLayoutNeeded = false; 8499 win.prelayout(); 8500 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 8501 win.mLayoutSeq = seq; 8502 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8503 + win.mFrame + " mContainingFrame=" 8504 + win.mContainingFrame + " mDisplayFrame=" 8505 + win.mDisplayFrame); 8506 } 8507 } else if (win.mAttrs.type == TYPE_DREAM) { 8508 // Don't layout windows behind a dream, so that if it 8509 // does stuff like hide the status bar we won't get a 8510 // bad transition when it goes away. 8511 attachedBehindDream = behindDream; 8512 } 8513 } 8514 8515 // Window frames may have changed. Tell the input dispatcher about it. 8516 mInputMonitor.setUpdateInputWindowsNeededLw(); 8517 if (updateInputWindows) { 8518 mInputMonitor.updateInputWindowsLw(false /*force*/); 8519 } 8520 8521 mPolicy.finishLayoutLw(); 8522 } 8523 8524 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8525 // If the screen is currently frozen or off, then keep 8526 // it frozen/off until this window draws at its new 8527 // orientation. 8528 if (!okToDisplay()) { 8529 if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); 8530 w.mOrientationChanging = true; 8531 w.mLastFreezeDuration = 0; 8532 mInnerFields.mOrientationChangeComplete = false; 8533 if (!mWindowsFreezingScreen) { 8534 mWindowsFreezingScreen = true; 8535 // XXX should probably keep timeout from 8536 // when we first froze the display. 8537 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8538 mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, 8539 WINDOW_FREEZE_TIMEOUT_DURATION); 8540 } 8541 } 8542 } 8543 8544 /** 8545 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8546 * @param windows List of windows on default display. 8547 * @return bitmap indicating if another pass through layout must be made. 8548 */ 8549 public int handleAppTransitionReadyLocked(WindowList windows) { 8550 int changes = 0; 8551 int i; 8552 int NN = mOpeningApps.size(); 8553 boolean goodToGo = true; 8554 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8555 "Checking " + NN + " opening apps (frozen=" 8556 + mDisplayFrozen + " timeout=" 8557 + mAppTransition.isTimeout() + ")..."); 8558 if (!mDisplayFrozen && !mAppTransition.isTimeout()) { 8559 // If the display isn't frozen, wait to do anything until 8560 // all of the apps are ready. Otherwise just go because 8561 // we'll unfreeze the display when everyone is ready. 8562 for (i=0; i<NN && goodToGo; i++) { 8563 AppWindowToken wtoken = mOpeningApps.get(i); 8564 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8565 "Check opening app=" + wtoken + ": allDrawn=" 8566 + wtoken.allDrawn + " startingDisplayed=" 8567 + wtoken.startingDisplayed + " startingMoved=" 8568 + wtoken.startingMoved); 8569 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8570 && !wtoken.startingMoved) { 8571 goodToGo = false; 8572 } 8573 } 8574 } 8575 if (goodToGo) { 8576 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8577 int transit = mAppTransition.getAppTransition(); 8578 if (mSkipAppTransitionAnimation) { 8579 transit = AppTransition.TRANSIT_UNSET; 8580 } 8581 mAppTransition.goodToGo(); 8582 mStartingIconInTransition = false; 8583 mSkipAppTransitionAnimation = false; 8584 8585 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8586 8587 rebuildAppWindowListLocked(); 8588 8589 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8590 WindowState oldWallpaper = 8591 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8592 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8593 ? null : mWallpaperTarget; 8594 8595 mInnerFields.mWallpaperMayChange = false; 8596 8597 // The top-most window will supply the layout params, 8598 // and we will determine it below. 8599 LayoutParams animLp = null; 8600 int bestAnimLayer = -1; 8601 boolean fullscreenAnim = false; 8602 8603 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8604 "New wallpaper target=" + mWallpaperTarget 8605 + ", oldWallpaper=" + oldWallpaper 8606 + ", lower target=" + mLowerWallpaperTarget 8607 + ", upper target=" + mUpperWallpaperTarget); 8608 8609 boolean openingAppHasWallpaper = false; 8610 boolean closingAppHasWallpaper = false; 8611 final AppWindowToken lowerWallpaperAppToken; 8612 final AppWindowToken upperWallpaperAppToken; 8613 if (mLowerWallpaperTarget == null) { 8614 lowerWallpaperAppToken = upperWallpaperAppToken = null; 8615 } else { 8616 lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken; 8617 upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken; 8618 } 8619 8620 // Do a first pass through the tokens for two 8621 // things: 8622 // (1) Determine if both the closing and opening 8623 // app token sets are wallpaper targets, in which 8624 // case special animations are needed 8625 // (since the wallpaper needs to stay static 8626 // behind them). 8627 // (2) Find the layout params of the top-most 8628 // application window in the tokens, which is 8629 // what will control the animation theme. 8630 final int NC = mClosingApps.size(); 8631 NN = NC + mOpeningApps.size(); 8632 for (i=0; i<NN; i++) { 8633 final AppWindowToken wtoken; 8634 if (i < NC) { 8635 wtoken = mClosingApps.get(i); 8636 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8637 closingAppHasWallpaper = true; 8638 } 8639 } else { 8640 wtoken = mOpeningApps.get(i - NC); 8641 if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { 8642 openingAppHasWallpaper = true; 8643 } 8644 } 8645 8646 if (wtoken.appFullscreen) { 8647 WindowState ws = wtoken.findMainWindow(); 8648 if (ws != null) { 8649 animLp = ws.mAttrs; 8650 bestAnimLayer = ws.mLayer; 8651 fullscreenAnim = true; 8652 } 8653 } else if (!fullscreenAnim) { 8654 WindowState ws = wtoken.findMainWindow(); 8655 if (ws != null) { 8656 if (ws.mLayer > bestAnimLayer) { 8657 animLp = ws.mAttrs; 8658 bestAnimLayer = ws.mLayer; 8659 } 8660 } 8661 } 8662 } 8663 8664 mAnimateWallpaperWithTarget = false; 8665 if (closingAppHasWallpaper && openingAppHasWallpaper) { 8666 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!"); 8667 switch (transit) { 8668 case AppTransition.TRANSIT_ACTIVITY_OPEN: 8669 case AppTransition.TRANSIT_TASK_OPEN: 8670 case AppTransition.TRANSIT_TASK_TO_FRONT: 8671 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN; 8672 break; 8673 case AppTransition.TRANSIT_ACTIVITY_CLOSE: 8674 case AppTransition.TRANSIT_TASK_CLOSE: 8675 case AppTransition.TRANSIT_TASK_TO_BACK: 8676 transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE; 8677 break; 8678 } 8679 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit); 8680 } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty() 8681 && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8682 // We are transitioning from an activity with 8683 // a wallpaper to one without. 8684 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE; 8685 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8686 "New transit away from wallpaper: " + transit); 8687 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8688 // We are transitioning from an activity without 8689 // a wallpaper to now showing the wallpaper 8690 transit = AppTransition.TRANSIT_WALLPAPER_OPEN; 8691 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8692 "New transit into wallpaper: " + transit); 8693 } else { 8694 mAnimateWallpaperWithTarget = true; 8695 } 8696 8697 // If all closing windows are obscured, then there is 8698 // no need to do an animation. This is the case, for 8699 // example, when this transition is being done behind 8700 // the lock screen. 8701 if (!mPolicy.allowAppAnimationsLw()) { 8702 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8703 "Animations disallowed by keyguard or dream."); 8704 animLp = null; 8705 } 8706 8707 AppWindowToken topOpeningApp = null; 8708 int topOpeningLayer = 0; 8709 8710 NN = mOpeningApps.size(); 8711 for (i=0; i<NN; i++) { 8712 AppWindowToken wtoken = mOpeningApps.get(i); 8713 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8714 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8715 appAnimator.clearThumbnail(); 8716 wtoken.inPendingTransaction = false; 8717 appAnimator.animation = null; 8718 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 8719 wtoken.updateReportedVisibilityLocked(); 8720 wtoken.waitingToShow = false; 8721 8722 appAnimator.mAllAppWinAnimators.clear(); 8723 final int N = wtoken.allAppWindows.size(); 8724 for (int j = 0; j < N; j++) { 8725 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8726 } 8727 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8728 8729 if (animLp != null) { 8730 int layer = -1; 8731 for (int j=0; j<wtoken.windows.size(); j++) { 8732 WindowState win = wtoken.windows.get(j); 8733 if (win.mWinAnimator.mAnimLayer > layer) { 8734 layer = win.mWinAnimator.mAnimLayer; 8735 } 8736 } 8737 if (topOpeningApp == null || layer > topOpeningLayer) { 8738 topOpeningApp = wtoken; 8739 topOpeningLayer = layer; 8740 } 8741 } 8742 } 8743 NN = mClosingApps.size(); 8744 for (i=0; i<NN; i++) { 8745 AppWindowToken wtoken = mClosingApps.get(i); 8746 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); 8747 wtoken.mAppAnimator.clearThumbnail(); 8748 wtoken.inPendingTransaction = false; 8749 wtoken.mAppAnimator.animation = null; 8750 setTokenVisibilityLocked(wtoken, animLp, false, transit, false); 8751 wtoken.updateReportedVisibilityLocked(); 8752 wtoken.waitingToHide = false; 8753 // Force the allDrawn flag, because we want to start 8754 // this guy's animations regardless of whether it's 8755 // gotten drawn. 8756 wtoken.allDrawn = true; 8757 wtoken.deferClearAllDrawn = false; 8758 } 8759 8760 AppWindowAnimator appAnimator = 8761 topOpeningApp == null ? null : topOpeningApp.mAppAnimator; 8762 Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail(); 8763 if (nextAppTransitionThumbnail != null && appAnimator != null 8764 && appAnimator.animation != null) { 8765 // This thumbnail animation is very special, we need to have 8766 // an extra surface with the thumbnail included with the animation. 8767 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(), 8768 nextAppTransitionThumbnail.getHeight()); 8769 try { 8770 // TODO(multi-display): support other displays 8771 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8772 final Display display = displayContent.getDisplay(); 8773 SurfaceControl surfaceControl = new SurfaceControl(mFxSession, 8774 "thumbnail anim", 8775 dirty.width(), dirty.height(), 8776 PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); 8777 surfaceControl.setLayerStack(display.getLayerStack()); 8778 appAnimator.thumbnail = surfaceControl; 8779 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); 8780 Surface drawSurface = new Surface(); 8781 drawSurface.copyFrom(surfaceControl); 8782 Canvas c = drawSurface.lockCanvas(dirty); 8783 c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null); 8784 drawSurface.unlockCanvasAndPost(c); 8785 drawSurface.release(); 8786 appAnimator.thumbnailLayer = topOpeningLayer; 8787 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 8788 Animation anim = mAppTransition.createThumbnailAnimationLocked( 8789 transit, true, true, displayInfo.appWidth, displayInfo.appHeight); 8790 appAnimator.thumbnailAnimation = anim; 8791 anim.restrictDuration(MAX_ANIMATION_DURATION); 8792 anim.scaleCurrentDuration(mTransitionAnimationScale); 8793 Point p = new Point(); 8794 mAppTransition.getStartingPoint(p); 8795 appAnimator.thumbnailX = p.x; 8796 appAnimator.thumbnailY = p.y; 8797 } catch (OutOfResourcesException e) { 8798 Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width() 8799 + " h=" + dirty.height(), e); 8800 appAnimator.clearThumbnail(); 8801 } 8802 } 8803 8804 mAppTransition.postAnimationCallback(); 8805 mAppTransition.clear(); 8806 8807 mOpeningApps.clear(); 8808 mClosingApps.clear(); 8809 8810 // This has changed the visibility of windows, so perform 8811 // a new layout to get them all up-to-date. 8812 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8813 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8814 getDefaultDisplayContentLocked().layoutNeeded = true; 8815 8816 // TODO(multidisplay): IMEs are only supported on the default display. 8817 if (windows == getDefaultWindowListLocked() 8818 && !moveInputMethodWindowsIfNeededLocked(true)) { 8819 assignLayersLocked(windows); 8820 } 8821 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8822 mFocusMayChange = false; 8823 } 8824 8825 return changes; 8826 } 8827 8828 /** 8829 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8830 * @return bitmap indicating if another pass through layout must be made. 8831 */ 8832 private int handleAnimatingStoppedAndTransitionLocked() { 8833 int changes = 0; 8834 8835 mAppTransition.setIdle(); 8836 // Restore window app tokens to the ActivityManager views 8837 ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); 8838 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 8839 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 8840 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 8841 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 8842 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 8843 tokens.get(tokenNdx).sendingToBottom = false; 8844 } 8845 } 8846 } 8847 rebuildAppWindowListLocked(); 8848 8849 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8850 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 8851 "Wallpaper layer changed: assigning layers + relayout"); 8852 moveInputMethodWindowsIfNeededLocked(true); 8853 mInnerFields.mWallpaperMayChange = true; 8854 // Since the window list has been rebuilt, focus might 8855 // have to be recomputed since the actual order of windows 8856 // might have changed again. 8857 mFocusMayChange = true; 8858 8859 return changes; 8860 } 8861 8862 private void updateResizingWindows(final WindowState w) { 8863 final WindowStateAnimator winAnimator = w.mWinAnimator; 8864 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8865 w.setInsetsChanged(); 8866 boolean configChanged = w.isConfigChanged(); 8867 if (DEBUG_CONFIGURATION && configChanged) { 8868 Slog.v(TAG, "Win " + w + " config changed: " 8869 + mCurConfiguration); 8870 } 8871 if (localLOGV) Slog.v(TAG, "Resizing " + w 8872 + ": configChanged=" + configChanged 8873 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8874 w.mLastFrame.set(w.mFrame); 8875 if (w.mContentInsetsChanged 8876 || w.mVisibleInsetsChanged 8877 || winAnimator.mSurfaceResized 8878 || configChanged) { 8879 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8880 Slog.v(TAG, "Resize reasons for w=" + w + ": " 8881 + " contentInsetsChanged=" + w.mContentInsetsChanged 8882 + " " + w.mContentInsets.toShortString() 8883 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8884 + " " + w.mVisibleInsets.toShortString() 8885 + " surfaceResized=" + winAnimator.mSurfaceResized 8886 + " configChanged=" + configChanged); 8887 } 8888 8889 w.mLastOverscanInsets.set(w.mOverscanInsets); 8890 w.mLastContentInsets.set(w.mContentInsets); 8891 w.mLastVisibleInsets.set(w.mVisibleInsets); 8892 makeWindowFreezingScreenIfNeededLocked(w); 8893 // If the orientation is changing, then we need to 8894 // hold off on unfreezing the display until this 8895 // window has been redrawn; to do that, we need 8896 // to go through the process of getting informed 8897 // by the application when it has finished drawing. 8898 if (w.mOrientationChanging) { 8899 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8900 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8901 + w + ", surface " + winAnimator.mSurfaceControl); 8902 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8903 if (w.mAppToken != null) { 8904 w.mAppToken.allDrawn = false; 8905 w.mAppToken.deferClearAllDrawn = false; 8906 } 8907 } 8908 if (!mResizingWindows.contains(w)) { 8909 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8910 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8911 + "x" + winAnimator.mSurfaceH); 8912 mResizingWindows.add(w); 8913 } 8914 } else if (w.mOrientationChanging) { 8915 if (w.isDrawnLw()) { 8916 if (DEBUG_ORIENTATION) Slog.v(TAG, 8917 "Orientation not waiting for draw in " 8918 + w + ", surface " + winAnimator.mSurfaceControl); 8919 w.mOrientationChanging = false; 8920 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 8921 - mDisplayFreezeTime); 8922 } 8923 } 8924 } 8925 } 8926 8927 /** 8928 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8929 * 8930 * @param w WindowState this method is applied to. 8931 * @param currentTime The time which animations use for calculating transitions. 8932 * @param innerDw Width of app window. 8933 * @param innerDh Height of app window. 8934 */ 8935 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8936 final int innerDw, final int innerDh) { 8937 final WindowManager.LayoutParams attrs = w.mAttrs; 8938 final int attrFlags = attrs.flags; 8939 final boolean canBeSeen = w.isDisplayedLw(); 8940 final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8941 8942 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8943 // This window completely covers everything behind it, 8944 // so we want to leave all of them as undimmed (for 8945 // performance reasons). 8946 mInnerFields.mObscured = true; 8947 } 8948 8949 if (w.mHasSurface) { 8950 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8951 mInnerFields.mHoldScreen = w.mSession; 8952 } 8953 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8954 && mInnerFields.mScreenBrightness < 0) { 8955 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8956 } 8957 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8958 && mInnerFields.mButtonBrightness < 0) { 8959 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8960 } 8961 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8962 && mInnerFields.mUserActivityTimeout < 0) { 8963 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8964 } 8965 8966 final int type = attrs.type; 8967 if (canBeSeen 8968 && (type == TYPE_SYSTEM_DIALOG 8969 || type == TYPE_RECENTS_OVERLAY 8970 || type == TYPE_KEYGUARD 8971 || type == TYPE_SYSTEM_ERROR)) { 8972 mInnerFields.mSyswin = true; 8973 } 8974 8975 if (canBeSeen) { 8976 // This function assumes that the contents of the default display are 8977 // processed first before secondary displays. 8978 final DisplayContent displayContent = w.getDisplayContent(); 8979 if (displayContent != null && displayContent.isDefaultDisplay) { 8980 // While a dream or keyguard is showing, obscure ordinary application 8981 // content on secondary displays (by forcibly enabling mirroring unless 8982 // there is other content we want to show) but still allow opaque 8983 // keyguard dialogs to be shown. 8984 if (type == TYPE_DREAM || type == TYPE_KEYGUARD) { 8985 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; 8986 } 8987 mInnerFields.mDisplayHasContent = true; 8988 } else if (displayContent != null && 8989 (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays 8990 || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) { 8991 // Allow full screen keyguard presentation dialogs to be seen. 8992 mInnerFields.mDisplayHasContent = true; 8993 } 8994 } 8995 } 8996 } 8997 8998 private void handleFlagDimBehind(WindowState w) { 8999 final WindowManager.LayoutParams attrs = w.mAttrs; 9000 if ((attrs.flags & FLAG_DIM_BEHIND) != 0 9001 && w.isDisplayedLw() 9002 && !w.mExiting) { 9003 final WindowStateAnimator winAnimator = w.mWinAnimator; 9004 final TaskStack stack = w.getStack(); 9005 stack.setDimmingTag(); 9006 if (!stack.isDimming(winAnimator)) { 9007 if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); 9008 stack.startDimmingIfNeeded(winAnimator); 9009 } 9010 } 9011 } 9012 9013 private void updateAllDrawnLocked(DisplayContent displayContent) { 9014 // See if any windows have been drawn, so they (and others 9015 // associated with them) can now be shown. 9016 ArrayList<TaskStack> stacks = displayContent.getStacks(); 9017 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 9018 final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks(); 9019 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9020 final AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9021 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9022 final AppWindowToken wtoken = tokens.get(tokenNdx); 9023 if (!wtoken.allDrawn) { 9024 int numInteresting = wtoken.numInterestingWindows; 9025 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 9026 if (DEBUG_VISIBILITY) Slog.v(TAG, 9027 "allDrawn: " + wtoken 9028 + " interesting=" + numInteresting 9029 + " drawn=" + wtoken.numDrawnWindows); 9030 wtoken.allDrawn = true; 9031 mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget(); 9032 } 9033 } 9034 } 9035 } 9036 } 9037 } 9038 9039 // "Something has changed! Let's make it correct now." 9040 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 9041 if (DEBUG_WINDOW_TRACE) { 9042 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 9043 + Debug.getCallers(3)); 9044 } 9045 9046 final long currentTime = SystemClock.uptimeMillis(); 9047 9048 int i; 9049 9050 if (mFocusMayChange) { 9051 mFocusMayChange = false; 9052 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 9053 false /*updateInputWindows*/); 9054 } 9055 9056 // Initialize state of exiting tokens. 9057 final int numDisplays = mDisplayContents.size(); 9058 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9059 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9060 for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) { 9061 displayContent.mExitingTokens.get(i).hasVisible = false; 9062 } 9063 } 9064 9065 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9066 // Initialize state of exiting applications. 9067 final AppTokenList exitingAppTokens = 9068 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9069 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 9070 exitingAppTokens.get(tokenNdx).hasVisible = false; 9071 } 9072 } 9073 9074 mInnerFields.mHoldScreen = null; 9075 mInnerFields.mScreenBrightness = -1; 9076 mInnerFields.mButtonBrightness = -1; 9077 mInnerFields.mUserActivityTimeout = -1; 9078 mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; 9079 9080 mTransactionSequence++; 9081 9082 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 9083 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 9084 final int defaultDw = defaultInfo.logicalWidth; 9085 final int defaultDh = defaultInfo.logicalHeight; 9086 9087 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9088 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 9089 SurfaceControl.openTransaction(); 9090 try { 9091 9092 if (mWatermark != null) { 9093 mWatermark.positionSurface(defaultDw, defaultDh); 9094 } 9095 if (mStrictModeFlash != null) { 9096 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 9097 } 9098 if (mCircularDisplayMask != null) { 9099 mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation); 9100 } 9101 9102 boolean focusDisplayed = false; 9103 9104 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9105 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9106 boolean updateAllDrawn = false; 9107 WindowList windows = displayContent.getWindowList(); 9108 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9109 final int displayId = displayContent.getDisplayId(); 9110 final int dw = displayInfo.logicalWidth; 9111 final int dh = displayInfo.logicalHeight; 9112 final int innerDw = displayInfo.appWidth; 9113 final int innerDh = displayInfo.appHeight; 9114 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9115 9116 // Reset for each display. 9117 mInnerFields.mDisplayHasContent = false; 9118 9119 int repeats = 0; 9120 do { 9121 repeats++; 9122 if (repeats > 6) { 9123 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9124 displayContent.layoutNeeded = false; 9125 break; 9126 } 9127 9128 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9129 displayContent.pendingLayoutChanges); 9130 9131 if ((displayContent.pendingLayoutChanges & 9132 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && 9133 (adjustWallpaperWindowsLocked() & 9134 ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9135 assignLayersLocked(windows); 9136 displayContent.layoutNeeded = true; 9137 } 9138 9139 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9140 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9141 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9142 if (updateOrientationFromAppTokensLocked(true)) { 9143 displayContent.layoutNeeded = true; 9144 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9145 } 9146 } 9147 9148 if ((displayContent.pendingLayoutChanges 9149 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9150 displayContent.layoutNeeded = true; 9151 } 9152 9153 // FIRST LOOP: Perform a layout, if needed. 9154 if (repeats < 4) { 9155 performLayoutLockedInner(displayContent, repeats == 1, 9156 false /*updateInputWindows*/); 9157 } else { 9158 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9159 } 9160 9161 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9162 // it is animating. 9163 displayContent.pendingLayoutChanges = 0; 9164 9165 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9166 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9167 9168 if (isDefaultDisplay) { 9169 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9170 for (i = windows.size() - 1; i >= 0; i--) { 9171 WindowState w = windows.get(i); 9172 if (w.mHasSurface) { 9173 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9174 } 9175 } 9176 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9177 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9178 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9179 } 9180 } while (displayContent.pendingLayoutChanges != 0); 9181 9182 mInnerFields.mObscured = false; 9183 mInnerFields.mSyswin = false; 9184 displayContent.resetDimming(); 9185 9186 // Only used if default window 9187 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9188 9189 final int N = windows.size(); 9190 for (i=N-1; i>=0; i--) { 9191 WindowState w = windows.get(i); 9192 final TaskStack stack = w.getStack(); 9193 if (stack == null) { 9194 continue; 9195 } 9196 9197 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9198 9199 // Update effect. 9200 w.mObscured = mInnerFields.mObscured; 9201 if (!mInnerFields.mObscured) { 9202 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9203 } 9204 9205 if (!stack.testDimmingTag()) { 9206 handleFlagDimBehind(w); 9207 } 9208 9209 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9210 && w.isVisibleLw()) { 9211 // This is the wallpaper target and its obscured state 9212 // changed... make sure the current wallaper's visibility 9213 // has been updated accordingly. 9214 updateWallpaperVisibilityLocked(); 9215 } 9216 9217 final WindowStateAnimator winAnimator = w.mWinAnimator; 9218 9219 // If the window has moved due to its containing 9220 // content frame changing, then we'd like to animate 9221 // it. 9222 if (w.mHasSurface && w.shouldAnimateMove()) { 9223 // Frame has moved, containing content frame 9224 // has also moved, and we're not currently animating... 9225 // let's do something. 9226 Animation a = AnimationUtils.loadAnimation(mContext, 9227 com.android.internal.R.anim.window_move_from_decor); 9228 winAnimator.setAnimation(a); 9229 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9230 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9231 try { 9232 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9233 } catch (RemoteException e) { 9234 } 9235 } 9236 9237 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9238 w.mContentChanged = false; 9239 9240 // Moved from updateWindowsAndWallpaperLocked(). 9241 if (w.mHasSurface) { 9242 // Take care of the window being ready to display. 9243 final boolean committed = 9244 winAnimator.commitFinishDrawingLocked(currentTime); 9245 if (isDefaultDisplay && committed) { 9246 if (w.mAttrs.type == TYPE_DREAM) { 9247 // HACK: When a dream is shown, it may at that 9248 // point hide the lock screen. So we need to 9249 // redo the layout to let the phone window manager 9250 // make this happen. 9251 displayContent.pendingLayoutChanges |= 9252 WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9253 if (DEBUG_LAYOUT_REPEATS) { 9254 debugLayoutRepeats( 9255 "dream and commitFinishDrawingLocked true", 9256 displayContent.pendingLayoutChanges); 9257 } 9258 } 9259 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9260 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 9261 "First draw done in potential wallpaper target " + w); 9262 mInnerFields.mWallpaperMayChange = true; 9263 displayContent.pendingLayoutChanges |= 9264 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9265 if (DEBUG_LAYOUT_REPEATS) { 9266 debugLayoutRepeats( 9267 "wallpaper and commitFinishDrawingLocked true", 9268 displayContent.pendingLayoutChanges); 9269 } 9270 } 9271 } 9272 9273 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9274 9275 final AppWindowToken atoken = w.mAppToken; 9276 if (DEBUG_STARTING_WINDOW && atoken != null 9277 && w == atoken.startingWindow) { 9278 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9279 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9280 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9281 } 9282 if (atoken != null 9283 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9284 if (atoken.lastTransactionSequence != mTransactionSequence) { 9285 atoken.lastTransactionSequence = mTransactionSequence; 9286 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9287 atoken.startingDisplayed = false; 9288 } 9289 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9290 && !w.mExiting && !w.mDestroying) { 9291 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 9292 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9293 + ", isAnimating=" + winAnimator.isAnimating()); 9294 if (!w.isDrawnLw()) { 9295 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl 9296 + " pv=" + w.mPolicyVisibility 9297 + " mDrawState=" + winAnimator.mDrawState 9298 + " ah=" + w.mAttachedHidden 9299 + " th=" + atoken.hiddenRequested 9300 + " a=" + winAnimator.mAnimating); 9301 } 9302 } 9303 if (w != atoken.startingWindow) { 9304 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9305 atoken.numInterestingWindows++; 9306 if (w.isDrawnLw()) { 9307 atoken.numDrawnWindows++; 9308 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 9309 "tokenMayBeDrawn: " + atoken 9310 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9311 + " mAppFreezing=" + w.mAppFreezing); 9312 updateAllDrawn = true; 9313 } 9314 } 9315 } else if (w.isDrawnLw()) { 9316 atoken.startingDisplayed = true; 9317 } 9318 } 9319 } 9320 } 9321 9322 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9323 && w.isDisplayedLw()) { 9324 focusDisplayed = true; 9325 } 9326 9327 updateResizingWindows(w); 9328 } 9329 9330 mDisplayManagerInternal.setDisplayHasContent(displayId, 9331 mInnerFields.mDisplayHasContent, 9332 true /* inTraversal, must call performTraversalInTrans... below */); 9333 9334 getDisplayContentLocked(displayId).stopDimmingIfNeeded(); 9335 9336 if (updateAllDrawn) { 9337 updateAllDrawnLocked(displayContent); 9338 } 9339 } 9340 9341 if (focusDisplayed) { 9342 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9343 } 9344 9345 // Give the display manager a chance to adjust properties 9346 // like display rotation if it needs to. 9347 mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 9348 9349 } catch (RuntimeException e) { 9350 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9351 } finally { 9352 SurfaceControl.closeTransaction(); 9353 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 9354 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 9355 } 9356 9357 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9358 9359 // If we are ready to perform an app transition, check through 9360 // all of the app tokens to be shown and see if they are ready 9361 // to go. 9362 if (mAppTransition.isReady()) { 9363 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9364 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9365 defaultDisplay.pendingLayoutChanges); 9366 } 9367 9368 if (!mAnimator.mAnimating && mAppTransition.isRunning()) { 9369 // We have finished the animation of an app transition. To do 9370 // this, we have delayed a lot of operations like showing and 9371 // hiding apps, moving apps in Z-order, etc. The app token list 9372 // reflects the correct Z-order, but the window list may now 9373 // be out of sync with it. So here we will just rebuild the 9374 // entire app window list. Fun! 9375 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9376 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9377 defaultDisplay.pendingLayoutChanges); 9378 } 9379 9380 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9381 && !mAppTransition.isReady()) { 9382 // At this point, there was a window with a wallpaper that 9383 // was force hiding other windows behind it, but now it 9384 // is going away. This may be simple -- just animate 9385 // away the wallpaper and its window -- or it may be 9386 // hard -- the wallpaper now needs to be shown behind 9387 // something that was hidden. 9388 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9389 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9390 defaultDisplay.pendingLayoutChanges); 9391 } 9392 mInnerFields.mWallpaperForceHidingChanged = false; 9393 9394 if (mInnerFields.mWallpaperMayChange) { 9395 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 9396 defaultDisplay.pendingLayoutChanges |= 9397 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9398 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange", 9399 defaultDisplay.pendingLayoutChanges); 9400 } 9401 9402 if (mFocusMayChange) { 9403 mFocusMayChange = false; 9404 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9405 false /*updateInputWindows*/)) { 9406 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9407 } 9408 } 9409 9410 if (needsLayout()) { 9411 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9412 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9413 defaultDisplay.pendingLayoutChanges); 9414 } 9415 9416 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9417 WindowState win = mResizingWindows.get(i); 9418 if (win.mAppFreezing) { 9419 // Don't remove this window until rotation has completed. 9420 continue; 9421 } 9422 win.reportResized(); 9423 mResizingWindows.remove(i); 9424 } 9425 9426 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9427 "With display frozen, orientationChangeComplete=" 9428 + mInnerFields.mOrientationChangeComplete); 9429 if (mInnerFields.mOrientationChangeComplete) { 9430 if (mWindowsFreezingScreen) { 9431 mWindowsFreezingScreen = false; 9432 mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource; 9433 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9434 } 9435 stopFreezingDisplayLocked(); 9436 } 9437 9438 // Destroy the surface of any windows that are no longer visible. 9439 boolean wallpaperDestroyed = false; 9440 i = mDestroySurface.size(); 9441 if (i > 0) { 9442 do { 9443 i--; 9444 WindowState win = mDestroySurface.get(i); 9445 win.mDestroying = false; 9446 if (mInputMethodWindow == win) { 9447 mInputMethodWindow = null; 9448 } 9449 if (win == mWallpaperTarget) { 9450 wallpaperDestroyed = true; 9451 } 9452 win.mWinAnimator.destroySurfaceLocked(); 9453 } while (i > 0); 9454 mDestroySurface.clear(); 9455 } 9456 9457 // Time to remove any exiting tokens? 9458 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9459 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9460 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 9461 for (i = exitingTokens.size() - 1; i >= 0; i--) { 9462 WindowToken token = exitingTokens.get(i); 9463 if (!token.hasVisible) { 9464 exitingTokens.remove(i); 9465 if (token.windowType == TYPE_WALLPAPER) { 9466 mWallpaperTokens.remove(token); 9467 } 9468 } 9469 } 9470 } 9471 9472 // Time to remove any exiting applications? 9473 for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 9474 // Initialize state of exiting applications. 9475 final AppTokenList exitingAppTokens = 9476 mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 9477 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 9478 AppWindowToken token = exitingAppTokens.get(i); 9479 if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) { 9480 // Make sure there is no animation running on this token, 9481 // so any windows associated with it will be removed as 9482 // soon as their animations are complete 9483 token.mAppAnimator.clearAnimation(); 9484 token.mAppAnimator.animating = false; 9485 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9486 "performLayout: App token exiting now removed" + token); 9487 removeAppFromTaskLocked(token); 9488 exitingAppTokens.remove(i); 9489 } 9490 } 9491 } 9492 9493 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9494 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9495 try { 9496 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9497 } catch (RemoteException e) { 9498 } 9499 } 9500 mRelayoutWhileAnimating.clear(); 9501 } 9502 9503 if (wallpaperDestroyed) { 9504 defaultDisplay.pendingLayoutChanges |= 9505 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9506 defaultDisplay.layoutNeeded = true; 9507 } 9508 9509 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9510 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9511 if (displayContent.pendingLayoutChanges != 0) { 9512 displayContent.layoutNeeded = true; 9513 } 9514 } 9515 9516 // Finally update all input windows now that the window changes have stabilized. 9517 mInputMonitor.updateInputWindowsLw(true /*force*/); 9518 9519 setHoldScreenLocked(mInnerFields.mHoldScreen); 9520 if (!mDisplayFrozen) { 9521 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9522 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 9523 } else { 9524 mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 9525 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9526 } 9527 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9528 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 9529 } else { 9530 mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 9531 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9532 } 9533 mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 9534 mInnerFields.mUserActivityTimeout); 9535 } 9536 9537 if (mTurnOnScreen) { 9538 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9539 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9540 mTurnOnScreen = false; 9541 } 9542 9543 if (mInnerFields.mUpdateRotation) { 9544 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9545 if (updateRotationUncheckedLocked(false)) { 9546 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9547 } else { 9548 mInnerFields.mUpdateRotation = false; 9549 } 9550 } 9551 9552 if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded 9553 && !mInnerFields.mUpdateRotation) { 9554 checkDrawnWindowsLocked(); 9555 } 9556 9557 final int N = mPendingRemove.size(); 9558 if (N > 0) { 9559 if (mPendingRemoveTmp.length < N) { 9560 mPendingRemoveTmp = new WindowState[N+10]; 9561 } 9562 mPendingRemove.toArray(mPendingRemoveTmp); 9563 mPendingRemove.clear(); 9564 DisplayContentList displayList = new DisplayContentList(); 9565 for (i = 0; i < N; i++) { 9566 WindowState w = mPendingRemoveTmp[i]; 9567 removeWindowInnerLocked(w.mSession, w); 9568 final DisplayContent displayContent = w.getDisplayContent(); 9569 if (displayContent != null && !displayList.contains(displayContent)) { 9570 displayList.add(displayContent); 9571 } 9572 } 9573 9574 for (DisplayContent displayContent : displayList) { 9575 assignLayersLocked(displayContent.getWindowList()); 9576 displayContent.layoutNeeded = true; 9577 } 9578 } 9579 9580 // Remove all deferred displays stacks, tasks, and activities. 9581 for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { 9582 mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); 9583 } 9584 9585 setFocusedStackFrame(); 9586 9587 // Check to see if we are now in a state where the screen should 9588 // be enabled, because the window obscured flags have changed. 9589 enableScreenIfNeededLocked(); 9590 9591 scheduleAnimationLocked(); 9592 9593 if (DEBUG_WINDOW_TRACE) { 9594 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9595 + mAnimator.mAnimating); 9596 } 9597 } 9598 9599 private int toBrightnessOverride(float value) { 9600 return (int)(value * PowerManager.BRIGHTNESS_ON); 9601 } 9602 9603 void checkDrawnWindowsLocked() { 9604 if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { 9605 return; 9606 } 9607 for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { 9608 WindowState win = mWaitingForDrawn.get(j); 9609 if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win + 9610 ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() + 9611 " mHasSurface=" + win.mHasSurface + 9612 " drawState=" + win.mWinAnimator.mDrawState); 9613 if (win.mRemoved || !win.mHasSurface) { 9614 // Window has been removed; no draw will now happen, so stop waiting. 9615 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win); 9616 mWaitingForDrawn.remove(win); 9617 } else if (win.hasDrawnLw()) { 9618 // Window is now drawn (and shown). 9619 if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win); 9620 mWaitingForDrawn.remove(win); 9621 } 9622 } 9623 if (mWaitingForDrawn.isEmpty()) { 9624 if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!"); 9625 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 9626 mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); 9627 } 9628 } 9629 9630 void setHoldScreenLocked(final Session newHoldScreen) { 9631 final boolean hold = newHoldScreen != null; 9632 9633 if (hold && mHoldingScreenOn != newHoldScreen) { 9634 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9635 } 9636 mHoldingScreenOn = newHoldScreen; 9637 9638 final boolean state = mHoldingScreenWakeLock.isHeld(); 9639 if (hold != state) { 9640 if (hold) { 9641 mHoldingScreenWakeLock.acquire(); 9642 mPolicy.keepScreenOnStartedLw(); 9643 } else { 9644 mPolicy.keepScreenOnStoppedLw(); 9645 mHoldingScreenWakeLock.release(); 9646 } 9647 } 9648 } 9649 9650 void requestTraversal() { 9651 synchronized (mWindowMap) { 9652 requestTraversalLocked(); 9653 } 9654 } 9655 9656 void requestTraversalLocked() { 9657 if (!mTraversalScheduled) { 9658 mTraversalScheduled = true; 9659 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9660 } 9661 } 9662 9663 /** Note that Locked in this case is on mLayoutToAnim */ 9664 void scheduleAnimationLocked() { 9665 if (!mAnimationScheduled) { 9666 mAnimationScheduled = true; 9667 mChoreographer.postCallback( 9668 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9669 } 9670 } 9671 9672 private boolean needsLayout() { 9673 final int numDisplays = mDisplayContents.size(); 9674 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9675 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 9676 if (displayContent.layoutNeeded) { 9677 return true; 9678 } 9679 } 9680 return false; 9681 } 9682 9683 boolean copyAnimToLayoutParamsLocked() { 9684 boolean doRequest = false; 9685 9686 final int bulkUpdateParams = mAnimator.mBulkUpdateParams; 9687 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9688 mInnerFields.mUpdateRotation = true; 9689 doRequest = true; 9690 } 9691 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9692 mInnerFields.mWallpaperMayChange = true; 9693 doRequest = true; 9694 } 9695 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9696 mInnerFields.mWallpaperForceHidingChanged = true; 9697 doRequest = true; 9698 } 9699 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9700 mInnerFields.mOrientationChangeComplete = false; 9701 } else { 9702 mInnerFields.mOrientationChangeComplete = true; 9703 mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource; 9704 if (mWindowsFreezingScreen) { 9705 doRequest = true; 9706 } 9707 } 9708 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9709 mTurnOnScreen = true; 9710 } 9711 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) { 9712 mInnerFields.mWallpaperActionPending = true; 9713 } 9714 9715 return doRequest; 9716 } 9717 9718 /** If a window that has an animation specifying a colored background and the current wallpaper 9719 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 9720 * suddenly disappear. */ 9721 int adjustAnimationBackground(WindowStateAnimator winAnimator) { 9722 WindowList windows = winAnimator.mWin.getWindowList(); 9723 for (int i = windows.size() - 1; i >= 0; --i) { 9724 WindowState testWin = windows.get(i); 9725 if (testWin.mIsWallpaper && testWin.isVisibleNow()) { 9726 return testWin.mWinAnimator.mAnimLayer; 9727 } 9728 } 9729 return winAnimator.mAnimLayer; 9730 } 9731 9732 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9733 boolean secure) { 9734 final SurfaceControl surface = winAnimator.mSurfaceControl; 9735 boolean leakedSurface = false; 9736 boolean killedApps = false; 9737 9738 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9739 winAnimator.mSession.mPid, operation); 9740 9741 if (mForceRemoves == null) { 9742 mForceRemoves = new ArrayList<WindowState>(); 9743 } 9744 9745 long callingIdentity = Binder.clearCallingIdentity(); 9746 try { 9747 // There was some problem... first, do a sanity check of the 9748 // window list to make sure we haven't left any dangling surfaces 9749 // around. 9750 9751 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9752 final int numDisplays = mDisplayContents.size(); 9753 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9754 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9755 final int numWindows = windows.size(); 9756 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9757 final WindowState ws = windows.get(winNdx); 9758 WindowStateAnimator wsa = ws.mWinAnimator; 9759 if (wsa.mSurfaceControl != null) { 9760 if (!mSessions.contains(wsa.mSession)) { 9761 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9762 + ws + " surface=" + wsa.mSurfaceControl 9763 + " token=" + ws.mToken 9764 + " pid=" + ws.mSession.mPid 9765 + " uid=" + ws.mSession.mUid); 9766 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9767 wsa.mSurfaceControl.destroy(); 9768 wsa.mSurfaceShown = false; 9769 wsa.mSurfaceControl = null; 9770 ws.mHasSurface = false; 9771 mForceRemoves.add(ws); 9772 leakedSurface = true; 9773 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9774 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9775 + ws + " surface=" + wsa.mSurfaceControl 9776 + " token=" + ws.mAppToken); 9777 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9778 wsa.mSurfaceControl.destroy(); 9779 wsa.mSurfaceShown = false; 9780 wsa.mSurfaceControl = null; 9781 ws.mHasSurface = false; 9782 leakedSurface = true; 9783 } 9784 } 9785 } 9786 } 9787 9788 if (!leakedSurface) { 9789 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9790 SparseIntArray pidCandidates = new SparseIntArray(); 9791 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 9792 final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList(); 9793 final int numWindows = windows.size(); 9794 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 9795 final WindowState ws = windows.get(winNdx); 9796 if (mForceRemoves.contains(ws)) { 9797 continue; 9798 } 9799 WindowStateAnimator wsa = ws.mWinAnimator; 9800 if (wsa.mSurfaceControl != null) { 9801 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9802 } 9803 } 9804 if (pidCandidates.size() > 0) { 9805 int[] pids = new int[pidCandidates.size()]; 9806 for (int i=0; i<pids.length; i++) { 9807 pids[i] = pidCandidates.keyAt(i); 9808 } 9809 try { 9810 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9811 killedApps = true; 9812 } 9813 } catch (RemoteException e) { 9814 } 9815 } 9816 } 9817 } 9818 9819 if (leakedSurface || killedApps) { 9820 // We managed to reclaim some memory, so get rid of the trouble 9821 // surface and ask the app to request another one. 9822 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9823 if (surface != null) { 9824 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9825 "RECOVER DESTROY", null); 9826 surface.destroy(); 9827 winAnimator.mSurfaceShown = false; 9828 winAnimator.mSurfaceControl = null; 9829 winAnimator.mWin.mHasSurface = false; 9830 scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken); 9831 } 9832 9833 try { 9834 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9835 } catch (RemoteException e) { 9836 } 9837 } 9838 } finally { 9839 Binder.restoreCallingIdentity(callingIdentity); 9840 } 9841 9842 return leakedSurface || killedApps; 9843 } 9844 9845 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9846 WindowState newFocus = computeFocusedWindowLocked(); 9847 if (mCurrentFocus != newFocus) { 9848 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9849 // This check makes sure that we don't already have the focus 9850 // change message pending. 9851 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9852 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9853 // TODO(multidisplay): Focused windows on default display only. 9854 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9855 final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked( 9856 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS 9857 && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES); 9858 if (imWindowChanged) { 9859 displayContent.layoutNeeded = true; 9860 newFocus = computeFocusedWindowLocked(); 9861 } 9862 9863 if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " + 9864 mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4)); 9865 final WindowState oldFocus = mCurrentFocus; 9866 mCurrentFocus = newFocus; 9867 mLosingFocus.remove(newFocus); 9868 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9869 9870 if (imWindowChanged && oldFocus != mInputMethodWindow) { 9871 // Focus of the input method window changed. Perform layout if needed. 9872 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9873 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9874 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9875 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9876 // Client will do the layout, but we need to assign layers 9877 // for handleNewWindowLocked() below. 9878 assignLayersLocked(displayContent.getWindowList()); 9879 } 9880 } 9881 9882 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9883 // The change in focus caused us to need to do a layout. Okay. 9884 displayContent.layoutNeeded = true; 9885 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9886 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9887 } 9888 } 9889 9890 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9891 // If we defer assigning layers, then the caller is responsible for 9892 // doing this part. 9893 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9894 } 9895 9896 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9897 return true; 9898 } 9899 return false; 9900 } 9901 9902 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9903 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9904 } 9905 9906 private WindowState computeFocusedWindowLocked() { 9907 if (mAnimator.mUniverseBackground != null 9908 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9909 return mAnimator.mUniverseBackground.mWin; 9910 } 9911 9912 final int displayCount = mDisplayContents.size(); 9913 for (int i = 0; i < displayCount; i++) { 9914 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9915 WindowState win = findFocusedWindowLocked(displayContent); 9916 if (win != null) { 9917 return win; 9918 } 9919 } 9920 return null; 9921 } 9922 9923 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9924 final WindowList windows = displayContent.getWindowList(); 9925 for (int i = windows.size() - 1; i >= 0; i--) { 9926 final WindowState win = windows.get(i); 9927 9928 if (localLOGV || DEBUG_FOCUS) Slog.v( 9929 TAG, "Looking for focus: " + i 9930 + " = " + win 9931 + ", flags=" + win.mAttrs.flags 9932 + ", canReceive=" + win.canReceiveKeys()); 9933 9934 AppWindowToken wtoken = win.mAppToken; 9935 9936 // If this window's application has been removed, just skip it. 9937 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 9938 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because " 9939 + (wtoken.removed ? "removed" : "sendingToBottom")); 9940 continue; 9941 } 9942 9943 if (!win.canReceiveKeys()) { 9944 continue; 9945 } 9946 9947 // Descend through all of the app tokens and find the first that either matches 9948 // win.mAppToken (return win) or mFocusedApp (return null). 9949 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && 9950 mFocusedApp != null) { 9951 ArrayList<Task> tasks = displayContent.getTasks(); 9952 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 9953 AppTokenList tokens = tasks.get(taskNdx).mAppTokens; 9954 int tokenNdx = tokens.size() - 1; 9955 for ( ; tokenNdx >= 0; --tokenNdx) { 9956 final AppWindowToken token = tokens.get(tokenNdx); 9957 if (wtoken == token) { 9958 break; 9959 } 9960 if (mFocusedApp == token) { 9961 // Whoops, we are below the focused app... no focus for you! 9962 if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG, 9963 "findFocusedWindow: Reached focused app=" + mFocusedApp); 9964 return null; 9965 } 9966 } 9967 if (tokenNdx >= 0) { 9968 // Early exit from loop, must have found the matching token. 9969 break; 9970 } 9971 } 9972 } 9973 9974 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i + 9975 " = " + win); 9976 return win; 9977 } 9978 9979 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows."); 9980 return null; 9981 } 9982 9983 private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { 9984 if (mDisplayFrozen) { 9985 return; 9986 } 9987 9988 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 9989 // No need to freeze the screen before the system is ready or if 9990 // the screen is off. 9991 return; 9992 } 9993 9994 mScreenFrozenLock.acquire(); 9995 9996 mDisplayFrozen = true; 9997 mDisplayFreezeTime = SystemClock.elapsedRealtime(); 9998 mLastFinishedFreezeSource = null; 9999 10000 mInputMonitor.freezeInputDispatchingLw(); 10001 10002 // Clear the last input window -- that is just used for 10003 // clean transitions between IMEs, and if we are freezing 10004 // the screen then the whole world is changing behind the scenes. 10005 mPolicy.setLastInputMethodWindowLw(null, null); 10006 10007 if (mAppTransition.isTransitionSet()) { 10008 mAppTransition.freeze(); 10009 } 10010 10011 if (PROFILE_ORIENTATION) { 10012 File file = new File("/data/system/frozen"); 10013 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10014 } 10015 10016 if (CUSTOM_SCREEN_ROTATION) { 10017 mExitAnimId = exitAnim; 10018 mEnterAnimId = enterAnim; 10019 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10020 final int displayId = displayContent.getDisplayId(); 10021 ScreenRotationAnimation screenRotationAnimation = 10022 mAnimator.getScreenRotationAnimationLocked(displayId); 10023 if (screenRotationAnimation != null) { 10024 screenRotationAnimation.kill(); 10025 } 10026 10027 // Check whether the current screen contains any secure content. 10028 boolean isSecure = false; 10029 final WindowList windows = getDefaultWindowListLocked(); 10030 final int N = windows.size(); 10031 for (int i = 0; i < N; i++) { 10032 WindowState ws = windows.get(i); 10033 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 10034 isSecure = true; 10035 break; 10036 } 10037 } 10038 10039 // TODO(multidisplay): rotation on main screen only. 10040 displayContent.updateDisplayInfo(); 10041 screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, 10042 mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure); 10043 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10044 } 10045 } 10046 10047 private void stopFreezingDisplayLocked() { 10048 if (!mDisplayFrozen) { 10049 return; 10050 } 10051 10052 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10053 || mClientFreezingScreen) { 10054 if (DEBUG_ORIENTATION) Slog.d(TAG, 10055 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10056 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10057 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10058 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10059 return; 10060 } 10061 10062 mDisplayFrozen = false; 10063 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); 10064 StringBuilder sb = new StringBuilder(128); 10065 sb.append("Screen frozen for "); 10066 TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb); 10067 if (mLastFinishedFreezeSource != null) { 10068 sb.append(" due to "); 10069 sb.append(mLastFinishedFreezeSource); 10070 } 10071 Slog.i(TAG, sb.toString()); 10072 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10073 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10074 if (PROFILE_ORIENTATION) { 10075 Debug.stopMethodTracing(); 10076 } 10077 10078 boolean updateRotation = false; 10079 10080 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10081 final int displayId = displayContent.getDisplayId(); 10082 ScreenRotationAnimation screenRotationAnimation = 10083 mAnimator.getScreenRotationAnimationLocked(displayId); 10084 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10085 && screenRotationAnimation.hasScreenshot()) { 10086 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10087 // TODO(multidisplay): rotation on main screen only. 10088 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10089 // Get rotation animation again, with new top window 10090 boolean isDimming = displayContent.isDimming(); 10091 if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { 10092 mExitAnimId = mEnterAnimId = 0; 10093 } 10094 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10095 mTransitionAnimationScale, displayInfo.logicalWidth, 10096 displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { 10097 scheduleAnimationLocked(); 10098 } else { 10099 screenRotationAnimation.kill(); 10100 screenRotationAnimation = null; 10101 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10102 updateRotation = true; 10103 } 10104 } else { 10105 if (screenRotationAnimation != null) { 10106 screenRotationAnimation.kill(); 10107 screenRotationAnimation = null; 10108 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10109 } 10110 updateRotation = true; 10111 } 10112 10113 mInputMonitor.thawInputDispatchingLw(); 10114 10115 boolean configChanged; 10116 10117 // While the display is frozen we don't re-compute the orientation 10118 // to avoid inconsistent states. However, something interesting 10119 // could have actually changed during that time so re-evaluate it 10120 // now to catch that. 10121 configChanged = updateOrientationFromAppTokensLocked(false); 10122 10123 // A little kludge: a lot could have happened while the 10124 // display was frozen, so now that we are coming back we 10125 // do a gc so that any remote references the system 10126 // processes holds on others can be released if they are 10127 // no longer needed. 10128 mH.removeMessages(H.FORCE_GC); 10129 mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); 10130 10131 mScreenFrozenLock.release(); 10132 10133 if (updateRotation) { 10134 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10135 configChanged |= updateRotationUncheckedLocked(false); 10136 } 10137 10138 if (configChanged) { 10139 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10140 } 10141 } 10142 10143 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10144 DisplayMetrics dm) { 10145 if (index < tokens.length) { 10146 String str = tokens[index]; 10147 if (str != null && str.length() > 0) { 10148 try { 10149 int val = Integer.parseInt(str); 10150 return val; 10151 } catch (Exception e) { 10152 } 10153 } 10154 } 10155 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10156 return defDps; 10157 } 10158 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10159 return val; 10160 } 10161 10162 void createWatermarkInTransaction() { 10163 if (mWatermark != null) { 10164 return; 10165 } 10166 10167 File file = new File("/system/etc/setup.conf"); 10168 FileInputStream in = null; 10169 DataInputStream ind = null; 10170 try { 10171 in = new FileInputStream(file); 10172 ind = new DataInputStream(in); 10173 String line = ind.readLine(); 10174 if (line != null) { 10175 String[] toks = line.split("%"); 10176 if (toks != null && toks.length > 0) { 10177 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10178 mRealDisplayMetrics, mFxSession, toks); 10179 } 10180 } 10181 } catch (FileNotFoundException e) { 10182 } catch (IOException e) { 10183 } finally { 10184 if (ind != null) { 10185 try { 10186 ind.close(); 10187 } catch (IOException e) { 10188 } 10189 } else if (in != null) { 10190 try { 10191 in.close(); 10192 } catch (IOException e) { 10193 } 10194 } 10195 } 10196 } 10197 10198 @Override 10199 public void statusBarVisibilityChanged(int visibility) { 10200 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10201 != PackageManager.PERMISSION_GRANTED) { 10202 throw new SecurityException("Caller does not hold permission " 10203 + android.Manifest.permission.STATUS_BAR); 10204 } 10205 10206 synchronized (mWindowMap) { 10207 mLastStatusBarVisibility = visibility; 10208 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10209 updateStatusBarVisibilityLocked(visibility); 10210 } 10211 } 10212 10213 // TOOD(multidisplay): StatusBar on multiple screens? 10214 void updateStatusBarVisibilityLocked(int visibility) { 10215 mInputManager.setSystemUiVisibility(visibility); 10216 final WindowList windows = getDefaultWindowListLocked(); 10217 final int N = windows.size(); 10218 for (int i = 0; i < N; i++) { 10219 WindowState ws = windows.get(i); 10220 try { 10221 int curValue = ws.mSystemUiVisibility; 10222 int diff = curValue ^ visibility; 10223 // We are only interested in differences of one of the 10224 // clearable flags... 10225 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10226 // ...if it has actually been cleared. 10227 diff &= ~visibility; 10228 int newValue = (curValue&~diff) | (visibility&diff); 10229 if (newValue != curValue) { 10230 ws.mSeq++; 10231 ws.mSystemUiVisibility = newValue; 10232 } 10233 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10234 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10235 visibility, newValue, diff); 10236 } 10237 } catch (RemoteException e) { 10238 // so sorry 10239 } 10240 } 10241 } 10242 10243 @Override 10244 public void reevaluateStatusBarVisibility() { 10245 synchronized (mWindowMap) { 10246 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10247 updateStatusBarVisibilityLocked(visibility); 10248 performLayoutAndPlaceSurfacesLocked(); 10249 } 10250 } 10251 10252 @Override 10253 public FakeWindow addFakeWindow(Looper looper, 10254 InputEventReceiver.Factory inputEventReceiverFactory, 10255 String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, 10256 boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { 10257 synchronized (mWindowMap) { 10258 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10259 name, windowType, 10260 layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys, 10261 hasFocus, touchFullscreen); 10262 int i=0; 10263 while (i<mFakeWindows.size()) { 10264 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10265 break; 10266 } 10267 } 10268 mFakeWindows.add(i, fw); 10269 mInputMonitor.updateInputWindowsLw(true); 10270 return fw; 10271 } 10272 } 10273 10274 boolean removeFakeWindowLocked(FakeWindow window) { 10275 synchronized (mWindowMap) { 10276 if (mFakeWindows.remove(window)) { 10277 mInputMonitor.updateInputWindowsLw(true); 10278 return true; 10279 } 10280 return false; 10281 } 10282 } 10283 10284 // It is assumed that this method is called only by InputMethodManagerService. 10285 public void saveLastInputMethodWindowForTransition() { 10286 synchronized (mWindowMap) { 10287 // TODO(multidisplay): Pass in the displayID. 10288 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10289 if (mInputMethodWindow != null) { 10290 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10291 } 10292 } 10293 } 10294 10295 @Override 10296 public boolean hasNavigationBar() { 10297 return mPolicy.hasNavigationBar(); 10298 } 10299 10300 @Override 10301 public void lockNow(Bundle options) { 10302 mPolicy.lockNow(options); 10303 } 10304 10305 @Override 10306 public boolean isSafeModeEnabled() { 10307 return mSafeMode; 10308 } 10309 10310 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10311 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10312 mPolicy.dump(" ", pw, args); 10313 } 10314 10315 void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10316 pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)"); 10317 mAnimator.dumpLocked(pw, " ", dumpAll); 10318 } 10319 10320 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10321 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10322 if (mTokenMap.size() > 0) { 10323 pw.println(" All tokens:"); 10324 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10325 while (it.hasNext()) { 10326 WindowToken token = it.next(); 10327 pw.print(" "); pw.print(token); 10328 if (dumpAll) { 10329 pw.println(':'); 10330 token.dump(pw, " "); 10331 } else { 10332 pw.println(); 10333 } 10334 } 10335 } 10336 if (mWallpaperTokens.size() > 0) { 10337 pw.println(); 10338 pw.println(" Wallpaper tokens:"); 10339 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10340 WindowToken token = mWallpaperTokens.get(i); 10341 pw.print(" Wallpaper #"); pw.print(i); 10342 pw.print(' '); pw.print(token); 10343 if (dumpAll) { 10344 pw.println(':'); 10345 token.dump(pw, " "); 10346 } else { 10347 pw.println(); 10348 } 10349 } 10350 } 10351 if (mFinishedStarting.size() > 0) { 10352 pw.println(); 10353 pw.println(" Finishing start of application tokens:"); 10354 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10355 WindowToken token = mFinishedStarting.get(i); 10356 pw.print(" Finished Starting #"); pw.print(i); 10357 pw.print(' '); pw.print(token); 10358 if (dumpAll) { 10359 pw.println(':'); 10360 token.dump(pw, " "); 10361 } else { 10362 pw.println(); 10363 } 10364 } 10365 } 10366 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10367 pw.println(); 10368 if (mOpeningApps.size() > 0) { 10369 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10370 } 10371 if (mClosingApps.size() > 0) { 10372 pw.print(" mClosingApps="); pw.println(mClosingApps); 10373 } 10374 } 10375 } 10376 10377 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10378 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10379 if (mSessions.size() > 0) { 10380 Iterator<Session> it = mSessions.iterator(); 10381 while (it.hasNext()) { 10382 Session s = it.next(); 10383 pw.print(" Session "); pw.print(s); pw.println(':'); 10384 s.dump(pw, " "); 10385 } 10386 } 10387 } 10388 10389 void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) { 10390 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 10391 if (mDisplayReady) { 10392 final int numDisplays = mDisplayContents.size(); 10393 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10394 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10395 displayContent.dump(" ", pw); 10396 } 10397 } else { 10398 pw.println(" NO DISPLAY"); 10399 } 10400 } 10401 10402 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10403 ArrayList<WindowState> windows) { 10404 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10405 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10406 } 10407 10408 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10409 ArrayList<WindowState> windows) { 10410 final int numDisplays = mDisplayContents.size(); 10411 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10412 final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList(); 10413 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10414 final WindowState w = windowList.get(winNdx); 10415 if (windows == null || windows.contains(w)) { 10416 pw.print(" Window #"); pw.print(winNdx); pw.print(' '); 10417 pw.print(w); pw.println(":"); 10418 w.dump(pw, " ", dumpAll || windows != null); 10419 } 10420 } 10421 } 10422 if (mInputMethodDialogs.size() > 0) { 10423 pw.println(); 10424 pw.println(" Input method dialogs:"); 10425 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10426 WindowState w = mInputMethodDialogs.get(i); 10427 if (windows == null || windows.contains(w)) { 10428 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10429 } 10430 } 10431 } 10432 if (mPendingRemove.size() > 0) { 10433 pw.println(); 10434 pw.println(" Remove pending for:"); 10435 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10436 WindowState w = mPendingRemove.get(i); 10437 if (windows == null || windows.contains(w)) { 10438 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10439 pw.print(w); 10440 if (dumpAll) { 10441 pw.println(":"); 10442 w.dump(pw, " ", true); 10443 } else { 10444 pw.println(); 10445 } 10446 } 10447 } 10448 } 10449 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10450 pw.println(); 10451 pw.println(" Windows force removing:"); 10452 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10453 WindowState w = mForceRemoves.get(i); 10454 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10455 pw.print(w); 10456 if (dumpAll) { 10457 pw.println(":"); 10458 w.dump(pw, " ", true); 10459 } else { 10460 pw.println(); 10461 } 10462 } 10463 } 10464 if (mDestroySurface.size() > 0) { 10465 pw.println(); 10466 pw.println(" Windows waiting to destroy their surface:"); 10467 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10468 WindowState w = mDestroySurface.get(i); 10469 if (windows == null || windows.contains(w)) { 10470 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10471 pw.print(w); 10472 if (dumpAll) { 10473 pw.println(":"); 10474 w.dump(pw, " ", true); 10475 } else { 10476 pw.println(); 10477 } 10478 } 10479 } 10480 } 10481 if (mLosingFocus.size() > 0) { 10482 pw.println(); 10483 pw.println(" Windows losing focus:"); 10484 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10485 WindowState w = mLosingFocus.get(i); 10486 if (windows == null || windows.contains(w)) { 10487 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10488 pw.print(w); 10489 if (dumpAll) { 10490 pw.println(":"); 10491 w.dump(pw, " ", true); 10492 } else { 10493 pw.println(); 10494 } 10495 } 10496 } 10497 } 10498 if (mResizingWindows.size() > 0) { 10499 pw.println(); 10500 pw.println(" Windows waiting to resize:"); 10501 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10502 WindowState w = mResizingWindows.get(i); 10503 if (windows == null || windows.contains(w)) { 10504 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10505 pw.print(w); 10506 if (dumpAll) { 10507 pw.println(":"); 10508 w.dump(pw, " ", true); 10509 } else { 10510 pw.println(); 10511 } 10512 } 10513 } 10514 } 10515 if (mWaitingForDrawn.size() > 0) { 10516 pw.println(); 10517 pw.println(" Clients waiting for these windows to be drawn:"); 10518 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10519 WindowState win = mWaitingForDrawn.get(i); 10520 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); 10521 } 10522 } 10523 pw.println(); 10524 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10525 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10526 if (mLastFocus != mCurrentFocus) { 10527 pw.print(" mLastFocus="); pw.println(mLastFocus); 10528 } 10529 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10530 if (mInputMethodTarget != null) { 10531 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10532 } 10533 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10534 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10535 pw.print(" mLastDisplayFreezeDuration="); 10536 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw); 10537 if ( mLastFinishedFreezeSource != null) { 10538 pw.print(" due to "); 10539 pw.print(mLastFinishedFreezeSource); 10540 } 10541 pw.println(); 10542 if (dumpAll) { 10543 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10544 pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); 10545 if (mLastStatusBarVisibility != 0) { 10546 pw.print(" mLastStatusBarVisibility=0x"); 10547 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10548 } 10549 if (mInputMethodWindow != null) { 10550 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10551 } 10552 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10553 if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) { 10554 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10555 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10556 } 10557 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10558 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10559 if (mInputMethodAnimLayerAdjustment != 0 || 10560 mWallpaperAnimLayerAdjustment != 0) { 10561 pw.print(" mInputMethodAnimLayerAdjustment="); 10562 pw.print(mInputMethodAnimLayerAdjustment); 10563 pw.print(" mWallpaperAnimLayerAdjustment="); 10564 pw.println(mWallpaperAnimLayerAdjustment); 10565 } 10566 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10567 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10568 if (needsLayout()) { 10569 pw.print(" layoutNeeded on displays="); 10570 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10571 final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); 10572 if (displayContent.layoutNeeded) { 10573 pw.print(displayContent.getDisplayId()); 10574 } 10575 } 10576 pw.println(); 10577 } 10578 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10579 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10580 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10581 pw.print(" client="); pw.print(mClientFreezingScreen); 10582 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10583 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10584 pw.print(" mRotation="); pw.print(mRotation); 10585 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10586 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10587 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10588 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10589 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 10590 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 10591 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 10592 pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); 10593 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10594 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10595 pw.println(" mLayoutToAnim:"); 10596 mAppTransition.dump(pw); 10597 } 10598 } 10599 10600 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10601 int opti, boolean dumpAll) { 10602 WindowList windows = new WindowList(); 10603 if ("visible".equals(name)) { 10604 synchronized(mWindowMap) { 10605 final int numDisplays = mDisplayContents.size(); 10606 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10607 final WindowList windowList = 10608 mDisplayContents.valueAt(displayNdx).getWindowList(); 10609 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10610 final WindowState w = windowList.get(winNdx); 10611 if (w.mWinAnimator.mSurfaceShown) { 10612 windows.add(w); 10613 } 10614 } 10615 } 10616 } 10617 } else { 10618 int objectId = 0; 10619 // See if this is an object ID. 10620 try { 10621 objectId = Integer.parseInt(name, 16); 10622 name = null; 10623 } catch (RuntimeException e) { 10624 } 10625 synchronized(mWindowMap) { 10626 final int numDisplays = mDisplayContents.size(); 10627 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 10628 final WindowList windowList = 10629 mDisplayContents.valueAt(displayNdx).getWindowList(); 10630 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 10631 final WindowState w = windowList.get(winNdx); 10632 if (name != null) { 10633 if (w.mAttrs.getTitle().toString().contains(name)) { 10634 windows.add(w); 10635 } 10636 } else if (System.identityHashCode(w) == objectId) { 10637 windows.add(w); 10638 } 10639 } 10640 } 10641 } 10642 } 10643 10644 if (windows.size() <= 0) { 10645 return false; 10646 } 10647 10648 synchronized(mWindowMap) { 10649 dumpWindowsLocked(pw, dumpAll, windows); 10650 } 10651 return true; 10652 } 10653 10654 void dumpLastANRLocked(PrintWriter pw) { 10655 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10656 if (mLastANRState == null) { 10657 pw.println(" <no ANR has occurred since boot>"); 10658 } else { 10659 pw.println(mLastANRState); 10660 } 10661 } 10662 10663 /** 10664 * Saves information about the state of the window manager at 10665 * the time an ANR occurred before anything else in the system changes 10666 * in response. 10667 * 10668 * @param appWindowToken The application that ANR'd, may be null. 10669 * @param windowState The window that ANR'd, may be null. 10670 * @param reason The reason for the ANR, may be null. 10671 */ 10672 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, 10673 String reason) { 10674 StringWriter sw = new StringWriter(); 10675 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 10676 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10677 if (appWindowToken != null) { 10678 pw.println(" Application at fault: " + appWindowToken.stringName); 10679 } 10680 if (windowState != null) { 10681 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10682 } 10683 if (reason != null) { 10684 pw.println(" Reason: " + reason); 10685 } 10686 pw.println(); 10687 dumpWindowsNoHeaderLocked(pw, true, null); 10688 pw.close(); 10689 mLastANRState = sw.toString(); 10690 } 10691 10692 @Override 10693 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10694 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10695 != PackageManager.PERMISSION_GRANTED) { 10696 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10697 + Binder.getCallingPid() 10698 + ", uid=" + Binder.getCallingUid()); 10699 return; 10700 } 10701 10702 boolean dumpAll = false; 10703 10704 int opti = 0; 10705 while (opti < args.length) { 10706 String opt = args[opti]; 10707 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10708 break; 10709 } 10710 opti++; 10711 if ("-a".equals(opt)) { 10712 dumpAll = true; 10713 } else if ("-h".equals(opt)) { 10714 pw.println("Window manager dump options:"); 10715 pw.println(" [-a] [-h] [cmd] ..."); 10716 pw.println(" cmd may be one of:"); 10717 pw.println(" l[astanr]: last ANR information"); 10718 pw.println(" p[policy]: policy state"); 10719 pw.println(" a[animator]: animator state"); 10720 pw.println(" s[essions]: active sessions"); 10721 pw.println(" d[isplays]: active display contents"); 10722 pw.println(" t[okens]: token list"); 10723 pw.println(" w[indows]: window list"); 10724 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10725 pw.println(" be a partial substring in a window name, a"); 10726 pw.println(" Window hex object identifier, or"); 10727 pw.println(" \"all\" for all windows, or"); 10728 pw.println(" \"visible\" for the visible windows."); 10729 pw.println(" -a: include all available server state."); 10730 return; 10731 } else { 10732 pw.println("Unknown argument: " + opt + "; use -h for help"); 10733 } 10734 } 10735 10736 // Is the caller requesting to dump a particular piece of data? 10737 if (opti < args.length) { 10738 String cmd = args[opti]; 10739 opti++; 10740 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10741 synchronized(mWindowMap) { 10742 dumpLastANRLocked(pw); 10743 } 10744 return; 10745 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10746 synchronized(mWindowMap) { 10747 dumpPolicyLocked(pw, args, true); 10748 } 10749 return; 10750 } else if ("animator".equals(cmd) || "a".equals(cmd)) { 10751 synchronized(mWindowMap) { 10752 dumpAnimatorLocked(pw, args, true); 10753 } 10754 return; 10755 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10756 synchronized(mWindowMap) { 10757 dumpSessionsLocked(pw, true); 10758 } 10759 return; 10760 } else if ("displays".equals(cmd) || "d".equals(cmd)) { 10761 synchronized(mWindowMap) { 10762 dumpDisplayContentsLocked(pw, true); 10763 } 10764 return; 10765 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10766 synchronized(mWindowMap) { 10767 dumpTokensLocked(pw, true); 10768 } 10769 return; 10770 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10771 synchronized(mWindowMap) { 10772 dumpWindowsLocked(pw, true, null); 10773 } 10774 return; 10775 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10776 synchronized(mWindowMap) { 10777 dumpWindowsLocked(pw, true, null); 10778 } 10779 return; 10780 } else { 10781 // Dumping a single name? 10782 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10783 pw.println("Bad window command, or no windows match: " + cmd); 10784 pw.println("Use -h for help."); 10785 } 10786 return; 10787 } 10788 } 10789 10790 synchronized(mWindowMap) { 10791 pw.println(); 10792 if (dumpAll) { 10793 pw.println("-------------------------------------------------------------------------------"); 10794 } 10795 dumpLastANRLocked(pw); 10796 pw.println(); 10797 if (dumpAll) { 10798 pw.println("-------------------------------------------------------------------------------"); 10799 } 10800 dumpPolicyLocked(pw, args, dumpAll); 10801 pw.println(); 10802 if (dumpAll) { 10803 pw.println("-------------------------------------------------------------------------------"); 10804 } 10805 dumpAnimatorLocked(pw, args, dumpAll); 10806 pw.println(); 10807 if (dumpAll) { 10808 pw.println("-------------------------------------------------------------------------------"); 10809 } 10810 dumpSessionsLocked(pw, dumpAll); 10811 pw.println(); 10812 if (dumpAll) { 10813 pw.println("-------------------------------------------------------------------------------"); 10814 } 10815 dumpDisplayContentsLocked(pw, dumpAll); 10816 pw.println(); 10817 if (dumpAll) { 10818 pw.println("-------------------------------------------------------------------------------"); 10819 } 10820 dumpTokensLocked(pw, dumpAll); 10821 pw.println(); 10822 if (dumpAll) { 10823 pw.println("-------------------------------------------------------------------------------"); 10824 } 10825 dumpWindowsLocked(pw, dumpAll, null); 10826 } 10827 } 10828 10829 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10830 @Override 10831 public void monitor() { 10832 synchronized (mWindowMap) { } 10833 } 10834 10835 public interface OnHardKeyboardStatusChangeListener { 10836 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10837 } 10838 10839 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10840 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10841 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10842 Integer.toHexString(pendingLayoutChanges)); 10843 } 10844 } 10845 10846 private DisplayContent newDisplayContentLocked(final Display display) { 10847 DisplayContent displayContent = new DisplayContent(display, this); 10848 final int displayId = display.getDisplayId(); 10849 if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); 10850 mDisplayContents.put(displayId, displayContent); 10851 10852 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10853 final Rect rect = new Rect(); 10854 mDisplaySettings.getOverscanLocked(displayInfo.name, rect); 10855 synchronized (displayContent.mDisplaySizeLock) { 10856 displayInfo.overscanLeft = rect.left; 10857 displayInfo.overscanTop = rect.top; 10858 displayInfo.overscanRight = rect.right; 10859 displayInfo.overscanBottom = rect.bottom; 10860 mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 10861 displayId, displayInfo); 10862 } 10863 configureDisplayPolicyLocked(displayContent); 10864 10865 // TODO: Create an input channel for each display with touch capability. 10866 if (displayId == Display.DEFAULT_DISPLAY) { 10867 displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); 10868 registerPointerEventListener(displayContent.mTapDetector); 10869 } 10870 10871 return displayContent; 10872 } 10873 10874 public void createDisplayContentLocked(final Display display) { 10875 if (display == null) { 10876 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10877 } 10878 getDisplayContentLocked(display.getDisplayId()); 10879 } 10880 10881 /** 10882 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 10883 * there is a Display for the displayId. 10884 * @param displayId The display the caller is interested in. 10885 * @return The DisplayContent associated with displayId or null if there is no Display for it. 10886 */ 10887 public DisplayContent getDisplayContentLocked(final int displayId) { 10888 DisplayContent displayContent = mDisplayContents.get(displayId); 10889 if (displayContent == null) { 10890 final Display display = mDisplayManager.getDisplay(displayId); 10891 if (display != null) { 10892 displayContent = newDisplayContentLocked(display); 10893 } 10894 } 10895 return displayContent; 10896 } 10897 10898 // There is an inherent assumption that this will never return null. 10899 public DisplayContent getDefaultDisplayContentLocked() { 10900 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10901 } 10902 10903 public WindowList getDefaultWindowListLocked() { 10904 return getDefaultDisplayContentLocked().getWindowList(); 10905 } 10906 10907 public DisplayInfo getDefaultDisplayInfoLocked() { 10908 return getDefaultDisplayContentLocked().getDisplayInfo(); 10909 } 10910 10911 /** 10912 * Return the list of WindowStates associated on the passed display. 10913 * @param display The screen to return windows from. 10914 * @return The list of WindowStates on the screen, or null if the there is no screen. 10915 */ 10916 public WindowList getWindowListLocked(final Display display) { 10917 return getWindowListLocked(display.getDisplayId()); 10918 } 10919 10920 /** 10921 * Return the list of WindowStates associated on the passed display. 10922 * @param displayId The screen to return windows from. 10923 * @return The list of WindowStates on the screen, or null if the there is no screen. 10924 */ 10925 public WindowList getWindowListLocked(final int displayId) { 10926 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10927 return displayContent != null ? displayContent.getWindowList() : null; 10928 } 10929 10930 public void onDisplayAdded(int displayId) { 10931 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10932 } 10933 10934 public void handleDisplayAdded(int displayId) { 10935 synchronized (mWindowMap) { 10936 final Display display = mDisplayManager.getDisplay(displayId); 10937 if (display != null) { 10938 createDisplayContentLocked(display); 10939 displayReady(displayId); 10940 } 10941 } 10942 } 10943 10944 public void onDisplayRemoved(int displayId) { 10945 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 10946 } 10947 10948 private void handleDisplayRemovedLocked(int displayId) { 10949 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10950 if (displayContent != null) { 10951 if (displayContent.isAnimating()) { 10952 displayContent.mDeferredRemoval = true; 10953 return; 10954 } 10955 if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); 10956 mDisplayContents.delete(displayId); 10957 displayContent.close(); 10958 if (displayId == Display.DEFAULT_DISPLAY) { 10959 unregisterPointerEventListener(displayContent.mTapDetector); 10960 } 10961 } 10962 mAnimator.removeDisplayLocked(displayId); 10963 } 10964 10965 public void onDisplayChanged(int displayId) { 10966 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 10967 } 10968 10969 private void handleDisplayChangedLocked(int displayId) { 10970 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10971 if (displayContent != null) { 10972 displayContent.updateDisplayInfo(); 10973 } 10974 } 10975 10976 @Override 10977 public Object getWindowManagerLock() { 10978 return mWindowMap; 10979 } 10980 10981 private final class LocalService extends WindowManagerInternal { 10982 @Override 10983 public void requestTraversalFromDisplayManager() { 10984 requestTraversal(); 10985 } 10986 10987 @Override 10988 public void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout) { 10989 synchronized (mWindowMap) { 10990 mWaitingForDrawnCallback = callback; 10991 final WindowList windows = getDefaultWindowListLocked(); 10992 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 10993 final WindowState win = windows.get(winNdx); 10994 if (win.mHasSurface) { 10995 win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 10996 // Force add to mResizingWindows. 10997 win.mLastContentInsets.set(-1, -1, -1, -1); 10998 mWaitingForDrawn.add(win); 10999 } 11000 } 11001 requestTraversalLocked(); 11002 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); 11003 mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); 11004 } 11005 checkDrawnWindowsLocked(); 11006 } 11007 } 11008} 11009