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