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