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