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