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