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