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