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