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