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