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