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