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