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