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