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