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