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