WindowManagerService.java revision 738cfc91053fc888397ec2d139e0798f8c95b3ca
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 if (mWindowMap.containsKey(client.asBinder())) { 2096 Slog.w(TAG, "Window " + client + " is already added"); 2097 return WindowManagerGlobal.ADD_DUPLICATE_ADD; 2098 } 2099 2100 if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { 2101 attachedWindow = windowForClientLocked(null, attrs.token, false); 2102 if (attachedWindow == null) { 2103 Slog.w(TAG, "Attempted to add window with token that is not a window: " 2104 + attrs.token + ". Aborting."); 2105 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2106 } 2107 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW 2108 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { 2109 Slog.w(TAG, "Attempted to add window with token that is a sub-window: " 2110 + attrs.token + ". Aborting."); 2111 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; 2112 } 2113 } 2114 2115 boolean addToken = false; 2116 WindowToken token = mTokenMap.get(attrs.token); 2117 if (token == null) { 2118 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2119 Slog.w(TAG, "Attempted to add application window with unknown token " 2120 + attrs.token + ". Aborting."); 2121 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2122 } 2123 if (type == TYPE_INPUT_METHOD) { 2124 Slog.w(TAG, "Attempted to add input method window with unknown token " 2125 + attrs.token + ". Aborting."); 2126 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2127 } 2128 if (type == TYPE_WALLPAPER) { 2129 Slog.w(TAG, "Attempted to add wallpaper window with unknown token " 2130 + attrs.token + ". Aborting."); 2131 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2132 } 2133 if (type == TYPE_DREAM) { 2134 Slog.w(TAG, "Attempted to add Dream window with unknown token " 2135 + attrs.token + ". Aborting."); 2136 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2137 } 2138 token = new WindowToken(this, attrs.token, -1, false); 2139 addToken = true; 2140 } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2141 AppWindowToken atoken = token.appWindowToken; 2142 if (atoken == null) { 2143 Slog.w(TAG, "Attempted to add window with non-application token " 2144 + token + ". Aborting."); 2145 return WindowManagerGlobal.ADD_NOT_APP_TOKEN; 2146 } else if (atoken.removed) { 2147 Slog.w(TAG, "Attempted to add window with exiting application token " 2148 + token + ". Aborting."); 2149 return WindowManagerGlobal.ADD_APP_EXITING; 2150 } 2151 if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { 2152 // No need for this guy! 2153 if (localLOGV) Slog.v( 2154 TAG, "**** NO NEED TO START: " + attrs.getTitle()); 2155 return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; 2156 } 2157 } else if (type == TYPE_INPUT_METHOD) { 2158 if (token.windowType != TYPE_INPUT_METHOD) { 2159 Slog.w(TAG, "Attempted to add input method window with bad token " 2160 + attrs.token + ". Aborting."); 2161 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2162 } 2163 } else if (type == TYPE_WALLPAPER) { 2164 if (token.windowType != TYPE_WALLPAPER) { 2165 Slog.w(TAG, "Attempted to add wallpaper window with bad token " 2166 + attrs.token + ". Aborting."); 2167 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2168 } 2169 } else if (type == TYPE_DREAM) { 2170 if (token.windowType != TYPE_DREAM) { 2171 Slog.w(TAG, "Attempted to add Dream window with bad token " 2172 + attrs.token + ". Aborting."); 2173 return WindowManagerGlobal.ADD_BAD_APP_TOKEN; 2174 } 2175 } 2176 2177 final DisplayContent displayContent = getDisplayContentLocked(displayId); 2178 win = new WindowState(this, session, client, token, 2179 attachedWindow, seq, attrs, viewVisibility, displayContent); 2180 if (win.mDeathRecipient == null) { 2181 // Client has apparently died, so there is no reason to 2182 // continue. 2183 Slog.w(TAG, "Adding window client " + client.asBinder() 2184 + " that is dead, aborting."); 2185 return WindowManagerGlobal.ADD_APP_EXITING; 2186 } 2187 2188 mPolicy.adjustWindowParamsLw(win.mAttrs); 2189 win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); 2190 2191 res = mPolicy.prepareAddWindowLw(win, attrs); 2192 if (res != WindowManagerGlobal.ADD_OKAY) { 2193 return res; 2194 } 2195 2196 if (outInputChannel != null && (attrs.inputFeatures 2197 & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { 2198 String name = win.makeInputChannelName(); 2199 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); 2200 win.setInputChannel(inputChannels[0]); 2201 inputChannels[1].transferTo(outInputChannel); 2202 2203 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); 2204 } 2205 2206 // From now on, no exceptions or errors allowed! 2207 2208 res = WindowManagerGlobal.ADD_OKAY; 2209 2210 origId = Binder.clearCallingIdentity(); 2211 2212 if (addToken) { 2213 mTokenMap.put(attrs.token, token); 2214 } 2215 win.attach(); 2216 mWindowMap.put(client.asBinder(), win); 2217 2218 if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) { 2219 token.appWindowToken.startingWindow = win; 2220 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken 2221 + " startingWindow=" + win); 2222 } 2223 2224 boolean imMayMove = true; 2225 2226 if (type == TYPE_INPUT_METHOD) { 2227 win.mGivenInsetsPending = true; 2228 mInputMethodWindow = win; 2229 addInputMethodWindowToListLocked(win); 2230 imMayMove = false; 2231 } else if (type == TYPE_INPUT_METHOD_DIALOG) { 2232 mInputMethodDialogs.add(win); 2233 addWindowToListInOrderLocked(win, true); 2234 adjustInputMethodDialogsLocked(); 2235 imMayMove = false; 2236 } else { 2237 addWindowToListInOrderLocked(win, true); 2238 if (type == TYPE_WALLPAPER) { 2239 mLastWallpaperTimeoutTime = 0; 2240 adjustWallpaperWindowsLocked(); 2241 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2242 adjustWallpaperWindowsLocked(); 2243 } 2244 } 2245 2246 win.mWinAnimator.mEnterAnimationPending = true; 2247 2248 if (displayContent.isDefaultDisplay) { 2249 mPolicy.getContentInsetHintLw(attrs, outContentInsets); 2250 } else { 2251 outContentInsets.setEmpty(); 2252 } 2253 2254 if (mInTouchMode) { 2255 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; 2256 } 2257 if (win.mAppToken == null || !win.mAppToken.clientHidden) { 2258 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; 2259 } 2260 2261 mInputMonitor.setUpdateInputWindowsNeededLw(); 2262 2263 boolean focusChanged = false; 2264 if (win.canReceiveKeys()) { 2265 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, 2266 false /*updateInputWindows*/); 2267 if (focusChanged) { 2268 imMayMove = false; 2269 } 2270 } 2271 2272 if (imMayMove) { 2273 moveInputMethodWindowsIfNeededLocked(false); 2274 } 2275 2276 assignLayersLocked(displayContent.getWindowList()); 2277 // Don't do layout here, the window must call 2278 // relayout to be displayed, so we'll do it there. 2279 2280 //dump(); 2281 2282 if (focusChanged) { 2283 finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/); 2284 } 2285 mInputMonitor.updateInputWindowsLw(false /*force*/); 2286 2287 if (localLOGV) Slog.v( 2288 TAG, "New client " + client.asBinder() 2289 + ": window=" + win); 2290 2291 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { 2292 reportNewConfig = true; 2293 } 2294 } 2295 2296 if (reportNewConfig) { 2297 sendNewConfiguration(); 2298 } 2299 2300 Binder.restoreCallingIdentity(origId); 2301 2302 return res; 2303 } 2304 2305 public void removeWindow(Session session, IWindow client) { 2306 synchronized(mWindowMap) { 2307 WindowState win = windowForClientLocked(session, client, false); 2308 if (win == null) { 2309 return; 2310 } 2311 removeWindowLocked(session, win); 2312 } 2313 } 2314 2315 public void removeWindowLocked(Session session, WindowState win) { 2316 2317 if (localLOGV || DEBUG_FOCUS) Slog.v( 2318 TAG, "Remove " + win + " client=" 2319 + Integer.toHexString(System.identityHashCode( 2320 win.mClient.asBinder())) 2321 + ", surface=" + win.mWinAnimator.mSurface); 2322 2323 final long origId = Binder.clearCallingIdentity(); 2324 2325 win.disposeInputChannel(); 2326 2327 if (DEBUG_APP_TRANSITIONS) Slog.v( 2328 TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurface 2329 + " mExiting=" + win.mExiting 2330 + " isAnimating=" + win.mWinAnimator.isAnimating() 2331 + " app-animation=" 2332 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null) 2333 + " inPendingTransaction=" 2334 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) 2335 + " mDisplayFrozen=" + mDisplayFrozen); 2336 // Visibility of the removed window. Will be used later to update orientation later on. 2337 boolean wasVisible = false; 2338 // First, see if we need to run an animation. If we do, we have 2339 // to hold off on removing the window until the animation is done. 2340 // If the display is frozen, just remove immediately, since the 2341 // animation wouldn't be seen. 2342 if (win.mHasSurface && okToDisplay()) { 2343 // If we are not currently running the exit animation, we 2344 // need to see about starting one. 2345 wasVisible = win.isWinVisibleLw(); 2346 if (wasVisible) { 2347 2348 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2349 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2350 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2351 } 2352 // Try starting an animation. 2353 if (win.mWinAnimator.applyAnimationLocked(transit, false)) { 2354 win.mExiting = true; 2355 } 2356 scheduleNotifyWindowTranstionIfNeededLocked(win, transit); 2357 } 2358 if (win.mExiting || win.mWinAnimator.isAnimating()) { 2359 // The exit animation is running... wait for it! 2360 //Slog.i(TAG, "*** Running exit animation..."); 2361 win.mExiting = true; 2362 win.mRemoveOnExit = true; 2363 win.mDisplayContent.layoutNeeded = true; 2364 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 2365 false /*updateInputWindows*/); 2366 performLayoutAndPlaceSurfacesLocked(); 2367 mInputMonitor.updateInputWindowsLw(false /*force*/); 2368 if (win.mAppToken != null) { 2369 win.mAppToken.updateReportedVisibilityLocked(); 2370 } 2371 //dump(); 2372 Binder.restoreCallingIdentity(origId); 2373 return; 2374 } 2375 } 2376 2377 removeWindowInnerLocked(session, win); 2378 // Removing a visible window will effect the computed orientation 2379 // So just update orientation if needed. 2380 if (wasVisible && computeForcedAppOrientationLocked() 2381 != mForcedAppOrientation 2382 && updateOrientationFromAppTokensLocked(false)) { 2383 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 2384 } 2385 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 2386 Binder.restoreCallingIdentity(origId); 2387 } 2388 2389 private void removeWindowInnerLocked(Session session, WindowState win) { 2390 if (win.mRemoved) { 2391 // Nothing to do. 2392 return; 2393 } 2394 2395 for (int i=win.mChildWindows.size()-1; i>=0; i--) { 2396 WindowState cwin = win.mChildWindows.get(i); 2397 Slog.w(TAG, "Force-removing child win " + cwin + " from container " 2398 + win); 2399 removeWindowInnerLocked(cwin.mSession, cwin); 2400 } 2401 2402 win.mRemoved = true; 2403 2404 if (mInputMethodTarget == win) { 2405 moveInputMethodWindowsIfNeededLocked(false); 2406 } 2407 2408 if (false) { 2409 RuntimeException e = new RuntimeException("here"); 2410 e.fillInStackTrace(); 2411 Slog.w(TAG, "Removing window " + win, e); 2412 } 2413 2414 mPolicy.removeWindowLw(win); 2415 win.removeLocked(); 2416 2417 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); 2418 mWindowMap.remove(win.mClient.asBinder()); 2419 2420 final WindowList windows = win.getWindowList(); 2421 windows.remove(win); 2422 mPendingRemove.remove(win); 2423 mResizingWindows.remove(win); 2424 mWindowsChanged = true; 2425 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win); 2426 2427 if (mInputMethodWindow == win) { 2428 mInputMethodWindow = null; 2429 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { 2430 mInputMethodDialogs.remove(win); 2431 } 2432 2433 final WindowToken token = win.mToken; 2434 final AppWindowToken atoken = win.mAppToken; 2435 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token); 2436 token.windows.remove(win); 2437 if (atoken != null) { 2438 atoken.allAppWindows.remove(win); 2439 } 2440 if (localLOGV) Slog.v( 2441 TAG, "**** Removing window " + win + ": count=" 2442 + token.windows.size()); 2443 if (token.windows.size() == 0) { 2444 if (!token.explicit) { 2445 mTokenMap.remove(token.token); 2446 } else if (atoken != null) { 2447 atoken.firstWindowDrawn = false; 2448 } 2449 } 2450 2451 if (atoken != null) { 2452 if (atoken.startingWindow == win) { 2453 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win); 2454 atoken.startingWindow = null; 2455 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) { 2456 // If this is the last window and we had requested a starting 2457 // transition window, well there is no point now. 2458 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow"); 2459 atoken.startingData = null; 2460 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) { 2461 // If this is the last window except for a starting transition 2462 // window, we need to get rid of the starting transition. 2463 if (DEBUG_STARTING_WINDOW) { 2464 Slog.v(TAG, "Schedule remove starting " + token 2465 + ": no more real windows"); 2466 } 2467 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken); 2468 mH.sendMessage(m); 2469 } 2470 } 2471 2472 if (win.mAttrs.type == TYPE_WALLPAPER) { 2473 mLastWallpaperTimeoutTime = 0; 2474 adjustWallpaperWindowsLocked(); 2475 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 2476 adjustWallpaperWindowsLocked(); 2477 } 2478 2479 if (!mInLayout) { 2480 assignLayersLocked(windows); 2481 win.mDisplayContent.layoutNeeded = true; 2482 performLayoutAndPlaceSurfacesLocked(); 2483 if (win.mAppToken != null) { 2484 win.mAppToken.updateReportedVisibilityLocked(); 2485 } 2486 } 2487 2488 mInputMonitor.updateInputWindowsLw(true /*force*/); 2489 } 2490 2491 static void logSurface(WindowState w, String msg, RuntimeException where) { 2492 String str = " SURFACE " + msg + ": " + w; 2493 if (where != null) { 2494 Slog.i(TAG, str, where); 2495 } else { 2496 Slog.i(TAG, str); 2497 } 2498 } 2499 2500 static void logSurface(Surface s, String title, String msg, RuntimeException where) { 2501 String str = " SURFACE " + s + ": " + msg + " / " + title; 2502 if (where != null) { 2503 Slog.i(TAG, str, where); 2504 } else { 2505 Slog.i(TAG, str); 2506 } 2507 } 2508 2509 // TODO(cmautner): Move to WindowStateAnimator. 2510 void setTransparentRegionHint(final WindowStateAnimator winAnimator, final Region region) { 2511 mH.sendMessage(mH.obtainMessage(H.SET_TRANSPARENT_REGION, 2512 new Pair<WindowStateAnimator, Region>(winAnimator, region))); 2513 } 2514 2515 void setTransparentRegionWindow(Session session, IWindow client, Region region) { 2516 long origId = Binder.clearCallingIdentity(); 2517 try { 2518 synchronized (mWindowMap) { 2519 WindowState w = windowForClientLocked(session, client, false); 2520 if ((w != null) && w.mHasSurface) { 2521 setTransparentRegionHint(w.mWinAnimator, region); 2522 } 2523 } 2524 } finally { 2525 Binder.restoreCallingIdentity(origId); 2526 } 2527 } 2528 2529 void setInsetsWindow(Session session, IWindow client, 2530 int touchableInsets, Rect contentInsets, 2531 Rect visibleInsets, Region touchableRegion) { 2532 long origId = Binder.clearCallingIdentity(); 2533 try { 2534 synchronized (mWindowMap) { 2535 WindowState w = windowForClientLocked(session, client, false); 2536 if (w != null) { 2537 w.mGivenInsetsPending = false; 2538 w.mGivenContentInsets.set(contentInsets); 2539 w.mGivenVisibleInsets.set(visibleInsets); 2540 w.mGivenTouchableRegion.set(touchableRegion); 2541 w.mTouchableInsets = touchableInsets; 2542 if (w.mGlobalScale != 1) { 2543 w.mGivenContentInsets.scale(w.mGlobalScale); 2544 w.mGivenVisibleInsets.scale(w.mGlobalScale); 2545 w.mGivenTouchableRegion.scale(w.mGlobalScale); 2546 } 2547 w.mDisplayContent.layoutNeeded = true; 2548 performLayoutAndPlaceSurfacesLocked(); 2549 } 2550 } 2551 } finally { 2552 Binder.restoreCallingIdentity(origId); 2553 } 2554 } 2555 2556 public void getWindowDisplayFrame(Session session, IWindow client, 2557 Rect outDisplayFrame) { 2558 synchronized(mWindowMap) { 2559 WindowState win = windowForClientLocked(session, client, false); 2560 if (win == null) { 2561 outDisplayFrame.setEmpty(); 2562 return; 2563 } 2564 outDisplayFrame.set(win.mDisplayFrame); 2565 } 2566 } 2567 2568 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y, 2569 float xStep, float yStep) { 2570 if (window.mWallpaperX != x || window.mWallpaperY != y) { 2571 window.mWallpaperX = x; 2572 window.mWallpaperY = y; 2573 window.mWallpaperXStep = xStep; 2574 window.mWallpaperYStep = yStep; 2575 updateWallpaperOffsetLocked(window, true); 2576 } 2577 } 2578 2579 void wallpaperCommandComplete(IBinder window, Bundle result) { 2580 synchronized (mWindowMap) { 2581 if (mWaitingOnWallpaper != null && 2582 mWaitingOnWallpaper.mClient.asBinder() == window) { 2583 mWaitingOnWallpaper = null; 2584 mWindowMap.notifyAll(); 2585 } 2586 } 2587 } 2588 2589 public Bundle sendWindowWallpaperCommandLocked(WindowState window, 2590 String action, int x, int y, int z, Bundle extras, boolean sync) { 2591 if (window == mWallpaperTarget || window == mLowerWallpaperTarget 2592 || window == mUpperWallpaperTarget) { 2593 boolean doWait = sync; 2594 int curTokenIndex = mWallpaperTokens.size(); 2595 while (curTokenIndex > 0) { 2596 curTokenIndex--; 2597 WindowToken token = mWallpaperTokens.get(curTokenIndex); 2598 int curWallpaperIndex = token.windows.size(); 2599 while (curWallpaperIndex > 0) { 2600 curWallpaperIndex--; 2601 WindowState wallpaper = token.windows.get(curWallpaperIndex); 2602 try { 2603 wallpaper.mClient.dispatchWallpaperCommand(action, 2604 x, y, z, extras, sync); 2605 // We only want to be synchronous with one wallpaper. 2606 sync = false; 2607 } catch (RemoteException e) { 2608 } 2609 } 2610 } 2611 2612 if (doWait) { 2613 // XXX Need to wait for result. 2614 } 2615 } 2616 2617 return null; 2618 } 2619 2620 public void setUniverseTransformLocked(WindowState window, float alpha, 2621 float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) { 2622 Transformation transform = window.mWinAnimator.mUniverseTransform; 2623 transform.setAlpha(alpha); 2624 Matrix matrix = transform.getMatrix(); 2625 matrix.getValues(mTmpFloats); 2626 mTmpFloats[Matrix.MTRANS_X] = offx; 2627 mTmpFloats[Matrix.MTRANS_Y] = offy; 2628 mTmpFloats[Matrix.MSCALE_X] = dsdx; 2629 mTmpFloats[Matrix.MSKEW_Y] = dtdx; 2630 mTmpFloats[Matrix.MSKEW_X] = dsdy; 2631 mTmpFloats[Matrix.MSCALE_Y] = dtdy; 2632 matrix.setValues(mTmpFloats); 2633 final DisplayInfo displayInfo = window.mDisplayContent.getDisplayInfo(); 2634 final RectF dispRect = new RectF(0, 0, 2635 displayInfo.logicalWidth, displayInfo.logicalHeight); 2636 matrix.mapRect(dispRect); 2637 window.mGivenTouchableRegion.set(0, 0, 2638 displayInfo.logicalWidth, displayInfo.logicalHeight); 2639 window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, 2640 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); 2641 window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; 2642 window.mDisplayContent.layoutNeeded = true; 2643 performLayoutAndPlaceSurfacesLocked(); 2644 } 2645 2646 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) { 2647 synchronized (mWindowMap) { 2648 WindowState window = mWindowMap.get(token); 2649 if (window != null) { 2650 scheduleNotifyRectangleOnScreenRequestedIfNeededLocked(window, rectangle, 2651 immediate); 2652 } 2653 } 2654 } 2655 2656 private void scheduleNotifyRectangleOnScreenRequestedIfNeededLocked(WindowState window, 2657 Rect rectangle, boolean immediate) { 2658 DisplayContent displayContent = window.mDisplayContent; 2659 if (displayContent.mDisplayContentChangeListeners != null 2660 && displayContent.mDisplayContentChangeListeners.getRegisteredCallbackCount() > 0) { 2661 mH.obtainMessage(H.NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED, displayContent.getDisplayId(), 2662 immediate? 1 : 0, new Rect(rectangle)).sendToTarget(); 2663 } 2664 } 2665 2666 private void handleNotifyRectangleOnScreenRequested(int displayId, Rect rectangle, 2667 boolean immediate) { 2668 RemoteCallbackList<IDisplayContentChangeListener> callbacks = null; 2669 synchronized (mWindowMap) { 2670 DisplayContent displayContent = getDisplayContentLocked(displayId); 2671 if (displayContent == null) { 2672 return; 2673 } 2674 callbacks = displayContent.mDisplayContentChangeListeners; 2675 if (callbacks == null) { 2676 return; 2677 } 2678 } 2679 final int callbackCount = callbacks.beginBroadcast(); 2680 try { 2681 for (int i = 0; i < callbackCount; i++) { 2682 try { 2683 callbacks.getBroadcastItem(i).onRectangleOnScreenRequested(displayId, 2684 rectangle, immediate); 2685 } catch (RemoteException re) { 2686 /* ignore */ 2687 } 2688 } 2689 } finally { 2690 callbacks.finishBroadcast(); 2691 } 2692 } 2693 2694 public int relayoutWindow(Session session, IWindow client, int seq, 2695 WindowManager.LayoutParams attrs, int requestedWidth, 2696 int requestedHeight, int viewVisibility, int flags, 2697 Rect outFrame, Rect outContentInsets, 2698 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { 2699 boolean toBeDisplayed = false; 2700 boolean inTouchMode; 2701 boolean configChanged; 2702 boolean surfaceChanged = false; 2703 boolean animating; 2704 2705 // if they don't have this permission, mask out the status bar bits 2706 int systemUiVisibility = 0; 2707 if (attrs != null) { 2708 systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility); 2709 if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) { 2710 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 2711 != PackageManager.PERMISSION_GRANTED) { 2712 systemUiVisibility &= ~StatusBarManager.DISABLE_MASK; 2713 } 2714 } 2715 } 2716 long origId = Binder.clearCallingIdentity(); 2717 2718 synchronized(mWindowMap) { 2719 // TODO(cmautner): synchronize on mAnimator or win.mWinAnimator. 2720 WindowState win = windowForClientLocked(session, client, false); 2721 if (win == null) { 2722 return 0; 2723 } 2724 WindowStateAnimator winAnimator = win.mWinAnimator; 2725 if (win.mRequestedWidth != requestedWidth 2726 || win.mRequestedHeight != requestedHeight) { 2727 win.mLayoutNeeded = true; 2728 win.mRequestedWidth = requestedWidth; 2729 win.mRequestedHeight = requestedHeight; 2730 } 2731 if (attrs != null && seq == win.mSeq) { 2732 win.mSystemUiVisibility = systemUiVisibility; 2733 } 2734 2735 if (attrs != null) { 2736 mPolicy.adjustWindowParamsLw(attrs); 2737 } 2738 2739 winAnimator.mSurfaceDestroyDeferred = 2740 (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0; 2741 2742 int attrChanges = 0; 2743 int flagChanges = 0; 2744 if (attrs != null) { 2745 if (win.mAttrs.type != attrs.type) { 2746 throw new IllegalArgumentException( 2747 "Window type can not be changed after the window is added."); 2748 } 2749 flagChanges = win.mAttrs.flags ^= attrs.flags; 2750 attrChanges = win.mAttrs.copyFrom(attrs); 2751 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED 2752 | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) { 2753 win.mLayoutNeeded = true; 2754 } 2755 } 2756 2757 if (DEBUG_LAYOUT 2758 // TODO: Remove once b/7094175 is fixed 2759 || ((String)win.mAttrs.getTitle()).contains("Keyguard") 2760 ) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility 2761 + " " + requestedWidth + "x" + requestedHeight + " " + win.mAttrs); 2762 2763 win.mEnforceSizeCompat = (win.mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0; 2764 2765 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { 2766 winAnimator.mAlpha = attrs.alpha; 2767 } 2768 2769 final boolean scaledWindow = 2770 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0); 2771 2772 if (scaledWindow) { 2773 // requested{Width|Height} Surface's physical size 2774 // attrs.{width|height} Size on screen 2775 win.mHScale = (attrs.width != requestedWidth) ? 2776 (attrs.width / (float)requestedWidth) : 1.0f; 2777 win.mVScale = (attrs.height != requestedHeight) ? 2778 (attrs.height / (float)requestedHeight) : 1.0f; 2779 } else { 2780 win.mHScale = win.mVScale = 1; 2781 } 2782 2783 boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0; 2784 2785 final boolean isDefaultDisplay = win.isDefaultDisplay(); 2786 boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility 2787 || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0) 2788 || (!win.mRelayoutCalled)); 2789 2790 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility 2791 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0; 2792 wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0; 2793 2794 win.mRelayoutCalled = true; 2795 final int oldVisibility = win.mViewVisibility; 2796 win.mViewVisibility = viewVisibility; 2797 if (DEBUG_SCREEN_ON) { 2798 RuntimeException stack = new RuntimeException(); 2799 stack.fillInStackTrace(); 2800 Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility 2801 + " newVis=" + viewVisibility, stack); 2802 } 2803 if (viewVisibility == View.VISIBLE && 2804 (win.mAppToken == null || !win.mAppToken.clientHidden)) { 2805 toBeDisplayed = !win.isVisibleLw(); 2806 if (win.mExiting) { 2807 winAnimator.cancelExitAnimationForNextAnimationLocked(); 2808 win.mExiting = false; 2809 } 2810 if (win.mDestroying) { 2811 win.mDestroying = false; 2812 mDestroySurface.remove(win); 2813 } 2814 if (oldVisibility == View.GONE) { 2815 winAnimator.mEnterAnimationPending = true; 2816 } 2817 if (toBeDisplayed) { 2818 if (win.isDrawnLw() && okToDisplay()) { 2819 winAnimator.applyEnterAnimationLocked(); 2820 } 2821 if ((win.mAttrs.flags 2822 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) { 2823 if (DEBUG_VISIBILITY) Slog.v(TAG, 2824 "Relayout window turning screen on: " + win); 2825 win.mTurnOnScreen = true; 2826 } 2827 if (win.isConfigChanged()) { 2828 if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win 2829 + " visible with new config: " + win.mConfiguration); 2830 outConfig.setTo(mCurConfiguration); 2831 } 2832 } 2833 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) { 2834 // To change the format, we need to re-build the surface. 2835 winAnimator.destroySurfaceLocked(); 2836 toBeDisplayed = true; 2837 surfaceChanged = true; 2838 } 2839 try { 2840 if (!win.mHasSurface) { 2841 surfaceChanged = true; 2842 } 2843 Surface surface = winAnimator.createSurfaceLocked(); 2844 if (surface != null) { 2845 outSurface.copyFrom(surface); 2846 if (SHOW_TRANSACTIONS) Slog.i(TAG, 2847 " OUT SURFACE " + outSurface + ": copied"); 2848 } else { 2849 // For some reason there isn't a surface. Clear the 2850 // caller's object so they see the same state. 2851 outSurface.release(); 2852 } 2853 } catch (Exception e) { 2854 mInputMonitor.updateInputWindowsLw(true /*force*/); 2855 2856 Slog.w(TAG, "Exception thrown when creating surface for client " 2857 + client + " (" + win.mAttrs.getTitle() + ")", 2858 e); 2859 Binder.restoreCallingIdentity(origId); 2860 return 0; 2861 } 2862 if (toBeDisplayed) { 2863 focusMayChange = isDefaultDisplay; 2864 } 2865 if (win.mAttrs.type == TYPE_INPUT_METHOD 2866 && mInputMethodWindow == null) { 2867 mInputMethodWindow = win; 2868 imMayMove = true; 2869 } 2870 if (win.mAttrs.type == TYPE_BASE_APPLICATION 2871 && win.mAppToken != null 2872 && win.mAppToken.startingWindow != null) { 2873 // Special handling of starting window over the base 2874 // window of the app: propagate lock screen flags to it, 2875 // to provide the correct semantics while starting. 2876 final int mask = 2877 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 2878 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 2879 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 2880 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs; 2881 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask); 2882 } 2883 } else { 2884 winAnimator.mEnterAnimationPending = false; 2885 if (winAnimator.mSurface != null) { 2886 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win 2887 + ": mExiting=" + win.mExiting); 2888 // If we are not currently running the exit animation, we 2889 // need to see about starting one. 2890 if (!win.mExiting) { 2891 surfaceChanged = true; 2892 // Try starting an animation; if there isn't one, we 2893 // can destroy the surface right away. 2894 int transit = WindowManagerPolicy.TRANSIT_EXIT; 2895 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2896 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; 2897 } 2898 if (win.isWinVisibleLw() && 2899 winAnimator.applyAnimationLocked(transit, false)) { 2900 focusMayChange = isDefaultDisplay; 2901 win.mExiting = true; 2902 } else if (win.mWinAnimator.isAnimating()) { 2903 // Currently in a hide animation... turn this into 2904 // an exit. 2905 win.mExiting = true; 2906 } else if (win == mWallpaperTarget) { 2907 // If the wallpaper is currently behind this 2908 // window, we need to change both of them inside 2909 // of a transaction to avoid artifacts. 2910 win.mExiting = true; 2911 win.mWinAnimator.mAnimating = true; 2912 } else { 2913 if (mInputMethodWindow == win) { 2914 mInputMethodWindow = null; 2915 } 2916 winAnimator.destroySurfaceLocked(); 2917 } 2918 scheduleNotifyWindowTranstionIfNeededLocked(win, transit); 2919 } 2920 } 2921 2922 outSurface.release(); 2923 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win); 2924 } 2925 2926 if (focusMayChange) { 2927 //System.out.println("Focus may change: " + win.mAttrs.getTitle()); 2928 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 2929 false /*updateInputWindows*/)) { 2930 imMayMove = false; 2931 } 2932 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus); 2933 } 2934 2935 // updateFocusedWindowLocked() already assigned layers so we only need to 2936 // reassign them at this point if the IM window state gets shuffled 2937 boolean assignLayers = false; 2938 2939 if (imMayMove) { 2940 if (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed) { 2941 // Little hack here -- we -should- be able to rely on the 2942 // function to return true if the IME has moved and needs 2943 // its layer recomputed. However, if the IME was hidden 2944 // and isn't actually moved in the list, its layer may be 2945 // out of data so we make sure to recompute it. 2946 assignLayers = true; 2947 } 2948 } 2949 if (wallpaperMayMove) { 2950 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 2951 assignLayers = true; 2952 } 2953 } 2954 2955 win.mDisplayContent.layoutNeeded = true; 2956 win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; 2957 if (assignLayers) { 2958 assignLayersLocked(win.getWindowList()); 2959 } 2960 configChanged = updateOrientationFromAppTokensLocked(false); 2961 performLayoutAndPlaceSurfacesLocked(); 2962 if (toBeDisplayed && win.mIsWallpaper) { 2963 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 2964 updateWallpaperOffsetLocked(win, 2965 displayInfo.appWidth, displayInfo.appHeight, false); 2966 } 2967 if (win.mAppToken != null) { 2968 win.mAppToken.updateReportedVisibilityLocked(); 2969 } 2970 outFrame.set(win.mCompatFrame); 2971 outContentInsets.set(win.mContentInsets); 2972 outVisibleInsets.set(win.mVisibleInsets); 2973 if (localLOGV) Slog.v( 2974 TAG, "Relayout given client " + client.asBinder() 2975 + ", requestedWidth=" + requestedWidth 2976 + ", requestedHeight=" + requestedHeight 2977 + ", viewVisibility=" + viewVisibility 2978 + "\nRelayout returning frame=" + outFrame 2979 + ", surface=" + outSurface); 2980 2981 if (localLOGV || DEBUG_FOCUS) Slog.v( 2982 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange); 2983 2984 inTouchMode = mInTouchMode; 2985 animating = mAnimator.mAnimating; 2986 if (animating && !mRelayoutWhileAnimating.contains(win)) { 2987 mRelayoutWhileAnimating.add(win); 2988 } 2989 2990 mInputMonitor.updateInputWindowsLw(true /*force*/); 2991 } 2992 2993 if (configChanged) { 2994 sendNewConfiguration(); 2995 } 2996 2997 Binder.restoreCallingIdentity(origId); 2998 2999 return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0) 3000 | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0) 3001 | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0) 3002 | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0); 3003 } 3004 3005 public void performDeferredDestroyWindow(Session session, IWindow client) { 3006 long origId = Binder.clearCallingIdentity(); 3007 3008 try { 3009 synchronized(mWindowMap) { 3010 WindowState win = windowForClientLocked(session, client, false); 3011 if (win == null) { 3012 return; 3013 } 3014 win.mWinAnimator.destroyDeferredSurfaceLocked(); 3015 } 3016 } finally { 3017 Binder.restoreCallingIdentity(origId); 3018 } 3019 } 3020 3021 public boolean outOfMemoryWindow(Session session, IWindow client) { 3022 long origId = Binder.clearCallingIdentity(); 3023 3024 try { 3025 synchronized(mWindowMap) { 3026 WindowState win = windowForClientLocked(session, client, false); 3027 if (win == null) { 3028 return false; 3029 } 3030 return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false); 3031 } 3032 } finally { 3033 Binder.restoreCallingIdentity(origId); 3034 } 3035 } 3036 3037 public void finishDrawingWindow(Session session, IWindow client) { 3038 final long origId = Binder.clearCallingIdentity(); 3039 synchronized(mWindowMap) { 3040 WindowState win = windowForClientLocked(session, client, false); 3041 if (win != null && win.mWinAnimator.finishDrawingLocked()) { 3042 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { 3043 adjustWallpaperWindowsLocked(); 3044 } 3045 win.mDisplayContent.layoutNeeded = true; 3046 performLayoutAndPlaceSurfacesLocked(); 3047 } 3048 } 3049 Binder.restoreCallingIdentity(origId); 3050 } 3051 3052 @Override 3053 public float getWindowCompatibilityScale(IBinder windowToken) { 3054 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 3055 "getWindowCompatibilityScale()")) { 3056 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 3057 } 3058 synchronized (mWindowMap) { 3059 WindowState windowState = mWindowMap.get(windowToken); 3060 return (windowState != null) ? windowState.mGlobalScale : 1.0f; 3061 } 3062 } 3063 3064 @Override 3065 public WindowInfo getWindowInfo(IBinder token) { 3066 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 3067 "getWindowInfo()")) { 3068 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 3069 } 3070 synchronized (mWindowMap) { 3071 WindowState window = mWindowMap.get(token); 3072 if (window != null) { 3073 return getWindowInfoForWindowStateLocked(window); 3074 } 3075 return null; 3076 } 3077 } 3078 3079 @Override 3080 public void getVisibleWindowsForDisplay(int displayId, List<WindowInfo> outInfos) { 3081 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 3082 "getWindowInfos()")) { 3083 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 3084 } 3085 synchronized (mWindowMap) { 3086 DisplayContent displayContent = getDisplayContentLocked(displayId); 3087 if (displayContent == null) { 3088 return; 3089 } 3090 WindowList windows = displayContent.getWindowList(); 3091 final int windowCount = windows.size(); 3092 for (int i = 0; i < windowCount; i++) { 3093 WindowState window = windows.get(i); 3094 if (window.isVisibleLw() || window.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 3095 WindowInfo info = getWindowInfoForWindowStateLocked(window); 3096 outInfos.add(info); 3097 } 3098 } 3099 } 3100 } 3101 3102 @Override 3103 public void magnifyDisplay(int displayId, float scale, float offsetX, float offsetY) { 3104 if (!checkCallingPermission( 3105 android.Manifest.permission.MAGNIFY_DISPLAY, "magnifyDisplay()")) { 3106 throw new SecurityException("Requires MAGNIFY_DISPLAY permission"); 3107 } 3108 synchronized (mWindowMap) { 3109 MagnificationSpec spec = getDisplayMagnificationSpecLocked(displayId); 3110 if (spec != null) { 3111 final boolean scaleChanged = spec.mScale != scale; 3112 final boolean offsetChanged = spec.mOffsetX != offsetX || spec.mOffsetY != offsetY; 3113 if (!scaleChanged && !offsetChanged) { 3114 return; 3115 } 3116 spec.initialize(scale, offsetX, offsetY); 3117 // If the offset has changed we need to re-add the input windows 3118 // since the offsets have to be propagated to the input system. 3119 if (offsetChanged) { 3120 // TODO(multidisplay): Input only occurs on the default display. 3121 if (displayId == Display.DEFAULT_DISPLAY) { 3122 mInputMonitor.updateInputWindowsLw(true); 3123 } 3124 } 3125 scheduleAnimationLocked(); 3126 } 3127 } 3128 } 3129 3130 MagnificationSpec getDisplayMagnificationSpecLocked(int displayId) { 3131 DisplayContent displayContent = getDisplayContentLocked(displayId); 3132 if (displayContent != null) { 3133 if (displayContent.mMagnificationSpec == null) { 3134 displayContent.mMagnificationSpec = new MagnificationSpec(); 3135 } 3136 return displayContent.mMagnificationSpec; 3137 } 3138 return null; 3139 } 3140 3141 private WindowInfo getWindowInfoForWindowStateLocked(WindowState window) { 3142 WindowInfo info = WindowInfo.obtain(); 3143 info.token = window.mToken.token; 3144 info.frame.set(window.mFrame); 3145 info.type = window.mAttrs.type; 3146 info.displayId = window.getDisplayId(); 3147 info.compatibilityScale = window.mGlobalScale; 3148 info.visible = window.isVisibleLw() || info.type == TYPE_UNIVERSE_BACKGROUND; 3149 info.layer = window.mLayer; 3150 window.getTouchableRegion(mTempRegion); 3151 mTempRegion.getBounds(info.touchableRegion); 3152 return info; 3153 } 3154 3155 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) { 3156 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg=" 3157 + (lp != null ? lp.packageName : null) 3158 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null)); 3159 if (lp != null && lp.windowAnimations != 0) { 3160 // If this is a system resource, don't try to load it from the 3161 // application resources. It is nice to avoid loading application 3162 // resources if we can. 3163 String packageName = lp.packageName != null ? lp.packageName : "android"; 3164 int resId = lp.windowAnimations; 3165 if ((resId&0xFF000000) == 0x01000000) { 3166 packageName = "android"; 3167 } 3168 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" 3169 + packageName); 3170 return AttributeCache.instance().get(packageName, resId, 3171 com.android.internal.R.styleable.WindowAnimation); 3172 } 3173 return null; 3174 } 3175 3176 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) { 3177 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package=" 3178 + packageName + " resId=0x" + Integer.toHexString(resId)); 3179 if (packageName != null) { 3180 if ((resId&0xFF000000) == 0x01000000) { 3181 packageName = "android"; 3182 } 3183 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" 3184 + packageName); 3185 return AttributeCache.instance().get(packageName, resId, 3186 com.android.internal.R.styleable.WindowAnimation); 3187 } 3188 return null; 3189 } 3190 3191 Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) { 3192 int anim = 0; 3193 Context context = mContext; 3194 if (animAttr >= 0) { 3195 AttributeCache.Entry ent = getCachedAnimations(lp); 3196 if (ent != null) { 3197 context = ent.context; 3198 anim = ent.array.getResourceId(animAttr, 0); 3199 } 3200 } 3201 if (anim != 0) { 3202 return AnimationUtils.loadAnimation(context, anim); 3203 } 3204 return null; 3205 } 3206 3207 private Animation loadAnimation(String packageName, int resId) { 3208 int anim = 0; 3209 Context context = mContext; 3210 if (resId >= 0) { 3211 AttributeCache.Entry ent = getCachedAnimations(packageName, resId); 3212 if (ent != null) { 3213 context = ent.context; 3214 anim = resId; 3215 } 3216 } 3217 if (anim != 0) { 3218 return AnimationUtils.loadAnimation(context, anim); 3219 } 3220 return null; 3221 } 3222 3223 private Animation createExitAnimationLocked(int transit, int duration) { 3224 if (transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN || 3225 transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE) { 3226 // If we are on top of the wallpaper, we need an animation that 3227 // correctly handles the wallpaper staying static behind all of 3228 // the animated elements. To do this, will just have the existing 3229 // element fade out. 3230 Animation a = new AlphaAnimation(1, 0); 3231 a.setDetachWallpaper(true); 3232 a.setDuration(duration); 3233 return a; 3234 } 3235 // For normal animations, the exiting element just holds in place. 3236 Animation a = new AlphaAnimation(1, 1); 3237 a.setDuration(duration); 3238 return a; 3239 } 3240 3241 /** 3242 * Compute the pivot point for an animation that is scaling from a small 3243 * rect on screen to a larger rect. The pivot point varies depending on 3244 * the distance between the inner and outer edges on both sides. This 3245 * function computes the pivot point for one dimension. 3246 * @param startPos Offset from left/top edge of outer rectangle to 3247 * left/top edge of inner rectangle. 3248 * @param finalScale The scaling factor between the size of the outer 3249 * and inner rectangles. 3250 */ 3251 private static float computePivot(int startPos, float finalScale) { 3252 final float denom = finalScale-1; 3253 if (Math.abs(denom) < .0001f) { 3254 return startPos; 3255 } 3256 return -startPos / denom; 3257 } 3258 3259 private Animation createScaleUpAnimationLocked(int transit, boolean enter) { 3260 Animation a; 3261 // Pick the desired duration. If this is an inter-activity transition, 3262 // it is the standard duration for that. Otherwise we use the longer 3263 // task transition duration. 3264 int duration; 3265 switch (transit) { 3266 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 3267 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 3268 duration = mContext.getResources().getInteger( 3269 com.android.internal.R.integer.config_shortAnimTime); 3270 break; 3271 default: 3272 duration = 300; 3273 break; 3274 } 3275 // TODO(multidisplay): For now assume all app animation is on main display. 3276 final DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3277 if (enter) { 3278 // Entering app zooms out from the center of the initial rect. 3279 float scaleW = mNextAppTransitionStartWidth / (float) displayInfo.appWidth; 3280 float scaleH = mNextAppTransitionStartHeight / (float) displayInfo.appHeight; 3281 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, 3282 computePivot(mNextAppTransitionStartX, scaleW), 3283 computePivot(mNextAppTransitionStartY, scaleH)); 3284 scale.setDuration(duration); 3285 AnimationSet set = new AnimationSet(true); 3286 Animation alpha = new AlphaAnimation(0, 1); 3287 scale.setDuration(duration); 3288 set.addAnimation(scale); 3289 alpha.setDuration(duration); 3290 set.addAnimation(alpha); 3291 set.setDetachWallpaper(true); 3292 a = set; 3293 } else { 3294 a = createExitAnimationLocked(transit, duration); 3295 } 3296 a.setFillAfter(true); 3297 final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext, 3298 com.android.internal.R.interpolator.decelerate_cubic); 3299 a.setInterpolator(interpolator); 3300 a.initialize(displayInfo.appWidth, displayInfo.appHeight, 3301 displayInfo.appWidth, displayInfo.appHeight); 3302 return a; 3303 } 3304 3305 private Animation createThumbnailAnimationLocked(int transit, 3306 boolean enter, boolean thumb, boolean scaleUp) { 3307 Animation a; 3308 final int thumbWidthI = mNextAppTransitionThumbnail.getWidth(); 3309 final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; 3310 final int thumbHeightI = mNextAppTransitionThumbnail.getHeight(); 3311 final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; 3312 // Pick the desired duration. If this is an inter-activity transition, 3313 // it is the standard duration for that. Otherwise we use the longer 3314 // task transition duration. 3315 int duration; 3316 switch (transit) { 3317 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 3318 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 3319 duration = mContext.getResources().getInteger( 3320 com.android.internal.R.integer.config_shortAnimTime); 3321 break; 3322 default: 3323 duration = 250; 3324 break; 3325 } 3326 // TOOD(multidisplay): For now assume all app animation is on the main screen. 3327 DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 3328 if (thumb) { 3329 // Animation for zooming thumbnail from its initial size to 3330 // filling the screen. 3331 if (scaleUp) { 3332 float scaleW = displayInfo.appWidth / thumbWidth; 3333 float scaleH = displayInfo.appHeight / thumbHeight; 3334 3335 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, 3336 computePivot(mNextAppTransitionStartX, 1 / scaleW), 3337 computePivot(mNextAppTransitionStartY, 1 / scaleH)); 3338 AnimationSet set = new AnimationSet(true); 3339 Animation alpha = new AlphaAnimation(1, 0); 3340 scale.setDuration(duration); 3341 scale.setInterpolator( 3342 new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR)); 3343 set.addAnimation(scale); 3344 alpha.setDuration(duration); 3345 set.addAnimation(alpha); 3346 set.setFillBefore(true); 3347 a = set; 3348 } else { 3349 float scaleW = displayInfo.appWidth / thumbWidth; 3350 float scaleH = displayInfo.appHeight / thumbHeight; 3351 3352 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, 3353 computePivot(mNextAppTransitionStartX, 1 / scaleW), 3354 computePivot(mNextAppTransitionStartY, 1 / scaleH)); 3355 AnimationSet set = new AnimationSet(true); 3356 Animation alpha = new AlphaAnimation(1, 1); 3357 scale.setDuration(duration); 3358 scale.setInterpolator( 3359 new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR)); 3360 set.addAnimation(scale); 3361 alpha.setDuration(duration); 3362 set.addAnimation(alpha); 3363 set.setFillBefore(true); 3364 3365 a = set; 3366 } 3367 } else if (enter) { 3368 // Entering app zooms out from the center of the thumbnail. 3369 if (scaleUp) { 3370 float scaleW = thumbWidth / displayInfo.appWidth; 3371 float scaleH = thumbHeight / displayInfo.appHeight; 3372 Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, 3373 computePivot(mNextAppTransitionStartX, scaleW), 3374 computePivot(mNextAppTransitionStartY, scaleH)); 3375 scale.setDuration(duration); 3376 scale.setInterpolator( 3377 new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR)); 3378 scale.setFillBefore(true); 3379 a = scale; 3380 } else { 3381 // noop animation 3382 a = new AlphaAnimation(1, 1); 3383 a.setDuration(duration); 3384 } 3385 } else { 3386 // Exiting app 3387 if (scaleUp) { 3388 if (transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN) { 3389 // Fade out while bringing up selected activity. This keeps the 3390 // current activity from showing through a launching wallpaper 3391 // activity. 3392 a = new AlphaAnimation(1, 0); 3393 } else { 3394 // noop animation 3395 a = new AlphaAnimation(1, 1); 3396 } 3397 a.setDuration(duration); 3398 } else { 3399 float scaleW = thumbWidth / displayInfo.appWidth; 3400 float scaleH = thumbHeight / displayInfo.appHeight; 3401 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, 3402 computePivot(mNextAppTransitionStartX, scaleW), 3403 computePivot(mNextAppTransitionStartY, scaleH)); 3404 scale.setDuration(duration); 3405 scale.setInterpolator( 3406 new DecelerateInterpolator(THUMBNAIL_ANIMATION_DECELERATE_FACTOR)); 3407 scale.setFillBefore(true); 3408 AnimationSet set = new AnimationSet(true); 3409 Animation alpha = new AlphaAnimation(1, 0); 3410 set.addAnimation(scale); 3411 alpha.setDuration(duration); 3412 alpha.setInterpolator(new DecelerateInterpolator( 3413 THUMBNAIL_ANIMATION_DECELERATE_FACTOR)); 3414 set.addAnimation(alpha); 3415 set.setFillBefore(true); 3416 set.setZAdjustment(Animation.ZORDER_TOP); 3417 a = set; 3418 } 3419 } 3420 a.setFillAfter(true); 3421 final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext, 3422 com.android.internal.R.interpolator.decelerate_quad); 3423 a.setInterpolator(interpolator); 3424 a.initialize(displayInfo.appWidth, displayInfo.appHeight, 3425 displayInfo.appWidth, displayInfo.appHeight); 3426 return a; 3427 } 3428 3429 private boolean applyAnimationLocked(AppWindowToken atoken, 3430 WindowManager.LayoutParams lp, int transit, boolean enter) { 3431 // Only apply an animation if the display isn't frozen. If it is 3432 // frozen, there is no reason to animate and it can cause strange 3433 // artifacts when we unfreeze the display if some different animation 3434 // is running. 3435 if (okToDisplay()) { 3436 Animation a; 3437 boolean initialized = false; 3438 if (mNextAppTransitionType == ActivityOptions.ANIM_CUSTOM) { 3439 a = loadAnimation(mNextAppTransitionPackage, enter ? 3440 mNextAppTransitionEnter : mNextAppTransitionExit); 3441 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 3442 "applyAnimation: atoken=" + atoken 3443 + " anim=" + a + " nextAppTransition=ANIM_CUSTOM" 3444 + " transit=" + transit + " isEntrance=" + enter 3445 + " Callers=" + Debug.getCallers(3)); 3446 } else if (mNextAppTransitionType == ActivityOptions.ANIM_SCALE_UP) { 3447 a = createScaleUpAnimationLocked(transit, enter); 3448 initialized = true; 3449 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 3450 "applyAnimation: atoken=" + atoken 3451 + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP" 3452 + " transit=" + transit + " isEntrance=" + enter 3453 + " Callers=" + Debug.getCallers(3)); 3454 } else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP || 3455 mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN) { 3456 boolean scaleUp = (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP); 3457 a = createThumbnailAnimationLocked(transit, enter, false, scaleUp); 3458 initialized = true; 3459 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { 3460 String animName = scaleUp ? "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN"; 3461 Slog.v(TAG, "applyAnimation: atoken=" + atoken 3462 + " anim=" + a + " nextAppTransition=" + animName 3463 + " transit=" + transit + " isEntrance=" + enter 3464 + " Callers=" + Debug.getCallers(3)); 3465 } 3466 } else { 3467 int animAttr = 0; 3468 switch (transit) { 3469 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 3470 animAttr = enter 3471 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation 3472 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation; 3473 break; 3474 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 3475 animAttr = enter 3476 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation 3477 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation; 3478 break; 3479 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 3480 animAttr = enter 3481 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation 3482 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation; 3483 break; 3484 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 3485 animAttr = enter 3486 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation 3487 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation; 3488 break; 3489 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 3490 animAttr = enter 3491 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation 3492 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation; 3493 break; 3494 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 3495 animAttr = enter 3496 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation 3497 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; 3498 break; 3499 case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN: 3500 animAttr = enter 3501 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation 3502 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation; 3503 break; 3504 case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE: 3505 animAttr = enter 3506 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation 3507 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation; 3508 break; 3509 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN: 3510 animAttr = enter 3511 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation 3512 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; 3513 break; 3514 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE: 3515 animAttr = enter 3516 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation 3517 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation; 3518 break; 3519 } 3520 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null; 3521 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 3522 "applyAnimation: atoken=" + atoken 3523 + " anim=" + a 3524 + " animAttr=0x" + Integer.toHexString(animAttr) 3525 + " transit=" + transit + " isEntrance=" + enter 3526 + " Callers=" + Debug.getCallers(3)); 3527 } 3528 if (a != null) { 3529 if (DEBUG_ANIM) { 3530 RuntimeException e = null; 3531 if (!HIDE_STACK_CRAWLS) { 3532 e = new RuntimeException(); 3533 e.fillInStackTrace(); 3534 } 3535 Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e); 3536 } 3537 atoken.mAppAnimator.setAnimation(a, initialized); 3538 } 3539 } else { 3540 atoken.mAppAnimator.clearAnimation(); 3541 } 3542 3543 return atoken.mAppAnimator.animation != null; 3544 } 3545 3546 // ------------------------------------------------------------- 3547 // Application Window Tokens 3548 // ------------------------------------------------------------- 3549 3550 public void validateAppTokens(List<IBinder> tokens) { 3551 int v = tokens.size()-1; 3552 int m = mAppTokens.size()-1; 3553 while (v >= 0 && m >= 0) { 3554 AppWindowToken atoken = mAppTokens.get(m); 3555 if (atoken.removed) { 3556 m--; 3557 continue; 3558 } 3559 if (tokens.get(v) != atoken.token) { 3560 Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v) 3561 + " @ " + v + ", internal is " + atoken.token + " @ " + m); 3562 } 3563 v--; 3564 m--; 3565 } 3566 while (v >= 0) { 3567 Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v); 3568 v--; 3569 } 3570 while (m >= 0) { 3571 AppWindowToken atoken = mAppTokens.get(m); 3572 if (!atoken.removed) { 3573 Slog.w(TAG, "Invalid internal atoken: " + atoken.token + " @ " + m); 3574 } 3575 m--; 3576 } 3577 } 3578 3579 boolean checkCallingPermission(String permission, String func) { 3580 // Quick check: if the calling permission is me, it's all okay. 3581 if (Binder.getCallingPid() == Process.myPid()) { 3582 return true; 3583 } 3584 3585 if (mContext.checkCallingPermission(permission) 3586 == PackageManager.PERMISSION_GRANTED) { 3587 return true; 3588 } 3589 String msg = "Permission Denial: " + func + " from pid=" 3590 + Binder.getCallingPid() 3591 + ", uid=" + Binder.getCallingUid() 3592 + " requires " + permission; 3593 Slog.w(TAG, msg); 3594 return false; 3595 } 3596 3597 boolean okToDisplay() { 3598 return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully(); 3599 } 3600 3601 AppWindowToken findAppWindowToken(IBinder token) { 3602 WindowToken wtoken = mTokenMap.get(token); 3603 if (wtoken == null) { 3604 return null; 3605 } 3606 return wtoken.appWindowToken; 3607 } 3608 3609 @Override 3610 public void addWindowToken(IBinder token, int type) { 3611 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3612 "addWindowToken()")) { 3613 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3614 } 3615 3616 synchronized(mWindowMap) { 3617 WindowToken wtoken = mTokenMap.get(token); 3618 if (wtoken != null) { 3619 Slog.w(TAG, "Attempted to add existing input method token: " + token); 3620 return; 3621 } 3622 wtoken = new WindowToken(this, token, type, true); 3623 mTokenMap.put(token, wtoken); 3624 if (type == TYPE_WALLPAPER) { 3625 mWallpaperTokens.add(wtoken); 3626 updateLayoutToAnimWallpaperTokens(); 3627 } 3628 } 3629 } 3630 3631 @Override 3632 public void removeWindowToken(IBinder token) { 3633 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3634 "removeWindowToken()")) { 3635 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3636 } 3637 3638 final long origId = Binder.clearCallingIdentity(); 3639 synchronized(mWindowMap) { 3640 WindowToken wtoken = mTokenMap.remove(token); 3641 if (wtoken != null) { 3642 boolean delayed = false; 3643 if (!wtoken.hidden) { 3644 final int N = wtoken.windows.size(); 3645 boolean changed = false; 3646 3647 for (int i=0; i<N; i++) { 3648 WindowState win = wtoken.windows.get(i); 3649 3650 if (win.mWinAnimator.isAnimating()) { 3651 delayed = true; 3652 } 3653 3654 if (win.isVisibleNow()) { 3655 win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, 3656 false); 3657 scheduleNotifyWindowTranstionIfNeededLocked(win, 3658 WindowManagerPolicy.TRANSIT_EXIT); 3659 changed = true; 3660 win.mDisplayContent.layoutNeeded = true; 3661 } 3662 } 3663 3664 wtoken.hidden = true; 3665 3666 if (changed) { 3667 performLayoutAndPlaceSurfacesLocked(); 3668 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 3669 false /*updateInputWindows*/); 3670 } 3671 3672 if (delayed) { 3673 mExitingTokens.add(wtoken); 3674 } else if (wtoken.windowType == TYPE_WALLPAPER) { 3675 mWallpaperTokens.remove(wtoken); 3676 updateLayoutToAnimWallpaperTokens(); 3677 } 3678 } 3679 3680 mInputMonitor.updateInputWindowsLw(true /*force*/); 3681 } else { 3682 Slog.w(TAG, "Attempted to remove non-existing token: " + token); 3683 } 3684 } 3685 Binder.restoreCallingIdentity(origId); 3686 } 3687 3688 /** 3689 * Find the location to insert a new AppWindowToken into the window-ordered app token list. 3690 * Note that mAppTokens.size() == mAnimatingAppTokens.size() + 1. 3691 * @param addPos The location the token was inserted into in mAppTokens. 3692 * @param atoken The token to insert. 3693 */ 3694 private void addAppTokenToAnimating(final int addPos, final AppWindowToken atoken) { 3695 if (addPos == 0 || addPos == mAnimatingAppTokens.size()) { 3696 // It was inserted into the beginning or end of mAppTokens. Honor that. 3697 mAnimatingAppTokens.add(addPos, atoken); 3698 return; 3699 } 3700 // Find the item immediately above the mAppTokens insertion point and put the token 3701 // immediately below that one in mAnimatingAppTokens. 3702 final AppWindowToken aboveAnchor = mAppTokens.get(addPos + 1); 3703 mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), atoken); 3704 } 3705 3706 @Override 3707 public void addAppToken(int addPos, IApplicationToken token, 3708 int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) { 3709 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3710 "addAppToken()")) { 3711 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3712 } 3713 3714 // Get the dispatching timeout here while we are not holding any locks so that it 3715 // can be cached by the AppWindowToken. The timeout value is used later by the 3716 // input dispatcher in code that does hold locks. If we did not cache the value 3717 // here we would run the chance of introducing a deadlock between the window manager 3718 // (which holds locks while updating the input dispatcher state) and the activity manager 3719 // (which holds locks while querying the application token). 3720 long inputDispatchingTimeoutNanos; 3721 try { 3722 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; 3723 } catch (RemoteException ex) { 3724 Slog.w(TAG, "Could not get dispatching timeout.", ex); 3725 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 3726 } 3727 3728 synchronized(mWindowMap) { 3729 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 3730 if (atoken != null) { 3731 Slog.w(TAG, "Attempted to add existing app token: " + token); 3732 return; 3733 } 3734 atoken = new AppWindowToken(this, token); 3735 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; 3736 atoken.groupId = groupId; 3737 atoken.appFullscreen = fullscreen; 3738 atoken.showWhenLocked = showWhenLocked; 3739 atoken.requestedOrientation = requestedOrientation; 3740 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken 3741 + " at " + addPos); 3742 mAppTokens.add(addPos, atoken); 3743 addAppTokenToAnimating(addPos, atoken); 3744 mTokenMap.put(token.asBinder(), atoken); 3745 3746 // Application tokens start out hidden. 3747 atoken.hidden = true; 3748 atoken.hiddenRequested = true; 3749 3750 //dump(); 3751 } 3752 } 3753 3754 @Override 3755 public void setAppGroupId(IBinder token, int groupId) { 3756 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3757 "setAppGroupId()")) { 3758 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3759 } 3760 3761 synchronized(mWindowMap) { 3762 AppWindowToken atoken = findAppWindowToken(token); 3763 if (atoken == null) { 3764 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); 3765 return; 3766 } 3767 atoken.groupId = groupId; 3768 } 3769 } 3770 3771 public int getOrientationFromWindowsLocked() { 3772 if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 3773 // If the display is frozen, some activities may be in the middle 3774 // of restarting, and thus have removed their old window. If the 3775 // window has the flag to hide the lock screen, then the lock screen 3776 // can re-appear and inflict its own orientation on us. Keep the 3777 // orientation stable until this all settles down. 3778 return mLastWindowForcedOrientation; 3779 } 3780 3781 // TODO(multidisplay): Change to the correct display. 3782 final WindowList windows = getDefaultWindowListLocked(); 3783 int pos = windows.size() - 1; 3784 while (pos >= 0) { 3785 WindowState wtoken = windows.get(pos); 3786 pos--; 3787 if (wtoken.mAppToken != null) { 3788 // We hit an application window. so the orientation will be determined by the 3789 // app window. No point in continuing further. 3790 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3791 } 3792 if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) { 3793 continue; 3794 } 3795 int req = wtoken.mAttrs.screenOrientation; 3796 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) || 3797 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){ 3798 continue; 3799 } 3800 3801 return (mLastWindowForcedOrientation=req); 3802 } 3803 return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 3804 } 3805 3806 public int getOrientationFromAppTokensLocked() { 3807 int curGroup = 0; 3808 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3809 boolean findingBehind = false; 3810 boolean haveGroup = false; 3811 boolean lastFullscreen = false; 3812 for (int pos = mAppTokens.size() - 1; pos >= 0; pos--) { 3813 AppWindowToken atoken = mAppTokens.get(pos); 3814 3815 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken); 3816 3817 // if we're about to tear down this window and not seek for 3818 // the behind activity, don't use it for orientation 3819 if (!findingBehind 3820 && (!atoken.hidden && atoken.hiddenRequested)) { 3821 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3822 + " -- going to hide"); 3823 continue; 3824 } 3825 3826 if (haveGroup == true && curGroup != atoken.groupId) { 3827 // If we have hit a new application group, and the bottom 3828 // of the previous group didn't explicitly say to use 3829 // the orientation behind it, and the last app was 3830 // full screen, then we'll stick with the 3831 // user's orientation. 3832 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND 3833 && lastFullscreen) { 3834 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3835 + " -- end of group, return " + lastOrientation); 3836 return lastOrientation; 3837 } 3838 } 3839 3840 // We ignore any hidden applications on the top. 3841 if (atoken.hiddenRequested || atoken.willBeHidden) { 3842 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken 3843 + " -- hidden on top"); 3844 continue; 3845 } 3846 3847 if (!haveGroup) { 3848 haveGroup = true; 3849 curGroup = atoken.groupId; 3850 lastOrientation = atoken.requestedOrientation; 3851 } 3852 3853 int or = atoken.requestedOrientation; 3854 // If this application is fullscreen, and didn't explicitly say 3855 // to use the orientation behind it, then just take whatever 3856 // orientation it has and ignores whatever is under it. 3857 lastFullscreen = atoken.appFullscreen; 3858 if (lastFullscreen 3859 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3860 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3861 + " -- full screen, return " + or); 3862 return or; 3863 } 3864 // If this application has requested an explicit orientation, 3865 // then use it. 3866 if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 3867 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { 3868 if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken 3869 + " -- explicitly set, return " + or); 3870 return or; 3871 } 3872 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND); 3873 } 3874 if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation"); 3875 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 3876 } 3877 3878 @Override 3879 public Configuration updateOrientationFromAppTokens( 3880 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3881 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3882 "updateOrientationFromAppTokens()")) { 3883 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3884 } 3885 3886 Configuration config = null; 3887 long ident = Binder.clearCallingIdentity(); 3888 3889 synchronized(mWindowMap) { 3890 config = updateOrientationFromAppTokensLocked(currentConfig, 3891 freezeThisOneIfNeeded); 3892 } 3893 3894 Binder.restoreCallingIdentity(ident); 3895 return config; 3896 } 3897 3898 private Configuration updateOrientationFromAppTokensLocked( 3899 Configuration currentConfig, IBinder freezeThisOneIfNeeded) { 3900 Configuration config = null; 3901 3902 if (updateOrientationFromAppTokensLocked(false)) { 3903 if (freezeThisOneIfNeeded != null) { 3904 AppWindowToken atoken = findAppWindowToken( 3905 freezeThisOneIfNeeded); 3906 if (atoken != null) { 3907 startAppFreezingScreenLocked(atoken, 3908 ActivityInfo.CONFIG_ORIENTATION); 3909 } 3910 } 3911 config = computeNewConfigurationLocked(); 3912 3913 } else if (currentConfig != null) { 3914 // No obvious action we need to take, but if our current 3915 // state mismatches the activity manager's, update it, 3916 // disregarding font scale, which should remain set to 3917 // the value of the previous configuration. 3918 mTempConfiguration.setToDefaults(); 3919 mTempConfiguration.fontScale = currentConfig.fontScale; 3920 if (computeScreenConfigurationLocked(mTempConfiguration)) { 3921 if (currentConfig.diff(mTempConfiguration) != 0) { 3922 mWaitingForConfig = true; 3923 getDefaultDisplayContentLocked().layoutNeeded = true; 3924 startFreezingDisplayLocked(false, 0, 0); 3925 config = new Configuration(mTempConfiguration); 3926 } 3927 } 3928 } 3929 3930 return config; 3931 } 3932 3933 /* 3934 * Determine the new desired orientation of the display, returning 3935 * a non-null new Configuration if it has changed from the current 3936 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL 3937 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE 3938 * SCREEN. This will typically be done for you if you call 3939 * sendNewConfiguration(). 3940 * 3941 * The orientation is computed from non-application windows first. If none of 3942 * the non-application windows specify orientation, the orientation is computed from 3943 * application tokens. 3944 * @see android.view.IWindowManager#updateOrientationFromAppTokens( 3945 * android.os.IBinder) 3946 */ 3947 boolean updateOrientationFromAppTokensLocked(boolean inTransaction) { 3948 long ident = Binder.clearCallingIdentity(); 3949 try { 3950 int req = computeForcedAppOrientationLocked(); 3951 3952 if (req != mForcedAppOrientation) { 3953 mForcedAppOrientation = req; 3954 //send a message to Policy indicating orientation change to take 3955 //action like disabling/enabling sensors etc., 3956 mPolicy.setCurrentOrientationLw(req); 3957 if (updateRotationUncheckedLocked(inTransaction)) { 3958 // changed 3959 return true; 3960 } 3961 } 3962 3963 return false; 3964 } finally { 3965 Binder.restoreCallingIdentity(ident); 3966 } 3967 } 3968 3969 int computeForcedAppOrientationLocked() { 3970 int req = getOrientationFromWindowsLocked(); 3971 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { 3972 req = getOrientationFromAppTokensLocked(); 3973 } 3974 return req; 3975 } 3976 3977 @Override 3978 public void setNewConfiguration(Configuration config) { 3979 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3980 "setNewConfiguration()")) { 3981 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3982 } 3983 3984 synchronized(mWindowMap) { 3985 mCurConfiguration = new Configuration(config); 3986 mWaitingForConfig = false; 3987 performLayoutAndPlaceSurfacesLocked(); 3988 } 3989 } 3990 3991 @Override 3992 public void setAppOrientation(IApplicationToken token, int requestedOrientation) { 3993 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 3994 "setAppOrientation()")) { 3995 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 3996 } 3997 3998 synchronized(mWindowMap) { 3999 AppWindowToken atoken = findAppWindowToken(token.asBinder()); 4000 if (atoken == null) { 4001 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token); 4002 return; 4003 } 4004 4005 atoken.requestedOrientation = requestedOrientation; 4006 } 4007 } 4008 4009 @Override 4010 public int getAppOrientation(IApplicationToken token) { 4011 synchronized(mWindowMap) { 4012 AppWindowToken wtoken = findAppWindowToken(token.asBinder()); 4013 if (wtoken == null) { 4014 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 4015 } 4016 4017 return wtoken.requestedOrientation; 4018 } 4019 } 4020 4021 @Override 4022 public void setFocusedApp(IBinder token, boolean moveFocusNow) { 4023 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4024 "setFocusedApp()")) { 4025 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4026 } 4027 4028 synchronized(mWindowMap) { 4029 boolean changed = false; 4030 if (token == null) { 4031 if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); 4032 changed = mFocusedApp != null; 4033 mFocusedApp = null; 4034 if (changed) { 4035 mInputMonitor.setFocusedAppLw(null); 4036 } 4037 } else { 4038 AppWindowToken newFocus = findAppWindowToken(token); 4039 if (newFocus == null) { 4040 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); 4041 return; 4042 } 4043 changed = mFocusedApp != newFocus; 4044 mFocusedApp = newFocus; 4045 if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp 4046 + " moveFocusNow=" + moveFocusNow); 4047 if (changed) { 4048 mInputMonitor.setFocusedAppLw(newFocus); 4049 } 4050 } 4051 4052 if (moveFocusNow && changed) { 4053 final long origId = Binder.clearCallingIdentity(); 4054 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4055 Binder.restoreCallingIdentity(origId); 4056 } 4057 } 4058 } 4059 4060 @Override 4061 public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { 4062 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4063 "prepareAppTransition()")) { 4064 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4065 } 4066 4067 synchronized(mWindowMap) { 4068 if (DEBUG_APP_TRANSITIONS) Slog.v( 4069 TAG, "Prepare app transition: transit=" + transit 4070 + " mNextAppTransition=" + mNextAppTransition 4071 + " alwaysKeepCurrent=" + alwaysKeepCurrent 4072 + " Callers=" + Debug.getCallers(3)); 4073 if (okToDisplay()) { 4074 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET 4075 || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) { 4076 mNextAppTransition = transit; 4077 } else if (!alwaysKeepCurrent) { 4078 if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN 4079 && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) { 4080 // Opening a new task always supersedes a close for the anim. 4081 mNextAppTransition = transit; 4082 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN 4083 && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) { 4084 // Opening a new activity always supersedes a close for the anim. 4085 mNextAppTransition = transit; 4086 } 4087 } 4088 mAppTransitionReady = false; 4089 mAppTransitionTimeout = false; 4090 mStartingIconInTransition = false; 4091 mSkipAppTransitionAnimation = false; 4092 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 4093 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT), 4094 5000); 4095 } 4096 } 4097 } 4098 4099 @Override 4100 public int getPendingAppTransition() { 4101 return mNextAppTransition; 4102 } 4103 4104 private void scheduleAnimationCallback(IRemoteCallback cb) { 4105 if (cb != null) { 4106 mH.sendMessage(mH.obtainMessage(H.DO_ANIMATION_CALLBACK, cb)); 4107 } 4108 } 4109 4110 @Override 4111 public void overridePendingAppTransition(String packageName, 4112 int enterAnim, int exitAnim, IRemoteCallback startedCallback) { 4113 synchronized(mWindowMap) { 4114 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4115 mNextAppTransitionType = ActivityOptions.ANIM_CUSTOM; 4116 mNextAppTransitionPackage = packageName; 4117 mNextAppTransitionThumbnail = null; 4118 mNextAppTransitionEnter = enterAnim; 4119 mNextAppTransitionExit = exitAnim; 4120 scheduleAnimationCallback(mNextAppTransitionCallback); 4121 mNextAppTransitionCallback = startedCallback; 4122 } else { 4123 scheduleAnimationCallback(startedCallback); 4124 } 4125 } 4126 } 4127 4128 @Override 4129 public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, 4130 int startHeight) { 4131 synchronized(mWindowMap) { 4132 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4133 mNextAppTransitionType = ActivityOptions.ANIM_SCALE_UP; 4134 mNextAppTransitionPackage = null; 4135 mNextAppTransitionThumbnail = null; 4136 mNextAppTransitionStartX = startX; 4137 mNextAppTransitionStartY = startY; 4138 mNextAppTransitionStartWidth = startWidth; 4139 mNextAppTransitionStartHeight = startHeight; 4140 scheduleAnimationCallback(mNextAppTransitionCallback); 4141 mNextAppTransitionCallback = null; 4142 } 4143 } 4144 } 4145 4146 @Override 4147 public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, 4148 int startY, IRemoteCallback startedCallback, boolean scaleUp) { 4149 synchronized(mWindowMap) { 4150 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4151 mNextAppTransitionType = scaleUp 4152 ? ActivityOptions.ANIM_THUMBNAIL_SCALE_UP : ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN; 4153 mNextAppTransitionPackage = null; 4154 mNextAppTransitionThumbnail = srcThumb; 4155 mNextAppTransitionScaleUp = scaleUp; 4156 mNextAppTransitionStartX = startX; 4157 mNextAppTransitionStartY = startY; 4158 scheduleAnimationCallback(mNextAppTransitionCallback); 4159 mNextAppTransitionCallback = startedCallback; 4160 } else { 4161 scheduleAnimationCallback(startedCallback); 4162 } 4163 } 4164 } 4165 4166 @Override 4167 public void executeAppTransition() { 4168 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4169 "executeAppTransition()")) { 4170 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4171 } 4172 4173 synchronized(mWindowMap) { 4174 if (DEBUG_APP_TRANSITIONS) { 4175 RuntimeException e = new RuntimeException("here"); 4176 e.fillInStackTrace(); 4177 Slog.w(TAG, "Execute app transition: mNextAppTransition=" 4178 + mNextAppTransition, e); 4179 } 4180 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4181 mAppTransitionReady = true; 4182 final long origId = Binder.clearCallingIdentity(); 4183 performLayoutAndPlaceSurfacesLocked(); 4184 Binder.restoreCallingIdentity(origId); 4185 } 4186 } 4187 } 4188 4189 @Override 4190 public void setAppStartingWindow(IBinder token, String pkg, 4191 int theme, CompatibilityInfo compatInfo, 4192 CharSequence nonLocalizedLabel, int labelRes, int icon, 4193 int windowFlags, IBinder transferFrom, boolean createIfNeeded) { 4194 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4195 "setAppStartingWindow()")) { 4196 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4197 } 4198 4199 synchronized(mWindowMap) { 4200 if (DEBUG_STARTING_WINDOW) Slog.v( 4201 TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg 4202 + " transferFrom=" + transferFrom); 4203 4204 AppWindowToken wtoken = findAppWindowToken(token); 4205 if (wtoken == null) { 4206 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token); 4207 return; 4208 } 4209 4210 // If the display is frozen, we won't do anything until the 4211 // actual window is displayed so there is no reason to put in 4212 // the starting window. 4213 if (!okToDisplay()) { 4214 return; 4215 } 4216 4217 if (wtoken.startingData != null) { 4218 return; 4219 } 4220 4221 if (transferFrom != null) { 4222 AppWindowToken ttoken = findAppWindowToken(transferFrom); 4223 if (ttoken != null) { 4224 WindowState startingWindow = ttoken.startingWindow; 4225 if (startingWindow != null) { 4226 if (mStartingIconInTransition) { 4227 // In this case, the starting icon has already 4228 // been displayed, so start letting windows get 4229 // shown immediately without any more transitions. 4230 mSkipAppTransitionAnimation = true; 4231 } 4232 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4233 "Moving existing starting " + startingWindow + " from " + ttoken 4234 + " to " + wtoken); 4235 final long origId = Binder.clearCallingIdentity(); 4236 4237 // Transfer the starting window over to the new 4238 // token. 4239 wtoken.startingData = ttoken.startingData; 4240 wtoken.startingView = ttoken.startingView; 4241 wtoken.startingDisplayed = ttoken.startingDisplayed; 4242 ttoken.startingDisplayed = false; 4243 wtoken.startingWindow = startingWindow; 4244 wtoken.reportedVisible = ttoken.reportedVisible; 4245 ttoken.startingData = null; 4246 ttoken.startingView = null; 4247 ttoken.startingWindow = null; 4248 ttoken.startingMoved = true; 4249 startingWindow.mToken = wtoken; 4250 startingWindow.mRootToken = wtoken; 4251 startingWindow.mAppToken = wtoken; 4252 startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator; 4253 4254 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { 4255 Slog.v(TAG, "Removing starting window: " + startingWindow); 4256 } 4257 startingWindow.getWindowList().remove(startingWindow); 4258 mWindowsChanged = true; 4259 if (DEBUG_ADD_REMOVE) Slog.v(TAG, 4260 "Removing starting " + startingWindow + " from " + ttoken); 4261 ttoken.windows.remove(startingWindow); 4262 ttoken.allAppWindows.remove(startingWindow); 4263 addWindowToListInOrderLocked(startingWindow, true); 4264 4265 // Propagate other interesting state between the 4266 // tokens. If the old token is displayed, we should 4267 // immediately force the new one to be displayed. If 4268 // it is animating, we need to move that animation to 4269 // the new one. 4270 if (ttoken.allDrawn) { 4271 wtoken.allDrawn = true; 4272 } 4273 if (ttoken.firstWindowDrawn) { 4274 wtoken.firstWindowDrawn = true; 4275 } 4276 if (!ttoken.hidden) { 4277 wtoken.hidden = false; 4278 wtoken.hiddenRequested = false; 4279 wtoken.willBeHidden = false; 4280 } 4281 if (wtoken.clientHidden != ttoken.clientHidden) { 4282 wtoken.clientHidden = ttoken.clientHidden; 4283 wtoken.sendAppVisibilityToClients(); 4284 } 4285 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4286 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4287 if (tAppAnimator.animation != null) { 4288 wAppAnimator.animation = tAppAnimator.animation; 4289 wAppAnimator.animating = tAppAnimator.animating; 4290 wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; 4291 tAppAnimator.animation = null; 4292 tAppAnimator.animLayerAdjustment = 0; 4293 wAppAnimator.updateLayers(); 4294 tAppAnimator.updateLayers(); 4295 } 4296 4297 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4298 true /*updateInputWindows*/); 4299 getDefaultDisplayContentLocked().layoutNeeded = true; 4300 performLayoutAndPlaceSurfacesLocked(); 4301 Binder.restoreCallingIdentity(origId); 4302 return; 4303 } else if (ttoken.startingData != null) { 4304 // The previous app was getting ready to show a 4305 // starting window, but hasn't yet done so. Steal it! 4306 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 4307 "Moving pending starting from " + ttoken 4308 + " to " + wtoken); 4309 wtoken.startingData = ttoken.startingData; 4310 ttoken.startingData = null; 4311 ttoken.startingMoved = true; 4312 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4313 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4314 // want to process the message ASAP, before any other queued 4315 // messages. 4316 mH.sendMessageAtFrontOfQueue(m); 4317 return; 4318 } 4319 final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; 4320 final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; 4321 if (tAppAnimator.thumbnail != null) { 4322 // The old token is animating with a thumbnail, transfer 4323 // that to the new token. 4324 if (wAppAnimator.thumbnail != null) { 4325 wAppAnimator.thumbnail.destroy(); 4326 } 4327 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 4328 wAppAnimator.thumbnailX = tAppAnimator.thumbnailX; 4329 wAppAnimator.thumbnailY = tAppAnimator.thumbnailY; 4330 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 4331 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 4332 tAppAnimator.thumbnail = null; 4333 } 4334 } 4335 } 4336 4337 // There is no existing starting window, and the caller doesn't 4338 // want us to create one, so that's it! 4339 if (!createIfNeeded) { 4340 return; 4341 } 4342 4343 // If this is a translucent window, then don't 4344 // show a starting window -- the current effect (a full-screen 4345 // opaque starting window that fades away to the real contents 4346 // when it is ready) does not work for this. 4347 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x" 4348 + Integer.toHexString(theme)); 4349 if (theme != 0) { 4350 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, 4351 com.android.internal.R.styleable.Window); 4352 if (ent == null) { 4353 // Whoops! App doesn't exist. Um. Okay. We'll just 4354 // pretend like we didn't see that. 4355 return; 4356 } 4357 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent=" 4358 + ent.array.getBoolean( 4359 com.android.internal.R.styleable.Window_windowIsTranslucent, false) 4360 + " Floating=" 4361 + ent.array.getBoolean( 4362 com.android.internal.R.styleable.Window_windowIsFloating, false) 4363 + " ShowWallpaper=" 4364 + ent.array.getBoolean( 4365 com.android.internal.R.styleable.Window_windowShowWallpaper, false)); 4366 if (ent.array.getBoolean( 4367 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { 4368 return; 4369 } 4370 if (ent.array.getBoolean( 4371 com.android.internal.R.styleable.Window_windowIsFloating, false)) { 4372 return; 4373 } 4374 if (ent.array.getBoolean( 4375 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { 4376 if (mWallpaperTarget == null) { 4377 // If this theme is requesting a wallpaper, and the wallpaper 4378 // is not curently visible, then this effectively serves as 4379 // an opaque window and our starting window transition animation 4380 // can still work. We just need to make sure the starting window 4381 // is also showing the wallpaper. 4382 windowFlags |= FLAG_SHOW_WALLPAPER; 4383 } else { 4384 return; 4385 } 4386 } 4387 } 4388 4389 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); 4390 mStartingIconInTransition = true; 4391 wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, 4392 labelRes, icon, windowFlags); 4393 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); 4394 // Note: we really want to do sendMessageAtFrontOfQueue() because we 4395 // want to process the message ASAP, before any other queued 4396 // messages. 4397 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING"); 4398 mH.sendMessageAtFrontOfQueue(m); 4399 } 4400 } 4401 4402 public void setAppWillBeHidden(IBinder token) { 4403 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4404 "setAppWillBeHidden()")) { 4405 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4406 } 4407 4408 AppWindowToken wtoken; 4409 4410 synchronized(mWindowMap) { 4411 wtoken = findAppWindowToken(token); 4412 if (wtoken == null) { 4413 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token); 4414 return; 4415 } 4416 wtoken.willBeHidden = true; 4417 } 4418 } 4419 4420 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, 4421 boolean visible, int transit, boolean performLayout) { 4422 boolean delayed = false; 4423 4424 if (wtoken.clientHidden == visible) { 4425 wtoken.clientHidden = !visible; 4426 wtoken.sendAppVisibilityToClients(); 4427 } 4428 4429 wtoken.willBeHidden = false; 4430 if (wtoken.hidden == visible) { 4431 boolean changed = false; 4432 if (DEBUG_APP_TRANSITIONS) Slog.v( 4433 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden 4434 + " performLayout=" + performLayout); 4435 4436 boolean runningAppAnimation = false; 4437 4438 if (transit != WindowManagerPolicy.TRANSIT_UNSET) { 4439 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 4440 wtoken.mAppAnimator.animation = null; 4441 } 4442 if (applyAnimationLocked(wtoken, lp, transit, visible)) { 4443 delayed = runningAppAnimation = true; 4444 } 4445 WindowState window = wtoken.findMainWindow(); 4446 if (window != null) { 4447 scheduleNotifyWindowTranstionIfNeededLocked(window, transit); 4448 } 4449 changed = true; 4450 } 4451 4452 final int N = wtoken.allAppWindows.size(); 4453 for (int i=0; i<N; i++) { 4454 WindowState win = wtoken.allAppWindows.get(i); 4455 if (win == wtoken.startingWindow) { 4456 continue; 4457 } 4458 4459 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); 4460 //win.dump(" "); 4461 if (visible) { 4462 if (!win.isVisibleNow()) { 4463 if (!runningAppAnimation) { 4464 win.mWinAnimator.applyAnimationLocked( 4465 WindowManagerPolicy.TRANSIT_ENTER, true); 4466 scheduleNotifyWindowTranstionIfNeededLocked(win, 4467 WindowManagerPolicy.TRANSIT_ENTER); 4468 } 4469 changed = true; 4470 win.mDisplayContent.layoutNeeded = true; 4471 } 4472 } else if (win.isVisibleNow()) { 4473 if (!runningAppAnimation) { 4474 win.mWinAnimator.applyAnimationLocked( 4475 WindowManagerPolicy.TRANSIT_EXIT, false); 4476 scheduleNotifyWindowTranstionIfNeededLocked(win, 4477 WindowManagerPolicy.TRANSIT_EXIT); 4478 } 4479 changed = true; 4480 win.mDisplayContent.layoutNeeded = true; 4481 } 4482 } 4483 4484 wtoken.hidden = wtoken.hiddenRequested = !visible; 4485 if (!visible) { 4486 unsetAppFreezingScreenLocked(wtoken, true, true); 4487 } else { 4488 // If we are being set visible, and the starting window is 4489 // not yet displayed, then make sure it doesn't get displayed. 4490 WindowState swin = wtoken.startingWindow; 4491 if (swin != null && !swin.isDrawnLw()) { 4492 swin.mPolicyVisibility = false; 4493 swin.mPolicyVisibilityAfterAnim = false; 4494 } 4495 } 4496 4497 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken 4498 + ": hidden=" + wtoken.hidden + " hiddenRequested=" 4499 + wtoken.hiddenRequested); 4500 4501 if (changed) { 4502 mInputMonitor.setUpdateInputWindowsNeededLw(); 4503 if (performLayout) { 4504 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4505 false /*updateInputWindows*/); 4506 performLayoutAndPlaceSurfacesLocked(); 4507 } 4508 mInputMonitor.updateInputWindowsLw(false /*force*/); 4509 } 4510 } 4511 4512 if (wtoken.mAppAnimator.animation != null) { 4513 delayed = true; 4514 } 4515 4516 for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { 4517 if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { 4518 delayed = true; 4519 } 4520 } 4521 4522 return delayed; 4523 } 4524 4525 public void setAppVisibility(IBinder token, boolean visible) { 4526 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4527 "setAppVisibility()")) { 4528 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4529 } 4530 4531 AppWindowToken wtoken; 4532 4533 synchronized(mWindowMap) { 4534 wtoken = findAppWindowToken(token); 4535 if (wtoken == null) { 4536 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); 4537 return; 4538 } 4539 4540 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) { 4541 RuntimeException e = null; 4542 if (!HIDE_STACK_CRAWLS) { 4543 e = new RuntimeException(); 4544 e.fillInStackTrace(); 4545 } 4546 Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible 4547 + "): mNextAppTransition=" + mNextAppTransition 4548 + " hidden=" + wtoken.hidden 4549 + " hiddenRequested=" + wtoken.hiddenRequested, e); 4550 } 4551 4552 // If we are preparing an app transition, then delay changing 4553 // the visibility of this token until we execute that transition. 4554 if (okToDisplay() && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4555 // Already in requested state, don't do anything more. 4556 if (wtoken.hiddenRequested != visible) { 4557 return; 4558 } 4559 wtoken.hiddenRequested = !visible; 4560 4561 if (!wtoken.startingDisplayed) { 4562 if (DEBUG_APP_TRANSITIONS) Slog.v( 4563 TAG, "Setting dummy animation on: " + wtoken); 4564 wtoken.mAppAnimator.setDummyAnimation(); 4565 } 4566 mOpeningApps.remove(wtoken); 4567 mClosingApps.remove(wtoken); 4568 wtoken.waitingToShow = wtoken.waitingToHide = false; 4569 wtoken.inPendingTransaction = true; 4570 if (visible) { 4571 mOpeningApps.add(wtoken); 4572 wtoken.startingMoved = false; 4573 4574 // If the token is currently hidden (should be the 4575 // common case), then we need to set up to wait for 4576 // its windows to be ready. 4577 if (wtoken.hidden) { 4578 wtoken.allDrawn = false; 4579 wtoken.waitingToShow = true; 4580 4581 if (wtoken.clientHidden) { 4582 // In the case where we are making an app visible 4583 // but holding off for a transition, we still need 4584 // to tell the client to make its windows visible so 4585 // they get drawn. Otherwise, we will wait on 4586 // performing the transition until all windows have 4587 // been drawn, they never will be, and we are sad. 4588 wtoken.clientHidden = false; 4589 wtoken.sendAppVisibilityToClients(); 4590 } 4591 } 4592 } else { 4593 mClosingApps.add(wtoken); 4594 4595 // If the token is currently visible (should be the 4596 // common case), then set up to wait for it to be hidden. 4597 if (!wtoken.hidden) { 4598 wtoken.waitingToHide = true; 4599 } 4600 } 4601 return; 4602 } 4603 4604 final long origId = Binder.clearCallingIdentity(); 4605 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, 4606 true); 4607 wtoken.updateReportedVisibilityLocked(); 4608 Binder.restoreCallingIdentity(origId); 4609 } 4610 } 4611 4612 void unsetAppFreezingScreenLocked(AppWindowToken wtoken, 4613 boolean unfreezeSurfaceNow, boolean force) { 4614 if (wtoken.mAppAnimator.freezingScreen) { 4615 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken 4616 + " force=" + force); 4617 final int N = wtoken.allAppWindows.size(); 4618 boolean unfrozeWindows = false; 4619 for (int i=0; i<N; i++) { 4620 WindowState w = wtoken.allAppWindows.get(i); 4621 if (w.mAppFreezing) { 4622 w.mAppFreezing = false; 4623 if (w.mHasSurface && !w.mOrientationChanging) { 4624 if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); 4625 w.mOrientationChanging = true; 4626 mInnerFields.mOrientationChangeComplete = false; 4627 } 4628 unfrozeWindows = true; 4629 w.mDisplayContent.layoutNeeded = true; 4630 } 4631 } 4632 if (force || unfrozeWindows) { 4633 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); 4634 wtoken.mAppAnimator.freezingScreen = false; 4635 mAppsFreezingScreen--; 4636 } 4637 if (unfreezeSurfaceNow) { 4638 if (unfrozeWindows) { 4639 performLayoutAndPlaceSurfacesLocked(); 4640 } 4641 stopFreezingDisplayLocked(); 4642 } 4643 } 4644 } 4645 4646 public void startAppFreezingScreenLocked(AppWindowToken wtoken, 4647 int configChanges) { 4648 if (DEBUG_ORIENTATION) { 4649 RuntimeException e = null; 4650 if (!HIDE_STACK_CRAWLS) { 4651 e = new RuntimeException(); 4652 e.fillInStackTrace(); 4653 } 4654 Slog.i(TAG, "Set freezing of " + wtoken.appToken 4655 + ": hidden=" + wtoken.hidden + " freezing=" 4656 + wtoken.mAppAnimator.freezingScreen, e); 4657 } 4658 if (!wtoken.hiddenRequested) { 4659 if (!wtoken.mAppAnimator.freezingScreen) { 4660 wtoken.mAppAnimator.freezingScreen = true; 4661 mAppsFreezingScreen++; 4662 if (mAppsFreezingScreen == 1) { 4663 startFreezingDisplayLocked(false, 0, 0); 4664 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 4665 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT), 4666 5000); 4667 } 4668 } 4669 final int N = wtoken.allAppWindows.size(); 4670 for (int i=0; i<N; i++) { 4671 WindowState w = wtoken.allAppWindows.get(i); 4672 w.mAppFreezing = true; 4673 } 4674 } 4675 } 4676 4677 public void startAppFreezingScreen(IBinder token, int configChanges) { 4678 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4679 "setAppFreezingScreen()")) { 4680 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4681 } 4682 4683 synchronized(mWindowMap) { 4684 if (configChanges == 0 && okToDisplay()) { 4685 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); 4686 return; 4687 } 4688 4689 AppWindowToken wtoken = findAppWindowToken(token); 4690 if (wtoken == null || wtoken.appToken == null) { 4691 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); 4692 return; 4693 } 4694 final long origId = Binder.clearCallingIdentity(); 4695 startAppFreezingScreenLocked(wtoken, configChanges); 4696 Binder.restoreCallingIdentity(origId); 4697 } 4698 } 4699 4700 public void stopAppFreezingScreen(IBinder token, boolean force) { 4701 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4702 "setAppFreezingScreen()")) { 4703 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4704 } 4705 4706 synchronized(mWindowMap) { 4707 AppWindowToken wtoken = findAppWindowToken(token); 4708 if (wtoken == null || wtoken.appToken == null) { 4709 return; 4710 } 4711 final long origId = Binder.clearCallingIdentity(); 4712 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token 4713 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen); 4714 unsetAppFreezingScreenLocked(wtoken, true, force); 4715 Binder.restoreCallingIdentity(origId); 4716 } 4717 } 4718 4719 public void removeAppToken(IBinder token) { 4720 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4721 "removeAppToken()")) { 4722 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4723 } 4724 4725 AppWindowToken wtoken = null; 4726 AppWindowToken startingToken = null; 4727 boolean delayed = false; 4728 4729 final long origId = Binder.clearCallingIdentity(); 4730 synchronized(mWindowMap) { 4731 WindowToken basewtoken = mTokenMap.remove(token); 4732 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { 4733 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); 4734 delayed = setTokenVisibilityLocked(wtoken, null, false, 4735 WindowManagerPolicy.TRANSIT_UNSET, true); 4736 wtoken.inPendingTransaction = false; 4737 mOpeningApps.remove(wtoken); 4738 wtoken.waitingToShow = false; 4739 if (mClosingApps.contains(wtoken)) { 4740 delayed = true; 4741 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 4742 mClosingApps.add(wtoken); 4743 wtoken.waitingToHide = true; 4744 delayed = true; 4745 } 4746 if (DEBUG_APP_TRANSITIONS) Slog.v( 4747 TAG, "Removing app " + wtoken + " delayed=" + delayed 4748 + " animation=" + wtoken.mAppAnimator.animation 4749 + " animating=" + wtoken.mAppAnimator.animating); 4750 if (delayed) { 4751 // set the token aside because it has an active animation to be finished 4752 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4753 "removeAppToken make exiting: " + wtoken); 4754 mExitingAppTokens.add(wtoken); 4755 } else { 4756 // Make sure there is no animation running on this token, 4757 // so any windows associated with it will be removed as 4758 // soon as their animations are complete 4759 wtoken.mAppAnimator.clearAnimation(); 4760 wtoken.mAppAnimator.animating = false; 4761 } 4762 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 4763 "removeAppToken: " + wtoken); 4764 mAppTokens.remove(wtoken); 4765 mAnimatingAppTokens.remove(wtoken); 4766 wtoken.removed = true; 4767 if (wtoken.startingData != null) { 4768 startingToken = wtoken; 4769 } 4770 unsetAppFreezingScreenLocked(wtoken, true, true); 4771 if (mFocusedApp == wtoken) { 4772 if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken); 4773 mFocusedApp = null; 4774 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 4775 mInputMonitor.setFocusedAppLw(null); 4776 } 4777 } else { 4778 Slog.w(TAG, "Attempted to remove non-existing app token: " + token); 4779 } 4780 4781 if (!delayed && wtoken != null) { 4782 wtoken.updateReportedVisibilityLocked(); 4783 } 4784 } 4785 Binder.restoreCallingIdentity(origId); 4786 4787 if (startingToken != null) { 4788 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting " 4789 + startingToken + ": app token removed"); 4790 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken); 4791 mH.sendMessage(m); 4792 } 4793 } 4794 4795 private boolean tmpRemoveAppWindowsLocked(WindowToken token) { 4796 final int NW = token.windows.size(); 4797 if (NW > 0) { 4798 mWindowsChanged = true; 4799 } 4800 for (int i=0; i<NW; i++) { 4801 WindowState win = token.windows.get(i); 4802 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); 4803 win.getWindowList().remove(win); 4804 int j = win.mChildWindows.size(); 4805 while (j > 0) { 4806 j--; 4807 WindowState cwin = win.mChildWindows.get(j); 4808 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 4809 "Tmp removing child window " + cwin); 4810 cwin.getWindowList().remove(cwin); 4811 } 4812 } 4813 return NW > 0; 4814 } 4815 4816 void dumpAppTokensLocked() { 4817 for (int i=mAppTokens.size()-1; i>=0; i--) { 4818 Slog.v(TAG, " #" + i + ": " + mAppTokens.get(i).token); 4819 } 4820 } 4821 4822 void dumpAnimatingAppTokensLocked() { 4823 for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) { 4824 Slog.v(TAG, " #" + i + ": " + mAnimatingAppTokens.get(i).token); 4825 } 4826 } 4827 4828 void dumpWindowsLocked() { 4829 int i = 0; 4830 final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR); 4831 while (iterator.hasNext()) { 4832 final WindowState w = iterator.next(); 4833 Slog.v(TAG, " #" + i++ + ": " + w); 4834 } 4835 } 4836 4837 private int findWindowOffsetLocked(WindowList windows, int tokenPos) { 4838 final int NW = windows.size(); 4839 4840 if (tokenPos >= mAnimatingAppTokens.size()) { 4841 int i = NW; 4842 while (i > 0) { 4843 i--; 4844 WindowState win = windows.get(i); 4845 if (win.getAppToken() != null) { 4846 return i+1; 4847 } 4848 } 4849 } 4850 4851 while (tokenPos > 0) { 4852 // Find the first app token below the new position that has 4853 // a window displayed. 4854 final AppWindowToken wtoken = mAppTokens.get(tokenPos-1); 4855 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ " 4856 + tokenPos + " -- " + wtoken.token); 4857 if (wtoken.sendingToBottom) { 4858 if (DEBUG_REORDER) Slog.v(TAG, 4859 "Skipping token -- currently sending to bottom"); 4860 tokenPos--; 4861 continue; 4862 } 4863 int i = wtoken.windows.size(); 4864 while (i > 0) { 4865 i--; 4866 WindowState win = wtoken.windows.get(i); 4867 int j = win.mChildWindows.size(); 4868 while (j > 0) { 4869 j--; 4870 WindowState cwin = win.mChildWindows.get(j); 4871 if (cwin.mSubLayer >= 0) { 4872 for (int pos=NW-1; pos>=0; pos--) { 4873 if (windows.get(pos) == cwin) { 4874 if (DEBUG_REORDER) Slog.v(TAG, 4875 "Found child win @" + (pos+1)); 4876 return pos+1; 4877 } 4878 } 4879 } 4880 } 4881 for (int pos=NW-1; pos>=0; pos--) { 4882 if (windows.get(pos) == win) { 4883 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1)); 4884 return pos+1; 4885 } 4886 } 4887 } 4888 tokenPos--; 4889 } 4890 4891 return 0; 4892 } 4893 4894 private final int reAddWindowLocked(int index, WindowState win) { 4895 final WindowList windows = win.getWindowList(); 4896 final int NCW = win.mChildWindows.size(); 4897 boolean added = false; 4898 for (int j=0; j<NCW; j++) { 4899 WindowState cwin = win.mChildWindows.get(j); 4900 if (!added && cwin.mSubLayer >= 0) { 4901 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " 4902 + index + ": " + cwin); 4903 win.mRebuilding = false; 4904 windows.add(index, win); 4905 index++; 4906 added = true; 4907 } 4908 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4909 + index + ": " + cwin); 4910 cwin.mRebuilding = false; 4911 windows.add(index, cwin); 4912 index++; 4913 } 4914 if (!added) { 4915 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " 4916 + index + ": " + win); 4917 win.mRebuilding = false; 4918 windows.add(index, win); 4919 index++; 4920 } 4921 mWindowsChanged = true; 4922 return index; 4923 } 4924 4925 private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index, 4926 WindowToken token) { 4927 final int NW = token.windows.size(); 4928 for (int i=0; i<NW; i++) { 4929 final WindowState win = token.windows.get(i); 4930 if (win.mDisplayContent == displayContent) { 4931 index = reAddWindowLocked(index, win); 4932 } 4933 } 4934 return index; 4935 } 4936 4937 public void moveAppToken(int index, IBinder token) { 4938 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 4939 "moveAppToken()")) { 4940 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 4941 } 4942 4943 synchronized(mWindowMap) { 4944 if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:"); 4945 if (DEBUG_REORDER) dumpAppTokensLocked(); 4946 final AppWindowToken wtoken = findAppWindowToken(token); 4947 final int oldIndex = mAppTokens.indexOf(wtoken); 4948 if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG, 4949 "Start moving token " + wtoken + " initially at " 4950 + oldIndex); 4951 if (oldIndex > index && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET 4952 && !mAppTransitionRunning) { 4953 // animation towards back has not started, copy old list for duration of animation. 4954 mAnimatingAppTokens.clear(); 4955 mAnimatingAppTokens.addAll(mAppTokens); 4956 } 4957 if (wtoken == null || !mAppTokens.remove(wtoken)) { 4958 Slog.w(TAG, "Attempting to reorder token that doesn't exist: " 4959 + token + " (" + wtoken + ")"); 4960 return; 4961 } 4962 mAppTokens.add(index, wtoken); 4963 if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":"); 4964 else if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "Moved " + token + " to " + index); 4965 if (DEBUG_REORDER) dumpAppTokensLocked(); 4966 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET && !mAppTransitionRunning) { 4967 // Not animating, bring animating app list in line with mAppTokens. 4968 mAnimatingAppTokens.clear(); 4969 mAnimatingAppTokens.addAll(mAppTokens); 4970 4971 // Bring window ordering, window focus and input window in line with new app token 4972 final long origId = Binder.clearCallingIdentity(); 4973 if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":"); 4974 if (DEBUG_REORDER) dumpWindowsLocked(); 4975 if (tmpRemoveAppWindowsLocked(wtoken)) { 4976 if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:"); 4977 if (DEBUG_REORDER) dumpWindowsLocked(); 4978 DisplayContentsIterator iterator = new DisplayContentsIterator(); 4979 while(iterator.hasNext()) { 4980 final DisplayContent displayContent = iterator.next(); 4981 final WindowList windows = displayContent.getWindowList(); 4982 final int pos = findWindowOffsetLocked(windows, index); 4983 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 4984 if (pos != newPos) { 4985 displayContent.layoutNeeded = true; 4986 } 4987 } 4988 if (DEBUG_REORDER) Slog.v(TAG, "Final window list:"); 4989 if (DEBUG_REORDER) dumpWindowsLocked(); 4990 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 4991 false /*updateInputWindows*/); 4992 mInputMonitor.setUpdateInputWindowsNeededLw(); 4993 performLayoutAndPlaceSurfacesLocked(); 4994 mInputMonitor.updateInputWindowsLw(false /*force*/); 4995 } 4996 Binder.restoreCallingIdentity(origId); 4997 } 4998 } 4999 } 5000 5001 private void removeAppTokensLocked(List<IBinder> tokens) { 5002 // XXX This should be done more efficiently! 5003 // (take advantage of the fact that both lists should be 5004 // ordered in the same way.) 5005 int N = tokens.size(); 5006 for (int i=0; i<N; i++) { 5007 IBinder token = tokens.get(i); 5008 final AppWindowToken wtoken = findAppWindowToken(token); 5009 if (DEBUG_REORDER || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 5010 "Temporarily removing " + wtoken + " from " + mAppTokens.indexOf(wtoken)); 5011 if (!mAppTokens.remove(wtoken)) { 5012 Slog.w(TAG, "Attempting to reorder token that doesn't exist: " 5013 + token + " (" + wtoken + ")"); 5014 i--; 5015 N--; 5016 } 5017 } 5018 } 5019 5020 private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos, 5021 boolean updateFocusAndLayout) { 5022 // First remove all of the windows from the list. 5023 tmpRemoveAppWindowsLocked(wtoken); 5024 5025 // And now add them back at the correct place. 5026 DisplayContentsIterator iterator = new DisplayContentsIterator(); 5027 while (iterator.hasNext()) { 5028 final DisplayContent displayContent = iterator.next(); 5029 final WindowList windows = displayContent.getWindowList(); 5030 final int pos = findWindowOffsetLocked(windows, tokenPos); 5031 final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); 5032 if (pos != newPos) { 5033 displayContent.layoutNeeded = true; 5034 } 5035 5036 if (updateFocusAndLayout && !updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 5037 false /*updateInputWindows*/)) { 5038 assignLayersLocked(windows); 5039 } 5040 } 5041 5042 if (updateFocusAndLayout) { 5043 mInputMonitor.setUpdateInputWindowsNeededLw(); 5044 5045 // Note that the above updateFocusedWindowLocked conditional used to sit here. 5046 5047 if (!mInLayout) { 5048 performLayoutAndPlaceSurfacesLocked(); 5049 } 5050 mInputMonitor.updateInputWindowsLw(false /*force*/); 5051 } 5052 } 5053 5054 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) { 5055 // First remove all of the windows from the list. 5056 final int N = tokens.size(); 5057 int i; 5058 for (i=0; i<N; i++) { 5059 WindowToken token = mTokenMap.get(tokens.get(i)); 5060 if (token != null) { 5061 tmpRemoveAppWindowsLocked(token); 5062 } 5063 } 5064 5065 // And now add them back at the correct place. 5066 DisplayContentsIterator iterator = new DisplayContentsIterator(); 5067 while (iterator.hasNext()) { 5068 final DisplayContent displayContent = iterator.next(); 5069 final WindowList windows = displayContent.getWindowList(); 5070 // Where to start adding? 5071 int pos = findWindowOffsetLocked(windows, tokenPos); 5072 for (i=0; i<N; i++) { 5073 WindowToken token = mTokenMap.get(tokens.get(i)); 5074 if (token != null) { 5075 final int newPos = reAddAppWindowsLocked(displayContent, pos, token); 5076 if (newPos != pos) { 5077 displayContent.layoutNeeded = true; 5078 } 5079 pos = newPos; 5080 } 5081 } 5082 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 5083 false /*updateInputWindows*/)) { 5084 assignLayersLocked(windows); 5085 } 5086 } 5087 5088 mInputMonitor.setUpdateInputWindowsNeededLw(); 5089 5090 // Note that the above updateFocusedWindowLocked used to sit here. 5091 5092 performLayoutAndPlaceSurfacesLocked(); 5093 mInputMonitor.updateInputWindowsLw(false /*force*/); 5094 5095 //dump(); 5096 } 5097 5098 public void moveAppTokensToTop(List<IBinder> tokens) { 5099 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 5100 "moveAppTokensToTop()")) { 5101 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 5102 } 5103 5104 final long origId = Binder.clearCallingIdentity(); 5105 synchronized(mWindowMap) { 5106 removeAppTokensLocked(tokens); 5107 final int N = tokens.size(); 5108 for (int i=0; i<N; i++) { 5109 AppWindowToken wt = findAppWindowToken(tokens.get(i)); 5110 if (wt != null) { 5111 if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG, 5112 "Adding next to top: " + wt); 5113 mAppTokens.add(wt); 5114 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 5115 wt.sendingToBottom = false; 5116 } 5117 } 5118 } 5119 5120 if (!mAppTransitionRunning) { 5121 mAnimatingAppTokens.clear(); 5122 mAnimatingAppTokens.addAll(mAppTokens); 5123 moveAppWindowsLocked(tokens, mAppTokens.size()); 5124 } 5125 } 5126 Binder.restoreCallingIdentity(origId); 5127 } 5128 5129 @Override 5130 public void moveAppTokensToBottom(List<IBinder> tokens) { 5131 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 5132 "moveAppTokensToBottom()")) { 5133 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 5134 } 5135 5136 final long origId = Binder.clearCallingIdentity(); 5137 synchronized(mWindowMap) { 5138 final int N = tokens.size(); 5139 if (N > 0 && !mAppTransitionRunning) { 5140 // animating towards back, hang onto old list for duration of animation. 5141 mAnimatingAppTokens.clear(); 5142 mAnimatingAppTokens.addAll(mAppTokens); 5143 } 5144 removeAppTokensLocked(tokens); 5145 int pos = 0; 5146 for (int i=0; i<N; i++) { 5147 AppWindowToken wt = findAppWindowToken(tokens.get(i)); 5148 if (wt != null) { 5149 if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 5150 "Adding next to bottom: " + wt + " at " + pos); 5151 mAppTokens.add(pos, wt); 5152 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 5153 wt.sendingToBottom = true; 5154 } 5155 pos++; 5156 } 5157 } 5158 5159 if (!mAppTransitionRunning) { 5160 mAnimatingAppTokens.clear(); 5161 mAnimatingAppTokens.addAll(mAppTokens); 5162 moveAppWindowsLocked(tokens, 0); 5163 } 5164 } 5165 Binder.restoreCallingIdentity(origId); 5166 } 5167 5168 // ------------------------------------------------------------- 5169 // Misc IWindowSession methods 5170 // ------------------------------------------------------------- 5171 5172 @Override 5173 public void startFreezingScreen(int exitAnim, int enterAnim) { 5174 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5175 "startFreezingScreen()")) { 5176 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5177 } 5178 5179 synchronized(mWindowMap) { 5180 if (!mClientFreezingScreen) { 5181 mClientFreezingScreen = true; 5182 final long origId = Binder.clearCallingIdentity(); 5183 try { 5184 startFreezingDisplayLocked(false, exitAnim, enterAnim); 5185 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 5186 mH.sendMessageDelayed(mH.obtainMessage(H.CLIENT_FREEZE_TIMEOUT), 5187 5000); 5188 } finally { 5189 Binder.restoreCallingIdentity(origId); 5190 } 5191 } 5192 } 5193 } 5194 5195 @Override 5196 public void stopFreezingScreen() { 5197 if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN, 5198 "stopFreezingScreen()")) { 5199 throw new SecurityException("Requires FREEZE_SCREEN permission"); 5200 } 5201 5202 synchronized(mWindowMap) { 5203 if (mClientFreezingScreen) { 5204 mClientFreezingScreen = false; 5205 final long origId = Binder.clearCallingIdentity(); 5206 try { 5207 stopFreezingDisplayLocked(); 5208 } finally { 5209 Binder.restoreCallingIdentity(origId); 5210 } 5211 } 5212 } 5213 } 5214 5215 @Override 5216 public void disableKeyguard(IBinder token, String tag) { 5217 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5218 != PackageManager.PERMISSION_GRANTED) { 5219 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5220 } 5221 5222 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5223 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag))); 5224 } 5225 5226 @Override 5227 public void reenableKeyguard(IBinder token) { 5228 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5229 != PackageManager.PERMISSION_GRANTED) { 5230 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5231 } 5232 5233 mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage( 5234 KeyguardDisableHandler.KEYGUARD_REENABLE, token)); 5235 } 5236 5237 /** 5238 * @see android.app.KeyguardManager#exitKeyguardSecurely 5239 */ 5240 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { 5241 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5242 != PackageManager.PERMISSION_GRANTED) { 5243 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5244 } 5245 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { 5246 public void onKeyguardExitResult(boolean success) { 5247 try { 5248 callback.onKeyguardExitResult(success); 5249 } catch (RemoteException e) { 5250 // Client has died, we don't care. 5251 } 5252 } 5253 }); 5254 } 5255 5256 public boolean inKeyguardRestrictedInputMode() { 5257 return mPolicy.inKeyguardRestrictedKeyInputMode(); 5258 } 5259 5260 public boolean isKeyguardLocked() { 5261 return mPolicy.isKeyguardLocked(); 5262 } 5263 5264 public boolean isKeyguardSecure() { 5265 return mPolicy.isKeyguardSecure(); 5266 } 5267 5268 public void dismissKeyguard() { 5269 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) 5270 != PackageManager.PERMISSION_GRANTED) { 5271 throw new SecurityException("Requires DISABLE_KEYGUARD permission"); 5272 } 5273 synchronized(mWindowMap) { 5274 mPolicy.dismissKeyguardLw(); 5275 } 5276 } 5277 5278 public void closeSystemDialogs(String reason) { 5279 synchronized(mWindowMap) { 5280 final AllWindowsIterator iterator = new AllWindowsIterator(); 5281 while (iterator.hasNext()) { 5282 final WindowState w = iterator.next(); 5283 if (w.mHasSurface) { 5284 try { 5285 w.mClient.closeSystemDialogs(reason); 5286 } catch (RemoteException e) { 5287 } 5288 } 5289 } 5290 } 5291 } 5292 5293 static float fixScale(float scale) { 5294 if (scale < 0) scale = 0; 5295 else if (scale > 20) scale = 20; 5296 return Math.abs(scale); 5297 } 5298 5299 public void setAnimationScale(int which, float scale) { 5300 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5301 "setAnimationScale()")) { 5302 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5303 } 5304 5305 if (scale < 0) scale = 0; 5306 else if (scale > 20) scale = 20; 5307 scale = Math.abs(scale); 5308 switch (which) { 5309 case 0: mWindowAnimationScale = fixScale(scale); break; 5310 case 1: mTransitionAnimationScale = fixScale(scale); break; 5311 case 2: mAnimatorDurationScale = fixScale(scale); break; 5312 } 5313 5314 // Persist setting 5315 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget(); 5316 } 5317 5318 public void setAnimationScales(float[] scales) { 5319 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, 5320 "setAnimationScale()")) { 5321 throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); 5322 } 5323 5324 if (scales != null) { 5325 if (scales.length >= 1) { 5326 mWindowAnimationScale = fixScale(scales[0]); 5327 } 5328 if (scales.length >= 2) { 5329 mTransitionAnimationScale = fixScale(scales[1]); 5330 } 5331 if (scales.length >= 3) { 5332 setAnimatorDurationScale(fixScale(scales[2])); 5333 } 5334 } 5335 5336 // Persist setting 5337 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget(); 5338 } 5339 5340 private void setAnimatorDurationScale(float scale) { 5341 mAnimatorDurationScale = scale; 5342 ValueAnimator.setDurationScale(scale); 5343 } 5344 5345 public float getAnimationScale(int which) { 5346 switch (which) { 5347 case 0: return mWindowAnimationScale; 5348 case 1: return mTransitionAnimationScale; 5349 case 2: return mAnimatorDurationScale; 5350 } 5351 return 0; 5352 } 5353 5354 public float[] getAnimationScales() { 5355 return new float[] { mWindowAnimationScale, mTransitionAnimationScale, 5356 mAnimatorDurationScale }; 5357 } 5358 5359 // Called by window manager policy. Not exposed externally. 5360 @Override 5361 public int getLidState() { 5362 int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, 5363 InputManagerService.SW_LID); 5364 if (sw > 0) { 5365 // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. 5366 return LID_CLOSED; 5367 } else if (sw == 0) { 5368 // Switch state: AKEY_STATE_UP. 5369 return LID_OPEN; 5370 } else { 5371 // Switch state: AKEY_STATE_UNKNOWN. 5372 return LID_ABSENT; 5373 } 5374 } 5375 5376 // Called by window manager policy. Not exposed externally. 5377 @Override 5378 public InputChannel monitorInput(String inputChannelName) { 5379 return mInputManager.monitorInput(inputChannelName); 5380 } 5381 5382 // Called by window manager policy. Not exposed externally. 5383 @Override 5384 public void switchKeyboardLayout(int deviceId, int direction) { 5385 mInputManager.switchKeyboardLayout(deviceId, direction); 5386 } 5387 5388 // Called by window manager policy. Not exposed externally. 5389 @Override 5390 public void shutdown(boolean confirm) { 5391 ShutdownThread.shutdown(mContext, confirm); 5392 } 5393 5394 // Called by window manager policy. Not exposed externally. 5395 @Override 5396 public void rebootSafeMode(boolean confirm) { 5397 ShutdownThread.rebootSafeMode(mContext, confirm); 5398 } 5399 5400 public void setInputFilter(IInputFilter filter) { 5401 if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) { 5402 throw new SecurityException("Requires FILTER_EVENTS permission"); 5403 } 5404 mInputManager.setInputFilter(filter); 5405 } 5406 5407 public void setCurrentUser(final int newUserId) { 5408 synchronized (mWindowMap) { 5409 mCurrentUserId = newUserId; 5410 mPolicy.setCurrentUserLw(newUserId); 5411 5412 // Hide windows that should not be seen by the new user. 5413 DisplayContentsIterator iterator = new DisplayContentsIterator(); 5414 while (iterator.hasNext()) { 5415 final WindowList windows = iterator.next().getWindowList(); 5416 for (int i = 0; i < windows.size(); i++) { 5417 final WindowState win = windows.get(i); 5418 if (win.isHiddenFromUserLocked()) { 5419 Slog.w(TAG, "current user violation " + newUserId + " hiding " 5420 + win + ", attrs=" + win.mAttrs.type + ", belonging to " 5421 + win.mOwnerUid); 5422 win.hideLw(false); 5423 } 5424 } 5425 } 5426 performLayoutAndPlaceSurfacesLocked(); 5427 } 5428 } 5429 5430 public void enableScreenAfterBoot() { 5431 synchronized(mWindowMap) { 5432 if (DEBUG_BOOT) { 5433 RuntimeException here = new RuntimeException("here"); 5434 here.fillInStackTrace(); 5435 Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled 5436 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5437 + " mShowingBootMessages=" + mShowingBootMessages 5438 + " mSystemBooted=" + mSystemBooted, here); 5439 } 5440 if (mSystemBooted) { 5441 return; 5442 } 5443 mSystemBooted = true; 5444 hideBootMessagesLocked(); 5445 // If the screen still doesn't come up after 30 seconds, give 5446 // up and turn it on. 5447 Message msg = mH.obtainMessage(H.BOOT_TIMEOUT); 5448 mH.sendMessageDelayed(msg, 30*1000); 5449 } 5450 5451 mPolicy.systemBooted(); 5452 5453 performEnableScreen(); 5454 } 5455 5456 void enableScreenIfNeededLocked() { 5457 if (DEBUG_BOOT) { 5458 RuntimeException here = new RuntimeException("here"); 5459 here.fillInStackTrace(); 5460 Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled 5461 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5462 + " mShowingBootMessages=" + mShowingBootMessages 5463 + " mSystemBooted=" + mSystemBooted, here); 5464 } 5465 if (mDisplayEnabled) { 5466 return; 5467 } 5468 if (!mSystemBooted && !mShowingBootMessages) { 5469 return; 5470 } 5471 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN)); 5472 } 5473 5474 public void performBootTimeout() { 5475 synchronized(mWindowMap) { 5476 if (mDisplayEnabled || mHeadless) { 5477 return; 5478 } 5479 Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); 5480 mForceDisplayEnabled = true; 5481 } 5482 performEnableScreen(); 5483 } 5484 5485 public void performEnableScreen() { 5486 synchronized(mWindowMap) { 5487 if (DEBUG_BOOT) { 5488 RuntimeException here = new RuntimeException("here"); 5489 here.fillInStackTrace(); 5490 Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled 5491 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5492 + " mShowingBootMessages=" + mShowingBootMessages 5493 + " mSystemBooted=" + mSystemBooted 5494 + " mOnlyCore=" + mOnlyCore, here); 5495 } 5496 if (mDisplayEnabled) { 5497 return; 5498 } 5499 if (!mSystemBooted && !mShowingBootMessages) { 5500 return; 5501 } 5502 5503 if (!mForceDisplayEnabled) { 5504 // Don't enable the screen until all existing windows 5505 // have been drawn. 5506 boolean haveBootMsg = false; 5507 boolean haveApp = false; 5508 // if the wallpaper service is disabled on the device, we're never going to have 5509 // wallpaper, don't bother waiting for it 5510 boolean haveWallpaper = false; 5511 boolean wallpaperEnabled = mContext.getResources().getBoolean( 5512 com.android.internal.R.bool.config_enableWallpaperService) 5513 && !mOnlyCore; 5514 boolean haveKeyguard = true; 5515 // TODO(multidisplay): Expand to all displays? 5516 final WindowList windows = getDefaultWindowListLocked(); 5517 final int N = windows.size(); 5518 for (int i=0; i<N; i++) { 5519 WindowState w = windows.get(i); 5520 if (w.mAttrs.type == TYPE_KEYGUARD) { 5521 // Only if there is a keyguard attached to the window manager 5522 // will we consider ourselves as having a keyguard. If it 5523 // isn't attached, we don't know if it wants to be shown or 5524 // hidden. If it is attached, we will say we have a keyguard 5525 // if the window doesn't want to be visible, because in that 5526 // case it explicitly doesn't want to be shown so we should 5527 // not delay turning the screen on for it. 5528 boolean vis = w.mViewVisibility == View.VISIBLE 5529 && w.mPolicyVisibility; 5530 haveKeyguard = !vis; 5531 } 5532 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 5533 return; 5534 } 5535 if (w.isDrawnLw()) { 5536 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 5537 haveBootMsg = true; 5538 } else if (w.mAttrs.type == TYPE_APPLICATION) { 5539 haveApp = true; 5540 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 5541 haveWallpaper = true; 5542 } else if (w.mAttrs.type == TYPE_KEYGUARD) { 5543 haveKeyguard = true; 5544 } 5545 } 5546 } 5547 5548 if (DEBUG_SCREEN_ON || DEBUG_BOOT) { 5549 Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages 5550 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 5551 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 5552 + " haveKeyguard=" + haveKeyguard); 5553 } 5554 5555 // If we are turning on the screen to show the boot message, 5556 // don't do it until the boot message is actually displayed. 5557 if (!mSystemBooted && !haveBootMsg) { 5558 return; 5559 } 5560 5561 // If we are turning on the screen after the boot is completed 5562 // normally, don't do so until we have the application and 5563 // wallpaper. 5564 if (mSystemBooted && ((!haveApp && !haveKeyguard) || 5565 (wallpaperEnabled && !haveWallpaper))) { 5566 return; 5567 } 5568 } 5569 5570 mDisplayEnabled = true; 5571 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); 5572 if (false) { 5573 StringWriter sw = new StringWriter(); 5574 PrintWriter pw = new PrintWriter(sw); 5575 this.dump(null, pw, null); 5576 Slog.i(TAG, sw.toString()); 5577 } 5578 try { 5579 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); 5580 if (surfaceFlinger != null) { 5581 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); 5582 Parcel data = Parcel.obtain(); 5583 data.writeInterfaceToken("android.ui.ISurfaceComposer"); 5584 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED 5585 data, null, 0); 5586 data.recycle(); 5587 } 5588 } catch (RemoteException ex) { 5589 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); 5590 } 5591 5592 // Enable input dispatch. 5593 mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); 5594 } 5595 5596 mPolicy.enableScreenAfterBoot(); 5597 5598 // Make sure the last requested orientation has been applied. 5599 updateRotationUnchecked(false, false); 5600 } 5601 5602 public void showBootMessage(final CharSequence msg, final boolean always) { 5603 boolean first = false; 5604 synchronized(mWindowMap) { 5605 if (DEBUG_BOOT) { 5606 RuntimeException here = new RuntimeException("here"); 5607 here.fillInStackTrace(); 5608 Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always 5609 + " mAllowBootMessages=" + mAllowBootMessages 5610 + " mShowingBootMessages=" + mShowingBootMessages 5611 + " mSystemBooted=" + mSystemBooted, here); 5612 } 5613 if (!mAllowBootMessages) { 5614 return; 5615 } 5616 if (!mShowingBootMessages) { 5617 if (!always) { 5618 return; 5619 } 5620 first = true; 5621 } 5622 if (mSystemBooted) { 5623 return; 5624 } 5625 mShowingBootMessages = true; 5626 mPolicy.showBootMessage(msg, always); 5627 } 5628 if (first) { 5629 performEnableScreen(); 5630 } 5631 } 5632 5633 public void hideBootMessagesLocked() { 5634 if (DEBUG_BOOT) { 5635 RuntimeException here = new RuntimeException("here"); 5636 here.fillInStackTrace(); 5637 Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled 5638 + " mForceDisplayEnabled=" + mForceDisplayEnabled 5639 + " mShowingBootMessages=" + mShowingBootMessages 5640 + " mSystemBooted=" + mSystemBooted, here); 5641 } 5642 if (mShowingBootMessages) { 5643 mShowingBootMessages = false; 5644 mPolicy.hideBootMessages(); 5645 } 5646 } 5647 5648 public void setInTouchMode(boolean mode) { 5649 synchronized(mWindowMap) { 5650 mInTouchMode = mode; 5651 } 5652 } 5653 5654 // TODO: more accounting of which pid(s) turned it on, keep count, 5655 // only allow disables from pids which have count on, etc. 5656 @Override 5657 public void showStrictModeViolation(boolean on) { 5658 if (mHeadless) return; 5659 int pid = Binder.getCallingPid(); 5660 mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid)); 5661 } 5662 5663 private void showStrictModeViolation(int arg, int pid) { 5664 final boolean on = arg != 0; 5665 synchronized(mWindowMap) { 5666 // Ignoring requests to enable the red border from clients 5667 // which aren't on screen. (e.g. Broadcast Receivers in 5668 // the background..) 5669 if (on) { 5670 boolean isVisible = false; 5671 final AllWindowsIterator iterator = new AllWindowsIterator(); 5672 while (iterator.hasNext()) { 5673 final WindowState ws = iterator.next(); 5674 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 5675 isVisible = true; 5676 break; 5677 } 5678 } 5679 if (!isVisible) { 5680 return; 5681 } 5682 } 5683 5684 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5685 ">>> OPEN TRANSACTION showStrictModeViolation"); 5686 Surface.openTransaction(); 5687 try { 5688 // TODO(multi-display): support multiple displays 5689 if (mStrictModeFlash == null) { 5690 mStrictModeFlash = new StrictModeFlash( 5691 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 5692 } 5693 mStrictModeFlash.setVisibility(on); 5694 } finally { 5695 Surface.closeTransaction(); 5696 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5697 "<<< CLOSE TRANSACTION showStrictModeViolation"); 5698 } 5699 } 5700 } 5701 5702 public void setStrictModeVisualIndicatorPreference(String value) { 5703 SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); 5704 } 5705 5706 /** 5707 * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. 5708 * In portrait mode, it grabs the upper region of the screen based on the vertical dimension 5709 * of the target image. 5710 * 5711 * @param displayId the Display to take a screenshot of. 5712 * @param width the width of the target bitmap 5713 * @param height the height of the target bitmap 5714 */ 5715 public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height) { 5716 if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, 5717 "screenshotApplications()")) { 5718 throw new SecurityException("Requires READ_FRAME_BUFFER permission"); 5719 } 5720 5721 Bitmap rawss; 5722 5723 int maxLayer = 0; 5724 final Rect frame = new Rect(); 5725 5726 float scale; 5727 int dw, dh; 5728 int rot; 5729 5730 synchronized(mWindowMap) { 5731 long ident = Binder.clearCallingIdentity(); 5732 5733 final DisplayContent displayContent = getDisplayContentLocked(displayId); 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 public void addDisplayContentChangeListener(int displayId, 6477 IDisplayContentChangeListener listener) { 6478 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 6479 "addDisplayContentChangeListener()")) { 6480 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission"); 6481 } 6482 synchronized(mWindowMap) { 6483 DisplayContent displayContent = getDisplayContentLocked(displayId); 6484 if (displayContent.mDisplayContentChangeListeners == null) { 6485 displayContent.mDisplayContentChangeListeners = 6486 new RemoteCallbackList<IDisplayContentChangeListener>(); 6487 displayContent.mDisplayContentChangeListeners.register(listener); 6488 } 6489 } 6490 } 6491 6492 public void removeDisplayContentChangeListener(int displayId, 6493 IDisplayContentChangeListener listener) { 6494 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 6495 "removeDisplayContentChangeListener()")) { 6496 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission"); 6497 } 6498 synchronized(mWindowMap) { 6499 DisplayContent displayContent = getDisplayContentLocked(displayId); 6500 if (displayContent.mDisplayContentChangeListeners != null) { 6501 displayContent.mDisplayContentChangeListeners.unregister(listener); 6502 if (displayContent.mDisplayContentChangeListeners 6503 .getRegisteredCallbackCount() == 0) { 6504 displayContent.mDisplayContentChangeListeners = null; 6505 } 6506 } 6507 } 6508 } 6509 6510 void scheduleNotifyWindowTranstionIfNeededLocked(WindowState window, int transition) { 6511 DisplayContent displayContent = window.mDisplayContent; 6512 if (displayContent.mDisplayContentChangeListeners != null) { 6513 WindowInfo info = getWindowInfoForWindowStateLocked(window); 6514 mH.obtainMessage(H.NOTIFY_WINDOW_TRANSITION, transition, 0, info).sendToTarget(); 6515 } 6516 } 6517 6518 private void handleNotifyWindowTranstion(int transition, WindowInfo info) { 6519 RemoteCallbackList<IDisplayContentChangeListener> callbacks = null; 6520 synchronized (mWindowMap) { 6521 DisplayContent displayContent = getDisplayContentLocked(info.displayId); 6522 if (displayContent == null) { 6523 return; 6524 } 6525 callbacks = displayContent.mDisplayContentChangeListeners; 6526 if (callbacks == null) { 6527 return; 6528 } 6529 } 6530 final int callbackCount = callbacks.beginBroadcast(); 6531 try { 6532 for (int i = 0; i < callbackCount; i++) { 6533 try { 6534 callbacks.getBroadcastItem(i).onWindowTransition(info.displayId, 6535 transition, info); 6536 } catch (RemoteException re) { 6537 /* ignore */ 6538 } 6539 } 6540 } finally { 6541 callbacks.finishBroadcast(); 6542 } 6543 } 6544 6545 private void scheduleNotifyRotationChangedIfNeededLocked(DisplayContent displayContent, 6546 int rotation) { 6547 if (displayContent.mDisplayContentChangeListeners != null 6548 && displayContent.mDisplayContentChangeListeners.getRegisteredCallbackCount() > 0) { 6549 mH.obtainMessage(H.NOTIFY_ROTATION_CHANGED, displayContent.getDisplayId(), 6550 rotation).sendToTarget(); 6551 } 6552 } 6553 6554 private void handleNotifyRotationChanged(int displayId, int rotation) { 6555 RemoteCallbackList<IDisplayContentChangeListener> callbacks = null; 6556 synchronized (mWindowMap) { 6557 DisplayContent displayContent = getDisplayContentLocked(displayId); 6558 if (displayContent == null) { 6559 return; 6560 } 6561 callbacks = displayContent.mDisplayContentChangeListeners; 6562 if (callbacks == null) { 6563 return; 6564 } 6565 } 6566 try { 6567 final int watcherCount = callbacks.beginBroadcast(); 6568 for (int i = 0; i < watcherCount; i++) { 6569 try { 6570 callbacks.getBroadcastItem(i).onRotationChanged(rotation); 6571 } catch (RemoteException re) { 6572 /* ignore */ 6573 } 6574 } 6575 } finally { 6576 callbacks.finishBroadcast(); 6577 } 6578 } 6579 6580 private void scheduleNotifyWindowLayersChangedIfNeededLocked(DisplayContent displayContent) { 6581 if (displayContent.mDisplayContentChangeListeners != null 6582 && displayContent.mDisplayContentChangeListeners.getRegisteredCallbackCount() > 0) { 6583 mH.obtainMessage(H.NOTIFY_WINDOW_LAYERS_CHANGED, displayContent) .sendToTarget(); 6584 } 6585 } 6586 6587 private void handleNotifyWindowLayersChanged(DisplayContent displayContent) { 6588 RemoteCallbackList<IDisplayContentChangeListener> callbacks = null; 6589 synchronized (mWindowMap) { 6590 callbacks = displayContent.mDisplayContentChangeListeners; 6591 if (callbacks == null) { 6592 return; 6593 } 6594 } 6595 try { 6596 final int watcherCount = callbacks.beginBroadcast(); 6597 for (int i = 0; i < watcherCount; i++) { 6598 try { 6599 callbacks.getBroadcastItem(i).onWindowLayersChanged( 6600 displayContent.getDisplayId()); 6601 } catch (RemoteException re) { 6602 /* ignore */ 6603 } 6604 } 6605 } finally { 6606 callbacks.finishBroadcast(); 6607 } 6608 } 6609 6610 public void addWindowChangeListener(WindowChangeListener listener) { 6611 synchronized(mWindowMap) { 6612 mWindowChangeListeners.add(listener); 6613 } 6614 } 6615 6616 public void removeWindowChangeListener(WindowChangeListener listener) { 6617 synchronized(mWindowMap) { 6618 mWindowChangeListeners.remove(listener); 6619 } 6620 } 6621 6622 private void notifyWindowsChanged() { 6623 WindowChangeListener[] windowChangeListeners; 6624 synchronized(mWindowMap) { 6625 if(mWindowChangeListeners.isEmpty()) { 6626 return; 6627 } 6628 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6629 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6630 } 6631 int N = windowChangeListeners.length; 6632 for(int i = 0; i < N; i++) { 6633 windowChangeListeners[i].windowsChanged(); 6634 } 6635 } 6636 6637 private void notifyFocusChanged() { 6638 WindowChangeListener[] windowChangeListeners; 6639 synchronized(mWindowMap) { 6640 if(mWindowChangeListeners.isEmpty()) { 6641 return; 6642 } 6643 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6644 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6645 } 6646 int N = windowChangeListeners.length; 6647 for(int i = 0; i < N; i++) { 6648 windowChangeListeners[i].focusChanged(); 6649 } 6650 } 6651 6652 private WindowState findWindow(int hashCode) { 6653 if (hashCode == -1) { 6654 // TODO(multidisplay): Extend to multiple displays. 6655 return getFocusedWindow(); 6656 } 6657 6658 synchronized (mWindowMap) { 6659 final AllWindowsIterator iterator = new AllWindowsIterator(); 6660 while (iterator.hasNext()) { 6661 final WindowState w = iterator.next(); 6662 if (System.identityHashCode(w) == hashCode) { 6663 return w; 6664 } 6665 } 6666 } 6667 6668 return null; 6669 } 6670 6671 /* 6672 * Instruct the Activity Manager to fetch the current configuration and broadcast 6673 * that to config-changed listeners if appropriate. 6674 */ 6675 void sendNewConfiguration() { 6676 try { 6677 mActivityManager.updateConfiguration(null); 6678 } catch (RemoteException e) { 6679 } 6680 } 6681 6682 public Configuration computeNewConfiguration() { 6683 synchronized (mWindowMap) { 6684 Configuration config = computeNewConfigurationLocked(); 6685 if (config == null && mWaitingForConfig) { 6686 // Nothing changed but we are waiting for something... stop that! 6687 mWaitingForConfig = false; 6688 performLayoutAndPlaceSurfacesLocked(); 6689 } 6690 return config; 6691 } 6692 } 6693 6694 Configuration computeNewConfigurationLocked() { 6695 Configuration config = new Configuration(); 6696 config.fontScale = 0; 6697 if (!computeScreenConfigurationLocked(config)) { 6698 return null; 6699 } 6700 return config; 6701 } 6702 6703 private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { 6704 // TODO: Multidisplay: for now only use with default display. 6705 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6706 if (width < displayInfo.smallestNominalAppWidth) { 6707 displayInfo.smallestNominalAppWidth = width; 6708 } 6709 if (width > displayInfo.largestNominalAppWidth) { 6710 displayInfo.largestNominalAppWidth = width; 6711 } 6712 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6713 if (height < displayInfo.smallestNominalAppHeight) { 6714 displayInfo.smallestNominalAppHeight = height; 6715 } 6716 if (height > displayInfo.largestNominalAppHeight) { 6717 displayInfo.largestNominalAppHeight = height; 6718 } 6719 } 6720 6721 private int reduceConfigLayout(int curLayout, int rotation, float density, 6722 int dw, int dh) { 6723 // TODO: Multidisplay: for now only use with default display. 6724 // Get the app screen size at this rotation. 6725 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6726 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6727 6728 // Compute the screen layout size class for this rotation. 6729 int longSize = w; 6730 int shortSize = h; 6731 if (longSize < shortSize) { 6732 int tmp = longSize; 6733 longSize = shortSize; 6734 shortSize = tmp; 6735 } 6736 longSize = (int)(longSize/density); 6737 shortSize = (int)(shortSize/density); 6738 return Configuration.reduceScreenLayout(curLayout, longSize, shortSize); 6739 } 6740 6741 private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated, 6742 int dw, int dh, float density, Configuration outConfig) { 6743 // TODO: Multidisplay: for now only use with default display. 6744 6745 // We need to determine the smallest width that will occur under normal 6746 // operation. To this, start with the base screen size and compute the 6747 // width under the different possible rotations. We need to un-rotate 6748 // the current screen dimensions before doing this. 6749 int unrotDw, unrotDh; 6750 if (rotated) { 6751 unrotDw = dh; 6752 unrotDh = dw; 6753 } else { 6754 unrotDw = dw; 6755 unrotDh = dh; 6756 } 6757 displayInfo.smallestNominalAppWidth = 1<<30; 6758 displayInfo.smallestNominalAppHeight = 1<<30; 6759 displayInfo.largestNominalAppWidth = 0; 6760 displayInfo.largestNominalAppHeight = 0; 6761 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh); 6762 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw); 6763 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh); 6764 adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw); 6765 int sl = Configuration.resetScreenLayout(outConfig.screenLayout); 6766 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6767 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6768 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6769 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6770 outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); 6771 outConfig.screenLayout = sl; 6772 } 6773 6774 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6775 int dw, int dh) { 6776 // TODO: Multidisplay: for now only use with default display. 6777 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6778 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6779 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6780 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6781 if (curSize == 0 || size < curSize) { 6782 curSize = size; 6783 } 6784 return curSize; 6785 } 6786 6787 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6788 // TODO: Multidisplay: for now only use with default display. 6789 mTmpDisplayMetrics.setTo(dm); 6790 final DisplayMetrics tmpDm = mTmpDisplayMetrics; 6791 final int unrotDw, unrotDh; 6792 if (rotated) { 6793 unrotDw = dh; 6794 unrotDh = dw; 6795 } else { 6796 unrotDw = dw; 6797 unrotDh = dh; 6798 } 6799 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh); 6800 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw); 6801 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh); 6802 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw); 6803 return sw; 6804 } 6805 6806 boolean computeScreenConfigurationLocked(Configuration config) { 6807 if (!mDisplayReady) { 6808 return false; 6809 } 6810 6811 // TODO(multidisplay): For now, apply Configuration to main screen only. 6812 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 6813 6814 // Use the effective "visual" dimensions based on current rotation 6815 final boolean rotated = (mRotation == Surface.ROTATION_90 6816 || mRotation == Surface.ROTATION_270); 6817 final int realdw = rotated ? 6818 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6819 final int realdh = rotated ? 6820 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6821 int dw = realdw; 6822 int dh = realdh; 6823 6824 if (mAltOrientation) { 6825 if (realdw > realdh) { 6826 // Turn landscape into portrait. 6827 int maxw = (int)(realdh/1.3f); 6828 if (maxw < realdw) { 6829 dw = maxw; 6830 } 6831 } else { 6832 // Turn portrait into landscape. 6833 int maxh = (int)(realdw/1.3f); 6834 if (maxh < realdh) { 6835 dh = maxh; 6836 } 6837 } 6838 } 6839 6840 if (config != null) { 6841 config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : 6842 Configuration.ORIENTATION_LANDSCAPE; 6843 } 6844 6845 // Update application display metrics. 6846 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6847 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6848 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6849 synchronized(displayContent.mDisplaySizeLock) { 6850 displayInfo.rotation = mRotation; 6851 displayInfo.logicalWidth = dw; 6852 displayInfo.logicalHeight = dh; 6853 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6854 displayInfo.appWidth = appWidth; 6855 displayInfo.appHeight = appHeight; 6856 displayInfo.getLogicalMetrics(mRealDisplayMetrics, null); 6857 displayInfo.getAppMetrics(mDisplayMetrics, null); 6858 mDisplayManagerService.setDisplayInfoOverrideFromWindowManager( 6859 displayContent.getDisplayId(), displayInfo); 6860 6861 mAnimator.setDisplayDimensions(dw, dh, appWidth, appHeight); 6862 } 6863 if (false) { 6864 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6865 } 6866 6867 final DisplayMetrics dm = mDisplayMetrics; 6868 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6869 mCompatDisplayMetrics); 6870 6871 if (config != null) { 6872 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6873 / dm.density); 6874 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6875 / dm.density); 6876 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6877 6878 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6879 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6880 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6881 config.densityDpi = displayContent.mBaseDisplayDensity; 6882 6883 // Update the configuration based on available input devices, lid switch, 6884 // and platform configuration. 6885 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6886 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6887 config.navigation = Configuration.NAVIGATION_NONAV; 6888 6889 int keyboardPresence = 0; 6890 int navigationPresence = 0; 6891 final InputDevice[] devices = mInputManager.getInputDevices(); 6892 final int len = devices.length; 6893 for (int i = 0; i < len; i++) { 6894 InputDevice device = devices[i]; 6895 if (!device.isVirtual()) { 6896 final int sources = device.getSources(); 6897 final int presenceFlag = device.isExternal() ? 6898 WindowManagerPolicy.PRESENCE_EXTERNAL : 6899 WindowManagerPolicy.PRESENCE_INTERNAL; 6900 6901 if (mIsTouchDevice) { 6902 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6903 InputDevice.SOURCE_TOUCHSCREEN) { 6904 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6905 } 6906 } else { 6907 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6908 } 6909 6910 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6911 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6912 navigationPresence |= presenceFlag; 6913 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6914 && config.navigation == Configuration.NAVIGATION_NONAV) { 6915 config.navigation = Configuration.NAVIGATION_DPAD; 6916 navigationPresence |= presenceFlag; 6917 } 6918 6919 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6920 config.keyboard = Configuration.KEYBOARD_QWERTY; 6921 keyboardPresence |= presenceFlag; 6922 } 6923 } 6924 } 6925 6926 // Determine whether a hard keyboard is available and enabled. 6927 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6928 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6929 mHardKeyboardAvailable = hardKeyboardAvailable; 6930 mHardKeyboardEnabled = hardKeyboardAvailable; 6931 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6932 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6933 } 6934 if (!mHardKeyboardEnabled) { 6935 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6936 } 6937 6938 // Let the policy update hidden states. 6939 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6940 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6941 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6942 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6943 } 6944 6945 return true; 6946 } 6947 6948 public boolean isHardKeyboardAvailable() { 6949 synchronized (mWindowMap) { 6950 return mHardKeyboardAvailable; 6951 } 6952 } 6953 6954 public boolean isHardKeyboardEnabled() { 6955 synchronized (mWindowMap) { 6956 return mHardKeyboardEnabled; 6957 } 6958 } 6959 6960 public void setHardKeyboardEnabled(boolean enabled) { 6961 synchronized (mWindowMap) { 6962 if (mHardKeyboardEnabled != enabled) { 6963 mHardKeyboardEnabled = enabled; 6964 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6965 } 6966 } 6967 } 6968 6969 public void setOnHardKeyboardStatusChangeListener( 6970 OnHardKeyboardStatusChangeListener listener) { 6971 synchronized (mWindowMap) { 6972 mHardKeyboardStatusChangeListener = listener; 6973 } 6974 } 6975 6976 void notifyHardKeyboardStatusChange() { 6977 final boolean available, enabled; 6978 final OnHardKeyboardStatusChangeListener listener; 6979 synchronized (mWindowMap) { 6980 listener = mHardKeyboardStatusChangeListener; 6981 available = mHardKeyboardAvailable; 6982 enabled = mHardKeyboardEnabled; 6983 } 6984 if (listener != null) { 6985 listener.onHardKeyboardStatusChange(available, enabled); 6986 } 6987 } 6988 6989 // ------------------------------------------------------------- 6990 // Drag and drop 6991 // ------------------------------------------------------------- 6992 6993 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6994 int flags, int width, int height, Surface outSurface) { 6995 if (DEBUG_DRAG) { 6996 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6997 + " flags=" + Integer.toHexString(flags) + " win=" + window 6998 + " asbinder=" + window.asBinder()); 6999 } 7000 7001 final int callerPid = Binder.getCallingPid(); 7002 final long origId = Binder.clearCallingIdentity(); 7003 IBinder token = null; 7004 7005 try { 7006 synchronized (mWindowMap) { 7007 try { 7008 if (mDragState == null) { 7009 // TODO(multi-display): support other displays 7010 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7011 final Display display = displayContent.getDisplay(); 7012 Surface surface = new Surface(session, "drag surface", 7013 width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN); 7014 surface.setLayerStack(display.getLayerStack()); 7015 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 7016 + surface + ": CREATE"); 7017 outSurface.copyFrom(surface); 7018 final IBinder winBinder = window.asBinder(); 7019 token = new Binder(); 7020 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 7021 token = mDragState.mToken = new Binder(); 7022 7023 // 5 second timeout for this window to actually begin the drag 7024 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 7025 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 7026 mH.sendMessageDelayed(msg, 5000); 7027 } else { 7028 Slog.w(TAG, "Drag already in progress"); 7029 } 7030 } catch (Surface.OutOfResourcesException e) { 7031 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 7032 if (mDragState != null) { 7033 mDragState.reset(); 7034 mDragState = null; 7035 } 7036 } 7037 } 7038 } finally { 7039 Binder.restoreCallingIdentity(origId); 7040 } 7041 7042 return token; 7043 } 7044 7045 // ------------------------------------------------------------- 7046 // Input Events and Focus Management 7047 // ------------------------------------------------------------- 7048 7049 final InputMonitor mInputMonitor = new InputMonitor(this); 7050 private boolean mEventDispatchingEnabled; 7051 7052 public void pauseKeyDispatching(IBinder _token) { 7053 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7054 "pauseKeyDispatching()")) { 7055 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7056 } 7057 7058 synchronized (mWindowMap) { 7059 WindowToken token = mTokenMap.get(_token); 7060 if (token != null) { 7061 mInputMonitor.pauseDispatchingLw(token); 7062 } 7063 } 7064 } 7065 7066 public void resumeKeyDispatching(IBinder _token) { 7067 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7068 "resumeKeyDispatching()")) { 7069 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7070 } 7071 7072 synchronized (mWindowMap) { 7073 WindowToken token = mTokenMap.get(_token); 7074 if (token != null) { 7075 mInputMonitor.resumeDispatchingLw(token); 7076 } 7077 } 7078 } 7079 7080 public void setEventDispatching(boolean enabled) { 7081 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 7082 "setEventDispatching()")) { 7083 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 7084 } 7085 7086 synchronized (mWindowMap) { 7087 mEventDispatchingEnabled = enabled; 7088 if (mDisplayEnabled) { 7089 mInputMonitor.setEventDispatchingLw(enabled); 7090 } 7091 sendScreenStatusToClientsLocked(); 7092 } 7093 } 7094 7095 public IBinder getFocusedWindowToken() { 7096 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 7097 "getFocusedWindowToken()")) { 7098 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 7099 } 7100 synchronized (mWindowMap) { 7101 WindowState windowState = getFocusedWindowLocked(); 7102 if (windowState != null) { 7103 return windowState.mClient.asBinder(); 7104 } 7105 return null; 7106 } 7107 } 7108 7109 private WindowState getFocusedWindow() { 7110 synchronized (mWindowMap) { 7111 return getFocusedWindowLocked(); 7112 } 7113 } 7114 7115 private WindowState getFocusedWindowLocked() { 7116 return mCurrentFocus; 7117 } 7118 7119 public boolean detectSafeMode() { 7120 if (!mInputMonitor.waitForInputDevicesReady( 7121 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 7122 Slog.w(TAG, "Devices still not ready after waiting " 7123 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 7124 + " milliseconds before attempting to detect safe mode."); 7125 } 7126 7127 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7128 KeyEvent.KEYCODE_MENU); 7129 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 7130 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 7131 KeyEvent.KEYCODE_DPAD_CENTER); 7132 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 7133 InputManagerService.BTN_MOUSE); 7134 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 7135 KeyEvent.KEYCODE_VOLUME_DOWN); 7136 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 7137 || volumeDownState > 0; 7138 try { 7139 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 7140 mSafeMode = true; 7141 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 7142 } 7143 } catch (IllegalArgumentException e) { 7144 } 7145 if (mSafeMode) { 7146 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 7147 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 7148 } else { 7149 Log.i(TAG, "SAFE MODE not enabled"); 7150 } 7151 mPolicy.setSafeMode(mSafeMode); 7152 return mSafeMode; 7153 } 7154 7155 public void displayReady() { 7156 displayReady(Display.DEFAULT_DISPLAY); 7157 7158 synchronized(mWindowMap) { 7159 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 7160 final Display display = displayContent.getDisplay(); 7161 readForcedDisplaySizeAndDensityLocked(displayContent); 7162 7163 mDisplayReady = true; 7164 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 7165 PackageManager.FEATURE_TOUCHSCREEN); 7166 7167 final DisplayInfo displayInfo = getDefaultDisplayInfoLocked(); 7168 mAnimator.setDisplayDimensions( 7169 displayInfo.logicalWidth, displayInfo.logicalHeight, 7170 displayInfo.appWidth, displayInfo.appHeight); 7171 7172 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 7173 displayContent.mInitialDisplayWidth, 7174 displayContent.mInitialDisplayHeight, 7175 displayContent.mInitialDisplayDensity); 7176 } 7177 7178 try { 7179 mActivityManager.updateConfiguration(null); 7180 } catch (RemoteException e) { 7181 } 7182 } 7183 7184 public void displayReady(int displayId) { 7185 synchronized(mWindowMap) { 7186 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7187 final DisplayInfo displayInfo; 7188 mAnimator.addDisplayLocked(displayId); 7189 synchronized(displayContent.mDisplaySizeLock) { 7190 // Bootstrap the default logical display from the display manager. 7191 displayInfo = displayContent.getDisplayInfo(); 7192 DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId); 7193 if (newDisplayInfo != null) { 7194 displayInfo.copyFrom(newDisplayInfo); 7195 } 7196 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 7197 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 7198 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 7199 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 7200 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 7201 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 7202 } 7203 } 7204 } 7205 7206 public void systemReady() { 7207 mPolicy.systemReady(); 7208 } 7209 7210 // TODO(multidisplay): Call isScreenOn for each display. 7211 private void sendScreenStatusToClientsLocked() { 7212 final boolean on = mPowerManager.isScreenOn(); 7213 final AllWindowsIterator iterator = new AllWindowsIterator(); 7214 while (iterator.hasNext()) { 7215 try { 7216 iterator.next().mClient.dispatchScreenState(on); 7217 } catch (RemoteException e) { 7218 // Ignored 7219 } 7220 } 7221 } 7222 7223 // ------------------------------------------------------------- 7224 // Async Handler 7225 // ------------------------------------------------------------- 7226 7227 final class H extends Handler { 7228 public static final int REPORT_FOCUS_CHANGE = 2; 7229 public static final int REPORT_LOSING_FOCUS = 3; 7230 public static final int DO_TRAVERSAL = 4; 7231 public static final int ADD_STARTING = 5; 7232 public static final int REMOVE_STARTING = 6; 7233 public static final int FINISHED_STARTING = 7; 7234 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 7235 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 7236 public static final int WINDOW_FREEZE_TIMEOUT = 11; 7237 7238 public static final int APP_TRANSITION_TIMEOUT = 13; 7239 public static final int PERSIST_ANIMATION_SCALE = 14; 7240 public static final int FORCE_GC = 15; 7241 public static final int ENABLE_SCREEN = 16; 7242 public static final int APP_FREEZE_TIMEOUT = 17; 7243 public static final int SEND_NEW_CONFIGURATION = 18; 7244 public static final int REPORT_WINDOWS_CHANGE = 19; 7245 public static final int DRAG_START_TIMEOUT = 20; 7246 public static final int DRAG_END_TIMEOUT = 21; 7247 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 7248 public static final int BOOT_TIMEOUT = 23; 7249 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 7250 public static final int UPDATE_ANIM_PARAMETERS = 25; 7251 public static final int SHOW_STRICT_MODE_VIOLATION = 26; 7252 public static final int DO_ANIMATION_CALLBACK = 27; 7253 public static final int NOTIFY_ROTATION_CHANGED = 28; 7254 public static final int NOTIFY_WINDOW_TRANSITION = 29; 7255 public static final int NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 30; 7256 public static final int NOTIFY_WINDOW_LAYERS_CHANGED = 31; 7257 7258 public static final int DO_DISPLAY_ADDED = 32; 7259 public static final int DO_DISPLAY_REMOVED = 33; 7260 public static final int DO_DISPLAY_CHANGED = 34; 7261 7262 public static final int CLIENT_FREEZE_TIMEOUT = 35; 7263 7264 public static final int ANIMATOR_WHAT_OFFSET = 100000; 7265 public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1; 7266 public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 2; 7267 7268 public H() { 7269 } 7270 7271 @Override 7272 public void handleMessage(Message msg) { 7273 if (DEBUG_WINDOW_TRACE) { 7274 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 7275 } 7276 switch (msg.what) { 7277 case REPORT_FOCUS_CHANGE: { 7278 WindowState lastFocus; 7279 WindowState newFocus; 7280 7281 synchronized(mWindowMap) { 7282 lastFocus = mLastFocus; 7283 newFocus = mCurrentFocus; 7284 if (lastFocus == newFocus) { 7285 // Focus is not changing, so nothing to do. 7286 return; 7287 } 7288 mLastFocus = newFocus; 7289 //Slog.i(TAG, "Focus moving from " + lastFocus 7290 // + " to " + newFocus); 7291 if (newFocus != null && lastFocus != null 7292 && !newFocus.isDisplayedLw()) { 7293 //Slog.i(TAG, "Delaying loss of focus..."); 7294 mLosingFocus.add(lastFocus); 7295 lastFocus = null; 7296 } 7297 } 7298 7299 if (lastFocus != newFocus) { 7300 //System.out.println("Changing focus from " + lastFocus 7301 // + " to " + newFocus); 7302 if (newFocus != null) { 7303 try { 7304 //Slog.i(TAG, "Gaining focus: " + newFocus); 7305 newFocus.mClient.windowFocusChanged(true, mInTouchMode); 7306 } catch (RemoteException e) { 7307 // Ignore if process has died. 7308 } 7309 notifyFocusChanged(); 7310 } 7311 7312 if (lastFocus != null) { 7313 try { 7314 //Slog.i(TAG, "Losing focus: " + lastFocus); 7315 lastFocus.mClient.windowFocusChanged(false, mInTouchMode); 7316 } catch (RemoteException e) { 7317 // Ignore if process has died. 7318 } 7319 } 7320 } 7321 } break; 7322 7323 case REPORT_LOSING_FOCUS: { 7324 ArrayList<WindowState> losers; 7325 7326 synchronized(mWindowMap) { 7327 losers = mLosingFocus; 7328 mLosingFocus = new ArrayList<WindowState>(); 7329 } 7330 7331 final int N = losers.size(); 7332 for (int i=0; i<N; i++) { 7333 try { 7334 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i)); 7335 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode); 7336 } catch (RemoteException e) { 7337 // Ignore if process has died. 7338 } 7339 } 7340 } break; 7341 7342 case DO_TRAVERSAL: { 7343 synchronized(mWindowMap) { 7344 mTraversalScheduled = false; 7345 performLayoutAndPlaceSurfacesLocked(); 7346 } 7347 } break; 7348 7349 case ADD_STARTING: { 7350 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7351 final StartingData sd = wtoken.startingData; 7352 7353 if (sd == null) { 7354 // Animation has been canceled... do nothing. 7355 return; 7356 } 7357 7358 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 7359 + wtoken + ": pkg=" + sd.pkg); 7360 7361 View view = null; 7362 try { 7363 view = mPolicy.addStartingWindow( 7364 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 7365 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags); 7366 } catch (Exception e) { 7367 Slog.w(TAG, "Exception when adding starting window", e); 7368 } 7369 7370 if (view != null) { 7371 boolean abort = false; 7372 7373 synchronized(mWindowMap) { 7374 if (wtoken.removed || wtoken.startingData == null) { 7375 // If the window was successfully added, then 7376 // we need to remove it. 7377 if (wtoken.startingWindow != null) { 7378 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7379 "Aborted starting " + wtoken 7380 + ": removed=" + wtoken.removed 7381 + " startingData=" + wtoken.startingData); 7382 wtoken.startingWindow = null; 7383 wtoken.startingData = null; 7384 abort = true; 7385 } 7386 } else { 7387 wtoken.startingView = view; 7388 } 7389 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7390 "Added starting " + wtoken 7391 + ": startingWindow=" 7392 + wtoken.startingWindow + " startingView=" 7393 + wtoken.startingView); 7394 } 7395 7396 if (abort) { 7397 try { 7398 mPolicy.removeStartingWindow(wtoken.token, view); 7399 } catch (Exception e) { 7400 Slog.w(TAG, "Exception when removing starting window", e); 7401 } 7402 } 7403 } 7404 } break; 7405 7406 case REMOVE_STARTING: { 7407 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7408 IBinder token = null; 7409 View view = null; 7410 synchronized (mWindowMap) { 7411 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7412 + wtoken + ": startingWindow=" 7413 + wtoken.startingWindow + " startingView=" 7414 + wtoken.startingView); 7415 if (wtoken.startingWindow != null) { 7416 view = wtoken.startingView; 7417 token = wtoken.token; 7418 wtoken.startingData = null; 7419 wtoken.startingView = null; 7420 wtoken.startingWindow = null; 7421 wtoken.startingDisplayed = false; 7422 } 7423 } 7424 if (view != null) { 7425 try { 7426 mPolicy.removeStartingWindow(token, view); 7427 } catch (Exception e) { 7428 Slog.w(TAG, "Exception when removing starting window", e); 7429 } 7430 } 7431 } break; 7432 7433 case FINISHED_STARTING: { 7434 IBinder token = null; 7435 View view = null; 7436 while (true) { 7437 synchronized (mWindowMap) { 7438 final int N = mFinishedStarting.size(); 7439 if (N <= 0) { 7440 break; 7441 } 7442 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7443 7444 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7445 "Finished starting " + wtoken 7446 + ": startingWindow=" + wtoken.startingWindow 7447 + " startingView=" + wtoken.startingView); 7448 7449 if (wtoken.startingWindow == null) { 7450 continue; 7451 } 7452 7453 view = wtoken.startingView; 7454 token = wtoken.token; 7455 wtoken.startingData = null; 7456 wtoken.startingView = null; 7457 wtoken.startingWindow = null; 7458 wtoken.startingDisplayed = false; 7459 } 7460 7461 try { 7462 mPolicy.removeStartingWindow(token, view); 7463 } catch (Exception e) { 7464 Slog.w(TAG, "Exception when removing starting window", e); 7465 } 7466 } 7467 } break; 7468 7469 case REPORT_APPLICATION_TOKEN_DRAWN: { 7470 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7471 7472 try { 7473 if (DEBUG_VISIBILITY) Slog.v( 7474 TAG, "Reporting drawn in " + wtoken); 7475 wtoken.appToken.windowsDrawn(); 7476 } catch (RemoteException ex) { 7477 } 7478 } break; 7479 7480 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7481 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7482 7483 boolean nowVisible = msg.arg1 != 0; 7484 boolean nowGone = msg.arg2 != 0; 7485 7486 try { 7487 if (DEBUG_VISIBILITY) Slog.v( 7488 TAG, "Reporting visible in " + wtoken 7489 + " visible=" + nowVisible 7490 + " gone=" + nowGone); 7491 if (nowVisible) { 7492 wtoken.appToken.windowsVisible(); 7493 } else { 7494 wtoken.appToken.windowsGone(); 7495 } 7496 } catch (RemoteException ex) { 7497 } 7498 } break; 7499 7500 case WINDOW_FREEZE_TIMEOUT: { 7501 // TODO(multidisplay): Can non-default displays rotate? 7502 synchronized (mWindowMap) { 7503 Slog.w(TAG, "Window freeze timeout expired."); 7504 final WindowList windows = getDefaultWindowListLocked(); 7505 int i = windows.size(); 7506 while (i > 0) { 7507 i--; 7508 WindowState w = windows.get(i); 7509 if (w.mOrientationChanging) { 7510 w.mOrientationChanging = false; 7511 Slog.w(TAG, "Force clearing orientation change: " + w); 7512 } 7513 } 7514 performLayoutAndPlaceSurfacesLocked(); 7515 } 7516 break; 7517 } 7518 7519 case APP_TRANSITION_TIMEOUT: { 7520 synchronized (mWindowMap) { 7521 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 7522 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7523 "*** APP TRANSITION TIMEOUT"); 7524 mAppTransitionReady = true; 7525 mAppTransitionTimeout = true; 7526 mAnimatingAppTokens.clear(); 7527 mAnimatingAppTokens.addAll(mAppTokens); 7528 performLayoutAndPlaceSurfacesLocked(); 7529 } 7530 } 7531 break; 7532 } 7533 7534 case PERSIST_ANIMATION_SCALE: { 7535 Settings.Global.putFloat(mContext.getContentResolver(), 7536 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 7537 Settings.Global.putFloat(mContext.getContentResolver(), 7538 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 7539 Settings.Global.putFloat(mContext.getContentResolver(), 7540 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 7541 break; 7542 } 7543 7544 case FORCE_GC: { 7545 synchronized (mWindowMap) { 7546 synchronized (mAnimator) { 7547 // Since we're holding both mWindowMap and mAnimator we don't need to 7548 // hold mAnimator.mLayoutToAnim. 7549 if (mAnimator.mAnimating || mLayoutToAnim.mAnimationScheduled) { 7550 // If we are animating, don't do the gc now but 7551 // delay a bit so we don't interrupt the animation. 7552 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 7553 2000); 7554 return; 7555 } 7556 // If we are currently rotating the display, it will 7557 // schedule a new message when done. 7558 if (mDisplayFrozen) { 7559 return; 7560 } 7561 } 7562 } 7563 Runtime.getRuntime().gc(); 7564 break; 7565 } 7566 7567 case ENABLE_SCREEN: { 7568 performEnableScreen(); 7569 break; 7570 } 7571 7572 case APP_FREEZE_TIMEOUT: { 7573 synchronized (mWindowMap) { 7574 synchronized (mAnimator) { 7575 Slog.w(TAG, "App freeze timeout expired."); 7576 int i = mAppTokens.size(); 7577 while (i > 0) { 7578 i--; 7579 AppWindowToken tok = mAppTokens.get(i); 7580 if (tok.mAppAnimator.freezingScreen) { 7581 Slog.w(TAG, "Force clearing freeze: " + tok); 7582 unsetAppFreezingScreenLocked(tok, true, true); 7583 } 7584 } 7585 } 7586 } 7587 break; 7588 } 7589 7590 case CLIENT_FREEZE_TIMEOUT: { 7591 synchronized (mWindowMap) { 7592 if (mClientFreezingScreen) { 7593 mClientFreezingScreen = false; 7594 stopFreezingDisplayLocked(); 7595 } 7596 } 7597 break; 7598 } 7599 7600 case SEND_NEW_CONFIGURATION: { 7601 removeMessages(SEND_NEW_CONFIGURATION); 7602 sendNewConfiguration(); 7603 break; 7604 } 7605 7606 case REPORT_WINDOWS_CHANGE: { 7607 if (mWindowsChanged) { 7608 synchronized (mWindowMap) { 7609 mWindowsChanged = false; 7610 } 7611 notifyWindowsChanged(); 7612 } 7613 break; 7614 } 7615 7616 case DRAG_START_TIMEOUT: { 7617 IBinder win = (IBinder)msg.obj; 7618 if (DEBUG_DRAG) { 7619 Slog.w(TAG, "Timeout starting drag by win " + win); 7620 } 7621 synchronized (mWindowMap) { 7622 // !!! TODO: ANR the app that has failed to start the drag in time 7623 if (mDragState != null) { 7624 mDragState.unregister(); 7625 mInputMonitor.updateInputWindowsLw(true /*force*/); 7626 mDragState.reset(); 7627 mDragState = null; 7628 } 7629 } 7630 break; 7631 } 7632 7633 case DRAG_END_TIMEOUT: { 7634 IBinder win = (IBinder)msg.obj; 7635 if (DEBUG_DRAG) { 7636 Slog.w(TAG, "Timeout ending drag to win " + win); 7637 } 7638 synchronized (mWindowMap) { 7639 // !!! TODO: ANR the drag-receiving app 7640 if (mDragState != null) { 7641 mDragState.mDragResult = false; 7642 mDragState.endDragLw(); 7643 } 7644 } 7645 break; 7646 } 7647 7648 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7649 notifyHardKeyboardStatusChange(); 7650 break; 7651 } 7652 7653 case BOOT_TIMEOUT: { 7654 performBootTimeout(); 7655 break; 7656 } 7657 7658 case WAITING_FOR_DRAWN_TIMEOUT: { 7659 Pair<WindowState, IRemoteCallback> pair; 7660 synchronized (mWindowMap) { 7661 pair = (Pair<WindowState, IRemoteCallback>)msg.obj; 7662 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first); 7663 if (!mWaitingForDrawn.remove(pair)) { 7664 return; 7665 } 7666 } 7667 try { 7668 pair.second.sendResult(null); 7669 } catch (RemoteException e) { 7670 } 7671 break; 7672 } 7673 7674 case UPDATE_ANIM_PARAMETERS: { 7675 // Used to send multiple changes from the animation side to the layout side. 7676 synchronized (mWindowMap) { 7677 if (copyAnimToLayoutParamsLocked()) { 7678 mH.sendEmptyMessage(CLEAR_PENDING_ACTIONS); 7679 performLayoutAndPlaceSurfacesLocked(); 7680 } 7681 } 7682 break; 7683 } 7684 7685 case SHOW_STRICT_MODE_VIOLATION: { 7686 showStrictModeViolation(msg.arg1, msg.arg2); 7687 break; 7688 } 7689 7690 // Animation messages. Move to Window{State}Animator 7691 case SET_TRANSPARENT_REGION: { 7692 Pair<WindowStateAnimator, Region> pair = 7693 (Pair<WindowStateAnimator, Region>) msg.obj; 7694 final WindowStateAnimator winAnimator = pair.first; 7695 winAnimator.setTransparentRegionHint(pair.second); 7696 break; 7697 } 7698 7699 case CLEAR_PENDING_ACTIONS: { 7700 mAnimator.clearPendingActions(); 7701 break; 7702 } 7703 7704 case DO_ANIMATION_CALLBACK: { 7705 try { 7706 ((IRemoteCallback)msg.obj).sendResult(null); 7707 } catch (RemoteException e) { 7708 } 7709 break; 7710 } 7711 7712 case NOTIFY_ROTATION_CHANGED: { 7713 final int displayId = msg.arg1; 7714 final int rotation = msg.arg2; 7715 handleNotifyRotationChanged(displayId, rotation); 7716 break; 7717 } 7718 7719 case NOTIFY_WINDOW_TRANSITION: { 7720 final int transition = msg.arg1; 7721 WindowInfo info = (WindowInfo) msg.obj; 7722 handleNotifyWindowTranstion(transition, info); 7723 break; 7724 } 7725 7726 case NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: { 7727 final int displayId = msg.arg1; 7728 final boolean immediate = (msg.arg2 == 1); 7729 Rect rectangle = (Rect) msg.obj; 7730 handleNotifyRectangleOnScreenRequested(displayId, rectangle, immediate); 7731 break; 7732 } 7733 7734 case NOTIFY_WINDOW_LAYERS_CHANGED: { 7735 DisplayContent displayContent = (DisplayContent) msg.obj; 7736 handleNotifyWindowLayersChanged(displayContent); 7737 break; 7738 } 7739 7740 case DO_DISPLAY_ADDED: 7741 synchronized (mWindowMap) { 7742 handleDisplayAddedLocked(msg.arg1); 7743 } 7744 break; 7745 7746 case DO_DISPLAY_REMOVED: 7747 synchronized (mWindowMap) { 7748 handleDisplayRemovedLocked(msg.arg1); 7749 } 7750 break; 7751 7752 case DO_DISPLAY_CHANGED: 7753 synchronized (mWindowMap) { 7754 handleDisplayChangedLocked(msg.arg1); 7755 } 7756 break; 7757 } 7758 if (DEBUG_WINDOW_TRACE) { 7759 Slog.v(TAG, "handleMessage: exit"); 7760 } 7761 } 7762 } 7763 7764 // ------------------------------------------------------------- 7765 // IWindowManager API 7766 // ------------------------------------------------------------- 7767 7768 @Override 7769 public IWindowSession openSession(IInputMethodClient client, 7770 IInputContext inputContext) { 7771 if (client == null) throw new IllegalArgumentException("null client"); 7772 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7773 Session session = new Session(this, client, inputContext); 7774 return session; 7775 } 7776 7777 @Override 7778 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7779 synchronized (mWindowMap) { 7780 // The focus for the client is the window immediately below 7781 // where we would place the input method window. 7782 int idx = findDesiredInputMethodWindowIndexLocked(false); 7783 if (idx > 0) { 7784 // TODO(multidisplay): IMEs are only supported on the default display. 7785 WindowState imFocus = getDefaultWindowListLocked().get(idx-1); 7786 if (DEBUG_INPUT_METHOD) { 7787 Slog.i(TAG, "Desired input method target: " + imFocus); 7788 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7789 Slog.i(TAG, "Last focus: " + mLastFocus); 7790 } 7791 if (imFocus != null) { 7792 // This may be a starting window, in which case we still want 7793 // to count it as okay. 7794 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7795 && imFocus.mAppToken != null) { 7796 // The client has definitely started, so it really should 7797 // have a window in this app token. Let's look for it. 7798 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7799 WindowState w = imFocus.mAppToken.windows.get(i); 7800 if (w != imFocus) { 7801 Log.i(TAG, "Switching to real app window: " + w); 7802 imFocus = w; 7803 break; 7804 } 7805 } 7806 } 7807 if (DEBUG_INPUT_METHOD) { 7808 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7809 if (imFocus.mSession.mClient != null) { 7810 Slog.i(TAG, "IM target client binder: " 7811 + imFocus.mSession.mClient.asBinder()); 7812 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7813 } 7814 } 7815 if (imFocus.mSession.mClient != null && 7816 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7817 return true; 7818 } 7819 } 7820 } 7821 7822 // Okay, how about this... what is the current focus? 7823 // It seems in some cases we may not have moved the IM 7824 // target window, such as when it was in a pop-up window, 7825 // so let's also look at the current focus. (An example: 7826 // go to Gmail, start searching so the keyboard goes up, 7827 // press home. Sometimes the IME won't go down.) 7828 // Would be nice to fix this more correctly, but it's 7829 // way at the end of a release, and this should be good enough. 7830 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7831 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7832 return true; 7833 } 7834 } 7835 return false; 7836 } 7837 7838 public void getInitialDisplaySize(int displayId, Point size) { 7839 // TODO(cmautner): Access to DisplayContent should be locked on mWindowMap. Doing that 7840 // could lead to deadlock since this is called from ActivityManager. 7841 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7842 synchronized(displayContent.mDisplaySizeLock) { 7843 size.x = displayContent.mInitialDisplayWidth; 7844 size.y = displayContent.mInitialDisplayHeight; 7845 } 7846 } 7847 7848 public void setForcedDisplaySize(int displayId, int width, int height) { 7849 synchronized(mWindowMap) { 7850 // Set some sort of reasonable bounds on the size of the display that we 7851 // will try to emulate. 7852 final int MIN_WIDTH = 200; 7853 final int MIN_HEIGHT = 200; 7854 final int MAX_SCALE = 2; 7855 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7856 7857 width = Math.min(Math.max(width, MIN_WIDTH), 7858 displayContent.mInitialDisplayWidth * MAX_SCALE); 7859 height = Math.min(Math.max(height, MIN_HEIGHT), 7860 displayContent.mInitialDisplayHeight * MAX_SCALE); 7861 setForcedDisplaySizeLocked(displayContent, width, height); 7862 Settings.Global.putString(mContext.getContentResolver(), 7863 Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height); 7864 } 7865 } 7866 7867 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7868 final String sizeStr = Settings.Global.getString(mContext.getContentResolver(), 7869 Settings.Global.DISPLAY_SIZE_FORCED); 7870 if (sizeStr != null && sizeStr.length() > 0) { 7871 final int pos = sizeStr.indexOf(','); 7872 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7873 int width, height; 7874 try { 7875 width = Integer.parseInt(sizeStr.substring(0, pos)); 7876 height = Integer.parseInt(sizeStr.substring(pos+1)); 7877 synchronized(displayContent.mDisplaySizeLock) { 7878 if (displayContent.mBaseDisplayWidth != width 7879 || displayContent.mBaseDisplayHeight != height) { 7880 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7881 displayContent.mBaseDisplayWidth = width; 7882 displayContent.mBaseDisplayHeight = height; 7883 } 7884 } 7885 } catch (NumberFormatException ex) { 7886 } 7887 } 7888 } 7889 final String densityStr = Settings.Global.getString(mContext.getContentResolver(), 7890 Settings.Global.DISPLAY_DENSITY_FORCED); 7891 if (densityStr != null && densityStr.length() > 0) { 7892 int density; 7893 try { 7894 density = Integer.parseInt(densityStr); 7895 synchronized(displayContent.mDisplaySizeLock) { 7896 if (displayContent.mBaseDisplayDensity != density) { 7897 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7898 displayContent.mBaseDisplayDensity = density; 7899 } 7900 } 7901 } catch (NumberFormatException ex) { 7902 } 7903 } 7904 } 7905 7906 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7907 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7908 7909 synchronized(displayContent.mDisplaySizeLock) { 7910 displayContent.mBaseDisplayWidth = width; 7911 displayContent.mBaseDisplayHeight = height; 7912 } 7913 reconfigureDisplayLocked(displayContent); 7914 } 7915 7916 public void clearForcedDisplaySize(int displayId) { 7917 synchronized(mWindowMap) { 7918 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7919 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7920 displayContent.mInitialDisplayHeight); 7921 Settings.Global.putString(mContext.getContentResolver(), 7922 Settings.Global.DISPLAY_SIZE_FORCED, ""); 7923 } 7924 } 7925 7926 public void setForcedDisplayDensity(int displayId, int density) { 7927 synchronized(mWindowMap) { 7928 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7929 setForcedDisplayDensityLocked(displayContent, density); 7930 Settings.Global.putString(mContext.getContentResolver(), 7931 Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7932 } 7933 } 7934 7935 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7936 Slog.i(TAG, "Using new display density: " + density); 7937 7938 synchronized(displayContent.mDisplaySizeLock) { 7939 displayContent.mBaseDisplayDensity = density; 7940 } 7941 reconfigureDisplayLocked(displayContent); 7942 } 7943 7944 public void clearForcedDisplayDensity(int displayId) { 7945 synchronized(mWindowMap) { 7946 final DisplayContent displayContent = getDisplayContentLocked(displayId); 7947 setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity); 7948 Settings.Global.putString(mContext.getContentResolver(), 7949 Settings.Global.DISPLAY_DENSITY_FORCED, ""); 7950 } 7951 } 7952 7953 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7954 // TODO: Multidisplay: for now only use with default display. 7955 mPolicy.setInitialDisplaySize(displayContent.getDisplay(), 7956 displayContent.mBaseDisplayWidth, 7957 displayContent.mBaseDisplayHeight, 7958 displayContent.mBaseDisplayDensity); 7959 7960 displayContent.layoutNeeded = true; 7961 7962 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7963 mTempConfiguration.setToDefaults(); 7964 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7965 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7966 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7967 configChanged = true; 7968 } 7969 } 7970 7971 if (configChanged) { 7972 mWaitingForConfig = true; 7973 startFreezingDisplayLocked(false, 0, 0); 7974 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7975 } 7976 7977 performLayoutAndPlaceSurfacesLocked(); 7978 } 7979 7980 public boolean hasSystemNavBar() { 7981 return mPolicy.hasSystemNavBar(); 7982 } 7983 7984 // ------------------------------------------------------------- 7985 // Internals 7986 // ------------------------------------------------------------- 7987 7988 final WindowState windowForClientLocked(Session session, IWindow client, 7989 boolean throwOnError) { 7990 return windowForClientLocked(session, client.asBinder(), throwOnError); 7991 } 7992 7993 final WindowState windowForClientLocked(Session session, IBinder client, 7994 boolean throwOnError) { 7995 WindowState win = mWindowMap.get(client); 7996 if (localLOGV) Slog.v( 7997 TAG, "Looking up client " + client + ": " + win); 7998 if (win == null) { 7999 RuntimeException ex = new IllegalArgumentException( 8000 "Requested window " + client + " does not exist"); 8001 if (throwOnError) { 8002 throw ex; 8003 } 8004 Slog.w(TAG, "Failed looking up window", ex); 8005 return null; 8006 } 8007 if (session != null && win.mSession != session) { 8008 RuntimeException ex = new IllegalArgumentException( 8009 "Requested window " + client + " is in session " + 8010 win.mSession + ", not " + session); 8011 if (throwOnError) { 8012 throw ex; 8013 } 8014 Slog.w(TAG, "Failed looking up window", ex); 8015 return null; 8016 } 8017 8018 return win; 8019 } 8020 8021 final void rebuildAppWindowListLocked() { 8022 DisplayContentsIterator iterator = new DisplayContentsIterator(); 8023 while (iterator.hasNext()) { 8024 rebuildAppWindowListLocked(iterator.next()); 8025 } 8026 } 8027 8028 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 8029 final WindowList windows = displayContent.getWindowList(); 8030 int NW = windows.size(); 8031 int i; 8032 int lastBelow = -1; 8033 int numRemoved = 0; 8034 8035 if (mRebuildTmp.length < NW) { 8036 mRebuildTmp = new WindowState[NW+10]; 8037 } 8038 8039 // First remove all existing app windows. 8040 i=0; 8041 while (i < NW) { 8042 WindowState w = windows.get(i); 8043 if (w.mAppToken != null) { 8044 WindowState win = windows.remove(i); 8045 win.mRebuilding = true; 8046 mRebuildTmp[numRemoved] = win; 8047 mWindowsChanged = true; 8048 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 8049 "Rebuild removing window: " + win); 8050 NW--; 8051 numRemoved++; 8052 continue; 8053 } else if (lastBelow == i-1) { 8054 if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8055 lastBelow = i; 8056 } 8057 } 8058 i++; 8059 } 8060 8061 // Keep whatever windows were below the app windows still below, 8062 // by skipping them. 8063 lastBelow++; 8064 i = lastBelow; 8065 8066 // First add all of the exiting app tokens... these are no longer 8067 // in the main app list, but still have windows shown. We put them 8068 // in the back because now that the animation is over we no longer 8069 // will care about them. 8070 int NT = mExitingAppTokens.size(); 8071 for (int j=0; j<NT; j++) { 8072 i = reAddAppWindowsLocked(displayContent, i, mExitingAppTokens.get(j)); 8073 } 8074 8075 // And add in the still active app tokens in Z order. 8076 NT = mAnimatingAppTokens.size(); 8077 for (int j=0; j<NT; j++) { 8078 i = reAddAppWindowsLocked(displayContent, i, mAnimatingAppTokens.get(j)); 8079 } 8080 8081 i -= lastBelow; 8082 if (i != numRemoved) { 8083 Slog.w(TAG, "Rebuild removed " + numRemoved 8084 + " windows but added " + i); 8085 for (i=0; i<numRemoved; i++) { 8086 WindowState ws = mRebuildTmp[i]; 8087 if (ws.mRebuilding) { 8088 StringWriter sw = new StringWriter(); 8089 PrintWriter pw = new PrintWriter(sw); 8090 ws.dump(pw, "", true); 8091 pw.flush(); 8092 Slog.w(TAG, "This window was lost: " + ws); 8093 Slog.w(TAG, sw.toString()); 8094 ws.mWinAnimator.destroySurfaceLocked(); 8095 } 8096 } 8097 Slog.w(TAG, "Current app token list:"); 8098 dumpAnimatingAppTokensLocked(); 8099 Slog.w(TAG, "Final window list:"); 8100 dumpWindowsLocked(); 8101 } 8102 } 8103 8104 private final void assignLayersLocked(WindowList windows) { 8105 int N = windows.size(); 8106 int curBaseLayer = 0; 8107 int curLayer = 0; 8108 int i; 8109 8110 if (DEBUG_LAYERS) { 8111 RuntimeException here = new RuntimeException("here"); 8112 here.fillInStackTrace(); 8113 Slog.v(TAG, "Assigning layers", here); 8114 } 8115 8116 boolean anyLayerChanged = false; 8117 8118 for (i=0; i<N; i++) { 8119 final WindowState w = windows.get(i); 8120 final WindowStateAnimator winAnimator = w.mWinAnimator; 8121 boolean layerChanged = false; 8122 int oldLayer = w.mLayer; 8123 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 8124 || (i > 0 && w.mIsWallpaper)) { 8125 curLayer += WINDOW_LAYER_MULTIPLIER; 8126 w.mLayer = curLayer; 8127 } else { 8128 curBaseLayer = curLayer = w.mBaseLayer; 8129 w.mLayer = curLayer; 8130 } 8131 if (w.mLayer != oldLayer) { 8132 layerChanged = true; 8133 anyLayerChanged = true; 8134 } 8135 oldLayer = winAnimator.mAnimLayer; 8136 if (w.mTargetAppToken != null) { 8137 winAnimator.mAnimLayer = 8138 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 8139 } else if (w.mAppToken != null) { 8140 winAnimator.mAnimLayer = 8141 w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment; 8142 } else { 8143 winAnimator.mAnimLayer = w.mLayer; 8144 } 8145 if (w.mIsImWindow) { 8146 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 8147 } else if (w.mIsWallpaper) { 8148 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 8149 } 8150 if (winAnimator.mAnimLayer != oldLayer) { 8151 layerChanged = true; 8152 anyLayerChanged = true; 8153 } 8154 if (layerChanged && mAnimator.isDimmingLocked(winAnimator)) { 8155 // Force an animation pass just to update the mDimAnimator layer. 8156 updateLayoutToAnimationLocked(); 8157 } 8158 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 8159 + "mBase=" + w.mBaseLayer 8160 + " mLayer=" + w.mLayer 8161 + (w.mAppToken == null ? 8162 "" : " mAppLayer=" + w.mAppToken.mAppAnimator.animLayerAdjustment) 8163 + " =mAnimLayer=" + winAnimator.mAnimLayer); 8164 //System.out.println( 8165 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 8166 } 8167 8168 if (anyLayerChanged) { 8169 scheduleNotifyWindowLayersChangedIfNeededLocked(getDefaultDisplayContentLocked()); 8170 } 8171 } 8172 8173 private final void performLayoutAndPlaceSurfacesLocked() { 8174 do { 8175 mTraversalScheduled = false; 8176 performLayoutAndPlaceSurfacesLockedLoop(); 8177 mH.removeMessages(H.DO_TRAVERSAL); 8178 } while (mTraversalScheduled); 8179 } 8180 8181 private boolean mInLayout = false; 8182 private final void performLayoutAndPlaceSurfacesLockedLoop() { 8183 if (mInLayout) { 8184 if (DEBUG) { 8185 throw new RuntimeException("Recursive call!"); 8186 } 8187 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 8188 + Debug.getCallers(3)); 8189 return; 8190 } 8191 8192 if (mWaitingForConfig) { 8193 // Our configuration has changed (most likely rotation), but we 8194 // don't yet have the complete configuration to report to 8195 // applications. Don't do any window layout until we have it. 8196 return; 8197 } 8198 8199 if (!mDisplayReady) { 8200 // Not yet initialized, nothing to do. 8201 return; 8202 } 8203 8204 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 8205 mInLayout = true; 8206 boolean recoveringMemory = false; 8207 8208 try { 8209 if (mForceRemoves != null) { 8210 recoveringMemory = true; 8211 // Wait a little bit for things to settle down, and off we go. 8212 for (int i=0; i<mForceRemoves.size(); i++) { 8213 WindowState ws = mForceRemoves.get(i); 8214 Slog.i(TAG, "Force removing: " + ws); 8215 removeWindowInnerLocked(ws.mSession, ws); 8216 } 8217 mForceRemoves = null; 8218 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 8219 Object tmp = new Object(); 8220 synchronized (tmp) { 8221 try { 8222 tmp.wait(250); 8223 } catch (InterruptedException e) { 8224 } 8225 } 8226 } 8227 } catch (RuntimeException e) { 8228 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 8229 } 8230 8231 try { 8232 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 8233 8234 mInLayout = false; 8235 8236 if (needsLayout()) { 8237 if (++mLayoutRepeatCount < 6) { 8238 requestTraversalLocked(); 8239 } else { 8240 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 8241 mLayoutRepeatCount = 0; 8242 } 8243 } else { 8244 mLayoutRepeatCount = 0; 8245 } 8246 8247 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 8248 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 8249 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE)); 8250 } 8251 } catch (RuntimeException e) { 8252 mInLayout = false; 8253 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 8254 } 8255 8256 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8257 } 8258 8259 private final void performLayoutLockedInner(final DisplayContent displayContent, 8260 boolean initial, boolean updateInputWindows) { 8261 if (!displayContent.layoutNeeded) { 8262 return; 8263 } 8264 displayContent.layoutNeeded = false; 8265 WindowList windows = displayContent.getWindowList(); 8266 boolean isDefaultDisplay = displayContent.isDefaultDisplay; 8267 8268 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8269 final int dw = displayInfo.logicalWidth; 8270 final int dh = displayInfo.logicalHeight; 8271 8272 final int NFW = mFakeWindows.size(); 8273 for (int i=0; i<NFW; i++) { 8274 mFakeWindows.get(i).layout(dw, dh); 8275 } 8276 8277 final int N = windows.size(); 8278 int i; 8279 8280 if (DEBUG_LAYOUT) { 8281 Slog.v(TAG, "-------------------------------------"); 8282 Slog.v(TAG, "performLayout: needed=" 8283 + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); 8284 } 8285 8286 WindowStateAnimator universeBackground = null; 8287 8288 mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); 8289 if (isDefaultDisplay) { 8290 // Not needed on non-default displays. 8291 mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect); 8292 mScreenRect.set(0, 0, dw, dh); 8293 } 8294 8295 int seq = mLayoutSeq+1; 8296 if (seq < 0) seq = 0; 8297 mLayoutSeq = seq; 8298 8299 boolean behindDream = false; 8300 8301 // First perform layout of any root windows (not attached 8302 // to another window). 8303 int topAttached = -1; 8304 for (i = N-1; i >= 0; i--) { 8305 final WindowState win = windows.get(i); 8306 8307 // Don't do layout of a window if it is not visible, or 8308 // soon won't be visible, to avoid wasting time and funky 8309 // changes while a window is animating away. 8310 final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) 8311 || win.isGoneForLayoutLw(); 8312 8313 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 8314 Slog.v(TAG, "1ST PASS " + win 8315 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 8316 + " mLayoutAttached=" + win.mLayoutAttached 8317 + " screen changed=" + win.isConfigChanged()); 8318 final AppWindowToken atoken = win.mAppToken; 8319 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 8320 + win.mViewVisibility + " mRelayoutCalled=" 8321 + win.mRelayoutCalled + " hidden=" 8322 + win.mRootToken.hidden + " hiddenRequested=" 8323 + (atoken != null && atoken.hiddenRequested) 8324 + " mAttachedHidden=" + win.mAttachedHidden); 8325 else Slog.v(TAG, " VIS: mViewVisibility=" 8326 + win.mViewVisibility + " mRelayoutCalled=" 8327 + win.mRelayoutCalled + " hidden=" 8328 + win.mRootToken.hidden + " hiddenRequested=" 8329 + (atoken != null && atoken.hiddenRequested) 8330 + " mAttachedHidden=" + win.mAttachedHidden); 8331 } 8332 8333 // If this view is GONE, then skip it -- keep the current 8334 // frame, and let the caller know so they can ignore it 8335 // if they want. (We do the normal layout for INVISIBLE 8336 // windows, since that means "perform layout as normal, 8337 // just don't display"). 8338 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 8339 || win.isConfigChanged() 8340 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 8341 if (!win.mLayoutAttached) { 8342 if (initial) { 8343 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8344 win.mContentChanged = false; 8345 } 8346 if (win.mAttrs.type == TYPE_DREAM) { 8347 // Don't layout windows behind a dream, so that if it 8348 // does stuff like hide the status bar we won't get a 8349 // bad transition when it goes away. 8350 behindDream = true; 8351 } 8352 win.mLayoutNeeded = false; 8353 win.prelayout(); 8354 mPolicy.layoutWindowLw(win, win.mAttrs, null); 8355 win.mLayoutSeq = seq; 8356 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8357 + win.mFrame + " mContainingFrame=" 8358 + win.mContainingFrame + " mDisplayFrame=" 8359 + win.mDisplayFrame); 8360 } else { 8361 if (topAttached < 0) topAttached = i; 8362 } 8363 } 8364 if (win.mViewVisibility == View.VISIBLE 8365 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 8366 && universeBackground == null) { 8367 universeBackground = win.mWinAnimator; 8368 } 8369 } 8370 8371 if (mAnimator.mUniverseBackground != universeBackground) { 8372 mFocusMayChange = true; 8373 mAnimator.mUniverseBackground = universeBackground; 8374 } 8375 8376 boolean attachedBehindDream = false; 8377 8378 // Now perform layout of attached windows, which usually 8379 // depend on the position of the window they are attached to. 8380 // XXX does not deal with windows that are attached to windows 8381 // that are themselves attached. 8382 for (i = topAttached; i >= 0; i--) { 8383 final WindowState win = windows.get(i); 8384 8385 if (win.mLayoutAttached) { 8386 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 8387 + " mHaveFrame=" + win.mHaveFrame 8388 + " mViewVisibility=" + win.mViewVisibility 8389 + " mRelayoutCalled=" + win.mRelayoutCalled); 8390 // If this view is GONE, then skip it -- keep the current 8391 // frame, and let the caller know so they can ignore it 8392 // if they want. (We do the normal layout for INVISIBLE 8393 // windows, since that means "perform layout as normal, 8394 // just don't display"). 8395 if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) { 8396 continue; 8397 } 8398 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 8399 || !win.mHaveFrame || win.mLayoutNeeded) { 8400 if (initial) { 8401 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 8402 win.mContentChanged = false; 8403 } 8404 win.mLayoutNeeded = false; 8405 win.prelayout(); 8406 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 8407 win.mLayoutSeq = seq; 8408 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 8409 + win.mFrame + " mContainingFrame=" 8410 + win.mContainingFrame + " mDisplayFrame=" 8411 + win.mDisplayFrame); 8412 } 8413 } else if (win.mAttrs.type == TYPE_DREAM) { 8414 // Don't layout windows behind a dream, so that if it 8415 // does stuff like hide the status bar we won't get a 8416 // bad transition when it goes away. 8417 attachedBehindDream = behindDream; 8418 } 8419 } 8420 8421 // Window frames may have changed. Tell the input dispatcher about it. 8422 mInputMonitor.setUpdateInputWindowsNeededLw(); 8423 if (updateInputWindows) { 8424 mInputMonitor.updateInputWindowsLw(false /*force*/); 8425 } 8426 8427 mPolicy.finishLayoutLw(); 8428 } 8429 8430 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8431 // If the screen is currently frozen or off, then keep 8432 // it frozen/off until this window draws at its new 8433 // orientation. 8434 if (!okToDisplay()) { 8435 if (DEBUG_ORIENTATION) Slog.v(TAG, 8436 "Changing surface while display frozen: " + w); 8437 w.mOrientationChanging = true; 8438 mInnerFields.mOrientationChangeComplete = false; 8439 if (!mWindowsFreezingScreen) { 8440 mWindowsFreezingScreen = true; 8441 // XXX should probably keep timeout from 8442 // when we first froze the display. 8443 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8444 mH.sendMessageDelayed(mH.obtainMessage( 8445 H.WINDOW_FREEZE_TIMEOUT), WINDOW_FREEZE_TIMEOUT_DURATION); 8446 } 8447 } 8448 } 8449 8450 /** 8451 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8452 * @param windows List of windows on default display. 8453 * @return bitmap indicating if another pass through layout must be made. 8454 */ 8455 public int handleAppTransitionReadyLocked(WindowList windows) { 8456 int changes = 0; 8457 int i; 8458 int NN = mOpeningApps.size(); 8459 boolean goodToGo = true; 8460 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8461 "Checking " + NN + " opening apps (frozen=" 8462 + mDisplayFrozen + " timeout=" 8463 + mAppTransitionTimeout + ")..."); 8464 if (!mDisplayFrozen && !mAppTransitionTimeout) { 8465 // If the display isn't frozen, wait to do anything until 8466 // all of the apps are ready. Otherwise just go because 8467 // we'll unfreeze the display when everyone is ready. 8468 for (i=0; i<NN && goodToGo; i++) { 8469 AppWindowToken wtoken = mOpeningApps.get(i); 8470 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8471 "Check opening app=" + wtoken + ": allDrawn=" 8472 + wtoken.allDrawn + " startingDisplayed=" 8473 + wtoken.startingDisplayed + " startingMoved=" 8474 + wtoken.startingMoved); 8475 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8476 && !wtoken.startingMoved) { 8477 goodToGo = false; 8478 } 8479 } 8480 } 8481 if (goodToGo) { 8482 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8483 int transit = mNextAppTransition; 8484 if (mSkipAppTransitionAnimation) { 8485 transit = WindowManagerPolicy.TRANSIT_UNSET; 8486 } 8487 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 8488 mAppTransitionReady = false; 8489 mAppTransitionRunning = true; 8490 mAppTransitionTimeout = false; 8491 mStartingIconInTransition = false; 8492 mSkipAppTransitionAnimation = false; 8493 8494 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8495 8496 rebuildAppWindowListLocked(); 8497 8498 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8499 WindowState oldWallpaper = 8500 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8501 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8502 ? null : mWallpaperTarget; 8503 8504 adjustWallpaperWindowsLocked(); 8505 mInnerFields.mWallpaperMayChange = false; 8506 8507 // The top-most window will supply the layout params, 8508 // and we will determine it below. 8509 LayoutParams animLp = null; 8510 int bestAnimLayer = -1; 8511 boolean fullscreenAnim = false; 8512 8513 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8514 "New wallpaper target=" + mWallpaperTarget 8515 + ", oldWallpaper=" + oldWallpaper 8516 + ", lower target=" + mLowerWallpaperTarget 8517 + ", upper target=" + mUpperWallpaperTarget); 8518 int foundWallpapers = 0; 8519 // Do a first pass through the tokens for two 8520 // things: 8521 // (1) Determine if both the closing and opening 8522 // app token sets are wallpaper targets, in which 8523 // case special animations are needed 8524 // (since the wallpaper needs to stay static 8525 // behind them). 8526 // (2) Find the layout params of the top-most 8527 // application window in the tokens, which is 8528 // what will control the animation theme. 8529 final int NC = mClosingApps.size(); 8530 NN = NC + mOpeningApps.size(); 8531 for (i=0; i<NN; i++) { 8532 AppWindowToken wtoken; 8533 int mode; 8534 if (i < NC) { 8535 wtoken = mClosingApps.get(i); 8536 mode = 1; 8537 } else { 8538 wtoken = mOpeningApps.get(i-NC); 8539 mode = 2; 8540 } 8541 if (mLowerWallpaperTarget != null) { 8542 if (mLowerWallpaperTarget.mAppToken == wtoken 8543 || mUpperWallpaperTarget.mAppToken == wtoken) { 8544 foundWallpapers |= mode; 8545 } 8546 } 8547 if (wtoken.appFullscreen) { 8548 WindowState ws = wtoken.findMainWindow(); 8549 if (ws != null) { 8550 animLp = ws.mAttrs; 8551 bestAnimLayer = ws.mLayer; 8552 fullscreenAnim = true; 8553 } 8554 } else if (!fullscreenAnim) { 8555 WindowState ws = wtoken.findMainWindow(); 8556 if (ws != null) { 8557 if (ws.mLayer > bestAnimLayer) { 8558 animLp = ws.mAttrs; 8559 bestAnimLayer = ws.mLayer; 8560 } 8561 } 8562 } 8563 } 8564 8565 if (foundWallpapers == 3) { 8566 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8567 "Wallpaper animation!"); 8568 switch (transit) { 8569 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 8570 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 8571 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 8572 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN; 8573 break; 8574 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 8575 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 8576 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 8577 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE; 8578 break; 8579 } 8580 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8581 "New transit: " + transit); 8582 } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8583 // We are transitioning from an activity with 8584 // a wallpaper to one without. 8585 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE; 8586 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8587 "New transit away from wallpaper: " + transit); 8588 } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) { 8589 // We are transitioning from an activity without 8590 // a wallpaper to now showing the wallpaper 8591 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN; 8592 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8593 "New transit into wallpaper: " + transit); 8594 } 8595 8596 // If all closing windows are obscured, then there is 8597 // no need to do an animation. This is the case, for 8598 // example, when this transition is being done behind 8599 // the lock screen. 8600 if (!mPolicy.allowAppAnimationsLw()) { 8601 animLp = null; 8602 } 8603 8604 AppWindowToken topOpeningApp = null; 8605 int topOpeningLayer = 0; 8606 8607 NN = mOpeningApps.size(); 8608 for (i=0; i<NN; i++) { 8609 AppWindowToken wtoken = mOpeningApps.get(i); 8610 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8611 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8612 appAnimator.clearThumbnail(); 8613 wtoken.reportedVisible = false; 8614 wtoken.inPendingTransaction = false; 8615 appAnimator.animation = null; 8616 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 8617 wtoken.updateReportedVisibilityLocked(); 8618 wtoken.waitingToShow = false; 8619 8620 appAnimator.mAllAppWinAnimators.clear(); 8621 final int N = wtoken.allAppWindows.size(); 8622 for (int j = 0; j < N; j++) { 8623 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8624 } 8625 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8626 8627 if (animLp != null) { 8628 int layer = -1; 8629 for (int j=0; j<wtoken.windows.size(); j++) { 8630 WindowState win = wtoken.windows.get(j); 8631 if (win.mWinAnimator.mAnimLayer > layer) { 8632 layer = win.mWinAnimator.mAnimLayer; 8633 } 8634 } 8635 if (topOpeningApp == null || layer > topOpeningLayer) { 8636 topOpeningApp = wtoken; 8637 topOpeningLayer = layer; 8638 } 8639 } 8640 } 8641 NN = mClosingApps.size(); 8642 for (i=0; i<NN; i++) { 8643 AppWindowToken wtoken = mClosingApps.get(i); 8644 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8645 "Now closing app " + wtoken); 8646 wtoken.mAppAnimator.clearThumbnail(); 8647 wtoken.inPendingTransaction = false; 8648 wtoken.mAppAnimator.animation = null; 8649 setTokenVisibilityLocked(wtoken, animLp, false, 8650 transit, false); 8651 wtoken.updateReportedVisibilityLocked(); 8652 wtoken.waitingToHide = false; 8653 // Force the allDrawn flag, because we want to start 8654 // this guy's animations regardless of whether it's 8655 // gotten drawn. 8656 wtoken.allDrawn = true; 8657 } 8658 8659 if (mNextAppTransitionThumbnail != null && topOpeningApp != null 8660 && topOpeningApp.mAppAnimator.animation != null) { 8661 // This thumbnail animation is very special, we need to have 8662 // an extra surface with the thumbnail included with the animation. 8663 Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(), 8664 mNextAppTransitionThumbnail.getHeight()); 8665 try { 8666 // TODO(multi-display): support other displays 8667 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8668 final Display display = displayContent.getDisplay(); 8669 Surface surface = new Surface(mFxSession, 8670 "thumbnail anim", 8671 dirty.width(), dirty.height(), 8672 PixelFormat.TRANSLUCENT, Surface.HIDDEN); 8673 surface.setLayerStack(display.getLayerStack()); 8674 topOpeningApp.mAppAnimator.thumbnail = surface; 8675 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " 8676 + surface + ": CREATE"); 8677 Surface drawSurface = new Surface(); 8678 drawSurface.copyFrom(surface); 8679 Canvas c = drawSurface.lockCanvas(dirty); 8680 c.drawBitmap(mNextAppTransitionThumbnail, 0, 0, null); 8681 drawSurface.unlockCanvasAndPost(c); 8682 drawSurface.release(); 8683 topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer; 8684 Animation anim = createThumbnailAnimationLocked( 8685 transit, true, true, mNextAppTransitionScaleUp); 8686 topOpeningApp.mAppAnimator.thumbnailAnimation = anim; 8687 anim.restrictDuration(MAX_ANIMATION_DURATION); 8688 anim.scaleCurrentDuration(mTransitionAnimationScale); 8689 topOpeningApp.mAppAnimator.thumbnailX = mNextAppTransitionStartX; 8690 topOpeningApp.mAppAnimator.thumbnailY = mNextAppTransitionStartY; 8691 } catch (Surface.OutOfResourcesException e) { 8692 Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width() 8693 + " h=" + dirty.height(), e); 8694 topOpeningApp.mAppAnimator.clearThumbnail(); 8695 } 8696 } 8697 8698 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 8699 mNextAppTransitionPackage = null; 8700 mNextAppTransitionThumbnail = null; 8701 scheduleAnimationCallback(mNextAppTransitionCallback); 8702 mNextAppTransitionCallback = null; 8703 8704 mOpeningApps.clear(); 8705 mClosingApps.clear(); 8706 8707 // This has changed the visibility of windows, so perform 8708 // a new layout to get them all up-to-date. 8709 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8710 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8711 getDefaultDisplayContentLocked().layoutNeeded = true; 8712 8713 // TODO(multidisplay): IMEs are only supported on the default display. 8714 if (windows == getDefaultWindowListLocked() 8715 && !moveInputMethodWindowsIfNeededLocked(true)) { 8716 assignLayersLocked(windows); 8717 } 8718 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8719 mFocusMayChange = false; 8720 } 8721 8722 return changes; 8723 } 8724 8725 /** 8726 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8727 * @return bitmap indicating if another pass through layout must be made. 8728 */ 8729 private int handleAnimatingStoppedAndTransitionLocked() { 8730 int changes = 0; 8731 8732 mAppTransitionRunning = false; 8733 // Restore window app tokens to the ActivityManager views 8734 for (int i = mAnimatingAppTokens.size() - 1; i >= 0; i--) { 8735 mAnimatingAppTokens.get(i).sendingToBottom = false; 8736 } 8737 mAnimatingAppTokens.clear(); 8738 mAnimatingAppTokens.addAll(mAppTokens); 8739 rebuildAppWindowListLocked(); 8740 8741 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8742 mInnerFields.mAdjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED; 8743 moveInputMethodWindowsIfNeededLocked(true); 8744 mInnerFields.mWallpaperMayChange = true; 8745 // Since the window list has been rebuilt, focus might 8746 // have to be recomputed since the actual order of windows 8747 // might have changed again. 8748 mFocusMayChange = true; 8749 8750 return changes; 8751 } 8752 8753 /** 8754 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8755 * 8756 * @return bitmap indicating if another pass through layout must be made. 8757 */ 8758 private int animateAwayWallpaperLocked() { 8759 int changes = 0; 8760 WindowState oldWallpaper = mWallpaperTarget; 8761 if (mLowerWallpaperTarget != null 8762 && mLowerWallpaperTarget.mAppToken != null) { 8763 if (DEBUG_WALLPAPER) Slog.v(TAG, 8764 "wallpaperForceHiding changed with lower=" 8765 + mLowerWallpaperTarget); 8766 if (DEBUG_WALLPAPER) Slog.v(TAG, 8767 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden + 8768 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested); 8769 if (mLowerWallpaperTarget.mAppToken.hidden) { 8770 // The lower target has become hidden before we 8771 // actually started the animation... let's completely 8772 // re-evaluate everything. 8773 mLowerWallpaperTarget = mUpperWallpaperTarget = null; 8774 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8775 } 8776 } 8777 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 8778 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper 8779 + " NEW: " + mWallpaperTarget 8780 + " LOWER: " + mLowerWallpaperTarget); 8781 return changes; 8782 } 8783 8784 private void updateResizingWindows(final WindowState w) { 8785 final WindowStateAnimator winAnimator = w.mWinAnimator; 8786 if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { 8787 w.mContentInsetsChanged |= 8788 !w.mLastContentInsets.equals(w.mContentInsets); 8789 w.mVisibleInsetsChanged |= 8790 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 8791 boolean configChanged = w.isConfigChanged(); 8792 if (DEBUG_CONFIGURATION && configChanged) { 8793 Slog.v(TAG, "Win " + w + " config changed: " 8794 + mCurConfiguration); 8795 } 8796 if (localLOGV) Slog.v(TAG, "Resizing " + w 8797 + ": configChanged=" + configChanged 8798 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8799 w.mLastFrame.set(w.mFrame); 8800 if (w.mContentInsetsChanged 8801 || w.mVisibleInsetsChanged 8802 || winAnimator.mSurfaceResized 8803 || configChanged) { 8804 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8805 Slog.v(TAG, "Resize reasons: " 8806 + " contentInsetsChanged=" + w.mContentInsetsChanged 8807 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8808 + " surfaceResized=" + winAnimator.mSurfaceResized 8809 + " configChanged=" + configChanged); 8810 } 8811 8812 w.mLastContentInsets.set(w.mContentInsets); 8813 w.mLastVisibleInsets.set(w.mVisibleInsets); 8814 makeWindowFreezingScreenIfNeededLocked(w); 8815 // If the orientation is changing, then we need to 8816 // hold off on unfreezing the display until this 8817 // window has been redrawn; to do that, we need 8818 // to go through the process of getting informed 8819 // by the application when it has finished drawing. 8820 if (w.mOrientationChanging) { 8821 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8822 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8823 + w + ", surface " + winAnimator.mSurface); 8824 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8825 if (w.mAppToken != null) { 8826 w.mAppToken.allDrawn = false; 8827 } 8828 } 8829 if (!mResizingWindows.contains(w)) { 8830 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8831 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8832 + "x" + winAnimator.mSurfaceH); 8833 mResizingWindows.add(w); 8834 } 8835 } else if (w.mOrientationChanging) { 8836 if (w.isDrawnLw()) { 8837 if (DEBUG_ORIENTATION) Slog.v(TAG, 8838 "Orientation not waiting for draw in " 8839 + w + ", surface " + winAnimator.mSurface); 8840 w.mOrientationChanging = false; 8841 } 8842 } 8843 } 8844 } 8845 8846 /** 8847 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8848 * 8849 * @param w WindowState this method is applied to. 8850 * @param currentTime The time which animations use for calculating transitions. 8851 * @param innerDw Width of app window. 8852 * @param innerDh Height of app window. 8853 */ 8854 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8855 final int innerDw, final int innerDh) { 8856 final WindowManager.LayoutParams attrs = w.mAttrs; 8857 final int attrFlags = attrs.flags; 8858 final boolean canBeSeen = w.isDisplayedLw(); 8859 8860 if (w.mHasSurface) { 8861 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8862 mInnerFields.mHoldScreen = w.mSession; 8863 } 8864 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8865 && mInnerFields.mScreenBrightness < 0) { 8866 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8867 } 8868 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8869 && mInnerFields.mButtonBrightness < 0) { 8870 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8871 } 8872 if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0 8873 && mInnerFields.mUserActivityTimeout < 0) { 8874 mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout; 8875 } 8876 8877 final int type = attrs.type; 8878 if (canBeSeen 8879 && (type == TYPE_SYSTEM_DIALOG 8880 || type == TYPE_RECENTS_OVERLAY 8881 || type == TYPE_KEYGUARD 8882 || type == TYPE_SYSTEM_ERROR)) { 8883 mInnerFields.mSyswin = true; 8884 } 8885 8886 if (canBeSeen) { 8887 if (type == TYPE_DREAM || type == TYPE_KEYGUARD) { 8888 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR; 8889 } else if (mInnerFields.mDisplayHasContent 8890 == LayoutFields.DISPLAY_CONTENT_UNKNOWN) { 8891 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE; 8892 } 8893 } 8894 } 8895 8896 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8897 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8898 // This window completely covers everything behind it, 8899 // so we want to leave all of them as undimmed (for 8900 // performance reasons). 8901 mInnerFields.mObscured = true; 8902 } else if (canBeSeen && (attrFlags & FLAG_DIM_BEHIND) != 0 8903 && !(w.mAppToken != null && w.mAppToken.hiddenRequested) 8904 && !w.mExiting) { 8905 if (localLOGV) Slog.v(TAG, "Win " + w + " obscured=" + mInnerFields.mObscured); 8906 if (!mInnerFields.mDimming) { 8907 //Slog.i(TAG, "DIM BEHIND: " + w); 8908 mInnerFields.mDimming = true; 8909 final WindowStateAnimator winAnimator = w.mWinAnimator; 8910 if (!mAnimator.isDimmingLocked(winAnimator)) { 8911 final int width, height; 8912 if (attrs.type == TYPE_BOOT_PROGRESS) { 8913 final DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo(); 8914 width = displayInfo.logicalWidth; 8915 height = displayInfo.logicalHeight; 8916 } else { 8917 width = innerDw; 8918 height = innerDh; 8919 } 8920 startDimmingLocked( 8921 winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height); 8922 } 8923 } 8924 } 8925 } 8926 8927 private void updateAllDrawnLocked() { 8928 // See if any windows have been drawn, so they (and others 8929 // associated with them) can now be shown. 8930 final ArrayList<AppWindowToken> appTokens = mAnimatingAppTokens; 8931 final int NT = appTokens.size(); 8932 for (int i=0; i<NT; i++) { 8933 AppWindowToken wtoken = appTokens.get(i); 8934 if (!wtoken.allDrawn) { 8935 int numInteresting = wtoken.numInterestingWindows; 8936 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 8937 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 8938 "allDrawn: " + wtoken 8939 + " interesting=" + numInteresting 8940 + " drawn=" + wtoken.numDrawnWindows); 8941 wtoken.allDrawn = true; 8942 } 8943 } 8944 } 8945 } 8946 8947 // "Something has changed! Let's make it correct now." 8948 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 8949 if (DEBUG_WINDOW_TRACE) { 8950 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 8951 + Debug.getCallers(3)); 8952 } 8953 8954 final long currentTime = SystemClock.uptimeMillis(); 8955 8956 int i; 8957 8958 if (mFocusMayChange) { 8959 mFocusMayChange = false; 8960 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 8961 false /*updateInputWindows*/); 8962 } 8963 8964 // Initialize state of exiting tokens. 8965 for (i=mExitingTokens.size()-1; i>=0; i--) { 8966 mExitingTokens.get(i).hasVisible = false; 8967 } 8968 8969 // Initialize state of exiting applications. 8970 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8971 mExitingAppTokens.get(i).hasVisible = false; 8972 } 8973 8974 mInnerFields.mHoldScreen = null; 8975 mInnerFields.mScreenBrightness = -1; 8976 mInnerFields.mButtonBrightness = -1; 8977 mInnerFields.mUserActivityTimeout = -1; 8978 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN; 8979 8980 mTransactionSequence++; 8981 8982 final DisplayContent defaultDisplay = getDefaultDisplayContentLocked(); 8983 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 8984 final int defaultDw = defaultInfo.logicalWidth; 8985 final int defaultDh = defaultInfo.logicalHeight; 8986 8987 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8988 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 8989 Surface.openTransaction(); 8990 try { 8991 8992 if (mWatermark != null) { 8993 mWatermark.positionSurface(defaultDw, defaultDh); 8994 } 8995 if (mStrictModeFlash != null) { 8996 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 8997 } 8998 8999 boolean focusDisplayed = false; 9000 boolean updateAllDrawn = false; 9001 9002 DisplayContentsIterator iterator = new DisplayContentsIterator(); 9003 while (iterator.hasNext()) { 9004 final DisplayContent displayContent = iterator.next(); 9005 WindowList windows = displayContent.getWindowList(); 9006 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 9007 final int displayId = displayContent.getDisplayId(); 9008 final int dw = displayInfo.logicalWidth; 9009 final int dh = displayInfo.logicalHeight; 9010 final int innerDw = displayInfo.appWidth; 9011 final int innerDh = displayInfo.appHeight; 9012 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 9013 9014 // Reset for each display unless we are forcing mirroring. 9015 if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) { 9016 mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN; 9017 } 9018 9019 int repeats = 0; 9020 do { 9021 repeats++; 9022 if (repeats > 6) { 9023 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 9024 displayContent.layoutNeeded = false; 9025 break; 9026 } 9027 9028 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 9029 displayContent.pendingLayoutChanges); 9030 9031 if (isDefaultDisplay && ((displayContent.pendingLayoutChanges 9032 & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) 9033 && ((adjustWallpaperWindowsLocked() 9034 & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0)) { 9035 assignLayersLocked(windows); 9036 displayContent.layoutNeeded = true; 9037 } 9038 9039 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 9040 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 9041 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 9042 if (updateOrientationFromAppTokensLocked(true)) { 9043 displayContent.layoutNeeded = true; 9044 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9045 } 9046 } 9047 9048 if ((displayContent.pendingLayoutChanges 9049 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9050 displayContent.layoutNeeded = true; 9051 } 9052 9053 // FIRST LOOP: Perform a layout, if needed. 9054 if (repeats < 4) { 9055 performLayoutLockedInner(displayContent, repeats == 1, 9056 false /*updateInputWindows*/); 9057 } else { 9058 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 9059 } 9060 9061 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 9062 // it is animating. 9063 displayContent.pendingLayoutChanges = 0; 9064 9065 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 9066 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 9067 9068 if (isDefaultDisplay) { 9069 mPolicy.beginPostLayoutPolicyLw(dw, dh); 9070 for (i = windows.size() - 1; i >= 0; i--) { 9071 WindowState w = windows.get(i); 9072 if (w.mHasSurface) { 9073 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 9074 } 9075 } 9076 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 9077 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( 9078 "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges); 9079 } 9080 } while (displayContent.pendingLayoutChanges != 0); 9081 9082 mInnerFields.mObscured = false; 9083 mInnerFields.mDimming = false; 9084 mInnerFields.mSyswin = false; 9085 9086 // Only used if default window 9087 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 9088 9089 final int N = windows.size(); 9090 for (i=N-1; i>=0; i--) { 9091 WindowState w = windows.get(i); 9092 9093 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 9094 9095 // Update effect. 9096 w.mObscured = mInnerFields.mObscured; 9097 if (!mInnerFields.mObscured) { 9098 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 9099 } 9100 9101 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 9102 && w.isVisibleLw()) { 9103 // This is the wallpaper target and its obscured state 9104 // changed... make sure the current wallaper's visibility 9105 // has been updated accordingly. 9106 updateWallpaperVisibilityLocked(); 9107 } 9108 9109 final WindowStateAnimator winAnimator = w.mWinAnimator; 9110 9111 // If the window has moved due to its containing 9112 // content frame changing, then we'd like to animate 9113 // it. 9114 if (w.mHasSurface && w.shouldAnimateMove()) { 9115 // Frame has moved, containing content frame 9116 // has also moved, and we're not currently animating... 9117 // let's do something. 9118 Animation a = AnimationUtils.loadAnimation(mContext, 9119 com.android.internal.R.anim.window_move_from_decor); 9120 winAnimator.setAnimation(a); 9121 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 9122 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 9123 try { 9124 w.mClient.moved(w.mFrame.left, w.mFrame.top); 9125 } catch (RemoteException e) { 9126 } 9127 } 9128 9129 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 9130 w.mContentChanged = false; 9131 9132 // Moved from updateWindowsAndWallpaperLocked(). 9133 if (w.mHasSurface) { 9134 // Take care of the window being ready to display. 9135 final boolean committed = 9136 winAnimator.commitFinishDrawingLocked(currentTime); 9137 if (isDefaultDisplay && committed) { 9138 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 9139 if (DEBUG_WALLPAPER) Slog.v(TAG, 9140 "First draw done in potential wallpaper target " + w); 9141 mInnerFields.mWallpaperMayChange = true; 9142 displayContent.pendingLayoutChanges |= 9143 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 9144 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 9145 debugLayoutRepeats( 9146 "wallpaper and commitFinishDrawingLocked true", 9147 displayContent.pendingLayoutChanges); 9148 } 9149 } 9150 } 9151 9152 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 9153 9154 final AppWindowToken atoken = w.mAppToken; 9155 if (DEBUG_STARTING_WINDOW && atoken != null 9156 && w == atoken.startingWindow) { 9157 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 9158 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 9159 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 9160 } 9161 if (atoken != null 9162 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 9163 if (atoken.lastTransactionSequence != mTransactionSequence) { 9164 atoken.lastTransactionSequence = mTransactionSequence; 9165 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 9166 atoken.startingDisplayed = false; 9167 } 9168 if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION) 9169 && !w.mExiting && !w.mDestroying) { 9170 if (WindowManagerService.DEBUG_VISIBILITY || 9171 WindowManagerService.DEBUG_ORIENTATION) { 9172 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 9173 + ", isAnimating=" + winAnimator.isAnimating()); 9174 if (!w.isDrawnLw()) { 9175 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface 9176 + " pv=" + w.mPolicyVisibility 9177 + " mDrawState=" + winAnimator.mDrawState 9178 + " ah=" + w.mAttachedHidden 9179 + " th=" + atoken.hiddenRequested 9180 + " a=" + winAnimator.mAnimating); 9181 } 9182 } 9183 if (w != atoken.startingWindow) { 9184 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 9185 atoken.numInterestingWindows++; 9186 if (w.isDrawnLw()) { 9187 atoken.numDrawnWindows++; 9188 if (WindowManagerService.DEBUG_VISIBILITY || 9189 WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG, 9190 "tokenMayBeDrawn: " + atoken 9191 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 9192 + " mAppFreezing=" + w.mAppFreezing); 9193 updateAllDrawn = true; 9194 } 9195 } 9196 } else if (w.isDrawnLw()) { 9197 atoken.startingDisplayed = true; 9198 } 9199 } 9200 } 9201 } 9202 9203 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 9204 && w.isDisplayedLw()) { 9205 focusDisplayed = true; 9206 } 9207 9208 updateResizingWindows(w); 9209 } 9210 9211 final boolean hasUniqueContent; 9212 switch (mInnerFields.mDisplayHasContent) { 9213 case LayoutFields.DISPLAY_CONTENT_MIRROR: 9214 hasUniqueContent = isDefaultDisplay; 9215 break; 9216 case LayoutFields.DISPLAY_CONTENT_UNIQUE: 9217 hasUniqueContent = true; 9218 break; 9219 case LayoutFields.DISPLAY_CONTENT_UNKNOWN: 9220 default: 9221 hasUniqueContent = false; 9222 break; 9223 } 9224 mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent, 9225 true /* inTraversal, must call performTraversalInTrans... below */); 9226 9227 if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) { 9228 stopDimmingLocked(displayId); 9229 } 9230 } 9231 9232 if (updateAllDrawn) { 9233 updateAllDrawnLocked(); 9234 } 9235 9236 if (focusDisplayed) { 9237 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 9238 } 9239 9240 // Give the display manager a chance to adjust properties 9241 // like display rotation if it needs to. 9242 mDisplayManagerService.performTraversalInTransactionFromWindowManager(); 9243 9244 } catch (RuntimeException e) { 9245 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 9246 } finally { 9247 Surface.closeTransaction(); 9248 } 9249 9250 final WindowList defaultWindows = defaultDisplay.getWindowList(); 9251 9252 // If we are ready to perform an app transition, check through 9253 // all of the app tokens to be shown and see if they are ready 9254 // to go. 9255 if (mAppTransitionReady) { 9256 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 9257 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 9258 defaultDisplay.pendingLayoutChanges); 9259 } 9260 9261 mInnerFields.mAdjResult = 0; 9262 9263 if (!mAnimator.mAnimating && mAppTransitionRunning) { 9264 // We have finished the animation of an app transition. To do 9265 // this, we have delayed a lot of operations like showing and 9266 // hiding apps, moving apps in Z-order, etc. The app token list 9267 // reflects the correct Z-order, but the window list may now 9268 // be out of sync with it. So here we will just rebuild the 9269 // entire app window list. Fun! 9270 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 9271 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 9272 defaultDisplay.pendingLayoutChanges); 9273 } 9274 9275 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 9276 && !mAppTransitionReady) { 9277 // At this point, there was a window with a wallpaper that 9278 // was force hiding other windows behind it, but now it 9279 // is going away. This may be simple -- just animate 9280 // away the wallpaper and its window -- or it may be 9281 // hard -- the wallpaper now needs to be shown behind 9282 // something that was hidden. 9283 defaultDisplay.pendingLayoutChanges |= animateAwayWallpaperLocked(); 9284 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 9285 defaultDisplay.pendingLayoutChanges); 9286 } 9287 mInnerFields.mWallpaperForceHidingChanged = false; 9288 9289 if (mInnerFields.mWallpaperMayChange) { 9290 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 9291 "Wallpaper may change! Adjusting"); 9292 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 9293 } 9294 9295 if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 9296 if (DEBUG_WALLPAPER) Slog.v(TAG, 9297 "Wallpaper layer changed: assigning layers + relayout"); 9298 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9299 assignLayersLocked(defaultWindows); 9300 } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { 9301 if (DEBUG_WALLPAPER) Slog.v(TAG, 9302 "Wallpaper visibility changed: relayout"); 9303 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9304 } 9305 9306 if (mFocusMayChange) { 9307 mFocusMayChange = false; 9308 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 9309 false /*updateInputWindows*/)) { 9310 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 9311 mInnerFields.mAdjResult = 0; 9312 } 9313 } 9314 9315 if (needsLayout()) { 9316 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9317 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 9318 defaultDisplay.pendingLayoutChanges); 9319 } 9320 9321 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 9322 WindowState win = mResizingWindows.get(i); 9323 if (win.mAppFreezing) { 9324 // Don't remove this window until rotation has completed. 9325 continue; 9326 } 9327 final WindowStateAnimator winAnimator = win.mWinAnimator; 9328 try { 9329 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 9330 "Reporting new frame to " + win + ": " + win.mCompatFrame); 9331 int diff = 0; 9332 boolean configChanged = win.isConfigChanged(); 9333 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION 9334 // TODO: Remove once b/7094175 is fixed 9335 || ((String)win.mAttrs.getTitle()).contains("Keyguard")) 9336 && configChanged) { 9337 Slog.i(TAG, "Sending new config to window " + win + ": " 9338 + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH 9339 + " / " + mCurConfiguration + " / 0x" 9340 + Integer.toHexString(diff)); 9341 } 9342 win.mConfiguration = mCurConfiguration; 9343 if (DEBUG_ORIENTATION && 9344 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( 9345 TAG, "Resizing " + win + " WITH DRAW PENDING"); 9346 win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets, 9347 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING, 9348 configChanged ? win.mConfiguration : null); 9349 win.mContentInsetsChanged = false; 9350 win.mVisibleInsetsChanged = false; 9351 winAnimator.mSurfaceResized = false; 9352 } catch (RemoteException e) { 9353 win.mOrientationChanging = false; 9354 } 9355 mResizingWindows.remove(i); 9356 } 9357 9358 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 9359 "With display frozen, orientationChangeComplete=" 9360 + mInnerFields.mOrientationChangeComplete); 9361 if (mInnerFields.mOrientationChangeComplete) { 9362 if (mWindowsFreezingScreen) { 9363 mWindowsFreezingScreen = false; 9364 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 9365 } 9366 stopFreezingDisplayLocked(); 9367 } 9368 9369 // Destroy the surface of any windows that are no longer visible. 9370 boolean wallpaperDestroyed = false; 9371 i = mDestroySurface.size(); 9372 if (i > 0) { 9373 do { 9374 i--; 9375 WindowState win = mDestroySurface.get(i); 9376 win.mDestroying = false; 9377 if (mInputMethodWindow == win) { 9378 mInputMethodWindow = null; 9379 } 9380 if (win == mWallpaperTarget) { 9381 wallpaperDestroyed = true; 9382 } 9383 win.mWinAnimator.destroySurfaceLocked(); 9384 } while (i > 0); 9385 mDestroySurface.clear(); 9386 } 9387 9388 // Time to remove any exiting tokens? 9389 for (i=mExitingTokens.size()-1; i>=0; i--) { 9390 WindowToken token = mExitingTokens.get(i); 9391 if (!token.hasVisible) { 9392 mExitingTokens.remove(i); 9393 if (token.windowType == TYPE_WALLPAPER) { 9394 mWallpaperTokens.remove(token); 9395 updateLayoutToAnimWallpaperTokens(); 9396 } 9397 } 9398 } 9399 9400 // Time to remove any exiting applications? 9401 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 9402 AppWindowToken token = mExitingAppTokens.get(i); 9403 if (!token.hasVisible && !mClosingApps.contains(token)) { 9404 // Make sure there is no animation running on this token, 9405 // so any windows associated with it will be removed as 9406 // soon as their animations are complete 9407 token.mAppAnimator.clearAnimation(); 9408 token.mAppAnimator.animating = false; 9409 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 9410 "performLayout: App token exiting now removed" + token); 9411 mAppTokens.remove(token); 9412 mAnimatingAppTokens.remove(token); 9413 mExitingAppTokens.remove(i); 9414 } 9415 } 9416 9417 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 9418 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 9419 try { 9420 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 9421 } catch (RemoteException e) { 9422 } 9423 } 9424 mRelayoutWhileAnimating.clear(); 9425 } 9426 9427 if (wallpaperDestroyed && (adjustWallpaperWindowsLocked() != 0)) { 9428 getDefaultDisplayContentLocked().layoutNeeded = true; 9429 } 9430 9431 DisplayContentsIterator iterator = new DisplayContentsIterator(); 9432 while (iterator.hasNext()) { 9433 DisplayContent displayContent = iterator.next(); 9434 if (displayContent.pendingLayoutChanges != 0) { 9435 displayContent.layoutNeeded = true; 9436 } 9437 } 9438 9439 // Finally update all input windows now that the window changes have stabilized. 9440 mInputMonitor.updateInputWindowsLw(true /*force*/); 9441 9442 setHoldScreenLocked(mInnerFields.mHoldScreen); 9443 if (!mDisplayFrozen) { 9444 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 9445 mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1); 9446 } else { 9447 mPowerManager.setScreenBrightnessOverrideFromWindowManager( 9448 toBrightnessOverride(mInnerFields.mScreenBrightness)); 9449 } 9450 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 9451 mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1); 9452 } else { 9453 mPowerManager.setButtonBrightnessOverrideFromWindowManager( 9454 toBrightnessOverride(mInnerFields.mButtonBrightness)); 9455 } 9456 mPowerManager.setUserActivityTimeoutOverrideFromWindowManager( 9457 mInnerFields.mUserActivityTimeout); 9458 } 9459 9460 if (mTurnOnScreen) { 9461 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9462 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9463 mTurnOnScreen = false; 9464 } 9465 9466 if (mInnerFields.mUpdateRotation) { 9467 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9468 if (updateRotationUncheckedLocked(false)) { 9469 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9470 } else { 9471 mInnerFields.mUpdateRotation = false; 9472 } 9473 } 9474 9475 if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded 9476 && !mInnerFields.mUpdateRotation) { 9477 checkDrawnWindowsLocked(); 9478 } 9479 9480 final int N = mPendingRemove.size(); 9481 if (N > 0) { 9482 if (mPendingRemoveTmp.length < N) { 9483 mPendingRemoveTmp = new WindowState[N+10]; 9484 } 9485 mPendingRemove.toArray(mPendingRemoveTmp); 9486 mPendingRemove.clear(); 9487 DisplayContentList displayList = new DisplayContentList(); 9488 for (i = 0; i < N; i++) { 9489 WindowState w = mPendingRemoveTmp[i]; 9490 removeWindowInnerLocked(w.mSession, w); 9491 if (!displayList.contains(w.mDisplayContent)) { 9492 displayList.add(w.mDisplayContent); 9493 } 9494 } 9495 9496 for (DisplayContent displayContent : displayList) { 9497 assignLayersLocked(displayContent.getWindowList()); 9498 displayContent.layoutNeeded = true; 9499 } 9500 } 9501 9502 // Check to see if we are now in a state where the screen should 9503 // be enabled, because the window obscured flags have changed. 9504 enableScreenIfNeededLocked(); 9505 9506 updateLayoutToAnimationLocked(); 9507 9508 if (DEBUG_WINDOW_TRACE) { 9509 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" 9510 + mAnimator.mAnimating); 9511 } 9512 } 9513 9514 private int toBrightnessOverride(float value) { 9515 return (int)(value * PowerManager.BRIGHTNESS_ON); 9516 } 9517 9518 void checkDrawnWindowsLocked() { 9519 if (mWaitingForDrawn.size() > 0) { 9520 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 9521 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 9522 WindowState win = pair.first; 9523 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 9524 // + win.mRemoved + " visible=" + win.isVisibleLw() 9525 // + " shown=" + win.mSurfaceShown); 9526 if (win.mRemoved || !win.isVisibleLw()) { 9527 // Window has been removed or made invisible; no draw 9528 // will now happen, so stop waiting. 9529 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 9530 try { 9531 pair.second.sendResult(null); 9532 } catch (RemoteException e) { 9533 } 9534 mWaitingForDrawn.remove(pair); 9535 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9536 } else if (win.mWinAnimator.mSurfaceShown) { 9537 // Window is now drawn (and shown). 9538 try { 9539 pair.second.sendResult(null); 9540 } catch (RemoteException e) { 9541 } 9542 mWaitingForDrawn.remove(pair); 9543 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9544 } 9545 } 9546 } 9547 } 9548 9549 public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 9550 if (token != null && callback != null) { 9551 synchronized (mWindowMap) { 9552 WindowState win = windowForClientLocked(null, token, true); 9553 if (win != null) { 9554 Pair<WindowState, IRemoteCallback> pair = 9555 new Pair<WindowState, IRemoteCallback>(win, callback); 9556 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9557 mH.sendMessageDelayed(m, 2000); 9558 mWaitingForDrawn.add(pair); 9559 checkDrawnWindowsLocked(); 9560 return true; 9561 } 9562 } 9563 } 9564 return false; 9565 } 9566 9567 void setHoldScreenLocked(final Session newHoldScreen) { 9568 final boolean hold = newHoldScreen != null; 9569 9570 if (hold && mHoldingScreenOn != newHoldScreen) { 9571 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9572 } 9573 mHoldingScreenOn = newHoldScreen; 9574 9575 final boolean state = mHoldingScreenWakeLock.isHeld(); 9576 if (hold != state) { 9577 if (hold) { 9578 mHoldingScreenWakeLock.acquire(); 9579 mPolicy.keepScreenOnStartedLw(); 9580 } else { 9581 mPolicy.keepScreenOnStoppedLw(); 9582 mHoldingScreenWakeLock.release(); 9583 } 9584 } 9585 } 9586 9587 @Override 9588 public void requestTraversal() { 9589 synchronized (mWindowMap) { 9590 requestTraversalLocked(); 9591 } 9592 } 9593 9594 void requestTraversalLocked() { 9595 if (!mTraversalScheduled) { 9596 mTraversalScheduled = true; 9597 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9598 } 9599 } 9600 9601 /** Note that Locked in this case is on mLayoutToAnim */ 9602 void scheduleAnimationLocked() { 9603 final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim; 9604 if (!layoutToAnim.mAnimationScheduled) { 9605 layoutToAnim.mAnimationScheduled = true; 9606 mChoreographer.postCallback( 9607 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9608 } 9609 } 9610 9611 void updateLayoutToAnimationLocked() { 9612 final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim; 9613 synchronized (layoutToAnim) { 9614 // Copy local params to transfer params. 9615 SparseArray<WinAnimatorList> allWinAnimatorLists = layoutToAnim.mWinAnimatorLists; 9616 allWinAnimatorLists.clear(); 9617 DisplayContentsIterator iterator = new DisplayContentsIterator(); 9618 while (iterator.hasNext()) { 9619 final DisplayContent displayContent = iterator.next(); 9620 WinAnimatorList winAnimatorList = new WinAnimatorList(); 9621 final WindowList windows = displayContent.getWindowList(); 9622 int N = windows.size(); 9623 for (int i = 0; i < N; i++) { 9624 final WindowStateAnimator winAnimator = windows.get(i).mWinAnimator; 9625 if (winAnimator.mSurface != null) { 9626 winAnimatorList.add(winAnimator); 9627 } 9628 } 9629 allWinAnimatorLists.put(displayContent.getDisplayId(), winAnimatorList); 9630 } 9631 9632 layoutToAnim.mWallpaperTarget = mWallpaperTarget; 9633 layoutToAnim.mLowerWallpaperTarget = mLowerWallpaperTarget; 9634 layoutToAnim.mUpperWallpaperTarget = mUpperWallpaperTarget; 9635 9636 final ArrayList<AppWindowAnimParams> paramList = layoutToAnim.mAppWindowAnimParams; 9637 paramList.clear(); 9638 int N = mAnimatingAppTokens.size(); 9639 for (int i = 0; i < N; i++) { 9640 paramList.add(new AppWindowAnimParams(mAnimatingAppTokens.get(i).mAppAnimator)); 9641 } 9642 9643 layoutToAnim.mParamsModified = true; 9644 scheduleAnimationLocked(); 9645 } 9646 } 9647 9648 void updateLayoutToAnimWallpaperTokens() { 9649 synchronized(mLayoutToAnim) { 9650 mLayoutToAnim.mWallpaperTokens = new ArrayList<WindowToken>(mWallpaperTokens); 9651 mLayoutToAnim.mChanges |= LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED; 9652 } 9653 } 9654 9655 void setAnimDimParams(int displayId, DimAnimator.Parameters params) { 9656 synchronized (mLayoutToAnim) { 9657 mLayoutToAnim.mDimParams.put(displayId, params); 9658 scheduleAnimationLocked(); 9659 } 9660 } 9661 9662 void startDimmingLocked(final WindowStateAnimator winAnimator, final float target, 9663 final int width, final int height) { 9664 setAnimDimParams(winAnimator.mWin.getDisplayId(), 9665 new DimAnimator.Parameters(winAnimator, width, height, target)); 9666 } 9667 9668 void stopDimmingLocked(int displayId) { 9669 setAnimDimParams(displayId, null); 9670 } 9671 9672 private boolean needsLayout() { 9673 DisplayContentsIterator iterator = new DisplayContentsIterator(); 9674 while (iterator.hasNext()) { 9675 if (iterator.next().layoutNeeded) { 9676 return true; 9677 } 9678 } 9679 return false; 9680 } 9681 9682 private boolean copyAnimToLayoutParamsLocked() { 9683 boolean doRequest = false; 9684 final WindowAnimator.AnimatorToLayoutParams animToLayout = mAnimator.mAnimToLayout; 9685 synchronized (animToLayout) { 9686 animToLayout.mUpdateQueued = false; 9687 final int bulkUpdateParams = animToLayout.mBulkUpdateParams; 9688 // TODO(cmautner): As the number of bits grows, use masks of bit groups to 9689 // eliminate unnecessary tests. 9690 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9691 mInnerFields.mUpdateRotation = true; 9692 doRequest = true; 9693 } 9694 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9695 mInnerFields.mWallpaperMayChange = true; 9696 doRequest = true; 9697 } 9698 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9699 mInnerFields.mWallpaperForceHidingChanged = true; 9700 doRequest = true; 9701 } 9702 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9703 mInnerFields.mOrientationChangeComplete = false; 9704 } else { 9705 mInnerFields.mOrientationChangeComplete = true; 9706 if (mWindowsFreezingScreen) { 9707 doRequest = true; 9708 } 9709 } 9710 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9711 mTurnOnScreen = true; 9712 } 9713 9714 SparseIntArray pendingLayouts = animToLayout.mPendingLayoutChanges; 9715 final int count = pendingLayouts.size(); 9716 if (count > 0) { 9717 doRequest = true; 9718 } 9719 for (int i = 0; i < count; ++i) { 9720 final DisplayContent displayContent = 9721 getDisplayContentLocked(pendingLayouts.keyAt(i)); 9722 displayContent.pendingLayoutChanges |= pendingLayouts.valueAt(i); 9723 } 9724 9725 mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper; 9726 } 9727 return doRequest; 9728 } 9729 9730 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9731 boolean secure) { 9732 final Surface surface = winAnimator.mSurface; 9733 boolean leakedSurface = false; 9734 boolean killedApps = false; 9735 9736 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9737 winAnimator.mSession.mPid, operation); 9738 9739 if (mForceRemoves == null) { 9740 mForceRemoves = new ArrayList<WindowState>(); 9741 } 9742 9743 long callingIdentity = Binder.clearCallingIdentity(); 9744 try { 9745 // There was some problem... first, do a sanity check of the 9746 // window list to make sure we haven't left any dangling surfaces 9747 // around. 9748 9749 AllWindowsIterator iterator = new AllWindowsIterator(); 9750 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9751 while (iterator.hasNext()) { 9752 WindowState ws = iterator.next(); 9753 WindowStateAnimator wsa = ws.mWinAnimator; 9754 if (wsa.mSurface != null) { 9755 if (!mSessions.contains(wsa.mSession)) { 9756 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9757 + ws + " surface=" + wsa.mSurface 9758 + " token=" + ws.mToken 9759 + " pid=" + ws.mSession.mPid 9760 + " uid=" + ws.mSession.mUid); 9761 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9762 wsa.mSurface.destroy(); 9763 wsa.mSurfaceShown = false; 9764 wsa.mSurface = null; 9765 ws.mHasSurface = false; 9766 mForceRemoves.add(ws); 9767 leakedSurface = true; 9768 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9769 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9770 + ws + " surface=" + wsa.mSurface 9771 + " token=" + ws.mAppToken); 9772 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9773 wsa.mSurface.destroy(); 9774 wsa.mSurfaceShown = false; 9775 wsa.mSurface = null; 9776 ws.mHasSurface = false; 9777 leakedSurface = true; 9778 } 9779 } 9780 } 9781 9782 if (!leakedSurface) { 9783 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9784 SparseIntArray pidCandidates = new SparseIntArray(); 9785 iterator = new AllWindowsIterator(); 9786 while (iterator.hasNext()) { 9787 WindowState ws = iterator.next(); 9788 if (mForceRemoves.contains(ws)) { 9789 continue; 9790 } 9791 WindowStateAnimator wsa = ws.mWinAnimator; 9792 if (wsa.mSurface != null) { 9793 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9794 } 9795 } 9796 if (pidCandidates.size() > 0) { 9797 int[] pids = new int[pidCandidates.size()]; 9798 for (int i=0; i<pids.length; i++) { 9799 pids[i] = pidCandidates.keyAt(i); 9800 } 9801 try { 9802 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9803 killedApps = true; 9804 } 9805 } catch (RemoteException e) { 9806 } 9807 } 9808 } 9809 9810 if (leakedSurface || killedApps) { 9811 // We managed to reclaim some memory, so get rid of the trouble 9812 // surface and ask the app to request another one. 9813 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9814 if (surface != null) { 9815 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9816 "RECOVER DESTROY", null); 9817 surface.destroy(); 9818 winAnimator.mSurfaceShown = false; 9819 winAnimator.mSurface = null; 9820 winAnimator.mWin.mHasSurface = false; 9821 } 9822 9823 try { 9824 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9825 } catch (RemoteException e) { 9826 } 9827 } 9828 } finally { 9829 Binder.restoreCallingIdentity(callingIdentity); 9830 } 9831 9832 return leakedSurface || killedApps; 9833 } 9834 9835 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9836 WindowState newFocus = computeFocusedWindowLocked(); 9837 if (mCurrentFocus != newFocus) { 9838 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9839 // This check makes sure that we don't already have the focus 9840 // change message pending. 9841 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9842 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9843 if (localLOGV) Slog.v( 9844 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 9845 final WindowState oldFocus = mCurrentFocus; 9846 mCurrentFocus = newFocus; 9847 mAnimator.setCurrentFocus(newFocus); 9848 mLosingFocus.remove(newFocus); 9849 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9850 9851 // TODO(multidisplay): Focused windows on default display only. 9852 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 9853 9854 final WindowState imWindow = mInputMethodWindow; 9855 if (newFocus != imWindow && oldFocus != imWindow) { 9856 if (moveInputMethodWindowsIfNeededLocked( 9857 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 9858 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 9859 displayContent.layoutNeeded = true; 9860 } 9861 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9862 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9863 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9864 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9865 // Client will do the layout, but we need to assign layers 9866 // for handleNewWindowLocked() below. 9867 assignLayersLocked(displayContent.getWindowList()); 9868 } 9869 } 9870 9871 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9872 // The change in focus caused us to need to do a layout. Okay. 9873 displayContent.layoutNeeded = true; 9874 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9875 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9876 } 9877 } 9878 9879 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9880 // If we defer assigning layers, then the caller is responsible for 9881 // doing this part. 9882 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9883 } 9884 9885 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9886 return true; 9887 } 9888 return false; 9889 } 9890 9891 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9892 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9893 } 9894 9895 private WindowState computeFocusedWindowLocked() { 9896 if (mAnimator.mUniverseBackground != null 9897 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9898 return mAnimator.mUniverseBackground.mWin; 9899 } 9900 9901 final int displayCount = mDisplayContents.size(); 9902 for (int i = 0; i < displayCount; i++) { 9903 final DisplayContent displayContent = mDisplayContents.valueAt(i); 9904 WindowState win = findFocusedWindowLocked(displayContent); 9905 if (win != null) { 9906 return win; 9907 } 9908 } 9909 return null; 9910 } 9911 9912 private WindowState findFocusedWindowLocked(DisplayContent displayContent) { 9913 int nextAppIndex = mAppTokens.size()-1; 9914 WindowToken nextApp = nextAppIndex >= 0 ? mAppTokens.get(nextAppIndex) : null; 9915 9916 final WindowList windows = displayContent.getWindowList(); 9917 for (int i = windows.size() - 1; i >= 0; i--) { 9918 final WindowState win = windows.get(i); 9919 9920 if (localLOGV || DEBUG_FOCUS) Slog.v( 9921 TAG, "Looking for focus: " + i 9922 + " = " + win 9923 + ", flags=" + win.mAttrs.flags 9924 + ", canReceive=" + win.canReceiveKeys()); 9925 9926 AppWindowToken thisApp = win.mAppToken; 9927 9928 // If this window's application has been removed, just skip it. 9929 if (thisApp != null && (thisApp.removed || thisApp.sendingToBottom)) { 9930 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping app because " + (thisApp.removed 9931 ? "removed" : "sendingToBottom")); 9932 continue; 9933 } 9934 9935 // If there is a focused app, don't allow focus to go to any 9936 // windows below it. If this is an application window, step 9937 // through the app tokens until we find its app. 9938 if (thisApp != null && nextApp != null && thisApp != nextApp 9939 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 9940 int origAppIndex = nextAppIndex; 9941 while (nextAppIndex > 0) { 9942 if (nextApp == mFocusedApp) { 9943 // Whoops, we are below the focused app... no focus 9944 // for you! 9945 if (localLOGV || DEBUG_FOCUS) Slog.v( 9946 TAG, "Reached focused app: " + mFocusedApp); 9947 return null; 9948 } 9949 nextAppIndex--; 9950 nextApp = mAppTokens.get(nextAppIndex); 9951 if (nextApp == thisApp) { 9952 break; 9953 } 9954 } 9955 if (thisApp != nextApp) { 9956 // Uh oh, the app token doesn't exist! This shouldn't 9957 // happen, but if it does we can get totally hosed... 9958 // so restart at the original app. 9959 nextAppIndex = origAppIndex; 9960 nextApp = mAppTokens.get(nextAppIndex); 9961 } 9962 } 9963 9964 // Dispatch to this window if it is wants key events. 9965 if (win.canReceiveKeys()) { 9966 if (DEBUG_FOCUS) Slog.v( 9967 TAG, "Found focus @ " + i + " = " + win); 9968 return win; 9969 } 9970 } 9971 return null; 9972 } 9973 9974 private void startFreezingDisplayLocked(boolean inTransaction, 9975 int exitAnim, int enterAnim) { 9976 if (mDisplayFrozen) { 9977 return; 9978 } 9979 9980 if (!mDisplayReady || !mPolicy.isScreenOnFully()) { 9981 // No need to freeze the screen before the system is ready or if 9982 // the screen is off. 9983 return; 9984 } 9985 9986 mScreenFrozenLock.acquire(); 9987 9988 mDisplayFrozen = true; 9989 9990 mInputMonitor.freezeInputDispatchingLw(); 9991 9992 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 9993 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 9994 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 9995 mNextAppTransitionPackage = null; 9996 mNextAppTransitionThumbnail = null; 9997 mAppTransitionReady = true; 9998 } 9999 10000 if (PROFILE_ORIENTATION) { 10001 File file = new File("/data/system/frozen"); 10002 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 10003 } 10004 10005 if (CUSTOM_SCREEN_ROTATION) { 10006 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10007 final int displayId = displayContent.getDisplayId(); 10008 ScreenRotationAnimation screenRotationAnimation = 10009 mAnimator.getScreenRotationAnimationLocked(displayId); 10010 if (screenRotationAnimation != null) { 10011 screenRotationAnimation.kill(); 10012 } 10013 10014 // TODO(multidisplay): rotation on main screen only. 10015 final Display display = displayContent.getDisplay(); 10016 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10017 screenRotationAnimation = new ScreenRotationAnimation(mContext, 10018 display, mFxSession, inTransaction, displayInfo.logicalWidth, 10019 displayInfo.logicalHeight, display.getRotation(), 10020 exitAnim, enterAnim); 10021 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10022 } 10023 } 10024 10025 private void stopFreezingDisplayLocked() { 10026 if (!mDisplayFrozen) { 10027 return; 10028 } 10029 10030 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen 10031 || mClientFreezingScreen) { 10032 if (DEBUG_ORIENTATION) Slog.d(TAG, 10033 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 10034 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 10035 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen 10036 + ", mClientFreezingScreen=" + mClientFreezingScreen); 10037 return; 10038 } 10039 10040 mDisplayFrozen = false; 10041 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 10042 mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); 10043 if (PROFILE_ORIENTATION) { 10044 Debug.stopMethodTracing(); 10045 } 10046 10047 boolean updateRotation = false; 10048 10049 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 10050 final int displayId = displayContent.getDisplayId(); 10051 ScreenRotationAnimation screenRotationAnimation = 10052 mAnimator.getScreenRotationAnimationLocked(displayId); 10053 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null 10054 && screenRotationAnimation.hasScreenshot()) { 10055 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 10056 // TODO(multidisplay): rotation on main screen only. 10057 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 10058 if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 10059 mTransitionAnimationScale, displayInfo.logicalWidth, 10060 displayInfo.logicalHeight)) { 10061 updateLayoutToAnimationLocked(); 10062 } else { 10063 screenRotationAnimation.kill(); 10064 screenRotationAnimation = null; 10065 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10066 updateRotation = true; 10067 } 10068 } else { 10069 if (screenRotationAnimation != null) { 10070 screenRotationAnimation.kill(); 10071 screenRotationAnimation = null; 10072 mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); 10073 } 10074 updateRotation = true; 10075 } 10076 10077 mInputMonitor.thawInputDispatchingLw(); 10078 10079 boolean configChanged; 10080 10081 // While the display is frozen we don't re-compute the orientation 10082 // to avoid inconsistent states. However, something interesting 10083 // could have actually changed during that time so re-evaluate it 10084 // now to catch that. 10085 configChanged = updateOrientationFromAppTokensLocked(false); 10086 10087 // A little kludge: a lot could have happened while the 10088 // display was frozen, so now that we are coming back we 10089 // do a gc so that any remote references the system 10090 // processes holds on others can be released if they are 10091 // no longer needed. 10092 mH.removeMessages(H.FORCE_GC); 10093 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 10094 2000); 10095 10096 mScreenFrozenLock.release(); 10097 10098 if (updateRotation) { 10099 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 10100 configChanged |= updateRotationUncheckedLocked(false); 10101 } 10102 10103 if (configChanged) { 10104 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 10105 } 10106 } 10107 10108 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 10109 DisplayMetrics dm) { 10110 if (index < tokens.length) { 10111 String str = tokens[index]; 10112 if (str != null && str.length() > 0) { 10113 try { 10114 int val = Integer.parseInt(str); 10115 return val; 10116 } catch (Exception e) { 10117 } 10118 } 10119 } 10120 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 10121 return defDps; 10122 } 10123 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 10124 return val; 10125 } 10126 10127 void createWatermarkInTransaction() { 10128 if (mWatermark != null) { 10129 return; 10130 } 10131 10132 File file = new File("/system/etc/setup.conf"); 10133 FileInputStream in = null; 10134 try { 10135 in = new FileInputStream(file); 10136 DataInputStream ind = new DataInputStream(in); 10137 String line = ind.readLine(); 10138 if (line != null) { 10139 String[] toks = line.split("%"); 10140 if (toks != null && toks.length > 0) { 10141 mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(), 10142 mRealDisplayMetrics, mFxSession, toks); 10143 } 10144 } 10145 } catch (FileNotFoundException e) { 10146 } catch (IOException e) { 10147 } finally { 10148 if (in != null) { 10149 try { 10150 in.close(); 10151 } catch (IOException e) { 10152 } 10153 } 10154 } 10155 } 10156 10157 @Override 10158 public void statusBarVisibilityChanged(int visibility) { 10159 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 10160 != PackageManager.PERMISSION_GRANTED) { 10161 throw new SecurityException("Caller does not hold permission " 10162 + android.Manifest.permission.STATUS_BAR); 10163 } 10164 10165 synchronized (mWindowMap) { 10166 mLastStatusBarVisibility = visibility; 10167 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 10168 updateStatusBarVisibilityLocked(visibility); 10169 } 10170 } 10171 10172 // TOOD(multidisplay): StatusBar on multiple screens? 10173 void updateStatusBarVisibilityLocked(int visibility) { 10174 mInputManager.setSystemUiVisibility(visibility); 10175 final WindowList windows = getDefaultWindowListLocked(); 10176 final int N = windows.size(); 10177 for (int i = 0; i < N; i++) { 10178 WindowState ws = windows.get(i); 10179 try { 10180 int curValue = ws.mSystemUiVisibility; 10181 int diff = curValue ^ visibility; 10182 // We are only interested in differences of one of the 10183 // clearable flags... 10184 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 10185 // ...if it has actually been cleared. 10186 diff &= ~visibility; 10187 int newValue = (curValue&~diff) | (visibility&diff); 10188 if (newValue != curValue) { 10189 ws.mSeq++; 10190 ws.mSystemUiVisibility = newValue; 10191 } 10192 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 10193 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 10194 visibility, newValue, diff); 10195 } 10196 } catch (RemoteException e) { 10197 // so sorry 10198 } 10199 } 10200 } 10201 10202 @Override 10203 public void reevaluateStatusBarVisibility() { 10204 synchronized (mWindowMap) { 10205 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 10206 updateStatusBarVisibilityLocked(visibility); 10207 performLayoutAndPlaceSurfacesLocked(); 10208 } 10209 } 10210 10211 @Override 10212 public FakeWindow addFakeWindow(Looper looper, 10213 InputEventReceiver.Factory inputEventReceiverFactory, 10214 String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys, 10215 boolean hasFocus, boolean touchFullscreen) { 10216 synchronized (mWindowMap) { 10217 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 10218 name, windowType, 10219 layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 10220 int i=0; 10221 while (i<mFakeWindows.size()) { 10222 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 10223 break; 10224 } 10225 } 10226 mFakeWindows.add(i, fw); 10227 mInputMonitor.updateInputWindowsLw(true); 10228 return fw; 10229 } 10230 } 10231 10232 boolean removeFakeWindowLocked(FakeWindow window) { 10233 synchronized (mWindowMap) { 10234 if (mFakeWindows.remove(window)) { 10235 mInputMonitor.updateInputWindowsLw(true); 10236 return true; 10237 } 10238 return false; 10239 } 10240 } 10241 10242 // It is assumed that this method is called only by InputMethodManagerService. 10243 public void saveLastInputMethodWindowForTransition() { 10244 synchronized (mWindowMap) { 10245 // TODO(multidisplay): Pass in the displayID. 10246 DisplayContent displayContent = getDefaultDisplayContentLocked(); 10247 if (mInputMethodWindow != null) { 10248 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 10249 } 10250 } 10251 } 10252 10253 @Override 10254 public boolean hasNavigationBar() { 10255 return mPolicy.hasNavigationBar(); 10256 } 10257 10258 public void lockNow(Bundle options) { 10259 mPolicy.lockNow(options); 10260 } 10261 10262 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 10263 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 10264 mPolicy.dump(" ", pw, args); 10265 } 10266 10267 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 10268 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 10269 if (mTokenMap.size() > 0) { 10270 pw.println(" All tokens:"); 10271 Iterator<WindowToken> it = mTokenMap.values().iterator(); 10272 while (it.hasNext()) { 10273 WindowToken token = it.next(); 10274 pw.print(" Token "); pw.print(token.token); 10275 if (dumpAll) { 10276 pw.println(':'); 10277 token.dump(pw, " "); 10278 } else { 10279 pw.println(); 10280 } 10281 } 10282 } 10283 if (mWallpaperTokens.size() > 0) { 10284 pw.println(); 10285 pw.println(" Wallpaper tokens:"); 10286 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 10287 WindowToken token = mWallpaperTokens.get(i); 10288 pw.print(" Wallpaper #"); pw.print(i); 10289 pw.print(' '); pw.print(token); 10290 if (dumpAll) { 10291 pw.println(':'); 10292 token.dump(pw, " "); 10293 } else { 10294 pw.println(); 10295 } 10296 } 10297 } 10298 if (mAppTokens.size() > 0) { 10299 pw.println(); 10300 pw.println(" Application tokens in Z order:"); 10301 for (int i=mAppTokens.size()-1; i>=0; i--) { 10302 pw.print(" App #"); pw.print(i); pw.println(": "); 10303 mAppTokens.get(i).dump(pw, " "); 10304 } 10305 } 10306 if (mFinishedStarting.size() > 0) { 10307 pw.println(); 10308 pw.println(" Finishing start of application tokens:"); 10309 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 10310 WindowToken token = mFinishedStarting.get(i); 10311 pw.print(" Finished Starting #"); pw.print(i); 10312 pw.print(' '); pw.print(token); 10313 if (dumpAll) { 10314 pw.println(':'); 10315 token.dump(pw, " "); 10316 } else { 10317 pw.println(); 10318 } 10319 } 10320 } 10321 if (mExitingTokens.size() > 0) { 10322 pw.println(); 10323 pw.println(" Exiting tokens:"); 10324 for (int i=mExitingTokens.size()-1; i>=0; i--) { 10325 WindowToken token = mExitingTokens.get(i); 10326 pw.print(" Exiting #"); pw.print(i); 10327 pw.print(' '); pw.print(token); 10328 if (dumpAll) { 10329 pw.println(':'); 10330 token.dump(pw, " "); 10331 } else { 10332 pw.println(); 10333 } 10334 } 10335 } 10336 if (mExitingAppTokens.size() > 0) { 10337 pw.println(); 10338 pw.println(" Exiting application tokens:"); 10339 for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 10340 WindowToken token = mExitingAppTokens.get(i); 10341 pw.print(" Exiting App #"); pw.print(i); 10342 pw.print(' '); pw.print(token); 10343 if (dumpAll) { 10344 pw.println(':'); 10345 token.dump(pw, " "); 10346 } else { 10347 pw.println(); 10348 } 10349 } 10350 } 10351 if (mAppTransitionRunning && mAnimatingAppTokens.size() > 0) { 10352 pw.println(); 10353 pw.println(" Application tokens during animation:"); 10354 for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) { 10355 WindowToken token = mAnimatingAppTokens.get(i); 10356 pw.print(" App moving to bottom #"); pw.print(i); 10357 pw.print(' '); pw.print(token); 10358 if (dumpAll) { 10359 pw.println(':'); 10360 token.dump(pw, " "); 10361 } else { 10362 pw.println(); 10363 } 10364 } 10365 } 10366 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 10367 pw.println(); 10368 if (mOpeningApps.size() > 0) { 10369 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 10370 } 10371 if (mClosingApps.size() > 0) { 10372 pw.print(" mClosingApps="); pw.println(mClosingApps); 10373 } 10374 } 10375 } 10376 10377 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 10378 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 10379 if (mSessions.size() > 0) { 10380 Iterator<Session> it = mSessions.iterator(); 10381 while (it.hasNext()) { 10382 Session s = it.next(); 10383 pw.print(" Session "); pw.print(s); pw.println(':'); 10384 s.dump(pw, " "); 10385 } 10386 } 10387 } 10388 10389 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 10390 ArrayList<WindowState> windows) { 10391 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 10392 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 10393 } 10394 10395 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 10396 ArrayList<WindowState> windows) { 10397 int j = 0; 10398 final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR); 10399 while (iterator.hasNext()) { 10400 final WindowState w = iterator.next(); 10401 if (windows == null || windows.contains(w)) { 10402 pw.print(" Window #"); pw.print(j++); pw.print(' '); 10403 pw.print(w); pw.println(":"); 10404 w.dump(pw, " ", dumpAll || windows != null); 10405 } 10406 } 10407 if (mInputMethodDialogs.size() > 0) { 10408 pw.println(); 10409 pw.println(" Input method dialogs:"); 10410 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 10411 WindowState w = mInputMethodDialogs.get(i); 10412 if (windows == null || windows.contains(w)) { 10413 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 10414 } 10415 } 10416 } 10417 if (mPendingRemove.size() > 0) { 10418 pw.println(); 10419 pw.println(" Remove pending for:"); 10420 for (int i=mPendingRemove.size()-1; i>=0; i--) { 10421 WindowState w = mPendingRemove.get(i); 10422 if (windows == null || windows.contains(w)) { 10423 pw.print(" Remove #"); pw.print(i); pw.print(' '); 10424 pw.print(w); 10425 if (dumpAll) { 10426 pw.println(":"); 10427 w.dump(pw, " ", true); 10428 } else { 10429 pw.println(); 10430 } 10431 } 10432 } 10433 } 10434 if (mForceRemoves != null && mForceRemoves.size() > 0) { 10435 pw.println(); 10436 pw.println(" Windows force removing:"); 10437 for (int i=mForceRemoves.size()-1; i>=0; i--) { 10438 WindowState w = mForceRemoves.get(i); 10439 pw.print(" Removing #"); pw.print(i); pw.print(' '); 10440 pw.print(w); 10441 if (dumpAll) { 10442 pw.println(":"); 10443 w.dump(pw, " ", true); 10444 } else { 10445 pw.println(); 10446 } 10447 } 10448 } 10449 if (mDestroySurface.size() > 0) { 10450 pw.println(); 10451 pw.println(" Windows waiting to destroy their surface:"); 10452 for (int i=mDestroySurface.size()-1; i>=0; i--) { 10453 WindowState w = mDestroySurface.get(i); 10454 if (windows == null || windows.contains(w)) { 10455 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 10456 pw.print(w); 10457 if (dumpAll) { 10458 pw.println(":"); 10459 w.dump(pw, " ", true); 10460 } else { 10461 pw.println(); 10462 } 10463 } 10464 } 10465 } 10466 if (mLosingFocus.size() > 0) { 10467 pw.println(); 10468 pw.println(" Windows losing focus:"); 10469 for (int i=mLosingFocus.size()-1; i>=0; i--) { 10470 WindowState w = mLosingFocus.get(i); 10471 if (windows == null || windows.contains(w)) { 10472 pw.print(" Losing #"); pw.print(i); pw.print(' '); 10473 pw.print(w); 10474 if (dumpAll) { 10475 pw.println(":"); 10476 w.dump(pw, " ", true); 10477 } else { 10478 pw.println(); 10479 } 10480 } 10481 } 10482 } 10483 if (mResizingWindows.size() > 0) { 10484 pw.println(); 10485 pw.println(" Windows waiting to resize:"); 10486 for (int i=mResizingWindows.size()-1; i>=0; i--) { 10487 WindowState w = mResizingWindows.get(i); 10488 if (windows == null || windows.contains(w)) { 10489 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 10490 pw.print(w); 10491 if (dumpAll) { 10492 pw.println(":"); 10493 w.dump(pw, " ", true); 10494 } else { 10495 pw.println(); 10496 } 10497 } 10498 } 10499 } 10500 if (mWaitingForDrawn.size() > 0) { 10501 pw.println(); 10502 pw.println(" Clients waiting for these windows to be drawn:"); 10503 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10504 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 10505 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 10506 pw.print(": "); pw.println(pair.second); 10507 } 10508 } 10509 pw.println(" DisplayContents"); 10510 if (mDisplayReady) { 10511 DisplayContentsIterator dCIterator = new DisplayContentsIterator(); 10512 while (dCIterator.hasNext()) { 10513 dCIterator.next().dump(" ", pw); 10514 } 10515 } else { 10516 pw.println(" NO DISPLAY"); 10517 } 10518 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10519 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10520 if (mLastFocus != mCurrentFocus) { 10521 pw.print(" mLastFocus="); pw.println(mLastFocus); 10522 } 10523 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10524 if (mInputMethodTarget != null) { 10525 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10526 } 10527 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10528 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10529 if (dumpAll) { 10530 pw.print(" mSystemDecorRect="); pw.print(mSystemDecorRect.toShortString()); 10531 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10532 pw.print(" mScreenRecr="); pw.println(mScreenRect.toShortString()); 10533 if (mLastStatusBarVisibility != 0) { 10534 pw.print(" mLastStatusBarVisibility=0x"); 10535 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10536 } 10537 if (mInputMethodWindow != null) { 10538 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10539 } 10540 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10541 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) { 10542 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10543 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10544 } 10545 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10546 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10547 if (mInputMethodAnimLayerAdjustment != 0 || 10548 mWallpaperAnimLayerAdjustment != 0) { 10549 pw.print(" mInputMethodAnimLayerAdjustment="); 10550 pw.print(mInputMethodAnimLayerAdjustment); 10551 pw.print(" mWallpaperAnimLayerAdjustment="); 10552 pw.println(mWallpaperAnimLayerAdjustment); 10553 } 10554 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10555 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10556 if (needsLayout()) { 10557 pw.print(" layoutNeeded on displays="); 10558 DisplayContentsIterator dcIterator = new DisplayContentsIterator(); 10559 while (dcIterator.hasNext()) { 10560 final DisplayContent displayContent = dcIterator.next(); 10561 if (displayContent.layoutNeeded) { 10562 pw.print(displayContent.getDisplayId()); 10563 } 10564 } 10565 pw.println(); 10566 } 10567 pw.print(" mTransactionSequence="); pw.println(mTransactionSequence); 10568 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10569 pw.print(" windows="); pw.print(mWindowsFreezingScreen); 10570 pw.print(" client="); pw.print(mClientFreezingScreen); 10571 pw.print(" apps="); pw.print(mAppsFreezingScreen); 10572 pw.print(" waitingForConfig="); pw.println(mWaitingForConfig); 10573 pw.print(" mRotation="); pw.print(mRotation); 10574 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10575 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10576 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10577 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10578 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 10579 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 10580 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 10581 pw.print(" mTraversalScheduled="); pw.print(mTraversalScheduled); 10582 pw.print(" mNextAppTransition=0x"); 10583 pw.print(Integer.toHexString(mNextAppTransition)); 10584 pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady); 10585 pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning); 10586 pw.print(" mAppTransitionTimeout="); pw.println(mAppTransitionTimeout); 10587 if (mNextAppTransitionType != ActivityOptions.ANIM_NONE) { 10588 pw.print(" mNextAppTransitionType="); pw.println(mNextAppTransitionType); 10589 } 10590 switch (mNextAppTransitionType) { 10591 case ActivityOptions.ANIM_CUSTOM: 10592 pw.print(" mNextAppTransitionPackage="); 10593 pw.println(mNextAppTransitionPackage); 10594 pw.print(" mNextAppTransitionEnter=0x"); 10595 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 10596 pw.print(" mNextAppTransitionExit=0x"); 10597 pw.println(Integer.toHexString(mNextAppTransitionExit)); 10598 break; 10599 case ActivityOptions.ANIM_SCALE_UP: 10600 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); 10601 pw.print(" mNextAppTransitionStartY="); 10602 pw.println(mNextAppTransitionStartY); 10603 pw.print(" mNextAppTransitionStartWidth="); 10604 pw.print(mNextAppTransitionStartWidth); 10605 pw.print(" mNextAppTransitionStartHeight="); 10606 pw.println(mNextAppTransitionStartHeight); 10607 break; 10608 case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP: 10609 case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN: 10610 pw.print(" mNextAppTransitionThumbnail="); 10611 pw.print(mNextAppTransitionThumbnail); 10612 pw.print(" mNextAppTransitionStartX="); 10613 pw.print(mNextAppTransitionStartX); 10614 pw.print(" mNextAppTransitionStartY="); 10615 pw.println(mNextAppTransitionStartY); 10616 pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp); 10617 break; 10618 } 10619 if (mNextAppTransitionCallback != null) { 10620 pw.print(" mNextAppTransitionCallback="); 10621 pw.println(mNextAppTransitionCallback); 10622 } 10623 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10624 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10625 pw.println(" Window Animator:"); 10626 mAnimator.dumpLocked(pw, " ", dumpAll); 10627 } 10628 } 10629 10630 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10631 int opti, boolean dumpAll) { 10632 WindowList windows = new WindowList(); 10633 if ("visible".equals(name)) { 10634 synchronized(mWindowMap) { 10635 final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR); 10636 while (iterator.hasNext()) { 10637 final WindowState w = iterator.next(); 10638 if (w.mWinAnimator.mSurfaceShown) { 10639 windows.add(w); 10640 } 10641 } 10642 } 10643 } else { 10644 int objectId = 0; 10645 // See if this is an object ID. 10646 try { 10647 objectId = Integer.parseInt(name, 16); 10648 name = null; 10649 } catch (RuntimeException e) { 10650 } 10651 synchronized(mWindowMap) { 10652 final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR); 10653 while (iterator.hasNext()) { 10654 final WindowState w = iterator.next(); 10655 if (name != null) { 10656 if (w.mAttrs.getTitle().toString().contains(name)) { 10657 windows.add(w); 10658 } 10659 } else if (System.identityHashCode(w) == objectId) { 10660 windows.add(w); 10661 } 10662 } 10663 } 10664 } 10665 10666 if (windows.size() <= 0) { 10667 return false; 10668 } 10669 10670 synchronized(mWindowMap) { 10671 dumpWindowsLocked(pw, dumpAll, windows); 10672 } 10673 return true; 10674 } 10675 10676 void dumpLastANRLocked(PrintWriter pw) { 10677 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10678 if (mLastANRState == null) { 10679 pw.println(" <no ANR has occurred since boot>"); 10680 } else { 10681 pw.println(mLastANRState); 10682 } 10683 } 10684 10685 /** 10686 * Saves information about the state of the window manager at 10687 * the time an ANR occurred before anything else in the system changes 10688 * in response. 10689 * 10690 * @param appWindowToken The application that ANR'd, may be null. 10691 * @param windowState The window that ANR'd, may be null. 10692 */ 10693 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) { 10694 StringWriter sw = new StringWriter(); 10695 PrintWriter pw = new PrintWriter(sw); 10696 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10697 if (appWindowToken != null) { 10698 pw.println(" Application at fault: " + appWindowToken.stringName); 10699 } 10700 if (windowState != null) { 10701 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10702 } 10703 pw.println(); 10704 dumpWindowsNoHeaderLocked(pw, true, null); 10705 pw.close(); 10706 mLastANRState = sw.toString(); 10707 } 10708 10709 @Override 10710 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10711 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10712 != PackageManager.PERMISSION_GRANTED) { 10713 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10714 + Binder.getCallingPid() 10715 + ", uid=" + Binder.getCallingUid()); 10716 return; 10717 } 10718 10719 boolean dumpAll = false; 10720 10721 int opti = 0; 10722 while (opti < args.length) { 10723 String opt = args[opti]; 10724 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10725 break; 10726 } 10727 opti++; 10728 if ("-a".equals(opt)) { 10729 dumpAll = true; 10730 } else if ("-h".equals(opt)) { 10731 pw.println("Window manager dump options:"); 10732 pw.println(" [-a] [-h] [cmd] ..."); 10733 pw.println(" cmd may be one of:"); 10734 pw.println(" l[astanr]: last ANR information"); 10735 pw.println(" p[policy]: policy state"); 10736 pw.println(" s[essions]: active sessions"); 10737 pw.println(" t[okens]: token list"); 10738 pw.println(" w[indows]: window list"); 10739 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10740 pw.println(" be a partial substring in a window name, a"); 10741 pw.println(" Window hex object identifier, or"); 10742 pw.println(" \"all\" for all windows, or"); 10743 pw.println(" \"visible\" for the visible windows."); 10744 pw.println(" -a: include all available server state."); 10745 return; 10746 } else { 10747 pw.println("Unknown argument: " + opt + "; use -h for help"); 10748 } 10749 } 10750 10751 // Is the caller requesting to dump a particular piece of data? 10752 if (opti < args.length) { 10753 String cmd = args[opti]; 10754 opti++; 10755 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10756 synchronized(mWindowMap) { 10757 dumpLastANRLocked(pw); 10758 } 10759 return; 10760 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10761 synchronized(mWindowMap) { 10762 dumpPolicyLocked(pw, args, true); 10763 } 10764 return; 10765 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10766 synchronized(mWindowMap) { 10767 dumpSessionsLocked(pw, true); 10768 } 10769 return; 10770 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10771 synchronized(mWindowMap) { 10772 dumpTokensLocked(pw, true); 10773 } 10774 return; 10775 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10776 synchronized(mWindowMap) { 10777 dumpWindowsLocked(pw, true, null); 10778 } 10779 return; 10780 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10781 synchronized(mWindowMap) { 10782 dumpWindowsLocked(pw, true, null); 10783 } 10784 return; 10785 } else { 10786 // Dumping a single name? 10787 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10788 pw.println("Bad window command, or no windows match: " + cmd); 10789 pw.println("Use -h for help."); 10790 } 10791 return; 10792 } 10793 } 10794 10795 synchronized(mWindowMap) { 10796 pw.println(); 10797 if (dumpAll) { 10798 pw.println("-------------------------------------------------------------------------------"); 10799 } 10800 dumpLastANRLocked(pw); 10801 pw.println(); 10802 if (dumpAll) { 10803 pw.println("-------------------------------------------------------------------------------"); 10804 } 10805 dumpPolicyLocked(pw, args, dumpAll); 10806 pw.println(); 10807 if (dumpAll) { 10808 pw.println("-------------------------------------------------------------------------------"); 10809 } 10810 dumpSessionsLocked(pw, dumpAll); 10811 pw.println(); 10812 if (dumpAll) { 10813 pw.println("-------------------------------------------------------------------------------"); 10814 } 10815 dumpTokensLocked(pw, dumpAll); 10816 pw.println(); 10817 if (dumpAll) { 10818 pw.println("-------------------------------------------------------------------------------"); 10819 } 10820 dumpWindowsLocked(pw, dumpAll, null); 10821 } 10822 } 10823 10824 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10825 public void monitor() { 10826 synchronized (mWindowMap) { } 10827 } 10828 10829 public interface OnHardKeyboardStatusChangeListener { 10830 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10831 } 10832 10833 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10834 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10835 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10836 Integer.toHexString(pendingLayoutChanges)); 10837 } 10838 } 10839 10840 public void createDisplayContentLocked(final Display display) { 10841 if (display == null) { 10842 throw new IllegalArgumentException("getDisplayContent: display must not be null"); 10843 } 10844 final DisplayContent displayContent = new DisplayContent(display); 10845 mDisplayContents.put(display.getDisplayId(), displayContent); 10846 } 10847 10848 public DisplayContent getDisplayContentLocked(final int displayId) { 10849 DisplayContent displayContent = mDisplayContents.get(displayId); 10850 if (displayContent == null) { 10851 displayContent = new DisplayContent(mDisplayManager.getDisplay(displayId)); 10852 mDisplayContents.put(displayId, displayContent); 10853 } 10854 return displayContent; 10855 } 10856 10857 class DisplayContentsIterator implements Iterator<DisplayContent> { 10858 private int cur; 10859 10860 @Override 10861 public boolean hasNext() { 10862 return cur < mDisplayContents.size(); 10863 } 10864 10865 @Override 10866 public DisplayContent next() { 10867 if (hasNext()) { 10868 return mDisplayContents.valueAt(cur++); 10869 } 10870 throw new NoSuchElementException(); 10871 } 10872 10873 @Override 10874 public void remove() { 10875 throw new IllegalArgumentException("AllDisplayContentIterator.remove not implemented"); 10876 } 10877 } 10878 10879 final static boolean REVERSE_ITERATOR = true; 10880 class AllWindowsIterator implements Iterator<WindowState> { 10881 private DisplayContent mDisplayContent; 10882 private DisplayContentsIterator mDisplayContentsIterator; 10883 private WindowList mWindowList; 10884 private int mWindowListIndex; 10885 private boolean mReverse; 10886 10887 AllWindowsIterator() { 10888 mDisplayContentsIterator = new DisplayContentsIterator(); 10889 mDisplayContent = mDisplayContentsIterator.next(); 10890 mWindowList = mDisplayContent.getWindowList(); 10891 } 10892 10893 AllWindowsIterator(boolean reverse) { 10894 this(); 10895 mReverse = reverse; 10896 mWindowListIndex = reverse ? mWindowList.size() - 1 : 0; 10897 } 10898 10899 @Override 10900 public boolean hasNext() { 10901 if (mReverse) { 10902 return mWindowListIndex >= 0; 10903 } 10904 return mWindowListIndex < mWindowList.size(); 10905 } 10906 10907 @Override 10908 public WindowState next() { 10909 if (hasNext()) { 10910 WindowState win = mWindowList.get(mWindowListIndex); 10911 if (mReverse) { 10912 mWindowListIndex--; 10913 if (mWindowListIndex < 0 && mDisplayContentsIterator.hasNext()) { 10914 mDisplayContent = mDisplayContentsIterator.next(); 10915 mWindowList = mDisplayContent.getWindowList(); 10916 mWindowListIndex = mWindowList.size() - 1; 10917 } 10918 } else { 10919 mWindowListIndex++; 10920 if (mWindowListIndex >= mWindowList.size() 10921 && mDisplayContentsIterator.hasNext()) { 10922 mDisplayContent = mDisplayContentsIterator.next(); 10923 mWindowList = mDisplayContent.getWindowList(); 10924 mWindowListIndex = 0; 10925 } 10926 } 10927 return win; 10928 } 10929 throw new NoSuchElementException(); 10930 } 10931 10932 @Override 10933 public void remove() { 10934 throw new IllegalArgumentException("AllWindowsIterator.remove not implemented"); 10935 } 10936 } 10937 10938 public DisplayContent getDefaultDisplayContentLocked() { 10939 return getDisplayContentLocked(Display.DEFAULT_DISPLAY); 10940 } 10941 10942 public WindowList getDefaultWindowListLocked() { 10943 return getDefaultDisplayContentLocked().getWindowList(); 10944 } 10945 10946 public DisplayInfo getDefaultDisplayInfoLocked() { 10947 return getDefaultDisplayContentLocked().getDisplayInfo(); 10948 } 10949 10950 public WindowList getWindowListLocked(final Display display) { 10951 return getDisplayContentLocked(display.getDisplayId()).getWindowList(); 10952 } 10953 10954 @Override 10955 public void onDisplayAdded(int displayId) { 10956 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0)); 10957 } 10958 10959 private void handleDisplayAddedLocked(int displayId) { 10960 createDisplayContentLocked(mDisplayManager.getDisplay(displayId)); 10961 displayReady(displayId); 10962 } 10963 10964 @Override 10965 public void onDisplayRemoved(int displayId) { 10966 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0)); 10967 } 10968 10969 private void handleDisplayRemovedLocked(int displayId) { 10970 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10971 mDisplayContents.delete(displayId); 10972 WindowList windows = displayContent.getWindowList(); 10973 while (!windows.isEmpty()) { 10974 final WindowState win = windows.get(windows.size() - 1); 10975 removeWindowLocked(win.mSession, win); 10976 } 10977 mAnimator.removeDisplayLocked(displayId); 10978 } 10979 10980 @Override 10981 public void onDisplayChanged(int displayId) { 10982 mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0)); 10983 } 10984 10985 private void handleDisplayChangedLocked(int displayId) { 10986 final DisplayContent displayContent = getDisplayContentLocked(displayId); 10987 if (displayContent != null) { 10988 displayContent.updateDisplayInfo(); 10989 } 10990 } 10991} 10992