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