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