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