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