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