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