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