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