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