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