WindowManagerService.java revision 322e40315609acd5a608440bc469d873e09559ca
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.InputFilter; 49import com.android.server.input.InputManagerService; 50import com.android.server.power.PowerManagerService; 51import com.android.server.power.ShutdownThread; 52 53import android.Manifest; 54import android.app.ActivityManagerNative; 55import android.app.ActivityOptions; 56import android.app.IActivityManager; 57import android.app.StatusBarManager; 58import android.app.admin.DevicePolicyManager; 59import android.content.BroadcastReceiver; 60import android.content.Context; 61import android.content.Intent; 62import android.content.IntentFilter; 63import android.content.pm.ActivityInfo; 64import android.content.pm.PackageManager; 65import android.content.res.CompatibilityInfo; 66import android.content.res.Configuration; 67import android.graphics.Bitmap; 68import android.graphics.Canvas; 69import android.graphics.Matrix; 70import android.graphics.PixelFormat; 71import android.graphics.Point; 72import android.graphics.Rect; 73import android.graphics.RectF; 74import android.graphics.Region; 75import android.os.BatteryStats; 76import android.os.Binder; 77import android.os.Bundle; 78import android.os.Debug; 79import android.os.Handler; 80import android.os.IBinder; 81import android.os.IRemoteCallback; 82import android.os.LocalPowerManager; 83import android.os.Looper; 84import android.os.Message; 85import android.os.Parcel; 86import android.os.ParcelFileDescriptor; 87import android.os.PowerManager; 88import android.os.Process; 89import android.os.RemoteException; 90import android.os.ServiceManager; 91import android.os.StrictMode; 92import android.os.SystemClock; 93import android.os.SystemProperties; 94import android.os.TokenWatcher; 95import android.os.Trace; 96import android.provider.Settings; 97import android.util.DisplayMetrics; 98import android.util.EventLog; 99import android.util.FloatMath; 100import android.util.Log; 101//import android.util.LogPrinter; 102import android.util.Pair; 103import android.util.Slog; 104import android.util.SparseIntArray; 105import android.util.TypedValue; 106import android.view.Choreographer; 107import android.view.Display; 108import android.view.Gravity; 109import android.view.IApplicationToken; 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 synchronized (mWindowMap) { 3073 WindowState windowState = mWindowMap.get(windowToken); 3074 return (windowState != null) ? windowState.mGlobalScale : 1.0f; 3075 } 3076 } 3077 3078 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) { 3079 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg=" 3080 + (lp != null ? lp.packageName : null) 3081 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null)); 3082 if (lp != null && lp.windowAnimations != 0) { 3083 // If this is a system resource, don't try to load it from the 3084 // application resources. It is nice to avoid loading application 3085 // resources if we can. 3086 String packageName = lp.packageName != null ? lp.packageName : "android"; 3087 int resId = lp.windowAnimations; 3088 if ((resId&0xFF000000) == 0x01000000) { 3089 packageName = "android"; 3090 } 3091 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" 3092 + packageName); 3093 return AttributeCache.instance().get(packageName, resId, 3094 com.android.internal.R.styleable.WindowAnimation); 3095 } 3096 return null; 3097 } 3098 3099 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) { 3100 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package=" 3101 + packageName + " resId=0x" + Integer.toHexString(resId)); 3102 if (packageName != null) { 3103 if ((resId&0xFF000000) == 0x01000000) { 3104 packageName = "android"; 3105 } 3106 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" 3107 + packageName); 3108 return AttributeCache.instance().get(packageName, resId, 3109 com.android.internal.R.styleable.WindowAnimation); 3110 } 3111 return null; 3112 } 3113 3114 Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) { 3115 int anim = 0; 3116 Context context = mContext; 3117 if (animAttr >= 0) { 3118 AttributeCache.Entry ent = getCachedAnimations(lp); 3119 if (ent != null) { 3120 context = ent.context; 3121 anim = ent.array.getResourceId(animAttr, 0); 3122 } 3123 } 3124 if (anim != 0) { 3125 return AnimationUtils.loadAnimation(context, anim); 3126 } 3127 return null; 3128 } 3129 3130 private Animation loadAnimation(String packageName, int resId) { 3131 int anim = 0; 3132 Context context = mContext; 3133 if (resId >= 0) { 3134 AttributeCache.Entry ent = getCachedAnimations(packageName, resId); 3135 if (ent != null) { 3136 context = ent.context; 3137 anim = resId; 3138 } 3139 } 3140 if (anim != 0) { 3141 return AnimationUtils.loadAnimation(context, anim); 3142 } 3143 return null; 3144 } 3145 3146 private Animation createExitAnimationLocked(int transit, int duration) { 3147 if (transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN || 3148 transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE) { 3149 // If we are on top of the wallpaper, we need an animation that 3150 // correctly handles the wallpaper staying static behind all of 3151 // the animated elements. To do this, will just have the existing 3152 // element fade out. 3153 Animation a = new AlphaAnimation(1, 0); 3154 a.setDetachWallpaper(true); 3155 a.setDuration(duration); 3156 return a; 3157 } 3158 // For normal animations, the exiting element just holds in place. 3159 Animation a = new AlphaAnimation(1, 1); 3160 a.setDuration(duration); 3161 return a; 3162 } 3163 3164 /** 3165 * Compute the pivot point for an animation that is scaling from a small 3166 * rect on screen to a larger rect. The pivot point varies depending on 3167 * the distance between the inner and outer edges on both sides. This 3168 * function computes the pivot point for one dimension. 3169 * @param startPos Offset from left/top edge of outer rectangle to 3170 * left/top edge of inner rectangle. 3171 * @param finalScale The scaling factor between the size of the outer 3172 * and inner rectangles. 3173 */ 3174 private static float computePivot(int startPos, float finalScale) { 3175 final float denom = finalScale-1; 3176 if (Math.abs(denom) < .0001f) { 3177 return startPos; 3178 } 3179 return -startPos / denom; 3180 } 3181 3182 private Animation createScaleUpAnimationLocked(int transit, boolean enter) { 3183 Animation a; 3184 // Pick the desired duration. If this is an inter-activity transition, 3185 // it is the standard duration for that. Otherwise we use the longer 3186 // task transition duration. 3187 int duration; 3188 switch (transit) { 3189 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 3190 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 3191 duration = mContext.getResources().getInteger( 3192 com.android.internal.R.integer.config_shortAnimTime); 3193 break; 3194 default: 3195 duration = 300; 3196 break; 3197 } 3198 if (enter) { 3199 // Entering app zooms out from the center of the initial rect. 3200 float scaleW = mNextAppTransitionStartWidth / (float) mAppDisplayWidth; 3201 float scaleH = mNextAppTransitionStartHeight / (float) mAppDisplayHeight; 3202 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, 3203 computePivot(mNextAppTransitionStartX, scaleW), 3204 computePivot(mNextAppTransitionStartY, scaleH)); 3205 scale.setDuration(duration); 3206 AnimationSet set = new AnimationSet(true); 3207 Animation alpha = new AlphaAnimation(0, 1); 3208 scale.setDuration(duration); 3209 set.addAnimation(scale); 3210 alpha.setDuration(duration); 3211 set.addAnimation(alpha); 3212 set.setDetachWallpaper(true); 3213 a = set; 3214 } else { 3215 a = createExitAnimationLocked(transit, duration); 3216 } 3217 a.setFillAfter(true); 3218 final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext, 3219 com.android.internal.R.interpolator.decelerate_cubic); 3220 a.setInterpolator(interpolator); 3221 a.initialize(mAppDisplayWidth, mAppDisplayHeight, 3222 mAppDisplayWidth, mAppDisplayHeight); 3223 return a; 3224 } 3225 3226 private Animation createThumbnailAnimationLocked(int transit, 3227 boolean enter, boolean thumb, boolean delayed) { 3228 Animation a; 3229 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth(); 3230 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; 3231 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight(); 3232 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; 3233 // Pick the desired duration. If this is an inter-activity transition, 3234 // it is the standard duration for that. Otherwise we use the longer 3235 // task transition duration. 3236 int duration; 3237 int delayDuration = delayed ? 270 : 0; 3238 switch (transit) { 3239 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 3240 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 3241 duration = mContext.getResources().getInteger( 3242 com.android.internal.R.integer.config_shortAnimTime); 3243 break; 3244 default: 3245 duration = delayed ? 250 : 300; 3246 break; 3247 } 3248 if (thumb) { 3249 // Animation for zooming thumbnail from its initial size to 3250 // filling the screen. 3251 float scaleW = mAppDisplayWidth/thumbWidth; 3252 float scaleH = mAppDisplayHeight/thumbHeight; 3253 3254 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, 3255 computePivot(mNextAppTransitionStartX, 1/scaleW), 3256 computePivot(mNextAppTransitionStartY, 1/scaleH)); 3257 AnimationSet set = new AnimationSet(true); 3258 Animation alpha = new AlphaAnimation(1, 0); 3259 scale.setDuration(duration); 3260 scale.setInterpolator( 3261 new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR)); 3262 set.addAnimation(scale); 3263 alpha.setDuration(duration); 3264 set.addAnimation(alpha); 3265 set.setFillBefore(true); 3266 if (delayDuration > 0) { 3267 set.setStartOffset(delayDuration); 3268 } 3269 a = set; 3270 } else if (enter) { 3271 // Entering app zooms out from the center of the thumbnail. 3272 float scaleW = thumbWidth / mAppDisplayWidth; 3273 float scaleH = thumbHeight / mAppDisplayHeight; 3274 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, 3275 computePivot(mNextAppTransitionStartX, scaleW), 3276 computePivot(mNextAppTransitionStartY, scaleH)); 3277 scale.setDuration(duration); 3278 scale.setInterpolator( 3279 new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR)); 3280 scale.setFillBefore(true); 3281 if (delayDuration > 0) { 3282 scale.setStartOffset(delayDuration); 3283 } 3284 a = scale; 3285 } else { 3286 if (delayed) { 3287 a = new AlphaAnimation(1, 0); 3288 a.setStartOffset(0); 3289 a.setDuration(delayDuration - 120); 3290 a.setBackgroundColor(0xFF000000); 3291 } else { 3292 a = createExitAnimationLocked(transit, duration); 3293 } 3294 } 3295 a.setFillAfter(true); 3296 final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext, 3297 com.android.internal.R.interpolator.decelerate_quad); 3298 a.setInterpolator(interpolator); 3299 a.initialize(mAppDisplayWidth, mAppDisplayHeight, 3300 mAppDisplayWidth, mAppDisplayHeight); 3301 return a; 3302 } 3303 3304 private boolean applyAnimationLocked(AppWindowToken wtoken, 3305 WindowManager.LayoutParams lp, int transit, boolean enter) { 3306 // Only apply an animation if the display isn't frozen. If it is 3307 // frozen, there is no reason to animate and it can cause strange 3308 // artifacts when we unfreeze the display if some different animation 3309 // is running. 3310 if (okToDisplay()) { 3311 Animation a; 3312 boolean initialized = false; 3313 if (mNextAppTransitionType == ActivityOptions.ANIM_CUSTOM) { 3314 a = loadAnimation(mNextAppTransitionPackage, enter ? 3315 mNextAppTransitionEnter : mNextAppTransitionExit); 3316 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 3317 "applyAnimation: wtoken=" + wtoken 3318 + " anim=" + a + " nextAppTransition=ANIM_CUSTOM" 3319 + " transit=" + transit + " Callers " + Debug.getCallers(3)); 3320 } else if (mNextAppTransitionType == ActivityOptions.ANIM_SCALE_UP) { 3321 a = createScaleUpAnimationLocked(transit, enter); 3322 initialized = true; 3323 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 3324 "applyAnimation: wtoken=" + wtoken 3325 + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP" 3326 + " transit=" + transit + " Callers " + Debug.getCallers(3)); 3327 } else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL || 3328 mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_DELAYED) { 3329 boolean delayed = (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_DELAYED); 3330 a = createThumbnailAnimationLocked(transit, enter, false, delayed); 3331 initialized = true; 3332 3333 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 3334 String animName = delayed ? "ANIM_THUMBNAIL_DELAYED" : "ANIM_THUMBNAIL"; 3335 Slog.v(TAG, "applyAnimation: wtoken=" + wtoken 3336 + " anim=" + a + " nextAppTransition=" + animName 3337 + " transit=" + transit + " Callers " + Debug.getCallers(3)); 3338 } 3339 } else { 3340 int animAttr = 0; 3341 switch (transit) { 3342 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 3343 animAttr = enter 3344 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation 3345 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation; 3346 break; 3347 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 3348 animAttr = enter 3349 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation 3350 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation; 3351 break; 3352 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 3353 animAttr = enter 3354 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation 3355 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation; 3356 break; 3357 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 3358 animAttr = enter 3359 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation 3360 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation; 3361 break; 3362 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 3363 animAttr = enter 3364 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation 3365 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation; 3366 break; 3367 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 3368 animAttr = enter 3369 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation 3370 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; 3371 break; 3372 case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN: 3373 animAttr = enter 3374 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation 3375 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation; 3376 break; 3377 case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE: 3378 animAttr = enter 3379 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation 3380 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation; 3381 break; 3382 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN: 3383 animAttr = enter 3384 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation 3385 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; 3386 break; 3387 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE: 3388 animAttr = enter 3389 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation 3390 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation; 3391 break; 3392 } 3393 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null; 3394 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 3395 "applyAnimation: wtoken=" + wtoken 3396 + " anim=" + a 3397 + " animAttr=0x" + Integer.toHexString(animAttr) 3398 + " transit=" + transit + " Callers " + Debug.getCallers(3)); 3399 } 3400 if (a != null) { 3401 if (DEBUG_ANIM) { 3402 RuntimeException e = null; 3403 if (!HIDE_STACK_CRAWLS) { 3404 e = new RuntimeException(); 3405 e.fillInStackTrace(); 3406 } 3407 Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e); 3408 } 3409 wtoken.mAppAnimator.setAnimation(a, initialized); 3410 } 3411 } else { 3412 wtoken.mAppAnimator.clearAnimation(); 3413 } 3414 3415 return wtoken.mAppAnimator.animation != null; 3416 } 3417 3418 // ------------------------------------------------------------- 3419 // Application Window Tokens 3420 // ------------------------------------------------------------- 3421 3422 public void validateAppTokens(List<IBinder> tokens) { 3423 int v = tokens.size()-1; 3424 int m = mAppTokens.size()-1; 3425 while (v >= 0 && m >= 0) { 3426 AppWindowToken wtoken = mAppTokens.get(m); 3427 if (wtoken.removed) { 3428 m--; 3429 continue; 3430 } 3431 if (tokens.get(v) != wtoken.token) { 3432 Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v) 3433 + " @ " + v + ", internal is " + wtoken.token + " @ " + m); 3434 } 3435 v--; 3436 m--; 3437 } 3438 while (v >= 0) { 3439 Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v); 3440 v--; 3441 } 3442 while (m >= 0) { 3443 AppWindowToken wtoken = mAppTokens.get(m); 3444 if (!wtoken.removed) { 3445 Slog.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m); 3446 } 3447 m--; 3448 } 3449 } 3450 3451 boolean checkCallingPermission(String permission, String func) { 3452 // Quick check: if the calling permission is me, it's all okay. 3453 if (Binder.getCallingPid() == Process.myPid()) { 3454 return true; 3455 } 3456 3457 if (mContext.checkCallingPermission(permission) 3458 == PackageManager.PERMISSION_GRANTED) { 3459 return true; 3460 } 3461 String msg = "Permission Denial: " + func + " from pid=" 3462 + Binder.getCallingPid() 3463 + ", uid=" + Binder.getCallingUid() 3464 + " requires " + permission; 3465 Slog.w(TAG, msg); 3466 return false; 3467 } 3468 3469 boolean okToDisplay() { 3470 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully(); 3471 } 3472 3473 AppWindowToken findAppWindowToken(IBinder token) { 3474 WindowToken wtoken = mTokenMap.get(token); 3475 if (wtoken == null) { 3476 return null; 3477 } 3478 return wtoken.appWindowToken; 3479 } 3480 3481 @Override 3482 public void addWindowToken(IBinder token, int type) { 3483 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3484 "addWindowToken()")) { 3485 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3486 } 3487 3488 synchronized(mWindowMap) { 3489 WindowToken wtoken = mTokenMap.get(token); 3490 if (wtoken != null) { 3491 Slog.w(TAG, "Attempted to add existing input method token: " + token); 3492 return; 3493 } 3494 wtoken = new WindowToken(this, token, type, true); 3495 mTokenMap.put(token, wtoken); 3496 if (type == TYPE_WALLPAPER) { 3497 mWallpaperTokens.add(wtoken); 3498 updateLayoutToAnimWallpaperTokens(); 3499 } 3500 } 3501 } 3502 3503 @Override 3504 public void removeWindowToken(IBinder token) { 3505 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3506 "removeWindowToken()")) { 3507 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3508 } 3509 3510 final long origId = Binder.clearCallingIdentity(); 3511 synchronized(mWindowMap) { 3512 WindowToken wtoken = mTokenMap.remove(token); 3513 if (wtoken != null) { 3514 boolean delayed = false; 3515 if (!wtoken.hidden) { 3516 wtoken.hidden = true; 3517 3518 final int N = wtoken.windows.size(); 3519 boolean changed = false; 3520 3521 for (int i=0; i<N; i++) { 3522 WindowState win = wtoken.windows.get(i); 3523 3524 if (win.mWinAnimator.isAnimating()) { 3525 delayed = true; 3526 } 3527 3528 if (win.isVisibleNow()) { 3529 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false); 3530 changed = true; 3531 } 3532 } 3533 3534 if (changed) { 3535 mLayoutNeeded = true; 3536 performLayoutAndPlaceSurfacesLocked(); 3537 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 3538 false /*updateInputWindows*/); 3539 } 3540 3541 if (delayed) { 3542 mExitingTokens.add(wtoken); 3543 } else if (wtoken.windowType == TYPE_WALLPAPER) { 3544 mWallpaperTokens.remove(wtoken); 3545 updateLayoutToAnimWallpaperTokens(); 3546 } 3547 } 3548 3549 mInputMonitor.updateInputWindowsLw(true /*force*/); 3550 } else { 3551 Slog.w(TAG, "Attempted to remove non-existing token: " + token); 3552 } 3553 } 3554 Binder.restoreCallingIdentity(origId); 3555 } 3556 3557 /** 3558 * Find the location to insert a new AppWindowToken into the window-ordered app token list. 3559 * Note that mAppTokens.size() == mAnimatingAppTokens.size() + 1. 3560 * @param addPos The location the token was inserted into in mAppTokens. 3561 * @param wtoken The token to insert. 3562 */ 3563 private void addAppTokenToAnimating(final int addPos, final AppWindowToken wtoken) { 3564 if (addPos == 0 || addPos == mAnimatingAppTokens.size()) { 3565 // It was inserted into the beginning or end of mAppTokens. Honor that. 3566 mAnimatingAppTokens.add(addPos, wtoken); 3567 return; 3568 } 3569 // Find the item immediately above the mAppTokens insertion point and put the token 3570 // immediately below that one in mAnimatingAppTokens. 3571 final AppWindowToken aboveAnchor = mAppTokens.get(addPos + 1); 3572 mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), wtoken); 3573 } 3574 3575 @Override 3576 public void addAppToken(int addPos, IApplicationToken token, 3577 int groupId, int requestedOrientation, boolean fullscreen) { 3578 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3579 "addAppToken()")) { 3580 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3581 } 3582 3583 // Get the dispatching timeout here while we are not holding any locks so that it 3584 // can be cached by the AppWindowToken. The timeout value is used later by the 3585 // input dispatcher in code that does hold locks. If we did not cache the value 3586 // here we would run the chance of introducing a deadlock between the window manager 3587 // (which holds locks while updating the input dispatcher state) and the activity manager 3588 // (which holds locks while querying the application token). 3589 long inputDispatchingTimeoutNanos; 3590 try { 3591 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; 3592 } catch (RemoteException ex) { 3593 Slog.w(TAG, "Could not get dispatching timeout.", ex); 3594 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 3595 } 3596 3597 synchronized(mWindowMap) { 3598 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 3599 if (wtoken != null) { 3600 Slog.w(TAG, "Attempted to add existing app token: " + token); 3601 return; 3602 } 3603 wtoken = new AppWindowToken(this, token); 3604 wtoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; 3605 wtoken.groupId = groupId; 3606 wtoken.appFullscreen = fullscreen; 3607 wtoken.requestedOrientation = requestedOrientation; 3608 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + wtoken 3609 + " at " + addPos); 3610 mAppTokens.add(addPos, wtoken); 3611 addAppTokenToAnimating(addPos, wtoken); 3612 mTokenMap.put(token.asBinder(), wtoken); 3613 3614 // Application tokens start out hidden. 3615 wtoken.hidden = true; 3616 wtoken.hiddenRequested = true; 3617 3618 //dump(); 3619 } 3620 } 3621 3622 @Override 3623 public void setAppGroupId(IBinder token, int groupId) { 3624 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3625 "setAppGroupId()")) { 3626 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3627 } 3628 3629 synchronized(mWindowMap) { 3630 AppWindowToken wtoken = findAppWindowToken(token); 3631 if (wtoken == null) { 3632 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); 3633 return; 3634 } 3635 wtoken.groupId = groupId; 3636 } 3637 } 3638 3639 public int getOrientationFromWindowsLocked() { 3640 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 3641 // If the display is frozen, some activities may be in the middle 3642 // of restarting, and thus have removed their old window. If the 3643 // window has the flag to hide the lock screen, then the lock screen 3644 // can re-appear and inflict its own orientation on us. Keep the 3645 // orientation stable until this all settles down. 3646 return mLastWindowForcedOrientation; 3647 } 3648 3649 int pos = mWindows.size() - 1; 3650 while (pos >= 0) { 3651 WindowState wtoken = mWindows.get(pos); 3652 pos--; 3653 if (wtoken.mAppToken != null) { 3654 // We hit an application window. so the orientation will be determined by the 3655 // app window. No point in continuing further. 3656 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3657 } 3658 if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) { 3659 continue; 3660 } 3661 int req = wtoken.mAttrs.screenOrientation; 3662 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) || 3663 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){ 3664 continue; 3665 } 3666 3667 return (mLastWindowForcedOrientation=req); 3668 } 3669 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3670 } 3671 3672 public int getOrientationFromAppTokensLocked() { 3673 int curGroup = 0; 3674 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3675 boolean findingBehind = false; 3676 boolean haveGroup = false; 3677 boolean lastFullscreen = false; 3678 for (int pos = mAppTokens.size() - 1; pos >= 0; pos--) { 3679 AppWindowToken wtoken = mAppTokens.get(pos); 3680 3681 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + wtoken); 3682 3683 // if we're about to tear down this window and not seek for 3684 // the behind activity, don't use it for orientation 3685 if (!findingBehind 3686 && (!wtoken.hidden && wtoken.hiddenRequested)) { 3687 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + wtoken 3688 + " -- going to hide"); 3689 continue; 3690 } 3691 3692 if (haveGroup == true && curGroup != wtoken.groupId) { 3693 // If we have hit a new application group, and the bottom 3694 // of the previous group didn't explicitly say to use 3695 // the orientation behind it, and the last app was 3696 // full screen, then we'll stick with the 3697 // user's orientation. 3698 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND 3699 && lastFullscreen) { 3700 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + wtoken 3701 + " -- end of group, return " + lastOrientation); 3702 return lastOrientation; 3703 } 3704 } 3705 3706 // We ignore any hidden applications on the top. 3707 if (wtoken.hiddenRequested || wtoken.willBeHidden) { 3708 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + wtoken 3709 + " -- hidden on top"); 3710 continue; 3711 } 3712 3713 if (!haveGroup) { 3714 haveGroup = true; 3715 curGroup = wtoken.groupId; 3716 lastOrientation = wtoken.requestedOrientation; 3717 } 3718 3719 int or = wtoken.requestedOrientation; 3720 // If this application is fullscreen, and didn't explicitly say 3721 // to use the orientation behind it, then just take whatever 3722 // orientation it has and ignores whatever is under it. 3723 lastFullscreen = wtoken.appFullscreen; 3724 if (lastFullscreen 3725 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3726 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + wtoken 3727 + " -- full screen, return " + or); 3728 return or; 3729 } 3730 // If this application has requested an explicit orientation, 3731 // then use it. 3732 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 3733 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3734 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + wtoken 3735 + " -- explicitly set, return " + or); 3736 return or; 3737 } 3738 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND); 3739 } 3740 if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation"); 3741 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3742 } 3743 3744 @Override 3745 public Configuration updateOrientationFromAppTokens( 3746 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3747 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3748 "updateOrientationFromAppTokens()")) { 3749 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3750 } 3751 3752 Configuration config = null; 3753 long ident = Binder.clearCallingIdentity(); 3754 3755 synchronized(mWindowMap) { 3756 config = updateOrientationFromAppTokensLocked(currentConfig, 3757 freezeThisOneIfNeeded); 3758 } 3759 3760 Binder.restoreCallingIdentity(ident); 3761 return config; 3762 } 3763 3764 private Configuration updateOrientationFromAppTokensLocked( 3765 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3766 Configuration config = null; 3767 3768 if (updateOrientationFromAppTokensLocked(false)) { 3769 if (freezeThisOneIfNeeded != null) { 3770 AppWindowToken wtoken = findAppWindowToken( 3771 freezeThisOneIfNeeded); 3772 if (wtoken != null) { 3773 startAppFreezingScreenLocked(wtoken, 3774 ActivityInfo.CONFIG_ORIENTATION); 3775 } 3776 } 3777 config = computeNewConfigurationLocked(); 3778 3779 } else if (currentConfig != null) { 3780 // No obvious action we need to take, but if our current 3781 // state mismatches the activity manager's, update it, 3782 // disregarding font scale, which should remain set to 3783 // the value of the previous configuration. 3784 mTempConfiguration.setToDefaults(); 3785 mTempConfiguration.fontScale = currentConfig.fontScale; 3786 if (computeScreenConfigurationLocked(mTempConfiguration)) { 3787 if (currentConfig.diff(mTempConfiguration) != 0) { 3788 mWaitingForConfig = true; 3789 mLayoutNeeded = true; 3790 startFreezingDisplayLocked(false); 3791 config = new Configuration(mTempConfiguration); 3792 } 3793 } 3794 } 3795 3796 return config; 3797 } 3798 3799 /* 3800 * Determine the new desired orientation of the display, returning 3801 * a non-null new Configuration if it has changed from the current 3802 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL 3803 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE 3804 * SCREEN. This will typically be done for you if you call 3805 * sendNewConfiguration(). 3806 * 3807 * The orientation is computed from non-application windows first. If none of 3808 * the non-application windows specify orientation, the orientation is computed from 3809 * application tokens. 3810 * @see android.view.IWindowManager#updateOrientationFromAppTokens( 3811 * android.os.IBinder) 3812 */ 3813 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) { 3814 long ident = Binder.clearCallingIdentity(); 3815 try { 3816 int req = computeForcedAppOrientationLocked(); 3817 3818 if (req != mForcedAppOrientation) { 3819 mForcedAppOrientation = req; 3820 //send a message to Policy indicating orientation change to take 3821 //action like disabling/enabling sensors etc., 3822 mPolicy.setCurrentOrientationLw(req); 3823 if (updateRotationUncheckedLocked(inTransaction)) { 3824 // changed 3825 return true; 3826 } 3827 } 3828 3829 return false; 3830 } finally { 3831 Binder.restoreCallingIdentity(ident); 3832 } 3833 } 3834 3835 int computeForcedAppOrientationLocked() { 3836 int req = getOrientationFromWindowsLocked(); 3837 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { 3838 req = getOrientationFromAppTokensLocked(); 3839 } 3840 return req; 3841 } 3842 3843 @Override 3844 public void setNewConfiguration(Configuration config) { 3845 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3846 "setNewConfiguration()")) { 3847 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3848 } 3849 3850 synchronized(mWindowMap) { 3851 mCurConfiguration = new Configuration(config); 3852 mWaitingForConfig = false; 3853 performLayoutAndPlaceSurfacesLocked(); 3854 } 3855 } 3856 3857 @Override 3858 public void setAppOrientation(IApplicationToken token, int requestedOrientation) { 3859 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3860 "setAppOrientation()")) { 3861 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3862 } 3863 3864 synchronized(mWindowMap) { 3865 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 3866 if (wtoken == null) { 3867 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token); 3868 return; 3869 } 3870 3871 wtoken.requestedOrientation = requestedOrientation; 3872 } 3873 } 3874 3875 public int getAppOrientation(IApplicationToken token) { 3876 synchronized(mWindowMap) { 3877 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 3878 if (wtoken == null) { 3879 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3880 } 3881 3882 return wtoken.requestedOrientation; 3883 } 3884 } 3885 3886 public void setFocusedApp(IBinder token, boolean moveFocusNow) { 3887 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3888 "setFocusedApp()")) { 3889 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3890 } 3891 3892 synchronized(mWindowMap) { 3893 boolean changed = false; 3894 if (token == null) { 3895 if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); 3896 changed = mFocusedApp != null; 3897 mFocusedApp = null; 3898 if (changed) { 3899 mInputMonitor.setFocusedAppLw(null); 3900 } 3901 } else { 3902 AppWindowToken newFocus = findAppWindowToken(token); 3903 if (newFocus == null) { 3904 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); 3905 return; 3906 } 3907 changed = mFocusedApp != newFocus; 3908 mFocusedApp = newFocus; 3909 if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp); 3910 if (changed) { 3911 mInputMonitor.setFocusedAppLw(newFocus); 3912 } 3913 } 3914 3915 if (moveFocusNow && changed) { 3916 final long origId = Binder.clearCallingIdentity(); 3917 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 3918 Binder.restoreCallingIdentity(origId); 3919 } 3920 } 3921 } 3922 3923 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { 3924 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3925 "prepareAppTransition()")) { 3926 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3927 } 3928 3929 synchronized(mWindowMap) { 3930 if (DEBUG_APP_TRANSITIONS) Slog.v( 3931 TAG, "Prepare app transition: transit=" + transit 3932 + " mNextAppTransition=" + mNextAppTransition 3933 + " alwaysKeepCurrent=" + alwaysKeepCurrent 3934 + " Callers=" + Debug.getCallers(3)); 3935 if (okToDisplay()) { 3936 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET 3937 || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) { 3938 mNextAppTransition = transit; 3939 } else if (!alwaysKeepCurrent) { 3940 if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN 3941 && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) { 3942 // Opening a new task always supersedes a close for the anim. 3943 mNextAppTransition = transit; 3944 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN 3945 && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) { 3946 // Opening a new activity always supersedes a close for the anim. 3947 mNextAppTransition = transit; 3948 } 3949 } 3950 mAppTransitionReady = false; 3951 mAppTransitionTimeout = false; 3952 mStartingIconInTransition = false; 3953 mSkipAppTransitionAnimation = false; 3954 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 3955 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT), 3956 5000); 3957 } 3958 } 3959 } 3960 3961 public int getPendingAppTransition() { 3962 return mNextAppTransition; 3963 } 3964 3965 private void scheduleAnimationCallback(IRemoteCallback cb) { 3966 if (cb != null) { 3967 mH.sendMessage(mH.obtainMessage(H.DO_ANIMATION_CALLBACK, cb)); 3968 } 3969 } 3970 3971 public void overridePendingAppTransition(String packageName, 3972 int enterAnim, int exitAnim, IRemoteCallback startedCallback) { 3973 synchronized(mWindowMap) { 3974 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 3975 mNextAppTransitionType = ActivityOptions.ANIM_CUSTOM; 3976 mNextAppTransitionPackage = packageName; 3977 mNextAppTransitionThumbnail = null; 3978 mNextAppTransitionEnter = enterAnim; 3979 mNextAppTransitionExit = exitAnim; 3980 scheduleAnimationCallback(mNextAppTransitionCallback); 3981 mNextAppTransitionCallback = startedCallback; 3982 } else { 3983 scheduleAnimationCallback(startedCallback); 3984 } 3985 } 3986 } 3987 3988 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 3989 int startHeight) { 3990 synchronized(mWindowMap) { 3991 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 3992 mNextAppTransitionType = ActivityOptions.ANIM_SCALE_UP; 3993 mNextAppTransitionPackage = null; 3994 mNextAppTransitionThumbnail = null; 3995 mNextAppTransitionStartX = startX; 3996 mNextAppTransitionStartY = startY; 3997 mNextAppTransitionStartWidth = startWidth; 3998 mNextAppTransitionStartHeight = startHeight; 3999 scheduleAnimationCallback(mNextAppTransitionCallback); 4000 mNextAppTransitionCallback = null; 4001 } 4002 } 4003 } 4004 4005 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, 4006 int startY, IRemoteCallback startedCallback, boolean delayed) { 4007 synchronized(mWindowMap) { 4008 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4009 mNextAppTransitionType = delayed 4010 ? ActivityOptions.ANIM_THUMBNAIL_DELAYED : ActivityOptions.ANIM_THUMBNAIL; 4011 mNextAppTransitionPackage = null; 4012 mNextAppTransitionThumbnail = srcThumb; 4013 mNextAppTransitionDelayed = delayed; 4014 mNextAppTransitionStartX = startX; 4015 mNextAppTransitionStartY = startY; 4016 scheduleAnimationCallback(mNextAppTransitionCallback); 4017 mNextAppTransitionCallback = startedCallback; 4018 } else { 4019 scheduleAnimationCallback(startedCallback); 4020 } 4021 } 4022 } 4023 4024 public void executeAppTransition() { 4025 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4026 "executeAppTransition()")) { 4027 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4028 } 4029 4030 synchronized(mWindowMap) { 4031 if (DEBUG_APP_TRANSITIONS) { 4032 RuntimeException e = new RuntimeException("here"); 4033 e.fillInStackTrace(); 4034 Slog.w(TAG, "Execute app transition: mNextAppTransition=" 4035 + mNextAppTransition, e); 4036 } 4037 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4038 mAppTransitionReady = true; 4039 final long origId = Binder.clearCallingIdentity(); 4040 performLayoutAndPlaceSurfacesLocked(); 4041 Binder.restoreCallingIdentity(origId); 4042 } 4043 } 4044 } 4045 4046 public void setAppStartingWindow(IBinder token, String pkg, 4047 int theme, CompatibilityInfo compatInfo, 4048 CharSequence nonLocalizedLabel, int labelRes, int icon, 4049 int windowFlags, IBinder transferFrom, boolean createIfNeeded) { 4050 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4051 "setAppStartingWindow()")) { 4052 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4053 } 4054 4055 synchronized(mWindowMap) { 4056 if (DEBUG_STARTING_WINDOW) Slog.v( 4057 TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg 4058 + " transferFrom=" + transferFrom); 4059 4060 AppWindowToken wtoken = findAppWindowToken(token); 4061 if (wtoken == null) { 4062 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token); 4063 return; 4064 } 4065 4066 // If the display is frozen, we won't do anything until the 4067 // actual window is displayed so there is no reason to put in 4068 // the starting window. 4069 if (!okToDisplay()) { 4070 return; 4071 } 4072 4073 if (wtoken.startingData != null) { 4074 return; 4075 } 4076 4077 if (transferFrom != null) { 4078 AppWindowToken ttoken = findAppWindowToken(transferFrom); 4079 if (ttoken != null) { 4080 WindowState startingWindow = ttoken.startingWindow; 4081 if (startingWindow != null) { 4082 if (mStartingIconInTransition) { 4083 // In this case, the starting icon has already 4084 // been displayed, so start letting windows get 4085 // shown immediately without any more transitions. 4086 mSkipAppTransitionAnimation = true; 4087 } 4088 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4089 "Moving existing starting from " + ttoken 4090 + " to " + wtoken); 4091 final long origId = Binder.clearCallingIdentity(); 4092 4093 // Transfer the starting window over to the new 4094 // token. 4095 wtoken.startingData = ttoken.startingData; 4096 wtoken.startingView = ttoken.startingView; 4097 wtoken.startingDisplayed = ttoken.startingDisplayed; 4098 wtoken.startingWindow = startingWindow; 4099 wtoken.reportedVisible = ttoken.reportedVisible; 4100 ttoken.startingData = null; 4101 ttoken.startingView = null; 4102 ttoken.startingWindow = null; 4103 ttoken.startingMoved = true; 4104 startingWindow.mToken = wtoken; 4105 startingWindow.mRootToken = wtoken; 4106 startingWindow.mAppToken = wtoken; 4107 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { 4108 Slog.v(TAG, "Removing starting window: " + startingWindow); 4109 } 4110 mWindows.remove(startingWindow); 4111 mWindowsChanged = true; 4112 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 4113 "Removing starting " + startingWindow + " from " + ttoken); 4114 ttoken.windows.remove(startingWindow); 4115 ttoken.allAppWindows.remove(startingWindow); 4116 addWindowToListInOrderLocked(startingWindow, true); 4117 4118 // Propagate other interesting state between the 4119 // tokens. If the old token is displayed, we should 4120 // immediately force the new one to be displayed. If 4121 // it is animating, we need to move that animation to 4122 // the new one. 4123 if (ttoken.allDrawn) { 4124 wtoken.allDrawn = true; 4125 } 4126 if (ttoken.firstWindowDrawn) { 4127 wtoken.firstWindowDrawn = true; 4128 } 4129 if (!ttoken.hidden) { 4130 wtoken.hidden = false; 4131 wtoken.hiddenRequested = false; 4132 wtoken.willBeHidden = false; 4133 } 4134 if (wtoken.clientHidden != ttoken.clientHidden) { 4135 wtoken.clientHidden = ttoken.clientHidden; 4136 wtoken.sendAppVisibilityToClients(); 4137 } 4138 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4139 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4140 if (tAppAnimator.animation != null) { 4141 wAppAnimator.animation = tAppAnimator.animation; 4142 wAppAnimator.animating = tAppAnimator.animating; 4143 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; 4144 tAppAnimator.animation = null; 4145 tAppAnimator.animLayerAdjustment = 0; 4146 wAppAnimator.updateLayers(); 4147 tAppAnimator.updateLayers(); 4148 } 4149 4150 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4151 true /*updateInputWindows*/); 4152 mLayoutNeeded = true; 4153 performLayoutAndPlaceSurfacesLocked(); 4154 Binder.restoreCallingIdentity(origId); 4155 return; 4156 } else if (ttoken.startingData != null) { 4157 // The previous app was getting ready to show a 4158 // starting window, but hasn't yet done so. Steal it! 4159 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4160 "Moving pending starting from " + ttoken 4161 + " to " + wtoken); 4162 wtoken.startingData = ttoken.startingData; 4163 ttoken.startingData = null; 4164 ttoken.startingMoved = true; 4165 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4166 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4167 // want to process the message ASAP, before any other queued 4168 // messages. 4169 mH.sendMessageAtFrontOfQueue(m); 4170 return; 4171 } 4172 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4173 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4174 if (tAppAnimator.thumbnail != null) { 4175 // The old token is animating with a thumbnail, transfer 4176 // that to the new token. 4177 if (wAppAnimator.thumbnail != null) { 4178 wAppAnimator.thumbnail.destroy(); 4179 } 4180 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 4181 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX; 4182 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY; 4183 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 4184 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 4185 tAppAnimator.thumbnail = null; 4186 } 4187 } 4188 } 4189 4190 // There is no existing starting window, and the caller doesn't 4191 // want us to create one, so that's it! 4192 if (!createIfNeeded) { 4193 return; 4194 } 4195 4196 // If this is a translucent window, then don't 4197 // show a starting window -- the current effect (a full-screen 4198 // opaque starting window that fades away to the real contents 4199 // when it is ready) does not work for this. 4200 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x" 4201 + Integer.toHexString(theme)); 4202 if (theme != 0) { 4203 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 4204 com.android.internal.R.styleable.Window); 4205 if (ent == null) { 4206 // Whoops! App doesn't exist. Um. Okay. We'll just 4207 // pretend like we didn't see that. 4208 return; 4209 } 4210 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent=" 4211 + ent.array.getBoolean( 4212 com.android.internal.R.styleable.Window_windowIsTranslucent, false) 4213 + " Floating=" 4214 + ent.array.getBoolean( 4215 com.android.internal.R.styleable.Window_windowIsFloating, false) 4216 + " ShowWallpaper=" 4217 + ent.array.getBoolean( 4218 com.android.internal.R.styleable.Window_windowShowWallpaper, false)); 4219 if (ent.array.getBoolean( 4220 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { 4221 return; 4222 } 4223 if (ent.array.getBoolean( 4224 com.android.internal.R.styleable.Window_windowIsFloating, false)) { 4225 return; 4226 } 4227 if (ent.array.getBoolean( 4228 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { 4229 if (mWallpaperTarget == null) { 4230 // If this theme is requesting a wallpaper, and the wallpaper 4231 // is not curently visible, then this effectively serves as 4232 // an opaque window and our starting window transition animation 4233 // can still work. We just need to make sure the starting window 4234 // is also showing the wallpaper. 4235 windowFlags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 4236 } else { 4237 return; 4238 } 4239 } 4240 } 4241 4242 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); 4243 mStartingIconInTransition = true; 4244 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, 4245 labelRes, icon, windowFlags); 4246 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4247 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4248 // want to process the message ASAP, before any other queued 4249 // messages. 4250 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING"); 4251 mH.sendMessageAtFrontOfQueue(m); 4252 } 4253 } 4254 4255 public void setAppWillBeHidden(IBinder token) { 4256 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4257 "setAppWillBeHidden()")) { 4258 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4259 } 4260 4261 AppWindowToken wtoken; 4262 4263 synchronized(mWindowMap) { 4264 wtoken = findAppWindowToken(token); 4265 if (wtoken == null) { 4266 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token); 4267 return; 4268 } 4269 wtoken.willBeHidden = true; 4270 } 4271 } 4272 4273 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4274 boolean visible, int transit, boolean performLayout) { 4275 boolean delayed = false; 4276 4277 if (wtoken.clientHidden == visible) { 4278 wtoken.clientHidden = !visible; 4279 wtoken.sendAppVisibilityToClients(); 4280 } 4281 4282 wtoken.willBeHidden = false; 4283 if (wtoken.hidden == visible) { 4284 boolean changed = false; 4285 if (DEBUG_APP_TRANSITIONS) Slog.v( 4286 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4287 + " performLayout=" + performLayout); 4288 4289 boolean runningAppAnimation = false; 4290 4291 if (transit != WindowManagerPolicy.TRANSIT_UNSET) { 4292 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4293 wtoken.mAppAnimator.animation = null; 4294 } 4295 if (applyAnimationLocked(wtoken, lp, transit, visible)) { 4296 delayed = runningAppAnimation = true; 4297 } 4298 changed = true; 4299 } 4300 4301 final int N = wtoken.allAppWindows.size(); 4302 for (int i=0; i<N; i++) { 4303 WindowState win = wtoken.allAppWindows.get(i); 4304 if (win == wtoken.startingWindow) { 4305 continue; 4306 } 4307 4308 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); 4309 //win.dump(" "); 4310 if (visible) { 4311 if (!win.isVisibleNow()) { 4312 if (!runningAppAnimation) { 4313 win.mWinAnimator.applyAnimationLocked( 4314 WindowManagerPolicy.TRANSIT_ENTER, true); 4315 } 4316 changed = true; 4317 } 4318 } else if (win.isVisibleNow()) { 4319 if (!runningAppAnimation) { 4320 win.mWinAnimator.applyAnimationLocked( 4321 WindowManagerPolicy.TRANSIT_EXIT, false); 4322 } 4323 changed = true; 4324 } 4325 } 4326 4327 wtoken.hidden = wtoken.hiddenRequested = !visible; 4328 if (!visible) { 4329 unsetAppFreezingScreenLocked(wtoken, true, true); 4330 } else { 4331 // If we are being set visible, and the starting window is 4332 // not yet displayed, then make sure it doesn't get displayed. 4333 WindowState swin = wtoken.startingWindow; 4334 if (swin != null && !swin.isDrawnLw()) { 4335 swin.mPolicyVisibility = false; 4336 swin.mPolicyVisibilityAfterAnim = false; 4337 } 4338 } 4339 4340 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken 4341 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4342 + wtoken.hiddenRequested); 4343 4344 if (changed) { 4345 mLayoutNeeded = true; 4346 mInputMonitor.setUpdateInputWindowsNeededLw(); 4347 if (performLayout) { 4348 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4349 false /*updateInputWindows*/); 4350 performLayoutAndPlaceSurfacesLocked(); 4351 } 4352 mInputMonitor.updateInputWindowsLw(false /*force*/); 4353 } 4354 } 4355 4356 if (wtoken.mAppAnimator.animation != null) { 4357 delayed = true; 4358 } 4359 4360 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4361 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { 4362 delayed = true; 4363 } 4364 } 4365 4366 return delayed; 4367 } 4368 4369 public void setAppVisibility(IBinder token, boolean visible) { 4370 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4371 "setAppVisibility()")) { 4372 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4373 } 4374 4375 AppWindowToken wtoken; 4376 4377 synchronized(mWindowMap) { 4378 wtoken = findAppWindowToken(token); 4379 if (wtoken == null) { 4380 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); 4381 return; 4382 } 4383 4384 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) { 4385 RuntimeException e = null; 4386 if (!HIDE_STACK_CRAWLS) { 4387 e = new RuntimeException(); 4388 e.fillInStackTrace(); 4389 } 4390 Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible 4391 + "): mNextAppTransition=" + mNextAppTransition 4392 + " hidden=" + wtoken.hidden 4393 + " hiddenRequested=" + wtoken.hiddenRequested, e); 4394 } 4395 4396 // If we are preparing an app transition, then delay changing 4397 // the visibility of this token until we execute that transition. 4398 if (okToDisplay() && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4399 // Already in requested state, don't do anything more. 4400 if (wtoken.hiddenRequested != visible) { 4401 return; 4402 } 4403 wtoken.hiddenRequested = !visible; 4404 4405 if (DEBUG_APP_TRANSITIONS) Slog.v( 4406 TAG, "Setting dummy animation on: " + wtoken); 4407 if (!wtoken.startingDisplayed) { 4408 wtoken.mAppAnimator.setDummyAnimation(); 4409 } 4410 mOpeningApps.remove(wtoken); 4411 mClosingApps.remove(wtoken); 4412 wtoken.waitingToShow = wtoken.waitingToHide = false; 4413 wtoken.inPendingTransaction = true; 4414 if (visible) { 4415 mOpeningApps.add(wtoken); 4416 wtoken.startingMoved = false; 4417 4418 // If the token is currently hidden (should be the 4419 // common case), then we need to set up to wait for 4420 // its windows to be ready. 4421 if (wtoken.hidden) { 4422 wtoken.allDrawn = false; 4423 wtoken.waitingToShow = true; 4424 4425 if (wtoken.clientHidden) { 4426 // In the case where we are making an app visible 4427 // but holding off for a transition, we still need 4428 // to tell the client to make its windows visible so 4429 // they get drawn. Otherwise, we will wait on 4430 // performing the transition until all windows have 4431 // been drawn, they never will be, and we are sad. 4432 wtoken.clientHidden = false; 4433 wtoken.sendAppVisibilityToClients(); 4434 } 4435 } 4436 } else { 4437 mClosingApps.add(wtoken); 4438 4439 // If the token is currently visible (should be the 4440 // common case), then set up to wait for it to be hidden. 4441 if (!wtoken.hidden) { 4442 wtoken.waitingToHide = true; 4443 } 4444 } 4445 return; 4446 } 4447 4448 final long origId = Binder.clearCallingIdentity(); 4449 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, 4450 true); 4451 wtoken.updateReportedVisibilityLocked(); 4452 Binder.restoreCallingIdentity(origId); 4453 } 4454 } 4455 4456 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4457 boolean unfreezeSurfaceNow, boolean force) { 4458 if (wtoken.mAppAnimator.freezingScreen) { 4459 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken 4460 + " force=" + force); 4461 final int N = wtoken.allAppWindows.size(); 4462 boolean unfrozeWindows = false; 4463 for (int i=0; i<N; i++) { 4464 WindowState w = wtoken.allAppWindows.get(i); 4465 if (w.mAppFreezing) { 4466 w.mAppFreezing = false; 4467 if (w.mHasSurface && !w.mOrientationChanging) { 4468 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); 4469 w.mOrientationChanging = true; 4470 mInnerFields.mOrientationChangeComplete = false; 4471 } 4472 unfrozeWindows = true; 4473 } 4474 } 4475 if (force || unfrozeWindows) { 4476 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); 4477 wtoken.mAppAnimator.freezingScreen = false; 4478 mAppsFreezingScreen--; 4479 } 4480 if (unfreezeSurfaceNow) { 4481 if (unfrozeWindows) { 4482 mLayoutNeeded = true; 4483 performLayoutAndPlaceSurfacesLocked(); 4484 } 4485 stopFreezingDisplayLocked(); 4486 } 4487 } 4488 } 4489 4490 public void startAppFreezingScreenLocked(AppWindowToken wtoken, 4491 int configChanges) { 4492 if (DEBUG_ORIENTATION) { 4493 RuntimeException e = null; 4494 if (!HIDE_STACK_CRAWLS) { 4495 e = new RuntimeException(); 4496 e.fillInStackTrace(); 4497 } 4498 Slog.i(TAG, "Set freezing of " + wtoken.appToken 4499 + ": hidden=" + wtoken.hidden + " freezing=" 4500 + wtoken.mAppAnimator.freezingScreen, e); 4501 } 4502 if (!wtoken.hiddenRequested) { 4503 if (!wtoken.mAppAnimator.freezingScreen) { 4504 wtoken.mAppAnimator.freezingScreen = true; 4505 mAppsFreezingScreen++; 4506 if (mAppsFreezingScreen == 1) { 4507 startFreezingDisplayLocked(false); 4508 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4509 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT), 4510 5000); 4511 } 4512 } 4513 final int N = wtoken.allAppWindows.size(); 4514 for (int i=0; i<N; i++) { 4515 WindowState w = wtoken.allAppWindows.get(i); 4516 w.mAppFreezing = true; 4517 } 4518 } 4519 } 4520 4521 public void startAppFreezingScreen(IBinder token, int configChanges) { 4522 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4523 "setAppFreezingScreen()")) { 4524 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4525 } 4526 4527 synchronized(mWindowMap) { 4528 if (configChanges == 0 && okToDisplay()) { 4529 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); 4530 return; 4531 } 4532 4533 AppWindowToken wtoken = findAppWindowToken(token); 4534 if (wtoken == null || wtoken.appToken == null) { 4535 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); 4536 return; 4537 } 4538 final long origId = Binder.clearCallingIdentity(); 4539 startAppFreezingScreenLocked(wtoken, configChanges); 4540 Binder.restoreCallingIdentity(origId); 4541 } 4542 } 4543 4544 public void stopAppFreezingScreen(IBinder token, boolean force) { 4545 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4546 "setAppFreezingScreen()")) { 4547 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4548 } 4549 4550 synchronized(mWindowMap) { 4551 AppWindowToken wtoken = findAppWindowToken(token); 4552 if (wtoken == null || wtoken.appToken == null) { 4553 return; 4554 } 4555 final long origId = Binder.clearCallingIdentity(); 4556 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token 4557 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4558 unsetAppFreezingScreenLocked(wtoken, true, force); 4559 Binder.restoreCallingIdentity(origId); 4560 } 4561 } 4562 4563 public void removeAppToken(IBinder token) { 4564 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4565 "removeAppToken()")) { 4566 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4567 } 4568 4569 AppWindowToken wtoken = null; 4570 AppWindowToken startingToken = null; 4571 boolean delayed = false; 4572 4573 final long origId = Binder.clearCallingIdentity(); 4574 synchronized(mWindowMap) { 4575 WindowToken basewtoken = mTokenMap.remove(token); 4576 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4577 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); 4578 delayed = setTokenVisibilityLocked(wtoken, null, false, 4579 WindowManagerPolicy.TRANSIT_UNSET, true); 4580 wtoken.inPendingTransaction = false; 4581 mOpeningApps.remove(wtoken); 4582 wtoken.waitingToShow = false; 4583 if (mClosingApps.contains(wtoken)) { 4584 delayed = true; 4585 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4586 mClosingApps.add(wtoken); 4587 wtoken.waitingToHide = true; 4588 delayed = true; 4589 } 4590 if (DEBUG_APP_TRANSITIONS) Slog.v( 4591 TAG, "Removing app " + wtoken + " delayed=" + delayed 4592 + " animation=" + wtoken.mAppAnimator.animation 4593 + " animating=" + wtoken.mAppAnimator.animating); 4594 if (delayed) { 4595 // set the token aside because it has an active animation to be finished 4596 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4597 "removeAppToken make exiting: " + wtoken); 4598 mExitingAppTokens.add(wtoken); 4599 } else { 4600 // Make sure there is no animation running on this token, 4601 // so any windows associated with it will be removed as 4602 // soon as their animations are complete 4603 wtoken.mAppAnimator.clearAnimation(); 4604 wtoken.mAppAnimator.animating = false; 4605 } 4606 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4607 "removeAppToken: " + wtoken); 4608 mAppTokens.remove(wtoken); 4609 mAnimatingAppTokens.remove(wtoken); 4610 wtoken.removed = true; 4611 if (wtoken.startingData != null) { 4612 startingToken = wtoken; 4613 } 4614 unsetAppFreezingScreenLocked(wtoken, true, true); 4615 if (mFocusedApp == wtoken) { 4616 if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken); 4617 mFocusedApp = null; 4618 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4619 mInputMonitor.setFocusedAppLw(null); 4620 } 4621 } else { 4622 Slog.w(TAG, "Attempted to remove non-existing app token: " + token); 4623 } 4624 4625 if (!delayed && wtoken != null) { 4626 wtoken.updateReportedVisibilityLocked(); 4627 } 4628 } 4629 Binder.restoreCallingIdentity(origId); 4630 4631 if (startingToken != null) { 4632 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting " 4633 + startingToken + ": app token removed"); 4634 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken); 4635 mH.sendMessage(m); 4636 } 4637 } 4638 4639 private boolean tmpRemoveAppWindowsLocked(WindowToken token) { 4640 final int NW = token.windows.size(); 4641 if (NW > 0) { 4642 mWindowsChanged = true; 4643 } 4644 for (int i=0; i<NW; i++) { 4645 WindowState win = token.windows.get(i); 4646 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); 4647 mWindows.remove(win); 4648 int j = win.mChildWindows.size(); 4649 while (j > 0) { 4650 j--; 4651 WindowState cwin = win.mChildWindows.get(j); 4652 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 4653 "Tmp removing child window " + cwin); 4654 mWindows.remove(cwin); 4655 } 4656 } 4657 return NW > 0; 4658 } 4659 4660 void dumpAppTokensLocked() { 4661 for (int i=mAppTokens.size()-1; i>=0; i--) { 4662 Slog.v(TAG, " #" + i + ": " + mAppTokens.get(i).token); 4663 } 4664 } 4665 4666 void dumpAnimatingAppTokensLocked() { 4667 for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) { 4668 Slog.v(TAG, " #" + i + ": " + mAnimatingAppTokens.get(i).token); 4669 } 4670 } 4671 4672 void dumpWindowsLocked() { 4673 for (int i=mWindows.size()-1; i>=0; i--) { 4674 Slog.v(TAG, " #" + i + ": " + mWindows.get(i)); 4675 } 4676 } 4677 4678 private int findWindowOffsetLocked(int tokenPos) { 4679 final int NW = mWindows.size(); 4680 4681 if (tokenPos >= mAnimatingAppTokens.size()) { 4682 int i = NW; 4683 while (i > 0) { 4684 i--; 4685 WindowState win = mWindows.get(i); 4686 if (win.getAppToken() != null) { 4687 return i+1; 4688 } 4689 } 4690 } 4691 4692 while (tokenPos > 0) { 4693 // Find the first app token below the new position that has 4694 // a window displayed. 4695 final AppWindowToken wtoken = mAnimatingAppTokens.get(tokenPos-1); 4696 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ " 4697 + tokenPos + " -- " + wtoken.token); 4698 if (wtoken.sendingToBottom) { 4699 if (DEBUG_REORDER) Slog.v(TAG, 4700 "Skipping token -- currently sending to bottom"); 4701 tokenPos--; 4702 continue; 4703 } 4704 int i = wtoken.windows.size(); 4705 while (i > 0) { 4706 i--; 4707 WindowState win = wtoken.windows.get(i); 4708 int j = win.mChildWindows.size(); 4709 while (j > 0) { 4710 j--; 4711 WindowState cwin = win.mChildWindows.get(j); 4712 if (cwin.mSubLayer >= 0) { 4713 for (int pos=NW-1; pos>=0; pos--) { 4714 if (mWindows.get(pos) == cwin) { 4715 if (DEBUG_REORDER) Slog.v(TAG, 4716 "Found child win @" + (pos+1)); 4717 return pos+1; 4718 } 4719 } 4720 } 4721 } 4722 for (int pos=NW-1; pos>=0; pos--) { 4723 if (mWindows.get(pos) == win) { 4724 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1)); 4725 return pos+1; 4726 } 4727 } 4728 } 4729 tokenPos--; 4730 } 4731 4732 return 0; 4733 } 4734 4735 private final int reAddWindowLocked(int index, WindowState win) { 4736 final int NCW = win.mChildWindows.size(); 4737 boolean added = false; 4738 for (int j=0; j<NCW; j++) { 4739 WindowState cwin = win.mChildWindows.get(j); 4740 if (!added && cwin.mSubLayer >= 0) { 4741 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " 4742 + index + ": " + cwin); 4743 win.mRebuilding = false; 4744 mWindows.add(index, win); 4745 index++; 4746 added = true; 4747 } 4748 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4749 + index + ": " + cwin); 4750 cwin.mRebuilding = false; 4751 mWindows.add(index, cwin); 4752 index++; 4753 } 4754 if (!added) { 4755 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4756 + index + ": " + win); 4757 win.mRebuilding = false; 4758 mWindows.add(index, win); 4759 index++; 4760 } 4761 mWindowsChanged = true; 4762 return index; 4763 } 4764 4765 private final int reAddAppWindowsLocked(int index, WindowToken token) { 4766 final int NW = token.windows.size(); 4767 for (int i=0; i<NW; i++) { 4768 index = reAddWindowLocked(index, token.windows.get(i)); 4769 } 4770 return index; 4771 } 4772 4773 public void moveAppToken(int index, IBinder token) { 4774 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4775 "moveAppToken()")) { 4776 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4777 } 4778 4779 synchronized(mWindowMap) { 4780 if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:"); 4781 if (DEBUG_REORDER) dumpAppTokensLocked(); 4782 final AppWindowToken wtoken = findAppWindowToken(token); 4783 final int oldIndex = mAppTokens.indexOf(wtoken); 4784 if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG, 4785 "Start moving token " + wtoken + " initially at " 4786 + oldIndex); 4787 if (oldIndex > index && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET 4788 && !mAppTransitionRunning) { 4789 // animation towards back has not started, copy old list for duration of animation. 4790 mAnimatingAppTokens.clear(); 4791 mAnimatingAppTokens.addAll(mAppTokens); 4792 } 4793 if (wtoken == null || !mAppTokens.remove(wtoken)) { 4794 Slog.w(TAG, "Attempting to reorder token that doesn't exist: " 4795 + token + " (" + wtoken + ")"); 4796 return; 4797 } 4798 mAppTokens.add(index, wtoken); 4799 if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":"); 4800 else if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "Moved " + token + " to " + index); 4801 if (DEBUG_REORDER) dumpAppTokensLocked(); 4802 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET && !mAppTransitionRunning) { 4803 // Not animating, bring animating app list in line with mAppTokens. 4804 mAnimatingAppTokens.clear(); 4805 mAnimatingAppTokens.addAll(mAppTokens); 4806 4807 // Bring window ordering, window focus and input window in line with new app token 4808 final long origId = Binder.clearCallingIdentity(); 4809 if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":"); 4810 if (DEBUG_REORDER) dumpWindowsLocked(); 4811 if (tmpRemoveAppWindowsLocked(wtoken)) { 4812 if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:"); 4813 if (DEBUG_REORDER) dumpWindowsLocked(); 4814 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken); 4815 if (DEBUG_REORDER) Slog.v(TAG, "Final window list:"); 4816 if (DEBUG_REORDER) dumpWindowsLocked(); 4817 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4818 false /*updateInputWindows*/); 4819 mLayoutNeeded = true; 4820 mInputMonitor.setUpdateInputWindowsNeededLw(); 4821 performLayoutAndPlaceSurfacesLocked(); 4822 mInputMonitor.updateInputWindowsLw(false /*force*/); 4823 } 4824 Binder.restoreCallingIdentity(origId); 4825 } 4826 } 4827 } 4828 4829 private void removeAppTokensLocked(List<IBinder> tokens) { 4830 // XXX This should be done more efficiently! 4831 // (take advantage of the fact that both lists should be 4832 // ordered in the same way.) 4833 int N = tokens.size(); 4834 for (int i=0; i<N; i++) { 4835 IBinder token = tokens.get(i); 4836 final AppWindowToken wtoken = findAppWindowToken(token); 4837 if (DEBUG_REORDER || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4838 "Temporarily removing " + wtoken + " from " + mAppTokens.indexOf(wtoken)); 4839 if (!mAppTokens.remove(wtoken)) { 4840 Slog.w(TAG, "Attempting to reorder token that doesn't exist: " 4841 + token + " (" + wtoken + ")"); 4842 i--; 4843 N--; 4844 } 4845 } 4846 } 4847 4848 private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos, 4849 boolean updateFocusAndLayout) { 4850 // First remove all of the windows from the list. 4851 tmpRemoveAppWindowsLocked(wtoken); 4852 4853 // Where to start adding? 4854 int pos = findWindowOffsetLocked(tokenPos); 4855 4856 // And now add them back at the correct place. 4857 pos = reAddAppWindowsLocked(pos, wtoken); 4858 4859 if (updateFocusAndLayout) { 4860 mInputMonitor.setUpdateInputWindowsNeededLw(); 4861 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4862 false /*updateInputWindows*/)) { 4863 assignLayersLocked(); 4864 } 4865 mLayoutNeeded = true; 4866 if (!mInLayout) { 4867 performLayoutAndPlaceSurfacesLocked(); 4868 } 4869 mInputMonitor.updateInputWindowsLw(false /*force*/); 4870 } 4871 } 4872 4873 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) { 4874 // First remove all of the windows from the list. 4875 final int N = tokens.size(); 4876 int i; 4877 for (i=0; i<N; i++) { 4878 WindowToken token = mTokenMap.get(tokens.get(i)); 4879 if (token != null) { 4880 tmpRemoveAppWindowsLocked(token); 4881 } 4882 } 4883 4884 // Where to start adding? 4885 int pos = findWindowOffsetLocked(tokenPos); 4886 4887 // And now add them back at the correct place. 4888 for (i=0; i<N; i++) { 4889 WindowToken token = mTokenMap.get(tokens.get(i)); 4890 if (token != null) { 4891 pos = reAddAppWindowsLocked(pos, token); 4892 } 4893 } 4894 4895 mInputMonitor.setUpdateInputWindowsNeededLw(); 4896 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4897 false /*updateInputWindows*/)) { 4898 assignLayersLocked(); 4899 } 4900 mLayoutNeeded = true; 4901 performLayoutAndPlaceSurfacesLocked(); 4902 mInputMonitor.updateInputWindowsLw(false /*force*/); 4903 4904 //dump(); 4905 } 4906 4907 public void moveAppTokensToTop(List<IBinder> tokens) { 4908 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4909 "moveAppTokensToTop()")) { 4910 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4911 } 4912 4913 final long origId = Binder.clearCallingIdentity(); 4914 synchronized(mWindowMap) { 4915 removeAppTokensLocked(tokens); 4916 final int N = tokens.size(); 4917 for (int i=0; i<N; i++) { 4918 AppWindowToken wt = findAppWindowToken(tokens.get(i)); 4919 if (wt != null) { 4920 if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG, 4921 "Adding next to top: " + wt); 4922 mAppTokens.add(wt); 4923 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4924 wt.sendingToBottom = false; 4925 } 4926 } 4927 } 4928 4929 if (!mAppTransitionRunning) { 4930 mAnimatingAppTokens.clear(); 4931 mAnimatingAppTokens.addAll(mAppTokens); 4932 moveAppWindowsLocked(tokens, mAppTokens.size()); 4933 } 4934 } 4935 Binder.restoreCallingIdentity(origId); 4936 } 4937 4938 @Override 4939 public void moveAppTokensToBottom(List<IBinder> tokens) { 4940 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4941 "moveAppTokensToBottom()")) { 4942 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4943 } 4944 4945 final long origId = Binder.clearCallingIdentity(); 4946 synchronized(mWindowMap) { 4947 final int N = tokens.size(); 4948 if (N > 0 && !mAppTransitionRunning) { 4949 // animating towards back, hang onto old list for duration of animation. 4950 mAnimatingAppTokens.clear(); 4951 mAnimatingAppTokens.addAll(mAppTokens); 4952 } 4953 removeAppTokensLocked(tokens); 4954 int pos = 0; 4955 for (int i=0; i<N; i++) { 4956 AppWindowToken wt = findAppWindowToken(tokens.get(i)); 4957 if (wt != null) { 4958 if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4959 "Adding next to bottom: " + wt + " at " + pos); 4960 mAppTokens.add(pos, wt); 4961 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4962 wt.sendingToBottom = true; 4963 } 4964 pos++; 4965 } 4966 } 4967 4968 if (!mAppTransitionRunning) { 4969 mAnimatingAppTokens.clear(); 4970 mAnimatingAppTokens.addAll(mAppTokens); 4971 moveAppWindowsLocked(tokens, 0); 4972 } 4973 } 4974 Binder.restoreCallingIdentity(origId); 4975 } 4976 4977 // ------------------------------------------------------------- 4978 // Misc IWindowSession methods 4979 // ------------------------------------------------------------- 4980 4981 private boolean shouldAllowDisableKeyguard() 4982 { 4983 // We fail safe and prevent disabling keyguard in the unlikely event this gets 4984 // called before DevicePolicyManagerService has started. 4985 if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) { 4986 DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService( 4987 Context.DEVICE_POLICY_SERVICE); 4988 if (dpm != null) { 4989 mAllowDisableKeyguard = dpm.getPasswordQuality(null) 4990 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ? 4991 ALLOW_DISABLE_YES : ALLOW_DISABLE_NO; 4992 } 4993 } 4994 return mAllowDisableKeyguard == ALLOW_DISABLE_YES; 4995 } 4996 4997 public void disableKeyguard(IBinder token, String tag) { 4998 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 4999 != PackageManager.PERMISSION_GRANTED) { 5000 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5001 } 5002 5003 synchronized (mKeyguardTokenWatcher) { 5004 mKeyguardTokenWatcher.acquire(token, tag); 5005 } 5006 } 5007 5008 public void reenableKeyguard(IBinder token) { 5009 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5010 != PackageManager.PERMISSION_GRANTED) { 5011 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5012 } 5013 5014 synchronized (mKeyguardTokenWatcher) { 5015 mKeyguardTokenWatcher.release(token); 5016 5017 if (!mKeyguardTokenWatcher.isAcquired()) { 5018 // If we are the last one to reenable the keyguard wait until 5019 // we have actually finished reenabling until returning. 5020 // It is possible that reenableKeyguard() can be called before 5021 // the previous disableKeyguard() is handled, in which case 5022 // neither mKeyguardTokenWatcher.acquired() or released() would 5023 // be called. In that case mKeyguardDisabled will be false here 5024 // and we have nothing to wait for. 5025 while (mKeyguardDisabled) { 5026 try { 5027 mKeyguardTokenWatcher.wait(); 5028 } catch (InterruptedException e) { 5029 Thread.currentThread().interrupt(); 5030 } 5031 } 5032 } 5033 } 5034 } 5035 5036 /** 5037 * @see android.app.KeyguardManager#exitKeyguardSecurely 5038 */ 5039 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5040 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5041 != PackageManager.PERMISSION_GRANTED) { 5042 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5043 } 5044 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5045 public void onKeyguardExitResult(boolean success) { 5046 try { 5047 callback.onKeyguardExitResult(success); 5048 } catch (RemoteException e) { 5049 // Client has died, we don't care. 5050 } 5051 } 5052 }); 5053 } 5054 5055 public boolean inKeyguardRestrictedInputMode() { 5056 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5057 } 5058 5059 public boolean isKeyguardLocked() { 5060 return mPolicy.isKeyguardLocked(); 5061 } 5062 5063 public boolean isKeyguardSecure() { 5064 return mPolicy.isKeyguardSecure(); 5065 } 5066 5067 public void dismissKeyguard() { 5068 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5069 != PackageManager.PERMISSION_GRANTED) { 5070 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5071 } 5072 synchronized(mWindowMap) { 5073 mPolicy.dismissKeyguardLw(); 5074 } 5075 } 5076 5077 public void closeSystemDialogs(String reason) { 5078 synchronized(mWindowMap) { 5079 for (int i=mWindows.size()-1; i>=0; i--) { 5080 WindowState w = mWindows.get(i); 5081 if (w.mHasSurface) { 5082 try { 5083 w.mClient.closeSystemDialogs(reason); 5084 } catch (RemoteException e) { 5085 } 5086 } 5087 } 5088 } 5089 } 5090 5091 static float fixScale(float scale) { 5092 if (scale < 0) scale = 0; 5093 else if (scale > 20) scale = 20; 5094 return Math.abs(scale); 5095 } 5096 5097 public void setAnimationScale(int which, float scale) { 5098 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5099 "setAnimationScale()")) { 5100 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5101 } 5102 5103 if (scale < 0) scale = 0; 5104 else if (scale > 20) scale = 20; 5105 scale = Math.abs(scale); 5106 switch (which) { 5107 case 0: mWindowAnimationScale = fixScale(scale); break; 5108 case 1: mTransitionAnimationScale = fixScale(scale); break; 5109 case 2: mAnimatorDurationScale = fixScale(scale); break; 5110 } 5111 5112 // Persist setting 5113 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget(); 5114 } 5115 5116 public void setAnimationScales(float[] scales) { 5117 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5118 "setAnimationScale()")) { 5119 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5120 } 5121 5122 if (scales != null) { 5123 if (scales.length >= 1) { 5124 mWindowAnimationScale = fixScale(scales[0]); 5125 } 5126 if (scales.length >= 2) { 5127 mTransitionAnimationScale = fixScale(scales[1]); 5128 } 5129 if (scales.length >= 3) { 5130 mAnimatorDurationScale = fixScale(scales[2]); 5131 } 5132 } 5133 5134 // Persist setting 5135 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget(); 5136 } 5137 5138 public float getAnimationScale(int which) { 5139 switch (which) { 5140 case 0: return mWindowAnimationScale; 5141 case 1: return mTransitionAnimationScale; 5142 case 2: return mAnimatorDurationScale; 5143 } 5144 return 0; 5145 } 5146 5147 public float[] getAnimationScales() { 5148 return new float[] { mWindowAnimationScale, mTransitionAnimationScale, 5149 mAnimatorDurationScale }; 5150 } 5151 5152 // Called by window manager policy. Not exposed externally. 5153 @Override 5154 public int getLidState() { 5155 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5156 InputManagerService.SW_LID); 5157 if (sw > 0) { 5158 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5159 return LID_CLOSED; 5160 } else if (sw == 0) { 5161 // Switch state: AKEY_STATE_UP. 5162 return LID_OPEN; 5163 } else { 5164 // Switch state: AKEY_STATE_UNKNOWN. 5165 return LID_ABSENT; 5166 } 5167 } 5168 5169 // Called by window manager policy. Not exposed externally. 5170 @Override 5171 public InputChannel monitorInput(String inputChannelName) { 5172 return mInputManager.monitorInput(inputChannelName); 5173 } 5174 5175 // Called by window manager policy. Not exposed externally. 5176 @Override 5177 public void switchKeyboardLayout(int deviceId, int direction) { 5178 mInputManager.switchKeyboardLayout(deviceId, direction); 5179 } 5180 5181 // Called by window manager policy. Not exposed externally. 5182 @Override 5183 public void shutdown() { 5184 ShutdownThread.shutdown(mContext, true); 5185 } 5186 5187 // Called by window manager policy. Not exposed externally. 5188 @Override 5189 public void rebootSafeMode() { 5190 ShutdownThread.rebootSafeMode(mContext, true); 5191 } 5192 5193 public void setInputFilter(InputFilter filter) { 5194 mInputManager.setInputFilter(filter); 5195 } 5196 5197 public void enableScreenAfterBoot() { 5198 synchronized(mWindowMap) { 5199 if (DEBUG_BOOT) { 5200 RuntimeException here = new RuntimeException("here"); 5201 here.fillInStackTrace(); 5202 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5203 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5204 + " mShowingBootMessages=" + mShowingBootMessages 5205 + " mSystemBooted=" + mSystemBooted, here); 5206 } 5207 if (mSystemBooted) { 5208 return; 5209 } 5210 mSystemBooted = true; 5211 hideBootMessagesLocked(); 5212 // If the screen still doesn't come up after 30 seconds, give 5213 // up and turn it on. 5214 Message msg = mH.obtainMessage(H.BOOT_TIMEOUT); 5215 mH.sendMessageDelayed(msg, 30*1000); 5216 } 5217 5218 mPolicy.systemBooted(); 5219 5220 performEnableScreen(); 5221 } 5222 5223 void enableScreenIfNeededLocked() { 5224 if (DEBUG_BOOT) { 5225 RuntimeException here = new RuntimeException("here"); 5226 here.fillInStackTrace(); 5227 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5228 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5229 + " mShowingBootMessages=" + mShowingBootMessages 5230 + " mSystemBooted=" + mSystemBooted, here); 5231 } 5232 if (mDisplayEnabled) { 5233 return; 5234 } 5235 if (!mSystemBooted && !mShowingBootMessages) { 5236 return; 5237 } 5238 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN)); 5239 } 5240 5241 public void performBootTimeout() { 5242 synchronized(mWindowMap) { 5243 if (mDisplayEnabled || mHeadless) { 5244 return; 5245 } 5246 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5247 mForceDisplayEnabled = true; 5248 } 5249 performEnableScreen(); 5250 } 5251 5252 public void performEnableScreen() { 5253 synchronized(mWindowMap) { 5254 if (DEBUG_BOOT) { 5255 RuntimeException here = new RuntimeException("here"); 5256 here.fillInStackTrace(); 5257 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5258 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5259 + " mShowingBootMessages=" + mShowingBootMessages 5260 + " mSystemBooted=" + mSystemBooted 5261 + " mOnlyCore=" + mOnlyCore, here); 5262 } 5263 if (mDisplayEnabled) { 5264 return; 5265 } 5266 if (!mSystemBooted && !mShowingBootMessages) { 5267 return; 5268 } 5269 5270 if (!mForceDisplayEnabled) { 5271 // Don't enable the screen until all existing windows 5272 // have been drawn. 5273 boolean haveBootMsg = false; 5274 boolean haveApp = false; 5275 // if the wallpaper service is disabled on the device, we're never going to have 5276 // wallpaper, don't bother waiting for it 5277 boolean haveWallpaper = false; 5278 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5279 com.android.internal.R.bool.config_enableWallpaperService) 5280 && !mOnlyCore; 5281 boolean haveKeyguard = true; 5282 final int N = mWindows.size(); 5283 for (int i=0; i<N; i++) { 5284 WindowState w = mWindows.get(i); 5285 if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) { 5286 // Only if there is a keyguard attached to the window manager 5287 // will we consider ourselves as having a keyguard. If it 5288 // isn't attached, we don't know if it wants to be shown or 5289 // hidden. If it is attached, we will say we have a keyguard 5290 // if the window doesn't want to be visible, because in that 5291 // case it explicitly doesn't want to be shown so we should 5292 // not delay turning the screen on for it. 5293 boolean vis = w.mViewVisibility == View.VISIBLE 5294 && w.mPolicyVisibility; 5295 haveKeyguard = !vis; 5296 } 5297 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5298 return; 5299 } 5300 if (w.isDrawnLw()) { 5301 if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { 5302 haveBootMsg = true; 5303 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION) { 5304 haveApp = true; 5305 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER) { 5306 haveWallpaper = true; 5307 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) { 5308 haveKeyguard = true; 5309 } 5310 } 5311 } 5312 5313 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5314 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5315 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5316 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5317 + " haveKeyguard=" + haveKeyguard); 5318 } 5319 5320 // If we are turning on the screen to show the boot message, 5321 // don't do it until the boot message is actually displayed. 5322 if (!mSystemBooted && !haveBootMsg) { 5323 return; 5324 } 5325 5326 // If we are turning on the screen after the boot is completed 5327 // normally, don't do so until we have the application and 5328 // wallpaper. 5329 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5330 (wallpaperEnabled && !haveWallpaper))) { 5331 return; 5332 } 5333 } 5334 5335 mDisplayEnabled = true; 5336 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5337 if (false) { 5338 StringWriter sw = new StringWriter(); 5339 PrintWriter pw = new PrintWriter(sw); 5340 this.dump(null, pw, null); 5341 Slog.i(TAG, sw.toString()); 5342 } 5343 try { 5344 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5345 if (surfaceFlinger != null) { 5346 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5347 Parcel data = Parcel.obtain(); 5348 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5349 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5350 data, null, 0); 5351 data.recycle(); 5352 } 5353 } catch (RemoteException ex) { 5354 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5355 } 5356 5357 // Enable input dispatch. 5358 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5359 } 5360 5361 mPolicy.enableScreenAfterBoot(); 5362 5363 // Make sure the last requested orientation has been applied. 5364 updateRotationUnchecked(false, false); 5365 } 5366 5367 public void showBootMessage(final CharSequence msg, final boolean always) { 5368 boolean first = false; 5369 synchronized(mWindowMap) { 5370 if (DEBUG_BOOT) { 5371 RuntimeException here = new RuntimeException("here"); 5372 here.fillInStackTrace(); 5373 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5374 + " mAllowBootMessages=" + mAllowBootMessages 5375 + " mShowingBootMessages=" + mShowingBootMessages 5376 + " mSystemBooted=" + mSystemBooted, here); 5377 } 5378 if (!mAllowBootMessages) { 5379 return; 5380 } 5381 if (!mShowingBootMessages) { 5382 if (!always) { 5383 return; 5384 } 5385 first = true; 5386 } 5387 if (mSystemBooted) { 5388 return; 5389 } 5390 mShowingBootMessages = true; 5391 mPolicy.showBootMessage(msg, always); 5392 } 5393 if (first) { 5394 performEnableScreen(); 5395 } 5396 } 5397 5398 public void hideBootMessagesLocked() { 5399 if (DEBUG_BOOT) { 5400 RuntimeException here = new RuntimeException("here"); 5401 here.fillInStackTrace(); 5402 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5403 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5404 + " mShowingBootMessages=" + mShowingBootMessages 5405 + " mSystemBooted=" + mSystemBooted, here); 5406 } 5407 if (mShowingBootMessages) { 5408 mShowingBootMessages = false; 5409 mPolicy.hideBootMessages(); 5410 } 5411 } 5412 5413 public void setInTouchMode(boolean mode) { 5414 synchronized(mWindowMap) { 5415 mInTouchMode = mode; 5416 } 5417 } 5418 5419 // TODO: more accounting of which pid(s) turned it on, keep count, 5420 // only allow disables from pids which have count on, etc. 5421 @Override 5422 public void showStrictModeViolation(boolean on) { 5423 if (mHeadless) return; 5424 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, 0)); 5425 } 5426 5427 private void showStrictModeViolation(int arg) { 5428 final boolean on = arg != 0; 5429 int pid = Binder.getCallingPid(); 5430 synchronized(mWindowMap) { 5431 // Ignoring requests to enable the red border from clients 5432 // which aren't on screen. (e.g. Broadcast Receivers in 5433 // the background..) 5434 if (on) { 5435 boolean isVisible = false; 5436 for (int i = mWindows.size() - 1; i >= 0; i--) { 5437 final WindowState ws = mWindows.get(i); 5438 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5439 isVisible = true; 5440 break; 5441 } 5442 } 5443 if (!isVisible) { 5444 return; 5445 } 5446 } 5447 5448 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5449 ">>> OPEN TRANSACTION showStrictModeViolation"); 5450 Surface.openTransaction(); 5451 try { 5452 if (mStrictModeFlash == null) { 5453 mStrictModeFlash = new StrictModeFlash(mDisplay, mFxSession); 5454 } 5455 mStrictModeFlash.setVisibility(on); 5456 } finally { 5457 Surface.closeTransaction(); 5458 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5459 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5460 } 5461 } 5462 } 5463 5464 public void setStrictModeVisualIndicatorPreference(String value) { 5465 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5466 } 5467 5468 /** 5469 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5470 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5471 * of the target image. 5472 * 5473 * @param width the width of the target bitmap 5474 * @param height the height of the target bitmap 5475 */ 5476 public Bitmap screenshotApplications(IBinder appToken, int width, int height) { 5477 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5478 "screenshotApplications()")) { 5479 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5480 } 5481 5482 Bitmap rawss; 5483 5484 int maxLayer = 0; 5485 final Rect frame = new Rect(); 5486 5487 float scale; 5488 int dw, dh; 5489 int rot; 5490 5491 synchronized(mWindowMap) { 5492 long ident = Binder.clearCallingIdentity(); 5493 5494 dw = mCurDisplayWidth; 5495 dh = mCurDisplayHeight; 5496 5497 int aboveAppLayer = mPolicy.windowTypeToLayerLw( 5498 WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER 5499 + TYPE_LAYER_OFFSET; 5500 aboveAppLayer += TYPE_LAYER_MULTIPLIER; 5501 5502 boolean isImeTarget = mInputMethodTarget != null 5503 && mInputMethodTarget.mAppToken != null 5504 && mInputMethodTarget.mAppToken.appToken != null 5505 && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; 5506 5507 // Figure out the part of the screen that is actually the app. 5508 boolean including = false; 5509 for (int i=mWindows.size()-1; i>=0; i--) { 5510 WindowState ws = mWindows.get(i); 5511 if (!ws.mHasSurface) { 5512 continue; 5513 } 5514 if (ws.mLayer >= aboveAppLayer) { 5515 continue; 5516 } 5517 // When we will skip windows: when we are not including 5518 // ones behind a window we didn't skip, and we are actually 5519 // taking a screenshot of a specific app. 5520 if (!including && appToken != null) { 5521 // Also, we can possibly skip this window if it is not 5522 // an IME target or the application for the screenshot 5523 // is not the current IME target. 5524 if (!ws.mIsImWindow || !isImeTarget) { 5525 // And finally, this window is of no interest if it 5526 // is not associated with the screenshot app. 5527 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 5528 continue; 5529 } 5530 } 5531 } 5532 5533 // We keep on including windows until we go past a full-screen 5534 // window. 5535 including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); 5536 5537 if (maxLayer < ws.mWinAnimator.mSurfaceLayer) { 5538 maxLayer = ws.mWinAnimator.mSurfaceLayer; 5539 } 5540 5541 // Don't include wallpaper in bounds calculation 5542 if (!ws.mIsWallpaper) { 5543 final Rect wf = ws.mFrame; 5544 final Rect cr = ws.mContentInsets; 5545 int left = wf.left + cr.left; 5546 int top = wf.top + cr.top; 5547 int right = wf.right - cr.right; 5548 int bottom = wf.bottom - cr.bottom; 5549 frame.union(left, top, right, bottom); 5550 } 5551 } 5552 Binder.restoreCallingIdentity(ident); 5553 5554 // Constrain frame to the screen size. 5555 frame.intersect(0, 0, dw, dh); 5556 5557 if (frame.isEmpty() || maxLayer == 0) { 5558 return null; 5559 } 5560 5561 // The screenshot API does not apply the current screen rotation. 5562 rot = mDisplay.getRotation(); 5563 int fw = frame.width(); 5564 int fh = frame.height(); 5565 5566 // Constrain thumbnail to smaller of screen width or height. Assumes aspect 5567 // of thumbnail is the same as the screen (in landscape) or square. 5568 float targetWidthScale = width / (float) fw; 5569 float targetHeightScale = height / (float) fh; 5570 if (dw <= dh) { 5571 scale = targetWidthScale; 5572 // If aspect of thumbnail is the same as the screen (in landscape), 5573 // select the slightly larger value so we fill the entire bitmap 5574 if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) { 5575 scale = targetHeightScale; 5576 } 5577 } else { 5578 scale = targetHeightScale; 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 (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) { 5582 scale = targetWidthScale; 5583 } 5584 } 5585 5586 // The screen shot will contain the entire screen. 5587 dw = (int)(dw*scale); 5588 dh = (int)(dh*scale); 5589 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 5590 int tmp = dw; 5591 dw = dh; 5592 dh = tmp; 5593 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; 5594 } 5595 if (DEBUG_SCREENSHOT) { 5596 Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from 0 to " + maxLayer); 5597 for (int i=0; i<mWindows.size(); i++) { 5598 Slog.i(TAG, mWindows.get(i) + ": " + mWindows.get(i).mLayer 5599 + " animLayer=" + mWindows.get(i).mWinAnimator.mAnimLayer 5600 + " surfaceLayer=" + mWindows.get(i).mWinAnimator.mSurfaceLayer); 5601 } 5602 } 5603 rawss = Surface.screenshot(dw, dh, 0, maxLayer); 5604 } 5605 5606 if (rawss == null) { 5607 Slog.w(TAG, "Failure taking screenshot for (" + dw + "x" + dh 5608 + ") to layer " + maxLayer); 5609 return null; 5610 } 5611 5612 Bitmap bm = Bitmap.createBitmap(width, height, rawss.getConfig()); 5613 Matrix matrix = new Matrix(); 5614 ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); 5615 matrix.postTranslate(-FloatMath.ceil(frame.left*scale), -FloatMath.ceil(frame.top*scale)); 5616 Canvas canvas = new Canvas(bm); 5617 canvas.drawBitmap(rawss, matrix, null); 5618 canvas.setBitmap(null); 5619 5620 rawss.recycle(); 5621 return bm; 5622 } 5623 5624 /** 5625 * Freeze rotation changes. (Enable "rotation lock".) 5626 * Persists across reboots. 5627 * @param rotation The desired rotation to freeze to, or -1 to use the 5628 * current rotation. 5629 */ 5630 public void freezeRotation(int rotation) { 5631 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5632 "freezeRotation()")) { 5633 throw new SecurityException("Requires SET_ORIENTATION permission"); 5634 } 5635 if (rotation < -1 || rotation > Surface.ROTATION_270) { 5636 throw new IllegalArgumentException("Rotation argument must be -1 or a valid " 5637 + "rotation constant."); 5638 } 5639 5640 if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); 5641 5642 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, 5643 rotation == -1 ? mRotation : rotation); 5644 updateRotationUnchecked(false, false); 5645 } 5646 5647 /** 5648 * Thaw rotation changes. (Disable "rotation lock".) 5649 * Persists across reboots. 5650 */ 5651 public void thawRotation() { 5652 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, 5653 "thawRotation()")) { 5654 throw new SecurityException("Requires SET_ORIENTATION permission"); 5655 } 5656 5657 if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); 5658 5659 mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used 5660 updateRotationUnchecked(false, false); 5661 } 5662 5663 /** 5664 * Recalculate the current rotation. 5665 * 5666 * Called by the window manager policy whenever the state of the system changes 5667 * such that the current rotation might need to be updated, such as when the 5668 * device is docked or rotated into a new posture. 5669 */ 5670 public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 5671 updateRotationUnchecked(alwaysSendConfiguration, forceRelayout); 5672 } 5673 5674 /** 5675 * Temporarily pauses rotation changes until resumed. 5676 * 5677 * This can be used to prevent rotation changes from occurring while the user is 5678 * performing certain operations, such as drag and drop. 5679 * 5680 * This call nests and must be matched by an equal number of calls to {@link #resumeRotation}. 5681 */ 5682 void pauseRotationLocked() { 5683 mDeferredRotationPauseCount += 1; 5684 } 5685 5686 /** 5687 * Resumes normal rotation changes after being paused. 5688 */ 5689 void resumeRotationLocked() { 5690 if (mDeferredRotationPauseCount > 0) { 5691 mDeferredRotationPauseCount -= 1; 5692 if (mDeferredRotationPauseCount == 0) { 5693 boolean changed = updateRotationUncheckedLocked(false); 5694 if (changed) { 5695 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 5696 } 5697 } 5698 } 5699 } 5700 5701 public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) { 5702 if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" 5703 + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); 5704 5705 long origId = Binder.clearCallingIdentity(); 5706 boolean changed; 5707 synchronized(mWindowMap) { 5708 changed = updateRotationUncheckedLocked(false); 5709 if (!changed || forceRelayout) { 5710 mLayoutNeeded = true; 5711 performLayoutAndPlaceSurfacesLocked(); 5712 } 5713 } 5714 5715 if (changed || alwaysSendConfiguration) { 5716 sendNewConfiguration(); 5717 } 5718 5719 Binder.restoreCallingIdentity(origId); 5720 } 5721 5722 /** 5723 * Updates the current rotation. 5724 * 5725 * Returns true if the rotation has been changed. In this case YOU 5726 * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. 5727 */ 5728 public boolean updateRotationUncheckedLocked(boolean inTransaction) { 5729 if (mDeferredRotationPauseCount > 0) { 5730 // Rotation updates have been paused temporarily. Defer the update until 5731 // updates have been resumed. 5732 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); 5733 return false; 5734 } 5735 5736 if (mAnimator.mScreenRotationAnimation != null && 5737 mAnimator.mScreenRotationAnimation.isAnimating()) { 5738 // Rotation updates cannot be performed while the previous rotation change 5739 // animation is still in progress. Skip this update. We will try updating 5740 // again after the animation is finished and the display is unfrozen. 5741 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); 5742 return false; 5743 } 5744 5745 if (!mDisplayEnabled) { 5746 // No point choosing a rotation if the display is not enabled. 5747 if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); 5748 return false; 5749 } 5750 5751 // TODO: Implement forced rotation changes. 5752 // Set mAltOrientation to indicate that the application is receiving 5753 // an orientation that has different metrics than it expected. 5754 // eg. Portrait instead of Landscape. 5755 5756 int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); 5757 boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( 5758 mForcedAppOrientation, rotation); 5759 5760 if (DEBUG_ORIENTATION) { 5761 Slog.v(TAG, "Application requested orientation " 5762 + mForcedAppOrientation + ", got rotation " + rotation 5763 + " which has " + (altOrientation ? "incompatible" : "compatible") 5764 + " metrics"); 5765 } 5766 5767 if (mRotation == rotation && mAltOrientation == altOrientation) { 5768 // No change. 5769 return false; 5770 } 5771 5772 if (DEBUG_ORIENTATION) { 5773 Slog.v(TAG, 5774 "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") 5775 + " from " + mRotation + (mAltOrientation ? " (alt)" : "") 5776 + ", forceApp=" + mForcedAppOrientation); 5777 } 5778 5779 mRotation = rotation; 5780 mAltOrientation = altOrientation; 5781 mPolicy.setRotationLw(mRotation); 5782 5783 mWindowsFreezingScreen = true; 5784 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 5785 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), 2000); 5786 mWaitingForConfig = true; 5787 mLayoutNeeded = true; 5788 startFreezingDisplayLocked(inTransaction); 5789 mInputManager.setDisplayOrientation(0, rotation, 5790 mDisplay != null ? mDisplay.getExternalRotation() : Surface.ROTATION_0); 5791 5792 // We need to update our screen size information to match the new 5793 // rotation. Note that this is redundant with the later call to 5794 // sendNewConfiguration() that must be called after this function 5795 // returns... however we need to do the screen size part of that 5796 // before then so we have the correct size to use when initializiation 5797 // the rotation animation for the new rotation. 5798 computeScreenConfigurationLocked(null); 5799 5800 if (!inTransaction) { 5801 if (SHOW_TRANSACTIONS) Slog.i(TAG, 5802 ">>> OPEN TRANSACTION setRotationUnchecked"); 5803 Surface.openTransaction(); 5804 } 5805 try { 5806 // NOTE: We disable the rotation in the emulator because 5807 // it doesn't support hardware OpenGL emulation yet. 5808 if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null 5809 && mAnimator.mScreenRotationAnimation.hasScreenshot()) { 5810 if (mAnimator.mScreenRotationAnimation.setRotation(rotation, mFxSession, 5811 MAX_ANIMATION_DURATION, mTransitionAnimationScale, 5812 mCurDisplayWidth, mCurDisplayHeight)) { 5813 updateLayoutToAnimationLocked(); 5814 } 5815 } 5816 Surface.setOrientation(0, rotation); 5817 } finally { 5818 if (!inTransaction) { 5819 Surface.closeTransaction(); 5820 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5821 "<<< CLOSE TRANSACTION setRotationUnchecked"); 5822 } 5823 } 5824 5825 rebuildBlackFrame(); 5826 5827 for (int i=mWindows.size()-1; i>=0; i--) { 5828 WindowState w = mWindows.get(i); 5829 if (w.mHasSurface) { 5830 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 5831 w.mOrientationChanging = true; 5832 mInnerFields.mOrientationChangeComplete = false; 5833 } 5834 } 5835 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 5836 try { 5837 mRotationWatchers.get(i).onRotationChanged(rotation); 5838 } catch (RemoteException e) { 5839 } 5840 } 5841 return true; 5842 } 5843 5844 public int getRotation() { 5845 return mRotation; 5846 } 5847 5848 public int watchRotation(IRotationWatcher watcher) { 5849 final IBinder watcherBinder = watcher.asBinder(); 5850 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 5851 public void binderDied() { 5852 synchronized (mWindowMap) { 5853 for (int i=0; i<mRotationWatchers.size(); i++) { 5854 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 5855 IRotationWatcher removed = mRotationWatchers.remove(i); 5856 if (removed != null) { 5857 removed.asBinder().unlinkToDeath(this, 0); 5858 } 5859 i--; 5860 } 5861 } 5862 } 5863 } 5864 }; 5865 5866 synchronized (mWindowMap) { 5867 try { 5868 watcher.asBinder().linkToDeath(dr, 0); 5869 mRotationWatchers.add(watcher); 5870 } catch (RemoteException e) { 5871 // Client died, no cleanup needed. 5872 } 5873 5874 return mRotation; 5875 } 5876 } 5877 5878 /** 5879 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 5880 * theme attribute) on devices that feature a physical options menu key attempt to position 5881 * their menu panel window along the edge of the screen nearest the physical menu key. 5882 * This lowers the travel distance between invoking the menu panel and selecting 5883 * a menu option. 5884 * 5885 * This method helps control where that menu is placed. Its current implementation makes 5886 * assumptions about the menu key and its relationship to the screen based on whether 5887 * the device's natural orientation is portrait (width < height) or landscape. 5888 * 5889 * The menu key is assumed to be located along the bottom edge of natural-portrait 5890 * devices and along the right edge of natural-landscape devices. If these assumptions 5891 * do not hold for the target device, this method should be changed to reflect that. 5892 * 5893 * @return A {@link Gravity} value for placing the options menu window 5894 */ 5895 public int getPreferredOptionsPanelGravity() { 5896 synchronized (mWindowMap) { 5897 final int rotation = getRotation(); 5898 5899 if (mInitialDisplayWidth < mInitialDisplayHeight) { 5900 // On devices with a natural orientation of portrait 5901 switch (rotation) { 5902 default: 5903 case Surface.ROTATION_0: 5904 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5905 case Surface.ROTATION_90: 5906 return Gravity.RIGHT | Gravity.BOTTOM; 5907 case Surface.ROTATION_180: 5908 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5909 case Surface.ROTATION_270: 5910 return Gravity.LEFT | Gravity.BOTTOM; 5911 } 5912 } else { 5913 // On devices with a natural orientation of landscape 5914 switch (rotation) { 5915 default: 5916 case Surface.ROTATION_0: 5917 return Gravity.RIGHT | Gravity.BOTTOM; 5918 case Surface.ROTATION_90: 5919 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5920 case Surface.ROTATION_180: 5921 return Gravity.LEFT | Gravity.BOTTOM; 5922 case Surface.ROTATION_270: 5923 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5924 } 5925 } 5926 } 5927 } 5928 5929 /** 5930 * Starts the view server on the specified port. 5931 * 5932 * @param port The port to listener to. 5933 * 5934 * @return True if the server was successfully started, false otherwise. 5935 * 5936 * @see com.android.server.wm.ViewServer 5937 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 5938 */ 5939 public boolean startViewServer(int port) { 5940 if (isSystemSecure()) { 5941 return false; 5942 } 5943 5944 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 5945 return false; 5946 } 5947 5948 if (port < 1024) { 5949 return false; 5950 } 5951 5952 if (mViewServer != null) { 5953 if (!mViewServer.isRunning()) { 5954 try { 5955 return mViewServer.start(); 5956 } catch (IOException e) { 5957 Slog.w(TAG, "View server did not start"); 5958 } 5959 } 5960 return false; 5961 } 5962 5963 try { 5964 mViewServer = new ViewServer(this, port); 5965 return mViewServer.start(); 5966 } catch (IOException e) { 5967 Slog.w(TAG, "View server did not start"); 5968 } 5969 return false; 5970 } 5971 5972 private boolean isSystemSecure() { 5973 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 5974 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 5975 } 5976 5977 /** 5978 * Stops the view server if it exists. 5979 * 5980 * @return True if the server stopped, false if it wasn't started or 5981 * couldn't be stopped. 5982 * 5983 * @see com.android.server.wm.ViewServer 5984 */ 5985 public boolean stopViewServer() { 5986 if (isSystemSecure()) { 5987 return false; 5988 } 5989 5990 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 5991 return false; 5992 } 5993 5994 if (mViewServer != null) { 5995 return mViewServer.stop(); 5996 } 5997 return false; 5998 } 5999 6000 /** 6001 * Indicates whether the view server is running. 6002 * 6003 * @return True if the server is running, false otherwise. 6004 * 6005 * @see com.android.server.wm.ViewServer 6006 */ 6007 public boolean isViewServerRunning() { 6008 if (isSystemSecure()) { 6009 return false; 6010 } 6011 6012 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 6013 return false; 6014 } 6015 6016 return mViewServer != null && mViewServer.isRunning(); 6017 } 6018 6019 /** 6020 * Lists all availble windows in the system. The listing is written in the 6021 * specified Socket's output stream with the following syntax: 6022 * windowHashCodeInHexadecimal windowName 6023 * Each line of the ouput represents a different window. 6024 * 6025 * @param client The remote client to send the listing to. 6026 * @return False if an error occured, true otherwise. 6027 */ 6028 boolean viewServerListWindows(Socket client) { 6029 if (isSystemSecure()) { 6030 return false; 6031 } 6032 6033 boolean result = true; 6034 6035 WindowState[] windows; 6036 synchronized (mWindowMap) { 6037 //noinspection unchecked 6038 windows = mWindows.toArray(new WindowState[mWindows.size()]); 6039 } 6040 6041 BufferedWriter out = null; 6042 6043 // Any uncaught exception will crash the system process 6044 try { 6045 OutputStream clientStream = client.getOutputStream(); 6046 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6047 6048 final int count = windows.length; 6049 for (int i = 0; i < count; i++) { 6050 final WindowState w = windows[i]; 6051 out.write(Integer.toHexString(System.identityHashCode(w))); 6052 out.write(' '); 6053 out.append(w.mAttrs.getTitle()); 6054 out.write('\n'); 6055 } 6056 6057 out.write("DONE.\n"); 6058 out.flush(); 6059 } catch (Exception e) { 6060 result = false; 6061 } finally { 6062 if (out != null) { 6063 try { 6064 out.close(); 6065 } catch (IOException e) { 6066 result = false; 6067 } 6068 } 6069 } 6070 6071 return result; 6072 } 6073 6074 /** 6075 * Returns the focused window in the following format: 6076 * windowHashCodeInHexadecimal windowName 6077 * 6078 * @param client The remote client to send the listing to. 6079 * @return False if an error occurred, true otherwise. 6080 */ 6081 boolean viewServerGetFocusedWindow(Socket client) { 6082 if (isSystemSecure()) { 6083 return false; 6084 } 6085 6086 boolean result = true; 6087 6088 WindowState focusedWindow = getFocusedWindow(); 6089 6090 BufferedWriter out = null; 6091 6092 // Any uncaught exception will crash the system process 6093 try { 6094 OutputStream clientStream = client.getOutputStream(); 6095 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 6096 6097 if(focusedWindow != null) { 6098 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 6099 out.write(' '); 6100 out.append(focusedWindow.mAttrs.getTitle()); 6101 } 6102 out.write('\n'); 6103 out.flush(); 6104 } catch (Exception e) { 6105 result = false; 6106 } finally { 6107 if (out != null) { 6108 try { 6109 out.close(); 6110 } catch (IOException e) { 6111 result = false; 6112 } 6113 } 6114 } 6115 6116 return result; 6117 } 6118 6119 /** 6120 * Sends a command to a target window. The result of the command, if any, will be 6121 * written in the output stream of the specified socket. 6122 * 6123 * The parameters must follow this syntax: 6124 * windowHashcode extra 6125 * 6126 * Where XX is the length in characeters of the windowTitle. 6127 * 6128 * The first parameter is the target window. The window with the specified hashcode 6129 * will be the target. If no target can be found, nothing happens. The extra parameters 6130 * will be delivered to the target window and as parameters to the command itself. 6131 * 6132 * @param client The remote client to sent the result, if any, to. 6133 * @param command The command to execute. 6134 * @param parameters The command parameters. 6135 * 6136 * @return True if the command was successfully delivered, false otherwise. This does 6137 * not indicate whether the command itself was successful. 6138 */ 6139 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 6140 if (isSystemSecure()) { 6141 return false; 6142 } 6143 6144 boolean success = true; 6145 Parcel data = null; 6146 Parcel reply = null; 6147 6148 BufferedWriter out = null; 6149 6150 // Any uncaught exception will crash the system process 6151 try { 6152 // Find the hashcode of the window 6153 int index = parameters.indexOf(' '); 6154 if (index == -1) { 6155 index = parameters.length(); 6156 } 6157 final String code = parameters.substring(0, index); 6158 int hashCode = (int) Long.parseLong(code, 16); 6159 6160 // Extract the command's parameter after the window description 6161 if (index < parameters.length()) { 6162 parameters = parameters.substring(index + 1); 6163 } else { 6164 parameters = ""; 6165 } 6166 6167 final WindowState window = findWindow(hashCode); 6168 if (window == null) { 6169 return false; 6170 } 6171 6172 data = Parcel.obtain(); 6173 data.writeInterfaceToken("android.view.IWindow"); 6174 data.writeString(command); 6175 data.writeString(parameters); 6176 data.writeInt(1); 6177 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 6178 6179 reply = Parcel.obtain(); 6180 6181 final IBinder binder = window.mClient.asBinder(); 6182 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 6183 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 6184 6185 reply.readException(); 6186 6187 if (!client.isOutputShutdown()) { 6188 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 6189 out.write("DONE\n"); 6190 out.flush(); 6191 } 6192 6193 } catch (Exception e) { 6194 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 6195 success = false; 6196 } finally { 6197 if (data != null) { 6198 data.recycle(); 6199 } 6200 if (reply != null) { 6201 reply.recycle(); 6202 } 6203 if (out != null) { 6204 try { 6205 out.close(); 6206 } catch (IOException e) { 6207 6208 } 6209 } 6210 } 6211 6212 return success; 6213 } 6214 6215 public void addWindowChangeListener(WindowChangeListener listener) { 6216 synchronized(mWindowMap) { 6217 mWindowChangeListeners.add(listener); 6218 } 6219 } 6220 6221 public void removeWindowChangeListener(WindowChangeListener listener) { 6222 synchronized(mWindowMap) { 6223 mWindowChangeListeners.remove(listener); 6224 } 6225 } 6226 6227 private void notifyWindowsChanged() { 6228 WindowChangeListener[] windowChangeListeners; 6229 synchronized(mWindowMap) { 6230 if(mWindowChangeListeners.isEmpty()) { 6231 return; 6232 } 6233 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6234 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6235 } 6236 int N = windowChangeListeners.length; 6237 for(int i = 0; i < N; i++) { 6238 windowChangeListeners[i].windowsChanged(); 6239 } 6240 } 6241 6242 private void notifyFocusChanged() { 6243 WindowChangeListener[] windowChangeListeners; 6244 synchronized(mWindowMap) { 6245 if(mWindowChangeListeners.isEmpty()) { 6246 return; 6247 } 6248 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6249 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6250 } 6251 int N = windowChangeListeners.length; 6252 for(int i = 0; i < N; i++) { 6253 windowChangeListeners[i].focusChanged(); 6254 } 6255 } 6256 6257 private WindowState findWindow(int hashCode) { 6258 if (hashCode == -1) { 6259 return getFocusedWindow(); 6260 } 6261 6262 synchronized (mWindowMap) { 6263 final ArrayList<WindowState> windows = mWindows; 6264 final int count = windows.size(); 6265 6266 for (int i = 0; i < count; i++) { 6267 WindowState w = windows.get(i); 6268 if (System.identityHashCode(w) == hashCode) { 6269 return w; 6270 } 6271 } 6272 } 6273 6274 return null; 6275 } 6276 6277 /* 6278 * Instruct the Activity Manager to fetch the current configuration and broadcast 6279 * that to config-changed listeners if appropriate. 6280 */ 6281 void sendNewConfiguration() { 6282 try { 6283 mActivityManager.updateConfiguration(null); 6284 } catch (RemoteException e) { 6285 } 6286 } 6287 6288 public Configuration computeNewConfiguration() { 6289 synchronized (mWindowMap) { 6290 Configuration config = computeNewConfigurationLocked(); 6291 if (config == null && mWaitingForConfig) { 6292 // Nothing changed but we are waiting for something... stop that! 6293 mWaitingForConfig = false; 6294 performLayoutAndPlaceSurfacesLocked(); 6295 } 6296 return config; 6297 } 6298 } 6299 6300 Configuration computeNewConfigurationLocked() { 6301 Configuration config = new Configuration(); 6302 config.fontScale = 0; 6303 if (!computeScreenConfigurationLocked(config)) { 6304 return null; 6305 } 6306 return config; 6307 } 6308 6309 private void adjustDisplaySizeRanges(int rotation, int dw, int dh) { 6310 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6311 if (width < mSmallestDisplayWidth) { 6312 mSmallestDisplayWidth = width; 6313 } 6314 if (width > mLargestDisplayWidth) { 6315 mLargestDisplayWidth = width; 6316 } 6317 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6318 if (height < mSmallestDisplayHeight) { 6319 mSmallestDisplayHeight = height; 6320 } 6321 if (height > mLargestDisplayHeight) { 6322 mLargestDisplayHeight = height; 6323 } 6324 } 6325 6326 private int reduceConfigLayout(int curLayout, int rotation, float density, 6327 int dw, int dh) { 6328 // Get the app screen size at this rotation. 6329 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6330 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6331 6332 // Compute the screen layout size class for this rotation. 6333 int screenLayoutSize; 6334 boolean screenLayoutLong; 6335 boolean screenLayoutCompatNeeded; 6336 int longSize = w; 6337 int shortSize = h; 6338 if (longSize < shortSize) { 6339 int tmp = longSize; 6340 longSize = shortSize; 6341 shortSize = tmp; 6342 } 6343 longSize = (int)(longSize/density); 6344 shortSize = (int)(shortSize/density); 6345 6346 // These semi-magic numbers define our compatibility modes for 6347 // applications with different screens. These are guarantees to 6348 // app developers about the space they can expect for a particular 6349 // configuration. DO NOT CHANGE! 6350 if (longSize < 470) { 6351 // This is shorter than an HVGA normal density screen (which 6352 // is 480 pixels on its long side). 6353 screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_SMALL; 6354 screenLayoutLong = false; 6355 screenLayoutCompatNeeded = false; 6356 } else { 6357 // What size is this screen screen? 6358 if (longSize >= 960 && shortSize >= 720) { 6359 // 1.5xVGA or larger screens at medium density are the point 6360 // at which we consider it to be an extra large screen. 6361 screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_XLARGE; 6362 } else if (longSize >= 640 && shortSize >= 480) { 6363 // VGA or larger screens at medium density are the point 6364 // at which we consider it to be a large screen. 6365 screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_LARGE; 6366 } else { 6367 screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_NORMAL; 6368 } 6369 6370 // If this screen is wider than normal HVGA, or taller 6371 // than FWVGA, then for old apps we want to run in size 6372 // compatibility mode. 6373 if (shortSize > 321 || longSize > 570) { 6374 screenLayoutCompatNeeded = true; 6375 } else { 6376 screenLayoutCompatNeeded = false; 6377 } 6378 6379 // Is this a long screen? 6380 if (((longSize*3)/5) >= (shortSize-1)) { 6381 // Anything wider than WVGA (5:3) is considering to be long. 6382 screenLayoutLong = true; 6383 } else { 6384 screenLayoutLong = false; 6385 } 6386 } 6387 6388 // Now reduce the last screenLayout to not be better than what we 6389 // have found. 6390 if (!screenLayoutLong) { 6391 curLayout = (curLayout&~Configuration.SCREENLAYOUT_LONG_MASK) 6392 | Configuration.SCREENLAYOUT_LONG_NO; 6393 } 6394 if (screenLayoutCompatNeeded) { 6395 curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED; 6396 } 6397 int curSize = curLayout&Configuration.SCREENLAYOUT_SIZE_MASK; 6398 if (screenLayoutSize < curSize) { 6399 curLayout = (curLayout&~Configuration.SCREENLAYOUT_SIZE_MASK) 6400 | screenLayoutSize; 6401 } 6402 return curLayout; 6403 } 6404 6405 private void computeSizeRangesAndScreenLayout(boolean rotated, int dw, int dh, 6406 float density, Configuration outConfig) { 6407 // We need to determine the smallest width that will occur under normal 6408 // operation. To this, start with the base screen size and compute the 6409 // width under the different possible rotations. We need to un-rotate 6410 // the current screen dimensions before doing this. 6411 int unrotDw, unrotDh; 6412 if (rotated) { 6413 unrotDw = dh; 6414 unrotDh = dw; 6415 } else { 6416 unrotDw = dw; 6417 unrotDh = dh; 6418 } 6419 mSmallestDisplayWidth = 1<<30; 6420 mSmallestDisplayHeight = 1<<30; 6421 mLargestDisplayWidth = 0; 6422 mLargestDisplayHeight = 0; 6423 adjustDisplaySizeRanges(Surface.ROTATION_0, unrotDw, unrotDh); 6424 adjustDisplaySizeRanges(Surface.ROTATION_90, unrotDh, unrotDw); 6425 adjustDisplaySizeRanges(Surface.ROTATION_180, unrotDw, unrotDh); 6426 adjustDisplaySizeRanges(Surface.ROTATION_270, unrotDh, unrotDw); 6427 int sl = Configuration.SCREENLAYOUT_SIZE_XLARGE 6428 | Configuration.SCREENLAYOUT_LONG_YES; 6429 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6430 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6431 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6432 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6433 outConfig.smallestScreenWidthDp = (int)(mSmallestDisplayWidth / density); 6434 outConfig.screenLayout = sl; 6435 } 6436 6437 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6438 int dw, int dh) { 6439 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6440 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6441 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6442 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6443 if (curSize == 0 || size < curSize) { 6444 curSize = size; 6445 } 6446 return curSize; 6447 } 6448 6449 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6450 mTmpDisplayMetrics.setTo(dm); 6451 dm = mTmpDisplayMetrics; 6452 int unrotDw, unrotDh; 6453 if (rotated) { 6454 unrotDw = dh; 6455 unrotDh = dw; 6456 } else { 6457 unrotDw = dw; 6458 unrotDh = dh; 6459 } 6460 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, dm, unrotDw, unrotDh); 6461 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, dm, unrotDh, unrotDw); 6462 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, dm, unrotDw, unrotDh); 6463 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, dm, unrotDh, unrotDw); 6464 return sw; 6465 } 6466 6467 boolean computeScreenConfigurationLocked(Configuration config) { 6468 if (mDisplay == null) { 6469 return false; 6470 } 6471 6472 // Use the effective "visual" dimensions based on current rotation 6473 final boolean rotated = (mRotation == Surface.ROTATION_90 6474 || mRotation == Surface.ROTATION_270); 6475 final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 6476 final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 6477 6478 synchronized(mDisplaySizeLock) { 6479 if (mAltOrientation) { 6480 mCurDisplayWidth = realdw; 6481 mCurDisplayHeight = realdh; 6482 if (realdw > realdh) { 6483 // Turn landscape into portrait. 6484 int maxw = (int)(realdh/1.3f); 6485 if (maxw < realdw) { 6486 mCurDisplayWidth = maxw; 6487 } 6488 } else { 6489 // Turn portrait into landscape. 6490 int maxh = (int)(realdw/1.3f); 6491 if (maxh < realdh) { 6492 mCurDisplayHeight = maxh; 6493 } 6494 } 6495 } else { 6496 mCurDisplayWidth = realdw; 6497 mCurDisplayHeight = realdh; 6498 } 6499 } 6500 6501 final int dw = mCurDisplayWidth; 6502 final int dh = mCurDisplayHeight; 6503 6504 if (config != null) { 6505 int orientation = Configuration.ORIENTATION_SQUARE; 6506 if (dw < dh) { 6507 orientation = Configuration.ORIENTATION_PORTRAIT; 6508 } else if (dw > dh) { 6509 orientation = Configuration.ORIENTATION_LANDSCAPE; 6510 } 6511 config.orientation = orientation; 6512 } 6513 6514 // Update real display metrics. 6515 mDisplay.getMetricsWithSize(mRealDisplayMetrics, mCurDisplayWidth, mCurDisplayHeight); 6516 6517 // Update application display metrics. 6518 final DisplayMetrics dm = mDisplayMetrics; 6519 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6520 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6521 synchronized(mDisplaySizeLock) { 6522 mAppDisplayWidth = appWidth; 6523 mAppDisplayHeight = appHeight; 6524 mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight, 6525 mAppDisplayWidth, mAppDisplayHeight); 6526 } 6527 if (false) { 6528 Slog.i(TAG, "Set app display size: " + mAppDisplayWidth 6529 + " x " + mAppDisplayHeight); 6530 } 6531 mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight); 6532 6533 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6534 mCompatDisplayMetrics); 6535 6536 if (config != null) { 6537 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6538 / dm.density); 6539 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6540 / dm.density); 6541 computeSizeRangesAndScreenLayout(rotated, dw, dh, dm.density, config); 6542 6543 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6544 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6545 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6546 6547 // Update the configuration based on available input devices, lid switch, 6548 // and platform configuration. 6549 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6550 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6551 config.navigation = Configuration.NAVIGATION_NONAV; 6552 6553 int keyboardPresence = 0; 6554 int navigationPresence = 0; 6555 final InputDevice[] devices = mInputManager.getInputDevices(); 6556 final int len = devices.length; 6557 for (int i = 0; i < len; i++) { 6558 InputDevice device = devices[i]; 6559 if (!device.isVirtual()) { 6560 final int sources = device.getSources(); 6561 final int presenceFlag = device.isExternal() ? 6562 WindowManagerPolicy.PRESENCE_EXTERNAL : 6563 WindowManagerPolicy.PRESENCE_INTERNAL; 6564 6565 if (mIsTouchDevice) { 6566 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6567 InputDevice.SOURCE_TOUCHSCREEN) { 6568 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6569 } 6570 } else { 6571 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6572 } 6573 6574 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6575 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6576 navigationPresence |= presenceFlag; 6577 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6578 && config.navigation == Configuration.NAVIGATION_NONAV) { 6579 config.navigation = Configuration.NAVIGATION_DPAD; 6580 navigationPresence |= presenceFlag; 6581 } 6582 6583 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6584 config.keyboard = Configuration.KEYBOARD_QWERTY; 6585 keyboardPresence |= presenceFlag; 6586 } 6587 } 6588 } 6589 6590 // Determine whether a hard keyboard is available and enabled. 6591 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6592 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6593 mHardKeyboardAvailable = hardKeyboardAvailable; 6594 mHardKeyboardEnabled = hardKeyboardAvailable; 6595 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6596 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6597 } 6598 if (!mHardKeyboardEnabled) { 6599 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6600 } 6601 6602 // Let the policy update hidden states. 6603 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6604 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6605 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6606 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6607 } 6608 6609 return true; 6610 } 6611 6612 public boolean isHardKeyboardAvailable() { 6613 synchronized (mWindowMap) { 6614 return mHardKeyboardAvailable; 6615 } 6616 } 6617 6618 public boolean isHardKeyboardEnabled() { 6619 synchronized (mWindowMap) { 6620 return mHardKeyboardEnabled; 6621 } 6622 } 6623 6624 public void setHardKeyboardEnabled(boolean enabled) { 6625 synchronized (mWindowMap) { 6626 if (mHardKeyboardEnabled != enabled) { 6627 mHardKeyboardEnabled = enabled; 6628 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6629 } 6630 } 6631 } 6632 6633 public void setOnHardKeyboardStatusChangeListener( 6634 OnHardKeyboardStatusChangeListener listener) { 6635 synchronized (mWindowMap) { 6636 mHardKeyboardStatusChangeListener = listener; 6637 } 6638 } 6639 6640 void notifyHardKeyboardStatusChange() { 6641 final boolean available, enabled; 6642 final OnHardKeyboardStatusChangeListener listener; 6643 synchronized (mWindowMap) { 6644 listener = mHardKeyboardStatusChangeListener; 6645 available = mHardKeyboardAvailable; 6646 enabled = mHardKeyboardEnabled; 6647 } 6648 if (listener != null) { 6649 listener.onHardKeyboardStatusChange(available, enabled); 6650 } 6651 } 6652 6653 // ------------------------------------------------------------- 6654 // Drag and drop 6655 // ------------------------------------------------------------- 6656 6657 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6658 int flags, int width, int height, Surface outSurface) { 6659 if (DEBUG_DRAG) { 6660 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6661 + " flags=" + Integer.toHexString(flags) + " win=" + window 6662 + " asbinder=" + window.asBinder()); 6663 } 6664 6665 final int callerPid = Binder.getCallingPid(); 6666 final long origId = Binder.clearCallingIdentity(); 6667 IBinder token = null; 6668 6669 try { 6670 synchronized (mWindowMap) { 6671 try { 6672 if (mDragState == null) { 6673 Surface surface = new Surface(session, callerPid, "drag surface", 0, 6674 width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN); 6675 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6676 + surface + ": CREATE"); 6677 outSurface.copyFrom(surface); 6678 final IBinder winBinder = window.asBinder(); 6679 token = new Binder(); 6680 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6681 token = mDragState.mToken = new Binder(); 6682 6683 // 5 second timeout for this window to actually begin the drag 6684 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6685 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6686 mH.sendMessageDelayed(msg, 5000); 6687 } else { 6688 Slog.w(TAG, "Drag already in progress"); 6689 } 6690 } catch (Surface.OutOfResourcesException e) { 6691 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6692 if (mDragState != null) { 6693 mDragState.reset(); 6694 mDragState = null; 6695 } 6696 } 6697 } 6698 } finally { 6699 Binder.restoreCallingIdentity(origId); 6700 } 6701 6702 return token; 6703 } 6704 6705 // ------------------------------------------------------------- 6706 // Input Events and Focus Management 6707 // ------------------------------------------------------------- 6708 6709 final InputMonitor mInputMonitor = new InputMonitor(this); 6710 private boolean mEventDispatchingEnabled; 6711 6712 public void pauseKeyDispatching(IBinder _token) { 6713 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6714 "pauseKeyDispatching()")) { 6715 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6716 } 6717 6718 synchronized (mWindowMap) { 6719 WindowToken token = mTokenMap.get(_token); 6720 if (token != null) { 6721 mInputMonitor.pauseDispatchingLw(token); 6722 } 6723 } 6724 } 6725 6726 public void resumeKeyDispatching(IBinder _token) { 6727 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6728 "resumeKeyDispatching()")) { 6729 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6730 } 6731 6732 synchronized (mWindowMap) { 6733 WindowToken token = mTokenMap.get(_token); 6734 if (token != null) { 6735 mInputMonitor.resumeDispatchingLw(token); 6736 } 6737 } 6738 } 6739 6740 public void setEventDispatching(boolean enabled) { 6741 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6742 "setEventDispatching()")) { 6743 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6744 } 6745 6746 synchronized (mWindowMap) { 6747 mEventDispatchingEnabled = enabled; 6748 if (mDisplayEnabled) { 6749 mInputMonitor.setEventDispatchingLw(enabled); 6750 } 6751 sendScreenStatusToClientsLocked(); 6752 } 6753 } 6754 6755 // TODO: Put this on the IWindowManagerService and guard with a permission. 6756 public IBinder getFocusedWindowClientToken() { 6757 synchronized (mWindowMap) { 6758 WindowState windowState = getFocusedWindowLocked(); 6759 if (windowState != null) { 6760 return windowState.mClient.asBinder(); 6761 } 6762 return null; 6763 } 6764 } 6765 6766 // TODO: This is a workaround - remove when 6623031 is fixed. 6767 public boolean getWindowFrame(IBinder token, Rect outBounds) { 6768 synchronized (mWindowMap) { 6769 WindowState windowState = mWindowMap.get(token); 6770 if (windowState != null) { 6771 outBounds.set(windowState.getFrameLw()); 6772 return true; 6773 } 6774 } 6775 return false; 6776 } 6777 6778 private WindowState getFocusedWindow() { 6779 synchronized (mWindowMap) { 6780 return getFocusedWindowLocked(); 6781 } 6782 } 6783 6784 private WindowState getFocusedWindowLocked() { 6785 return mCurrentFocus; 6786 } 6787 6788 public boolean detectSafeMode() { 6789 if (!mInputMonitor.waitForInputDevicesReady( 6790 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 6791 Slog.w(TAG, "Devices still not ready after waiting " 6792 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 6793 + " milliseconds before attempting to detect safe mode."); 6794 } 6795 6796 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6797 KeyEvent.KEYCODE_MENU); 6798 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 6799 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 6800 KeyEvent.KEYCODE_DPAD_CENTER); 6801 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 6802 InputManagerService.BTN_MOUSE); 6803 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6804 KeyEvent.KEYCODE_VOLUME_DOWN); 6805 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 6806 || volumeDownState > 0; 6807 try { 6808 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 6809 mSafeMode = true; 6810 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 6811 } 6812 } catch (IllegalArgumentException e) { 6813 } 6814 if (mSafeMode) { 6815 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 6816 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 6817 } else { 6818 Log.i(TAG, "SAFE MODE not enabled"); 6819 } 6820 mPolicy.setSafeMode(mSafeMode); 6821 return mSafeMode; 6822 } 6823 6824 public void displayReady() { 6825 synchronized(mWindowMap) { 6826 if (mDisplay != null) { 6827 throw new IllegalStateException("Display already initialized"); 6828 } 6829 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 6830 mDisplay = wm.getDefaultDisplay(); 6831 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 6832 PackageManager.FEATURE_TOUCHSCREEN); 6833 synchronized(mDisplaySizeLock) { 6834 mInitialDisplayWidth = mDisplay.getRawWidth(); 6835 mInitialDisplayHeight = mDisplay.getRawHeight(); 6836 int rot = mDisplay.getRotation(); 6837 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 6838 // If the screen is currently rotated, we need to swap the 6839 // initial width and height to get the true natural values. 6840 int tmp = mInitialDisplayWidth; 6841 mInitialDisplayWidth = mInitialDisplayHeight; 6842 mInitialDisplayHeight = tmp; 6843 } 6844 mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth; 6845 mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight; 6846 mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight, 6847 mAppDisplayWidth, mAppDisplayHeight); 6848 } 6849 mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY, 6850 mDisplay.getRawWidth(), mDisplay.getRawHeight(), 6851 mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight()); 6852 mInputManager.setDisplayOrientation(Display.DEFAULT_DISPLAY, 6853 mDisplay.getRotation(), mDisplay.getExternalRotation()); 6854 mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight); 6855 } 6856 6857 try { 6858 mActivityManager.updateConfiguration(null); 6859 } catch (RemoteException e) { 6860 } 6861 6862 synchronized (mWindowMap) { 6863 readForcedDisplaySizeLocked(); 6864 } 6865 } 6866 6867 public void systemReady() { 6868 mPolicy.systemReady(); 6869 } 6870 6871 private void sendScreenStatusToClientsLocked() { 6872 final ArrayList<WindowState> windows = mWindows; 6873 final int count = windows.size(); 6874 boolean on = mPowerManager.isScreenOn(); 6875 for (int i = count - 1; i >= 0; i--) { 6876 WindowState win = mWindows.get(i); 6877 try { 6878 win.mClient.dispatchScreenState(on); 6879 } catch (RemoteException e) { 6880 // Ignored 6881 } 6882 } 6883 } 6884 6885 // ------------------------------------------------------------- 6886 // Async Handler 6887 // ------------------------------------------------------------- 6888 6889 final class H extends Handler { 6890 public static final int REPORT_FOCUS_CHANGE = 2; 6891 public static final int REPORT_LOSING_FOCUS = 3; 6892 public static final int DO_TRAVERSAL = 4; 6893 public static final int ADD_STARTING = 5; 6894 public static final int REMOVE_STARTING = 6; 6895 public static final int FINISHED_STARTING = 7; 6896 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 6897 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 6898 public static final int WINDOW_FREEZE_TIMEOUT = 11; 6899 public static final int HOLD_SCREEN_CHANGED = 12; 6900 public static final int APP_TRANSITION_TIMEOUT = 13; 6901 public static final int PERSIST_ANIMATION_SCALE = 14; 6902 public static final int FORCE_GC = 15; 6903 public static final int ENABLE_SCREEN = 16; 6904 public static final int APP_FREEZE_TIMEOUT = 17; 6905 public static final int SEND_NEW_CONFIGURATION = 18; 6906 public static final int REPORT_WINDOWS_CHANGE = 19; 6907 public static final int DRAG_START_TIMEOUT = 20; 6908 public static final int DRAG_END_TIMEOUT = 21; 6909 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 6910 public static final int BOOT_TIMEOUT = 23; 6911 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 6912 public static final int UPDATE_ANIM_PARAMETERS = 25; 6913 public static final int SHOW_STRICT_MODE_VIOLATION = 26; 6914 public static final int DO_ANIMATION_CALLBACK = 27; 6915 6916 public static final int ANIMATOR_WHAT_OFFSET = 100000; 6917 public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1; 6918 public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 2; 6919 6920 private Session mLastReportedHold; 6921 6922 public H() { 6923 } 6924 6925 @Override 6926 public void handleMessage(Message msg) { 6927 if (DEBUG_WINDOW_TRACE) { 6928 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 6929 } 6930 switch (msg.what) { 6931 case REPORT_FOCUS_CHANGE: { 6932 WindowState lastFocus; 6933 WindowState newFocus; 6934 6935 synchronized(mWindowMap) { 6936 lastFocus = mLastFocus; 6937 newFocus = mCurrentFocus; 6938 if (lastFocus == newFocus) { 6939 // Focus is not changing, so nothing to do. 6940 return; 6941 } 6942 mLastFocus = newFocus; 6943 //Slog.i(TAG, "Focus moving from " + lastFocus 6944 // + " to " + newFocus); 6945 if (newFocus != null && lastFocus != null 6946 && !newFocus.isDisplayedLw()) { 6947 //Slog.i(TAG, "Delaying loss of focus..."); 6948 mLosingFocus.add(lastFocus); 6949 lastFocus = null; 6950 } 6951 } 6952 6953 if (lastFocus != newFocus) { 6954 //System.out.println("Changing focus from " + lastFocus 6955 // + " to " + newFocus); 6956 if (newFocus != null) { 6957 try { 6958 //Slog.i(TAG, "Gaining focus: " + newFocus); 6959 newFocus.mClient.windowFocusChanged(true, mInTouchMode); 6960 } catch (RemoteException e) { 6961 // Ignore if process has died. 6962 } 6963 notifyFocusChanged(); 6964 } 6965 6966 if (lastFocus != null) { 6967 try { 6968 //Slog.i(TAG, "Losing focus: " + lastFocus); 6969 lastFocus.mClient.windowFocusChanged(false, mInTouchMode); 6970 } catch (RemoteException e) { 6971 // Ignore if process has died. 6972 } 6973 } 6974 } 6975 } break; 6976 6977 case REPORT_LOSING_FOCUS: { 6978 ArrayList<WindowState> losers; 6979 6980 synchronized(mWindowMap) { 6981 losers = mLosingFocus; 6982 mLosingFocus = new ArrayList<WindowState>(); 6983 } 6984 6985 final int N = losers.size(); 6986 for (int i=0; i<N; i++) { 6987 try { 6988 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i)); 6989 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode); 6990 } catch (RemoteException e) { 6991 // Ignore if process has died. 6992 } 6993 } 6994 } break; 6995 6996 case DO_TRAVERSAL: { 6997 synchronized(mWindowMap) { 6998 mTraversalScheduled = false; 6999 performLayoutAndPlaceSurfacesLocked(); 7000 } 7001 } break; 7002 7003 case ADD_STARTING: { 7004 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7005 final StartingData sd = wtoken.startingData; 7006 7007 if (sd == null) { 7008 // Animation has been canceled... do nothing. 7009 return; 7010 } 7011 7012 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7013 + wtoken + ": pkg=" + sd.pkg); 7014 7015 View view = null; 7016 try { 7017 view = mPolicy.addStartingWindow( 7018 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7019 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags); 7020 } catch (Exception e) { 7021 Slog.w(TAG, "Exception when adding starting window", e); 7022 } 7023 7024 if (view != null) { 7025 boolean abort = false; 7026 7027 synchronized(mWindowMap) { 7028 if (wtoken.removed || wtoken.startingData == null) { 7029 // If the window was successfully added, then 7030 // we need to remove it. 7031 if (wtoken.startingWindow != null) { 7032 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7033 "Aborted starting " + wtoken 7034 + ": removed=" + wtoken.removed 7035 + " startingData=" + wtoken.startingData); 7036 wtoken.startingWindow = null; 7037 wtoken.startingData = null; 7038 abort = true; 7039 } 7040 } else { 7041 wtoken.startingView = view; 7042 } 7043 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7044 "Added starting " + wtoken 7045 + ": startingWindow=" 7046 + wtoken.startingWindow + " startingView=" 7047 + wtoken.startingView); 7048 } 7049 7050 if (abort) { 7051 try { 7052 mPolicy.removeStartingWindow(wtoken.token, view); 7053 } catch (Exception e) { 7054 Slog.w(TAG, "Exception when removing starting window", e); 7055 } 7056 } 7057 } 7058 } break; 7059 7060 case REMOVE_STARTING: { 7061 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7062 IBinder token = null; 7063 View view = null; 7064 synchronized (mWindowMap) { 7065 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7066 + wtoken + ": startingWindow=" 7067 + wtoken.startingWindow + " startingView=" 7068 + wtoken.startingView); 7069 if (wtoken.startingWindow != null) { 7070 view = wtoken.startingView; 7071 token = wtoken.token; 7072 wtoken.startingData = null; 7073 wtoken.startingView = null; 7074 wtoken.startingWindow = null; 7075 wtoken.startingDisplayed = false; 7076 } 7077 } 7078 if (view != null) { 7079 try { 7080 mPolicy.removeStartingWindow(token, view); 7081 } catch (Exception e) { 7082 Slog.w(TAG, "Exception when removing starting window", e); 7083 } 7084 } 7085 } break; 7086 7087 case FINISHED_STARTING: { 7088 IBinder token = null; 7089 View view = null; 7090 while (true) { 7091 synchronized (mWindowMap) { 7092 final int N = mFinishedStarting.size(); 7093 if (N <= 0) { 7094 break; 7095 } 7096 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7097 7098 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7099 "Finished starting " + wtoken 7100 + ": startingWindow=" + wtoken.startingWindow 7101 + " startingView=" + wtoken.startingView); 7102 7103 if (wtoken.startingWindow == null) { 7104 continue; 7105 } 7106 7107 view = wtoken.startingView; 7108 token = wtoken.token; 7109 wtoken.startingData = null; 7110 wtoken.startingView = null; 7111 wtoken.startingWindow = null; 7112 wtoken.startingDisplayed = false; 7113 } 7114 7115 try { 7116 mPolicy.removeStartingWindow(token, view); 7117 } catch (Exception e) { 7118 Slog.w(TAG, "Exception when removing starting window", e); 7119 } 7120 } 7121 } break; 7122 7123 case REPORT_APPLICATION_TOKEN_DRAWN: { 7124 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7125 7126 try { 7127 if (DEBUG_VISIBILITY) Slog.v( 7128 TAG, "Reporting drawn in " + wtoken); 7129 wtoken.appToken.windowsDrawn(); 7130 } catch (RemoteException ex) { 7131 } 7132 } break; 7133 7134 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7135 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7136 7137 boolean nowVisible = msg.arg1 != 0; 7138 boolean nowGone = msg.arg2 != 0; 7139 7140 try { 7141 if (DEBUG_VISIBILITY) Slog.v( 7142 TAG, "Reporting visible in " + wtoken 7143 + " visible=" + nowVisible 7144 + " gone=" + nowGone); 7145 if (nowVisible) { 7146 wtoken.appToken.windowsVisible(); 7147 } else { 7148 wtoken.appToken.windowsGone(); 7149 } 7150 } catch (RemoteException ex) { 7151 } 7152 } break; 7153 7154 case WINDOW_FREEZE_TIMEOUT: { 7155 synchronized (mWindowMap) { 7156 Slog.w(TAG, "Window freeze timeout expired."); 7157 int i = mWindows.size(); 7158 while (i > 0) { 7159 i--; 7160 WindowState w = mWindows.get(i); 7161 if (w.mOrientationChanging) { 7162 w.mOrientationChanging = false; 7163 Slog.w(TAG, "Force clearing orientation change: " + w); 7164 } 7165 } 7166 performLayoutAndPlaceSurfacesLocked(); 7167 } 7168 break; 7169 } 7170 7171 case HOLD_SCREEN_CHANGED: { 7172 Session oldHold; 7173 Session newHold; 7174 synchronized (mWindowMap) { 7175 oldHold = mLastReportedHold; 7176 newHold = (Session)msg.obj; 7177 mLastReportedHold = newHold; 7178 } 7179 7180 if (oldHold != newHold) { 7181 try { 7182 if (oldHold != null) { 7183 mBatteryStats.noteStopWakelock(oldHold.mUid, -1, 7184 "window", 7185 BatteryStats.WAKE_TYPE_WINDOW); 7186 } 7187 if (newHold != null) { 7188 mBatteryStats.noteStartWakelock(newHold.mUid, -1, 7189 "window", 7190 BatteryStats.WAKE_TYPE_WINDOW); 7191 } 7192 } catch (RemoteException e) { 7193 } 7194 } 7195 break; 7196 } 7197 7198 case APP_TRANSITION_TIMEOUT: { 7199 synchronized (mWindowMap) { 7200 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 7201 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7202 "*** APP TRANSITION TIMEOUT"); 7203 mAppTransitionReady = true; 7204 mAppTransitionTimeout = true; 7205 mAnimatingAppTokens.clear(); 7206 mAnimatingAppTokens.addAll(mAppTokens); 7207 performLayoutAndPlaceSurfacesLocked(); 7208 } 7209 } 7210 break; 7211 } 7212 7213 case PERSIST_ANIMATION_SCALE: { 7214 Settings.System.putFloat(mContext.getContentResolver(), 7215 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 7216 Settings.System.putFloat(mContext.getContentResolver(), 7217 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 7218 Settings.System.putFloat(mContext.getContentResolver(), 7219 Settings.System.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 7220 break; 7221 } 7222 7223 case FORCE_GC: { 7224 synchronized (mWindowMap) { 7225 synchronized (mAnimator) { 7226 // Since we're holding both mWindowMap and mAnimator we don't need to 7227 // hold mAnimator.mLayoutToAnim. 7228 if (mAnimator.mAnimating || mLayoutToAnim.mAnimationScheduled) { 7229 // If we are animating, don't do the gc now but 7230 // delay a bit so we don't interrupt the animation. 7231 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 7232 2000); 7233 return; 7234 } 7235 // If we are currently rotating the display, it will 7236 // schedule a new message when done. 7237 if (mDisplayFrozen) { 7238 return; 7239 } 7240 } 7241 } 7242 Runtime.getRuntime().gc(); 7243 break; 7244 } 7245 7246 case ENABLE_SCREEN: { 7247 performEnableScreen(); 7248 break; 7249 } 7250 7251 case APP_FREEZE_TIMEOUT: { 7252 synchronized (mWindowMap) { 7253 synchronized (mAnimator) { 7254 Slog.w(TAG, "App freeze timeout expired."); 7255 int i = mAppTokens.size(); 7256 while (i > 0) { 7257 i--; 7258 AppWindowToken tok = mAppTokens.get(i); 7259 if (tok.mAppAnimator.freezingScreen) { 7260 Slog.w(TAG, "Force clearing freeze: " + tok); 7261 unsetAppFreezingScreenLocked(tok, true, true); 7262 } 7263 } 7264 } 7265 } 7266 break; 7267 } 7268 7269 case SEND_NEW_CONFIGURATION: { 7270 removeMessages(SEND_NEW_CONFIGURATION); 7271 sendNewConfiguration(); 7272 break; 7273 } 7274 7275 case REPORT_WINDOWS_CHANGE: { 7276 if (mWindowsChanged) { 7277 synchronized (mWindowMap) { 7278 mWindowsChanged = false; 7279 } 7280 notifyWindowsChanged(); 7281 } 7282 break; 7283 } 7284 7285 case DRAG_START_TIMEOUT: { 7286 IBinder win = (IBinder)msg.obj; 7287 if (DEBUG_DRAG) { 7288 Slog.w(TAG, "Timeout starting drag by win " + win); 7289 } 7290 synchronized (mWindowMap) { 7291 // !!! TODO: ANR the app that has failed to start the drag in time 7292 if (mDragState != null) { 7293 mDragState.unregister(); 7294 mInputMonitor.updateInputWindowsLw(true /*force*/); 7295 mDragState.reset(); 7296 mDragState = null; 7297 } 7298 } 7299 break; 7300 } 7301 7302 case DRAG_END_TIMEOUT: { 7303 IBinder win = (IBinder)msg.obj; 7304 if (DEBUG_DRAG) { 7305 Slog.w(TAG, "Timeout ending drag to win " + win); 7306 } 7307 synchronized (mWindowMap) { 7308 // !!! TODO: ANR the drag-receiving app 7309 if (mDragState != null) { 7310 mDragState.mDragResult = false; 7311 mDragState.endDragLw(); 7312 } 7313 } 7314 break; 7315 } 7316 7317 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7318 notifyHardKeyboardStatusChange(); 7319 break; 7320 } 7321 7322 case BOOT_TIMEOUT: { 7323 performBootTimeout(); 7324 break; 7325 } 7326 7327 case WAITING_FOR_DRAWN_TIMEOUT: { 7328 Pair<WindowState, IRemoteCallback> pair; 7329 synchronized (mWindowMap) { 7330 pair = (Pair<WindowState, IRemoteCallback>)msg.obj; 7331 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first); 7332 if (!mWaitingForDrawn.remove(pair)) { 7333 return; 7334 } 7335 } 7336 try { 7337 pair.second.sendResult(null); 7338 } catch (RemoteException e) { 7339 } 7340 break; 7341 } 7342 7343 case UPDATE_ANIM_PARAMETERS: { 7344 // Used to send multiple changes from the animation side to the layout side. 7345 synchronized (mWindowMap) { 7346 if (copyAnimToLayoutParamsLocked()) { 7347 mH.sendEmptyMessage(CLEAR_PENDING_ACTIONS); 7348 performLayoutAndPlaceSurfacesLocked(); 7349 } 7350 } 7351 break; 7352 } 7353 7354 case SHOW_STRICT_MODE_VIOLATION: { 7355 showStrictModeViolation(msg.arg1); 7356 break; 7357 } 7358 7359 // Animation messages. Move to Window{State}Animator 7360 case SET_TRANSPARENT_REGION: { 7361 Pair<WindowStateAnimator, Region> pair = 7362 (Pair<WindowStateAnimator, Region>) msg.obj; 7363 final WindowStateAnimator winAnimator = pair.first; 7364 winAnimator.setTransparentRegionHint(pair.second); 7365 break; 7366 } 7367 7368 case CLEAR_PENDING_ACTIONS: { 7369 mAnimator.clearPendingActions(); 7370 break; 7371 } 7372 7373 case DO_ANIMATION_CALLBACK: { 7374 try { 7375 ((IRemoteCallback)msg.obj).sendResult(null); 7376 } catch (RemoteException e) { 7377 } 7378 break; 7379 } 7380 } 7381 if (DEBUG_WINDOW_TRACE) { 7382 Slog.v(TAG, "handleMessage: exit"); 7383 } 7384 } 7385 } 7386 7387 // ------------------------------------------------------------- 7388 // IWindowManager API 7389 // ------------------------------------------------------------- 7390 7391 @Override 7392 public IWindowSession openSession(IInputMethodClient client, 7393 IInputContext inputContext) { 7394 if (client == null) throw new IllegalArgumentException("null client"); 7395 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7396 Session session = new Session(this, client, inputContext); 7397 return session; 7398 } 7399 7400 @Override 7401 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7402 synchronized (mWindowMap) { 7403 // The focus for the client is the window immediately below 7404 // where we would place the input method window. 7405 int idx = findDesiredInputMethodWindowIndexLocked(false); 7406 WindowState imFocus; 7407 if (idx > 0) { 7408 imFocus = mWindows.get(idx-1); 7409 if (DEBUG_INPUT_METHOD) { 7410 Slog.i(TAG, "Desired input method target: " + imFocus); 7411 Slog.i(TAG, "Current focus: " + this.mCurrentFocus); 7412 Slog.i(TAG, "Last focus: " + this.mLastFocus); 7413 } 7414 if (imFocus != null) { 7415 // This may be a starting window, in which case we still want 7416 // to count it as okay. 7417 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7418 && imFocus.mAppToken != null) { 7419 // The client has definitely started, so it really should 7420 // have a window in this app token. Let's look for it. 7421 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7422 WindowState w = imFocus.mAppToken.windows.get(i); 7423 if (w != imFocus) { 7424 Log.i(TAG, "Switching to real app window: " + w); 7425 imFocus = w; 7426 break; 7427 } 7428 } 7429 } 7430 if (DEBUG_INPUT_METHOD) { 7431 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7432 if (imFocus.mSession.mClient != null) { 7433 Slog.i(TAG, "IM target client binder: " 7434 + imFocus.mSession.mClient.asBinder()); 7435 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7436 } 7437 } 7438 if (imFocus.mSession.mClient != null && 7439 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7440 return true; 7441 } 7442 7443 // Okay, how about this... what is the current focus? 7444 // It seems in some cases we may not have moved the IM 7445 // target window, such as when it was in a pop-up window, 7446 // so let's also look at the current focus. (An example: 7447 // go to Gmail, start searching so the keyboard goes up, 7448 // press home. Sometimes the IME won't go down.) 7449 // Would be nice to fix this more correctly, but it's 7450 // way at the end of a release, and this should be good enough. 7451 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null && 7452 mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7453 return true; 7454 } 7455 } 7456 } 7457 } 7458 return false; 7459 } 7460 7461 public void getDisplaySize(Point size) { 7462 synchronized(mDisplaySizeLock) { 7463 size.x = mAppDisplayWidth; 7464 size.y = mAppDisplayHeight; 7465 } 7466 } 7467 7468 public void getRealDisplaySize(Point size) { 7469 synchronized(mDisplaySizeLock) { 7470 size.x = mCurDisplayWidth; 7471 size.y = mCurDisplayHeight; 7472 } 7473 } 7474 7475 public void getInitialDisplaySize(Point size) { 7476 synchronized(mDisplaySizeLock) { 7477 size.x = mInitialDisplayWidth; 7478 size.y = mInitialDisplayHeight; 7479 } 7480 } 7481 7482 public int getMaximumSizeDimension() { 7483 synchronized(mDisplaySizeLock) { 7484 // Do this based on the raw screen size, until we are smarter. 7485 return mBaseDisplayWidth > mBaseDisplayHeight 7486 ? mBaseDisplayWidth : mBaseDisplayHeight; 7487 } 7488 } 7489 7490 public void getCurrentSizeRange(Point smallestSize, Point largestSize) { 7491 synchronized(mDisplaySizeLock) { 7492 smallestSize.x = mSmallestDisplayWidth; 7493 smallestSize.y = mSmallestDisplayHeight; 7494 largestSize.x = mLargestDisplayWidth; 7495 largestSize.y = mLargestDisplayHeight; 7496 } 7497 } 7498 7499 public void setForcedDisplaySize(int longDimen, int shortDimen) { 7500 synchronized(mWindowMap) { 7501 int width, height; 7502 if (mInitialDisplayWidth < mInitialDisplayHeight) { 7503 width = shortDimen < mInitialDisplayWidth 7504 ? shortDimen : mInitialDisplayWidth; 7505 height = longDimen < mInitialDisplayHeight 7506 ? longDimen : mInitialDisplayHeight; 7507 } else { 7508 width = longDimen < mInitialDisplayWidth 7509 ? longDimen : mInitialDisplayWidth; 7510 height = shortDimen < mInitialDisplayHeight 7511 ? shortDimen : mInitialDisplayHeight; 7512 } 7513 setForcedDisplaySizeLocked(width, height); 7514 Settings.Secure.putString(mContext.getContentResolver(), 7515 Settings.Secure.DISPLAY_SIZE_FORCED, width + "," + height); 7516 } 7517 } 7518 7519 private void rebuildBlackFrame() { 7520 if (mBlackFrame != null) { 7521 mBlackFrame.kill(); 7522 mBlackFrame = null; 7523 } 7524 if (mBaseDisplayWidth < mInitialDisplayWidth 7525 || mBaseDisplayHeight < mInitialDisplayHeight) { 7526 int initW, initH, baseW, baseH; 7527 final boolean rotated = (mRotation == Surface.ROTATION_90 7528 || mRotation == Surface.ROTATION_270); 7529 if (rotated) { 7530 initW = mInitialDisplayHeight; 7531 initH = mInitialDisplayWidth; 7532 baseW = mBaseDisplayHeight; 7533 baseH = mBaseDisplayWidth; 7534 } else { 7535 initW = mInitialDisplayWidth; 7536 initH = mInitialDisplayHeight; 7537 baseW = mBaseDisplayWidth; 7538 baseH = mBaseDisplayHeight; 7539 } 7540 Rect outer = new Rect(0, 0, initW, initH); 7541 Rect inner = new Rect(0, 0, baseW, baseH); 7542 try { 7543 mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER); 7544 } catch (Surface.OutOfResourcesException e) { 7545 } 7546 } 7547 } 7548 7549 private void readForcedDisplaySizeLocked() { 7550 final String str = Settings.Secure.getString(mContext.getContentResolver(), 7551 Settings.Secure.DISPLAY_SIZE_FORCED); 7552 if (str == null || str.length() == 0) { 7553 return; 7554 } 7555 final int pos = str.indexOf(','); 7556 if (pos <= 0 || str.lastIndexOf(',') != pos) { 7557 return; 7558 } 7559 int width, height; 7560 try { 7561 width = Integer.parseInt(str.substring(0, pos)); 7562 height = Integer.parseInt(str.substring(pos+1)); 7563 } catch (NumberFormatException ex) { 7564 return; 7565 } 7566 setForcedDisplaySizeLocked(width, height); 7567 } 7568 7569 private void setForcedDisplaySizeLocked(int width, int height) { 7570 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7571 7572 synchronized(mDisplaySizeLock) { 7573 mBaseDisplayWidth = width; 7574 mBaseDisplayHeight = height; 7575 } 7576 mPolicy.setInitialDisplaySize(mDisplay, mBaseDisplayWidth, mBaseDisplayHeight); 7577 7578 mLayoutNeeded = true; 7579 7580 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7581 mTempConfiguration.setToDefaults(); 7582 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7583 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7584 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7585 configChanged = true; 7586 } 7587 } 7588 7589 if (configChanged) { 7590 mWaitingForConfig = true; 7591 startFreezingDisplayLocked(false); 7592 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7593 } 7594 7595 rebuildBlackFrame(); 7596 7597 performLayoutAndPlaceSurfacesLocked(); 7598 } 7599 7600 public void clearForcedDisplaySize() { 7601 synchronized(mWindowMap) { 7602 setForcedDisplaySizeLocked(mInitialDisplayWidth, mInitialDisplayHeight); 7603 Settings.Secure.putString(mContext.getContentResolver(), 7604 Settings.Secure.DISPLAY_SIZE_FORCED, ""); 7605 } 7606 } 7607 7608 public boolean hasSystemNavBar() { 7609 return mPolicy.hasSystemNavBar(); 7610 } 7611 7612 // ------------------------------------------------------------- 7613 // Internals 7614 // ------------------------------------------------------------- 7615 7616 final WindowState windowForClientLocked(Session session, IWindow client, 7617 boolean throwOnError) { 7618 return windowForClientLocked(session, client.asBinder(), throwOnError); 7619 } 7620 7621 final WindowState windowForClientLocked(Session session, IBinder client, 7622 boolean throwOnError) { 7623 WindowState win = mWindowMap.get(client); 7624 if (localLOGV) Slog.v( 7625 TAG, "Looking up client " + client + ": " + win); 7626 if (win == null) { 7627 RuntimeException ex = new IllegalArgumentException( 7628 "Requested window " + client + " does not exist"); 7629 if (throwOnError) { 7630 throw ex; 7631 } 7632 Slog.w(TAG, "Failed looking up window", ex); 7633 return null; 7634 } 7635 if (session != null && win.mSession != session) { 7636 RuntimeException ex = new IllegalArgumentException( 7637 "Requested window " + client + " is in session " + 7638 win.mSession + ", not " + session); 7639 if (throwOnError) { 7640 throw ex; 7641 } 7642 Slog.w(TAG, "Failed looking up window", ex); 7643 return null; 7644 } 7645 7646 return win; 7647 } 7648 7649 final void rebuildAppWindowListLocked() { 7650 int NW = mWindows.size(); 7651 int i; 7652 int lastBelow = -1; 7653 int numRemoved = 0; 7654 7655 if (mRebuildTmp.length < NW) { 7656 mRebuildTmp = new WindowState[NW+10]; 7657 } 7658 7659 // First remove all existing app windows. 7660 i=0; 7661 while (i < NW) { 7662 WindowState w = mWindows.get(i); 7663 if (w.mAppToken != null) { 7664 WindowState win = mWindows.remove(i); 7665 win.mRebuilding = true; 7666 mRebuildTmp[numRemoved] = win; 7667 mWindowsChanged = true; 7668 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 7669 "Rebuild removing window: " + win); 7670 NW--; 7671 numRemoved++; 7672 continue; 7673 } else if (lastBelow == i-1) { 7674 if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER 7675 || w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) { 7676 lastBelow = i; 7677 } 7678 } 7679 i++; 7680 } 7681 7682 // Keep whatever windows were below the app windows still below, 7683 // by skipping them. 7684 lastBelow++; 7685 i = lastBelow; 7686 7687 // First add all of the exiting app tokens... these are no longer 7688 // in the main app list, but still have windows shown. We put them 7689 // in the back because now that the animation is over we no longer 7690 // will care about them. 7691 int NT = mExitingAppTokens.size(); 7692 for (int j=0; j<NT; j++) { 7693 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j)); 7694 } 7695 7696 // And add in the still active app tokens in Z order. 7697 NT = mAnimatingAppTokens.size(); 7698 for (int j=0; j<NT; j++) { 7699 i = reAddAppWindowsLocked(i, mAnimatingAppTokens.get(j)); 7700 } 7701 7702 i -= lastBelow; 7703 if (i != numRemoved) { 7704 Slog.w(TAG, "Rebuild removed " + numRemoved 7705 + " windows but added " + i); 7706 for (i=0; i<numRemoved; i++) { 7707 WindowState ws = mRebuildTmp[i]; 7708 if (ws.mRebuilding) { 7709 StringWriter sw = new StringWriter(); 7710 PrintWriter pw = new PrintWriter(sw); 7711 ws.dump(pw, "", true); 7712 pw.flush(); 7713 Slog.w(TAG, "This window was lost: " + ws); 7714 Slog.w(TAG, sw.toString()); 7715 ws.mWinAnimator.destroySurfaceLocked(); 7716 } 7717 } 7718 Slog.w(TAG, "Current app token list:"); 7719 dumpAnimatingAppTokensLocked(); 7720 Slog.w(TAG, "Final window list:"); 7721 dumpWindowsLocked(); 7722 } 7723 } 7724 7725 private final void assignLayersLocked() { 7726 int N = mWindows.size(); 7727 int curBaseLayer = 0; 7728 int curLayer = 0; 7729 int i; 7730 7731 if (DEBUG_LAYERS) { 7732 RuntimeException here = new RuntimeException("here"); 7733 here.fillInStackTrace(); 7734 Slog.v(TAG, "Assigning layers", here); 7735 } 7736 7737 for (i=0; i<N; i++) { 7738 final WindowState w = mWindows.get(i); 7739 final WindowStateAnimator winAnimator = w.mWinAnimator; 7740 boolean layerChanged = false; 7741 int oldLayer = w.mLayer; 7742 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 7743 || (i > 0 && w.mIsWallpaper)) { 7744 curLayer += WINDOW_LAYER_MULTIPLIER; 7745 w.mLayer = curLayer; 7746 } else { 7747 curBaseLayer = curLayer = w.mBaseLayer; 7748 w.mLayer = curLayer; 7749 } 7750 if (w.mLayer != oldLayer) { 7751 layerChanged = true; 7752 } 7753 oldLayer = winAnimator.mAnimLayer; 7754 if (w.mTargetAppToken != null) { 7755 winAnimator.mAnimLayer = 7756 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 7757 } else if (w.mAppToken != null) { 7758 winAnimator.mAnimLayer = 7759 w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment; 7760 } else { 7761 winAnimator.mAnimLayer = w.mLayer; 7762 } 7763 if (w.mIsImWindow) { 7764 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 7765 } else if (w.mIsWallpaper) { 7766 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 7767 } 7768 if (winAnimator.mAnimLayer != oldLayer) { 7769 layerChanged = true; 7770 } 7771 if (layerChanged && mAnimator.isDimming(winAnimator)) { 7772 // Force an animation pass just to update the mDimAnimator layer. 7773 updateLayoutToAnimationLocked(); 7774 } 7775 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 7776 + winAnimator.mAnimLayer); 7777 //System.out.println( 7778 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 7779 } 7780 } 7781 7782 private boolean mInLayout = false; 7783 private final void performLayoutAndPlaceSurfacesLocked() { 7784 if (mInLayout) { 7785 if (DEBUG) { 7786 throw new RuntimeException("Recursive call!"); 7787 } 7788 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 7789 + Debug.getCallers(3)); 7790 return; 7791 } 7792 7793 if (mWaitingForConfig) { 7794 // Our configuration has changed (most likely rotation), but we 7795 // don't yet have the complete configuration to report to 7796 // applications. Don't do any window layout until we have it. 7797 return; 7798 } 7799 7800 if (mDisplay == null) { 7801 // Not yet initialized, nothing to do. 7802 return; 7803 } 7804 7805 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 7806 mInLayout = true; 7807 boolean recoveringMemory = false; 7808 7809 try { 7810 if (mForceRemoves != null) { 7811 recoveringMemory = true; 7812 // Wait a little bit for things to settle down, and off we go. 7813 for (int i=0; i<mForceRemoves.size(); i++) { 7814 WindowState ws = mForceRemoves.get(i); 7815 Slog.i(TAG, "Force removing: " + ws); 7816 removeWindowInnerLocked(ws.mSession, ws); 7817 } 7818 mForceRemoves = null; 7819 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 7820 Object tmp = new Object(); 7821 synchronized (tmp) { 7822 try { 7823 tmp.wait(250); 7824 } catch (InterruptedException e) { 7825 } 7826 } 7827 } 7828 } catch (RuntimeException e) { 7829 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 7830 } 7831 7832 try { 7833 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 7834 7835 final int N = mPendingRemove.size(); 7836 if (N > 0) { 7837 if (mPendingRemoveTmp.length < N) { 7838 mPendingRemoveTmp = new WindowState[N+10]; 7839 } 7840 mPendingRemove.toArray(mPendingRemoveTmp); 7841 mPendingRemove.clear(); 7842 for (int i=0; i<N; i++) { 7843 WindowState w = mPendingRemoveTmp[i]; 7844 removeWindowInnerLocked(w.mSession, w); 7845 } 7846 7847 mInLayout = false; 7848 assignLayersLocked(); 7849 mLayoutNeeded = true; 7850 // XXX this recursion seems broken! 7851 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 7852 performLayoutAndPlaceSurfacesLocked(); 7853 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 7854 7855 } else { 7856 mInLayout = false; 7857 } 7858 7859 if (mLayoutNeeded) { 7860 if (++mLayoutRepeatCount < 6) { 7861 requestTraversalLocked(); 7862 } else { 7863 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 7864 mLayoutRepeatCount = 0; 7865 } 7866 } else { 7867 mLayoutRepeatCount = 0; 7868 } 7869 7870 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 7871 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 7872 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE)); 7873 } 7874 } catch (RuntimeException e) { 7875 mInLayout = false; 7876 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 7877 } 7878 7879 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 7880 } 7881 7882 private final void performLayoutLockedInner(boolean initial, boolean updateInputWindows) { 7883 if (!mLayoutNeeded) { 7884 return; 7885 } 7886 7887 mLayoutNeeded = false; 7888 7889 final int dw = mCurDisplayWidth; 7890 final int dh = mCurDisplayHeight; 7891 7892 final int NFW = mFakeWindows.size(); 7893 for (int i=0; i<NFW; i++) { 7894 mFakeWindows.get(i).layout(dw, dh); 7895 } 7896 7897 final int N = mWindows.size(); 7898 int i; 7899 7900 if (DEBUG_LAYOUT) { 7901 Slog.v(TAG, "-------------------------------------"); 7902 Slog.v(TAG, "performLayout: needed=" 7903 + mLayoutNeeded + " dw=" + dw + " dh=" + dh); 7904 } 7905 7906 WindowStateAnimator universeBackground = null; 7907 7908 mPolicy.beginLayoutLw(dw, dh, mRotation); 7909 mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect); 7910 mScreenRect.set(0, 0, dw, dh); 7911 7912 int seq = mLayoutSeq+1; 7913 if (seq < 0) seq = 0; 7914 mLayoutSeq = seq; 7915 7916 // First perform layout of any root windows (not attached 7917 // to another window). 7918 int topAttached = -1; 7919 for (i = N-1; i >= 0; i--) { 7920 final WindowState win = mWindows.get(i); 7921 7922 // Don't do layout of a window if it is not visible, or 7923 // soon won't be visible, to avoid wasting time and funky 7924 // changes while a window is animating away. 7925 final boolean gone = win.isGoneForLayoutLw(); 7926 7927 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 7928 Slog.v(TAG, "1ST PASS " + win 7929 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 7930 + " mLayoutAttached=" + win.mLayoutAttached); 7931 final AppWindowToken atoken = win.mAppToken; 7932 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 7933 + win.mViewVisibility + " mRelayoutCalled=" 7934 + win.mRelayoutCalled + " hidden=" 7935 + win.mRootToken.hidden + " hiddenRequested=" 7936 + (atoken != null && atoken.hiddenRequested) 7937 + " mAttachedHidden=" + win.mAttachedHidden); 7938 else Slog.v(TAG, " VIS: mViewVisibility=" 7939 + win.mViewVisibility + " mRelayoutCalled=" 7940 + win.mRelayoutCalled + " hidden=" 7941 + win.mRootToken.hidden + " hiddenRequested=" 7942 + (atoken != null && atoken.hiddenRequested) 7943 + " mAttachedHidden=" + win.mAttachedHidden); 7944 } 7945 7946 // If this view is GONE, then skip it -- keep the current 7947 // frame, and let the caller know so they can ignore it 7948 // if they want. (We do the normal layout for INVISIBLE 7949 // windows, since that means "perform layout as normal, 7950 // just don't display"). 7951 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 7952 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 7953 if (!win.mLayoutAttached) { 7954 if (initial) { 7955 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7956 win.mContentChanged = false; 7957 } 7958 win.mLayoutNeeded = false; 7959 win.prelayout(); 7960 mPolicy.layoutWindowLw(win, win.mAttrs, null); 7961 win.mLayoutSeq = seq; 7962 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7963 + win.mFrame + " mContainingFrame=" 7964 + win.mContainingFrame + " mDisplayFrame=" 7965 + win.mDisplayFrame); 7966 } else { 7967 if (topAttached < 0) topAttached = i; 7968 } 7969 } 7970 if (win.mViewVisibility == View.VISIBLE 7971 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 7972 && universeBackground == null) { 7973 universeBackground = win.mWinAnimator; 7974 } 7975 } 7976 7977 if (mAnimator.mUniverseBackground != universeBackground) { 7978 mFocusMayChange = true; 7979 mAnimator.mUniverseBackground = universeBackground; 7980 } 7981 7982 // Now perform layout of attached windows, which usually 7983 // depend on the position of the window they are attached to. 7984 // XXX does not deal with windows that are attached to windows 7985 // that are themselves attached. 7986 for (i = topAttached; i >= 0; i--) { 7987 final WindowState win = mWindows.get(i); 7988 7989 if (win.mLayoutAttached) { 7990 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 7991 + " mHaveFrame=" + win.mHaveFrame 7992 + " mViewVisibility=" + win.mViewVisibility 7993 + " mRelayoutCalled=" + win.mRelayoutCalled); 7994 // If this view is GONE, then skip it -- keep the current 7995 // frame, and let the caller know so they can ignore it 7996 // if they want. (We do the normal layout for INVISIBLE 7997 // windows, since that means "perform layout as normal, 7998 // just don't display"). 7999 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8000 || !win.mHaveFrame || win.mLayoutNeeded) { 8001 if (initial) { 8002 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8003 win.mContentChanged = false; 8004 } 8005 win.mLayoutNeeded = false; 8006 win.prelayout(); 8007 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 8008 win.mLayoutSeq = seq; 8009 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8010 + win.mFrame + " mContainingFrame=" 8011 + win.mContainingFrame + " mDisplayFrame=" 8012 + win.mDisplayFrame); 8013 } 8014 } 8015 } 8016 8017 // Window frames may have changed. Tell the input dispatcher about it. 8018 mInputMonitor.setUpdateInputWindowsNeededLw(); 8019 if (updateInputWindows) { 8020 mInputMonitor.updateInputWindowsLw(false /*force*/); 8021 } 8022 8023 mPolicy.finishLayoutLw(); 8024 } 8025 8026 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8027 // If the screen is currently frozen or off, then keep 8028 // it frozen/off until this window draws at its new 8029 // orientation. 8030 if (!okToDisplay()) { 8031 if (DEBUG_ORIENTATION) Slog.v(TAG, 8032 "Changing surface while display frozen: " + w); 8033 w.mOrientationChanging = true; 8034 mInnerFields.mOrientationChangeComplete = false; 8035 if (!mWindowsFreezingScreen) { 8036 mWindowsFreezingScreen = true; 8037 // XXX should probably keep timeout from 8038 // when we first froze the display. 8039 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8040 mH.sendMessageDelayed(mH.obtainMessage( 8041 H.WINDOW_FREEZE_TIMEOUT), 2000); 8042 } 8043 } 8044 } 8045 8046 /** 8047 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8048 * 8049 * @return bitmap indicating if another pass through layout must be made. 8050 */ 8051 public int handleAppTransitionReadyLocked() { 8052 int changes = 0; 8053 int i; 8054 int NN = mOpeningApps.size(); 8055 boolean goodToGo = true; 8056 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8057 "Checking " + NN + " opening apps (frozen=" 8058 + mDisplayFrozen + " timeout=" 8059 + mAppTransitionTimeout + ")..."); 8060 if (!mDisplayFrozen && !mAppTransitionTimeout) { 8061 // If the display isn't frozen, wait to do anything until 8062 // all of the apps are ready. Otherwise just go because 8063 // we'll unfreeze the display when everyone is ready. 8064 for (i=0; i<NN && goodToGo; i++) { 8065 AppWindowToken wtoken = mOpeningApps.get(i); 8066 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8067 "Check opening app=" + wtoken + ": allDrawn=" 8068 + wtoken.allDrawn + " startingDisplayed=" 8069 + wtoken.startingDisplayed + " startingMoved=" 8070 + wtoken.startingMoved); 8071 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8072 && !wtoken.startingMoved) { 8073 goodToGo = false; 8074 } 8075 } 8076 } 8077 if (goodToGo) { 8078 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8079 int transit = mNextAppTransition; 8080 if (mSkipAppTransitionAnimation) { 8081 transit = WindowManagerPolicy.TRANSIT_UNSET; 8082 } 8083 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 8084 mAppTransitionReady = false; 8085 mAppTransitionRunning = true; 8086 mAppTransitionTimeout = false; 8087 mStartingIconInTransition = false; 8088 mSkipAppTransitionAnimation = false; 8089 8090 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8091 8092 rebuildAppWindowListLocked(); 8093 8094 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8095 WindowState oldWallpaper = 8096 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8097 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8098 ? null : mWallpaperTarget; 8099 8100 adjustWallpaperWindowsLocked(); 8101 mInnerFields.mWallpaperMayChange = false; 8102 8103 // The top-most window will supply the layout params, 8104 // and we will determine it below. 8105 LayoutParams animLp = null; 8106 int bestAnimLayer = -1; 8107 boolean fullscreenAnim = false; 8108 8109 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8110 "New wallpaper target=" + mWallpaperTarget 8111 + ", oldWallpaper=" + oldWallpaper 8112 + ", lower target=" + mLowerWallpaperTarget 8113 + ", upper target=" + mUpperWallpaperTarget); 8114 int foundWallpapers = 0; 8115 // Do a first pass through the tokens for two 8116 // things: 8117 // (1) Determine if both the closing and opening 8118 // app token sets are wallpaper targets, in which 8119 // case special animations are needed 8120 // (since the wallpaper needs to stay static 8121 // behind them). 8122 // (2) Find the layout params of the top-most 8123 // application window in the tokens, which is 8124 // what will control the animation theme. 8125 final int NC = mClosingApps.size(); 8126 NN = NC + mOpeningApps.size(); 8127 for (i=0; i<NN; i++) { 8128 AppWindowToken wtoken; 8129 int mode; 8130 if (i < NC) { 8131 wtoken = mClosingApps.get(i); 8132 mode = 1; 8133 } else { 8134 wtoken = mOpeningApps.get(i-NC); 8135 mode = 2; 8136 } 8137 if (mLowerWallpaperTarget != null) { 8138 if (mLowerWallpaperTarget.mAppToken == wtoken 8139 || mUpperWallpaperTarget.mAppToken == wtoken) { 8140 foundWallpapers |= mode; 8141 } 8142 } 8143 if (wtoken.appFullscreen) { 8144 WindowState ws = wtoken.findMainWindow(); 8145 if (ws != null) { 8146 animLp = ws.mAttrs; 8147 bestAnimLayer = ws.mLayer; 8148 fullscreenAnim = true; 8149 } 8150 } else if (!fullscreenAnim) { 8151 WindowState ws = wtoken.findMainWindow(); 8152 if (ws != null) { 8153 if (ws.mLayer > bestAnimLayer) { 8154 animLp = ws.mAttrs; 8155 bestAnimLayer = ws.mLayer; 8156 } 8157 } 8158 } 8159 } 8160 8161 if (foundWallpapers == 3) { 8162 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8163 "Wallpaper animation!"); 8164 switch (transit) { 8165 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 8166 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 8167 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 8168 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN; 8169 break; 8170 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 8171 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 8172 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 8173 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE; 8174 break; 8175 } 8176 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8177 "New transit: " + transit); 8178 } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8179 // We are transitioning from an activity with 8180 // a wallpaper to one without. 8181 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE; 8182 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8183 "New transit away from wallpaper: " + transit); 8184 } else if (mWallpaperTarget != null) { 8185 // We are transitioning from an activity without 8186 // a wallpaper to now showing the wallpaper 8187 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN; 8188 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8189 "New transit into wallpaper: " + transit); 8190 } 8191 8192 // If all closing windows are obscured, then there is 8193 // no need to do an animation. This is the case, for 8194 // example, when this transition is being done behind 8195 // the lock screen. 8196 if (!mPolicy.allowAppAnimationsLw()) { 8197 animLp = null; 8198 } 8199 8200 AppWindowToken topOpeningApp = null; 8201 int topOpeningLayer = 0; 8202 8203 NN = mOpeningApps.size(); 8204 for (i=0; i<NN; i++) { 8205 AppWindowToken wtoken = mOpeningApps.get(i); 8206 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8207 wtoken.mAppAnimator.clearThumbnail(); 8208 wtoken.reportedVisible = false; 8209 wtoken.inPendingTransaction = false; 8210 wtoken.mAppAnimator.animation = null; 8211 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 8212 wtoken.updateReportedVisibilityLocked(); 8213 wtoken.waitingToShow = false; 8214 mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked(); 8215 if (animLp != null) { 8216 int layer = -1; 8217 for (int j=0; j<wtoken.windows.size(); j++) { 8218 WindowState win = wtoken.windows.get(j); 8219 if (win.mWinAnimator.mAnimLayer > layer) { 8220 layer = win.mWinAnimator.mAnimLayer; 8221 } 8222 } 8223 if (topOpeningApp == null || layer > topOpeningLayer) { 8224 topOpeningApp = wtoken; 8225 topOpeningLayer = layer; 8226 } 8227 } 8228 } 8229 NN = mClosingApps.size(); 8230 for (i=0; i<NN; i++) { 8231 AppWindowToken wtoken = mClosingApps.get(i); 8232 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8233 "Now closing app" + wtoken); 8234 wtoken.mAppAnimator.clearThumbnail(); 8235 wtoken.inPendingTransaction = false; 8236 wtoken.mAppAnimator.animation = null; 8237 setTokenVisibilityLocked(wtoken, animLp, false, 8238 transit, false); 8239 wtoken.updateReportedVisibilityLocked(); 8240 wtoken.waitingToHide = false; 8241 // Force the allDrawn flag, because we want to start 8242 // this guy's animations regardless of whether it's 8243 // gotten drawn. 8244 wtoken.allDrawn = true; 8245 } 8246 8247 if (mNextAppTransitionThumbnail != null && topOpeningApp != null 8248 && topOpeningApp.mAppAnimator.animation != null) { 8249 // This thumbnail animation is very special, we need to have 8250 // an extra surface with the thumbnail included with the animation. 8251 Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(), 8252 mNextAppTransitionThumbnail.getHeight()); 8253 try { 8254 Surface surface = new Surface(mFxSession, Process.myPid(), 8255 "thumbnail anim", 0, dirty.width(), dirty.height(), 8256 PixelFormat.TRANSLUCENT, Surface.HIDDEN); 8257 topOpeningApp.mAppAnimator.thumbnail = surface; 8258 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " 8259 + surface + ": CREATE"); 8260 Surface drawSurface = new Surface(); 8261 drawSurface.copyFrom(surface); 8262 Canvas c = drawSurface.lockCanvas(dirty); 8263 c.drawBitmap(mNextAppTransitionThumbnail, 0, 0, null); 8264 drawSurface.unlockCanvasAndPost(c); 8265 drawSurface.release(); 8266 topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer; 8267 Animation anim = createThumbnailAnimationLocked( 8268 transit, true, true, mNextAppTransitionDelayed); 8269 topOpeningApp.mAppAnimator.thumbnailAnimation = anim; 8270 anim.restrictDuration(MAX_ANIMATION_DURATION); 8271 anim.scaleCurrentDuration(mTransitionAnimationScale); 8272 topOpeningApp.mAppAnimator.thumbnailX = mNextAppTransitionStartX; 8273 topOpeningApp.mAppAnimator.thumbnailY = mNextAppTransitionStartY; 8274 } catch (Surface.OutOfResourcesException e) { 8275 Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width() 8276 + " h=" + dirty.height(), e); 8277 topOpeningApp.mAppAnimator.clearThumbnail(); 8278 } 8279 } 8280 8281 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 8282 mNextAppTransitionPackage = null; 8283 mNextAppTransitionThumbnail = null; 8284 scheduleAnimationCallback(mNextAppTransitionCallback); 8285 mNextAppTransitionCallback = null; 8286 8287 mOpeningApps.clear(); 8288 mClosingApps.clear(); 8289 8290 // This has changed the visibility of windows, so perform 8291 // a new layout to get them all up-to-date. 8292 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT 8293 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8294 mLayoutNeeded = true; 8295 if (!moveInputMethodWindowsIfNeededLocked(true)) { 8296 assignLayersLocked(); 8297 } 8298 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8299 false /*updateInputWindows*/); 8300 mFocusMayChange = false; 8301 } 8302 8303 return changes; 8304 } 8305 8306 /** 8307 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8308 * 8309 * @return bitmap indicating if another pass through layout must be made. 8310 */ 8311 private int handleAnimatingStoppedAndTransitionLocked() { 8312 int changes = 0; 8313 8314 mAppTransitionRunning = false; 8315 // Restore window app tokens to the ActivityManager views 8316 for (int i = mAnimatingAppTokens.size() - 1; i >= 0; i--) { 8317 mAnimatingAppTokens.get(i).sendingToBottom = false; 8318 } 8319 mAnimatingAppTokens.clear(); 8320 mAnimatingAppTokens.addAll(mAppTokens); 8321 rebuildAppWindowListLocked(); 8322 8323 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8324 mInnerFields.mAdjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED; 8325 moveInputMethodWindowsIfNeededLocked(true); 8326 mInnerFields.mWallpaperMayChange = true; 8327 // Since the window list has been rebuilt, focus might 8328 // have to be recomputed since the actual order of windows 8329 // might have changed again. 8330 mFocusMayChange = true; 8331 8332 return changes; 8333 } 8334 8335 /** 8336 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8337 * 8338 * @return bitmap indicating if another pass through layout must be made. 8339 */ 8340 private int animateAwayWallpaperLocked() { 8341 int changes = 0; 8342 WindowState oldWallpaper = mWallpaperTarget; 8343 if (mLowerWallpaperTarget != null 8344 && mLowerWallpaperTarget.mAppToken != null) { 8345 if (DEBUG_WALLPAPER) Slog.v(TAG, 8346 "wallpaperForceHiding changed with lower=" 8347 + mLowerWallpaperTarget); 8348 if (DEBUG_WALLPAPER) Slog.v(TAG, 8349 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden + 8350 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested); 8351 if (mLowerWallpaperTarget.mAppToken.hidden) { 8352 // The lower target has become hidden before we 8353 // actually started the animation... let's completely 8354 // re-evaluate everything. 8355 mLowerWallpaperTarget = mUpperWallpaperTarget = null; 8356 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8357 } 8358 } 8359 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 8360 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper 8361 + " NEW: " + mWallpaperTarget 8362 + " LOWER: " + mLowerWallpaperTarget); 8363 return changes; 8364 } 8365 8366 private void updateResizingWindows(final WindowState w) { 8367 final WindowStateAnimator winAnimator = w.mWinAnimator; 8368 if (w.mHasSurface && !w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) { 8369 w.mContentInsetsChanged |= 8370 !w.mLastContentInsets.equals(w.mContentInsets); 8371 w.mVisibleInsetsChanged |= 8372 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 8373 boolean configChanged = 8374 w.mConfiguration != mCurConfiguration 8375 && (w.mConfiguration == null 8376 || mCurConfiguration.diff(w.mConfiguration) != 0); 8377 if (DEBUG_CONFIGURATION && configChanged) { 8378 Slog.v(TAG, "Win " + w + " config changed: " 8379 + mCurConfiguration); 8380 } 8381 if (localLOGV) Slog.v(TAG, "Resizing " + w 8382 + ": configChanged=" + configChanged 8383 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8384 w.mLastFrame.set(w.mFrame); 8385 if (w.mContentInsetsChanged 8386 || w.mVisibleInsetsChanged 8387 || winAnimator.mSurfaceResized 8388 || configChanged) { 8389 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8390 Slog.v(TAG, "Resize reasons: " 8391 + " contentInsetsChanged=" + w.mContentInsetsChanged 8392 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8393 + " surfaceResized=" + winAnimator.mSurfaceResized 8394 + " configChanged=" + configChanged); 8395 } 8396 8397 w.mLastContentInsets.set(w.mContentInsets); 8398 w.mLastVisibleInsets.set(w.mVisibleInsets); 8399 makeWindowFreezingScreenIfNeededLocked(w); 8400 // If the orientation is changing, then we need to 8401 // hold off on unfreezing the display until this 8402 // window has been redrawn; to do that, we need 8403 // to go through the process of getting informed 8404 // by the application when it has finished drawing. 8405 if (w.mOrientationChanging) { 8406 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8407 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8408 + w + ", surface " + winAnimator.mSurface); 8409 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8410 if (w.mAppToken != null) { 8411 w.mAppToken.allDrawn = false; 8412 } 8413 } 8414 if (!mResizingWindows.contains(w)) { 8415 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8416 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8417 + "x" + winAnimator.mSurfaceH); 8418 mResizingWindows.add(w); 8419 } 8420 } else if (w.mOrientationChanging) { 8421 if (w.isDrawnLw()) { 8422 if (DEBUG_ORIENTATION) Slog.v(TAG, 8423 "Orientation not waiting for draw in " 8424 + w + ", surface " + winAnimator.mSurface); 8425 w.mOrientationChanging = false; 8426 } 8427 } 8428 } 8429 } 8430 8431 /** 8432 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8433 * 8434 * @param w WindowState this method is applied to. 8435 * @param currentTime The time which animations use for calculating transitions. 8436 * @param innerDw Width of app window. 8437 * @param innerDh Height of app window. 8438 */ 8439 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8440 final int innerDw, final int innerDh) { 8441 final WindowManager.LayoutParams attrs = w.mAttrs; 8442 final int attrFlags = attrs.flags; 8443 final boolean canBeSeen = w.isDisplayedLw(); 8444 8445 if (w.mHasSurface) { 8446 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8447 mInnerFields.mHoldScreen = w.mSession; 8448 } 8449 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8450 && mInnerFields.mScreenBrightness < 0) { 8451 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8452 } 8453 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8454 && mInnerFields.mButtonBrightness < 0) { 8455 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8456 } 8457 if (canBeSeen 8458 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG 8459 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD 8460 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) { 8461 mInnerFields.mSyswin = true; 8462 } 8463 } 8464 8465 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8466 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8467 // This window completely covers everything behind it, 8468 // so we want to leave all of them as undimmed (for 8469 // performance reasons). 8470 mInnerFields.mObscured = true; 8471 } else if (canBeSeen && (attrFlags & FLAG_DIM_BEHIND) != 0 8472 && !(w.mAppToken != null && w.mAppToken.hiddenRequested) 8473 && !w.mExiting) { 8474 if (localLOGV) Slog.v(TAG, "Win " + w + " obscured=" + mInnerFields.mObscured); 8475 if (!mInnerFields.mDimming) { 8476 //Slog.i(TAG, "DIM BEHIND: " + w); 8477 mInnerFields.mDimming = true; 8478 final WindowStateAnimator winAnimator = w.mWinAnimator; 8479 if (!mAnimator.isDimming(winAnimator)) { 8480 final int width, height; 8481 if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { 8482 width = mCurDisplayWidth; 8483 height = mCurDisplayHeight; 8484 } else { 8485 width = innerDw; 8486 height = innerDh; 8487 } 8488 startDimming(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height); 8489 } 8490 } 8491 } 8492 } 8493 8494 private void updateAllDrawnLocked() { 8495 // See if any windows have been drawn, so they (and others 8496 // associated with them) can now be shown. 8497 final ArrayList<AppWindowToken> appTokens = mAnimatingAppTokens; 8498 final int NT = appTokens.size(); 8499 for (int i=0; i<NT; i++) { 8500 AppWindowToken wtoken = appTokens.get(i); 8501 if (!wtoken.allDrawn) { 8502 int numInteresting = wtoken.numInterestingWindows; 8503 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 8504 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 8505 "allDrawn: " + wtoken 8506 + " interesting=" + numInteresting 8507 + " drawn=" + wtoken.numDrawnWindows); 8508 wtoken.allDrawn = true; 8509 } 8510 } 8511 } 8512 } 8513 8514 // "Something has changed! Let's make it correct now." 8515 private final void performLayoutAndPlaceSurfacesLockedInner( 8516 boolean recoveringMemory) { 8517 if (DEBUG_WINDOW_TRACE) { 8518 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 8519 + Debug.getCallers(3)); 8520 } 8521 if (mDisplay == null) { 8522 Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay"); 8523 return; 8524 } 8525 8526 final long currentTime = SystemClock.uptimeMillis(); 8527 final int dw = mCurDisplayWidth; 8528 final int dh = mCurDisplayHeight; 8529 final int innerDw = mAppDisplayWidth; 8530 final int innerDh = mAppDisplayHeight; 8531 8532 int i; 8533 8534 if (mFocusMayChange) { 8535 mFocusMayChange = false; 8536 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 8537 false /*updateInputWindows*/); 8538 } 8539 8540 // Initialize state of exiting tokens. 8541 for (i=mExitingTokens.size()-1; i>=0; i--) { 8542 mExitingTokens.get(i).hasVisible = false; 8543 } 8544 8545 // Initialize state of exiting applications. 8546 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8547 mExitingAppTokens.get(i).hasVisible = false; 8548 } 8549 8550 mInnerFields.mHoldScreen = null; 8551 mInnerFields.mScreenBrightness = -1; 8552 mInnerFields.mButtonBrightness = -1; 8553 mTransactionSequence++; 8554 8555 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8556 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 8557 8558 Surface.openTransaction(); 8559 8560 if (mWatermark != null) { 8561 mWatermark.positionSurface(dw, dh); 8562 } 8563 if (mStrictModeFlash != null) { 8564 mStrictModeFlash.positionSurface(dw, dh); 8565 } 8566 8567 try { 8568 int repeats = 0; 8569 8570 do { 8571 repeats++; 8572 if (repeats > 6) { 8573 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 8574 mLayoutNeeded = false; 8575 break; 8576 } 8577 8578 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 8579 mPendingLayoutChanges); 8580 8581 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 8582 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8583 assignLayersLocked(); 8584 mLayoutNeeded = true; 8585 } 8586 } 8587 8588 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 8589 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 8590 if (updateOrientationFromAppTokensLocked(true)) { 8591 mLayoutNeeded = true; 8592 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8593 } 8594 } 8595 8596 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8597 mLayoutNeeded = true; 8598 } 8599 8600 // FIRST LOOP: Perform a layout, if needed. 8601 if (repeats < 4) { 8602 performLayoutLockedInner(repeats == 1, false /*updateInputWindows*/); 8603 } else { 8604 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 8605 } 8606 8607 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 8608 // it is animating. 8609 mPendingLayoutChanges = 0; 8610 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " + mLayoutRepeatCount, 8611 mPendingLayoutChanges); 8612 mPolicy.beginAnimationLw(dw, dh); 8613 for (i = mWindows.size() - 1; i >= 0; i--) { 8614 WindowState w = mWindows.get(i); 8615 if (w.mHasSurface) { 8616 mPolicy.animatingWindowLw(w, w.mAttrs); 8617 } 8618 } 8619 mPendingLayoutChanges |= mPolicy.finishAnimationLw(); 8620 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw", 8621 mPendingLayoutChanges); 8622 } while (mPendingLayoutChanges != 0); 8623 8624 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 8625 8626 mInnerFields.mObscured = false; 8627 mInnerFields.mDimming = false; 8628 mInnerFields.mSyswin = false; 8629 8630 boolean focusDisplayed = false; 8631 boolean updateAllDrawn = false; 8632 final int N = mWindows.size(); 8633 for (i=N-1; i>=0; i--) { 8634 WindowState w = mWindows.get(i); 8635 8636 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 8637 8638 // Update effect. 8639 w.mObscured = mInnerFields.mObscured; 8640 if (!mInnerFields.mObscured) { 8641 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 8642 } 8643 8644 if (obscuredChanged && (mWallpaperTarget == w) && w.isVisibleLw()) { 8645 // This is the wallpaper target and its obscured state 8646 // changed... make sure the current wallaper's visibility 8647 // has been updated accordingly. 8648 updateWallpaperVisibilityLocked(); 8649 } 8650 8651 final WindowStateAnimator winAnimator = w.mWinAnimator; 8652 8653 // If the window has moved due to its containing 8654 // content frame changing, then we'd like to animate 8655 // it. 8656 if (w.mHasSurface && w.shouldAnimateMove()) { 8657 // Frame has moved, containing content frame 8658 // has also moved, and we're not currently animating... 8659 // let's do something. 8660 Animation a = AnimationUtils.loadAnimation(mContext, 8661 com.android.internal.R.anim.window_move_from_decor); 8662 winAnimator.setAnimation(a); 8663 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 8664 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 8665 try { 8666 w.mClient.moved(w.mFrame.left, w.mFrame.top); 8667 } catch (RemoteException e) { 8668 } 8669 } 8670 8671 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 8672 w.mContentChanged = false; 8673 8674 // Moved from updateWindowsAndWallpaperLocked(). 8675 if (w.mHasSurface) { 8676 // Take care of the window being ready to display. 8677 if (winAnimator.commitFinishDrawingLocked(currentTime)) { 8678 if ((w.mAttrs.flags 8679 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 8680 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 8681 "First draw done in potential wallpaper target " + w); 8682 mInnerFields.mWallpaperMayChange = true; 8683 mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 8684 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 8685 debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true", 8686 mPendingLayoutChanges); 8687 } 8688 } 8689 } 8690 8691 winAnimator.setSurfaceBoundaries(recoveringMemory); 8692 8693 final AppWindowToken atoken = w.mAppToken; 8694 if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) { 8695 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 8696 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 8697 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 8698 } 8699 if (atoken != null 8700 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 8701 if (atoken.lastTransactionSequence != mTransactionSequence) { 8702 atoken.lastTransactionSequence = mTransactionSequence; 8703 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 8704 atoken.startingDisplayed = false; 8705 } 8706 if ((w.isOnScreen() || winAnimator.mAttrType 8707 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION) 8708 && !w.mExiting && !w.mDestroying) { 8709 if (WindowManagerService.DEBUG_VISIBILITY || 8710 WindowManagerService.DEBUG_ORIENTATION) { 8711 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 8712 + ", isAnimating=" + winAnimator.isAnimating()); 8713 if (!w.isDrawnLw()) { 8714 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface 8715 + " pv=" + w.mPolicyVisibility 8716 + " mDrawState=" + winAnimator.mDrawState 8717 + " ah=" + w.mAttachedHidden 8718 + " th=" + atoken.hiddenRequested 8719 + " a=" + winAnimator.mAnimating); 8720 } 8721 } 8722 if (w != atoken.startingWindow) { 8723 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 8724 atoken.numInterestingWindows++; 8725 if (w.isDrawnLw()) { 8726 atoken.numDrawnWindows++; 8727 if (WindowManagerService.DEBUG_VISIBILITY || 8728 WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG, 8729 "tokenMayBeDrawn: " + atoken 8730 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 8731 + " mAppFreezing=" + w.mAppFreezing); 8732 updateAllDrawn = true; 8733 } 8734 } 8735 } else if (w.isDrawnLw()) { 8736 atoken.startingDisplayed = true; 8737 } 8738 } 8739 } 8740 } 8741 8742 if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) { 8743 focusDisplayed = true; 8744 } 8745 8746 updateResizingWindows(w); 8747 } 8748 8749 if (updateAllDrawn) { 8750 updateAllDrawnLocked(); 8751 } 8752 8753 if (focusDisplayed) { 8754 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 8755 } 8756 8757 if (!mInnerFields.mDimming && mAnimator.isDimming()) { 8758 stopDimming(); 8759 } 8760 } catch (RuntimeException e) { 8761 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 8762 } finally { 8763 Surface.closeTransaction(); 8764 } 8765 8766 // If we are ready to perform an app transition, check through 8767 // all of the app tokens to be shown and see if they are ready 8768 // to go. 8769 if (mAppTransitionReady) { 8770 mPendingLayoutChanges |= handleAppTransitionReadyLocked(); 8771 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 8772 mPendingLayoutChanges); 8773 } 8774 8775 mInnerFields.mAdjResult = 0; 8776 8777 if (!mAnimator.mAnimating && mAppTransitionRunning) { 8778 // We have finished the animation of an app transition. To do 8779 // this, we have delayed a lot of operations like showing and 8780 // hiding apps, moving apps in Z-order, etc. The app token list 8781 // reflects the correct Z-order, but the window list may now 8782 // be out of sync with it. So here we will just rebuild the 8783 // entire app window list. Fun! 8784 mPendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 8785 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 8786 mPendingLayoutChanges); 8787 } 8788 8789 if (mInnerFields.mWallpaperForceHidingChanged && mPendingLayoutChanges == 0 && 8790 !mAppTransitionReady) { 8791 // At this point, there was a window with a wallpaper that 8792 // was force hiding other windows behind it, but now it 8793 // is going away. This may be simple -- just animate 8794 // away the wallpaper and its window -- or it may be 8795 // hard -- the wallpaper now needs to be shown behind 8796 // something that was hidden. 8797 mPendingLayoutChanges |= animateAwayWallpaperLocked(); 8798 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 8799 mPendingLayoutChanges); 8800 } 8801 mInnerFields.mWallpaperForceHidingChanged = false; 8802 8803 if (mInnerFields.mWallpaperMayChange) { 8804 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 8805 "Wallpaper may change! Adjusting"); 8806 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 8807 } 8808 8809 if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8810 if (DEBUG_WALLPAPER) Slog.v(TAG, 8811 "Wallpaper layer changed: assigning layers + relayout"); 8812 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8813 assignLayersLocked(); 8814 } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { 8815 if (DEBUG_WALLPAPER) Slog.v(TAG, 8816 "Wallpaper visibility changed: relayout"); 8817 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8818 } 8819 8820 if (mFocusMayChange) { 8821 mFocusMayChange = false; 8822 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8823 false /*updateInputWindows*/)) { 8824 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8825 mInnerFields.mAdjResult = 0; 8826 } 8827 } 8828 8829 if (mLayoutNeeded) { 8830 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8831 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", mPendingLayoutChanges); 8832 } 8833 8834 if (!mResizingWindows.isEmpty()) { 8835 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 8836 WindowState win = mResizingWindows.get(i); 8837 final WindowStateAnimator winAnimator = win.mWinAnimator; 8838 try { 8839 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8840 "Reporting new frame to " + win + ": " + win.mCompatFrame); 8841 int diff = 0; 8842 boolean configChanged = 8843 win.mConfiguration != mCurConfiguration 8844 && (win.mConfiguration == null 8845 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0); 8846 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 8847 && configChanged) { 8848 Slog.i(TAG, "Sending new config to window " + win + ": " 8849 + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH 8850 + " / " + mCurConfiguration + " / 0x" 8851 + Integer.toHexString(diff)); 8852 } 8853 win.mConfiguration = mCurConfiguration; 8854 if (DEBUG_ORIENTATION && 8855 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( 8856 TAG, "Resizing " + win + " WITH DRAW PENDING"); 8857 win.mClient.resized((int)winAnimator.mSurfaceW, 8858 (int)winAnimator.mSurfaceH, 8859 win.mLastContentInsets, win.mLastVisibleInsets, 8860 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING, 8861 configChanged ? win.mConfiguration : null); 8862 win.mContentInsetsChanged = false; 8863 win.mVisibleInsetsChanged = false; 8864 winAnimator.mSurfaceResized = false; 8865 } catch (RemoteException e) { 8866 win.mOrientationChanging = false; 8867 } 8868 } 8869 mResizingWindows.clear(); 8870 } 8871 8872 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 8873 "With display frozen, orientationChangeComplete=" 8874 + mInnerFields.mOrientationChangeComplete); 8875 if (mInnerFields.mOrientationChangeComplete) { 8876 if (mWindowsFreezingScreen) { 8877 mWindowsFreezingScreen = false; 8878 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8879 } 8880 stopFreezingDisplayLocked(); 8881 } 8882 8883 // Destroy the surface of any windows that are no longer visible. 8884 boolean wallpaperDestroyed = false; 8885 i = mDestroySurface.size(); 8886 if (i > 0) { 8887 do { 8888 i--; 8889 WindowState win = mDestroySurface.get(i); 8890 win.mDestroying = false; 8891 if (mInputMethodWindow == win) { 8892 mInputMethodWindow = null; 8893 } 8894 if (win == mWallpaperTarget) { 8895 wallpaperDestroyed = true; 8896 } 8897 win.mWinAnimator.destroySurfaceLocked(); 8898 } while (i > 0); 8899 mDestroySurface.clear(); 8900 } 8901 8902 // Time to remove any exiting tokens? 8903 for (i=mExitingTokens.size()-1; i>=0; i--) { 8904 WindowToken token = mExitingTokens.get(i); 8905 if (!token.hasVisible) { 8906 mExitingTokens.remove(i); 8907 if (token.windowType == TYPE_WALLPAPER) { 8908 mWallpaperTokens.remove(token); 8909 updateLayoutToAnimWallpaperTokens(); 8910 } 8911 } 8912 } 8913 8914 // Time to remove any exiting applications? 8915 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8916 AppWindowToken token = mExitingAppTokens.get(i); 8917 if (!token.hasVisible && !mClosingApps.contains(token)) { 8918 // Make sure there is no animation running on this token, 8919 // so any windows associated with it will be removed as 8920 // soon as their animations are complete 8921 token.mAppAnimator.clearAnimation(); 8922 token.mAppAnimator.animating = false; 8923 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 8924 "performLayout: App token exiting now removed" + token); 8925 mAppTokens.remove(token); 8926 mAnimatingAppTokens.remove(token); 8927 mExitingAppTokens.remove(i); 8928 } 8929 } 8930 8931 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 8932 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 8933 try { 8934 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 8935 } catch (RemoteException e) { 8936 } 8937 } 8938 mRelayoutWhileAnimating.clear(); 8939 } 8940 8941 if (wallpaperDestroyed) { 8942 mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0; 8943 } 8944 if (mPendingLayoutChanges != 0) { 8945 mLayoutNeeded = true; 8946 } 8947 8948 // Finally update all input windows now that the window changes have stabilized. 8949 mInputMonitor.updateInputWindowsLw(true /*force*/); 8950 8951 setHoldScreenLocked(mInnerFields.mHoldScreen != null); 8952 if (!mDisplayFrozen) { 8953 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 8954 mPowerManager.setScreenBrightnessOverride(-1); 8955 } else { 8956 mPowerManager.setScreenBrightnessOverride((int) 8957 (mInnerFields.mScreenBrightness * PowerManager.BRIGHTNESS_ON)); 8958 } 8959 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 8960 mPowerManager.setButtonBrightnessOverride(-1); 8961 } else { 8962 mPowerManager.setButtonBrightnessOverride((int) 8963 (mInnerFields.mButtonBrightness * PowerManager.BRIGHTNESS_ON)); 8964 } 8965 } 8966 if (mInnerFields.mHoldScreen != mHoldingScreenOn) { 8967 mHoldingScreenOn = mInnerFields.mHoldScreen; 8968 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, mInnerFields.mHoldScreen); 8969 mH.sendMessage(m); 8970 } 8971 8972 if (mTurnOnScreen) { 8973 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 8974 mPowerManager.userActivity(SystemClock.uptimeMillis(), false, 8975 LocalPowerManager.BUTTON_EVENT, true); 8976 mTurnOnScreen = false; 8977 } 8978 8979 if (mInnerFields.mUpdateRotation) { 8980 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 8981 if (updateRotationUncheckedLocked(false)) { 8982 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8983 } else { 8984 mInnerFields.mUpdateRotation = false; 8985 } 8986 } 8987 8988 if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded && 8989 !mInnerFields.mUpdateRotation) { 8990 checkDrawnWindowsLocked(); 8991 } 8992 8993 // Check to see if we are now in a state where the screen should 8994 // be enabled, because the window obscured flags have changed. 8995 enableScreenIfNeededLocked(); 8996 8997 updateLayoutToAnimationLocked(); 8998 8999 if (DEBUG_WINDOW_TRACE) { 9000 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mPendingLayoutChanges=" 9001 + Integer.toHexString(mPendingLayoutChanges) + " mLayoutNeeded=" + mLayoutNeeded 9002 + " animating=" + mAnimator.mAnimating); 9003 } 9004 } 9005 9006 void checkDrawnWindowsLocked() { 9007 if (mWaitingForDrawn.size() > 0) { 9008 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 9009 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 9010 WindowState win = pair.first; 9011 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 9012 // + win.mRemoved + " visible=" + win.isVisibleLw() 9013 // + " shown=" + win.mSurfaceShown); 9014 if (win.mRemoved || !win.isVisibleLw()) { 9015 // Window has been removed or made invisible; no draw 9016 // will now happen, so stop waiting. 9017 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 9018 try { 9019 pair.second.sendResult(null); 9020 } catch (RemoteException e) { 9021 } 9022 mWaitingForDrawn.remove(pair); 9023 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9024 } else if (win.mWinAnimator.mSurfaceShown) { 9025 // Window is now drawn (and shown). 9026 try { 9027 pair.second.sendResult(null); 9028 } catch (RemoteException e) { 9029 } 9030 mWaitingForDrawn.remove(pair); 9031 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9032 } 9033 } 9034 } 9035 } 9036 9037 public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 9038 synchronized (mWindowMap) { 9039 WindowState win = windowForClientLocked(null, token, true); 9040 if (win != null) { 9041 Pair<WindowState, IRemoteCallback> pair = 9042 new Pair<WindowState, IRemoteCallback>(win, callback); 9043 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9044 mH.sendMessageDelayed(m, 2000); 9045 mWaitingForDrawn.add(pair); 9046 checkDrawnWindowsLocked(); 9047 } 9048 } 9049 } 9050 9051 /** 9052 * Must be called with the main window manager lock held. 9053 */ 9054 void setHoldScreenLocked(boolean holding) { 9055 boolean state = mHoldingScreenWakeLock.isHeld(); 9056 if (holding != state) { 9057 if (holding) { 9058 mPolicy.screenOnStartedLw(); 9059 mHoldingScreenWakeLock.acquire(); 9060 } else { 9061 mPolicy.screenOnStoppedLw(); 9062 mHoldingScreenWakeLock.release(); 9063 } 9064 } 9065 } 9066 9067 void requestTraversalLocked() { 9068 if (!mTraversalScheduled) { 9069 mTraversalScheduled = true; 9070 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9071 } 9072 } 9073 9074 /** Note that Locked in this case is on mLayoutToAnim */ 9075 void scheduleAnimationLocked() { 9076 final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim; 9077 if (!layoutToAnim.mAnimationScheduled) { 9078 layoutToAnim.mAnimationScheduled = true; 9079 mChoreographer.postCallback( 9080 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9081 } 9082 } 9083 9084 void updateLayoutToAnimationLocked() { 9085 final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim; 9086 synchronized (layoutToAnim) { 9087 // Copy local params to transfer params. 9088 ArrayList<WindowStateAnimator> winAnimators = layoutToAnim.mWinAnimators; 9089 winAnimators.clear(); 9090 int N = mWindows.size(); 9091 for (int i = 0; i < N; i++) { 9092 final WindowStateAnimator winAnimator = mWindows.get(i).mWinAnimator; 9093 if (winAnimator.mSurface != null) { 9094 winAnimators.add(winAnimator); 9095 } 9096 } 9097 9098 layoutToAnim.mWallpaperTarget = mWallpaperTarget; 9099 layoutToAnim.mLowerWallpaperTarget = mLowerWallpaperTarget; 9100 layoutToAnim.mUpperWallpaperTarget = mUpperWallpaperTarget; 9101 9102 final ArrayList<AppWindowAnimParams> paramList = layoutToAnim.mAppWindowAnimParams; 9103 paramList.clear(); 9104 N = mAnimatingAppTokens.size(); 9105 for (int i = 0; i < N; i++) { 9106 paramList.add(new AppWindowAnimParams(mAnimatingAppTokens.get(i).mAppAnimator)); 9107 } 9108 9109 layoutToAnim.mParamsModified = true; 9110 scheduleAnimationLocked(); 9111 } 9112 } 9113 9114 void updateLayoutToAnimWallpaperTokens() { 9115 synchronized(mLayoutToAnim) { 9116 mLayoutToAnim.mWallpaperTokens = new ArrayList<WindowToken>(mWallpaperTokens); 9117 mLayoutToAnim.mChanges |= LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED; 9118 } 9119 } 9120 9121 void setAnimDimParams(DimAnimator.Parameters params) { 9122 synchronized (mLayoutToAnim) { 9123 mLayoutToAnim.mDimParams = params; 9124 scheduleAnimationLocked(); 9125 } 9126 } 9127 9128 void startDimming(final WindowStateAnimator winAnimator, final float target, 9129 final int width, final int height) { 9130 setAnimDimParams(new DimAnimator.Parameters(winAnimator, width, height, target)); 9131 } 9132 9133 void stopDimming() { 9134 setAnimDimParams(null); 9135 } 9136 9137 private boolean copyAnimToLayoutParamsLocked() { 9138 boolean doRequest = false; 9139 final WindowAnimator.AnimatorToLayoutParams animToLayout = mAnimator.mAnimToLayout; 9140 synchronized (animToLayout) { 9141 animToLayout.mUpdateQueued = false; 9142 final int bulkUpdateParams = animToLayout.mBulkUpdateParams; 9143 // TODO(cmautner): As the number of bits grows, use masks of bit groups to 9144 // eliminate unnecessary tests. 9145 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9146 mInnerFields.mUpdateRotation = true; 9147 doRequest = true; 9148 } 9149 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9150 mInnerFields.mWallpaperMayChange = true; 9151 doRequest = true; 9152 } 9153 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9154 mInnerFields.mWallpaperForceHidingChanged = true; 9155 doRequest = true; 9156 } 9157 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9158 mInnerFields.mOrientationChangeComplete = false; 9159 } else { 9160 mInnerFields.mOrientationChangeComplete = true; 9161 if (mWindowsFreezingScreen) { 9162 doRequest = true; 9163 } 9164 } 9165 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9166 mTurnOnScreen = true; 9167 } 9168 9169 mPendingLayoutChanges |= animToLayout.mPendingLayoutChanges; 9170 if (mPendingLayoutChanges != 0) { 9171 doRequest = true; 9172 } 9173 9174 mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper; 9175 } 9176 return doRequest; 9177 } 9178 9179 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9180 boolean secure) { 9181 final Surface surface = winAnimator.mSurface; 9182 boolean leakedSurface = false; 9183 boolean killedApps = false; 9184 9185 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9186 winAnimator.mSession.mPid, operation); 9187 9188 if (mForceRemoves == null) { 9189 mForceRemoves = new ArrayList<WindowState>(); 9190 } 9191 9192 long callingIdentity = Binder.clearCallingIdentity(); 9193 try { 9194 // There was some problem... first, do a sanity check of the 9195 // window list to make sure we haven't left any dangling surfaces 9196 // around. 9197 int N = mWindows.size(); 9198 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9199 for (int i=0; i<N; i++) { 9200 WindowState ws = mWindows.get(i); 9201 WindowStateAnimator wsa = ws.mWinAnimator; 9202 if (wsa.mSurface != null) { 9203 if (!mSessions.contains(wsa.mSession)) { 9204 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9205 + ws + " surface=" + wsa.mSurface 9206 + " token=" + ws.mToken 9207 + " pid=" + ws.mSession.mPid 9208 + " uid=" + ws.mSession.mUid); 9209 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9210 wsa.mSurface.destroy(); 9211 wsa.mSurfaceShown = false; 9212 wsa.mSurface = null; 9213 ws.mHasSurface = false; 9214 mForceRemoves.add(ws); 9215 i--; 9216 N--; 9217 leakedSurface = true; 9218 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9219 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9220 + ws + " surface=" + wsa.mSurface 9221 + " token=" + ws.mAppToken); 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 leakedSurface = true; 9228 } 9229 } 9230 } 9231 9232 if (!leakedSurface) { 9233 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9234 SparseIntArray pidCandidates = new SparseIntArray(); 9235 for (int i=0; i<N; i++) { 9236 WindowStateAnimator wsa = mWindows.get(i).mWinAnimator; 9237 if (wsa.mSurface != null) { 9238 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9239 } 9240 } 9241 if (pidCandidates.size() > 0) { 9242 int[] pids = new int[pidCandidates.size()]; 9243 for (int i=0; i<pids.length; i++) { 9244 pids[i] = pidCandidates.keyAt(i); 9245 } 9246 try { 9247 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9248 killedApps = true; 9249 } 9250 } catch (RemoteException e) { 9251 } 9252 } 9253 } 9254 9255 if (leakedSurface || killedApps) { 9256 // We managed to reclaim some memory, so get rid of the trouble 9257 // surface and ask the app to request another one. 9258 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9259 if (surface != null) { 9260 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9261 "RECOVER DESTROY", null); 9262 surface.destroy(); 9263 winAnimator.mSurfaceShown = false; 9264 winAnimator.mSurface = null; 9265 winAnimator.mWin.mHasSurface = false; 9266 } 9267 9268 try { 9269 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9270 } catch (RemoteException e) { 9271 } 9272 } 9273 } finally { 9274 Binder.restoreCallingIdentity(callingIdentity); 9275 } 9276 9277 return leakedSurface || killedApps; 9278 } 9279 9280 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9281 WindowState newFocus = computeFocusedWindowLocked(); 9282 if (mCurrentFocus != newFocus) { 9283 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9284 // This check makes sure that we don't already have the focus 9285 // change message pending. 9286 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9287 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9288 if (localLOGV) Slog.v( 9289 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 9290 final WindowState oldFocus = mCurrentFocus; 9291 mCurrentFocus = newFocus; 9292 mAnimator.setCurrentFocus(newFocus); 9293 mLosingFocus.remove(newFocus); 9294 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9295 9296 final WindowState imWindow = mInputMethodWindow; 9297 if (newFocus != imWindow && oldFocus != imWindow) { 9298 if (moveInputMethodWindowsIfNeededLocked( 9299 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 9300 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 9301 mLayoutNeeded = true; 9302 } 9303 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9304 performLayoutLockedInner(true /*initial*/, updateInputWindows); 9305 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9306 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9307 // Client will do the layout, but we need to assign layers 9308 // for handleNewWindowLocked() below. 9309 assignLayersLocked(); 9310 } 9311 } 9312 9313 if ((focusChanged&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9314 // The change in focus caused us to need to do a layout. Okay. 9315 mLayoutNeeded = true; 9316 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9317 performLayoutLockedInner(true /*initial*/, updateInputWindows); 9318 } 9319 } 9320 9321 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9322 // If we defer assigning layers, then the caller is responsible for 9323 // doing this part. 9324 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9325 } 9326 9327 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9328 return true; 9329 } 9330 return false; 9331 } 9332 9333 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9334 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9335 } 9336 9337 private WindowState computeFocusedWindowLocked() { 9338 WindowState result = null; 9339 WindowState win; 9340 9341 if (mAnimator.mUniverseBackground != null 9342 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9343 return mAnimator.mUniverseBackground.mWin; 9344 } 9345 9346 int nextAppIndex = mAppTokens.size()-1; 9347 WindowToken nextApp = nextAppIndex >= 0 9348 ? mAppTokens.get(nextAppIndex) : null; 9349 9350 for (int i = mWindows.size() - 1; i >= 0; i--) { 9351 win = mWindows.get(i); 9352 9353 if (localLOGV || DEBUG_FOCUS) Slog.v( 9354 TAG, "Looking for focus: " + i 9355 + " = " + win 9356 + ", flags=" + win.mAttrs.flags 9357 + ", canReceive=" + win.canReceiveKeys()); 9358 9359 AppWindowToken thisApp = win.mAppToken; 9360 9361 // If this window's application has been removed, just skip it. 9362 if (thisApp != null && (thisApp.removed || thisApp.sendingToBottom)) { 9363 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping app because " + (thisApp.removed 9364 ? "removed" : "sendingToBottom")); 9365 continue; 9366 } 9367 9368 // If there is a focused app, don't allow focus to go to any 9369 // windows below it. If this is an application window, step 9370 // through the app tokens until we find its app. 9371 if (thisApp != null && nextApp != null && thisApp != nextApp 9372 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 9373 int origAppIndex = nextAppIndex; 9374 while (nextAppIndex > 0) { 9375 if (nextApp == mFocusedApp) { 9376 // Whoops, we are below the focused app... no focus 9377 // for you! 9378 if (localLOGV || DEBUG_FOCUS) Slog.v( 9379 TAG, "Reached focused app: " + mFocusedApp); 9380 return null; 9381 } 9382 nextAppIndex--; 9383 nextApp = mAppTokens.get(nextAppIndex); 9384 if (nextApp == thisApp) { 9385 break; 9386 } 9387 } 9388 if (thisApp != nextApp) { 9389 // Uh oh, the app token doesn't exist! This shouldn't 9390 // happen, but if it does we can get totally hosed... 9391 // so restart at the original app. 9392 nextAppIndex = origAppIndex; 9393 nextApp = mAppTokens.get(nextAppIndex); 9394 } 9395 } 9396 9397 // Dispatch to this window if it is wants key events. 9398 if (win.canReceiveKeys()) { 9399 if (DEBUG_FOCUS) Slog.v( 9400 TAG, "Found focus @ " + i + " = " + win); 9401 result = win; 9402 break; 9403 } 9404 } 9405 9406 return result; 9407 } 9408 9409 private void startFreezingDisplayLocked(boolean inTransaction) { 9410 if (mDisplayFrozen) { 9411 return; 9412 } 9413 9414 if (mDisplay == null || !mPolicy.isScreenOnFully()) { 9415 // No need to freeze the screen before the system is ready or if 9416 // the screen is off. 9417 return; 9418 } 9419 9420 mScreenFrozenLock.acquire(); 9421 9422 mDisplayFrozen = true; 9423 9424 mInputMonitor.freezeInputDispatchingLw(); 9425 9426 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 9427 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 9428 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 9429 mNextAppTransitionPackage = null; 9430 mNextAppTransitionThumbnail = null; 9431 mAppTransitionReady = true; 9432 } 9433 9434 if (PROFILE_ORIENTATION) { 9435 File file = new File("/data/system/frozen"); 9436 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9437 } 9438 9439 if (CUSTOM_SCREEN_ROTATION) { 9440 if (mAnimator.mScreenRotationAnimation != null) { 9441 mAnimator.mScreenRotationAnimation.kill(); 9442 mAnimator.mScreenRotationAnimation = null; 9443 } 9444 9445 mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, 9446 mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight, 9447 mDisplay.getRotation()); 9448 9449 if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) { 9450 Surface.freezeDisplay(0); 9451 } 9452 } else { 9453 Surface.freezeDisplay(0); 9454 } 9455 } 9456 9457 private void stopFreezingDisplayLocked() { 9458 if (!mDisplayFrozen) { 9459 return; 9460 } 9461 9462 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) { 9463 if (DEBUG_ORIENTATION) Slog.d(TAG, 9464 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 9465 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 9466 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen); 9467 return; 9468 } 9469 9470 mDisplayFrozen = false; 9471 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9472 if (PROFILE_ORIENTATION) { 9473 Debug.stopMethodTracing(); 9474 } 9475 9476 boolean updateRotation = false; 9477 9478 if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null 9479 && mAnimator.mScreenRotationAnimation.hasScreenshot()) { 9480 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 9481 if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 9482 mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { 9483 updateLayoutToAnimationLocked(); 9484 } else { 9485 mAnimator.mScreenRotationAnimation.kill(); 9486 mAnimator.mScreenRotationAnimation = null; 9487 updateRotation = true; 9488 } 9489 } else { 9490 if (mAnimator.mScreenRotationAnimation != null) { 9491 mAnimator.mScreenRotationAnimation.kill(); 9492 mAnimator.mScreenRotationAnimation = null; 9493 } 9494 updateRotation = true; 9495 } 9496 Surface.unfreezeDisplay(0); 9497 9498 mInputMonitor.thawInputDispatchingLw(); 9499 9500 boolean configChanged; 9501 9502 // While the display is frozen we don't re-compute the orientation 9503 // to avoid inconsistent states. However, something interesting 9504 // could have actually changed during that time so re-evaluate it 9505 // now to catch that. 9506 configChanged = updateOrientationFromAppTokensLocked(false); 9507 9508 // A little kludge: a lot could have happened while the 9509 // display was frozen, so now that we are coming back we 9510 // do a gc so that any remote references the system 9511 // processes holds on others can be released if they are 9512 // no longer needed. 9513 mH.removeMessages(H.FORCE_GC); 9514 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 9515 2000); 9516 9517 mScreenFrozenLock.release(); 9518 9519 if (updateRotation) { 9520 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9521 configChanged |= updateRotationUncheckedLocked(false); 9522 } 9523 9524 if (configChanged) { 9525 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9526 } 9527 } 9528 9529 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 9530 DisplayMetrics dm) { 9531 if (index < tokens.length) { 9532 String str = tokens[index]; 9533 if (str != null && str.length() > 0) { 9534 try { 9535 int val = Integer.parseInt(str); 9536 return val; 9537 } catch (Exception e) { 9538 } 9539 } 9540 } 9541 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 9542 return defDps; 9543 } 9544 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 9545 return val; 9546 } 9547 9548 void createWatermark() { 9549 if (mWatermark != null) { 9550 return; 9551 } 9552 9553 File file = new File("/system/etc/setup.conf"); 9554 FileInputStream in = null; 9555 try { 9556 in = new FileInputStream(file); 9557 DataInputStream ind = new DataInputStream(in); 9558 String line = ind.readLine(); 9559 if (line != null) { 9560 String[] toks = line.split("%"); 9561 if (toks != null && toks.length > 0) { 9562 mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks); 9563 } 9564 } 9565 } catch (FileNotFoundException e) { 9566 } catch (IOException e) { 9567 } finally { 9568 if (in != null) { 9569 try { 9570 in.close(); 9571 } catch (IOException e) { 9572 } 9573 } 9574 } 9575 } 9576 9577 @Override 9578 public void statusBarVisibilityChanged(int visibility) { 9579 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 9580 != PackageManager.PERMISSION_GRANTED) { 9581 throw new SecurityException("Caller does not hold permission " 9582 + android.Manifest.permission.STATUS_BAR); 9583 } 9584 9585 synchronized (mWindowMap) { 9586 mLastStatusBarVisibility = visibility; 9587 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 9588 updateStatusBarVisibilityLocked(visibility); 9589 } 9590 } 9591 9592 void updateStatusBarVisibilityLocked(int visibility) { 9593 mInputManager.setSystemUiVisibility(visibility); 9594 final int N = mWindows.size(); 9595 for (int i = 0; i < N; i++) { 9596 WindowState ws = mWindows.get(i); 9597 try { 9598 int curValue = ws.mSystemUiVisibility; 9599 int diff = curValue ^ visibility; 9600 // We are only interested in differences of one of the 9601 // clearable flags... 9602 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 9603 // ...if it has actually been cleared. 9604 diff &= ~visibility; 9605 int newValue = (curValue&~diff) | (visibility&diff); 9606 if (newValue != curValue) { 9607 ws.mSeq++; 9608 ws.mSystemUiVisibility = newValue; 9609 } 9610 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 9611 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 9612 visibility, newValue, diff); 9613 } 9614 } catch (RemoteException e) { 9615 // so sorry 9616 } 9617 } 9618 } 9619 9620 @Override 9621 public void reevaluateStatusBarVisibility() { 9622 synchronized (mWindowMap) { 9623 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 9624 updateStatusBarVisibilityLocked(visibility); 9625 performLayoutAndPlaceSurfacesLocked(); 9626 } 9627 } 9628 9629 @Override 9630 public FakeWindow addFakeWindow(Looper looper, 9631 InputEventReceiver.Factory inputEventReceiverFactory, 9632 String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys, 9633 boolean hasFocus, boolean touchFullscreen) { 9634 synchronized (mWindowMap) { 9635 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 9636 name, windowType, 9637 layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 9638 int i=0; 9639 while (i<mFakeWindows.size()) { 9640 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 9641 break; 9642 } 9643 } 9644 mFakeWindows.add(i, fw); 9645 mInputMonitor.updateInputWindowsLw(true); 9646 return fw; 9647 } 9648 } 9649 9650 boolean removeFakeWindowLocked(FakeWindow window) { 9651 synchronized (mWindowMap) { 9652 if (mFakeWindows.remove(window)) { 9653 mInputMonitor.updateInputWindowsLw(true); 9654 return true; 9655 } 9656 return false; 9657 } 9658 } 9659 9660 // It is assumed that this method is called only by InputMethodManagerService. 9661 public void saveLastInputMethodWindowForTransition() { 9662 synchronized (mWindowMap) { 9663 if (mInputMethodWindow != null) { 9664 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 9665 } 9666 } 9667 } 9668 9669 @Override 9670 public boolean hasNavigationBar() { 9671 return mPolicy.hasNavigationBar(); 9672 } 9673 9674 public void lockNow() { 9675 mPolicy.lockNow(); 9676 } 9677 9678 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 9679 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 9680 mPolicy.dump(" ", pw, args); 9681 } 9682 9683 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 9684 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 9685 if (mTokenMap.size() > 0) { 9686 pw.println(" All tokens:"); 9687 Iterator<WindowToken> it = mTokenMap.values().iterator(); 9688 while (it.hasNext()) { 9689 WindowToken token = it.next(); 9690 pw.print(" Token "); pw.print(token.token); 9691 if (dumpAll) { 9692 pw.println(':'); 9693 token.dump(pw, " "); 9694 } else { 9695 pw.println(); 9696 } 9697 } 9698 } 9699 if (mWallpaperTokens.size() > 0) { 9700 pw.println(); 9701 pw.println(" Wallpaper tokens:"); 9702 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 9703 WindowToken token = mWallpaperTokens.get(i); 9704 pw.print(" Wallpaper #"); pw.print(i); 9705 pw.print(' '); pw.print(token); 9706 if (dumpAll) { 9707 pw.println(':'); 9708 token.dump(pw, " "); 9709 } else { 9710 pw.println(); 9711 } 9712 } 9713 } 9714 if (mAppTokens.size() > 0) { 9715 pw.println(); 9716 pw.println(" Application tokens in Z order:"); 9717 for (int i=mAppTokens.size()-1; i>=0; i--) { 9718 pw.print(" App #"); pw.print(i); pw.println(": "); 9719 mAppTokens.get(i).dump(pw, " "); 9720 } 9721 } 9722 if (mFinishedStarting.size() > 0) { 9723 pw.println(); 9724 pw.println(" Finishing start of application tokens:"); 9725 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 9726 WindowToken token = mFinishedStarting.get(i); 9727 pw.print(" Finished Starting #"); pw.print(i); 9728 pw.print(' '); pw.print(token); 9729 if (dumpAll) { 9730 pw.println(':'); 9731 token.dump(pw, " "); 9732 } else { 9733 pw.println(); 9734 } 9735 } 9736 } 9737 if (mExitingTokens.size() > 0) { 9738 pw.println(); 9739 pw.println(" Exiting tokens:"); 9740 for (int i=mExitingTokens.size()-1; i>=0; i--) { 9741 WindowToken token = mExitingTokens.get(i); 9742 pw.print(" Exiting #"); pw.print(i); 9743 pw.print(' '); pw.print(token); 9744 if (dumpAll) { 9745 pw.println(':'); 9746 token.dump(pw, " "); 9747 } else { 9748 pw.println(); 9749 } 9750 } 9751 } 9752 if (mExitingAppTokens.size() > 0) { 9753 pw.println(); 9754 pw.println(" Exiting application tokens:"); 9755 for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 9756 WindowToken token = mExitingAppTokens.get(i); 9757 pw.print(" Exiting App #"); pw.print(i); 9758 pw.print(' '); pw.print(token); 9759 if (dumpAll) { 9760 pw.println(':'); 9761 token.dump(pw, " "); 9762 } else { 9763 pw.println(); 9764 } 9765 } 9766 } 9767 if (mAppTransitionRunning && mAnimatingAppTokens.size() > 0) { 9768 pw.println(); 9769 pw.println(" Application tokens during animation:"); 9770 for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) { 9771 WindowToken token = mAnimatingAppTokens.get(i); 9772 pw.print(" App moving to bottom #"); pw.print(i); 9773 pw.print(' '); pw.print(token); 9774 if (dumpAll) { 9775 pw.println(':'); 9776 token.dump(pw, " "); 9777 } else { 9778 pw.println(); 9779 } 9780 } 9781 } 9782 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 9783 pw.println(); 9784 if (mOpeningApps.size() > 0) { 9785 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 9786 } 9787 if (mClosingApps.size() > 0) { 9788 pw.print(" mClosingApps="); pw.println(mClosingApps); 9789 } 9790 } 9791 } 9792 9793 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 9794 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 9795 if (mSessions.size() > 0) { 9796 Iterator<Session> it = mSessions.iterator(); 9797 while (it.hasNext()) { 9798 Session s = it.next(); 9799 pw.print(" Session "); pw.print(s); pw.println(':'); 9800 s.dump(pw, " "); 9801 } 9802 } 9803 } 9804 9805 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 9806 ArrayList<WindowState> windows) { 9807 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 9808 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 9809 } 9810 9811 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 9812 ArrayList<WindowState> windows) { 9813 for (int i=mWindows.size()-1; i>=0; i--) { 9814 WindowState w = mWindows.get(i); 9815 if (windows == null || windows.contains(w)) { 9816 pw.print(" Window #"); pw.print(i); pw.print(' '); 9817 pw.print(w); pw.println(":"); 9818 w.dump(pw, " ", dumpAll || windows != null); 9819 } 9820 } 9821 if (mInputMethodDialogs.size() > 0) { 9822 pw.println(); 9823 pw.println(" Input method dialogs:"); 9824 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 9825 WindowState w = mInputMethodDialogs.get(i); 9826 if (windows == null || windows.contains(w)) { 9827 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 9828 } 9829 } 9830 } 9831 if (mPendingRemove.size() > 0) { 9832 pw.println(); 9833 pw.println(" Remove pending for:"); 9834 for (int i=mPendingRemove.size()-1; i>=0; i--) { 9835 WindowState w = mPendingRemove.get(i); 9836 if (windows == null || windows.contains(w)) { 9837 pw.print(" Remove #"); pw.print(i); pw.print(' '); 9838 pw.print(w); 9839 if (dumpAll) { 9840 pw.println(":"); 9841 w.dump(pw, " ", true); 9842 } else { 9843 pw.println(); 9844 } 9845 } 9846 } 9847 } 9848 if (mForceRemoves != null && mForceRemoves.size() > 0) { 9849 pw.println(); 9850 pw.println(" Windows force removing:"); 9851 for (int i=mForceRemoves.size()-1; i>=0; i--) { 9852 WindowState w = mForceRemoves.get(i); 9853 pw.print(" Removing #"); pw.print(i); pw.print(' '); 9854 pw.print(w); 9855 if (dumpAll) { 9856 pw.println(":"); 9857 w.dump(pw, " ", true); 9858 } else { 9859 pw.println(); 9860 } 9861 } 9862 } 9863 if (mDestroySurface.size() > 0) { 9864 pw.println(); 9865 pw.println(" Windows waiting to destroy their surface:"); 9866 for (int i=mDestroySurface.size()-1; i>=0; i--) { 9867 WindowState w = mDestroySurface.get(i); 9868 if (windows == null || windows.contains(w)) { 9869 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 9870 pw.print(w); 9871 if (dumpAll) { 9872 pw.println(":"); 9873 w.dump(pw, " ", true); 9874 } else { 9875 pw.println(); 9876 } 9877 } 9878 } 9879 } 9880 if (mLosingFocus.size() > 0) { 9881 pw.println(); 9882 pw.println(" Windows losing focus:"); 9883 for (int i=mLosingFocus.size()-1; i>=0; i--) { 9884 WindowState w = mLosingFocus.get(i); 9885 if (windows == null || windows.contains(w)) { 9886 pw.print(" Losing #"); pw.print(i); pw.print(' '); 9887 pw.print(w); 9888 if (dumpAll) { 9889 pw.println(":"); 9890 w.dump(pw, " ", true); 9891 } else { 9892 pw.println(); 9893 } 9894 } 9895 } 9896 } 9897 if (mResizingWindows.size() > 0) { 9898 pw.println(); 9899 pw.println(" Windows waiting to resize:"); 9900 for (int i=mResizingWindows.size()-1; i>=0; i--) { 9901 WindowState w = mResizingWindows.get(i); 9902 if (windows == null || windows.contains(w)) { 9903 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 9904 pw.print(w); 9905 if (dumpAll) { 9906 pw.println(":"); 9907 w.dump(pw, " ", true); 9908 } else { 9909 pw.println(); 9910 } 9911 } 9912 } 9913 } 9914 if (mWaitingForDrawn.size() > 0) { 9915 pw.println(); 9916 pw.println(" Clients waiting for these windows to be drawn:"); 9917 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 9918 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 9919 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 9920 pw.print(": "); pw.println(pair.second); 9921 } 9922 } 9923 pw.println(); 9924 if (mDisplay != null) { 9925 pw.print(" Display: init="); pw.print(mInitialDisplayWidth); pw.print("x"); 9926 pw.print(mInitialDisplayHeight); 9927 if (mInitialDisplayWidth != mBaseDisplayWidth 9928 || mInitialDisplayHeight != mBaseDisplayHeight) { 9929 pw.print(" base="); 9930 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 9931 } 9932 final int rawWidth = mDisplay.getRawWidth(); 9933 final int rawHeight = mDisplay.getRawHeight(); 9934 if (rawWidth != mCurDisplayWidth || rawHeight != mCurDisplayHeight) { 9935 pw.print(" raw="); pw.print(rawWidth); pw.print("x"); pw.print(rawHeight); 9936 } 9937 pw.print(" cur="); 9938 pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight); 9939 pw.print(" app="); 9940 pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight); 9941 pw.print(" rng="); pw.print(mSmallestDisplayWidth); 9942 pw.print("x"); pw.print(mSmallestDisplayHeight); 9943 pw.print("-"); pw.print(mLargestDisplayWidth); 9944 pw.print("x"); pw.println(mLargestDisplayHeight); 9945 } else { 9946 pw.println(" NO DISPLAY"); 9947 } 9948 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 9949 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 9950 if (mLastFocus != mCurrentFocus) { 9951 pw.print(" mLastFocus="); pw.println(mLastFocus); 9952 } 9953 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 9954 if (mInputMethodTarget != null) { 9955 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 9956 } 9957 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 9958 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 9959 if (dumpAll) { 9960 pw.print(" mSystemDecorRect="); pw.print(mSystemDecorRect.toShortString()); 9961 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 9962 pw.print(" mScreenRecr="); pw.println(mScreenRect.toShortString()); 9963 if (mLastStatusBarVisibility != 0) { 9964 pw.print(" mLastStatusBarVisibility=0x"); 9965 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 9966 } 9967 if (mInputMethodWindow != null) { 9968 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 9969 } 9970 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 9971 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) { 9972 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 9973 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 9974 } 9975 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 9976 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 9977 if (mInputMethodAnimLayerAdjustment != 0 || 9978 mWallpaperAnimLayerAdjustment != 0) { 9979 pw.print(" mInputMethodAnimLayerAdjustment="); 9980 pw.print(mInputMethodAnimLayerAdjustment); 9981 pw.print(" mWallpaperAnimLayerAdjustment="); 9982 pw.println(mWallpaperAnimLayerAdjustment); 9983 } 9984 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 9985 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 9986 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); 9987 pw.print("mTransactionSequence="); pw.println(mTransactionSequence); 9988 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 9989 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); 9990 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); 9991 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); 9992 pw.print(" mRotation="); pw.print(mRotation); 9993 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 9994 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 9995 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 9996 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 9997 if (mAnimator.mScreenRotationAnimation != null) { 9998 pw.println(" mScreenRotationAnimation:"); 9999 mAnimator.mScreenRotationAnimation.printTo(" ", pw); 10000 } 10001 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 10002 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 10003 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 10004 pw.print(" mTraversalScheduled="); pw.print(mTraversalScheduled); 10005 pw.print(" mNextAppTransition=0x"); 10006 pw.print(Integer.toHexString(mNextAppTransition)); 10007 pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady); 10008 pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning); 10009 pw.print(" mAppTransitionTimeout="); pw.println(mAppTransitionTimeout); 10010 if (mNextAppTransitionType != ActivityOptions.ANIM_NONE) { 10011 pw.print(" mNextAppTransitionType="); pw.println(mNextAppTransitionType); 10012 } 10013 switch (mNextAppTransitionType) { 10014 case ActivityOptions.ANIM_CUSTOM: 10015 pw.print(" mNextAppTransitionPackage="); 10016 pw.println(mNextAppTransitionPackage); 10017 pw.print(" mNextAppTransitionEnter=0x"); 10018 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 10019 pw.print(" mNextAppTransitionExit=0x"); 10020 pw.println(Integer.toHexString(mNextAppTransitionExit)); 10021 break; 10022 case ActivityOptions.ANIM_SCALE_UP: 10023 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); 10024 pw.print(" mNextAppTransitionStartY="); 10025 pw.println(mNextAppTransitionStartY); 10026 pw.print(" mNextAppTransitionStartWidth="); 10027 pw.print(mNextAppTransitionStartWidth); 10028 pw.print(" mNextAppTransitionStartHeight="); 10029 pw.println(mNextAppTransitionStartHeight); 10030 break; 10031 case ActivityOptions.ANIM_THUMBNAIL: 10032 case ActivityOptions.ANIM_THUMBNAIL_DELAYED: 10033 pw.print(" mNextAppTransitionThumbnail="); 10034 pw.print(mNextAppTransitionThumbnail); 10035 pw.print(" mNextAppTransitionStartX="); 10036 pw.print(mNextAppTransitionStartX); 10037 pw.print(" mNextAppTransitionStartY="); 10038 pw.println(mNextAppTransitionStartY); 10039 pw.print(" mNextAppTransitionDelayed="); pw.println(mNextAppTransitionDelayed); 10040 break; 10041 } 10042 if (mNextAppTransitionCallback != null) { 10043 pw.print(" mNextAppTransitionCallback="); 10044 pw.println(mNextAppTransitionCallback); 10045 } 10046 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10047 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10048 pw.println(" Window Animator:"); 10049 mAnimator.dump(pw, " ", dumpAll); 10050 } 10051 } 10052 10053 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10054 int opti, boolean dumpAll) { 10055 ArrayList<WindowState> windows = new ArrayList<WindowState>(); 10056 if ("visible".equals(name)) { 10057 synchronized(mWindowMap) { 10058 for (int i=mWindows.size()-1; i>=0; i--) { 10059 WindowState w = mWindows.get(i); 10060 if (w.mWinAnimator.mSurfaceShown) { 10061 windows.add(w); 10062 } 10063 } 10064 } 10065 } else { 10066 int objectId = 0; 10067 // See if this is an object ID. 10068 try { 10069 objectId = Integer.parseInt(name, 16); 10070 name = null; 10071 } catch (RuntimeException e) { 10072 } 10073 synchronized(mWindowMap) { 10074 for (int i=mWindows.size()-1; i>=0; i--) { 10075 WindowState w = mWindows.get(i); 10076 if (name != null) { 10077 if (w.mAttrs.getTitle().toString().contains(name)) { 10078 windows.add(w); 10079 } 10080 } else if (System.identityHashCode(w) == objectId) { 10081 windows.add(w); 10082 } 10083 } 10084 } 10085 } 10086 10087 if (windows.size() <= 0) { 10088 return false; 10089 } 10090 10091 synchronized(mWindowMap) { 10092 dumpWindowsLocked(pw, dumpAll, windows); 10093 } 10094 return true; 10095 } 10096 10097 void dumpLastANRLocked(PrintWriter pw) { 10098 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10099 if (mLastANRState == null) { 10100 pw.println(" <no ANR has occurred since boot>"); 10101 } else { 10102 pw.println(mLastANRState); 10103 } 10104 } 10105 10106 /** 10107 * Saves information about the state of the window manager at 10108 * the time an ANR occurred before anything else in the system changes 10109 * in response. 10110 * 10111 * @param appWindowToken The application that ANR'd, may be null. 10112 * @param windowState The window that ANR'd, may be null. 10113 */ 10114 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) { 10115 StringWriter sw = new StringWriter(); 10116 PrintWriter pw = new PrintWriter(sw); 10117 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10118 if (appWindowToken != null) { 10119 pw.println(" Application at fault: " + appWindowToken.stringName); 10120 } 10121 if (windowState != null) { 10122 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10123 } 10124 pw.println(); 10125 dumpWindowsNoHeaderLocked(pw, true, null); 10126 pw.close(); 10127 mLastANRState = sw.toString(); 10128 } 10129 10130 @Override 10131 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10132 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10133 != PackageManager.PERMISSION_GRANTED) { 10134 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10135 + Binder.getCallingPid() 10136 + ", uid=" + Binder.getCallingUid()); 10137 return; 10138 } 10139 10140 boolean dumpAll = false; 10141 10142 int opti = 0; 10143 while (opti < args.length) { 10144 String opt = args[opti]; 10145 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10146 break; 10147 } 10148 opti++; 10149 if ("-a".equals(opt)) { 10150 dumpAll = true; 10151 } else if ("-h".equals(opt)) { 10152 pw.println("Window manager dump options:"); 10153 pw.println(" [-a] [-h] [cmd] ..."); 10154 pw.println(" cmd may be one of:"); 10155 pw.println(" l[astanr]: last ANR information"); 10156 pw.println(" p[policy]: policy state"); 10157 pw.println(" s[essions]: active sessions"); 10158 pw.println(" t[okens]: token list"); 10159 pw.println(" w[indows]: window list"); 10160 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10161 pw.println(" be a partial substring in a window name, a"); 10162 pw.println(" Window hex object identifier, or"); 10163 pw.println(" \"all\" for all windows, or"); 10164 pw.println(" \"visible\" for the visible windows."); 10165 pw.println(" -a: include all available server state."); 10166 return; 10167 } else { 10168 pw.println("Unknown argument: " + opt + "; use -h for help"); 10169 } 10170 } 10171 10172 // Is the caller requesting to dump a particular piece of data? 10173 if (opti < args.length) { 10174 String cmd = args[opti]; 10175 opti++; 10176 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10177 synchronized(mWindowMap) { 10178 dumpLastANRLocked(pw); 10179 } 10180 return; 10181 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10182 synchronized(mWindowMap) { 10183 dumpPolicyLocked(pw, args, true); 10184 } 10185 return; 10186 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10187 synchronized(mWindowMap) { 10188 dumpSessionsLocked(pw, true); 10189 } 10190 return; 10191 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10192 synchronized(mWindowMap) { 10193 dumpTokensLocked(pw, true); 10194 } 10195 return; 10196 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10197 synchronized(mWindowMap) { 10198 dumpWindowsLocked(pw, true, null); 10199 } 10200 return; 10201 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10202 synchronized(mWindowMap) { 10203 dumpWindowsLocked(pw, true, null); 10204 } 10205 return; 10206 } else { 10207 // Dumping a single name? 10208 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10209 pw.println("Bad window command, or no windows match: " + cmd); 10210 pw.println("Use -h for help."); 10211 } 10212 return; 10213 } 10214 } 10215 10216 synchronized(mWindowMap) { 10217 pw.println(); 10218 if (dumpAll) { 10219 pw.println("-------------------------------------------------------------------------------"); 10220 } 10221 dumpLastANRLocked(pw); 10222 pw.println(); 10223 if (dumpAll) { 10224 pw.println("-------------------------------------------------------------------------------"); 10225 } 10226 dumpPolicyLocked(pw, args, dumpAll); 10227 pw.println(); 10228 if (dumpAll) { 10229 pw.println("-------------------------------------------------------------------------------"); 10230 } 10231 dumpSessionsLocked(pw, dumpAll); 10232 pw.println(); 10233 if (dumpAll) { 10234 pw.println("-------------------------------------------------------------------------------"); 10235 } 10236 dumpTokensLocked(pw, dumpAll); 10237 pw.println(); 10238 if (dumpAll) { 10239 pw.println("-------------------------------------------------------------------------------"); 10240 } 10241 dumpWindowsLocked(pw, dumpAll, null); 10242 } 10243 } 10244 10245 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10246 public void monitor() { 10247 synchronized (mWindowMap) { } 10248 synchronized (mKeyguardTokenWatcher) { } 10249 } 10250 10251 public interface OnHardKeyboardStatusChangeListener { 10252 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10253 } 10254 10255 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10256 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10257 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10258 Integer.toHexString(pendingLayoutChanges)); 10259 } 10260 } 10261} 10262