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