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