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