WindowManagerService.java revision b696de5c10ebcc7bf42d8487fc0e56e0e937754d
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 6550 // Update the configuration based on available input devices, lid switch, 6551 // and platform configuration. 6552 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6553 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6554 config.navigation = Configuration.NAVIGATION_NONAV; 6555 6556 int keyboardPresence = 0; 6557 int navigationPresence = 0; 6558 final InputDevice[] devices = mInputManager.getInputDevices(); 6559 final int len = devices.length; 6560 for (int i = 0; i < len; i++) { 6561 InputDevice device = devices[i]; 6562 if (!device.isVirtual()) { 6563 final int sources = device.getSources(); 6564 final int presenceFlag = device.isExternal() ? 6565 WindowManagerPolicy.PRESENCE_EXTERNAL : 6566 WindowManagerPolicy.PRESENCE_INTERNAL; 6567 6568 if (mIsTouchDevice) { 6569 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6570 InputDevice.SOURCE_TOUCHSCREEN) { 6571 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6572 } 6573 } else { 6574 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6575 } 6576 6577 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6578 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6579 navigationPresence |= presenceFlag; 6580 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6581 && config.navigation == Configuration.NAVIGATION_NONAV) { 6582 config.navigation = Configuration.NAVIGATION_DPAD; 6583 navigationPresence |= presenceFlag; 6584 } 6585 6586 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6587 config.keyboard = Configuration.KEYBOARD_QWERTY; 6588 keyboardPresence |= presenceFlag; 6589 } 6590 } 6591 } 6592 6593 // Determine whether a hard keyboard is available and enabled. 6594 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6595 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6596 mHardKeyboardAvailable = hardKeyboardAvailable; 6597 mHardKeyboardEnabled = hardKeyboardAvailable; 6598 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6599 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6600 } 6601 if (!mHardKeyboardEnabled) { 6602 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6603 } 6604 6605 // Let the policy update hidden states. 6606 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6607 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6608 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6609 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6610 } 6611 6612 return true; 6613 } 6614 6615 public boolean isHardKeyboardAvailable() { 6616 synchronized (mWindowMap) { 6617 return mHardKeyboardAvailable; 6618 } 6619 } 6620 6621 public boolean isHardKeyboardEnabled() { 6622 synchronized (mWindowMap) { 6623 return mHardKeyboardEnabled; 6624 } 6625 } 6626 6627 public void setHardKeyboardEnabled(boolean enabled) { 6628 synchronized (mWindowMap) { 6629 if (mHardKeyboardEnabled != enabled) { 6630 mHardKeyboardEnabled = enabled; 6631 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6632 } 6633 } 6634 } 6635 6636 public void setOnHardKeyboardStatusChangeListener( 6637 OnHardKeyboardStatusChangeListener listener) { 6638 synchronized (mWindowMap) { 6639 mHardKeyboardStatusChangeListener = listener; 6640 } 6641 } 6642 6643 void notifyHardKeyboardStatusChange() { 6644 final boolean available, enabled; 6645 final OnHardKeyboardStatusChangeListener listener; 6646 synchronized (mWindowMap) { 6647 listener = mHardKeyboardStatusChangeListener; 6648 available = mHardKeyboardAvailable; 6649 enabled = mHardKeyboardEnabled; 6650 } 6651 if (listener != null) { 6652 listener.onHardKeyboardStatusChange(available, enabled); 6653 } 6654 } 6655 6656 // ------------------------------------------------------------- 6657 // Drag and drop 6658 // ------------------------------------------------------------- 6659 6660 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6661 int flags, int width, int height, Surface outSurface) { 6662 if (DEBUG_DRAG) { 6663 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6664 + " flags=" + Integer.toHexString(flags) + " win=" + window 6665 + " asbinder=" + window.asBinder()); 6666 } 6667 6668 final int callerPid = Binder.getCallingPid(); 6669 final long origId = Binder.clearCallingIdentity(); 6670 IBinder token = null; 6671 6672 try { 6673 synchronized (mWindowMap) { 6674 try { 6675 if (mDragState == null) { 6676 Surface surface = new Surface(session, callerPid, "drag surface", 6677 Display.DEFAULT_DISPLAY, 6678 width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN); 6679 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6680 + surface + ": CREATE"); 6681 outSurface.copyFrom(surface); 6682 final IBinder winBinder = window.asBinder(); 6683 token = new Binder(); 6684 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6685 token = mDragState.mToken = new Binder(); 6686 6687 // 5 second timeout for this window to actually begin the drag 6688 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6689 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6690 mH.sendMessageDelayed(msg, 5000); 6691 } else { 6692 Slog.w(TAG, "Drag already in progress"); 6693 } 6694 } catch (Surface.OutOfResourcesException e) { 6695 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6696 if (mDragState != null) { 6697 mDragState.reset(); 6698 mDragState = null; 6699 } 6700 } 6701 } 6702 } finally { 6703 Binder.restoreCallingIdentity(origId); 6704 } 6705 6706 return token; 6707 } 6708 6709 // ------------------------------------------------------------- 6710 // Input Events and Focus Management 6711 // ------------------------------------------------------------- 6712 6713 final InputMonitor mInputMonitor = new InputMonitor(this); 6714 private boolean mEventDispatchingEnabled; 6715 6716 public void pauseKeyDispatching(IBinder _token) { 6717 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6718 "pauseKeyDispatching()")) { 6719 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6720 } 6721 6722 synchronized (mWindowMap) { 6723 WindowToken token = mTokenMap.get(_token); 6724 if (token != null) { 6725 mInputMonitor.pauseDispatchingLw(token); 6726 } 6727 } 6728 } 6729 6730 public void resumeKeyDispatching(IBinder _token) { 6731 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6732 "resumeKeyDispatching()")) { 6733 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6734 } 6735 6736 synchronized (mWindowMap) { 6737 WindowToken token = mTokenMap.get(_token); 6738 if (token != null) { 6739 mInputMonitor.resumeDispatchingLw(token); 6740 } 6741 } 6742 } 6743 6744 public void setEventDispatching(boolean enabled) { 6745 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6746 "setEventDispatching()")) { 6747 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6748 } 6749 6750 synchronized (mWindowMap) { 6751 mEventDispatchingEnabled = enabled; 6752 if (mDisplayEnabled) { 6753 mInputMonitor.setEventDispatchingLw(enabled); 6754 } 6755 sendScreenStatusToClientsLocked(); 6756 } 6757 } 6758 6759 public IBinder getFocusedWindowToken() { 6760 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 6761 "getFocusedWindowToken()")) { 6762 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 6763 } 6764 synchronized (mWindowMap) { 6765 WindowState windowState = getFocusedWindowLocked(); 6766 if (windowState != null) { 6767 return windowState.mClient.asBinder(); 6768 } 6769 return null; 6770 } 6771 } 6772 6773 public boolean getWindowFrame(IBinder token, Rect outBounds) { 6774 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 6775 "getWindowFrame()")) { 6776 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 6777 } 6778 synchronized (mWindowMap) { 6779 WindowState windowState = mWindowMap.get(token); 6780 if (windowState != null) { 6781 outBounds.set(windowState.getFrameLw()); 6782 return true; 6783 } 6784 } 6785 return false; 6786 } 6787 6788 private WindowState getFocusedWindow() { 6789 synchronized (mWindowMap) { 6790 return getFocusedWindowLocked(); 6791 } 6792 } 6793 6794 private WindowState getFocusedWindowLocked() { 6795 return mCurrentFocus; 6796 } 6797 6798 public boolean detectSafeMode() { 6799 if (!mInputMonitor.waitForInputDevicesReady( 6800 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 6801 Slog.w(TAG, "Devices still not ready after waiting " 6802 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 6803 + " milliseconds before attempting to detect safe mode."); 6804 } 6805 6806 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6807 KeyEvent.KEYCODE_MENU); 6808 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 6809 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 6810 KeyEvent.KEYCODE_DPAD_CENTER); 6811 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 6812 InputManagerService.BTN_MOUSE); 6813 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6814 KeyEvent.KEYCODE_VOLUME_DOWN); 6815 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 6816 || volumeDownState > 0; 6817 try { 6818 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 6819 mSafeMode = true; 6820 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 6821 } 6822 } catch (IllegalArgumentException e) { 6823 } 6824 if (mSafeMode) { 6825 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 6826 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 6827 } else { 6828 Log.i(TAG, "SAFE MODE not enabled"); 6829 } 6830 mPolicy.setSafeMode(mSafeMode); 6831 return mSafeMode; 6832 } 6833 6834 public void displayReady() { 6835 synchronized(mWindowMap) { 6836 if (mDisplay != null) { 6837 throw new IllegalStateException("Display already initialized"); 6838 } 6839 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 6840 mDisplay = wm.getDefaultDisplay(); 6841 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 6842 PackageManager.FEATURE_TOUCHSCREEN); 6843 6844 synchronized(mDisplaySizeLock) { 6845 // Bootstrap the default logical display from the display manager. 6846 mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY, mDisplayInfo); 6847 mInitialDisplayWidth = mDisplayInfo.logicalWidth; 6848 mInitialDisplayHeight = mDisplayInfo.logicalHeight; 6849 mBaseDisplayWidth = mInitialDisplayWidth; 6850 mBaseDisplayHeight = mInitialDisplayHeight; 6851 6852 mAnimator.setDisplayDimensions(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, 6853 mDisplayInfo.appWidth, mDisplayInfo.appHeight); 6854 } 6855 6856 DisplayDeviceInfo info = new DisplayDeviceInfo(); 6857 mDisplayManager.getDefaultExternalDisplayDeviceInfo(info); 6858 mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY, 6859 mInitialDisplayWidth, mInitialDisplayHeight, 6860 info.width, info.height); 6861 mInputManager.setDisplayOrientation(Display.DEFAULT_DISPLAY, 6862 mDisplay.getRotation(), Surface.ROTATION_0); 6863 mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight); 6864 } 6865 6866 try { 6867 mActivityManager.updateConfiguration(null); 6868 } catch (RemoteException e) { 6869 } 6870 6871 synchronized (mWindowMap) { 6872 readForcedDisplaySizeLocked(); 6873 } 6874 } 6875 6876 public void systemReady() { 6877 mPolicy.systemReady(); 6878 } 6879 6880 private void sendScreenStatusToClientsLocked() { 6881 final ArrayList<WindowState> windows = mWindows; 6882 final int count = windows.size(); 6883 boolean on = mPowerManager.isScreenOn(); 6884 for (int i = count - 1; i >= 0; i--) { 6885 WindowState win = mWindows.get(i); 6886 try { 6887 win.mClient.dispatchScreenState(on); 6888 } catch (RemoteException e) { 6889 // Ignored 6890 } 6891 } 6892 } 6893 6894 // ------------------------------------------------------------- 6895 // Async Handler 6896 // ------------------------------------------------------------- 6897 6898 final class H extends Handler { 6899 public static final int REPORT_FOCUS_CHANGE = 2; 6900 public static final int REPORT_LOSING_FOCUS = 3; 6901 public static final int DO_TRAVERSAL = 4; 6902 public static final int ADD_STARTING = 5; 6903 public static final int REMOVE_STARTING = 6; 6904 public static final int FINISHED_STARTING = 7; 6905 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 6906 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 6907 public static final int WINDOW_FREEZE_TIMEOUT = 11; 6908 public static final int HOLD_SCREEN_CHANGED = 12; 6909 public static final int APP_TRANSITION_TIMEOUT = 13; 6910 public static final int PERSIST_ANIMATION_SCALE = 14; 6911 public static final int FORCE_GC = 15; 6912 public static final int ENABLE_SCREEN = 16; 6913 public static final int APP_FREEZE_TIMEOUT = 17; 6914 public static final int SEND_NEW_CONFIGURATION = 18; 6915 public static final int REPORT_WINDOWS_CHANGE = 19; 6916 public static final int DRAG_START_TIMEOUT = 20; 6917 public static final int DRAG_END_TIMEOUT = 21; 6918 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 6919 public static final int BOOT_TIMEOUT = 23; 6920 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 6921 public static final int UPDATE_ANIM_PARAMETERS = 25; 6922 public static final int SHOW_STRICT_MODE_VIOLATION = 26; 6923 public static final int DO_ANIMATION_CALLBACK = 27; 6924 6925 public static final int ANIMATOR_WHAT_OFFSET = 100000; 6926 public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1; 6927 public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 2; 6928 6929 private Session mLastReportedHold; 6930 6931 public H() { 6932 } 6933 6934 @Override 6935 public void handleMessage(Message msg) { 6936 if (DEBUG_WINDOW_TRACE) { 6937 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 6938 } 6939 switch (msg.what) { 6940 case REPORT_FOCUS_CHANGE: { 6941 WindowState lastFocus; 6942 WindowState newFocus; 6943 6944 synchronized(mWindowMap) { 6945 lastFocus = mLastFocus; 6946 newFocus = mCurrentFocus; 6947 if (lastFocus == newFocus) { 6948 // Focus is not changing, so nothing to do. 6949 return; 6950 } 6951 mLastFocus = newFocus; 6952 //Slog.i(TAG, "Focus moving from " + lastFocus 6953 // + " to " + newFocus); 6954 if (newFocus != null && lastFocus != null 6955 && !newFocus.isDisplayedLw()) { 6956 //Slog.i(TAG, "Delaying loss of focus..."); 6957 mLosingFocus.add(lastFocus); 6958 lastFocus = null; 6959 } 6960 } 6961 6962 if (lastFocus != newFocus) { 6963 //System.out.println("Changing focus from " + lastFocus 6964 // + " to " + newFocus); 6965 if (newFocus != null) { 6966 try { 6967 //Slog.i(TAG, "Gaining focus: " + newFocus); 6968 newFocus.mClient.windowFocusChanged(true, mInTouchMode); 6969 } catch (RemoteException e) { 6970 // Ignore if process has died. 6971 } 6972 notifyFocusChanged(); 6973 } 6974 6975 if (lastFocus != null) { 6976 try { 6977 //Slog.i(TAG, "Losing focus: " + lastFocus); 6978 lastFocus.mClient.windowFocusChanged(false, mInTouchMode); 6979 } catch (RemoteException e) { 6980 // Ignore if process has died. 6981 } 6982 } 6983 } 6984 } break; 6985 6986 case REPORT_LOSING_FOCUS: { 6987 ArrayList<WindowState> losers; 6988 6989 synchronized(mWindowMap) { 6990 losers = mLosingFocus; 6991 mLosingFocus = new ArrayList<WindowState>(); 6992 } 6993 6994 final int N = losers.size(); 6995 for (int i=0; i<N; i++) { 6996 try { 6997 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i)); 6998 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode); 6999 } catch (RemoteException e) { 7000 // Ignore if process has died. 7001 } 7002 } 7003 } break; 7004 7005 case DO_TRAVERSAL: { 7006 synchronized(mWindowMap) { 7007 mTraversalScheduled = false; 7008 performLayoutAndPlaceSurfacesLocked(); 7009 } 7010 } break; 7011 7012 case ADD_STARTING: { 7013 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7014 final StartingData sd = wtoken.startingData; 7015 7016 if (sd == null) { 7017 // Animation has been canceled... do nothing. 7018 return; 7019 } 7020 7021 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7022 + wtoken + ": pkg=" + sd.pkg); 7023 7024 View view = null; 7025 try { 7026 view = mPolicy.addStartingWindow( 7027 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7028 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags); 7029 } catch (Exception e) { 7030 Slog.w(TAG, "Exception when adding starting window", e); 7031 } 7032 7033 if (view != null) { 7034 boolean abort = false; 7035 7036 synchronized(mWindowMap) { 7037 if (wtoken.removed || wtoken.startingData == null) { 7038 // If the window was successfully added, then 7039 // we need to remove it. 7040 if (wtoken.startingWindow != null) { 7041 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7042 "Aborted starting " + wtoken 7043 + ": removed=" + wtoken.removed 7044 + " startingData=" + wtoken.startingData); 7045 wtoken.startingWindow = null; 7046 wtoken.startingData = null; 7047 abort = true; 7048 } 7049 } else { 7050 wtoken.startingView = view; 7051 } 7052 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7053 "Added starting " + wtoken 7054 + ": startingWindow=" 7055 + wtoken.startingWindow + " startingView=" 7056 + wtoken.startingView); 7057 } 7058 7059 if (abort) { 7060 try { 7061 mPolicy.removeStartingWindow(wtoken.token, view); 7062 } catch (Exception e) { 7063 Slog.w(TAG, "Exception when removing starting window", e); 7064 } 7065 } 7066 } 7067 } break; 7068 7069 case REMOVE_STARTING: { 7070 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7071 IBinder token = null; 7072 View view = null; 7073 synchronized (mWindowMap) { 7074 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7075 + wtoken + ": startingWindow=" 7076 + wtoken.startingWindow + " startingView=" 7077 + wtoken.startingView); 7078 if (wtoken.startingWindow != null) { 7079 view = wtoken.startingView; 7080 token = wtoken.token; 7081 wtoken.startingData = null; 7082 wtoken.startingView = null; 7083 wtoken.startingWindow = null; 7084 wtoken.startingDisplayed = false; 7085 } 7086 } 7087 if (view != null) { 7088 try { 7089 mPolicy.removeStartingWindow(token, view); 7090 } catch (Exception e) { 7091 Slog.w(TAG, "Exception when removing starting window", e); 7092 } 7093 } 7094 } break; 7095 7096 case FINISHED_STARTING: { 7097 IBinder token = null; 7098 View view = null; 7099 while (true) { 7100 synchronized (mWindowMap) { 7101 final int N = mFinishedStarting.size(); 7102 if (N <= 0) { 7103 break; 7104 } 7105 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7106 7107 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7108 "Finished starting " + wtoken 7109 + ": startingWindow=" + wtoken.startingWindow 7110 + " startingView=" + wtoken.startingView); 7111 7112 if (wtoken.startingWindow == null) { 7113 continue; 7114 } 7115 7116 view = wtoken.startingView; 7117 token = wtoken.token; 7118 wtoken.startingData = null; 7119 wtoken.startingView = null; 7120 wtoken.startingWindow = null; 7121 wtoken.startingDisplayed = false; 7122 } 7123 7124 try { 7125 mPolicy.removeStartingWindow(token, view); 7126 } catch (Exception e) { 7127 Slog.w(TAG, "Exception when removing starting window", e); 7128 } 7129 } 7130 } break; 7131 7132 case REPORT_APPLICATION_TOKEN_DRAWN: { 7133 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7134 7135 try { 7136 if (DEBUG_VISIBILITY) Slog.v( 7137 TAG, "Reporting drawn in " + wtoken); 7138 wtoken.appToken.windowsDrawn(); 7139 } catch (RemoteException ex) { 7140 } 7141 } break; 7142 7143 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7144 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7145 7146 boolean nowVisible = msg.arg1 != 0; 7147 boolean nowGone = msg.arg2 != 0; 7148 7149 try { 7150 if (DEBUG_VISIBILITY) Slog.v( 7151 TAG, "Reporting visible in " + wtoken 7152 + " visible=" + nowVisible 7153 + " gone=" + nowGone); 7154 if (nowVisible) { 7155 wtoken.appToken.windowsVisible(); 7156 } else { 7157 wtoken.appToken.windowsGone(); 7158 } 7159 } catch (RemoteException ex) { 7160 } 7161 } break; 7162 7163 case WINDOW_FREEZE_TIMEOUT: { 7164 synchronized (mWindowMap) { 7165 Slog.w(TAG, "Window freeze timeout expired."); 7166 int i = mWindows.size(); 7167 while (i > 0) { 7168 i--; 7169 WindowState w = mWindows.get(i); 7170 if (w.mOrientationChanging) { 7171 w.mOrientationChanging = false; 7172 Slog.w(TAG, "Force clearing orientation change: " + w); 7173 } 7174 } 7175 performLayoutAndPlaceSurfacesLocked(); 7176 } 7177 break; 7178 } 7179 7180 case HOLD_SCREEN_CHANGED: { 7181 Session oldHold; 7182 Session newHold; 7183 synchronized (mWindowMap) { 7184 oldHold = mLastReportedHold; 7185 newHold = (Session)msg.obj; 7186 mLastReportedHold = newHold; 7187 } 7188 7189 if (oldHold != newHold) { 7190 try { 7191 if (oldHold != null) { 7192 mBatteryStats.noteStopWakelock(oldHold.mUid, -1, 7193 "window", 7194 BatteryStats.WAKE_TYPE_WINDOW); 7195 } 7196 if (newHold != null) { 7197 mBatteryStats.noteStartWakelock(newHold.mUid, -1, 7198 "window", 7199 BatteryStats.WAKE_TYPE_WINDOW); 7200 } 7201 } catch (RemoteException e) { 7202 } 7203 } 7204 break; 7205 } 7206 7207 case APP_TRANSITION_TIMEOUT: { 7208 synchronized (mWindowMap) { 7209 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 7210 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7211 "*** APP TRANSITION TIMEOUT"); 7212 mAppTransitionReady = true; 7213 mAppTransitionTimeout = true; 7214 mAnimatingAppTokens.clear(); 7215 mAnimatingAppTokens.addAll(mAppTokens); 7216 performLayoutAndPlaceSurfacesLocked(); 7217 } 7218 } 7219 break; 7220 } 7221 7222 case PERSIST_ANIMATION_SCALE: { 7223 Settings.System.putFloat(mContext.getContentResolver(), 7224 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 7225 Settings.System.putFloat(mContext.getContentResolver(), 7226 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 7227 Settings.System.putFloat(mContext.getContentResolver(), 7228 Settings.System.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 7229 break; 7230 } 7231 7232 case FORCE_GC: { 7233 synchronized (mWindowMap) { 7234 synchronized (mAnimator) { 7235 // Since we're holding both mWindowMap and mAnimator we don't need to 7236 // hold mAnimator.mLayoutToAnim. 7237 if (mAnimator.mAnimating || mLayoutToAnim.mAnimationScheduled) { 7238 // If we are animating, don't do the gc now but 7239 // delay a bit so we don't interrupt the animation. 7240 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 7241 2000); 7242 return; 7243 } 7244 // If we are currently rotating the display, it will 7245 // schedule a new message when done. 7246 if (mDisplayFrozen) { 7247 return; 7248 } 7249 } 7250 } 7251 Runtime.getRuntime().gc(); 7252 break; 7253 } 7254 7255 case ENABLE_SCREEN: { 7256 performEnableScreen(); 7257 break; 7258 } 7259 7260 case APP_FREEZE_TIMEOUT: { 7261 synchronized (mWindowMap) { 7262 synchronized (mAnimator) { 7263 Slog.w(TAG, "App freeze timeout expired."); 7264 int i = mAppTokens.size(); 7265 while (i > 0) { 7266 i--; 7267 AppWindowToken tok = mAppTokens.get(i); 7268 if (tok.mAppAnimator.freezingScreen) { 7269 Slog.w(TAG, "Force clearing freeze: " + tok); 7270 unsetAppFreezingScreenLocked(tok, true, true); 7271 } 7272 } 7273 } 7274 } 7275 break; 7276 } 7277 7278 case SEND_NEW_CONFIGURATION: { 7279 removeMessages(SEND_NEW_CONFIGURATION); 7280 sendNewConfiguration(); 7281 break; 7282 } 7283 7284 case REPORT_WINDOWS_CHANGE: { 7285 if (mWindowsChanged) { 7286 synchronized (mWindowMap) { 7287 mWindowsChanged = false; 7288 } 7289 notifyWindowsChanged(); 7290 } 7291 break; 7292 } 7293 7294 case DRAG_START_TIMEOUT: { 7295 IBinder win = (IBinder)msg.obj; 7296 if (DEBUG_DRAG) { 7297 Slog.w(TAG, "Timeout starting drag by win " + win); 7298 } 7299 synchronized (mWindowMap) { 7300 // !!! TODO: ANR the app that has failed to start the drag in time 7301 if (mDragState != null) { 7302 mDragState.unregister(); 7303 mInputMonitor.updateInputWindowsLw(true /*force*/); 7304 mDragState.reset(); 7305 mDragState = null; 7306 } 7307 } 7308 break; 7309 } 7310 7311 case DRAG_END_TIMEOUT: { 7312 IBinder win = (IBinder)msg.obj; 7313 if (DEBUG_DRAG) { 7314 Slog.w(TAG, "Timeout ending drag to win " + win); 7315 } 7316 synchronized (mWindowMap) { 7317 // !!! TODO: ANR the drag-receiving app 7318 if (mDragState != null) { 7319 mDragState.mDragResult = false; 7320 mDragState.endDragLw(); 7321 } 7322 } 7323 break; 7324 } 7325 7326 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7327 notifyHardKeyboardStatusChange(); 7328 break; 7329 } 7330 7331 case BOOT_TIMEOUT: { 7332 performBootTimeout(); 7333 break; 7334 } 7335 7336 case WAITING_FOR_DRAWN_TIMEOUT: { 7337 Pair<WindowState, IRemoteCallback> pair; 7338 synchronized (mWindowMap) { 7339 pair = (Pair<WindowState, IRemoteCallback>)msg.obj; 7340 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first); 7341 if (!mWaitingForDrawn.remove(pair)) { 7342 return; 7343 } 7344 } 7345 try { 7346 pair.second.sendResult(null); 7347 } catch (RemoteException e) { 7348 } 7349 break; 7350 } 7351 7352 case UPDATE_ANIM_PARAMETERS: { 7353 // Used to send multiple changes from the animation side to the layout side. 7354 synchronized (mWindowMap) { 7355 if (copyAnimToLayoutParamsLocked()) { 7356 mH.sendEmptyMessage(CLEAR_PENDING_ACTIONS); 7357 performLayoutAndPlaceSurfacesLocked(); 7358 } 7359 } 7360 break; 7361 } 7362 7363 case SHOW_STRICT_MODE_VIOLATION: { 7364 showStrictModeViolation(msg.arg1); 7365 break; 7366 } 7367 7368 // Animation messages. Move to Window{State}Animator 7369 case SET_TRANSPARENT_REGION: { 7370 Pair<WindowStateAnimator, Region> pair = 7371 (Pair<WindowStateAnimator, Region>) msg.obj; 7372 final WindowStateAnimator winAnimator = pair.first; 7373 winAnimator.setTransparentRegionHint(pair.second); 7374 break; 7375 } 7376 7377 case CLEAR_PENDING_ACTIONS: { 7378 mAnimator.clearPendingActions(); 7379 break; 7380 } 7381 7382 case DO_ANIMATION_CALLBACK: { 7383 try { 7384 ((IRemoteCallback)msg.obj).sendResult(null); 7385 } catch (RemoteException e) { 7386 } 7387 break; 7388 } 7389 } 7390 if (DEBUG_WINDOW_TRACE) { 7391 Slog.v(TAG, "handleMessage: exit"); 7392 } 7393 } 7394 } 7395 7396 // ------------------------------------------------------------- 7397 // IWindowManager API 7398 // ------------------------------------------------------------- 7399 7400 @Override 7401 public IWindowSession openSession(IInputMethodClient client, 7402 IInputContext inputContext) { 7403 if (client == null) throw new IllegalArgumentException("null client"); 7404 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7405 Session session = new Session(this, client, inputContext); 7406 return session; 7407 } 7408 7409 @Override 7410 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7411 synchronized (mWindowMap) { 7412 // The focus for the client is the window immediately below 7413 // where we would place the input method window. 7414 int idx = findDesiredInputMethodWindowIndexLocked(false); 7415 WindowState imFocus; 7416 if (idx > 0) { 7417 imFocus = mWindows.get(idx-1); 7418 if (DEBUG_INPUT_METHOD) { 7419 Slog.i(TAG, "Desired input method target: " + imFocus); 7420 Slog.i(TAG, "Current focus: " + this.mCurrentFocus); 7421 Slog.i(TAG, "Last focus: " + this.mLastFocus); 7422 } 7423 if (imFocus != null) { 7424 // This may be a starting window, in which case we still want 7425 // to count it as okay. 7426 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7427 && imFocus.mAppToken != null) { 7428 // The client has definitely started, so it really should 7429 // have a window in this app token. Let's look for it. 7430 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7431 WindowState w = imFocus.mAppToken.windows.get(i); 7432 if (w != imFocus) { 7433 Log.i(TAG, "Switching to real app window: " + w); 7434 imFocus = w; 7435 break; 7436 } 7437 } 7438 } 7439 if (DEBUG_INPUT_METHOD) { 7440 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7441 if (imFocus.mSession.mClient != null) { 7442 Slog.i(TAG, "IM target client binder: " 7443 + imFocus.mSession.mClient.asBinder()); 7444 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7445 } 7446 } 7447 if (imFocus.mSession.mClient != null && 7448 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7449 return true; 7450 } 7451 7452 // Okay, how about this... what is the current focus? 7453 // It seems in some cases we may not have moved the IM 7454 // target window, such as when it was in a pop-up window, 7455 // so let's also look at the current focus. (An example: 7456 // go to Gmail, start searching so the keyboard goes up, 7457 // press home. Sometimes the IME won't go down.) 7458 // Would be nice to fix this more correctly, but it's 7459 // way at the end of a release, and this should be good enough. 7460 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null && 7461 mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7462 return true; 7463 } 7464 } 7465 } 7466 } 7467 return false; 7468 } 7469 7470 public void getInitialDisplaySize(Point size) { 7471 synchronized(mDisplaySizeLock) { 7472 size.x = mInitialDisplayWidth; 7473 size.y = mInitialDisplayHeight; 7474 } 7475 } 7476 7477 public void setForcedDisplaySize(int longDimen, int shortDimen) { 7478 synchronized(mWindowMap) { 7479 int width, height; 7480 if (mInitialDisplayWidth < mInitialDisplayHeight) { 7481 width = shortDimen < mInitialDisplayWidth 7482 ? shortDimen : mInitialDisplayWidth; 7483 height = longDimen < mInitialDisplayHeight 7484 ? longDimen : mInitialDisplayHeight; 7485 } else { 7486 width = longDimen < mInitialDisplayWidth 7487 ? longDimen : mInitialDisplayWidth; 7488 height = shortDimen < mInitialDisplayHeight 7489 ? shortDimen : mInitialDisplayHeight; 7490 } 7491 setForcedDisplaySizeLocked(width, height); 7492 Settings.Secure.putString(mContext.getContentResolver(), 7493 Settings.Secure.DISPLAY_SIZE_FORCED, width + "," + height); 7494 } 7495 } 7496 7497 private void rebuildBlackFrame() { 7498 if (mBlackFrame != null) { 7499 mBlackFrame.kill(); 7500 mBlackFrame = null; 7501 } 7502 if (mBaseDisplayWidth < mInitialDisplayWidth 7503 || mBaseDisplayHeight < mInitialDisplayHeight) { 7504 int initW, initH, baseW, baseH; 7505 final boolean rotated = (mRotation == Surface.ROTATION_90 7506 || mRotation == Surface.ROTATION_270); 7507 if (rotated) { 7508 initW = mInitialDisplayHeight; 7509 initH = mInitialDisplayWidth; 7510 baseW = mBaseDisplayHeight; 7511 baseH = mBaseDisplayWidth; 7512 } else { 7513 initW = mInitialDisplayWidth; 7514 initH = mInitialDisplayHeight; 7515 baseW = mBaseDisplayWidth; 7516 baseH = mBaseDisplayHeight; 7517 } 7518 Rect outer = new Rect(0, 0, initW, initH); 7519 Rect inner = new Rect(0, 0, baseW, baseH); 7520 try { 7521 mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER); 7522 } catch (Surface.OutOfResourcesException e) { 7523 } 7524 } 7525 } 7526 7527 private void readForcedDisplaySizeLocked() { 7528 final String str = Settings.Secure.getString(mContext.getContentResolver(), 7529 Settings.Secure.DISPLAY_SIZE_FORCED); 7530 if (str == null || str.length() == 0) { 7531 return; 7532 } 7533 final int pos = str.indexOf(','); 7534 if (pos <= 0 || str.lastIndexOf(',') != pos) { 7535 return; 7536 } 7537 int width, height; 7538 try { 7539 width = Integer.parseInt(str.substring(0, pos)); 7540 height = Integer.parseInt(str.substring(pos+1)); 7541 } catch (NumberFormatException ex) { 7542 return; 7543 } 7544 setForcedDisplaySizeLocked(width, height); 7545 } 7546 7547 private void setForcedDisplaySizeLocked(int width, int height) { 7548 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7549 7550 synchronized(mDisplaySizeLock) { 7551 mBaseDisplayWidth = width; 7552 mBaseDisplayHeight = height; 7553 } 7554 mPolicy.setInitialDisplaySize(mDisplay, mBaseDisplayWidth, mBaseDisplayHeight); 7555 7556 mLayoutNeeded = true; 7557 7558 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7559 mTempConfiguration.setToDefaults(); 7560 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7561 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7562 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7563 configChanged = true; 7564 } 7565 } 7566 7567 if (configChanged) { 7568 mWaitingForConfig = true; 7569 startFreezingDisplayLocked(false); 7570 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7571 } 7572 7573 rebuildBlackFrame(); 7574 7575 performLayoutAndPlaceSurfacesLocked(); 7576 } 7577 7578 public void clearForcedDisplaySize() { 7579 synchronized(mWindowMap) { 7580 setForcedDisplaySizeLocked(mInitialDisplayWidth, mInitialDisplayHeight); 7581 Settings.Secure.putString(mContext.getContentResolver(), 7582 Settings.Secure.DISPLAY_SIZE_FORCED, ""); 7583 } 7584 } 7585 7586 public boolean hasSystemNavBar() { 7587 return mPolicy.hasSystemNavBar(); 7588 } 7589 7590 // ------------------------------------------------------------- 7591 // Internals 7592 // ------------------------------------------------------------- 7593 7594 final WindowState windowForClientLocked(Session session, IWindow client, 7595 boolean throwOnError) { 7596 return windowForClientLocked(session, client.asBinder(), throwOnError); 7597 } 7598 7599 final WindowState windowForClientLocked(Session session, IBinder client, 7600 boolean throwOnError) { 7601 WindowState win = mWindowMap.get(client); 7602 if (localLOGV) Slog.v( 7603 TAG, "Looking up client " + client + ": " + win); 7604 if (win == null) { 7605 RuntimeException ex = new IllegalArgumentException( 7606 "Requested window " + client + " does not exist"); 7607 if (throwOnError) { 7608 throw ex; 7609 } 7610 Slog.w(TAG, "Failed looking up window", ex); 7611 return null; 7612 } 7613 if (session != null && win.mSession != session) { 7614 RuntimeException ex = new IllegalArgumentException( 7615 "Requested window " + client + " is in session " + 7616 win.mSession + ", not " + session); 7617 if (throwOnError) { 7618 throw ex; 7619 } 7620 Slog.w(TAG, "Failed looking up window", ex); 7621 return null; 7622 } 7623 7624 return win; 7625 } 7626 7627 final void rebuildAppWindowListLocked() { 7628 int NW = mWindows.size(); 7629 int i; 7630 int lastBelow = -1; 7631 int numRemoved = 0; 7632 7633 if (mRebuildTmp.length < NW) { 7634 mRebuildTmp = new WindowState[NW+10]; 7635 } 7636 7637 // First remove all existing app windows. 7638 i=0; 7639 while (i < NW) { 7640 WindowState w = mWindows.get(i); 7641 if (w.mAppToken != null) { 7642 WindowState win = mWindows.remove(i); 7643 win.mRebuilding = true; 7644 mRebuildTmp[numRemoved] = win; 7645 mWindowsChanged = true; 7646 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 7647 "Rebuild removing window: " + win); 7648 NW--; 7649 numRemoved++; 7650 continue; 7651 } else if (lastBelow == i-1) { 7652 if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER 7653 || w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) { 7654 lastBelow = i; 7655 } 7656 } 7657 i++; 7658 } 7659 7660 // Keep whatever windows were below the app windows still below, 7661 // by skipping them. 7662 lastBelow++; 7663 i = lastBelow; 7664 7665 // First add all of the exiting app tokens... these are no longer 7666 // in the main app list, but still have windows shown. We put them 7667 // in the back because now that the animation is over we no longer 7668 // will care about them. 7669 int NT = mExitingAppTokens.size(); 7670 for (int j=0; j<NT; j++) { 7671 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j)); 7672 } 7673 7674 // And add in the still active app tokens in Z order. 7675 NT = mAnimatingAppTokens.size(); 7676 for (int j=0; j<NT; j++) { 7677 i = reAddAppWindowsLocked(i, mAnimatingAppTokens.get(j)); 7678 } 7679 7680 i -= lastBelow; 7681 if (i != numRemoved) { 7682 Slog.w(TAG, "Rebuild removed " + numRemoved 7683 + " windows but added " + i); 7684 for (i=0; i<numRemoved; i++) { 7685 WindowState ws = mRebuildTmp[i]; 7686 if (ws.mRebuilding) { 7687 StringWriter sw = new StringWriter(); 7688 PrintWriter pw = new PrintWriter(sw); 7689 ws.dump(pw, "", true); 7690 pw.flush(); 7691 Slog.w(TAG, "This window was lost: " + ws); 7692 Slog.w(TAG, sw.toString()); 7693 ws.mWinAnimator.destroySurfaceLocked(); 7694 } 7695 } 7696 Slog.w(TAG, "Current app token list:"); 7697 dumpAnimatingAppTokensLocked(); 7698 Slog.w(TAG, "Final window list:"); 7699 dumpWindowsLocked(); 7700 } 7701 } 7702 7703 private final void assignLayersLocked() { 7704 int N = mWindows.size(); 7705 int curBaseLayer = 0; 7706 int curLayer = 0; 7707 int i; 7708 7709 if (DEBUG_LAYERS) { 7710 RuntimeException here = new RuntimeException("here"); 7711 here.fillInStackTrace(); 7712 Slog.v(TAG, "Assigning layers", here); 7713 } 7714 7715 for (i=0; i<N; i++) { 7716 final WindowState w = mWindows.get(i); 7717 final WindowStateAnimator winAnimator = w.mWinAnimator; 7718 boolean layerChanged = false; 7719 int oldLayer = w.mLayer; 7720 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 7721 || (i > 0 && w.mIsWallpaper)) { 7722 curLayer += WINDOW_LAYER_MULTIPLIER; 7723 w.mLayer = curLayer; 7724 } else { 7725 curBaseLayer = curLayer = w.mBaseLayer; 7726 w.mLayer = curLayer; 7727 } 7728 if (w.mLayer != oldLayer) { 7729 layerChanged = true; 7730 } 7731 oldLayer = winAnimator.mAnimLayer; 7732 if (w.mTargetAppToken != null) { 7733 winAnimator.mAnimLayer = 7734 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 7735 } else if (w.mAppToken != null) { 7736 winAnimator.mAnimLayer = 7737 w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment; 7738 } else { 7739 winAnimator.mAnimLayer = w.mLayer; 7740 } 7741 if (w.mIsImWindow) { 7742 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 7743 } else if (w.mIsWallpaper) { 7744 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 7745 } 7746 if (winAnimator.mAnimLayer != oldLayer) { 7747 layerChanged = true; 7748 } 7749 if (layerChanged && mAnimator.isDimming(winAnimator)) { 7750 // Force an animation pass just to update the mDimAnimator layer. 7751 updateLayoutToAnimationLocked(); 7752 } 7753 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 7754 + winAnimator.mAnimLayer); 7755 //System.out.println( 7756 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 7757 } 7758 } 7759 7760 private boolean mInLayout = false; 7761 private final void performLayoutAndPlaceSurfacesLocked() { 7762 if (mInLayout) { 7763 if (DEBUG) { 7764 throw new RuntimeException("Recursive call!"); 7765 } 7766 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 7767 + Debug.getCallers(3)); 7768 return; 7769 } 7770 7771 if (mWaitingForConfig) { 7772 // Our configuration has changed (most likely rotation), but we 7773 // don't yet have the complete configuration to report to 7774 // applications. Don't do any window layout until we have it. 7775 return; 7776 } 7777 7778 if (mDisplay == null) { 7779 // Not yet initialized, nothing to do. 7780 return; 7781 } 7782 7783 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 7784 mInLayout = true; 7785 boolean recoveringMemory = false; 7786 7787 try { 7788 if (mForceRemoves != null) { 7789 recoveringMemory = true; 7790 // Wait a little bit for things to settle down, and off we go. 7791 for (int i=0; i<mForceRemoves.size(); i++) { 7792 WindowState ws = mForceRemoves.get(i); 7793 Slog.i(TAG, "Force removing: " + ws); 7794 removeWindowInnerLocked(ws.mSession, ws); 7795 } 7796 mForceRemoves = null; 7797 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 7798 Object tmp = new Object(); 7799 synchronized (tmp) { 7800 try { 7801 tmp.wait(250); 7802 } catch (InterruptedException e) { 7803 } 7804 } 7805 } 7806 } catch (RuntimeException e) { 7807 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 7808 } 7809 7810 try { 7811 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 7812 7813 final int N = mPendingRemove.size(); 7814 if (N > 0) { 7815 if (mPendingRemoveTmp.length < N) { 7816 mPendingRemoveTmp = new WindowState[N+10]; 7817 } 7818 mPendingRemove.toArray(mPendingRemoveTmp); 7819 mPendingRemove.clear(); 7820 for (int i=0; i<N; i++) { 7821 WindowState w = mPendingRemoveTmp[i]; 7822 removeWindowInnerLocked(w.mSession, w); 7823 } 7824 7825 mInLayout = false; 7826 assignLayersLocked(); 7827 mLayoutNeeded = true; 7828 // XXX this recursion seems broken! 7829 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 7830 performLayoutAndPlaceSurfacesLocked(); 7831 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 7832 7833 } else { 7834 mInLayout = false; 7835 } 7836 7837 if (mLayoutNeeded) { 7838 if (++mLayoutRepeatCount < 6) { 7839 requestTraversalLocked(); 7840 } else { 7841 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 7842 mLayoutRepeatCount = 0; 7843 } 7844 } else { 7845 mLayoutRepeatCount = 0; 7846 } 7847 7848 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 7849 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 7850 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE)); 7851 } 7852 } catch (RuntimeException e) { 7853 mInLayout = false; 7854 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 7855 } 7856 7857 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 7858 } 7859 7860 private final void performLayoutLockedInner(boolean initial, boolean updateInputWindows) { 7861 if (!mLayoutNeeded) { 7862 return; 7863 } 7864 7865 mLayoutNeeded = false; 7866 7867 final int dw = mDisplayInfo.logicalWidth; 7868 final int dh = mDisplayInfo.logicalHeight; 7869 7870 final int NFW = mFakeWindows.size(); 7871 for (int i=0; i<NFW; i++) { 7872 mFakeWindows.get(i).layout(dw, dh); 7873 } 7874 7875 final int N = mWindows.size(); 7876 int i; 7877 7878 if (DEBUG_LAYOUT) { 7879 Slog.v(TAG, "-------------------------------------"); 7880 Slog.v(TAG, "performLayout: needed=" 7881 + mLayoutNeeded + " dw=" + dw + " dh=" + dh); 7882 } 7883 7884 WindowStateAnimator universeBackground = null; 7885 7886 mPolicy.beginLayoutLw(dw, dh, mRotation); 7887 mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect); 7888 mScreenRect.set(0, 0, dw, dh); 7889 7890 int seq = mLayoutSeq+1; 7891 if (seq < 0) seq = 0; 7892 mLayoutSeq = seq; 7893 7894 // First perform layout of any root windows (not attached 7895 // to another window). 7896 int topAttached = -1; 7897 for (i = N-1; i >= 0; i--) { 7898 final WindowState win = mWindows.get(i); 7899 7900 // Don't do layout of a window if it is not visible, or 7901 // soon won't be visible, to avoid wasting time and funky 7902 // changes while a window is animating away. 7903 final boolean gone = win.isGoneForLayoutLw(); 7904 7905 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 7906 Slog.v(TAG, "1ST PASS " + win 7907 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 7908 + " mLayoutAttached=" + win.mLayoutAttached); 7909 final AppWindowToken atoken = win.mAppToken; 7910 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 7911 + win.mViewVisibility + " mRelayoutCalled=" 7912 + win.mRelayoutCalled + " hidden=" 7913 + win.mRootToken.hidden + " hiddenRequested=" 7914 + (atoken != null && atoken.hiddenRequested) 7915 + " mAttachedHidden=" + win.mAttachedHidden); 7916 else Slog.v(TAG, " VIS: mViewVisibility=" 7917 + win.mViewVisibility + " mRelayoutCalled=" 7918 + win.mRelayoutCalled + " hidden=" 7919 + win.mRootToken.hidden + " hiddenRequested=" 7920 + (atoken != null && atoken.hiddenRequested) 7921 + " mAttachedHidden=" + win.mAttachedHidden); 7922 } 7923 7924 // If this view is GONE, then skip it -- keep the current 7925 // frame, and let the caller know so they can ignore it 7926 // if they want. (We do the normal layout for INVISIBLE 7927 // windows, since that means "perform layout as normal, 7928 // just don't display"). 7929 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 7930 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 7931 if (!win.mLayoutAttached) { 7932 if (initial) { 7933 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7934 win.mContentChanged = false; 7935 } 7936 win.mLayoutNeeded = false; 7937 win.prelayout(); 7938 mPolicy.layoutWindowLw(win, win.mAttrs, null); 7939 win.mLayoutSeq = seq; 7940 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7941 + win.mFrame + " mContainingFrame=" 7942 + win.mContainingFrame + " mDisplayFrame=" 7943 + win.mDisplayFrame); 7944 } else { 7945 if (topAttached < 0) topAttached = i; 7946 } 7947 } 7948 if (win.mViewVisibility == View.VISIBLE 7949 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 7950 && universeBackground == null) { 7951 universeBackground = win.mWinAnimator; 7952 } 7953 } 7954 7955 if (mAnimator.mUniverseBackground != universeBackground) { 7956 mFocusMayChange = true; 7957 mAnimator.mUniverseBackground = universeBackground; 7958 } 7959 7960 // Now perform layout of attached windows, which usually 7961 // depend on the position of the window they are attached to. 7962 // XXX does not deal with windows that are attached to windows 7963 // that are themselves attached. 7964 for (i = topAttached; i >= 0; i--) { 7965 final WindowState win = mWindows.get(i); 7966 7967 if (win.mLayoutAttached) { 7968 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 7969 + " mHaveFrame=" + win.mHaveFrame 7970 + " mViewVisibility=" + win.mViewVisibility 7971 + " mRelayoutCalled=" + win.mRelayoutCalled); 7972 // If this view is GONE, then skip it -- keep the current 7973 // frame, and let the caller know so they can ignore it 7974 // if they want. (We do the normal layout for INVISIBLE 7975 // windows, since that means "perform layout as normal, 7976 // just don't display"). 7977 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 7978 || !win.mHaveFrame || win.mLayoutNeeded) { 7979 if (initial) { 7980 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7981 win.mContentChanged = false; 7982 } 7983 win.mLayoutNeeded = false; 7984 win.prelayout(); 7985 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 7986 win.mLayoutSeq = seq; 7987 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7988 + win.mFrame + " mContainingFrame=" 7989 + win.mContainingFrame + " mDisplayFrame=" 7990 + win.mDisplayFrame); 7991 } 7992 } 7993 } 7994 7995 // Window frames may have changed. Tell the input dispatcher about it. 7996 mInputMonitor.setUpdateInputWindowsNeededLw(); 7997 if (updateInputWindows) { 7998 mInputMonitor.updateInputWindowsLw(false /*force*/); 7999 } 8000 8001 mPolicy.finishLayoutLw(); 8002 } 8003 8004 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8005 // If the screen is currently frozen or off, then keep 8006 // it frozen/off until this window draws at its new 8007 // orientation. 8008 if (!okToDisplay()) { 8009 if (DEBUG_ORIENTATION) Slog.v(TAG, 8010 "Changing surface while display frozen: " + w); 8011 w.mOrientationChanging = true; 8012 mInnerFields.mOrientationChangeComplete = false; 8013 if (!mWindowsFreezingScreen) { 8014 mWindowsFreezingScreen = true; 8015 // XXX should probably keep timeout from 8016 // when we first froze the display. 8017 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8018 mH.sendMessageDelayed(mH.obtainMessage( 8019 H.WINDOW_FREEZE_TIMEOUT), 2000); 8020 } 8021 } 8022 } 8023 8024 /** 8025 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8026 * 8027 * @return bitmap indicating if another pass through layout must be made. 8028 */ 8029 public int handleAppTransitionReadyLocked() { 8030 int changes = 0; 8031 int i; 8032 int NN = mOpeningApps.size(); 8033 boolean goodToGo = true; 8034 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8035 "Checking " + NN + " opening apps (frozen=" 8036 + mDisplayFrozen + " timeout=" 8037 + mAppTransitionTimeout + ")..."); 8038 if (!mDisplayFrozen && !mAppTransitionTimeout) { 8039 // If the display isn't frozen, wait to do anything until 8040 // all of the apps are ready. Otherwise just go because 8041 // we'll unfreeze the display when everyone is ready. 8042 for (i=0; i<NN && goodToGo; i++) { 8043 AppWindowToken wtoken = mOpeningApps.get(i); 8044 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8045 "Check opening app=" + wtoken + ": allDrawn=" 8046 + wtoken.allDrawn + " startingDisplayed=" 8047 + wtoken.startingDisplayed + " startingMoved=" 8048 + wtoken.startingMoved); 8049 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8050 && !wtoken.startingMoved) { 8051 goodToGo = false; 8052 } 8053 } 8054 } 8055 if (goodToGo) { 8056 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8057 int transit = mNextAppTransition; 8058 if (mSkipAppTransitionAnimation) { 8059 transit = WindowManagerPolicy.TRANSIT_UNSET; 8060 } 8061 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 8062 mAppTransitionReady = false; 8063 mAppTransitionRunning = true; 8064 mAppTransitionTimeout = false; 8065 mStartingIconInTransition = false; 8066 mSkipAppTransitionAnimation = false; 8067 8068 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8069 8070 rebuildAppWindowListLocked(); 8071 8072 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8073 WindowState oldWallpaper = 8074 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8075 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8076 ? null : mWallpaperTarget; 8077 8078 adjustWallpaperWindowsLocked(); 8079 mInnerFields.mWallpaperMayChange = false; 8080 8081 // The top-most window will supply the layout params, 8082 // and we will determine it below. 8083 LayoutParams animLp = null; 8084 int bestAnimLayer = -1; 8085 boolean fullscreenAnim = false; 8086 8087 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8088 "New wallpaper target=" + mWallpaperTarget 8089 + ", oldWallpaper=" + oldWallpaper 8090 + ", lower target=" + mLowerWallpaperTarget 8091 + ", upper target=" + mUpperWallpaperTarget); 8092 int foundWallpapers = 0; 8093 // Do a first pass through the tokens for two 8094 // things: 8095 // (1) Determine if both the closing and opening 8096 // app token sets are wallpaper targets, in which 8097 // case special animations are needed 8098 // (since the wallpaper needs to stay static 8099 // behind them). 8100 // (2) Find the layout params of the top-most 8101 // application window in the tokens, which is 8102 // what will control the animation theme. 8103 final int NC = mClosingApps.size(); 8104 NN = NC + mOpeningApps.size(); 8105 for (i=0; i<NN; i++) { 8106 AppWindowToken wtoken; 8107 int mode; 8108 if (i < NC) { 8109 wtoken = mClosingApps.get(i); 8110 mode = 1; 8111 } else { 8112 wtoken = mOpeningApps.get(i-NC); 8113 mode = 2; 8114 } 8115 if (mLowerWallpaperTarget != null) { 8116 if (mLowerWallpaperTarget.mAppToken == wtoken 8117 || mUpperWallpaperTarget.mAppToken == wtoken) { 8118 foundWallpapers |= mode; 8119 } 8120 } 8121 if (wtoken.appFullscreen) { 8122 WindowState ws = wtoken.findMainWindow(); 8123 if (ws != null) { 8124 animLp = ws.mAttrs; 8125 bestAnimLayer = ws.mLayer; 8126 fullscreenAnim = true; 8127 } 8128 } else if (!fullscreenAnim) { 8129 WindowState ws = wtoken.findMainWindow(); 8130 if (ws != null) { 8131 if (ws.mLayer > bestAnimLayer) { 8132 animLp = ws.mAttrs; 8133 bestAnimLayer = ws.mLayer; 8134 } 8135 } 8136 } 8137 } 8138 8139 if (foundWallpapers == 3) { 8140 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8141 "Wallpaper animation!"); 8142 switch (transit) { 8143 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 8144 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 8145 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 8146 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN; 8147 break; 8148 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 8149 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 8150 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 8151 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE; 8152 break; 8153 } 8154 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8155 "New transit: " + transit); 8156 } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8157 // We are transitioning from an activity with 8158 // a wallpaper to one without. 8159 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE; 8160 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8161 "New transit away from wallpaper: " + transit); 8162 } else if (mWallpaperTarget != null) { 8163 // We are transitioning from an activity without 8164 // a wallpaper to now showing the wallpaper 8165 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN; 8166 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8167 "New transit into wallpaper: " + transit); 8168 } 8169 8170 // If all closing windows are obscured, then there is 8171 // no need to do an animation. This is the case, for 8172 // example, when this transition is being done behind 8173 // the lock screen. 8174 if (!mPolicy.allowAppAnimationsLw()) { 8175 animLp = null; 8176 } 8177 8178 AppWindowToken topOpeningApp = null; 8179 int topOpeningLayer = 0; 8180 8181 NN = mOpeningApps.size(); 8182 for (i=0; i<NN; i++) { 8183 AppWindowToken wtoken = mOpeningApps.get(i); 8184 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8185 wtoken.mAppAnimator.clearThumbnail(); 8186 wtoken.reportedVisible = false; 8187 wtoken.inPendingTransaction = false; 8188 wtoken.mAppAnimator.animation = null; 8189 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 8190 wtoken.updateReportedVisibilityLocked(); 8191 wtoken.waitingToShow = false; 8192 mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked(); 8193 if (animLp != null) { 8194 int layer = -1; 8195 for (int j=0; j<wtoken.windows.size(); j++) { 8196 WindowState win = wtoken.windows.get(j); 8197 if (win.mWinAnimator.mAnimLayer > layer) { 8198 layer = win.mWinAnimator.mAnimLayer; 8199 } 8200 } 8201 if (topOpeningApp == null || layer > topOpeningLayer) { 8202 topOpeningApp = wtoken; 8203 topOpeningLayer = layer; 8204 } 8205 } 8206 } 8207 NN = mClosingApps.size(); 8208 for (i=0; i<NN; i++) { 8209 AppWindowToken wtoken = mClosingApps.get(i); 8210 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8211 "Now closing app" + wtoken); 8212 wtoken.mAppAnimator.clearThumbnail(); 8213 wtoken.inPendingTransaction = false; 8214 wtoken.mAppAnimator.animation = null; 8215 setTokenVisibilityLocked(wtoken, animLp, false, 8216 transit, false); 8217 wtoken.updateReportedVisibilityLocked(); 8218 wtoken.waitingToHide = false; 8219 // Force the allDrawn flag, because we want to start 8220 // this guy's animations regardless of whether it's 8221 // gotten drawn. 8222 wtoken.allDrawn = true; 8223 } 8224 8225 if (mNextAppTransitionThumbnail != null && topOpeningApp != null 8226 && topOpeningApp.mAppAnimator.animation != null) { 8227 // This thumbnail animation is very special, we need to have 8228 // an extra surface with the thumbnail included with the animation. 8229 Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(), 8230 mNextAppTransitionThumbnail.getHeight()); 8231 try { 8232 Surface surface = new Surface(mFxSession, Process.myPid(), 8233 "thumbnail anim", Display.DEFAULT_DISPLAY, 8234 dirty.width(), dirty.height(), 8235 PixelFormat.TRANSLUCENT, Surface.HIDDEN); 8236 topOpeningApp.mAppAnimator.thumbnail = surface; 8237 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " 8238 + surface + ": CREATE"); 8239 Surface drawSurface = new Surface(); 8240 drawSurface.copyFrom(surface); 8241 Canvas c = drawSurface.lockCanvas(dirty); 8242 c.drawBitmap(mNextAppTransitionThumbnail, 0, 0, null); 8243 drawSurface.unlockCanvasAndPost(c); 8244 drawSurface.release(); 8245 topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer; 8246 Animation anim = createThumbnailAnimationLocked( 8247 transit, true, true, mNextAppTransitionDelayed); 8248 topOpeningApp.mAppAnimator.thumbnailAnimation = anim; 8249 anim.restrictDuration(MAX_ANIMATION_DURATION); 8250 anim.scaleCurrentDuration(mTransitionAnimationScale); 8251 topOpeningApp.mAppAnimator.thumbnailX = mNextAppTransitionStartX; 8252 topOpeningApp.mAppAnimator.thumbnailY = mNextAppTransitionStartY; 8253 } catch (Surface.OutOfResourcesException e) { 8254 Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width() 8255 + " h=" + dirty.height(), e); 8256 topOpeningApp.mAppAnimator.clearThumbnail(); 8257 } 8258 } 8259 8260 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 8261 mNextAppTransitionPackage = null; 8262 mNextAppTransitionThumbnail = null; 8263 scheduleAnimationCallback(mNextAppTransitionCallback); 8264 mNextAppTransitionCallback = null; 8265 8266 mOpeningApps.clear(); 8267 mClosingApps.clear(); 8268 8269 // This has changed the visibility of windows, so perform 8270 // a new layout to get them all up-to-date. 8271 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT 8272 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8273 mLayoutNeeded = true; 8274 if (!moveInputMethodWindowsIfNeededLocked(true)) { 8275 assignLayersLocked(); 8276 } 8277 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8278 false /*updateInputWindows*/); 8279 mFocusMayChange = false; 8280 } 8281 8282 return changes; 8283 } 8284 8285 /** 8286 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8287 * 8288 * @return bitmap indicating if another pass through layout must be made. 8289 */ 8290 private int handleAnimatingStoppedAndTransitionLocked() { 8291 int changes = 0; 8292 8293 mAppTransitionRunning = false; 8294 // Restore window app tokens to the ActivityManager views 8295 for (int i = mAnimatingAppTokens.size() - 1; i >= 0; i--) { 8296 mAnimatingAppTokens.get(i).sendingToBottom = false; 8297 } 8298 mAnimatingAppTokens.clear(); 8299 mAnimatingAppTokens.addAll(mAppTokens); 8300 rebuildAppWindowListLocked(); 8301 8302 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8303 mInnerFields.mAdjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED; 8304 moveInputMethodWindowsIfNeededLocked(true); 8305 mInnerFields.mWallpaperMayChange = true; 8306 // Since the window list has been rebuilt, focus might 8307 // have to be recomputed since the actual order of windows 8308 // might have changed again. 8309 mFocusMayChange = true; 8310 8311 return changes; 8312 } 8313 8314 /** 8315 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8316 * 8317 * @return bitmap indicating if another pass through layout must be made. 8318 */ 8319 private int animateAwayWallpaperLocked() { 8320 int changes = 0; 8321 WindowState oldWallpaper = mWallpaperTarget; 8322 if (mLowerWallpaperTarget != null 8323 && mLowerWallpaperTarget.mAppToken != null) { 8324 if (DEBUG_WALLPAPER) Slog.v(TAG, 8325 "wallpaperForceHiding changed with lower=" 8326 + mLowerWallpaperTarget); 8327 if (DEBUG_WALLPAPER) Slog.v(TAG, 8328 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden + 8329 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested); 8330 if (mLowerWallpaperTarget.mAppToken.hidden) { 8331 // The lower target has become hidden before we 8332 // actually started the animation... let's completely 8333 // re-evaluate everything. 8334 mLowerWallpaperTarget = mUpperWallpaperTarget = null; 8335 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8336 } 8337 } 8338 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 8339 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper 8340 + " NEW: " + mWallpaperTarget 8341 + " LOWER: " + mLowerWallpaperTarget); 8342 return changes; 8343 } 8344 8345 private void updateResizingWindows(final WindowState w) { 8346 final WindowStateAnimator winAnimator = w.mWinAnimator; 8347 if (w.mHasSurface && !w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) { 8348 w.mContentInsetsChanged |= 8349 !w.mLastContentInsets.equals(w.mContentInsets); 8350 w.mVisibleInsetsChanged |= 8351 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 8352 boolean configChanged = 8353 w.mConfiguration != mCurConfiguration 8354 && (w.mConfiguration == null 8355 || mCurConfiguration.diff(w.mConfiguration) != 0); 8356 if (DEBUG_CONFIGURATION && configChanged) { 8357 Slog.v(TAG, "Win " + w + " config changed: " 8358 + mCurConfiguration); 8359 } 8360 if (localLOGV) Slog.v(TAG, "Resizing " + w 8361 + ": configChanged=" + configChanged 8362 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8363 w.mLastFrame.set(w.mFrame); 8364 if (w.mContentInsetsChanged 8365 || w.mVisibleInsetsChanged 8366 || winAnimator.mSurfaceResized 8367 || configChanged) { 8368 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8369 Slog.v(TAG, "Resize reasons: " 8370 + " contentInsetsChanged=" + w.mContentInsetsChanged 8371 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8372 + " surfaceResized=" + winAnimator.mSurfaceResized 8373 + " configChanged=" + configChanged); 8374 } 8375 8376 w.mLastContentInsets.set(w.mContentInsets); 8377 w.mLastVisibleInsets.set(w.mVisibleInsets); 8378 makeWindowFreezingScreenIfNeededLocked(w); 8379 // If the orientation is changing, then we need to 8380 // hold off on unfreezing the display until this 8381 // window has been redrawn; to do that, we need 8382 // to go through the process of getting informed 8383 // by the application when it has finished drawing. 8384 if (w.mOrientationChanging) { 8385 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8386 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8387 + w + ", surface " + winAnimator.mSurface); 8388 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8389 if (w.mAppToken != null) { 8390 w.mAppToken.allDrawn = false; 8391 } 8392 } 8393 if (!mResizingWindows.contains(w)) { 8394 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8395 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8396 + "x" + winAnimator.mSurfaceH); 8397 mResizingWindows.add(w); 8398 } 8399 } else if (w.mOrientationChanging) { 8400 if (w.isDrawnLw()) { 8401 if (DEBUG_ORIENTATION) Slog.v(TAG, 8402 "Orientation not waiting for draw in " 8403 + w + ", surface " + winAnimator.mSurface); 8404 w.mOrientationChanging = false; 8405 } 8406 } 8407 } 8408 } 8409 8410 /** 8411 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8412 * 8413 * @param w WindowState this method is applied to. 8414 * @param currentTime The time which animations use for calculating transitions. 8415 * @param innerDw Width of app window. 8416 * @param innerDh Height of app window. 8417 */ 8418 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8419 final int innerDw, final int innerDh) { 8420 final WindowManager.LayoutParams attrs = w.mAttrs; 8421 final int attrFlags = attrs.flags; 8422 final boolean canBeSeen = w.isDisplayedLw(); 8423 8424 if (w.mHasSurface) { 8425 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8426 mInnerFields.mHoldScreen = w.mSession; 8427 } 8428 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8429 && mInnerFields.mScreenBrightness < 0) { 8430 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8431 } 8432 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8433 && mInnerFields.mButtonBrightness < 0) { 8434 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8435 } 8436 if (canBeSeen 8437 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG 8438 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD 8439 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) { 8440 mInnerFields.mSyswin = true; 8441 } 8442 } 8443 8444 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8445 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8446 // This window completely covers everything behind it, 8447 // so we want to leave all of them as undimmed (for 8448 // performance reasons). 8449 mInnerFields.mObscured = true; 8450 } else if (canBeSeen && (attrFlags & FLAG_DIM_BEHIND) != 0 8451 && !(w.mAppToken != null && w.mAppToken.hiddenRequested) 8452 && !w.mExiting) { 8453 if (localLOGV) Slog.v(TAG, "Win " + w + " obscured=" + mInnerFields.mObscured); 8454 if (!mInnerFields.mDimming) { 8455 //Slog.i(TAG, "DIM BEHIND: " + w); 8456 mInnerFields.mDimming = true; 8457 final WindowStateAnimator winAnimator = w.mWinAnimator; 8458 if (!mAnimator.isDimming(winAnimator)) { 8459 final int width, height; 8460 if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { 8461 width = mDisplayInfo.logicalWidth; 8462 height = mDisplayInfo.logicalHeight; 8463 } else { 8464 width = innerDw; 8465 height = innerDh; 8466 } 8467 startDimming(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height); 8468 } 8469 } 8470 } 8471 } 8472 8473 private void updateAllDrawnLocked() { 8474 // See if any windows have been drawn, so they (and others 8475 // associated with them) can now be shown. 8476 final ArrayList<AppWindowToken> appTokens = mAnimatingAppTokens; 8477 final int NT = appTokens.size(); 8478 for (int i=0; i<NT; i++) { 8479 AppWindowToken wtoken = appTokens.get(i); 8480 if (!wtoken.allDrawn) { 8481 int numInteresting = wtoken.numInterestingWindows; 8482 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 8483 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 8484 "allDrawn: " + wtoken 8485 + " interesting=" + numInteresting 8486 + " drawn=" + wtoken.numDrawnWindows); 8487 wtoken.allDrawn = true; 8488 } 8489 } 8490 } 8491 } 8492 8493 // "Something has changed! Let's make it correct now." 8494 private final void performLayoutAndPlaceSurfacesLockedInner( 8495 boolean recoveringMemory) { 8496 if (DEBUG_WINDOW_TRACE) { 8497 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 8498 + Debug.getCallers(3)); 8499 } 8500 if (mDisplay == null) { 8501 Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay"); 8502 return; 8503 } 8504 8505 final long currentTime = SystemClock.uptimeMillis(); 8506 final int dw = mDisplayInfo.logicalWidth; 8507 final int dh = mDisplayInfo.logicalHeight; 8508 final int innerDw = mDisplayInfo.appWidth; 8509 final int innerDh = mDisplayInfo.appHeight; 8510 8511 int i; 8512 8513 if (mFocusMayChange) { 8514 mFocusMayChange = false; 8515 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 8516 false /*updateInputWindows*/); 8517 } 8518 8519 // Initialize state of exiting tokens. 8520 for (i=mExitingTokens.size()-1; i>=0; i--) { 8521 mExitingTokens.get(i).hasVisible = false; 8522 } 8523 8524 // Initialize state of exiting applications. 8525 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8526 mExitingAppTokens.get(i).hasVisible = false; 8527 } 8528 8529 mInnerFields.mHoldScreen = null; 8530 mInnerFields.mScreenBrightness = -1; 8531 mInnerFields.mButtonBrightness = -1; 8532 mTransactionSequence++; 8533 8534 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8535 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 8536 8537 Surface.openTransaction(); 8538 8539 if (mWatermark != null) { 8540 mWatermark.positionSurface(dw, dh); 8541 } 8542 if (mStrictModeFlash != null) { 8543 mStrictModeFlash.positionSurface(dw, dh); 8544 } 8545 8546 try { 8547 int repeats = 0; 8548 8549 do { 8550 repeats++; 8551 if (repeats > 6) { 8552 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 8553 mLayoutNeeded = false; 8554 break; 8555 } 8556 8557 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 8558 mPendingLayoutChanges); 8559 8560 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 8561 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8562 assignLayersLocked(); 8563 mLayoutNeeded = true; 8564 } 8565 } 8566 8567 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 8568 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 8569 if (updateOrientationFromAppTokensLocked(true)) { 8570 mLayoutNeeded = true; 8571 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8572 } 8573 } 8574 8575 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8576 mLayoutNeeded = true; 8577 } 8578 8579 // FIRST LOOP: Perform a layout, if needed. 8580 if (repeats < 4) { 8581 performLayoutLockedInner(repeats == 1, false /*updateInputWindows*/); 8582 } else { 8583 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 8584 } 8585 8586 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 8587 // it is animating. 8588 mPendingLayoutChanges = 0; 8589 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " + mLayoutRepeatCount, 8590 mPendingLayoutChanges); 8591 mPolicy.beginAnimationLw(dw, dh); 8592 for (i = mWindows.size() - 1; i >= 0; i--) { 8593 WindowState w = mWindows.get(i); 8594 if (w.mHasSurface) { 8595 mPolicy.animatingWindowLw(w, w.mAttrs); 8596 } 8597 } 8598 mPendingLayoutChanges |= mPolicy.finishAnimationLw(); 8599 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw", 8600 mPendingLayoutChanges); 8601 } while (mPendingLayoutChanges != 0); 8602 8603 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 8604 8605 mInnerFields.mObscured = false; 8606 mInnerFields.mDimming = false; 8607 mInnerFields.mSyswin = false; 8608 8609 boolean focusDisplayed = false; 8610 boolean updateAllDrawn = false; 8611 final int N = mWindows.size(); 8612 for (i=N-1; i>=0; i--) { 8613 WindowState w = mWindows.get(i); 8614 8615 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 8616 8617 // Update effect. 8618 w.mObscured = mInnerFields.mObscured; 8619 if (!mInnerFields.mObscured) { 8620 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 8621 } 8622 8623 if (obscuredChanged && (mWallpaperTarget == w) && w.isVisibleLw()) { 8624 // This is the wallpaper target and its obscured state 8625 // changed... make sure the current wallaper's visibility 8626 // has been updated accordingly. 8627 updateWallpaperVisibilityLocked(); 8628 } 8629 8630 final WindowStateAnimator winAnimator = w.mWinAnimator; 8631 8632 // If the window has moved due to its containing 8633 // content frame changing, then we'd like to animate 8634 // it. 8635 if (w.mHasSurface && w.shouldAnimateMove()) { 8636 // Frame has moved, containing content frame 8637 // has also moved, and we're not currently animating... 8638 // let's do something. 8639 Animation a = AnimationUtils.loadAnimation(mContext, 8640 com.android.internal.R.anim.window_move_from_decor); 8641 winAnimator.setAnimation(a); 8642 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 8643 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 8644 try { 8645 w.mClient.moved(w.mFrame.left, w.mFrame.top); 8646 } catch (RemoteException e) { 8647 } 8648 } 8649 8650 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 8651 w.mContentChanged = false; 8652 8653 // Moved from updateWindowsAndWallpaperLocked(). 8654 if (w.mHasSurface) { 8655 // Take care of the window being ready to display. 8656 if (winAnimator.commitFinishDrawingLocked(currentTime)) { 8657 if ((w.mAttrs.flags 8658 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 8659 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 8660 "First draw done in potential wallpaper target " + w); 8661 mInnerFields.mWallpaperMayChange = true; 8662 mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 8663 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 8664 debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true", 8665 mPendingLayoutChanges); 8666 } 8667 } 8668 } 8669 8670 winAnimator.setSurfaceBoundaries(recoveringMemory); 8671 8672 final AppWindowToken atoken = w.mAppToken; 8673 if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) { 8674 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 8675 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 8676 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 8677 } 8678 if (atoken != null 8679 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 8680 if (atoken.lastTransactionSequence != mTransactionSequence) { 8681 atoken.lastTransactionSequence = mTransactionSequence; 8682 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 8683 atoken.startingDisplayed = false; 8684 } 8685 if ((w.isOnScreen() || winAnimator.mAttrType 8686 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION) 8687 && !w.mExiting && !w.mDestroying) { 8688 if (WindowManagerService.DEBUG_VISIBILITY || 8689 WindowManagerService.DEBUG_ORIENTATION) { 8690 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 8691 + ", isAnimating=" + winAnimator.isAnimating()); 8692 if (!w.isDrawnLw()) { 8693 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface 8694 + " pv=" + w.mPolicyVisibility 8695 + " mDrawState=" + winAnimator.mDrawState 8696 + " ah=" + w.mAttachedHidden 8697 + " th=" + atoken.hiddenRequested 8698 + " a=" + winAnimator.mAnimating); 8699 } 8700 } 8701 if (w != atoken.startingWindow) { 8702 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 8703 atoken.numInterestingWindows++; 8704 if (w.isDrawnLw()) { 8705 atoken.numDrawnWindows++; 8706 if (WindowManagerService.DEBUG_VISIBILITY || 8707 WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG, 8708 "tokenMayBeDrawn: " + atoken 8709 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 8710 + " mAppFreezing=" + w.mAppFreezing); 8711 updateAllDrawn = true; 8712 } 8713 } 8714 } else if (w.isDrawnLw()) { 8715 atoken.startingDisplayed = true; 8716 } 8717 } 8718 } 8719 } 8720 8721 if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) { 8722 focusDisplayed = true; 8723 } 8724 8725 updateResizingWindows(w); 8726 } 8727 8728 if (updateAllDrawn) { 8729 updateAllDrawnLocked(); 8730 } 8731 8732 if (focusDisplayed) { 8733 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 8734 } 8735 8736 if (!mInnerFields.mDimming && mAnimator.isDimming()) { 8737 stopDimming(); 8738 } 8739 } catch (RuntimeException e) { 8740 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 8741 } finally { 8742 Surface.closeTransaction(); 8743 } 8744 8745 // If we are ready to perform an app transition, check through 8746 // all of the app tokens to be shown and see if they are ready 8747 // to go. 8748 if (mAppTransitionReady) { 8749 mPendingLayoutChanges |= handleAppTransitionReadyLocked(); 8750 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 8751 mPendingLayoutChanges); 8752 } 8753 8754 mInnerFields.mAdjResult = 0; 8755 8756 if (!mAnimator.mAnimating && mAppTransitionRunning) { 8757 // We have finished the animation of an app transition. To do 8758 // this, we have delayed a lot of operations like showing and 8759 // hiding apps, moving apps in Z-order, etc. The app token list 8760 // reflects the correct Z-order, but the window list may now 8761 // be out of sync with it. So here we will just rebuild the 8762 // entire app window list. Fun! 8763 mPendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 8764 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 8765 mPendingLayoutChanges); 8766 } 8767 8768 if (mInnerFields.mWallpaperForceHidingChanged && mPendingLayoutChanges == 0 && 8769 !mAppTransitionReady) { 8770 // At this point, there was a window with a wallpaper that 8771 // was force hiding other windows behind it, but now it 8772 // is going away. This may be simple -- just animate 8773 // away the wallpaper and its window -- or it may be 8774 // hard -- the wallpaper now needs to be shown behind 8775 // something that was hidden. 8776 mPendingLayoutChanges |= animateAwayWallpaperLocked(); 8777 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 8778 mPendingLayoutChanges); 8779 } 8780 mInnerFields.mWallpaperForceHidingChanged = false; 8781 8782 if (mInnerFields.mWallpaperMayChange) { 8783 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 8784 "Wallpaper may change! Adjusting"); 8785 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 8786 } 8787 8788 if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8789 if (DEBUG_WALLPAPER) Slog.v(TAG, 8790 "Wallpaper layer changed: assigning layers + relayout"); 8791 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8792 assignLayersLocked(); 8793 } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { 8794 if (DEBUG_WALLPAPER) Slog.v(TAG, 8795 "Wallpaper visibility changed: relayout"); 8796 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8797 } 8798 8799 if (mFocusMayChange) { 8800 mFocusMayChange = false; 8801 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8802 false /*updateInputWindows*/)) { 8803 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8804 mInnerFields.mAdjResult = 0; 8805 } 8806 } 8807 8808 if (mLayoutNeeded) { 8809 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8810 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", mPendingLayoutChanges); 8811 } 8812 8813 if (!mResizingWindows.isEmpty()) { 8814 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 8815 WindowState win = mResizingWindows.get(i); 8816 final WindowStateAnimator winAnimator = win.mWinAnimator; 8817 try { 8818 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8819 "Reporting new frame to " + win + ": " + win.mCompatFrame); 8820 int diff = 0; 8821 boolean configChanged = 8822 win.mConfiguration != mCurConfiguration 8823 && (win.mConfiguration == null 8824 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0); 8825 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 8826 && configChanged) { 8827 Slog.i(TAG, "Sending new config to window " + win + ": " 8828 + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH 8829 + " / " + mCurConfiguration + " / 0x" 8830 + Integer.toHexString(diff)); 8831 } 8832 win.mConfiguration = mCurConfiguration; 8833 if (DEBUG_ORIENTATION && 8834 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( 8835 TAG, "Resizing " + win + " WITH DRAW PENDING"); 8836 win.mClient.resized((int)winAnimator.mSurfaceW, 8837 (int)winAnimator.mSurfaceH, 8838 win.mLastContentInsets, win.mLastVisibleInsets, 8839 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING, 8840 configChanged ? win.mConfiguration : null); 8841 win.mContentInsetsChanged = false; 8842 win.mVisibleInsetsChanged = false; 8843 winAnimator.mSurfaceResized = false; 8844 } catch (RemoteException e) { 8845 win.mOrientationChanging = false; 8846 } 8847 } 8848 mResizingWindows.clear(); 8849 } 8850 8851 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 8852 "With display frozen, orientationChangeComplete=" 8853 + mInnerFields.mOrientationChangeComplete); 8854 if (mInnerFields.mOrientationChangeComplete) { 8855 if (mWindowsFreezingScreen) { 8856 mWindowsFreezingScreen = false; 8857 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8858 } 8859 stopFreezingDisplayLocked(); 8860 } 8861 8862 // Destroy the surface of any windows that are no longer visible. 8863 boolean wallpaperDestroyed = false; 8864 i = mDestroySurface.size(); 8865 if (i > 0) { 8866 do { 8867 i--; 8868 WindowState win = mDestroySurface.get(i); 8869 win.mDestroying = false; 8870 if (mInputMethodWindow == win) { 8871 mInputMethodWindow = null; 8872 } 8873 if (win == mWallpaperTarget) { 8874 wallpaperDestroyed = true; 8875 } 8876 win.mWinAnimator.destroySurfaceLocked(); 8877 } while (i > 0); 8878 mDestroySurface.clear(); 8879 } 8880 8881 // Time to remove any exiting tokens? 8882 for (i=mExitingTokens.size()-1; i>=0; i--) { 8883 WindowToken token = mExitingTokens.get(i); 8884 if (!token.hasVisible) { 8885 mExitingTokens.remove(i); 8886 if (token.windowType == TYPE_WALLPAPER) { 8887 mWallpaperTokens.remove(token); 8888 updateLayoutToAnimWallpaperTokens(); 8889 } 8890 } 8891 } 8892 8893 // Time to remove any exiting applications? 8894 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8895 AppWindowToken token = mExitingAppTokens.get(i); 8896 if (!token.hasVisible && !mClosingApps.contains(token)) { 8897 // Make sure there is no animation running on this token, 8898 // so any windows associated with it will be removed as 8899 // soon as their animations are complete 8900 token.mAppAnimator.clearAnimation(); 8901 token.mAppAnimator.animating = false; 8902 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 8903 "performLayout: App token exiting now removed" + token); 8904 mAppTokens.remove(token); 8905 mAnimatingAppTokens.remove(token); 8906 mExitingAppTokens.remove(i); 8907 } 8908 } 8909 8910 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 8911 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 8912 try { 8913 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 8914 } catch (RemoteException e) { 8915 } 8916 } 8917 mRelayoutWhileAnimating.clear(); 8918 } 8919 8920 if (wallpaperDestroyed) { 8921 mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0; 8922 } 8923 if (mPendingLayoutChanges != 0) { 8924 mLayoutNeeded = true; 8925 } 8926 8927 // Finally update all input windows now that the window changes have stabilized. 8928 mInputMonitor.updateInputWindowsLw(true /*force*/); 8929 8930 setHoldScreenLocked(mInnerFields.mHoldScreen != null); 8931 if (!mDisplayFrozen) { 8932 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 8933 mPowerManager.setScreenBrightnessOverride(-1); 8934 } else { 8935 mPowerManager.setScreenBrightnessOverride((int) 8936 (mInnerFields.mScreenBrightness * PowerManager.BRIGHTNESS_ON)); 8937 } 8938 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 8939 mPowerManager.setButtonBrightnessOverride(-1); 8940 } else { 8941 mPowerManager.setButtonBrightnessOverride((int) 8942 (mInnerFields.mButtonBrightness * PowerManager.BRIGHTNESS_ON)); 8943 } 8944 } 8945 if (mInnerFields.mHoldScreen != mHoldingScreenOn) { 8946 mHoldingScreenOn = mInnerFields.mHoldScreen; 8947 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, mInnerFields.mHoldScreen); 8948 mH.sendMessage(m); 8949 } 8950 8951 if (mTurnOnScreen) { 8952 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 8953 mPowerManager.userActivity(SystemClock.uptimeMillis(), false, 8954 PowerManager.USER_ACTIVITY_EVENT_BUTTON, true); 8955 mTurnOnScreen = false; 8956 } 8957 8958 if (mInnerFields.mUpdateRotation) { 8959 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 8960 if (updateRotationUncheckedLocked(false)) { 8961 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8962 } else { 8963 mInnerFields.mUpdateRotation = false; 8964 } 8965 } 8966 8967 if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded && 8968 !mInnerFields.mUpdateRotation) { 8969 checkDrawnWindowsLocked(); 8970 } 8971 8972 // Check to see if we are now in a state where the screen should 8973 // be enabled, because the window obscured flags have changed. 8974 enableScreenIfNeededLocked(); 8975 8976 updateLayoutToAnimationLocked(); 8977 8978 if (DEBUG_WINDOW_TRACE) { 8979 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mPendingLayoutChanges=" 8980 + Integer.toHexString(mPendingLayoutChanges) + " mLayoutNeeded=" + mLayoutNeeded 8981 + " animating=" + mAnimator.mAnimating); 8982 } 8983 } 8984 8985 void checkDrawnWindowsLocked() { 8986 if (mWaitingForDrawn.size() > 0) { 8987 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 8988 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 8989 WindowState win = pair.first; 8990 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 8991 // + win.mRemoved + " visible=" + win.isVisibleLw() 8992 // + " shown=" + win.mSurfaceShown); 8993 if (win.mRemoved || !win.isVisibleLw()) { 8994 // Window has been removed or made invisible; no draw 8995 // will now happen, so stop waiting. 8996 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 8997 try { 8998 pair.second.sendResult(null); 8999 } catch (RemoteException e) { 9000 } 9001 mWaitingForDrawn.remove(pair); 9002 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9003 } else if (win.mWinAnimator.mSurfaceShown) { 9004 // Window is now drawn (and shown). 9005 try { 9006 pair.second.sendResult(null); 9007 } catch (RemoteException e) { 9008 } 9009 mWaitingForDrawn.remove(pair); 9010 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9011 } 9012 } 9013 } 9014 } 9015 9016 public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 9017 synchronized (mWindowMap) { 9018 WindowState win = windowForClientLocked(null, token, true); 9019 if (win != null) { 9020 Pair<WindowState, IRemoteCallback> pair = 9021 new Pair<WindowState, IRemoteCallback>(win, callback); 9022 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9023 mH.sendMessageDelayed(m, 2000); 9024 mWaitingForDrawn.add(pair); 9025 checkDrawnWindowsLocked(); 9026 } 9027 } 9028 } 9029 9030 /** 9031 * Must be called with the main window manager lock held. 9032 */ 9033 void setHoldScreenLocked(boolean holding) { 9034 boolean state = mHoldingScreenWakeLock.isHeld(); 9035 if (holding != state) { 9036 if (holding) { 9037 mPolicy.screenOnStartedLw(); 9038 mHoldingScreenWakeLock.acquire(); 9039 } else { 9040 mPolicy.screenOnStoppedLw(); 9041 mHoldingScreenWakeLock.release(); 9042 } 9043 } 9044 } 9045 9046 void requestTraversalLocked() { 9047 if (!mTraversalScheduled) { 9048 mTraversalScheduled = true; 9049 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9050 } 9051 } 9052 9053 /** Note that Locked in this case is on mLayoutToAnim */ 9054 void scheduleAnimationLocked() { 9055 final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim; 9056 if (!layoutToAnim.mAnimationScheduled) { 9057 layoutToAnim.mAnimationScheduled = true; 9058 mChoreographer.postCallback( 9059 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9060 } 9061 } 9062 9063 void updateLayoutToAnimationLocked() { 9064 final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim; 9065 synchronized (layoutToAnim) { 9066 // Copy local params to transfer params. 9067 ArrayList<WindowStateAnimator> winAnimators = layoutToAnim.mWinAnimators; 9068 winAnimators.clear(); 9069 int N = mWindows.size(); 9070 for (int i = 0; i < N; i++) { 9071 final WindowStateAnimator winAnimator = mWindows.get(i).mWinAnimator; 9072 if (winAnimator.mSurface != null) { 9073 winAnimators.add(winAnimator); 9074 } 9075 } 9076 9077 layoutToAnim.mWallpaperTarget = mWallpaperTarget; 9078 layoutToAnim.mLowerWallpaperTarget = mLowerWallpaperTarget; 9079 layoutToAnim.mUpperWallpaperTarget = mUpperWallpaperTarget; 9080 9081 final ArrayList<AppWindowAnimParams> paramList = layoutToAnim.mAppWindowAnimParams; 9082 paramList.clear(); 9083 N = mAnimatingAppTokens.size(); 9084 for (int i = 0; i < N; i++) { 9085 paramList.add(new AppWindowAnimParams(mAnimatingAppTokens.get(i).mAppAnimator)); 9086 } 9087 9088 layoutToAnim.mParamsModified = true; 9089 scheduleAnimationLocked(); 9090 } 9091 } 9092 9093 void updateLayoutToAnimWallpaperTokens() { 9094 synchronized(mLayoutToAnim) { 9095 mLayoutToAnim.mWallpaperTokens = new ArrayList<WindowToken>(mWallpaperTokens); 9096 mLayoutToAnim.mChanges |= LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED; 9097 } 9098 } 9099 9100 void setAnimDimParams(DimAnimator.Parameters params) { 9101 synchronized (mLayoutToAnim) { 9102 mLayoutToAnim.mDimParams = params; 9103 scheduleAnimationLocked(); 9104 } 9105 } 9106 9107 void startDimming(final WindowStateAnimator winAnimator, final float target, 9108 final int width, final int height) { 9109 setAnimDimParams(new DimAnimator.Parameters(winAnimator, width, height, target)); 9110 } 9111 9112 void stopDimming() { 9113 setAnimDimParams(null); 9114 } 9115 9116 private boolean copyAnimToLayoutParamsLocked() { 9117 boolean doRequest = false; 9118 final WindowAnimator.AnimatorToLayoutParams animToLayout = mAnimator.mAnimToLayout; 9119 synchronized (animToLayout) { 9120 animToLayout.mUpdateQueued = false; 9121 final int bulkUpdateParams = animToLayout.mBulkUpdateParams; 9122 // TODO(cmautner): As the number of bits grows, use masks of bit groups to 9123 // eliminate unnecessary tests. 9124 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9125 mInnerFields.mUpdateRotation = true; 9126 doRequest = true; 9127 } 9128 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9129 mInnerFields.mWallpaperMayChange = true; 9130 doRequest = true; 9131 } 9132 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9133 mInnerFields.mWallpaperForceHidingChanged = true; 9134 doRequest = true; 9135 } 9136 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9137 mInnerFields.mOrientationChangeComplete = false; 9138 } else { 9139 mInnerFields.mOrientationChangeComplete = true; 9140 if (mWindowsFreezingScreen) { 9141 doRequest = true; 9142 } 9143 } 9144 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9145 mTurnOnScreen = true; 9146 } 9147 9148 mPendingLayoutChanges |= animToLayout.mPendingLayoutChanges; 9149 if (mPendingLayoutChanges != 0) { 9150 doRequest = true; 9151 } 9152 9153 mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper; 9154 } 9155 return doRequest; 9156 } 9157 9158 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9159 boolean secure) { 9160 final Surface surface = winAnimator.mSurface; 9161 boolean leakedSurface = false; 9162 boolean killedApps = false; 9163 9164 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9165 winAnimator.mSession.mPid, operation); 9166 9167 if (mForceRemoves == null) { 9168 mForceRemoves = new ArrayList<WindowState>(); 9169 } 9170 9171 long callingIdentity = Binder.clearCallingIdentity(); 9172 try { 9173 // There was some problem... first, do a sanity check of the 9174 // window list to make sure we haven't left any dangling surfaces 9175 // around. 9176 int N = mWindows.size(); 9177 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9178 for (int i=0; i<N; i++) { 9179 WindowState ws = mWindows.get(i); 9180 WindowStateAnimator wsa = ws.mWinAnimator; 9181 if (wsa.mSurface != null) { 9182 if (!mSessions.contains(wsa.mSession)) { 9183 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9184 + ws + " surface=" + wsa.mSurface 9185 + " token=" + ws.mToken 9186 + " pid=" + ws.mSession.mPid 9187 + " uid=" + ws.mSession.mUid); 9188 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9189 wsa.mSurface.destroy(); 9190 wsa.mSurfaceShown = false; 9191 wsa.mSurface = null; 9192 ws.mHasSurface = false; 9193 mForceRemoves.add(ws); 9194 i--; 9195 N--; 9196 leakedSurface = true; 9197 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9198 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9199 + ws + " surface=" + wsa.mSurface 9200 + " token=" + ws.mAppToken); 9201 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9202 wsa.mSurface.destroy(); 9203 wsa.mSurfaceShown = false; 9204 wsa.mSurface = null; 9205 ws.mHasSurface = false; 9206 leakedSurface = true; 9207 } 9208 } 9209 } 9210 9211 if (!leakedSurface) { 9212 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9213 SparseIntArray pidCandidates = new SparseIntArray(); 9214 for (int i=0; i<N; i++) { 9215 WindowStateAnimator wsa = mWindows.get(i).mWinAnimator; 9216 if (wsa.mSurface != null) { 9217 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9218 } 9219 } 9220 if (pidCandidates.size() > 0) { 9221 int[] pids = new int[pidCandidates.size()]; 9222 for (int i=0; i<pids.length; i++) { 9223 pids[i] = pidCandidates.keyAt(i); 9224 } 9225 try { 9226 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9227 killedApps = true; 9228 } 9229 } catch (RemoteException e) { 9230 } 9231 } 9232 } 9233 9234 if (leakedSurface || killedApps) { 9235 // We managed to reclaim some memory, so get rid of the trouble 9236 // surface and ask the app to request another one. 9237 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9238 if (surface != null) { 9239 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9240 "RECOVER DESTROY", null); 9241 surface.destroy(); 9242 winAnimator.mSurfaceShown = false; 9243 winAnimator.mSurface = null; 9244 winAnimator.mWin.mHasSurface = false; 9245 } 9246 9247 try { 9248 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9249 } catch (RemoteException e) { 9250 } 9251 } 9252 } finally { 9253 Binder.restoreCallingIdentity(callingIdentity); 9254 } 9255 9256 return leakedSurface || killedApps; 9257 } 9258 9259 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9260 WindowState newFocus = computeFocusedWindowLocked(); 9261 if (mCurrentFocus != newFocus) { 9262 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9263 // This check makes sure that we don't already have the focus 9264 // change message pending. 9265 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9266 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9267 if (localLOGV) Slog.v( 9268 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 9269 final WindowState oldFocus = mCurrentFocus; 9270 mCurrentFocus = newFocus; 9271 mAnimator.setCurrentFocus(newFocus); 9272 mLosingFocus.remove(newFocus); 9273 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9274 9275 final WindowState imWindow = mInputMethodWindow; 9276 if (newFocus != imWindow && oldFocus != imWindow) { 9277 if (moveInputMethodWindowsIfNeededLocked( 9278 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 9279 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 9280 mLayoutNeeded = true; 9281 } 9282 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9283 performLayoutLockedInner(true /*initial*/, updateInputWindows); 9284 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9285 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9286 // Client will do the layout, but we need to assign layers 9287 // for handleNewWindowLocked() below. 9288 assignLayersLocked(); 9289 } 9290 } 9291 9292 if ((focusChanged&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9293 // The change in focus caused us to need to do a layout. Okay. 9294 mLayoutNeeded = true; 9295 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9296 performLayoutLockedInner(true /*initial*/, updateInputWindows); 9297 } 9298 } 9299 9300 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9301 // If we defer assigning layers, then the caller is responsible for 9302 // doing this part. 9303 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9304 } 9305 9306 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9307 return true; 9308 } 9309 return false; 9310 } 9311 9312 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9313 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9314 } 9315 9316 private WindowState computeFocusedWindowLocked() { 9317 WindowState result = null; 9318 WindowState win; 9319 9320 if (mAnimator.mUniverseBackground != null 9321 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9322 return mAnimator.mUniverseBackground.mWin; 9323 } 9324 9325 int nextAppIndex = mAppTokens.size()-1; 9326 WindowToken nextApp = nextAppIndex >= 0 9327 ? mAppTokens.get(nextAppIndex) : null; 9328 9329 for (int i = mWindows.size() - 1; i >= 0; i--) { 9330 win = mWindows.get(i); 9331 9332 if (localLOGV || DEBUG_FOCUS) Slog.v( 9333 TAG, "Looking for focus: " + i 9334 + " = " + win 9335 + ", flags=" + win.mAttrs.flags 9336 + ", canReceive=" + win.canReceiveKeys()); 9337 9338 AppWindowToken thisApp = win.mAppToken; 9339 9340 // If this window's application has been removed, just skip it. 9341 if (thisApp != null && (thisApp.removed || thisApp.sendingToBottom)) { 9342 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping app because " + (thisApp.removed 9343 ? "removed" : "sendingToBottom")); 9344 continue; 9345 } 9346 9347 // If there is a focused app, don't allow focus to go to any 9348 // windows below it. If this is an application window, step 9349 // through the app tokens until we find its app. 9350 if (thisApp != null && nextApp != null && thisApp != nextApp 9351 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 9352 int origAppIndex = nextAppIndex; 9353 while (nextAppIndex > 0) { 9354 if (nextApp == mFocusedApp) { 9355 // Whoops, we are below the focused app... no focus 9356 // for you! 9357 if (localLOGV || DEBUG_FOCUS) Slog.v( 9358 TAG, "Reached focused app: " + mFocusedApp); 9359 return null; 9360 } 9361 nextAppIndex--; 9362 nextApp = mAppTokens.get(nextAppIndex); 9363 if (nextApp == thisApp) { 9364 break; 9365 } 9366 } 9367 if (thisApp != nextApp) { 9368 // Uh oh, the app token doesn't exist! This shouldn't 9369 // happen, but if it does we can get totally hosed... 9370 // so restart at the original app. 9371 nextAppIndex = origAppIndex; 9372 nextApp = mAppTokens.get(nextAppIndex); 9373 } 9374 } 9375 9376 // Dispatch to this window if it is wants key events. 9377 if (win.canReceiveKeys()) { 9378 if (DEBUG_FOCUS) Slog.v( 9379 TAG, "Found focus @ " + i + " = " + win); 9380 result = win; 9381 break; 9382 } 9383 } 9384 9385 return result; 9386 } 9387 9388 private void startFreezingDisplayLocked(boolean inTransaction) { 9389 if (mDisplayFrozen) { 9390 return; 9391 } 9392 9393 if (mDisplay == null || !mPolicy.isScreenOnFully()) { 9394 // No need to freeze the screen before the system is ready or if 9395 // the screen is off. 9396 return; 9397 } 9398 9399 mScreenFrozenLock.acquire(); 9400 9401 mDisplayFrozen = true; 9402 9403 mInputMonitor.freezeInputDispatchingLw(); 9404 9405 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 9406 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 9407 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 9408 mNextAppTransitionPackage = null; 9409 mNextAppTransitionThumbnail = null; 9410 mAppTransitionReady = true; 9411 } 9412 9413 if (PROFILE_ORIENTATION) { 9414 File file = new File("/data/system/frozen"); 9415 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9416 } 9417 9418 if (CUSTOM_SCREEN_ROTATION) { 9419 if (mAnimator.mScreenRotationAnimation != null) { 9420 mAnimator.mScreenRotationAnimation.kill(); 9421 mAnimator.mScreenRotationAnimation = null; 9422 } 9423 9424 mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, 9425 mFxSession, inTransaction, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, 9426 mDisplay.getRotation()); 9427 } 9428 } 9429 9430 private void stopFreezingDisplayLocked() { 9431 if (!mDisplayFrozen) { 9432 return; 9433 } 9434 9435 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) { 9436 if (DEBUG_ORIENTATION) Slog.d(TAG, 9437 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 9438 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 9439 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen); 9440 return; 9441 } 9442 9443 mDisplayFrozen = false; 9444 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9445 if (PROFILE_ORIENTATION) { 9446 Debug.stopMethodTracing(); 9447 } 9448 9449 boolean updateRotation = false; 9450 9451 if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null 9452 && mAnimator.mScreenRotationAnimation.hasScreenshot()) { 9453 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 9454 if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 9455 mTransitionAnimationScale, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) { 9456 updateLayoutToAnimationLocked(); 9457 } else { 9458 mAnimator.mScreenRotationAnimation.kill(); 9459 mAnimator.mScreenRotationAnimation = null; 9460 updateRotation = true; 9461 } 9462 } else { 9463 if (mAnimator.mScreenRotationAnimation != null) { 9464 mAnimator.mScreenRotationAnimation.kill(); 9465 mAnimator.mScreenRotationAnimation = null; 9466 } 9467 updateRotation = true; 9468 } 9469 9470 mInputMonitor.thawInputDispatchingLw(); 9471 9472 boolean configChanged; 9473 9474 // While the display is frozen we don't re-compute the orientation 9475 // to avoid inconsistent states. However, something interesting 9476 // could have actually changed during that time so re-evaluate it 9477 // now to catch that. 9478 configChanged = updateOrientationFromAppTokensLocked(false); 9479 9480 // A little kludge: a lot could have happened while the 9481 // display was frozen, so now that we are coming back we 9482 // do a gc so that any remote references the system 9483 // processes holds on others can be released if they are 9484 // no longer needed. 9485 mH.removeMessages(H.FORCE_GC); 9486 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 9487 2000); 9488 9489 mScreenFrozenLock.release(); 9490 9491 if (updateRotation) { 9492 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9493 configChanged |= updateRotationUncheckedLocked(false); 9494 } 9495 9496 if (configChanged) { 9497 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9498 } 9499 } 9500 9501 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 9502 DisplayMetrics dm) { 9503 if (index < tokens.length) { 9504 String str = tokens[index]; 9505 if (str != null && str.length() > 0) { 9506 try { 9507 int val = Integer.parseInt(str); 9508 return val; 9509 } catch (Exception e) { 9510 } 9511 } 9512 } 9513 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 9514 return defDps; 9515 } 9516 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 9517 return val; 9518 } 9519 9520 void createWatermark() { 9521 if (mWatermark != null) { 9522 return; 9523 } 9524 9525 File file = new File("/system/etc/setup.conf"); 9526 FileInputStream in = null; 9527 try { 9528 in = new FileInputStream(file); 9529 DataInputStream ind = new DataInputStream(in); 9530 String line = ind.readLine(); 9531 if (line != null) { 9532 String[] toks = line.split("%"); 9533 if (toks != null && toks.length > 0) { 9534 mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks); 9535 } 9536 } 9537 } catch (FileNotFoundException e) { 9538 } catch (IOException e) { 9539 } finally { 9540 if (in != null) { 9541 try { 9542 in.close(); 9543 } catch (IOException e) { 9544 } 9545 } 9546 } 9547 } 9548 9549 @Override 9550 public void statusBarVisibilityChanged(int visibility) { 9551 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 9552 != PackageManager.PERMISSION_GRANTED) { 9553 throw new SecurityException("Caller does not hold permission " 9554 + android.Manifest.permission.STATUS_BAR); 9555 } 9556 9557 synchronized (mWindowMap) { 9558 mLastStatusBarVisibility = visibility; 9559 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 9560 updateStatusBarVisibilityLocked(visibility); 9561 } 9562 } 9563 9564 void updateStatusBarVisibilityLocked(int visibility) { 9565 mInputManager.setSystemUiVisibility(visibility); 9566 final int N = mWindows.size(); 9567 for (int i = 0; i < N; i++) { 9568 WindowState ws = mWindows.get(i); 9569 try { 9570 int curValue = ws.mSystemUiVisibility; 9571 int diff = curValue ^ visibility; 9572 // We are only interested in differences of one of the 9573 // clearable flags... 9574 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 9575 // ...if it has actually been cleared. 9576 diff &= ~visibility; 9577 int newValue = (curValue&~diff) | (visibility&diff); 9578 if (newValue != curValue) { 9579 ws.mSeq++; 9580 ws.mSystemUiVisibility = newValue; 9581 } 9582 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 9583 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 9584 visibility, newValue, diff); 9585 } 9586 } catch (RemoteException e) { 9587 // so sorry 9588 } 9589 } 9590 } 9591 9592 @Override 9593 public void reevaluateStatusBarVisibility() { 9594 synchronized (mWindowMap) { 9595 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 9596 updateStatusBarVisibilityLocked(visibility); 9597 performLayoutAndPlaceSurfacesLocked(); 9598 } 9599 } 9600 9601 @Override 9602 public FakeWindow addFakeWindow(Looper looper, 9603 InputEventReceiver.Factory inputEventReceiverFactory, 9604 String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys, 9605 boolean hasFocus, boolean touchFullscreen) { 9606 synchronized (mWindowMap) { 9607 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 9608 name, windowType, 9609 layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 9610 int i=0; 9611 while (i<mFakeWindows.size()) { 9612 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 9613 break; 9614 } 9615 } 9616 mFakeWindows.add(i, fw); 9617 mInputMonitor.updateInputWindowsLw(true); 9618 return fw; 9619 } 9620 } 9621 9622 boolean removeFakeWindowLocked(FakeWindow window) { 9623 synchronized (mWindowMap) { 9624 if (mFakeWindows.remove(window)) { 9625 mInputMonitor.updateInputWindowsLw(true); 9626 return true; 9627 } 9628 return false; 9629 } 9630 } 9631 9632 // It is assumed that this method is called only by InputMethodManagerService. 9633 public void saveLastInputMethodWindowForTransition() { 9634 synchronized (mWindowMap) { 9635 if (mInputMethodWindow != null) { 9636 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 9637 } 9638 } 9639 } 9640 9641 @Override 9642 public boolean hasNavigationBar() { 9643 return mPolicy.hasNavigationBar(); 9644 } 9645 9646 public void lockNow() { 9647 mPolicy.lockNow(); 9648 } 9649 9650 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 9651 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 9652 mPolicy.dump(" ", pw, args); 9653 } 9654 9655 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 9656 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 9657 if (mTokenMap.size() > 0) { 9658 pw.println(" All tokens:"); 9659 Iterator<WindowToken> it = mTokenMap.values().iterator(); 9660 while (it.hasNext()) { 9661 WindowToken token = it.next(); 9662 pw.print(" Token "); pw.print(token.token); 9663 if (dumpAll) { 9664 pw.println(':'); 9665 token.dump(pw, " "); 9666 } else { 9667 pw.println(); 9668 } 9669 } 9670 } 9671 if (mWallpaperTokens.size() > 0) { 9672 pw.println(); 9673 pw.println(" Wallpaper tokens:"); 9674 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 9675 WindowToken token = mWallpaperTokens.get(i); 9676 pw.print(" Wallpaper #"); pw.print(i); 9677 pw.print(' '); pw.print(token); 9678 if (dumpAll) { 9679 pw.println(':'); 9680 token.dump(pw, " "); 9681 } else { 9682 pw.println(); 9683 } 9684 } 9685 } 9686 if (mAppTokens.size() > 0) { 9687 pw.println(); 9688 pw.println(" Application tokens in Z order:"); 9689 for (int i=mAppTokens.size()-1; i>=0; i--) { 9690 pw.print(" App #"); pw.print(i); pw.println(": "); 9691 mAppTokens.get(i).dump(pw, " "); 9692 } 9693 } 9694 if (mFinishedStarting.size() > 0) { 9695 pw.println(); 9696 pw.println(" Finishing start of application tokens:"); 9697 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 9698 WindowToken token = mFinishedStarting.get(i); 9699 pw.print(" Finished Starting #"); pw.print(i); 9700 pw.print(' '); pw.print(token); 9701 if (dumpAll) { 9702 pw.println(':'); 9703 token.dump(pw, " "); 9704 } else { 9705 pw.println(); 9706 } 9707 } 9708 } 9709 if (mExitingTokens.size() > 0) { 9710 pw.println(); 9711 pw.println(" Exiting tokens:"); 9712 for (int i=mExitingTokens.size()-1; i>=0; i--) { 9713 WindowToken token = mExitingTokens.get(i); 9714 pw.print(" Exiting #"); pw.print(i); 9715 pw.print(' '); pw.print(token); 9716 if (dumpAll) { 9717 pw.println(':'); 9718 token.dump(pw, " "); 9719 } else { 9720 pw.println(); 9721 } 9722 } 9723 } 9724 if (mExitingAppTokens.size() > 0) { 9725 pw.println(); 9726 pw.println(" Exiting application tokens:"); 9727 for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 9728 WindowToken token = mExitingAppTokens.get(i); 9729 pw.print(" Exiting App #"); pw.print(i); 9730 pw.print(' '); pw.print(token); 9731 if (dumpAll) { 9732 pw.println(':'); 9733 token.dump(pw, " "); 9734 } else { 9735 pw.println(); 9736 } 9737 } 9738 } 9739 if (mAppTransitionRunning && mAnimatingAppTokens.size() > 0) { 9740 pw.println(); 9741 pw.println(" Application tokens during animation:"); 9742 for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) { 9743 WindowToken token = mAnimatingAppTokens.get(i); 9744 pw.print(" App moving to bottom #"); pw.print(i); 9745 pw.print(' '); pw.print(token); 9746 if (dumpAll) { 9747 pw.println(':'); 9748 token.dump(pw, " "); 9749 } else { 9750 pw.println(); 9751 } 9752 } 9753 } 9754 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 9755 pw.println(); 9756 if (mOpeningApps.size() > 0) { 9757 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 9758 } 9759 if (mClosingApps.size() > 0) { 9760 pw.print(" mClosingApps="); pw.println(mClosingApps); 9761 } 9762 } 9763 } 9764 9765 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 9766 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 9767 if (mSessions.size() > 0) { 9768 Iterator<Session> it = mSessions.iterator(); 9769 while (it.hasNext()) { 9770 Session s = it.next(); 9771 pw.print(" Session "); pw.print(s); pw.println(':'); 9772 s.dump(pw, " "); 9773 } 9774 } 9775 } 9776 9777 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 9778 ArrayList<WindowState> windows) { 9779 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 9780 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 9781 } 9782 9783 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 9784 ArrayList<WindowState> windows) { 9785 for (int i=mWindows.size()-1; i>=0; i--) { 9786 WindowState w = mWindows.get(i); 9787 if (windows == null || windows.contains(w)) { 9788 pw.print(" Window #"); pw.print(i); pw.print(' '); 9789 pw.print(w); pw.println(":"); 9790 w.dump(pw, " ", dumpAll || windows != null); 9791 } 9792 } 9793 if (mInputMethodDialogs.size() > 0) { 9794 pw.println(); 9795 pw.println(" Input method dialogs:"); 9796 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 9797 WindowState w = mInputMethodDialogs.get(i); 9798 if (windows == null || windows.contains(w)) { 9799 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 9800 } 9801 } 9802 } 9803 if (mPendingRemove.size() > 0) { 9804 pw.println(); 9805 pw.println(" Remove pending for:"); 9806 for (int i=mPendingRemove.size()-1; i>=0; i--) { 9807 WindowState w = mPendingRemove.get(i); 9808 if (windows == null || windows.contains(w)) { 9809 pw.print(" Remove #"); pw.print(i); pw.print(' '); 9810 pw.print(w); 9811 if (dumpAll) { 9812 pw.println(":"); 9813 w.dump(pw, " ", true); 9814 } else { 9815 pw.println(); 9816 } 9817 } 9818 } 9819 } 9820 if (mForceRemoves != null && mForceRemoves.size() > 0) { 9821 pw.println(); 9822 pw.println(" Windows force removing:"); 9823 for (int i=mForceRemoves.size()-1; i>=0; i--) { 9824 WindowState w = mForceRemoves.get(i); 9825 pw.print(" Removing #"); pw.print(i); pw.print(' '); 9826 pw.print(w); 9827 if (dumpAll) { 9828 pw.println(":"); 9829 w.dump(pw, " ", true); 9830 } else { 9831 pw.println(); 9832 } 9833 } 9834 } 9835 if (mDestroySurface.size() > 0) { 9836 pw.println(); 9837 pw.println(" Windows waiting to destroy their surface:"); 9838 for (int i=mDestroySurface.size()-1; i>=0; i--) { 9839 WindowState w = mDestroySurface.get(i); 9840 if (windows == null || windows.contains(w)) { 9841 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 9842 pw.print(w); 9843 if (dumpAll) { 9844 pw.println(":"); 9845 w.dump(pw, " ", true); 9846 } else { 9847 pw.println(); 9848 } 9849 } 9850 } 9851 } 9852 if (mLosingFocus.size() > 0) { 9853 pw.println(); 9854 pw.println(" Windows losing focus:"); 9855 for (int i=mLosingFocus.size()-1; i>=0; i--) { 9856 WindowState w = mLosingFocus.get(i); 9857 if (windows == null || windows.contains(w)) { 9858 pw.print(" Losing #"); pw.print(i); pw.print(' '); 9859 pw.print(w); 9860 if (dumpAll) { 9861 pw.println(":"); 9862 w.dump(pw, " ", true); 9863 } else { 9864 pw.println(); 9865 } 9866 } 9867 } 9868 } 9869 if (mResizingWindows.size() > 0) { 9870 pw.println(); 9871 pw.println(" Windows waiting to resize:"); 9872 for (int i=mResizingWindows.size()-1; i>=0; i--) { 9873 WindowState w = mResizingWindows.get(i); 9874 if (windows == null || windows.contains(w)) { 9875 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 9876 pw.print(w); 9877 if (dumpAll) { 9878 pw.println(":"); 9879 w.dump(pw, " ", true); 9880 } else { 9881 pw.println(); 9882 } 9883 } 9884 } 9885 } 9886 if (mWaitingForDrawn.size() > 0) { 9887 pw.println(); 9888 pw.println(" Clients waiting for these windows to be drawn:"); 9889 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 9890 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 9891 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 9892 pw.print(": "); pw.println(pair.second); 9893 } 9894 } 9895 pw.println(); 9896 if (mDisplay != null) { 9897 pw.print(" Display: init="); pw.print(mInitialDisplayWidth); pw.print("x"); 9898 pw.print(mInitialDisplayHeight); 9899 if (mInitialDisplayWidth != mBaseDisplayWidth 9900 || mInitialDisplayHeight != mBaseDisplayHeight) { 9901 pw.print(" base="); 9902 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 9903 } 9904 if (mInitialDisplayWidth != mDisplayInfo.logicalWidth 9905 || mInitialDisplayHeight != mDisplayInfo.logicalHeight) { 9906 pw.print(" init="); pw.print(mInitialDisplayWidth); 9907 pw.print("x"); pw.print(mInitialDisplayHeight); 9908 } 9909 pw.print(" cur="); 9910 pw.print(mDisplayInfo.logicalWidth); 9911 pw.print("x"); pw.print(mDisplayInfo.logicalHeight); 9912 pw.print(" app="); 9913 pw.print(mDisplayInfo.appWidth); 9914 pw.print("x"); pw.print(mDisplayInfo.appHeight); 9915 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); 9916 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); 9917 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); 9918 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); 9919 } else { 9920 pw.println(" NO DISPLAY"); 9921 } 9922 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 9923 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 9924 if (mLastFocus != mCurrentFocus) { 9925 pw.print(" mLastFocus="); pw.println(mLastFocus); 9926 } 9927 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 9928 if (mInputMethodTarget != null) { 9929 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 9930 } 9931 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 9932 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 9933 if (dumpAll) { 9934 pw.print(" mSystemDecorRect="); pw.print(mSystemDecorRect.toShortString()); 9935 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 9936 pw.print(" mScreenRecr="); pw.println(mScreenRect.toShortString()); 9937 if (mLastStatusBarVisibility != 0) { 9938 pw.print(" mLastStatusBarVisibility=0x"); 9939 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 9940 } 9941 if (mInputMethodWindow != null) { 9942 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 9943 } 9944 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 9945 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) { 9946 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 9947 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 9948 } 9949 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 9950 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 9951 if (mInputMethodAnimLayerAdjustment != 0 || 9952 mWallpaperAnimLayerAdjustment != 0) { 9953 pw.print(" mInputMethodAnimLayerAdjustment="); 9954 pw.print(mInputMethodAnimLayerAdjustment); 9955 pw.print(" mWallpaperAnimLayerAdjustment="); 9956 pw.println(mWallpaperAnimLayerAdjustment); 9957 } 9958 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 9959 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 9960 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); 9961 pw.print("mTransactionSequence="); pw.println(mTransactionSequence); 9962 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 9963 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); 9964 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); 9965 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); 9966 pw.print(" mRotation="); pw.print(mRotation); 9967 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 9968 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 9969 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 9970 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 9971 if (mAnimator.mScreenRotationAnimation != null) { 9972 pw.println(" mScreenRotationAnimation:"); 9973 mAnimator.mScreenRotationAnimation.printTo(" ", pw); 9974 } 9975 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 9976 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 9977 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 9978 pw.print(" mTraversalScheduled="); pw.print(mTraversalScheduled); 9979 pw.print(" mNextAppTransition=0x"); 9980 pw.print(Integer.toHexString(mNextAppTransition)); 9981 pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady); 9982 pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning); 9983 pw.print(" mAppTransitionTimeout="); pw.println(mAppTransitionTimeout); 9984 if (mNextAppTransitionType != ActivityOptions.ANIM_NONE) { 9985 pw.print(" mNextAppTransitionType="); pw.println(mNextAppTransitionType); 9986 } 9987 switch (mNextAppTransitionType) { 9988 case ActivityOptions.ANIM_CUSTOM: 9989 pw.print(" mNextAppTransitionPackage="); 9990 pw.println(mNextAppTransitionPackage); 9991 pw.print(" mNextAppTransitionEnter=0x"); 9992 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 9993 pw.print(" mNextAppTransitionExit=0x"); 9994 pw.println(Integer.toHexString(mNextAppTransitionExit)); 9995 break; 9996 case ActivityOptions.ANIM_SCALE_UP: 9997 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); 9998 pw.print(" mNextAppTransitionStartY="); 9999 pw.println(mNextAppTransitionStartY); 10000 pw.print(" mNextAppTransitionStartWidth="); 10001 pw.print(mNextAppTransitionStartWidth); 10002 pw.print(" mNextAppTransitionStartHeight="); 10003 pw.println(mNextAppTransitionStartHeight); 10004 break; 10005 case ActivityOptions.ANIM_THUMBNAIL: 10006 case ActivityOptions.ANIM_THUMBNAIL_DELAYED: 10007 pw.print(" mNextAppTransitionThumbnail="); 10008 pw.print(mNextAppTransitionThumbnail); 10009 pw.print(" mNextAppTransitionStartX="); 10010 pw.print(mNextAppTransitionStartX); 10011 pw.print(" mNextAppTransitionStartY="); 10012 pw.println(mNextAppTransitionStartY); 10013 pw.print(" mNextAppTransitionDelayed="); pw.println(mNextAppTransitionDelayed); 10014 break; 10015 } 10016 if (mNextAppTransitionCallback != null) { 10017 pw.print(" mNextAppTransitionCallback="); 10018 pw.println(mNextAppTransitionCallback); 10019 } 10020 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10021 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10022 pw.println(" Window Animator:"); 10023 mAnimator.dump(pw, " ", dumpAll); 10024 } 10025 } 10026 10027 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10028 int opti, boolean dumpAll) { 10029 ArrayList<WindowState> windows = new ArrayList<WindowState>(); 10030 if ("visible".equals(name)) { 10031 synchronized(mWindowMap) { 10032 for (int i=mWindows.size()-1; i>=0; i--) { 10033 WindowState w = mWindows.get(i); 10034 if (w.mWinAnimator.mSurfaceShown) { 10035 windows.add(w); 10036 } 10037 } 10038 } 10039 } else { 10040 int objectId = 0; 10041 // See if this is an object ID. 10042 try { 10043 objectId = Integer.parseInt(name, 16); 10044 name = null; 10045 } catch (RuntimeException e) { 10046 } 10047 synchronized(mWindowMap) { 10048 for (int i=mWindows.size()-1; i>=0; i--) { 10049 WindowState w = mWindows.get(i); 10050 if (name != null) { 10051 if (w.mAttrs.getTitle().toString().contains(name)) { 10052 windows.add(w); 10053 } 10054 } else if (System.identityHashCode(w) == objectId) { 10055 windows.add(w); 10056 } 10057 } 10058 } 10059 } 10060 10061 if (windows.size() <= 0) { 10062 return false; 10063 } 10064 10065 synchronized(mWindowMap) { 10066 dumpWindowsLocked(pw, dumpAll, windows); 10067 } 10068 return true; 10069 } 10070 10071 void dumpLastANRLocked(PrintWriter pw) { 10072 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10073 if (mLastANRState == null) { 10074 pw.println(" <no ANR has occurred since boot>"); 10075 } else { 10076 pw.println(mLastANRState); 10077 } 10078 } 10079 10080 /** 10081 * Saves information about the state of the window manager at 10082 * the time an ANR occurred before anything else in the system changes 10083 * in response. 10084 * 10085 * @param appWindowToken The application that ANR'd, may be null. 10086 * @param windowState The window that ANR'd, may be null. 10087 */ 10088 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) { 10089 StringWriter sw = new StringWriter(); 10090 PrintWriter pw = new PrintWriter(sw); 10091 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10092 if (appWindowToken != null) { 10093 pw.println(" Application at fault: " + appWindowToken.stringName); 10094 } 10095 if (windowState != null) { 10096 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10097 } 10098 pw.println(); 10099 dumpWindowsNoHeaderLocked(pw, true, null); 10100 pw.close(); 10101 mLastANRState = sw.toString(); 10102 } 10103 10104 @Override 10105 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10106 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10107 != PackageManager.PERMISSION_GRANTED) { 10108 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10109 + Binder.getCallingPid() 10110 + ", uid=" + Binder.getCallingUid()); 10111 return; 10112 } 10113 10114 boolean dumpAll = false; 10115 10116 int opti = 0; 10117 while (opti < args.length) { 10118 String opt = args[opti]; 10119 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10120 break; 10121 } 10122 opti++; 10123 if ("-a".equals(opt)) { 10124 dumpAll = true; 10125 } else if ("-h".equals(opt)) { 10126 pw.println("Window manager dump options:"); 10127 pw.println(" [-a] [-h] [cmd] ..."); 10128 pw.println(" cmd may be one of:"); 10129 pw.println(" l[astanr]: last ANR information"); 10130 pw.println(" p[policy]: policy state"); 10131 pw.println(" s[essions]: active sessions"); 10132 pw.println(" t[okens]: token list"); 10133 pw.println(" w[indows]: window list"); 10134 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10135 pw.println(" be a partial substring in a window name, a"); 10136 pw.println(" Window hex object identifier, or"); 10137 pw.println(" \"all\" for all windows, or"); 10138 pw.println(" \"visible\" for the visible windows."); 10139 pw.println(" -a: include all available server state."); 10140 return; 10141 } else { 10142 pw.println("Unknown argument: " + opt + "; use -h for help"); 10143 } 10144 } 10145 10146 // Is the caller requesting to dump a particular piece of data? 10147 if (opti < args.length) { 10148 String cmd = args[opti]; 10149 opti++; 10150 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10151 synchronized(mWindowMap) { 10152 dumpLastANRLocked(pw); 10153 } 10154 return; 10155 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10156 synchronized(mWindowMap) { 10157 dumpPolicyLocked(pw, args, true); 10158 } 10159 return; 10160 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10161 synchronized(mWindowMap) { 10162 dumpSessionsLocked(pw, true); 10163 } 10164 return; 10165 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10166 synchronized(mWindowMap) { 10167 dumpTokensLocked(pw, true); 10168 } 10169 return; 10170 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10171 synchronized(mWindowMap) { 10172 dumpWindowsLocked(pw, true, null); 10173 } 10174 return; 10175 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10176 synchronized(mWindowMap) { 10177 dumpWindowsLocked(pw, true, null); 10178 } 10179 return; 10180 } else { 10181 // Dumping a single name? 10182 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10183 pw.println("Bad window command, or no windows match: " + cmd); 10184 pw.println("Use -h for help."); 10185 } 10186 return; 10187 } 10188 } 10189 10190 synchronized(mWindowMap) { 10191 pw.println(); 10192 if (dumpAll) { 10193 pw.println("-------------------------------------------------------------------------------"); 10194 } 10195 dumpLastANRLocked(pw); 10196 pw.println(); 10197 if (dumpAll) { 10198 pw.println("-------------------------------------------------------------------------------"); 10199 } 10200 dumpPolicyLocked(pw, args, dumpAll); 10201 pw.println(); 10202 if (dumpAll) { 10203 pw.println("-------------------------------------------------------------------------------"); 10204 } 10205 dumpSessionsLocked(pw, dumpAll); 10206 pw.println(); 10207 if (dumpAll) { 10208 pw.println("-------------------------------------------------------------------------------"); 10209 } 10210 dumpTokensLocked(pw, dumpAll); 10211 pw.println(); 10212 if (dumpAll) { 10213 pw.println("-------------------------------------------------------------------------------"); 10214 } 10215 dumpWindowsLocked(pw, dumpAll, null); 10216 } 10217 } 10218 10219 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10220 public void monitor() { 10221 synchronized (mWindowMap) { } 10222 synchronized (mKeyguardTokenWatcher) { } 10223 } 10224 10225 public interface OnHardKeyboardStatusChangeListener { 10226 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10227 } 10228 10229 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10230 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10231 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10232 Integer.toHexString(pendingLayoutChanges)); 10233 } 10234 } 10235} 10236