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