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