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