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