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