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