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