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