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