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