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