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