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