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