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