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