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