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