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