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