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