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