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