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