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