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