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