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