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