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