WindowManagerService.java revision 76a7165719dc3ccce902953f6244e2c2668aa753
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 = sl; 6396 } 6397 6398 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6399 int dw, int dh) { 6400 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6401 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6402 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6403 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6404 if (curSize == 0 || size < curSize) { 6405 curSize = size; 6406 } 6407 return curSize; 6408 } 6409 6410 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6411 mTmpDisplayMetrics.setTo(dm); 6412 dm = mTmpDisplayMetrics; 6413 int unrotDw, unrotDh; 6414 if (rotated) { 6415 unrotDw = dh; 6416 unrotDh = dw; 6417 } else { 6418 unrotDw = dw; 6419 unrotDh = dh; 6420 } 6421 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, dm, unrotDw, unrotDh); 6422 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, dm, unrotDh, unrotDw); 6423 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, dm, unrotDw, unrotDh); 6424 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, dm, unrotDh, unrotDw); 6425 return sw; 6426 } 6427 6428 boolean computeScreenConfigurationLocked(Configuration config) { 6429 if (mDefaultDisplay == null) { 6430 return false; 6431 } 6432 6433 // TODO(multidisplay): For now, apply Configuration to main screen only. 6434 final DisplayContent displayContent = getDefaultDisplayContent(); 6435 6436 // Use the effective "visual" dimensions based on current rotation 6437 final boolean rotated = (mRotation == Surface.ROTATION_90 6438 || mRotation == Surface.ROTATION_270); 6439 final int realdw = rotated ? 6440 displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth; 6441 final int realdh = rotated ? 6442 displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight; 6443 int dw = realdw; 6444 int dh = realdh; 6445 6446 if (mAltOrientation) { 6447 if (realdw > realdh) { 6448 // Turn landscape into portrait. 6449 int maxw = (int)(realdh/1.3f); 6450 if (maxw < realdw) { 6451 dw = maxw; 6452 } 6453 } else { 6454 // Turn portrait into landscape. 6455 int maxh = (int)(realdw/1.3f); 6456 if (maxh < realdh) { 6457 dh = maxh; 6458 } 6459 } 6460 } 6461 6462 if (config != null) { 6463 int orientation = Configuration.ORIENTATION_SQUARE; 6464 if (dw < dh) { 6465 orientation = Configuration.ORIENTATION_PORTRAIT; 6466 } else if (dw > dh) { 6467 orientation = Configuration.ORIENTATION_LANDSCAPE; 6468 } 6469 config.orientation = orientation; 6470 } 6471 6472 // Update application display metrics. 6473 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6474 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6475 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 6476 synchronized(displayContent.mDisplaySizeLock) { 6477 displayInfo.rotation = mRotation; 6478 displayInfo.logicalWidth = dw; 6479 displayInfo.logicalHeight = dh; 6480 displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity; 6481 displayInfo.appWidth = appWidth; 6482 displayInfo.appHeight = appHeight; 6483 displayInfo.getLogicalMetrics(mRealDisplayMetrics, null); 6484 displayInfo.getAppMetrics(mDisplayMetrics, null); 6485 mDisplayManagerService.setDisplayInfoOverrideFromWindowManager( 6486 displayContent.getDisplayId(), displayInfo); 6487 6488 mAnimator.setDisplayDimensions(dw, dh, appWidth, appHeight); 6489 } 6490 if (false) { 6491 Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); 6492 } 6493 6494 final DisplayMetrics dm = mDisplayMetrics; 6495 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6496 mCompatDisplayMetrics); 6497 6498 if (config != null) { 6499 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6500 / dm.density); 6501 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6502 / dm.density); 6503 computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); 6504 6505 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6506 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6507 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6508 config.densityDpi = displayContent.mBaseDisplayDensity; 6509 6510 // Update the configuration based on available input devices, lid switch, 6511 // and platform configuration. 6512 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6513 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6514 config.navigation = Configuration.NAVIGATION_NONAV; 6515 6516 int keyboardPresence = 0; 6517 int navigationPresence = 0; 6518 final InputDevice[] devices = mInputManager.getInputDevices(); 6519 final int len = devices.length; 6520 for (int i = 0; i < len; i++) { 6521 InputDevice device = devices[i]; 6522 if (!device.isVirtual()) { 6523 final int sources = device.getSources(); 6524 final int presenceFlag = device.isExternal() ? 6525 WindowManagerPolicy.PRESENCE_EXTERNAL : 6526 WindowManagerPolicy.PRESENCE_INTERNAL; 6527 6528 if (mIsTouchDevice) { 6529 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == 6530 InputDevice.SOURCE_TOUCHSCREEN) { 6531 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6532 } 6533 } else { 6534 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6535 } 6536 6537 if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { 6538 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6539 navigationPresence |= presenceFlag; 6540 } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD 6541 && config.navigation == Configuration.NAVIGATION_NONAV) { 6542 config.navigation = Configuration.NAVIGATION_DPAD; 6543 navigationPresence |= presenceFlag; 6544 } 6545 6546 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6547 config.keyboard = Configuration.KEYBOARD_QWERTY; 6548 keyboardPresence |= presenceFlag; 6549 } 6550 } 6551 } 6552 6553 // Determine whether a hard keyboard is available and enabled. 6554 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6555 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6556 mHardKeyboardAvailable = hardKeyboardAvailable; 6557 mHardKeyboardEnabled = hardKeyboardAvailable; 6558 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6559 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6560 } 6561 if (!mHardKeyboardEnabled) { 6562 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6563 } 6564 6565 // Let the policy update hidden states. 6566 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6567 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6568 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6569 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6570 } 6571 6572 return true; 6573 } 6574 6575 public boolean isHardKeyboardAvailable() { 6576 synchronized (mWindowMap) { 6577 return mHardKeyboardAvailable; 6578 } 6579 } 6580 6581 public boolean isHardKeyboardEnabled() { 6582 synchronized (mWindowMap) { 6583 return mHardKeyboardEnabled; 6584 } 6585 } 6586 6587 public void setHardKeyboardEnabled(boolean enabled) { 6588 synchronized (mWindowMap) { 6589 if (mHardKeyboardEnabled != enabled) { 6590 mHardKeyboardEnabled = enabled; 6591 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6592 } 6593 } 6594 } 6595 6596 public void setOnHardKeyboardStatusChangeListener( 6597 OnHardKeyboardStatusChangeListener listener) { 6598 synchronized (mWindowMap) { 6599 mHardKeyboardStatusChangeListener = listener; 6600 } 6601 } 6602 6603 void notifyHardKeyboardStatusChange() { 6604 final boolean available, enabled; 6605 final OnHardKeyboardStatusChangeListener listener; 6606 synchronized (mWindowMap) { 6607 listener = mHardKeyboardStatusChangeListener; 6608 available = mHardKeyboardAvailable; 6609 enabled = mHardKeyboardEnabled; 6610 } 6611 if (listener != null) { 6612 listener.onHardKeyboardStatusChange(available, enabled); 6613 } 6614 } 6615 6616 // ------------------------------------------------------------- 6617 // Drag and drop 6618 // ------------------------------------------------------------- 6619 6620 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6621 int flags, int width, int height, Surface outSurface) { 6622 if (DEBUG_DRAG) { 6623 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6624 + " flags=" + Integer.toHexString(flags) + " win=" + window 6625 + " asbinder=" + window.asBinder()); 6626 } 6627 6628 final int callerPid = Binder.getCallingPid(); 6629 final long origId = Binder.clearCallingIdentity(); 6630 IBinder token = null; 6631 6632 try { 6633 synchronized (mWindowMap) { 6634 try { 6635 if (mDragState == null) { 6636 Surface surface = new Surface(session, "drag surface", 6637 width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN); 6638 surface.setLayerStack(mDefaultDisplay.getLayerStack()); 6639 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6640 + surface + ": CREATE"); 6641 outSurface.copyFrom(surface); 6642 final IBinder winBinder = window.asBinder(); 6643 token = new Binder(); 6644 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6645 token = mDragState.mToken = new Binder(); 6646 6647 // 5 second timeout for this window to actually begin the drag 6648 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6649 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6650 mH.sendMessageDelayed(msg, 5000); 6651 } else { 6652 Slog.w(TAG, "Drag already in progress"); 6653 } 6654 } catch (Surface.OutOfResourcesException e) { 6655 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6656 if (mDragState != null) { 6657 mDragState.reset(); 6658 mDragState = null; 6659 } 6660 } 6661 } 6662 } finally { 6663 Binder.restoreCallingIdentity(origId); 6664 } 6665 6666 return token; 6667 } 6668 6669 // ------------------------------------------------------------- 6670 // Input Events and Focus Management 6671 // ------------------------------------------------------------- 6672 6673 final InputMonitor mInputMonitor = new InputMonitor(this); 6674 private boolean mEventDispatchingEnabled; 6675 6676 public void pauseKeyDispatching(IBinder _token) { 6677 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6678 "pauseKeyDispatching()")) { 6679 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6680 } 6681 6682 synchronized (mWindowMap) { 6683 WindowToken token = mTokenMap.get(_token); 6684 if (token != null) { 6685 mInputMonitor.pauseDispatchingLw(token); 6686 } 6687 } 6688 } 6689 6690 public void resumeKeyDispatching(IBinder _token) { 6691 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6692 "resumeKeyDispatching()")) { 6693 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6694 } 6695 6696 synchronized (mWindowMap) { 6697 WindowToken token = mTokenMap.get(_token); 6698 if (token != null) { 6699 mInputMonitor.resumeDispatchingLw(token); 6700 } 6701 } 6702 } 6703 6704 public void setEventDispatching(boolean enabled) { 6705 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6706 "setEventDispatching()")) { 6707 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6708 } 6709 6710 synchronized (mWindowMap) { 6711 mEventDispatchingEnabled = enabled; 6712 if (mDisplayEnabled) { 6713 mInputMonitor.setEventDispatchingLw(enabled); 6714 } 6715 sendScreenStatusToClientsLocked(); 6716 } 6717 } 6718 6719 public IBinder getFocusedWindowToken() { 6720 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 6721 "getFocusedWindowToken()")) { 6722 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 6723 } 6724 synchronized (mWindowMap) { 6725 WindowState windowState = getFocusedWindowLocked(); 6726 if (windowState != null) { 6727 return windowState.mClient.asBinder(); 6728 } 6729 return null; 6730 } 6731 } 6732 6733 public boolean getWindowFrame(IBinder token, Rect outBounds) { 6734 if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO, 6735 "getWindowFrame()")) { 6736 throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission."); 6737 } 6738 synchronized (mWindowMap) { 6739 WindowState windowState = mWindowMap.get(token); 6740 if (windowState != null) { 6741 outBounds.set(windowState.getFrameLw()); 6742 return true; 6743 } 6744 } 6745 return false; 6746 } 6747 6748 private WindowState getFocusedWindow() { 6749 synchronized (mWindowMap) { 6750 return getFocusedWindowLocked(); 6751 } 6752 } 6753 6754 private WindowState getFocusedWindowLocked() { 6755 return mCurrentFocus; 6756 } 6757 6758 public boolean detectSafeMode() { 6759 if (!mInputMonitor.waitForInputDevicesReady( 6760 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 6761 Slog.w(TAG, "Devices still not ready after waiting " 6762 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 6763 + " milliseconds before attempting to detect safe mode."); 6764 } 6765 6766 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6767 KeyEvent.KEYCODE_MENU); 6768 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 6769 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 6770 KeyEvent.KEYCODE_DPAD_CENTER); 6771 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 6772 InputManagerService.BTN_MOUSE); 6773 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6774 KeyEvent.KEYCODE_VOLUME_DOWN); 6775 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 6776 || volumeDownState > 0; 6777 try { 6778 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 6779 mSafeMode = true; 6780 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 6781 } 6782 } catch (IllegalArgumentException e) { 6783 } 6784 if (mSafeMode) { 6785 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 6786 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 6787 } else { 6788 Log.i(TAG, "SAFE MODE not enabled"); 6789 } 6790 mPolicy.setSafeMode(mSafeMode); 6791 return mSafeMode; 6792 } 6793 6794 public void displayReady() { 6795 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 6796 final Display display = wm.getDefaultDisplay(); 6797 displayReady(display.getDisplayId()); 6798 6799 synchronized(mWindowMap) { 6800 readForcedDisplaySizeAndDensityLocked(getDefaultDisplayContent()); 6801 6802 mDefaultDisplay = display; 6803 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 6804 PackageManager.FEATURE_TOUCHSCREEN); 6805 6806 mAnimator.initializeLocked(display.getLayerStack()); 6807 6808 final DisplayInfo displayInfo = getDefaultDisplayInfo(); 6809 mAnimator.setDisplayDimensions(displayInfo.logicalWidth, displayInfo.logicalHeight, 6810 displayInfo.appWidth, displayInfo.appHeight); 6811 6812 final DisplayContent displayContent = getDefaultDisplayContent(); 6813 mInputManager.setDisplaySize(displayContent.getDisplayId(), 6814 displayContent.mInitialDisplayWidth, displayContent.mInitialDisplayHeight); 6815 mInputManager.setDisplayOrientation(displayContent.getDisplayId(), 6816 mDefaultDisplay.getRotation()); 6817 mPolicy.setInitialDisplaySize(mDefaultDisplay, displayContent.mInitialDisplayWidth, 6818 displayContent.mInitialDisplayHeight, displayContent.mInitialDisplayDensity); 6819 } 6820 6821 try { 6822 mActivityManager.updateConfiguration(null); 6823 } catch (RemoteException e) { 6824 } 6825 } 6826 6827 public void displayReady(int displayId) { 6828 synchronized(mWindowMap) { 6829 final DisplayContent displayContent = getDisplayContent(displayId); 6830 final DisplayInfo displayInfo; 6831 synchronized(displayContent.mDisplaySizeLock) { 6832 // Bootstrap the default logical display from the display manager. 6833 displayInfo = displayContent.getDisplayInfo(); 6834 DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId); 6835 if (newDisplayInfo != null) { 6836 displayInfo.copyFrom(newDisplayInfo); 6837 } 6838 displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; 6839 displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; 6840 displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; 6841 displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; 6842 displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; 6843 displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; 6844 } 6845 } 6846 } 6847 6848 public void systemReady() { 6849 mPolicy.systemReady(); 6850 } 6851 6852 // TODO(multidisplay): Call isScreenOn for each display. 6853 private void sendScreenStatusToClientsLocked() { 6854 final boolean on = mPowerManager.isScreenOn(); 6855 final AllWindowsIterator iterator = new AllWindowsIterator(); 6856 while (iterator.hasNext()) { 6857 try { 6858 iterator.next().mClient.dispatchScreenState(on); 6859 } catch (RemoteException e) { 6860 // Ignored 6861 } 6862 } 6863 } 6864 6865 // ------------------------------------------------------------- 6866 // Async Handler 6867 // ------------------------------------------------------------- 6868 6869 final class H extends Handler { 6870 public static final int REPORT_FOCUS_CHANGE = 2; 6871 public static final int REPORT_LOSING_FOCUS = 3; 6872 public static final int DO_TRAVERSAL = 4; 6873 public static final int ADD_STARTING = 5; 6874 public static final int REMOVE_STARTING = 6; 6875 public static final int FINISHED_STARTING = 7; 6876 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 6877 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 6878 public static final int WINDOW_FREEZE_TIMEOUT = 11; 6879 6880 public static final int APP_TRANSITION_TIMEOUT = 13; 6881 public static final int PERSIST_ANIMATION_SCALE = 14; 6882 public static final int FORCE_GC = 15; 6883 public static final int ENABLE_SCREEN = 16; 6884 public static final int APP_FREEZE_TIMEOUT = 17; 6885 public static final int SEND_NEW_CONFIGURATION = 18; 6886 public static final int REPORT_WINDOWS_CHANGE = 19; 6887 public static final int DRAG_START_TIMEOUT = 20; 6888 public static final int DRAG_END_TIMEOUT = 21; 6889 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 6890 public static final int BOOT_TIMEOUT = 23; 6891 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 6892 public static final int UPDATE_ANIM_PARAMETERS = 25; 6893 public static final int SHOW_STRICT_MODE_VIOLATION = 26; 6894 public static final int DO_ANIMATION_CALLBACK = 27; 6895 6896 public static final int ANIMATOR_WHAT_OFFSET = 100000; 6897 public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1; 6898 public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 2; 6899 6900 public H() { 6901 } 6902 6903 @Override 6904 public void handleMessage(Message msg) { 6905 if (DEBUG_WINDOW_TRACE) { 6906 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 6907 } 6908 switch (msg.what) { 6909 case REPORT_FOCUS_CHANGE: { 6910 WindowState lastFocus; 6911 WindowState newFocus; 6912 6913 synchronized(mWindowMap) { 6914 lastFocus = mLastFocus; 6915 newFocus = mCurrentFocus; 6916 if (lastFocus == newFocus) { 6917 // Focus is not changing, so nothing to do. 6918 return; 6919 } 6920 mLastFocus = newFocus; 6921 //Slog.i(TAG, "Focus moving from " + lastFocus 6922 // + " to " + newFocus); 6923 if (newFocus != null && lastFocus != null 6924 && !newFocus.isDisplayedLw()) { 6925 //Slog.i(TAG, "Delaying loss of focus..."); 6926 mLosingFocus.add(lastFocus); 6927 lastFocus = null; 6928 } 6929 } 6930 6931 if (lastFocus != newFocus) { 6932 //System.out.println("Changing focus from " + lastFocus 6933 // + " to " + newFocus); 6934 if (newFocus != null) { 6935 try { 6936 //Slog.i(TAG, "Gaining focus: " + newFocus); 6937 newFocus.mClient.windowFocusChanged(true, mInTouchMode); 6938 } catch (RemoteException e) { 6939 // Ignore if process has died. 6940 } 6941 notifyFocusChanged(); 6942 } 6943 6944 if (lastFocus != null) { 6945 try { 6946 //Slog.i(TAG, "Losing focus: " + lastFocus); 6947 lastFocus.mClient.windowFocusChanged(false, mInTouchMode); 6948 } catch (RemoteException e) { 6949 // Ignore if process has died. 6950 } 6951 } 6952 } 6953 } break; 6954 6955 case REPORT_LOSING_FOCUS: { 6956 ArrayList<WindowState> losers; 6957 6958 synchronized(mWindowMap) { 6959 losers = mLosingFocus; 6960 mLosingFocus = new ArrayList<WindowState>(); 6961 } 6962 6963 final int N = losers.size(); 6964 for (int i=0; i<N; i++) { 6965 try { 6966 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i)); 6967 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode); 6968 } catch (RemoteException e) { 6969 // Ignore if process has died. 6970 } 6971 } 6972 } break; 6973 6974 case DO_TRAVERSAL: { 6975 synchronized(mWindowMap) { 6976 mTraversalScheduled = false; 6977 performLayoutAndPlaceSurfacesLocked(); 6978 } 6979 } break; 6980 6981 case ADD_STARTING: { 6982 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6983 final StartingData sd = wtoken.startingData; 6984 6985 if (sd == null) { 6986 // Animation has been canceled... do nothing. 6987 return; 6988 } 6989 6990 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 6991 + wtoken + ": pkg=" + sd.pkg); 6992 6993 View view = null; 6994 try { 6995 view = mPolicy.addStartingWindow( 6996 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 6997 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags); 6998 } catch (Exception e) { 6999 Slog.w(TAG, "Exception when adding starting window", e); 7000 } 7001 7002 if (view != null) { 7003 boolean abort = false; 7004 7005 synchronized(mWindowMap) { 7006 if (wtoken.removed || wtoken.startingData == null) { 7007 // If the window was successfully added, then 7008 // we need to remove it. 7009 if (wtoken.startingWindow != null) { 7010 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7011 "Aborted starting " + wtoken 7012 + ": removed=" + wtoken.removed 7013 + " startingData=" + wtoken.startingData); 7014 wtoken.startingWindow = null; 7015 wtoken.startingData = null; 7016 abort = true; 7017 } 7018 } else { 7019 wtoken.startingView = view; 7020 } 7021 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 7022 "Added starting " + wtoken 7023 + ": startingWindow=" 7024 + wtoken.startingWindow + " startingView=" 7025 + wtoken.startingView); 7026 } 7027 7028 if (abort) { 7029 try { 7030 mPolicy.removeStartingWindow(wtoken.token, view); 7031 } catch (Exception e) { 7032 Slog.w(TAG, "Exception when removing starting window", e); 7033 } 7034 } 7035 } 7036 } break; 7037 7038 case REMOVE_STARTING: { 7039 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7040 IBinder token = null; 7041 View view = null; 7042 synchronized (mWindowMap) { 7043 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 7044 + wtoken + ": startingWindow=" 7045 + wtoken.startingWindow + " startingView=" 7046 + wtoken.startingView); 7047 if (wtoken.startingWindow != null) { 7048 view = wtoken.startingView; 7049 token = wtoken.token; 7050 wtoken.startingData = null; 7051 wtoken.startingView = null; 7052 wtoken.startingWindow = null; 7053 wtoken.startingDisplayed = false; 7054 } 7055 } 7056 if (view != null) { 7057 try { 7058 mPolicy.removeStartingWindow(token, view); 7059 } catch (Exception e) { 7060 Slog.w(TAG, "Exception when removing starting window", e); 7061 } 7062 } 7063 } break; 7064 7065 case FINISHED_STARTING: { 7066 IBinder token = null; 7067 View view = null; 7068 while (true) { 7069 synchronized (mWindowMap) { 7070 final int N = mFinishedStarting.size(); 7071 if (N <= 0) { 7072 break; 7073 } 7074 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 7075 7076 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 7077 "Finished starting " + wtoken 7078 + ": startingWindow=" + wtoken.startingWindow 7079 + " startingView=" + wtoken.startingView); 7080 7081 if (wtoken.startingWindow == null) { 7082 continue; 7083 } 7084 7085 view = wtoken.startingView; 7086 token = wtoken.token; 7087 wtoken.startingData = null; 7088 wtoken.startingView = null; 7089 wtoken.startingWindow = null; 7090 wtoken.startingDisplayed = false; 7091 } 7092 7093 try { 7094 mPolicy.removeStartingWindow(token, view); 7095 } catch (Exception e) { 7096 Slog.w(TAG, "Exception when removing starting window", e); 7097 } 7098 } 7099 } break; 7100 7101 case REPORT_APPLICATION_TOKEN_DRAWN: { 7102 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7103 7104 try { 7105 if (DEBUG_VISIBILITY) Slog.v( 7106 TAG, "Reporting drawn in " + wtoken); 7107 wtoken.appToken.windowsDrawn(); 7108 } catch (RemoteException ex) { 7109 } 7110 } break; 7111 7112 case REPORT_APPLICATION_TOKEN_WINDOWS: { 7113 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 7114 7115 boolean nowVisible = msg.arg1 != 0; 7116 boolean nowGone = msg.arg2 != 0; 7117 7118 try { 7119 if (DEBUG_VISIBILITY) Slog.v( 7120 TAG, "Reporting visible in " + wtoken 7121 + " visible=" + nowVisible 7122 + " gone=" + nowGone); 7123 if (nowVisible) { 7124 wtoken.appToken.windowsVisible(); 7125 } else { 7126 wtoken.appToken.windowsGone(); 7127 } 7128 } catch (RemoteException ex) { 7129 } 7130 } break; 7131 7132 case WINDOW_FREEZE_TIMEOUT: { 7133 // TODO(multidisplay): Can non-default displays rotate? 7134 synchronized (mWindowMap) { 7135 Slog.w(TAG, "Window freeze timeout expired."); 7136 final WindowList windows = getDefaultWindowList(); 7137 int i = windows.size(); 7138 while (i > 0) { 7139 i--; 7140 WindowState w = windows.get(i); 7141 if (w.mOrientationChanging) { 7142 w.mOrientationChanging = false; 7143 Slog.w(TAG, "Force clearing orientation change: " + w); 7144 } 7145 } 7146 performLayoutAndPlaceSurfacesLocked(); 7147 } 7148 break; 7149 } 7150 7151 case APP_TRANSITION_TIMEOUT: { 7152 synchronized (mWindowMap) { 7153 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 7154 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7155 "*** APP TRANSITION TIMEOUT"); 7156 mAppTransitionReady = true; 7157 mAppTransitionTimeout = true; 7158 mAnimatingAppTokens.clear(); 7159 mAnimatingAppTokens.addAll(mAppTokens); 7160 performLayoutAndPlaceSurfacesLocked(); 7161 } 7162 } 7163 break; 7164 } 7165 7166 case PERSIST_ANIMATION_SCALE: { 7167 Settings.System.putFloat(mContext.getContentResolver(), 7168 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 7169 Settings.System.putFloat(mContext.getContentResolver(), 7170 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 7171 Settings.System.putFloat(mContext.getContentResolver(), 7172 Settings.System.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 7173 break; 7174 } 7175 7176 case FORCE_GC: { 7177 synchronized (mWindowMap) { 7178 synchronized (mAnimator) { 7179 // Since we're holding both mWindowMap and mAnimator we don't need to 7180 // hold mAnimator.mLayoutToAnim. 7181 if (mAnimator.mAnimating || mLayoutToAnim.mAnimationScheduled) { 7182 // If we are animating, don't do the gc now but 7183 // delay a bit so we don't interrupt the animation. 7184 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 7185 2000); 7186 return; 7187 } 7188 // If we are currently rotating the display, it will 7189 // schedule a new message when done. 7190 if (mDisplayFrozen) { 7191 return; 7192 } 7193 } 7194 } 7195 Runtime.getRuntime().gc(); 7196 break; 7197 } 7198 7199 case ENABLE_SCREEN: { 7200 performEnableScreen(); 7201 break; 7202 } 7203 7204 case APP_FREEZE_TIMEOUT: { 7205 synchronized (mWindowMap) { 7206 synchronized (mAnimator) { 7207 Slog.w(TAG, "App freeze timeout expired."); 7208 int i = mAppTokens.size(); 7209 while (i > 0) { 7210 i--; 7211 AppWindowToken tok = mAppTokens.get(i); 7212 if (tok.mAppAnimator.freezingScreen) { 7213 Slog.w(TAG, "Force clearing freeze: " + tok); 7214 unsetAppFreezingScreenLocked(tok, true, true); 7215 } 7216 } 7217 } 7218 } 7219 break; 7220 } 7221 7222 case SEND_NEW_CONFIGURATION: { 7223 removeMessages(SEND_NEW_CONFIGURATION); 7224 sendNewConfiguration(); 7225 break; 7226 } 7227 7228 case REPORT_WINDOWS_CHANGE: { 7229 if (mWindowsChanged) { 7230 synchronized (mWindowMap) { 7231 mWindowsChanged = false; 7232 } 7233 notifyWindowsChanged(); 7234 } 7235 break; 7236 } 7237 7238 case DRAG_START_TIMEOUT: { 7239 IBinder win = (IBinder)msg.obj; 7240 if (DEBUG_DRAG) { 7241 Slog.w(TAG, "Timeout starting drag by win " + win); 7242 } 7243 synchronized (mWindowMap) { 7244 // !!! TODO: ANR the app that has failed to start the drag in time 7245 if (mDragState != null) { 7246 mDragState.unregister(); 7247 mInputMonitor.updateInputWindowsLw(true /*force*/); 7248 mDragState.reset(); 7249 mDragState = null; 7250 } 7251 } 7252 break; 7253 } 7254 7255 case DRAG_END_TIMEOUT: { 7256 IBinder win = (IBinder)msg.obj; 7257 if (DEBUG_DRAG) { 7258 Slog.w(TAG, "Timeout ending drag to win " + win); 7259 } 7260 synchronized (mWindowMap) { 7261 // !!! TODO: ANR the drag-receiving app 7262 if (mDragState != null) { 7263 mDragState.mDragResult = false; 7264 mDragState.endDragLw(); 7265 } 7266 } 7267 break; 7268 } 7269 7270 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7271 notifyHardKeyboardStatusChange(); 7272 break; 7273 } 7274 7275 case BOOT_TIMEOUT: { 7276 performBootTimeout(); 7277 break; 7278 } 7279 7280 case WAITING_FOR_DRAWN_TIMEOUT: { 7281 Pair<WindowState, IRemoteCallback> pair; 7282 synchronized (mWindowMap) { 7283 pair = (Pair<WindowState, IRemoteCallback>)msg.obj; 7284 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first); 7285 if (!mWaitingForDrawn.remove(pair)) { 7286 return; 7287 } 7288 } 7289 try { 7290 pair.second.sendResult(null); 7291 } catch (RemoteException e) { 7292 } 7293 break; 7294 } 7295 7296 case UPDATE_ANIM_PARAMETERS: { 7297 // Used to send multiple changes from the animation side to the layout side. 7298 synchronized (mWindowMap) { 7299 if (copyAnimToLayoutParamsLocked()) { 7300 mH.sendEmptyMessage(CLEAR_PENDING_ACTIONS); 7301 performLayoutAndPlaceSurfacesLocked(); 7302 } 7303 } 7304 break; 7305 } 7306 7307 case SHOW_STRICT_MODE_VIOLATION: { 7308 showStrictModeViolation(msg.arg1); 7309 break; 7310 } 7311 7312 // Animation messages. Move to Window{State}Animator 7313 case SET_TRANSPARENT_REGION: { 7314 Pair<WindowStateAnimator, Region> pair = 7315 (Pair<WindowStateAnimator, Region>) msg.obj; 7316 final WindowStateAnimator winAnimator = pair.first; 7317 winAnimator.setTransparentRegionHint(pair.second); 7318 break; 7319 } 7320 7321 case CLEAR_PENDING_ACTIONS: { 7322 mAnimator.clearPendingActions(); 7323 break; 7324 } 7325 7326 case DO_ANIMATION_CALLBACK: { 7327 try { 7328 ((IRemoteCallback)msg.obj).sendResult(null); 7329 } catch (RemoteException e) { 7330 } 7331 break; 7332 } 7333 } 7334 if (DEBUG_WINDOW_TRACE) { 7335 Slog.v(TAG, "handleMessage: exit"); 7336 } 7337 } 7338 } 7339 7340 // ------------------------------------------------------------- 7341 // IWindowManager API 7342 // ------------------------------------------------------------- 7343 7344 @Override 7345 public IWindowSession openSession(IInputMethodClient client, 7346 IInputContext inputContext) { 7347 if (client == null) throw new IllegalArgumentException("null client"); 7348 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7349 Session session = new Session(this, client, inputContext); 7350 return session; 7351 } 7352 7353 @Override 7354 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7355 synchronized (mWindowMap) { 7356 // The focus for the client is the window immediately below 7357 // where we would place the input method window. 7358 int idx = findDesiredInputMethodWindowIndexLocked(false); 7359 if (idx > 0) { 7360 // TODO(multidisplay): IMEs are only supported on the default display. 7361 WindowState imFocus = getDefaultWindowList().get(idx-1); 7362 if (DEBUG_INPUT_METHOD) { 7363 Slog.i(TAG, "Desired input method target: " + imFocus); 7364 Slog.i(TAG, "Current focus: " + mCurrentFocus); 7365 Slog.i(TAG, "Last focus: " + mLastFocus); 7366 } 7367 if (imFocus != null) { 7368 // This may be a starting window, in which case we still want 7369 // to count it as okay. 7370 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7371 && imFocus.mAppToken != null) { 7372 // The client has definitely started, so it really should 7373 // have a window in this app token. Let's look for it. 7374 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7375 WindowState w = imFocus.mAppToken.windows.get(i); 7376 if (w != imFocus) { 7377 Log.i(TAG, "Switching to real app window: " + w); 7378 imFocus = w; 7379 break; 7380 } 7381 } 7382 } 7383 if (DEBUG_INPUT_METHOD) { 7384 Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7385 if (imFocus.mSession.mClient != null) { 7386 Slog.i(TAG, "IM target client binder: " 7387 + imFocus.mSession.mClient.asBinder()); 7388 Slog.i(TAG, "Requesting client binder: " + client.asBinder()); 7389 } 7390 } 7391 if (imFocus.mSession.mClient != null && 7392 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7393 return true; 7394 } 7395 } 7396 } 7397 7398 // Okay, how about this... what is the current focus? 7399 // It seems in some cases we may not have moved the IM 7400 // target window, such as when it was in a pop-up window, 7401 // so let's also look at the current focus. (An example: 7402 // go to Gmail, start searching so the keyboard goes up, 7403 // press home. Sometimes the IME won't go down.) 7404 // Would be nice to fix this more correctly, but it's 7405 // way at the end of a release, and this should be good enough. 7406 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null 7407 && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7408 return true; 7409 } 7410 } 7411 return false; 7412 } 7413 7414 public void getInitialDisplaySize(int displayId, Point size) { 7415 // TODO(cmautner): Access to DisplayContent should be locked on mWindowMap. Doing that 7416 // could lead to deadlock since this is called from ActivityManager. 7417 final DisplayContent displayContent = getDisplayContent(displayId); 7418 synchronized(displayContent.mDisplaySizeLock) { 7419 size.x = displayContent.mInitialDisplayWidth; 7420 size.y = displayContent.mInitialDisplayHeight; 7421 } 7422 } 7423 7424 public void setForcedDisplaySize(int displayId, int longDimen, int shortDimen) { 7425 synchronized(mWindowMap) { 7426 final DisplayContent displayContent = getDisplayContent(displayId); 7427 int width, height; 7428 if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) { 7429 width = shortDimen < displayContent.mInitialDisplayWidth 7430 ? shortDimen : displayContent.mInitialDisplayWidth; 7431 height = longDimen < displayContent.mInitialDisplayHeight 7432 ? longDimen : displayContent.mInitialDisplayHeight; 7433 } else { 7434 width = longDimen < displayContent.mInitialDisplayWidth 7435 ? longDimen : displayContent.mInitialDisplayWidth; 7436 height = shortDimen < displayContent.mInitialDisplayHeight 7437 ? shortDimen : displayContent.mInitialDisplayHeight; 7438 } 7439 setForcedDisplaySizeLocked(displayContent, width, height); 7440 Settings.Secure.putString(mContext.getContentResolver(), 7441 Settings.Secure.DISPLAY_SIZE_FORCED, width + "," + height); 7442 } 7443 } 7444 7445 private void rebuildBlackFrameLocked() { 7446 if (mBlackFrame != null) { 7447 mBlackFrame.kill(); 7448 mBlackFrame = null; 7449 } 7450 // TODO(multidisplay): For now rotations are only main screen. 7451 final DisplayContent displayContent = getDefaultDisplayContent(); 7452 if (displayContent.mBaseDisplayWidth < displayContent.mInitialDisplayWidth 7453 || displayContent.mBaseDisplayHeight < displayContent.mInitialDisplayHeight) { 7454 int initW, initH, baseW, baseH; 7455 final boolean rotated = (mRotation == Surface.ROTATION_90 7456 || mRotation == Surface.ROTATION_270); 7457 if (DEBUG_BOOT) { 7458 Slog.i(TAG, "BLACK FRAME: rotated=" + rotated + " init=" 7459 + displayContent.mInitialDisplayWidth + "x" 7460 + displayContent.mInitialDisplayHeight + " base=" 7461 + displayContent.mBaseDisplayWidth + "x" 7462 + displayContent.mBaseDisplayHeight); 7463 } 7464 if (rotated) { 7465 initW = displayContent.mInitialDisplayHeight; 7466 initH = displayContent.mInitialDisplayWidth; 7467 baseW = displayContent.mBaseDisplayHeight; 7468 baseH = displayContent.mBaseDisplayWidth; 7469 } else { 7470 initW = displayContent.mInitialDisplayWidth; 7471 initH = displayContent.mInitialDisplayHeight; 7472 baseW = displayContent.mBaseDisplayWidth; 7473 baseH = displayContent.mBaseDisplayHeight; 7474 } 7475 Rect outer = new Rect(0, 0, initW, initH); 7476 Rect inner = new Rect(0, 0, baseW, baseH); 7477 try { 7478 mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER, 7479 mDefaultDisplay.getLayerStack()); 7480 } catch (Surface.OutOfResourcesException e) { 7481 } 7482 } 7483 } 7484 7485 private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { 7486 boolean changed = false; 7487 final String sizeStr = Settings.Secure.getString(mContext.getContentResolver(), 7488 Settings.Secure.DISPLAY_SIZE_FORCED); 7489 if (sizeStr != null && sizeStr.length() > 0) { 7490 final int pos = sizeStr.indexOf(','); 7491 if (pos > 0 && sizeStr.lastIndexOf(',') == pos) { 7492 int width, height; 7493 try { 7494 width = Integer.parseInt(sizeStr.substring(0, pos)); 7495 height = Integer.parseInt(sizeStr.substring(pos+1)); 7496 synchronized(displayContent.mDisplaySizeLock) { 7497 if (displayContent.mBaseDisplayWidth != width 7498 || displayContent.mBaseDisplayHeight != height) { 7499 changed = true; 7500 Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height); 7501 displayContent.mBaseDisplayWidth = width; 7502 displayContent.mBaseDisplayHeight = height; 7503 } 7504 } 7505 } catch (NumberFormatException ex) { 7506 } 7507 } 7508 } 7509 final String densityStr = Settings.Secure.getString(mContext.getContentResolver(), 7510 Settings.Secure.DISPLAY_DENSITY_FORCED); 7511 if (densityStr != null && densityStr.length() > 0) { 7512 int density; 7513 try { 7514 density = Integer.parseInt(densityStr); 7515 synchronized(displayContent.mDisplaySizeLock) { 7516 if (displayContent.mBaseDisplayDensity != density) { 7517 changed = true; 7518 Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density); 7519 displayContent.mBaseDisplayDensity = density; 7520 } 7521 } 7522 } catch (NumberFormatException ex) { 7523 } 7524 } 7525 if (changed) { 7526 rebuildBlackFrameLocked(); 7527 } 7528 } 7529 7530 private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) { 7531 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7532 7533 synchronized(displayContent.mDisplaySizeLock) { 7534 displayContent.mBaseDisplayWidth = width; 7535 displayContent.mBaseDisplayHeight = height; 7536 } 7537 reconfigureDisplayLocked(displayContent); 7538 } 7539 7540 public void clearForcedDisplaySize(int displayId) { 7541 synchronized(mWindowMap) { 7542 final DisplayContent displayContent = getDisplayContent(displayId); 7543 setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth, 7544 displayContent.mInitialDisplayHeight); 7545 Settings.Secure.putString(mContext.getContentResolver(), 7546 Settings.Secure.DISPLAY_SIZE_FORCED, ""); 7547 } 7548 } 7549 7550 public void setForcedDisplayDensity(int displayId, int density) { 7551 synchronized(mWindowMap) { 7552 final DisplayContent displayContent = getDisplayContent(displayId); 7553 setForcedDisplayDensityLocked(displayContent, density); 7554 Settings.Secure.putString(mContext.getContentResolver(), 7555 Settings.Secure.DISPLAY_DENSITY_FORCED, Integer.toString(density)); 7556 } 7557 } 7558 7559 private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) { 7560 Slog.i(TAG, "Using new display density: " + density); 7561 7562 synchronized(displayContent.mDisplaySizeLock) { 7563 displayContent.mBaseDisplayDensity = density; 7564 } 7565 reconfigureDisplayLocked(displayContent); 7566 } 7567 7568 public void clearForcedDisplayDensity(int displayId) { 7569 synchronized(mWindowMap) { 7570 final DisplayContent displayContent = getDisplayContent(displayId); 7571 setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity); 7572 Settings.Secure.putString(mContext.getContentResolver(), 7573 Settings.Secure.DISPLAY_DENSITY_FORCED, ""); 7574 } 7575 } 7576 7577 private void reconfigureDisplayLocked(DisplayContent displayContent) { 7578 mPolicy.setInitialDisplaySize(mDefaultDisplay, displayContent.mBaseDisplayWidth, 7579 displayContent.mBaseDisplayHeight, displayContent.mBaseDisplayDensity); 7580 7581 mLayoutNeeded = true; 7582 7583 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7584 mTempConfiguration.setToDefaults(); 7585 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7586 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7587 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7588 configChanged = true; 7589 } 7590 } 7591 7592 if (configChanged) { 7593 mWaitingForConfig = true; 7594 startFreezingDisplayLocked(false); 7595 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7596 } 7597 7598 rebuildBlackFrameLocked(); 7599 7600 performLayoutAndPlaceSurfacesLocked(); 7601 } 7602 7603 public boolean hasSystemNavBar() { 7604 return mPolicy.hasSystemNavBar(); 7605 } 7606 7607 // ------------------------------------------------------------- 7608 // Internals 7609 // ------------------------------------------------------------- 7610 7611 final WindowState windowForClientLocked(Session session, IWindow client, 7612 boolean throwOnError) { 7613 return windowForClientLocked(session, client.asBinder(), throwOnError); 7614 } 7615 7616 final WindowState windowForClientLocked(Session session, IBinder client, 7617 boolean throwOnError) { 7618 WindowState win = mWindowMap.get(client); 7619 if (localLOGV) Slog.v( 7620 TAG, "Looking up client " + client + ": " + win); 7621 if (win == null) { 7622 RuntimeException ex = new IllegalArgumentException( 7623 "Requested window " + client + " does not exist"); 7624 if (throwOnError) { 7625 throw ex; 7626 } 7627 Slog.w(TAG, "Failed looking up window", ex); 7628 return null; 7629 } 7630 if (session != null && win.mSession != session) { 7631 RuntimeException ex = new IllegalArgumentException( 7632 "Requested window " + client + " is in session " + 7633 win.mSession + ", not " + session); 7634 if (throwOnError) { 7635 throw ex; 7636 } 7637 Slog.w(TAG, "Failed looking up window", ex); 7638 return null; 7639 } 7640 7641 return win; 7642 } 7643 7644 final void rebuildAppWindowListLocked() { 7645 DisplayContentsIterator iterator = new DisplayContentsIterator(); 7646 while (iterator.hasNext()) { 7647 rebuildAppWindowListLocked(iterator.next()); 7648 } 7649 } 7650 7651 private void rebuildAppWindowListLocked(final DisplayContent displayContent) { 7652 final WindowList windows = displayContent.getWindowList(); 7653 int NW = windows.size(); 7654 int i; 7655 int lastBelow = -1; 7656 int numRemoved = 0; 7657 7658 if (mRebuildTmp.length < NW) { 7659 mRebuildTmp = new WindowState[NW+10]; 7660 } 7661 7662 // First remove all existing app windows. 7663 i=0; 7664 while (i < NW) { 7665 WindowState w = windows.get(i); 7666 if (w.mAppToken != null) { 7667 WindowState win = windows.remove(i); 7668 win.mRebuilding = true; 7669 mRebuildTmp[numRemoved] = win; 7670 mWindowsChanged = true; 7671 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 7672 "Rebuild removing window: " + win); 7673 NW--; 7674 numRemoved++; 7675 continue; 7676 } else if (lastBelow == i-1) { 7677 if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER 7678 || w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) { 7679 lastBelow = i; 7680 } 7681 } 7682 i++; 7683 } 7684 7685 // Keep whatever windows were below the app windows still below, 7686 // by skipping them. 7687 lastBelow++; 7688 i = lastBelow; 7689 7690 // First add all of the exiting app tokens... these are no longer 7691 // in the main app list, but still have windows shown. We put them 7692 // in the back because now that the animation is over we no longer 7693 // will care about them. 7694 int NT = mExitingAppTokens.size(); 7695 for (int j=0; j<NT; j++) { 7696 i = reAddAppWindowsLocked(displayContent, i, mExitingAppTokens.get(j)); 7697 } 7698 7699 // And add in the still active app tokens in Z order. 7700 NT = mAnimatingAppTokens.size(); 7701 for (int j=0; j<NT; j++) { 7702 i = reAddAppWindowsLocked(displayContent, i, mAnimatingAppTokens.get(j)); 7703 } 7704 7705 i -= lastBelow; 7706 if (i != numRemoved) { 7707 Slog.w(TAG, "Rebuild removed " + numRemoved 7708 + " windows but added " + i); 7709 for (i=0; i<numRemoved; i++) { 7710 WindowState ws = mRebuildTmp[i]; 7711 if (ws.mRebuilding) { 7712 StringWriter sw = new StringWriter(); 7713 PrintWriter pw = new PrintWriter(sw); 7714 ws.dump(pw, "", true); 7715 pw.flush(); 7716 Slog.w(TAG, "This window was lost: " + ws); 7717 Slog.w(TAG, sw.toString()); 7718 ws.mWinAnimator.destroySurfaceLocked(); 7719 } 7720 } 7721 Slog.w(TAG, "Current app token list:"); 7722 dumpAnimatingAppTokensLocked(); 7723 Slog.w(TAG, "Final window list:"); 7724 dumpWindowsLocked(); 7725 } 7726 } 7727 7728 private final void assignLayersLocked(WindowList windows) { 7729 int N = windows.size(); 7730 int curBaseLayer = 0; 7731 int curLayer = 0; 7732 int i; 7733 7734 if (DEBUG_LAYERS) { 7735 RuntimeException here = new RuntimeException("here"); 7736 here.fillInStackTrace(); 7737 Slog.v(TAG, "Assigning layers", here); 7738 } 7739 7740 for (i=0; i<N; i++) { 7741 final WindowState w = windows.get(i); 7742 final WindowStateAnimator winAnimator = w.mWinAnimator; 7743 boolean layerChanged = false; 7744 int oldLayer = w.mLayer; 7745 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 7746 || (i > 0 && w.mIsWallpaper)) { 7747 curLayer += WINDOW_LAYER_MULTIPLIER; 7748 w.mLayer = curLayer; 7749 } else { 7750 curBaseLayer = curLayer = w.mBaseLayer; 7751 w.mLayer = curLayer; 7752 } 7753 if (w.mLayer != oldLayer) { 7754 layerChanged = true; 7755 } 7756 oldLayer = winAnimator.mAnimLayer; 7757 if (w.mTargetAppToken != null) { 7758 winAnimator.mAnimLayer = 7759 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 7760 } else if (w.mAppToken != null) { 7761 winAnimator.mAnimLayer = 7762 w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment; 7763 } else { 7764 winAnimator.mAnimLayer = w.mLayer; 7765 } 7766 if (w.mIsImWindow) { 7767 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 7768 } else if (w.mIsWallpaper) { 7769 winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 7770 } 7771 if (winAnimator.mAnimLayer != oldLayer) { 7772 layerChanged = true; 7773 } 7774 if (layerChanged && mAnimator.isDimming(winAnimator)) { 7775 // Force an animation pass just to update the mDimAnimator layer. 7776 updateLayoutToAnimationLocked(); 7777 } 7778 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 7779 + winAnimator.mAnimLayer); 7780 //System.out.println( 7781 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 7782 } 7783 } 7784 7785 private boolean mInLayout = false; 7786 private final void performLayoutAndPlaceSurfacesLocked() { 7787 if (mInLayout) { 7788 if (DEBUG) { 7789 throw new RuntimeException("Recursive call!"); 7790 } 7791 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers=" 7792 + Debug.getCallers(3)); 7793 return; 7794 } 7795 7796 if (mWaitingForConfig) { 7797 // Our configuration has changed (most likely rotation), but we 7798 // don't yet have the complete configuration to report to 7799 // applications. Don't do any window layout until we have it. 7800 return; 7801 } 7802 7803 if (mDefaultDisplay == null) { 7804 // Not yet initialized, nothing to do. 7805 return; 7806 } 7807 7808 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 7809 mInLayout = true; 7810 boolean recoveringMemory = false; 7811 7812 try { 7813 if (mForceRemoves != null) { 7814 recoveringMemory = true; 7815 // Wait a little bit for things to settle down, and off we go. 7816 for (int i=0; i<mForceRemoves.size(); i++) { 7817 WindowState ws = mForceRemoves.get(i); 7818 Slog.i(TAG, "Force removing: " + ws); 7819 removeWindowInnerLocked(ws.mSession, ws); 7820 } 7821 mForceRemoves = null; 7822 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 7823 Object tmp = new Object(); 7824 synchronized (tmp) { 7825 try { 7826 tmp.wait(250); 7827 } catch (InterruptedException e) { 7828 } 7829 } 7830 } 7831 } catch (RuntimeException e) { 7832 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 7833 } 7834 7835 try { 7836 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 7837 7838 mInLayout = false; 7839 7840 if (mLayoutNeeded) { 7841 if (++mLayoutRepeatCount < 6) { 7842 requestTraversalLocked(); 7843 } else { 7844 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 7845 mLayoutRepeatCount = 0; 7846 } 7847 } else { 7848 mLayoutRepeatCount = 0; 7849 } 7850 7851 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 7852 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 7853 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE)); 7854 } 7855 } catch (RuntimeException e) { 7856 mInLayout = false; 7857 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 7858 } 7859 7860 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 7861 } 7862 7863 private final void performLayoutLockedInner(final DisplayContent displayContent, 7864 boolean initial, boolean updateInputWindows) { 7865 if (!mLayoutNeeded) { 7866 return; 7867 } 7868 WindowList windows = displayContent.getWindowList(); 7869 mLayoutNeeded = false; 7870 7871 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 7872 final int dw = displayInfo.logicalWidth; 7873 final int dh = displayInfo.logicalHeight; 7874 7875 final int NFW = mFakeWindows.size(); 7876 for (int i=0; i<NFW; i++) { 7877 mFakeWindows.get(i).layout(dw, dh); 7878 } 7879 7880 final int N = windows.size(); 7881 int i; 7882 7883 if (DEBUG_LAYOUT) { 7884 Slog.v(TAG, "-------------------------------------"); 7885 Slog.v(TAG, "performLayout: needed=" 7886 + mLayoutNeeded + " dw=" + dw + " dh=" + dh); 7887 } 7888 7889 WindowStateAnimator universeBackground = null; 7890 7891 mPolicy.beginLayoutLw(dw, dh, mRotation); 7892 mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect); 7893 mScreenRect.set(0, 0, dw, dh); 7894 7895 int seq = mLayoutSeq+1; 7896 if (seq < 0) seq = 0; 7897 mLayoutSeq = seq; 7898 7899 // First perform layout of any root windows (not attached 7900 // to another window). 7901 int topAttached = -1; 7902 for (i = N-1; i >= 0; i--) { 7903 final WindowState win = windows.get(i); 7904 7905 // Don't do layout of a window if it is not visible, or 7906 // soon won't be visible, to avoid wasting time and funky 7907 // changes while a window is animating away. 7908 final boolean gone = win.isGoneForLayoutLw(); 7909 7910 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 7911 Slog.v(TAG, "1ST PASS " + win 7912 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 7913 + " mLayoutAttached=" + win.mLayoutAttached); 7914 final AppWindowToken atoken = win.mAppToken; 7915 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 7916 + win.mViewVisibility + " mRelayoutCalled=" 7917 + win.mRelayoutCalled + " hidden=" 7918 + win.mRootToken.hidden + " hiddenRequested=" 7919 + (atoken != null && atoken.hiddenRequested) 7920 + " mAttachedHidden=" + win.mAttachedHidden); 7921 else Slog.v(TAG, " VIS: mViewVisibility=" 7922 + win.mViewVisibility + " mRelayoutCalled=" 7923 + win.mRelayoutCalled + " hidden=" 7924 + win.mRootToken.hidden + " hiddenRequested=" 7925 + (atoken != null && atoken.hiddenRequested) 7926 + " mAttachedHidden=" + win.mAttachedHidden); 7927 } 7928 7929 // If this view is GONE, then skip it -- keep the current 7930 // frame, and let the caller know so they can ignore it 7931 // if they want. (We do the normal layout for INVISIBLE 7932 // windows, since that means "perform layout as normal, 7933 // just don't display"). 7934 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 7935 || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { 7936 if (!win.mLayoutAttached) { 7937 if (initial) { 7938 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7939 win.mContentChanged = false; 7940 } 7941 win.mLayoutNeeded = false; 7942 win.prelayout(); 7943 mPolicy.layoutWindowLw(win, win.mAttrs, null); 7944 win.mLayoutSeq = seq; 7945 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7946 + win.mFrame + " mContainingFrame=" 7947 + win.mContainingFrame + " mDisplayFrame=" 7948 + win.mDisplayFrame); 7949 } else { 7950 if (topAttached < 0) topAttached = i; 7951 } 7952 } 7953 if (win.mViewVisibility == View.VISIBLE 7954 && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND 7955 && universeBackground == null) { 7956 universeBackground = win.mWinAnimator; 7957 } 7958 } 7959 7960 if (mAnimator.mUniverseBackground != universeBackground) { 7961 mFocusMayChange = true; 7962 mAnimator.mUniverseBackground = universeBackground; 7963 } 7964 7965 // Now perform layout of attached windows, which usually 7966 // depend on the position of the window they are attached to. 7967 // XXX does not deal with windows that are attached to windows 7968 // that are themselves attached. 7969 for (i = topAttached; i >= 0; i--) { 7970 final WindowState win = windows.get(i); 7971 7972 if (win.mLayoutAttached) { 7973 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 7974 + " mHaveFrame=" + win.mHaveFrame 7975 + " mViewVisibility=" + win.mViewVisibility 7976 + " mRelayoutCalled=" + win.mRelayoutCalled); 7977 // If this view is GONE, then skip it -- keep the current 7978 // frame, and let the caller know so they can ignore it 7979 // if they want. (We do the normal layout for INVISIBLE 7980 // windows, since that means "perform layout as normal, 7981 // just don't display"). 7982 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 7983 || !win.mHaveFrame || win.mLayoutNeeded) { 7984 if (initial) { 7985 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7986 win.mContentChanged = false; 7987 } 7988 win.mLayoutNeeded = false; 7989 win.prelayout(); 7990 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 7991 win.mLayoutSeq = seq; 7992 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7993 + win.mFrame + " mContainingFrame=" 7994 + win.mContainingFrame + " mDisplayFrame=" 7995 + win.mDisplayFrame); 7996 } 7997 } 7998 } 7999 8000 // Window frames may have changed. Tell the input dispatcher about it. 8001 mInputMonitor.setUpdateInputWindowsNeededLw(); 8002 if (updateInputWindows) { 8003 mInputMonitor.updateInputWindowsLw(false /*force*/); 8004 } 8005 8006 mPolicy.finishLayoutLw(); 8007 } 8008 8009 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 8010 // If the screen is currently frozen or off, then keep 8011 // it frozen/off until this window draws at its new 8012 // orientation. 8013 if (!okToDisplay()) { 8014 if (DEBUG_ORIENTATION) Slog.v(TAG, 8015 "Changing surface while display frozen: " + w); 8016 w.mOrientationChanging = true; 8017 mInnerFields.mOrientationChangeComplete = false; 8018 if (!mWindowsFreezingScreen) { 8019 mWindowsFreezingScreen = true; 8020 // XXX should probably keep timeout from 8021 // when we first froze the display. 8022 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8023 mH.sendMessageDelayed(mH.obtainMessage( 8024 H.WINDOW_FREEZE_TIMEOUT), 2000); 8025 } 8026 } 8027 } 8028 8029 /** 8030 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8031 * @param windows TODO(cmautner): 8032 * 8033 * @return bitmap indicating if another pass through layout must be made. 8034 */ 8035 public int handleAppTransitionReadyLocked(WindowList windows) { 8036 int changes = 0; 8037 int i; 8038 int NN = mOpeningApps.size(); 8039 boolean goodToGo = true; 8040 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8041 "Checking " + NN + " opening apps (frozen=" 8042 + mDisplayFrozen + " timeout=" 8043 + mAppTransitionTimeout + ")..."); 8044 if (!mDisplayFrozen && !mAppTransitionTimeout) { 8045 // If the display isn't frozen, wait to do anything until 8046 // all of the apps are ready. Otherwise just go because 8047 // we'll unfreeze the display when everyone is ready. 8048 for (i=0; i<NN && goodToGo; i++) { 8049 AppWindowToken wtoken = mOpeningApps.get(i); 8050 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8051 "Check opening app=" + wtoken + ": allDrawn=" 8052 + wtoken.allDrawn + " startingDisplayed=" 8053 + wtoken.startingDisplayed + " startingMoved=" 8054 + wtoken.startingMoved); 8055 if (!wtoken.allDrawn && !wtoken.startingDisplayed 8056 && !wtoken.startingMoved) { 8057 goodToGo = false; 8058 } 8059 } 8060 } 8061 if (goodToGo) { 8062 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 8063 int transit = mNextAppTransition; 8064 if (mSkipAppTransitionAnimation) { 8065 transit = WindowManagerPolicy.TRANSIT_UNSET; 8066 } 8067 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 8068 mAppTransitionReady = false; 8069 mAppTransitionRunning = true; 8070 mAppTransitionTimeout = false; 8071 mStartingIconInTransition = false; 8072 mSkipAppTransitionAnimation = false; 8073 8074 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 8075 8076 rebuildAppWindowListLocked(); 8077 8078 // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper 8079 WindowState oldWallpaper = 8080 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 8081 && !mWallpaperTarget.mWinAnimator.isDummyAnimation() 8082 ? null : mWallpaperTarget; 8083 8084 adjustWallpaperWindowsLocked(); 8085 mInnerFields.mWallpaperMayChange = false; 8086 8087 // The top-most window will supply the layout params, 8088 // and we will determine it below. 8089 LayoutParams animLp = null; 8090 int bestAnimLayer = -1; 8091 boolean fullscreenAnim = false; 8092 8093 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8094 "New wallpaper target=" + mWallpaperTarget 8095 + ", oldWallpaper=" + oldWallpaper 8096 + ", lower target=" + mLowerWallpaperTarget 8097 + ", upper target=" + mUpperWallpaperTarget); 8098 int foundWallpapers = 0; 8099 // Do a first pass through the tokens for two 8100 // things: 8101 // (1) Determine if both the closing and opening 8102 // app token sets are wallpaper targets, in which 8103 // case special animations are needed 8104 // (since the wallpaper needs to stay static 8105 // behind them). 8106 // (2) Find the layout params of the top-most 8107 // application window in the tokens, which is 8108 // what will control the animation theme. 8109 final int NC = mClosingApps.size(); 8110 NN = NC + mOpeningApps.size(); 8111 for (i=0; i<NN; i++) { 8112 AppWindowToken wtoken; 8113 int mode; 8114 if (i < NC) { 8115 wtoken = mClosingApps.get(i); 8116 mode = 1; 8117 } else { 8118 wtoken = mOpeningApps.get(i-NC); 8119 mode = 2; 8120 } 8121 if (mLowerWallpaperTarget != null) { 8122 if (mLowerWallpaperTarget.mAppToken == wtoken 8123 || mUpperWallpaperTarget.mAppToken == wtoken) { 8124 foundWallpapers |= mode; 8125 } 8126 } 8127 if (wtoken.appFullscreen) { 8128 WindowState ws = wtoken.findMainWindow(); 8129 if (ws != null) { 8130 animLp = ws.mAttrs; 8131 bestAnimLayer = ws.mLayer; 8132 fullscreenAnim = true; 8133 } 8134 } else if (!fullscreenAnim) { 8135 WindowState ws = wtoken.findMainWindow(); 8136 if (ws != null) { 8137 if (ws.mLayer > bestAnimLayer) { 8138 animLp = ws.mAttrs; 8139 bestAnimLayer = ws.mLayer; 8140 } 8141 } 8142 } 8143 } 8144 8145 if (foundWallpapers == 3) { 8146 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8147 "Wallpaper animation!"); 8148 switch (transit) { 8149 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 8150 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 8151 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 8152 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN; 8153 break; 8154 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 8155 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 8156 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 8157 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE; 8158 break; 8159 } 8160 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8161 "New transit: " + transit); 8162 } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) { 8163 // We are transitioning from an activity with 8164 // a wallpaper to one without. 8165 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE; 8166 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8167 "New transit away from wallpaper: " + transit); 8168 } else if (mWallpaperTarget != null) { 8169 // We are transitioning from an activity without 8170 // a wallpaper to now showing the wallpaper 8171 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN; 8172 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8173 "New transit into wallpaper: " + transit); 8174 } 8175 8176 // If all closing windows are obscured, then there is 8177 // no need to do an animation. This is the case, for 8178 // example, when this transition is being done behind 8179 // the lock screen. 8180 if (!mPolicy.allowAppAnimationsLw()) { 8181 animLp = null; 8182 } 8183 8184 AppWindowToken topOpeningApp = null; 8185 int topOpeningLayer = 0; 8186 8187 NN = mOpeningApps.size(); 8188 for (i=0; i<NN; i++) { 8189 AppWindowToken wtoken = mOpeningApps.get(i); 8190 final AppWindowAnimator appAnimator = wtoken.mAppAnimator; 8191 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 8192 appAnimator.clearThumbnail(); 8193 wtoken.reportedVisible = false; 8194 wtoken.inPendingTransaction = false; 8195 appAnimator.animation = null; 8196 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 8197 wtoken.updateReportedVisibilityLocked(); 8198 wtoken.waitingToShow = false; 8199 8200 appAnimator.mAllAppWinAnimators.clear(); 8201 final int N = wtoken.allAppWindows.size(); 8202 for (int j = 0; j < N; j++) { 8203 appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); 8204 } 8205 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); 8206 8207 if (animLp != null) { 8208 int layer = -1; 8209 for (int j=0; j<wtoken.windows.size(); j++) { 8210 WindowState win = wtoken.windows.get(j); 8211 if (win.mWinAnimator.mAnimLayer > layer) { 8212 layer = win.mWinAnimator.mAnimLayer; 8213 } 8214 } 8215 if (topOpeningApp == null || layer > topOpeningLayer) { 8216 topOpeningApp = wtoken; 8217 topOpeningLayer = layer; 8218 } 8219 } 8220 } 8221 NN = mClosingApps.size(); 8222 for (i=0; i<NN; i++) { 8223 AppWindowToken wtoken = mClosingApps.get(i); 8224 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8225 "Now closing app" + wtoken); 8226 wtoken.mAppAnimator.clearThumbnail(); 8227 wtoken.inPendingTransaction = false; 8228 wtoken.mAppAnimator.animation = null; 8229 setTokenVisibilityLocked(wtoken, animLp, false, 8230 transit, false); 8231 wtoken.updateReportedVisibilityLocked(); 8232 wtoken.waitingToHide = false; 8233 // Force the allDrawn flag, because we want to start 8234 // this guy's animations regardless of whether it's 8235 // gotten drawn. 8236 wtoken.allDrawn = true; 8237 } 8238 8239 if (mNextAppTransitionThumbnail != null && topOpeningApp != null 8240 && topOpeningApp.mAppAnimator.animation != null) { 8241 // This thumbnail animation is very special, we need to have 8242 // an extra surface with the thumbnail included with the animation. 8243 Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(), 8244 mNextAppTransitionThumbnail.getHeight()); 8245 try { 8246 Surface surface = new Surface(mFxSession, 8247 "thumbnail anim", 8248 dirty.width(), dirty.height(), 8249 PixelFormat.TRANSLUCENT, Surface.HIDDEN); 8250 surface.setLayerStack(mDefaultDisplay.getLayerStack()); 8251 topOpeningApp.mAppAnimator.thumbnail = surface; 8252 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " 8253 + surface + ": CREATE"); 8254 Surface drawSurface = new Surface(); 8255 drawSurface.copyFrom(surface); 8256 Canvas c = drawSurface.lockCanvas(dirty); 8257 c.drawBitmap(mNextAppTransitionThumbnail, 0, 0, null); 8258 drawSurface.unlockCanvasAndPost(c); 8259 drawSurface.release(); 8260 topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer; 8261 Animation anim = createThumbnailAnimationLocked( 8262 transit, true, true, mNextAppTransitionScaleUp); 8263 topOpeningApp.mAppAnimator.thumbnailAnimation = anim; 8264 anim.restrictDuration(MAX_ANIMATION_DURATION); 8265 anim.scaleCurrentDuration(mTransitionAnimationScale); 8266 topOpeningApp.mAppAnimator.thumbnailX = mNextAppTransitionStartX; 8267 topOpeningApp.mAppAnimator.thumbnailY = mNextAppTransitionStartY; 8268 } catch (Surface.OutOfResourcesException e) { 8269 Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width() 8270 + " h=" + dirty.height(), e); 8271 topOpeningApp.mAppAnimator.clearThumbnail(); 8272 } 8273 } 8274 8275 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 8276 mNextAppTransitionPackage = null; 8277 mNextAppTransitionThumbnail = null; 8278 scheduleAnimationCallback(mNextAppTransitionCallback); 8279 mNextAppTransitionCallback = null; 8280 8281 mOpeningApps.clear(); 8282 mClosingApps.clear(); 8283 8284 // This has changed the visibility of windows, so perform 8285 // a new layout to get them all up-to-date. 8286 changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT 8287 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8288 mLayoutNeeded = true; 8289 8290 // TODO(multidisplay): IMEs are only supported on the default display. 8291 if (windows == getDefaultWindowList() && !moveInputMethodWindowsIfNeededLocked(true)) { 8292 assignLayersLocked(windows); 8293 } 8294 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/); 8295 mFocusMayChange = false; 8296 } 8297 8298 return changes; 8299 } 8300 8301 /** 8302 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8303 * @return bitmap indicating if another pass through layout must be made. 8304 */ 8305 private int handleAnimatingStoppedAndTransitionLocked() { 8306 int changes = 0; 8307 8308 mAppTransitionRunning = false; 8309 // Restore window app tokens to the ActivityManager views 8310 for (int i = mAnimatingAppTokens.size() - 1; i >= 0; i--) { 8311 mAnimatingAppTokens.get(i).sendingToBottom = false; 8312 } 8313 mAnimatingAppTokens.clear(); 8314 mAnimatingAppTokens.addAll(mAppTokens); 8315 rebuildAppWindowListLocked(); 8316 8317 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8318 mInnerFields.mAdjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED; 8319 moveInputMethodWindowsIfNeededLocked(true); 8320 mInnerFields.mWallpaperMayChange = true; 8321 // Since the window list has been rebuilt, focus might 8322 // have to be recomputed since the actual order of windows 8323 // might have changed again. 8324 mFocusMayChange = true; 8325 8326 return changes; 8327 } 8328 8329 /** 8330 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8331 * 8332 * @return bitmap indicating if another pass through layout must be made. 8333 */ 8334 private int animateAwayWallpaperLocked() { 8335 int changes = 0; 8336 WindowState oldWallpaper = mWallpaperTarget; 8337 if (mLowerWallpaperTarget != null 8338 && mLowerWallpaperTarget.mAppToken != null) { 8339 if (DEBUG_WALLPAPER) Slog.v(TAG, 8340 "wallpaperForceHiding changed with lower=" 8341 + mLowerWallpaperTarget); 8342 if (DEBUG_WALLPAPER) Slog.v(TAG, 8343 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden + 8344 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested); 8345 if (mLowerWallpaperTarget.mAppToken.hidden) { 8346 // The lower target has become hidden before we 8347 // actually started the animation... let's completely 8348 // re-evaluate everything. 8349 mLowerWallpaperTarget = mUpperWallpaperTarget = null; 8350 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8351 } 8352 } 8353 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 8354 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper 8355 + " NEW: " + mWallpaperTarget 8356 + " LOWER: " + mLowerWallpaperTarget); 8357 return changes; 8358 } 8359 8360 private void updateResizingWindows(final WindowState w) { 8361 final WindowStateAnimator winAnimator = w.mWinAnimator; 8362 if (w.mHasSurface && !w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) { 8363 w.mContentInsetsChanged |= 8364 !w.mLastContentInsets.equals(w.mContentInsets); 8365 w.mVisibleInsetsChanged |= 8366 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 8367 boolean configChanged = 8368 w.mConfiguration != mCurConfiguration 8369 && (w.mConfiguration == null 8370 || mCurConfiguration.diff(w.mConfiguration) != 0); 8371 if (DEBUG_CONFIGURATION && configChanged) { 8372 Slog.v(TAG, "Win " + w + " config changed: " 8373 + mCurConfiguration); 8374 } 8375 if (localLOGV) Slog.v(TAG, "Resizing " + w 8376 + ": configChanged=" + configChanged 8377 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8378 w.mLastFrame.set(w.mFrame); 8379 if (w.mContentInsetsChanged 8380 || w.mVisibleInsetsChanged 8381 || winAnimator.mSurfaceResized 8382 || configChanged) { 8383 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8384 Slog.v(TAG, "Resize reasons: " 8385 + " contentInsetsChanged=" + w.mContentInsetsChanged 8386 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8387 + " surfaceResized=" + winAnimator.mSurfaceResized 8388 + " configChanged=" + configChanged); 8389 } 8390 8391 w.mLastContentInsets.set(w.mContentInsets); 8392 w.mLastVisibleInsets.set(w.mVisibleInsets); 8393 makeWindowFreezingScreenIfNeededLocked(w); 8394 // If the orientation is changing, then we need to 8395 // hold off on unfreezing the display until this 8396 // window has been redrawn; to do that, we need 8397 // to go through the process of getting informed 8398 // by the application when it has finished drawing. 8399 if (w.mOrientationChanging) { 8400 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8401 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8402 + w + ", surface " + winAnimator.mSurface); 8403 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8404 if (w.mAppToken != null) { 8405 w.mAppToken.allDrawn = false; 8406 } 8407 } 8408 if (!mResizingWindows.contains(w)) { 8409 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8410 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8411 + "x" + winAnimator.mSurfaceH); 8412 mResizingWindows.add(w); 8413 } 8414 } else if (w.mOrientationChanging) { 8415 if (w.isDrawnLw()) { 8416 if (DEBUG_ORIENTATION) Slog.v(TAG, 8417 "Orientation not waiting for draw in " 8418 + w + ", surface " + winAnimator.mSurface); 8419 w.mOrientationChanging = false; 8420 } 8421 } 8422 } 8423 } 8424 8425 /** 8426 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8427 * 8428 * @param w WindowState this method is applied to. 8429 * @param currentTime The time which animations use for calculating transitions. 8430 * @param innerDw Width of app window. 8431 * @param innerDh Height of app window. 8432 */ 8433 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8434 final int innerDw, final int innerDh) { 8435 final WindowManager.LayoutParams attrs = w.mAttrs; 8436 final int attrFlags = attrs.flags; 8437 final boolean canBeSeen = w.isDisplayedLw(); 8438 8439 if (w.mHasSurface) { 8440 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8441 mInnerFields.mHoldScreen = w.mSession; 8442 } 8443 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8444 && mInnerFields.mScreenBrightness < 0) { 8445 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8446 } 8447 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8448 && mInnerFields.mButtonBrightness < 0) { 8449 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8450 } 8451 if (canBeSeen 8452 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG 8453 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD 8454 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) { 8455 mInnerFields.mSyswin = true; 8456 } 8457 } 8458 8459 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8460 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8461 // This window completely covers everything behind it, 8462 // so we want to leave all of them as undimmed (for 8463 // performance reasons). 8464 mInnerFields.mObscured = true; 8465 } else if (canBeSeen && (attrFlags & FLAG_DIM_BEHIND) != 0 8466 && !(w.mAppToken != null && w.mAppToken.hiddenRequested) 8467 && !w.mExiting) { 8468 if (localLOGV) Slog.v(TAG, "Win " + w + " obscured=" + mInnerFields.mObscured); 8469 if (!mInnerFields.mDimming) { 8470 //Slog.i(TAG, "DIM BEHIND: " + w); 8471 mInnerFields.mDimming = true; 8472 final WindowStateAnimator winAnimator = w.mWinAnimator; 8473 if (!mAnimator.isDimming(winAnimator)) { 8474 final int width, height; 8475 if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { 8476 final DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo(); 8477 width = displayInfo.logicalWidth; 8478 height = displayInfo.logicalHeight; 8479 } else { 8480 width = innerDw; 8481 height = innerDh; 8482 } 8483 startDimming(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height); 8484 } 8485 } 8486 } 8487 } 8488 8489 private void updateAllDrawnLocked() { 8490 // See if any windows have been drawn, so they (and others 8491 // associated with them) can now be shown. 8492 final ArrayList<AppWindowToken> appTokens = mAnimatingAppTokens; 8493 final int NT = appTokens.size(); 8494 for (int i=0; i<NT; i++) { 8495 AppWindowToken wtoken = appTokens.get(i); 8496 if (!wtoken.allDrawn) { 8497 int numInteresting = wtoken.numInterestingWindows; 8498 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 8499 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 8500 "allDrawn: " + wtoken 8501 + " interesting=" + numInteresting 8502 + " drawn=" + wtoken.numDrawnWindows); 8503 wtoken.allDrawn = true; 8504 } 8505 } 8506 } 8507 } 8508 8509 // "Something has changed! Let's make it correct now." 8510 private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { 8511 if (DEBUG_WINDOW_TRACE) { 8512 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 8513 + Debug.getCallers(3)); 8514 } 8515 if (mDefaultDisplay == null) { 8516 Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay"); 8517 return; 8518 } 8519 8520 final long currentTime = SystemClock.uptimeMillis(); 8521 8522 int i; 8523 8524 if (mFocusMayChange) { 8525 mFocusMayChange = false; 8526 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 8527 false /*updateInputWindows*/); 8528 } 8529 8530 // Initialize state of exiting tokens. 8531 for (i=mExitingTokens.size()-1; i>=0; i--) { 8532 mExitingTokens.get(i).hasVisible = false; 8533 } 8534 8535 // Initialize state of exiting applications. 8536 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8537 mExitingAppTokens.get(i).hasVisible = false; 8538 } 8539 8540 mInnerFields.mHoldScreen = null; 8541 mInnerFields.mScreenBrightness = -1; 8542 mInnerFields.mButtonBrightness = -1; 8543 mTransactionSequence++; 8544 8545 final DisplayContent defaultDisplay = getDefaultDisplayContent(); 8546 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 8547 final int defaultDw = defaultInfo.logicalWidth; 8548 final int defaultDh = defaultInfo.logicalHeight; 8549 final int defaultInnerDw = defaultInfo.appWidth; 8550 final int defaultInnerDh = defaultInfo.appHeight; 8551 8552 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8553 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 8554 Surface.openTransaction(); 8555 try { 8556 8557 if (mWatermark != null) { 8558 mWatermark.positionSurface(defaultDw, defaultDh); 8559 } 8560 if (mStrictModeFlash != null) { 8561 mStrictModeFlash.positionSurface(defaultDw, defaultDh); 8562 } 8563 8564 // Give the display manager a chance to adjust properties 8565 // like display rotation if it needs to. 8566 mDisplayManagerService.performTraversalInTransactionFromWindowManager(); 8567 8568 boolean focusDisplayed = false; 8569 boolean updateAllDrawn = false; 8570 8571 DisplayContentsIterator iterator = new DisplayContentsIterator(); 8572 while (iterator.hasNext()) { 8573 final DisplayContent displayContent = iterator.next(); 8574 WindowList windows = displayContent.getWindowList(); 8575 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 8576 final int dw = displayInfo.logicalWidth; 8577 final int dh = displayInfo.logicalHeight; 8578 final int innerDw = displayInfo.appWidth; 8579 final int innerDh = displayInfo.appHeight; 8580 final boolean isDefaultDisplay = 8581 displayContent.getDisplayId() == Display.DEFAULT_DISPLAY; 8582 8583 int repeats = 0; 8584 do { 8585 repeats++; 8586 if (repeats > 6) { 8587 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 8588 mLayoutNeeded = false; 8589 displayContent.layoutNeeded = false; 8590 break; 8591 } 8592 8593 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 8594 displayContent.pendingLayoutChanges); 8595 8596 if (isDefaultDisplay && ((displayContent.pendingLayoutChanges 8597 & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) 8598 && ((adjustWallpaperWindowsLocked() 8599 & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0)) { 8600 assignLayersLocked(windows); 8601 mLayoutNeeded = true; 8602 displayContent.layoutNeeded = true; 8603 } 8604 8605 if (isDefaultDisplay && (displayContent.pendingLayoutChanges 8606 & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 8607 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 8608 if (updateOrientationFromAppTokensLocked(true)) { 8609 mLayoutNeeded = true; 8610 displayContent.layoutNeeded = true; 8611 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8612 } 8613 } 8614 8615 if ((displayContent.pendingLayoutChanges 8616 & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8617 mLayoutNeeded = true; 8618 displayContent.layoutNeeded = true; 8619 } 8620 8621 // FIRST LOOP: Perform a layout, if needed. 8622 if (repeats < 4) { 8623 performLayoutLockedInner(displayContent, repeats == 1, 8624 false /*updateInputWindows*/); 8625 } else { 8626 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 8627 } 8628 8629 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 8630 // it is animating. 8631 displayContent.pendingLayoutChanges = 0; 8632 8633 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " 8634 + mLayoutRepeatCount, displayContent.pendingLayoutChanges); 8635 8636 mPolicy.beginPostLayoutPolicyLw(dw, dh); 8637 for (i = windows.size() - 1; i >= 0; i--) { 8638 WindowState w = windows.get(i); 8639 if (w.mHasSurface) { 8640 mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); 8641 } 8642 } 8643 displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); 8644 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishPostLayoutPolicyLw", 8645 displayContent.pendingLayoutChanges); 8646 } while (displayContent.pendingLayoutChanges != 0); 8647 8648 mInnerFields.mObscured = false; 8649 mInnerFields.mDimming = false; 8650 mInnerFields.mSyswin = false; 8651 8652 // Only used if default window 8653 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 8654 8655 final int N = windows.size(); 8656 for (i=N-1; i>=0; i--) { 8657 WindowState w = windows.get(i); 8658 8659 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 8660 8661 // Update effect. 8662 w.mObscured = mInnerFields.mObscured; 8663 if (!mInnerFields.mObscured) { 8664 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 8665 } 8666 8667 if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) 8668 && w.isVisibleLw()) { 8669 // This is the wallpaper target and its obscured state 8670 // changed... make sure the current wallaper's visibility 8671 // has been updated accordingly. 8672 updateWallpaperVisibilityLocked(); 8673 } 8674 8675 final WindowStateAnimator winAnimator = w.mWinAnimator; 8676 8677 // If the window has moved due to its containing 8678 // content frame changing, then we'd like to animate 8679 // it. 8680 if (w.mHasSurface && w.shouldAnimateMove()) { 8681 // Frame has moved, containing content frame 8682 // has also moved, and we're not currently animating... 8683 // let's do something. 8684 Animation a = AnimationUtils.loadAnimation(mContext, 8685 com.android.internal.R.anim.window_move_from_decor); 8686 winAnimator.setAnimation(a); 8687 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 8688 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 8689 try { 8690 w.mClient.moved(w.mFrame.left, w.mFrame.top); 8691 } catch (RemoteException e) { 8692 } 8693 } 8694 8695 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 8696 w.mContentChanged = false; 8697 8698 // Moved from updateWindowsAndWallpaperLocked(). 8699 if (w.mHasSurface) { 8700 // Take care of the window being ready to display. 8701 if (isDefaultDisplay 8702 && winAnimator.commitFinishDrawingLocked(currentTime)) { 8703 if ((w.mAttrs.flags 8704 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 8705 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 8706 "First draw done in potential wallpaper target " + w); 8707 mInnerFields.mWallpaperMayChange = true; 8708 displayContent.pendingLayoutChanges |= 8709 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 8710 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 8711 debugLayoutRepeats( 8712 "wallpaper and commitFinishDrawingLocked true", 8713 displayContent.pendingLayoutChanges); 8714 } 8715 } 8716 } 8717 8718 winAnimator.setSurfaceBoundaries(recoveringMemory); 8719 8720 final AppWindowToken atoken = w.mAppToken; 8721 if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) { 8722 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" 8723 + w.isOnScreen() + " allDrawn=" + atoken.allDrawn 8724 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); 8725 } 8726 if (atoken != null 8727 && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { 8728 if (atoken.lastTransactionSequence != mTransactionSequence) { 8729 atoken.lastTransactionSequence = mTransactionSequence; 8730 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 8731 atoken.startingDisplayed = false; 8732 } 8733 if ((w.isOnScreen() || winAnimator.mAttrType 8734 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION) 8735 && !w.mExiting && !w.mDestroying) { 8736 if (WindowManagerService.DEBUG_VISIBILITY || 8737 WindowManagerService.DEBUG_ORIENTATION) { 8738 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 8739 + ", isAnimating=" + winAnimator.isAnimating()); 8740 if (!w.isDrawnLw()) { 8741 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface 8742 + " pv=" + w.mPolicyVisibility 8743 + " mDrawState=" + winAnimator.mDrawState 8744 + " ah=" + w.mAttachedHidden 8745 + " th=" + atoken.hiddenRequested 8746 + " a=" + winAnimator.mAnimating); 8747 } 8748 } 8749 if (w != atoken.startingWindow) { 8750 if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { 8751 atoken.numInterestingWindows++; 8752 if (w.isDrawnLw()) { 8753 atoken.numDrawnWindows++; 8754 if (WindowManagerService.DEBUG_VISIBILITY || 8755 WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG, 8756 "tokenMayBeDrawn: " + atoken 8757 + " freezingScreen=" + atoken.mAppAnimator.freezingScreen 8758 + " mAppFreezing=" + w.mAppFreezing); 8759 updateAllDrawn = true; 8760 } 8761 } 8762 } else if (w.isDrawnLw()) { 8763 atoken.startingDisplayed = true; 8764 } 8765 } 8766 } 8767 } 8768 8769 if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) 8770 && w.isDisplayedLw()) { 8771 focusDisplayed = true; 8772 } 8773 8774 updateResizingWindows(w); 8775 } 8776 } 8777 8778 if (updateAllDrawn) { 8779 updateAllDrawnLocked(); 8780 } 8781 8782 if (focusDisplayed) { 8783 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 8784 } 8785 8786 if (!mInnerFields.mDimming && mAnimator.isDimming()) { 8787 stopDimming(); 8788 } 8789 } catch (RuntimeException e) { 8790 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 8791 } finally { 8792 Surface.closeTransaction(); 8793 } 8794 8795 final WindowList defaultWindows = defaultDisplay.getWindowList(); 8796 8797 // If we are ready to perform an app transition, check through 8798 // all of the app tokens to be shown and see if they are ready 8799 // to go. 8800 if (mAppTransitionReady) { 8801 defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); 8802 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 8803 defaultDisplay.pendingLayoutChanges); 8804 } 8805 8806 mInnerFields.mAdjResult = 0; 8807 8808 if (!mAnimator.mAnimating && mAppTransitionRunning) { 8809 // We have finished the animation of an app transition. To do 8810 // this, we have delayed a lot of operations like showing and 8811 // hiding apps, moving apps in Z-order, etc. The app token list 8812 // reflects the correct Z-order, but the window list may now 8813 // be out of sync with it. So here we will just rebuild the 8814 // entire app window list. Fun! 8815 defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 8816 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 8817 defaultDisplay.pendingLayoutChanges); 8818 } 8819 8820 if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 8821 && !mAppTransitionReady) { 8822 // At this point, there was a window with a wallpaper that 8823 // was force hiding other windows behind it, but now it 8824 // is going away. This may be simple -- just animate 8825 // away the wallpaper and its window -- or it may be 8826 // hard -- the wallpaper now needs to be shown behind 8827 // something that was hidden. 8828 defaultDisplay.pendingLayoutChanges |= animateAwayWallpaperLocked(); 8829 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 8830 defaultDisplay.pendingLayoutChanges); 8831 } 8832 mInnerFields.mWallpaperForceHidingChanged = false; 8833 8834 if (mInnerFields.mWallpaperMayChange) { 8835 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 8836 "Wallpaper may change! Adjusting"); 8837 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 8838 } 8839 8840 if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8841 if (DEBUG_WALLPAPER) Slog.v(TAG, 8842 "Wallpaper layer changed: assigning layers + relayout"); 8843 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8844 assignLayersLocked(defaultWindows); 8845 } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { 8846 if (DEBUG_WALLPAPER) Slog.v(TAG, 8847 "Wallpaper visibility changed: relayout"); 8848 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8849 } 8850 8851 if (mFocusMayChange) { 8852 mFocusMayChange = false; 8853 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8854 false /*updateInputWindows*/)) { 8855 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 8856 mInnerFields.mAdjResult = 0; 8857 } 8858 } 8859 8860 if (mLayoutNeeded) { 8861 defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8862 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", 8863 defaultDisplay.pendingLayoutChanges); 8864 } 8865 8866 if (!mResizingWindows.isEmpty()) { 8867 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 8868 WindowState win = mResizingWindows.get(i); 8869 final WindowStateAnimator winAnimator = win.mWinAnimator; 8870 try { 8871 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8872 "Reporting new frame to " + win + ": " + win.mCompatFrame); 8873 int diff = 0; 8874 boolean configChanged = 8875 win.mConfiguration != mCurConfiguration 8876 && (win.mConfiguration == null 8877 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0); 8878 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 8879 && configChanged) { 8880 Slog.i(TAG, "Sending new config to window " + win + ": " 8881 + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH 8882 + " / " + mCurConfiguration + " / 0x" 8883 + Integer.toHexString(diff)); 8884 } 8885 win.mConfiguration = mCurConfiguration; 8886 if (DEBUG_ORIENTATION && 8887 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( 8888 TAG, "Resizing " + win + " WITH DRAW PENDING"); 8889 win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets, 8890 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING, 8891 configChanged ? win.mConfiguration : null); 8892 win.mContentInsetsChanged = false; 8893 win.mVisibleInsetsChanged = false; 8894 winAnimator.mSurfaceResized = false; 8895 } catch (RemoteException e) { 8896 win.mOrientationChanging = false; 8897 } 8898 } 8899 mResizingWindows.clear(); 8900 } 8901 8902 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 8903 "With display frozen, orientationChangeComplete=" 8904 + mInnerFields.mOrientationChangeComplete); 8905 if (mInnerFields.mOrientationChangeComplete) { 8906 if (mWindowsFreezingScreen) { 8907 mWindowsFreezingScreen = false; 8908 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8909 } 8910 stopFreezingDisplayLocked(); 8911 } 8912 8913 // Destroy the surface of any windows that are no longer visible. 8914 boolean wallpaperDestroyed = false; 8915 i = mDestroySurface.size(); 8916 if (i > 0) { 8917 do { 8918 i--; 8919 WindowState win = mDestroySurface.get(i); 8920 win.mDestroying = false; 8921 if (mInputMethodWindow == win) { 8922 mInputMethodWindow = null; 8923 } 8924 if (win == mWallpaperTarget) { 8925 wallpaperDestroyed = true; 8926 } 8927 win.mWinAnimator.destroySurfaceLocked(); 8928 } while (i > 0); 8929 mDestroySurface.clear(); 8930 } 8931 8932 // Time to remove any exiting tokens? 8933 for (i=mExitingTokens.size()-1; i>=0; i--) { 8934 WindowToken token = mExitingTokens.get(i); 8935 if (!token.hasVisible) { 8936 mExitingTokens.remove(i); 8937 if (token.windowType == TYPE_WALLPAPER) { 8938 mWallpaperTokens.remove(token); 8939 updateLayoutToAnimWallpaperTokens(); 8940 } 8941 } 8942 } 8943 8944 // Time to remove any exiting applications? 8945 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8946 AppWindowToken token = mExitingAppTokens.get(i); 8947 if (!token.hasVisible && !mClosingApps.contains(token)) { 8948 // Make sure there is no animation running on this token, 8949 // so any windows associated with it will be removed as 8950 // soon as their animations are complete 8951 token.mAppAnimator.clearAnimation(); 8952 token.mAppAnimator.animating = false; 8953 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 8954 "performLayout: App token exiting now removed" + token); 8955 mAppTokens.remove(token); 8956 mAnimatingAppTokens.remove(token); 8957 mExitingAppTokens.remove(i); 8958 } 8959 } 8960 8961 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 8962 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 8963 try { 8964 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 8965 } catch (RemoteException e) { 8966 } 8967 } 8968 mRelayoutWhileAnimating.clear(); 8969 } 8970 8971 if (wallpaperDestroyed) { 8972 mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0; 8973 } 8974 8975 DisplayContentsIterator iterator = new DisplayContentsIterator(); 8976 while (iterator.hasNext()) { 8977 DisplayContent displayContent = iterator.next(); 8978 if (displayContent.pendingLayoutChanges != 0) { 8979 mLayoutNeeded = true; 8980 } 8981 } 8982 8983 // Finally update all input windows now that the window changes have stabilized. 8984 mInputMonitor.updateInputWindowsLw(true /*force*/); 8985 8986 setHoldScreenLocked(mInnerFields.mHoldScreen); 8987 if (!mDisplayFrozen) { 8988 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 8989 mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1); 8990 } else { 8991 mPowerManager.setScreenBrightnessOverrideFromWindowManager( 8992 toBrightnessOverride(mInnerFields.mScreenBrightness)); 8993 } 8994 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 8995 mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1); 8996 } else { 8997 mPowerManager.setButtonBrightnessOverrideFromWindowManager( 8998 toBrightnessOverride(mInnerFields.mButtonBrightness)); 8999 } 9000 } 9001 9002 if (mTurnOnScreen) { 9003 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 9004 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 9005 mTurnOnScreen = false; 9006 } 9007 9008 if (mInnerFields.mUpdateRotation) { 9009 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9010 if (updateRotationUncheckedLocked(false)) { 9011 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9012 } else { 9013 mInnerFields.mUpdateRotation = false; 9014 } 9015 } 9016 9017 if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded && 9018 !mInnerFields.mUpdateRotation) { 9019 checkDrawnWindowsLocked(); 9020 } 9021 9022 final int N = mPendingRemove.size(); 9023 if (N > 0) { 9024 if (mPendingRemoveTmp.length < N) { 9025 mPendingRemoveTmp = new WindowState[N+10]; 9026 } 9027 mPendingRemove.toArray(mPendingRemoveTmp); 9028 mPendingRemove.clear(); 9029 DisplayContentList displayList = new DisplayContentList(); 9030 for (i = 0; i < N; i++) { 9031 WindowState w = mPendingRemoveTmp[i]; 9032 removeWindowInnerLocked(w.mSession, w); 9033 if (!displayList.contains(w.mDisplayContent)) { 9034 displayList.add(w.mDisplayContent); 9035 } 9036 } 9037 9038 for (DisplayContent displayContent : displayList) { 9039 assignLayersLocked(displayContent.getWindowList()); 9040 } 9041 mLayoutNeeded = true; 9042 } 9043 9044 // Check to see if we are now in a state where the screen should 9045 // be enabled, because the window obscured flags have changed. 9046 enableScreenIfNeededLocked(); 9047 9048 updateLayoutToAnimationLocked(); 9049 9050 if (DEBUG_WINDOW_TRACE) { 9051 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mLayoutNeeded=" 9052 + mLayoutNeeded + " animating=" + mAnimator.mAnimating); 9053 } 9054 } 9055 9056 private int toBrightnessOverride(float value) { 9057 return (int)(value * PowerManager.BRIGHTNESS_ON); 9058 } 9059 9060 void checkDrawnWindowsLocked() { 9061 if (mWaitingForDrawn.size() > 0) { 9062 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 9063 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 9064 WindowState win = pair.first; 9065 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 9066 // + win.mRemoved + " visible=" + win.isVisibleLw() 9067 // + " shown=" + win.mSurfaceShown); 9068 if (win.mRemoved || !win.isVisibleLw()) { 9069 // Window has been removed or made invisible; no draw 9070 // will now happen, so stop waiting. 9071 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 9072 try { 9073 pair.second.sendResult(null); 9074 } catch (RemoteException e) { 9075 } 9076 mWaitingForDrawn.remove(pair); 9077 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9078 } else if (win.mWinAnimator.mSurfaceShown) { 9079 // Window is now drawn (and shown). 9080 try { 9081 pair.second.sendResult(null); 9082 } catch (RemoteException e) { 9083 } 9084 mWaitingForDrawn.remove(pair); 9085 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9086 } 9087 } 9088 } 9089 } 9090 9091 public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 9092 synchronized (mWindowMap) { 9093 WindowState win = windowForClientLocked(null, token, true); 9094 if (win != null) { 9095 Pair<WindowState, IRemoteCallback> pair = 9096 new Pair<WindowState, IRemoteCallback>(win, callback); 9097 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 9098 mH.sendMessageDelayed(m, 2000); 9099 mWaitingForDrawn.add(pair); 9100 checkDrawnWindowsLocked(); 9101 } 9102 } 9103 } 9104 9105 void setHoldScreenLocked(final Session newHoldScreen) { 9106 final boolean hold = newHoldScreen != null; 9107 9108 if (hold && mHoldingScreenOn != newHoldScreen) { 9109 mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid)); 9110 } 9111 mHoldingScreenOn = newHoldScreen; 9112 9113 final boolean state = mHoldingScreenWakeLock.isHeld(); 9114 if (hold != state) { 9115 if (hold) { 9116 mPolicy.screenOnStartedLw(); 9117 mHoldingScreenWakeLock.acquire(); 9118 } else { 9119 mPolicy.screenOnStoppedLw(); 9120 mHoldingScreenWakeLock.release(); 9121 } 9122 } 9123 } 9124 9125 public void requestTraversal() { 9126 synchronized (mWindowMap) { 9127 requestTraversalLocked(); 9128 } 9129 } 9130 9131 void requestTraversalLocked() { 9132 if (!mTraversalScheduled) { 9133 mTraversalScheduled = true; 9134 mH.sendEmptyMessage(H.DO_TRAVERSAL); 9135 } 9136 } 9137 9138 /** Note that Locked in this case is on mLayoutToAnim */ 9139 void scheduleAnimationLocked() { 9140 final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim; 9141 if (!layoutToAnim.mAnimationScheduled) { 9142 layoutToAnim.mAnimationScheduled = true; 9143 mChoreographer.postCallback( 9144 Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); 9145 } 9146 } 9147 9148 void updateLayoutToAnimationLocked() { 9149 final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim; 9150 synchronized (layoutToAnim) { 9151 // Copy local params to transfer params. 9152 ArrayList<WinAnimatorList> allWinAnimatorLists = layoutToAnim.mWinAnimatorLists; 9153 allWinAnimatorLists.clear(); 9154 DisplayContentsIterator iterator = new DisplayContentsIterator(); 9155 while (iterator.hasNext()) { 9156 final DisplayContent displayContent = iterator.next(); 9157 WinAnimatorList winAnimatorList = new WinAnimatorList(); 9158 final WindowList windows = displayContent.getWindowList(); 9159 int N = windows.size(); 9160 for (int i = 0; i < N; i++) { 9161 final WindowStateAnimator winAnimator = windows.get(i).mWinAnimator; 9162 if (winAnimator.mSurface != null) { 9163 winAnimatorList.add(winAnimator); 9164 } 9165 } 9166 allWinAnimatorLists.add(winAnimatorList); 9167 } 9168 9169 layoutToAnim.mWallpaperTarget = mWallpaperTarget; 9170 layoutToAnim.mLowerWallpaperTarget = mLowerWallpaperTarget; 9171 layoutToAnim.mUpperWallpaperTarget = mUpperWallpaperTarget; 9172 9173 final ArrayList<AppWindowAnimParams> paramList = layoutToAnim.mAppWindowAnimParams; 9174 paramList.clear(); 9175 int N = mAnimatingAppTokens.size(); 9176 for (int i = 0; i < N; i++) { 9177 paramList.add(new AppWindowAnimParams(mAnimatingAppTokens.get(i).mAppAnimator)); 9178 } 9179 9180 layoutToAnim.mParamsModified = true; 9181 scheduleAnimationLocked(); 9182 } 9183 } 9184 9185 void updateLayoutToAnimWallpaperTokens() { 9186 synchronized(mLayoutToAnim) { 9187 mLayoutToAnim.mWallpaperTokens = new ArrayList<WindowToken>(mWallpaperTokens); 9188 mLayoutToAnim.mChanges |= LayoutToAnimatorParams.WALLPAPER_TOKENS_CHANGED; 9189 } 9190 } 9191 9192 void setAnimDimParams(DimAnimator.Parameters params) { 9193 synchronized (mLayoutToAnim) { 9194 mLayoutToAnim.mDimParams = params; 9195 scheduleAnimationLocked(); 9196 } 9197 } 9198 9199 void startDimming(final WindowStateAnimator winAnimator, final float target, 9200 final int width, final int height) { 9201 setAnimDimParams(new DimAnimator.Parameters(winAnimator, width, height, target)); 9202 } 9203 9204 void stopDimming() { 9205 setAnimDimParams(null); 9206 } 9207 9208 private boolean copyAnimToLayoutParamsLocked() { 9209 boolean doRequest = false; 9210 final WindowAnimator.AnimatorToLayoutParams animToLayout = mAnimator.mAnimToLayout; 9211 synchronized (animToLayout) { 9212 animToLayout.mUpdateQueued = false; 9213 final int bulkUpdateParams = animToLayout.mBulkUpdateParams; 9214 // TODO(cmautner): As the number of bits grows, use masks of bit groups to 9215 // eliminate unnecessary tests. 9216 if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) { 9217 mInnerFields.mUpdateRotation = true; 9218 doRequest = true; 9219 } 9220 if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 9221 mInnerFields.mWallpaperMayChange = true; 9222 doRequest = true; 9223 } 9224 if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 9225 mInnerFields.mWallpaperForceHidingChanged = true; 9226 doRequest = true; 9227 } 9228 if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 9229 mInnerFields.mOrientationChangeComplete = false; 9230 } else { 9231 mInnerFields.mOrientationChangeComplete = true; 9232 if (mWindowsFreezingScreen) { 9233 doRequest = true; 9234 } 9235 } 9236 if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 9237 mTurnOnScreen = true; 9238 } 9239 9240 SparseIntArray pendingLayouts = animToLayout.mPendingLayoutChanges; 9241 final int count = pendingLayouts.size(); 9242 if (count > 0) { 9243 doRequest = true; 9244 } 9245 for (int i = 0; i < count; ++i) { 9246 final DisplayContent displayContent = getDisplayContent(pendingLayouts.keyAt(i)); 9247 displayContent.pendingLayoutChanges = pendingLayouts.valueAt(i); 9248 } 9249 9250 mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper; 9251 } 9252 return doRequest; 9253 } 9254 9255 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 9256 boolean secure) { 9257 final Surface surface = winAnimator.mSurface; 9258 boolean leakedSurface = false; 9259 boolean killedApps = false; 9260 9261 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 9262 winAnimator.mSession.mPid, operation); 9263 9264 if (mForceRemoves == null) { 9265 mForceRemoves = new ArrayList<WindowState>(); 9266 } 9267 9268 long callingIdentity = Binder.clearCallingIdentity(); 9269 try { 9270 // There was some problem... first, do a sanity check of the 9271 // window list to make sure we haven't left any dangling surfaces 9272 // around. 9273 9274 AllWindowsIterator iterator = new AllWindowsIterator(); 9275 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 9276 while (iterator.hasNext()) { 9277 WindowState ws = iterator.next(); 9278 WindowStateAnimator wsa = ws.mWinAnimator; 9279 if (wsa.mSurface != null) { 9280 if (!mSessions.contains(wsa.mSession)) { 9281 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 9282 + ws + " surface=" + wsa.mSurface 9283 + " token=" + ws.mToken 9284 + " pid=" + ws.mSession.mPid 9285 + " uid=" + ws.mSession.mUid); 9286 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9287 wsa.mSurface.destroy(); 9288 wsa.mSurfaceShown = false; 9289 wsa.mSurface = null; 9290 ws.mHasSurface = false; 9291 mForceRemoves.add(ws); 9292 leakedSurface = true; 9293 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 9294 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 9295 + ws + " surface=" + wsa.mSurface 9296 + " token=" + ws.mAppToken); 9297 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 9298 wsa.mSurface.destroy(); 9299 wsa.mSurfaceShown = false; 9300 wsa.mSurface = null; 9301 ws.mHasSurface = false; 9302 leakedSurface = true; 9303 } 9304 } 9305 } 9306 9307 if (!leakedSurface) { 9308 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 9309 SparseIntArray pidCandidates = new SparseIntArray(); 9310 iterator = new AllWindowsIterator(); 9311 while (iterator.hasNext()) { 9312 WindowState ws = iterator.next(); 9313 if (mForceRemoves.contains(ws)) { 9314 continue; 9315 } 9316 WindowStateAnimator wsa = ws.mWinAnimator; 9317 if (wsa.mSurface != null) { 9318 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 9319 } 9320 } 9321 if (pidCandidates.size() > 0) { 9322 int[] pids = new int[pidCandidates.size()]; 9323 for (int i=0; i<pids.length; i++) { 9324 pids[i] = pidCandidates.keyAt(i); 9325 } 9326 try { 9327 if (mActivityManager.killPids(pids, "Free memory", secure)) { 9328 killedApps = true; 9329 } 9330 } catch (RemoteException e) { 9331 } 9332 } 9333 } 9334 9335 if (leakedSurface || killedApps) { 9336 // We managed to reclaim some memory, so get rid of the trouble 9337 // surface and ask the app to request another one. 9338 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 9339 if (surface != null) { 9340 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 9341 "RECOVER DESTROY", null); 9342 surface.destroy(); 9343 winAnimator.mSurfaceShown = false; 9344 winAnimator.mSurface = null; 9345 winAnimator.mWin.mHasSurface = false; 9346 } 9347 9348 try { 9349 winAnimator.mWin.mClient.dispatchGetNewSurface(); 9350 } catch (RemoteException e) { 9351 } 9352 } 9353 } finally { 9354 Binder.restoreCallingIdentity(callingIdentity); 9355 } 9356 9357 return leakedSurface || killedApps; 9358 } 9359 9360 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 9361 WindowState newFocus = computeFocusedWindowLocked(); 9362 if (mCurrentFocus != newFocus) { 9363 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 9364 // This check makes sure that we don't already have the focus 9365 // change message pending. 9366 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 9367 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 9368 if (localLOGV) Slog.v( 9369 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 9370 final WindowState oldFocus = mCurrentFocus; 9371 mCurrentFocus = newFocus; 9372 mAnimator.setCurrentFocus(newFocus); 9373 mLosingFocus.remove(newFocus); 9374 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 9375 9376 // TODO(multidisplay): Focused windows on default display only. 9377 final DisplayContent displayContent = getDefaultDisplayContent(); 9378 9379 final WindowState imWindow = mInputMethodWindow; 9380 if (newFocus != imWindow && oldFocus != imWindow) { 9381 if (moveInputMethodWindowsIfNeededLocked( 9382 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 9383 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 9384 mLayoutNeeded = true; 9385 } 9386 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9387 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9388 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 9389 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 9390 // Client will do the layout, but we need to assign layers 9391 // for handleNewWindowLocked() below. 9392 assignLayersLocked(displayContent.getWindowList()); 9393 } 9394 } 9395 9396 if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 9397 // The change in focus caused us to need to do a layout. Okay. 9398 mLayoutNeeded = true; 9399 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 9400 performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); 9401 } 9402 } 9403 9404 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 9405 // If we defer assigning layers, then the caller is responsible for 9406 // doing this part. 9407 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 9408 } 9409 9410 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 9411 return true; 9412 } 9413 return false; 9414 } 9415 9416 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 9417 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 9418 } 9419 9420 private WindowState computeFocusedWindowLocked() { 9421 WindowState result = null; 9422 WindowState win; 9423 9424 if (mAnimator.mUniverseBackground != null 9425 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { 9426 return mAnimator.mUniverseBackground.mWin; 9427 } 9428 9429 int nextAppIndex = mAppTokens.size()-1; 9430 WindowToken nextApp = nextAppIndex >= 0 9431 ? mAppTokens.get(nextAppIndex) : null; 9432 9433 // TODO(multidisplay): IMEs are only supported on the default display. 9434 WindowList windows = getDefaultWindowList(); 9435 for (int i = windows.size() - 1; i >= 0; i--) { 9436 win = windows.get(i); 9437 9438 if (localLOGV || DEBUG_FOCUS) Slog.v( 9439 TAG, "Looking for focus: " + i 9440 + " = " + win 9441 + ", flags=" + win.mAttrs.flags 9442 + ", canReceive=" + win.canReceiveKeys()); 9443 9444 AppWindowToken thisApp = win.mAppToken; 9445 9446 // If this window's application has been removed, just skip it. 9447 if (thisApp != null && (thisApp.removed || thisApp.sendingToBottom)) { 9448 if (DEBUG_FOCUS) Slog.v(TAG, "Skipping app because " + (thisApp.removed 9449 ? "removed" : "sendingToBottom")); 9450 continue; 9451 } 9452 9453 // If there is a focused app, don't allow focus to go to any 9454 // windows below it. If this is an application window, step 9455 // through the app tokens until we find its app. 9456 if (thisApp != null && nextApp != null && thisApp != nextApp 9457 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 9458 int origAppIndex = nextAppIndex; 9459 while (nextAppIndex > 0) { 9460 if (nextApp == mFocusedApp) { 9461 // Whoops, we are below the focused app... no focus 9462 // for you! 9463 if (localLOGV || DEBUG_FOCUS) Slog.v( 9464 TAG, "Reached focused app: " + mFocusedApp); 9465 return null; 9466 } 9467 nextAppIndex--; 9468 nextApp = mAppTokens.get(nextAppIndex); 9469 if (nextApp == thisApp) { 9470 break; 9471 } 9472 } 9473 if (thisApp != nextApp) { 9474 // Uh oh, the app token doesn't exist! This shouldn't 9475 // happen, but if it does we can get totally hosed... 9476 // so restart at the original app. 9477 nextAppIndex = origAppIndex; 9478 nextApp = mAppTokens.get(nextAppIndex); 9479 } 9480 } 9481 9482 // Dispatch to this window if it is wants key events. 9483 if (win.canReceiveKeys()) { 9484 if (DEBUG_FOCUS) Slog.v( 9485 TAG, "Found focus @ " + i + " = " + win); 9486 result = win; 9487 break; 9488 } 9489 } 9490 9491 return result; 9492 } 9493 9494 private void startFreezingDisplayLocked(boolean inTransaction) { 9495 if (mDisplayFrozen) { 9496 return; 9497 } 9498 9499 if (mDefaultDisplay == null || !mPolicy.isScreenOnFully()) { 9500 // No need to freeze the screen before the system is ready or if 9501 // the screen is off. 9502 return; 9503 } 9504 9505 mScreenFrozenLock.acquire(); 9506 9507 mDisplayFrozen = true; 9508 9509 mInputMonitor.freezeInputDispatchingLw(); 9510 9511 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 9512 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 9513 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 9514 mNextAppTransitionPackage = null; 9515 mNextAppTransitionThumbnail = null; 9516 mAppTransitionReady = true; 9517 } 9518 9519 if (PROFILE_ORIENTATION) { 9520 File file = new File("/data/system/frozen"); 9521 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9522 } 9523 9524 if (CUSTOM_SCREEN_ROTATION) { 9525 if (mAnimator.mScreenRotationAnimation != null) { 9526 mAnimator.mScreenRotationAnimation.kill(); 9527 mAnimator.mScreenRotationAnimation = null; 9528 } 9529 9530 // TODO(multidisplay): rotation on main screen only. 9531 DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo(); 9532 mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, 9533 mDefaultDisplay, mFxSession, inTransaction, displayInfo.logicalWidth, 9534 displayInfo.logicalHeight, mDefaultDisplay.getRotation()); 9535 } 9536 } 9537 9538 private void stopFreezingDisplayLocked() { 9539 if (!mDisplayFrozen) { 9540 return; 9541 } 9542 9543 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) { 9544 if (DEBUG_ORIENTATION) Slog.d(TAG, 9545 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 9546 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 9547 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen); 9548 return; 9549 } 9550 9551 mDisplayFrozen = false; 9552 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9553 if (PROFILE_ORIENTATION) { 9554 Debug.stopMethodTracing(); 9555 } 9556 9557 boolean updateRotation = false; 9558 9559 if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null 9560 && mAnimator.mScreenRotationAnimation.hasScreenshot()) { 9561 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 9562 // TODO(multidisplay): rotation on main screen only. 9563 DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo(); 9564 if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 9565 mTransitionAnimationScale, displayInfo.logicalWidth, 9566 displayInfo.logicalHeight)) { 9567 updateLayoutToAnimationLocked(); 9568 } else { 9569 mAnimator.mScreenRotationAnimation.kill(); 9570 mAnimator.mScreenRotationAnimation = null; 9571 updateRotation = true; 9572 } 9573 } else { 9574 if (mAnimator.mScreenRotationAnimation != null) { 9575 mAnimator.mScreenRotationAnimation.kill(); 9576 mAnimator.mScreenRotationAnimation = null; 9577 } 9578 updateRotation = true; 9579 } 9580 9581 mInputMonitor.thawInputDispatchingLw(); 9582 9583 boolean configChanged; 9584 9585 // While the display is frozen we don't re-compute the orientation 9586 // to avoid inconsistent states. However, something interesting 9587 // could have actually changed during that time so re-evaluate it 9588 // now to catch that. 9589 configChanged = updateOrientationFromAppTokensLocked(false); 9590 9591 // A little kludge: a lot could have happened while the 9592 // display was frozen, so now that we are coming back we 9593 // do a gc so that any remote references the system 9594 // processes holds on others can be released if they are 9595 // no longer needed. 9596 mH.removeMessages(H.FORCE_GC); 9597 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 9598 2000); 9599 9600 mScreenFrozenLock.release(); 9601 9602 if (updateRotation) { 9603 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9604 configChanged |= updateRotationUncheckedLocked(false); 9605 } 9606 9607 if (configChanged) { 9608 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9609 } 9610 } 9611 9612 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 9613 DisplayMetrics dm) { 9614 if (index < tokens.length) { 9615 String str = tokens[index]; 9616 if (str != null && str.length() > 0) { 9617 try { 9618 int val = Integer.parseInt(str); 9619 return val; 9620 } catch (Exception e) { 9621 } 9622 } 9623 } 9624 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 9625 return defDps; 9626 } 9627 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 9628 return val; 9629 } 9630 9631 void createWatermarkInTransaction() { 9632 if (mWatermark != null) { 9633 return; 9634 } 9635 9636 File file = new File("/system/etc/setup.conf"); 9637 FileInputStream in = null; 9638 try { 9639 in = new FileInputStream(file); 9640 DataInputStream ind = new DataInputStream(in); 9641 String line = ind.readLine(); 9642 if (line != null) { 9643 String[] toks = line.split("%"); 9644 if (toks != null && toks.length > 0) { 9645 mWatermark = 9646 new Watermark(mDefaultDisplay, mRealDisplayMetrics, mFxSession, toks); 9647 } 9648 } 9649 } catch (FileNotFoundException e) { 9650 } catch (IOException e) { 9651 } finally { 9652 if (in != null) { 9653 try { 9654 in.close(); 9655 } catch (IOException e) { 9656 } 9657 } 9658 } 9659 } 9660 9661 @Override 9662 public void statusBarVisibilityChanged(int visibility) { 9663 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 9664 != PackageManager.PERMISSION_GRANTED) { 9665 throw new SecurityException("Caller does not hold permission " 9666 + android.Manifest.permission.STATUS_BAR); 9667 } 9668 9669 synchronized (mWindowMap) { 9670 mLastStatusBarVisibility = visibility; 9671 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 9672 updateStatusBarVisibilityLocked(visibility); 9673 } 9674 } 9675 9676 // TOOD(multidisplay): StatusBar on multiple screens? 9677 void updateStatusBarVisibilityLocked(int visibility) { 9678 mInputManager.setSystemUiVisibility(visibility); 9679 final WindowList windows = getDefaultWindowList(); 9680 final int N = windows.size(); 9681 for (int i = 0; i < N; i++) { 9682 WindowState ws = windows.get(i); 9683 try { 9684 int curValue = ws.mSystemUiVisibility; 9685 int diff = curValue ^ visibility; 9686 // We are only interested in differences of one of the 9687 // clearable flags... 9688 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 9689 // ...if it has actually been cleared. 9690 diff &= ~visibility; 9691 int newValue = (curValue&~diff) | (visibility&diff); 9692 if (newValue != curValue) { 9693 ws.mSeq++; 9694 ws.mSystemUiVisibility = newValue; 9695 } 9696 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 9697 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 9698 visibility, newValue, diff); 9699 } 9700 } catch (RemoteException e) { 9701 // so sorry 9702 } 9703 } 9704 } 9705 9706 @Override 9707 public void reevaluateStatusBarVisibility() { 9708 synchronized (mWindowMap) { 9709 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 9710 updateStatusBarVisibilityLocked(visibility); 9711 performLayoutAndPlaceSurfacesLocked(); 9712 } 9713 } 9714 9715 @Override 9716 public FakeWindow addFakeWindow(Looper looper, 9717 InputEventReceiver.Factory inputEventReceiverFactory, 9718 String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys, 9719 boolean hasFocus, boolean touchFullscreen) { 9720 synchronized (mWindowMap) { 9721 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 9722 name, windowType, 9723 layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 9724 int i=0; 9725 while (i<mFakeWindows.size()) { 9726 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 9727 break; 9728 } 9729 } 9730 mFakeWindows.add(i, fw); 9731 mInputMonitor.updateInputWindowsLw(true); 9732 return fw; 9733 } 9734 } 9735 9736 boolean removeFakeWindowLocked(FakeWindow window) { 9737 synchronized (mWindowMap) { 9738 if (mFakeWindows.remove(window)) { 9739 mInputMonitor.updateInputWindowsLw(true); 9740 return true; 9741 } 9742 return false; 9743 } 9744 } 9745 9746 // It is assumed that this method is called only by InputMethodManagerService. 9747 public void saveLastInputMethodWindowForTransition() { 9748 synchronized (mWindowMap) { 9749 // TODO(multidisplay): Pass in the displayID. 9750 DisplayContent displayContent = getDefaultDisplayContent(); 9751 if (mInputMethodWindow != null) { 9752 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget); 9753 } 9754 } 9755 } 9756 9757 @Override 9758 public boolean hasNavigationBar() { 9759 return mPolicy.hasNavigationBar(); 9760 } 9761 9762 public void lockNow() { 9763 mPolicy.lockNow(); 9764 } 9765 9766 void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { 9767 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 9768 mPolicy.dump(" ", pw, args); 9769 } 9770 9771 void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { 9772 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 9773 if (mTokenMap.size() > 0) { 9774 pw.println(" All tokens:"); 9775 Iterator<WindowToken> it = mTokenMap.values().iterator(); 9776 while (it.hasNext()) { 9777 WindowToken token = it.next(); 9778 pw.print(" Token "); pw.print(token.token); 9779 if (dumpAll) { 9780 pw.println(':'); 9781 token.dump(pw, " "); 9782 } else { 9783 pw.println(); 9784 } 9785 } 9786 } 9787 if (mWallpaperTokens.size() > 0) { 9788 pw.println(); 9789 pw.println(" Wallpaper tokens:"); 9790 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 9791 WindowToken token = mWallpaperTokens.get(i); 9792 pw.print(" Wallpaper #"); pw.print(i); 9793 pw.print(' '); pw.print(token); 9794 if (dumpAll) { 9795 pw.println(':'); 9796 token.dump(pw, " "); 9797 } else { 9798 pw.println(); 9799 } 9800 } 9801 } 9802 if (mAppTokens.size() > 0) { 9803 pw.println(); 9804 pw.println(" Application tokens in Z order:"); 9805 for (int i=mAppTokens.size()-1; i>=0; i--) { 9806 pw.print(" App #"); pw.print(i); pw.println(": "); 9807 mAppTokens.get(i).dump(pw, " "); 9808 } 9809 } 9810 if (mFinishedStarting.size() > 0) { 9811 pw.println(); 9812 pw.println(" Finishing start of application tokens:"); 9813 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 9814 WindowToken token = mFinishedStarting.get(i); 9815 pw.print(" Finished Starting #"); pw.print(i); 9816 pw.print(' '); pw.print(token); 9817 if (dumpAll) { 9818 pw.println(':'); 9819 token.dump(pw, " "); 9820 } else { 9821 pw.println(); 9822 } 9823 } 9824 } 9825 if (mExitingTokens.size() > 0) { 9826 pw.println(); 9827 pw.println(" Exiting tokens:"); 9828 for (int i=mExitingTokens.size()-1; i>=0; i--) { 9829 WindowToken token = mExitingTokens.get(i); 9830 pw.print(" Exiting #"); pw.print(i); 9831 pw.print(' '); pw.print(token); 9832 if (dumpAll) { 9833 pw.println(':'); 9834 token.dump(pw, " "); 9835 } else { 9836 pw.println(); 9837 } 9838 } 9839 } 9840 if (mExitingAppTokens.size() > 0) { 9841 pw.println(); 9842 pw.println(" Exiting application tokens:"); 9843 for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 9844 WindowToken token = mExitingAppTokens.get(i); 9845 pw.print(" Exiting App #"); pw.print(i); 9846 pw.print(' '); pw.print(token); 9847 if (dumpAll) { 9848 pw.println(':'); 9849 token.dump(pw, " "); 9850 } else { 9851 pw.println(); 9852 } 9853 } 9854 } 9855 if (mAppTransitionRunning && mAnimatingAppTokens.size() > 0) { 9856 pw.println(); 9857 pw.println(" Application tokens during animation:"); 9858 for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) { 9859 WindowToken token = mAnimatingAppTokens.get(i); 9860 pw.print(" App moving to bottom #"); pw.print(i); 9861 pw.print(' '); pw.print(token); 9862 if (dumpAll) { 9863 pw.println(':'); 9864 token.dump(pw, " "); 9865 } else { 9866 pw.println(); 9867 } 9868 } 9869 } 9870 if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { 9871 pw.println(); 9872 if (mOpeningApps.size() > 0) { 9873 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 9874 } 9875 if (mClosingApps.size() > 0) { 9876 pw.print(" mClosingApps="); pw.println(mClosingApps); 9877 } 9878 } 9879 } 9880 9881 void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) { 9882 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 9883 if (mSessions.size() > 0) { 9884 Iterator<Session> it = mSessions.iterator(); 9885 while (it.hasNext()) { 9886 Session s = it.next(); 9887 pw.print(" Session "); pw.print(s); pw.println(':'); 9888 s.dump(pw, " "); 9889 } 9890 } 9891 } 9892 9893 void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, 9894 ArrayList<WindowState> windows) { 9895 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 9896 dumpWindowsNoHeaderLocked(pw, dumpAll, windows); 9897 } 9898 9899 void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll, 9900 ArrayList<WindowState> windows) { 9901 int j = 0; 9902 final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR); 9903 while (iterator.hasNext()) { 9904 final WindowState w = iterator.next(); 9905 if (windows == null || windows.contains(w)) { 9906 pw.print(" Window #"); pw.print(j++); pw.print(' '); 9907 pw.print(w); pw.println(":"); 9908 w.dump(pw, " ", dumpAll || windows != null); 9909 } 9910 } 9911 if (mInputMethodDialogs.size() > 0) { 9912 pw.println(); 9913 pw.println(" Input method dialogs:"); 9914 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 9915 WindowState w = mInputMethodDialogs.get(i); 9916 if (windows == null || windows.contains(w)) { 9917 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 9918 } 9919 } 9920 } 9921 if (mPendingRemove.size() > 0) { 9922 pw.println(); 9923 pw.println(" Remove pending for:"); 9924 for (int i=mPendingRemove.size()-1; i>=0; i--) { 9925 WindowState w = mPendingRemove.get(i); 9926 if (windows == null || windows.contains(w)) { 9927 pw.print(" Remove #"); pw.print(i); pw.print(' '); 9928 pw.print(w); 9929 if (dumpAll) { 9930 pw.println(":"); 9931 w.dump(pw, " ", true); 9932 } else { 9933 pw.println(); 9934 } 9935 } 9936 } 9937 } 9938 if (mForceRemoves != null && mForceRemoves.size() > 0) { 9939 pw.println(); 9940 pw.println(" Windows force removing:"); 9941 for (int i=mForceRemoves.size()-1; i>=0; i--) { 9942 WindowState w = mForceRemoves.get(i); 9943 pw.print(" Removing #"); pw.print(i); pw.print(' '); 9944 pw.print(w); 9945 if (dumpAll) { 9946 pw.println(":"); 9947 w.dump(pw, " ", true); 9948 } else { 9949 pw.println(); 9950 } 9951 } 9952 } 9953 if (mDestroySurface.size() > 0) { 9954 pw.println(); 9955 pw.println(" Windows waiting to destroy their surface:"); 9956 for (int i=mDestroySurface.size()-1; i>=0; i--) { 9957 WindowState w = mDestroySurface.get(i); 9958 if (windows == null || windows.contains(w)) { 9959 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 9960 pw.print(w); 9961 if (dumpAll) { 9962 pw.println(":"); 9963 w.dump(pw, " ", true); 9964 } else { 9965 pw.println(); 9966 } 9967 } 9968 } 9969 } 9970 if (mLosingFocus.size() > 0) { 9971 pw.println(); 9972 pw.println(" Windows losing focus:"); 9973 for (int i=mLosingFocus.size()-1; i>=0; i--) { 9974 WindowState w = mLosingFocus.get(i); 9975 if (windows == null || windows.contains(w)) { 9976 pw.print(" Losing #"); pw.print(i); pw.print(' '); 9977 pw.print(w); 9978 if (dumpAll) { 9979 pw.println(":"); 9980 w.dump(pw, " ", true); 9981 } else { 9982 pw.println(); 9983 } 9984 } 9985 } 9986 } 9987 if (mResizingWindows.size() > 0) { 9988 pw.println(); 9989 pw.println(" Windows waiting to resize:"); 9990 for (int i=mResizingWindows.size()-1; i>=0; i--) { 9991 WindowState w = mResizingWindows.get(i); 9992 if (windows == null || windows.contains(w)) { 9993 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 9994 pw.print(w); 9995 if (dumpAll) { 9996 pw.println(":"); 9997 w.dump(pw, " ", true); 9998 } else { 9999 pw.println(); 10000 } 10001 } 10002 } 10003 } 10004 if (mWaitingForDrawn.size() > 0) { 10005 pw.println(); 10006 pw.println(" Clients waiting for these windows to be drawn:"); 10007 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 10008 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 10009 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 10010 pw.print(": "); pw.println(pair.second); 10011 } 10012 } 10013 pw.println(); 10014 if (mDefaultDisplay != null) { 10015 DisplayContentsIterator dCIterator = new DisplayContentsIterator(); 10016 while (dCIterator.hasNext()) { 10017 dCIterator.next().dump(pw); 10018 } 10019 } else { 10020 pw.println(" NO DISPLAY"); 10021 } 10022 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 10023 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 10024 if (mLastFocus != mCurrentFocus) { 10025 pw.print(" mLastFocus="); pw.println(mLastFocus); 10026 } 10027 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 10028 if (mInputMethodTarget != null) { 10029 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 10030 } 10031 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 10032 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 10033 if (dumpAll) { 10034 pw.print(" mSystemDecorRect="); pw.print(mSystemDecorRect.toShortString()); 10035 pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); 10036 pw.print(" mScreenRecr="); pw.println(mScreenRect.toShortString()); 10037 if (mLastStatusBarVisibility != 0) { 10038 pw.print(" mLastStatusBarVisibility=0x"); 10039 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 10040 } 10041 if (mInputMethodWindow != null) { 10042 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 10043 } 10044 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 10045 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) { 10046 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 10047 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 10048 } 10049 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 10050 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 10051 if (mInputMethodAnimLayerAdjustment != 0 || 10052 mWallpaperAnimLayerAdjustment != 0) { 10053 pw.print(" mInputMethodAnimLayerAdjustment="); 10054 pw.print(mInputMethodAnimLayerAdjustment); 10055 pw.print(" mWallpaperAnimLayerAdjustment="); 10056 pw.println(mWallpaperAnimLayerAdjustment); 10057 } 10058 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 10059 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 10060 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); 10061 pw.print("mTransactionSequence="); pw.println(mTransactionSequence); 10062 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 10063 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); 10064 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); 10065 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); 10066 pw.print(" mRotation="); pw.print(mRotation); 10067 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 10068 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 10069 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 10070 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 10071 if (mAnimator.mScreenRotationAnimation != null) { 10072 pw.println(" mScreenRotationAnimation:"); 10073 mAnimator.mScreenRotationAnimation.printTo(" ", pw); 10074 } 10075 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 10076 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 10077 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 10078 pw.print(" mTraversalScheduled="); pw.print(mTraversalScheduled); 10079 pw.print(" mNextAppTransition=0x"); 10080 pw.print(Integer.toHexString(mNextAppTransition)); 10081 pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady); 10082 pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning); 10083 pw.print(" mAppTransitionTimeout="); pw.println(mAppTransitionTimeout); 10084 if (mNextAppTransitionType != ActivityOptions.ANIM_NONE) { 10085 pw.print(" mNextAppTransitionType="); pw.println(mNextAppTransitionType); 10086 } 10087 switch (mNextAppTransitionType) { 10088 case ActivityOptions.ANIM_CUSTOM: 10089 pw.print(" mNextAppTransitionPackage="); 10090 pw.println(mNextAppTransitionPackage); 10091 pw.print(" mNextAppTransitionEnter=0x"); 10092 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 10093 pw.print(" mNextAppTransitionExit=0x"); 10094 pw.println(Integer.toHexString(mNextAppTransitionExit)); 10095 break; 10096 case ActivityOptions.ANIM_SCALE_UP: 10097 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); 10098 pw.print(" mNextAppTransitionStartY="); 10099 pw.println(mNextAppTransitionStartY); 10100 pw.print(" mNextAppTransitionStartWidth="); 10101 pw.print(mNextAppTransitionStartWidth); 10102 pw.print(" mNextAppTransitionStartHeight="); 10103 pw.println(mNextAppTransitionStartHeight); 10104 break; 10105 case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP: 10106 case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN: 10107 pw.print(" mNextAppTransitionThumbnail="); 10108 pw.print(mNextAppTransitionThumbnail); 10109 pw.print(" mNextAppTransitionStartX="); 10110 pw.print(mNextAppTransitionStartX); 10111 pw.print(" mNextAppTransitionStartY="); 10112 pw.println(mNextAppTransitionStartY); 10113 pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp); 10114 break; 10115 } 10116 if (mNextAppTransitionCallback != null) { 10117 pw.print(" mNextAppTransitionCallback="); 10118 pw.println(mNextAppTransitionCallback); 10119 } 10120 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 10121 pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 10122 pw.println(" Window Animator:"); 10123 mAnimator.dump(pw, " ", dumpAll); 10124 } 10125 } 10126 10127 boolean dumpWindows(PrintWriter pw, String name, String[] args, 10128 int opti, boolean dumpAll) { 10129 ArrayList<WindowState> windows = new ArrayList<WindowState>(); 10130 if ("visible".equals(name)) { 10131 synchronized(mWindowMap) { 10132 final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR); 10133 while (iterator.hasNext()) { 10134 final WindowState w = iterator.next(); 10135 if (w.mWinAnimator.mSurfaceShown) { 10136 windows.add(w); 10137 } 10138 } 10139 } 10140 } else { 10141 int objectId = 0; 10142 // See if this is an object ID. 10143 try { 10144 objectId = Integer.parseInt(name, 16); 10145 name = null; 10146 } catch (RuntimeException e) { 10147 } 10148 synchronized(mWindowMap) { 10149 final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR); 10150 while (iterator.hasNext()) { 10151 final WindowState w = iterator.next(); 10152 if (name != null) { 10153 if (w.mAttrs.getTitle().toString().contains(name)) { 10154 windows.add(w); 10155 } 10156 } else if (System.identityHashCode(w) == objectId) { 10157 windows.add(w); 10158 } 10159 } 10160 } 10161 } 10162 10163 if (windows.size() <= 0) { 10164 return false; 10165 } 10166 10167 synchronized(mWindowMap) { 10168 dumpWindowsLocked(pw, dumpAll, windows); 10169 } 10170 return true; 10171 } 10172 10173 void dumpLastANRLocked(PrintWriter pw) { 10174 pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)"); 10175 if (mLastANRState == null) { 10176 pw.println(" <no ANR has occurred since boot>"); 10177 } else { 10178 pw.println(mLastANRState); 10179 } 10180 } 10181 10182 /** 10183 * Saves information about the state of the window manager at 10184 * the time an ANR occurred before anything else in the system changes 10185 * in response. 10186 * 10187 * @param appWindowToken The application that ANR'd, may be null. 10188 * @param windowState The window that ANR'd, may be null. 10189 */ 10190 public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) { 10191 StringWriter sw = new StringWriter(); 10192 PrintWriter pw = new PrintWriter(sw); 10193 pw.println(" ANR time: " + DateFormat.getInstance().format(new Date())); 10194 if (appWindowToken != null) { 10195 pw.println(" Application at fault: " + appWindowToken.stringName); 10196 } 10197 if (windowState != null) { 10198 pw.println(" Window at fault: " + windowState.mAttrs.getTitle()); 10199 } 10200 pw.println(); 10201 dumpWindowsNoHeaderLocked(pw, true, null); 10202 pw.close(); 10203 mLastANRState = sw.toString(); 10204 } 10205 10206 @Override 10207 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 10208 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 10209 != PackageManager.PERMISSION_GRANTED) { 10210 pw.println("Permission Denial: can't dump WindowManager from from pid=" 10211 + Binder.getCallingPid() 10212 + ", uid=" + Binder.getCallingUid()); 10213 return; 10214 } 10215 10216 boolean dumpAll = false; 10217 10218 int opti = 0; 10219 while (opti < args.length) { 10220 String opt = args[opti]; 10221 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 10222 break; 10223 } 10224 opti++; 10225 if ("-a".equals(opt)) { 10226 dumpAll = true; 10227 } else if ("-h".equals(opt)) { 10228 pw.println("Window manager dump options:"); 10229 pw.println(" [-a] [-h] [cmd] ..."); 10230 pw.println(" cmd may be one of:"); 10231 pw.println(" l[astanr]: last ANR information"); 10232 pw.println(" p[policy]: policy state"); 10233 pw.println(" s[essions]: active sessions"); 10234 pw.println(" t[okens]: token list"); 10235 pw.println(" w[indows]: window list"); 10236 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 10237 pw.println(" be a partial substring in a window name, a"); 10238 pw.println(" Window hex object identifier, or"); 10239 pw.println(" \"all\" for all windows, or"); 10240 pw.println(" \"visible\" for the visible windows."); 10241 pw.println(" -a: include all available server state."); 10242 return; 10243 } else { 10244 pw.println("Unknown argument: " + opt + "; use -h for help"); 10245 } 10246 } 10247 10248 // Is the caller requesting to dump a particular piece of data? 10249 if (opti < args.length) { 10250 String cmd = args[opti]; 10251 opti++; 10252 if ("lastanr".equals(cmd) || "l".equals(cmd)) { 10253 synchronized(mWindowMap) { 10254 dumpLastANRLocked(pw); 10255 } 10256 return; 10257 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 10258 synchronized(mWindowMap) { 10259 dumpPolicyLocked(pw, args, true); 10260 } 10261 return; 10262 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 10263 synchronized(mWindowMap) { 10264 dumpSessionsLocked(pw, true); 10265 } 10266 return; 10267 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 10268 synchronized(mWindowMap) { 10269 dumpTokensLocked(pw, true); 10270 } 10271 return; 10272 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 10273 synchronized(mWindowMap) { 10274 dumpWindowsLocked(pw, true, null); 10275 } 10276 return; 10277 } else if ("all".equals(cmd) || "a".equals(cmd)) { 10278 synchronized(mWindowMap) { 10279 dumpWindowsLocked(pw, true, null); 10280 } 10281 return; 10282 } else { 10283 // Dumping a single name? 10284 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) { 10285 pw.println("Bad window command, or no windows match: " + cmd); 10286 pw.println("Use -h for help."); 10287 } 10288 return; 10289 } 10290 } 10291 10292 synchronized(mWindowMap) { 10293 pw.println(); 10294 if (dumpAll) { 10295 pw.println("-------------------------------------------------------------------------------"); 10296 } 10297 dumpLastANRLocked(pw); 10298 pw.println(); 10299 if (dumpAll) { 10300 pw.println("-------------------------------------------------------------------------------"); 10301 } 10302 dumpPolicyLocked(pw, args, dumpAll); 10303 pw.println(); 10304 if (dumpAll) { 10305 pw.println("-------------------------------------------------------------------------------"); 10306 } 10307 dumpSessionsLocked(pw, dumpAll); 10308 pw.println(); 10309 if (dumpAll) { 10310 pw.println("-------------------------------------------------------------------------------"); 10311 } 10312 dumpTokensLocked(pw, dumpAll); 10313 pw.println(); 10314 if (dumpAll) { 10315 pw.println("-------------------------------------------------------------------------------"); 10316 } 10317 dumpWindowsLocked(pw, dumpAll, null); 10318 } 10319 } 10320 10321 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 10322 public void monitor() { 10323 synchronized (mWindowMap) { } 10324 } 10325 10326 public interface OnHardKeyboardStatusChangeListener { 10327 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 10328 } 10329 10330 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 10331 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 10332 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 10333 Integer.toHexString(pendingLayoutChanges)); 10334 } 10335 } 10336 10337 public DisplayContent getDisplayContent(final int displayId) { 10338 DisplayContent displayContent = mDisplayContents.get(displayId); 10339 if (displayContent == null) { 10340 displayContent = new DisplayContent(mDisplayManager.getDisplay(displayId)); 10341 mDisplayContents.put(displayId, displayContent); 10342 } 10343 return displayContent; 10344 } 10345 10346 class DisplayContentsIterator implements Iterator<DisplayContent> { 10347 private int cur; 10348 10349 @Override 10350 public boolean hasNext() { 10351 return cur < mDisplayContents.size(); 10352 } 10353 10354 @Override 10355 public DisplayContent next() { 10356 if (hasNext()) { 10357 return mDisplayContents.valueAt(cur++); 10358 } 10359 throw new NoSuchElementException(); 10360 } 10361 10362 @Override 10363 public void remove() { 10364 throw new IllegalArgumentException("AllDisplayContentIterator.remove not implemented"); 10365 } 10366 } 10367 10368 boolean REVERSE_ITERATOR = true; 10369 class AllWindowsIterator implements Iterator<WindowState> { 10370 private DisplayContent mDisplayContent; 10371 private DisplayContentsIterator mDisplayContentsIterator; 10372 private WindowList mWindowList; 10373 private int mWindowListIndex; 10374 private boolean mReverse; 10375 10376 AllWindowsIterator() { 10377 mDisplayContentsIterator = new DisplayContentsIterator(); 10378 mDisplayContent = mDisplayContentsIterator.next(); 10379 mWindowList = mDisplayContent.getWindowList(); 10380 } 10381 10382 AllWindowsIterator(boolean reverse) { 10383 this(); 10384 mReverse = reverse; 10385 mWindowListIndex = reverse ? mWindowList.size() - 1 : 0; 10386 } 10387 10388 @Override 10389 public boolean hasNext() { 10390 if (mReverse) { 10391 return mWindowListIndex >= 0; 10392 } 10393 return mWindowListIndex < mWindowList.size(); 10394 } 10395 10396 @Override 10397 public WindowState next() { 10398 if (hasNext()) { 10399 WindowState win = mWindowList.get(mWindowListIndex); 10400 if (mReverse) { 10401 mWindowListIndex--; 10402 if (mWindowListIndex < 0 && mDisplayContentsIterator.hasNext()) { 10403 mDisplayContent = mDisplayContentsIterator.next(); 10404 mWindowList = mDisplayContent.getWindowList(); 10405 mWindowListIndex = mWindowList.size() - 1; 10406 } 10407 } else { 10408 mWindowListIndex++; 10409 if (mWindowListIndex >= mWindowList.size() 10410 && mDisplayContentsIterator.hasNext()) { 10411 mDisplayContent = mDisplayContentsIterator.next(); 10412 mWindowList = mDisplayContent.getWindowList(); 10413 mWindowListIndex = 0; 10414 } 10415 } 10416 return win; 10417 } 10418 throw new NoSuchElementException(); 10419 } 10420 10421 @Override 10422 public void remove() { 10423 throw new IllegalArgumentException("AllWindowsIterator.remove not implemented"); 10424 } 10425 } 10426 10427 public DisplayContent getDefaultDisplayContent() { 10428 final int displayId = mDefaultDisplay == null 10429 ? Display.DEFAULT_DISPLAY : mDefaultDisplay.getDisplayId(); 10430 return getDisplayContent(displayId); 10431 } 10432 10433 public WindowList getDefaultWindowList() { 10434 return getDefaultDisplayContent().getWindowList(); 10435 } 10436 10437 public DisplayInfo getDefaultDisplayInfo() { 10438 return getDefaultDisplayContent().getDisplayInfo(); 10439 } 10440 10441 public WindowList getWindowList(final Display display) { 10442 return getDisplayContent(display.getDisplayId()).getWindowList(); 10443 } 10444} 10445