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