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