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