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