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