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