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