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