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