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