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