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