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