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