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