WindowManagerService.java revision be4f5bb7fc08ca25d67525fdd97d15f73d150891
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 5585 // We need to update our screen size information to match the new 5586 // rotation. Note that this is redundant with the later call to 5587 // sendNewConfiguration() that must be called after this function 5588 // returns... however we need to do the screen size part of that 5589 // before then so we have the correct size to use when initializiation 5590 // the rotation animation for the new rotation. 5591 computeScreenConfigurationLocked(null); 5592 5593 if (!inTransaction) { 5594 if (SHOW_TRANSACTIONS) Slog.i(TAG, 5595 ">>> OPEN TRANSACTION setRotationUnchecked"); 5596 Surface.openTransaction(); 5597 } 5598 try { 5599 // NOTE: We disable the rotation in the emulator because 5600 // it doesn't support hardware OpenGL emulation yet. 5601 if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null 5602 && mAnimator.mScreenRotationAnimation.hasScreenshot()) { 5603 if (mAnimator.mScreenRotationAnimation.setRotation(rotation, mFxSession, 5604 MAX_ANIMATION_DURATION, mTransitionAnimationScale, 5605 mCurDisplayWidth, mCurDisplayHeight)) { 5606 scheduleAnimationLocked(); 5607 } 5608 } 5609 Surface.setOrientation(0, rotation); 5610 } finally { 5611 if (!inTransaction) { 5612 Surface.closeTransaction(); 5613 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 5614 "<<< CLOSE TRANSACTION setRotationUnchecked"); 5615 } 5616 } 5617 5618 rebuildBlackFrame(); 5619 5620 for (int i=mWindows.size()-1; i>=0; i--) { 5621 WindowState w = mWindows.get(i); 5622 if (w.mHasSurface) { 5623 if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); 5624 w.mOrientationChanging = true; 5625 mInnerFields.mOrientationChangeComplete = false; 5626 } 5627 } 5628 for (int i=mRotationWatchers.size()-1; i>=0; i--) { 5629 try { 5630 mRotationWatchers.get(i).onRotationChanged(rotation); 5631 } catch (RemoteException e) { 5632 } 5633 } 5634 return true; 5635 } 5636 5637 public int getRotation() { 5638 return mRotation; 5639 } 5640 5641 public int watchRotation(IRotationWatcher watcher) { 5642 final IBinder watcherBinder = watcher.asBinder(); 5643 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 5644 public void binderDied() { 5645 synchronized (mWindowMap) { 5646 for (int i=0; i<mRotationWatchers.size(); i++) { 5647 if (watcherBinder == mRotationWatchers.get(i).asBinder()) { 5648 IRotationWatcher removed = mRotationWatchers.remove(i); 5649 if (removed != null) { 5650 removed.asBinder().unlinkToDeath(this, 0); 5651 } 5652 i--; 5653 } 5654 } 5655 } 5656 } 5657 }; 5658 5659 synchronized (mWindowMap) { 5660 try { 5661 watcher.asBinder().linkToDeath(dr, 0); 5662 mRotationWatchers.add(watcher); 5663 } catch (RemoteException e) { 5664 // Client died, no cleanup needed. 5665 } 5666 5667 return mRotation; 5668 } 5669 } 5670 5671 /** 5672 * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact 5673 * theme attribute) on devices that feature a physical options menu key attempt to position 5674 * their menu panel window along the edge of the screen nearest the physical menu key. 5675 * This lowers the travel distance between invoking the menu panel and selecting 5676 * a menu option. 5677 * 5678 * This method helps control where that menu is placed. Its current implementation makes 5679 * assumptions about the menu key and its relationship to the screen based on whether 5680 * the device's natural orientation is portrait (width < height) or landscape. 5681 * 5682 * The menu key is assumed to be located along the bottom edge of natural-portrait 5683 * devices and along the right edge of natural-landscape devices. If these assumptions 5684 * do not hold for the target device, this method should be changed to reflect that. 5685 * 5686 * @return A {@link Gravity} value for placing the options menu window 5687 */ 5688 public int getPreferredOptionsPanelGravity() { 5689 synchronized (mWindowMap) { 5690 final int rotation = getRotation(); 5691 5692 if (mInitialDisplayWidth < mInitialDisplayHeight) { 5693 // On devices with a natural orientation of portrait 5694 switch (rotation) { 5695 default: 5696 case Surface.ROTATION_0: 5697 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5698 case Surface.ROTATION_90: 5699 return Gravity.RIGHT | Gravity.BOTTOM; 5700 case Surface.ROTATION_180: 5701 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5702 case Surface.ROTATION_270: 5703 return Gravity.LEFT | Gravity.BOTTOM; 5704 } 5705 } else { 5706 // On devices with a natural orientation of landscape 5707 switch (rotation) { 5708 default: 5709 case Surface.ROTATION_0: 5710 return Gravity.RIGHT | Gravity.BOTTOM; 5711 case Surface.ROTATION_90: 5712 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5713 case Surface.ROTATION_180: 5714 return Gravity.LEFT | Gravity.BOTTOM; 5715 case Surface.ROTATION_270: 5716 return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 5717 } 5718 } 5719 } 5720 } 5721 5722 /** 5723 * Starts the view server on the specified port. 5724 * 5725 * @param port The port to listener to. 5726 * 5727 * @return True if the server was successfully started, false otherwise. 5728 * 5729 * @see com.android.server.wm.ViewServer 5730 * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT 5731 */ 5732 public boolean startViewServer(int port) { 5733 if (isSystemSecure()) { 5734 return false; 5735 } 5736 5737 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { 5738 return false; 5739 } 5740 5741 if (port < 1024) { 5742 return false; 5743 } 5744 5745 if (mViewServer != null) { 5746 if (!mViewServer.isRunning()) { 5747 try { 5748 return mViewServer.start(); 5749 } catch (IOException e) { 5750 Slog.w(TAG, "View server did not start"); 5751 } 5752 } 5753 return false; 5754 } 5755 5756 try { 5757 mViewServer = new ViewServer(this, port); 5758 return mViewServer.start(); 5759 } catch (IOException e) { 5760 Slog.w(TAG, "View server did not start"); 5761 } 5762 return false; 5763 } 5764 5765 private boolean isSystemSecure() { 5766 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && 5767 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 5768 } 5769 5770 /** 5771 * Stops the view server if it exists. 5772 * 5773 * @return True if the server stopped, false if it wasn't started or 5774 * couldn't be stopped. 5775 * 5776 * @see com.android.server.wm.ViewServer 5777 */ 5778 public boolean stopViewServer() { 5779 if (isSystemSecure()) { 5780 return false; 5781 } 5782 5783 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { 5784 return false; 5785 } 5786 5787 if (mViewServer != null) { 5788 return mViewServer.stop(); 5789 } 5790 return false; 5791 } 5792 5793 /** 5794 * Indicates whether the view server is running. 5795 * 5796 * @return True if the server is running, false otherwise. 5797 * 5798 * @see com.android.server.wm.ViewServer 5799 */ 5800 public boolean isViewServerRunning() { 5801 if (isSystemSecure()) { 5802 return false; 5803 } 5804 5805 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { 5806 return false; 5807 } 5808 5809 return mViewServer != null && mViewServer.isRunning(); 5810 } 5811 5812 /** 5813 * Lists all availble windows in the system. The listing is written in the 5814 * specified Socket's output stream with the following syntax: 5815 * windowHashCodeInHexadecimal windowName 5816 * Each line of the ouput represents a different window. 5817 * 5818 * @param client The remote client to send the listing to. 5819 * @return False if an error occured, true otherwise. 5820 */ 5821 boolean viewServerListWindows(Socket client) { 5822 if (isSystemSecure()) { 5823 return false; 5824 } 5825 5826 boolean result = true; 5827 5828 WindowState[] windows; 5829 synchronized (mWindowMap) { 5830 //noinspection unchecked 5831 windows = mWindows.toArray(new WindowState[mWindows.size()]); 5832 } 5833 5834 BufferedWriter out = null; 5835 5836 // Any uncaught exception will crash the system process 5837 try { 5838 OutputStream clientStream = client.getOutputStream(); 5839 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 5840 5841 final int count = windows.length; 5842 for (int i = 0; i < count; i++) { 5843 final WindowState w = windows[i]; 5844 out.write(Integer.toHexString(System.identityHashCode(w))); 5845 out.write(' '); 5846 out.append(w.mAttrs.getTitle()); 5847 out.write('\n'); 5848 } 5849 5850 out.write("DONE.\n"); 5851 out.flush(); 5852 } catch (Exception e) { 5853 result = false; 5854 } finally { 5855 if (out != null) { 5856 try { 5857 out.close(); 5858 } catch (IOException e) { 5859 result = false; 5860 } 5861 } 5862 } 5863 5864 return result; 5865 } 5866 5867 /** 5868 * Returns the focused window in the following format: 5869 * windowHashCodeInHexadecimal windowName 5870 * 5871 * @param client The remote client to send the listing to. 5872 * @return False if an error occurred, true otherwise. 5873 */ 5874 boolean viewServerGetFocusedWindow(Socket client) { 5875 if (isSystemSecure()) { 5876 return false; 5877 } 5878 5879 boolean result = true; 5880 5881 WindowState focusedWindow = getFocusedWindow(); 5882 5883 BufferedWriter out = null; 5884 5885 // Any uncaught exception will crash the system process 5886 try { 5887 OutputStream clientStream = client.getOutputStream(); 5888 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); 5889 5890 if(focusedWindow != null) { 5891 out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); 5892 out.write(' '); 5893 out.append(focusedWindow.mAttrs.getTitle()); 5894 } 5895 out.write('\n'); 5896 out.flush(); 5897 } catch (Exception e) { 5898 result = false; 5899 } finally { 5900 if (out != null) { 5901 try { 5902 out.close(); 5903 } catch (IOException e) { 5904 result = false; 5905 } 5906 } 5907 } 5908 5909 return result; 5910 } 5911 5912 /** 5913 * Sends a command to a target window. The result of the command, if any, will be 5914 * written in the output stream of the specified socket. 5915 * 5916 * The parameters must follow this syntax: 5917 * windowHashcode extra 5918 * 5919 * Where XX is the length in characeters of the windowTitle. 5920 * 5921 * The first parameter is the target window. The window with the specified hashcode 5922 * will be the target. If no target can be found, nothing happens. The extra parameters 5923 * will be delivered to the target window and as parameters to the command itself. 5924 * 5925 * @param client The remote client to sent the result, if any, to. 5926 * @param command The command to execute. 5927 * @param parameters The command parameters. 5928 * 5929 * @return True if the command was successfully delivered, false otherwise. This does 5930 * not indicate whether the command itself was successful. 5931 */ 5932 boolean viewServerWindowCommand(Socket client, String command, String parameters) { 5933 if (isSystemSecure()) { 5934 return false; 5935 } 5936 5937 boolean success = true; 5938 Parcel data = null; 5939 Parcel reply = null; 5940 5941 BufferedWriter out = null; 5942 5943 // Any uncaught exception will crash the system process 5944 try { 5945 // Find the hashcode of the window 5946 int index = parameters.indexOf(' '); 5947 if (index == -1) { 5948 index = parameters.length(); 5949 } 5950 final String code = parameters.substring(0, index); 5951 int hashCode = (int) Long.parseLong(code, 16); 5952 5953 // Extract the command's parameter after the window description 5954 if (index < parameters.length()) { 5955 parameters = parameters.substring(index + 1); 5956 } else { 5957 parameters = ""; 5958 } 5959 5960 final WindowState window = findWindow(hashCode); 5961 if (window == null) { 5962 return false; 5963 } 5964 5965 data = Parcel.obtain(); 5966 data.writeInterfaceToken("android.view.IWindow"); 5967 data.writeString(command); 5968 data.writeString(parameters); 5969 data.writeInt(1); 5970 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); 5971 5972 reply = Parcel.obtain(); 5973 5974 final IBinder binder = window.mClient.asBinder(); 5975 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER 5976 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 5977 5978 reply.readException(); 5979 5980 if (!client.isOutputShutdown()) { 5981 out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 5982 out.write("DONE\n"); 5983 out.flush(); 5984 } 5985 5986 } catch (Exception e) { 5987 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); 5988 success = false; 5989 } finally { 5990 if (data != null) { 5991 data.recycle(); 5992 } 5993 if (reply != null) { 5994 reply.recycle(); 5995 } 5996 if (out != null) { 5997 try { 5998 out.close(); 5999 } catch (IOException e) { 6000 6001 } 6002 } 6003 } 6004 6005 return success; 6006 } 6007 6008 public void addWindowChangeListener(WindowChangeListener listener) { 6009 synchronized(mWindowMap) { 6010 mWindowChangeListeners.add(listener); 6011 } 6012 } 6013 6014 public void removeWindowChangeListener(WindowChangeListener listener) { 6015 synchronized(mWindowMap) { 6016 mWindowChangeListeners.remove(listener); 6017 } 6018 } 6019 6020 private void notifyWindowsChanged() { 6021 WindowChangeListener[] windowChangeListeners; 6022 synchronized(mWindowMap) { 6023 if(mWindowChangeListeners.isEmpty()) { 6024 return; 6025 } 6026 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6027 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6028 } 6029 int N = windowChangeListeners.length; 6030 for(int i = 0; i < N; i++) { 6031 windowChangeListeners[i].windowsChanged(); 6032 } 6033 } 6034 6035 private void notifyFocusChanged() { 6036 WindowChangeListener[] windowChangeListeners; 6037 synchronized(mWindowMap) { 6038 if(mWindowChangeListeners.isEmpty()) { 6039 return; 6040 } 6041 windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; 6042 windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); 6043 } 6044 int N = windowChangeListeners.length; 6045 for(int i = 0; i < N; i++) { 6046 windowChangeListeners[i].focusChanged(); 6047 } 6048 } 6049 6050 private WindowState findWindow(int hashCode) { 6051 if (hashCode == -1) { 6052 return getFocusedWindow(); 6053 } 6054 6055 synchronized (mWindowMap) { 6056 final ArrayList<WindowState> windows = mWindows; 6057 final int count = windows.size(); 6058 6059 for (int i = 0; i < count; i++) { 6060 WindowState w = windows.get(i); 6061 if (System.identityHashCode(w) == hashCode) { 6062 return w; 6063 } 6064 } 6065 } 6066 6067 return null; 6068 } 6069 6070 /* 6071 * Instruct the Activity Manager to fetch the current configuration and broadcast 6072 * that to config-changed listeners if appropriate. 6073 */ 6074 void sendNewConfiguration() { 6075 try { 6076 mActivityManager.updateConfiguration(null); 6077 } catch (RemoteException e) { 6078 } 6079 } 6080 6081 public Configuration computeNewConfiguration() { 6082 synchronized (mWindowMap) { 6083 Configuration config = computeNewConfigurationLocked(); 6084 if (config == null && mWaitingForConfig) { 6085 // Nothing changed but we are waiting for something... stop that! 6086 mWaitingForConfig = false; 6087 performLayoutAndPlaceSurfacesLocked(); 6088 } 6089 return config; 6090 } 6091 } 6092 6093 Configuration computeNewConfigurationLocked() { 6094 Configuration config = new Configuration(); 6095 config.fontScale = 0; 6096 if (!computeScreenConfigurationLocked(config)) { 6097 return null; 6098 } 6099 return config; 6100 } 6101 6102 private void adjustDisplaySizeRanges(int rotation, int dw, int dh) { 6103 final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation); 6104 if (width < mSmallestDisplayWidth) { 6105 mSmallestDisplayWidth = width; 6106 } 6107 if (width > mLargestDisplayWidth) { 6108 mLargestDisplayWidth = width; 6109 } 6110 final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation); 6111 if (height < mSmallestDisplayHeight) { 6112 mSmallestDisplayHeight = height; 6113 } 6114 if (height > mLargestDisplayHeight) { 6115 mLargestDisplayHeight = height; 6116 } 6117 } 6118 6119 private int reduceConfigLayout(int curLayout, int rotation, float density, 6120 int dw, int dh) { 6121 // Get the app screen size at this rotation. 6122 int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6123 int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6124 6125 // Compute the screen layout size class for this rotation. 6126 int screenLayoutSize; 6127 boolean screenLayoutLong; 6128 boolean screenLayoutCompatNeeded; 6129 int longSize = w; 6130 int shortSize = h; 6131 if (longSize < shortSize) { 6132 int tmp = longSize; 6133 longSize = shortSize; 6134 shortSize = tmp; 6135 } 6136 longSize = (int)(longSize/density); 6137 shortSize = (int)(shortSize/density); 6138 6139 // These semi-magic numbers define our compatibility modes for 6140 // applications with different screens. These are guarantees to 6141 // app developers about the space they can expect for a particular 6142 // configuration. DO NOT CHANGE! 6143 if (longSize < 470) { 6144 // This is shorter than an HVGA normal density screen (which 6145 // is 480 pixels on its long side). 6146 screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_SMALL; 6147 screenLayoutLong = false; 6148 screenLayoutCompatNeeded = false; 6149 } else { 6150 // What size is this screen screen? 6151 if (longSize >= 960 && shortSize >= 720) { 6152 // 1.5xVGA or larger screens at medium density are the point 6153 // at which we consider it to be an extra large screen. 6154 screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_XLARGE; 6155 } else if (longSize >= 640 && shortSize >= 480) { 6156 // VGA or larger screens at medium density are the point 6157 // at which we consider it to be a large screen. 6158 screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_LARGE; 6159 } else { 6160 screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_NORMAL; 6161 } 6162 6163 // If this screen is wider than normal HVGA, or taller 6164 // than FWVGA, then for old apps we want to run in size 6165 // compatibility mode. 6166 if (shortSize > 321 || longSize > 570) { 6167 screenLayoutCompatNeeded = true; 6168 } else { 6169 screenLayoutCompatNeeded = false; 6170 } 6171 6172 // Is this a long screen? 6173 if (((longSize*3)/5) >= (shortSize-1)) { 6174 // Anything wider than WVGA (5:3) is considering to be long. 6175 screenLayoutLong = true; 6176 } else { 6177 screenLayoutLong = false; 6178 } 6179 } 6180 6181 // Now reduce the last screenLayout to not be better than what we 6182 // have found. 6183 if (!screenLayoutLong) { 6184 curLayout = (curLayout&~Configuration.SCREENLAYOUT_LONG_MASK) 6185 | Configuration.SCREENLAYOUT_LONG_NO; 6186 } 6187 if (screenLayoutCompatNeeded) { 6188 curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED; 6189 } 6190 int curSize = curLayout&Configuration.SCREENLAYOUT_SIZE_MASK; 6191 if (screenLayoutSize < curSize) { 6192 curLayout = (curLayout&~Configuration.SCREENLAYOUT_SIZE_MASK) 6193 | screenLayoutSize; 6194 } 6195 return curLayout; 6196 } 6197 6198 private void computeSizeRangesAndScreenLayout(boolean rotated, int dw, int dh, 6199 float density, Configuration outConfig) { 6200 // We need to determine the smallest width that will occur under normal 6201 // operation. To this, start with the base screen size and compute the 6202 // width under the different possible rotations. We need to un-rotate 6203 // the current screen dimensions before doing this. 6204 int unrotDw, unrotDh; 6205 if (rotated) { 6206 unrotDw = dh; 6207 unrotDh = dw; 6208 } else { 6209 unrotDw = dw; 6210 unrotDh = dh; 6211 } 6212 mSmallestDisplayWidth = 1<<30; 6213 mSmallestDisplayHeight = 1<<30; 6214 mLargestDisplayWidth = 0; 6215 mLargestDisplayHeight = 0; 6216 adjustDisplaySizeRanges(Surface.ROTATION_0, unrotDw, unrotDh); 6217 adjustDisplaySizeRanges(Surface.ROTATION_90, unrotDh, unrotDw); 6218 adjustDisplaySizeRanges(Surface.ROTATION_180, unrotDw, unrotDh); 6219 adjustDisplaySizeRanges(Surface.ROTATION_270, unrotDh, unrotDw); 6220 int sl = Configuration.SCREENLAYOUT_SIZE_XLARGE 6221 | Configuration.SCREENLAYOUT_LONG_YES; 6222 sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh); 6223 sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw); 6224 sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); 6225 sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); 6226 outConfig.smallestScreenWidthDp = (int)(mSmallestDisplayWidth / density); 6227 outConfig.screenLayout = sl; 6228 } 6229 6230 private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, 6231 int dw, int dh) { 6232 dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation); 6233 dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation); 6234 float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); 6235 int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f); 6236 if (curSize == 0 || size < curSize) { 6237 curSize = size; 6238 } 6239 return curSize; 6240 } 6241 6242 private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) { 6243 mTmpDisplayMetrics.setTo(dm); 6244 dm = mTmpDisplayMetrics; 6245 int unrotDw, unrotDh; 6246 if (rotated) { 6247 unrotDw = dh; 6248 unrotDh = dw; 6249 } else { 6250 unrotDw = dw; 6251 unrotDh = dh; 6252 } 6253 int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, dm, unrotDw, unrotDh); 6254 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, dm, unrotDh, unrotDw); 6255 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, dm, unrotDw, unrotDh); 6256 sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, dm, unrotDh, unrotDw); 6257 return sw; 6258 } 6259 6260 boolean computeScreenConfigurationLocked(Configuration config) { 6261 if (mDisplay == null) { 6262 return false; 6263 } 6264 6265 // Use the effective "visual" dimensions based on current rotation 6266 final boolean rotated = (mRotation == Surface.ROTATION_90 6267 || mRotation == Surface.ROTATION_270); 6268 final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 6269 final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 6270 6271 synchronized(mDisplaySizeLock) { 6272 if (mAltOrientation) { 6273 mCurDisplayWidth = realdw; 6274 mCurDisplayHeight = realdh; 6275 if (realdw > realdh) { 6276 // Turn landscape into portrait. 6277 int maxw = (int)(realdh/1.3f); 6278 if (maxw < realdw) { 6279 mCurDisplayWidth = maxw; 6280 } 6281 } else { 6282 // Turn portrait into landscape. 6283 int maxh = (int)(realdw/1.3f); 6284 if (maxh < realdh) { 6285 mCurDisplayHeight = maxh; 6286 } 6287 } 6288 } else { 6289 mCurDisplayWidth = realdw; 6290 mCurDisplayHeight = realdh; 6291 } 6292 } 6293 6294 final int dw = mCurDisplayWidth; 6295 final int dh = mCurDisplayHeight; 6296 6297 if (config != null) { 6298 int orientation = Configuration.ORIENTATION_SQUARE; 6299 if (dw < dh) { 6300 orientation = Configuration.ORIENTATION_PORTRAIT; 6301 } else if (dw > dh) { 6302 orientation = Configuration.ORIENTATION_LANDSCAPE; 6303 } 6304 config.orientation = orientation; 6305 } 6306 6307 // Update real display metrics. 6308 mDisplay.getMetricsWithSize(mRealDisplayMetrics, mCurDisplayWidth, mCurDisplayHeight); 6309 6310 // Update application display metrics. 6311 final DisplayMetrics dm = mDisplayMetrics; 6312 final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); 6313 final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); 6314 synchronized(mDisplaySizeLock) { 6315 mAppDisplayWidth = appWidth; 6316 mAppDisplayHeight = appHeight; 6317 mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight, 6318 mAppDisplayWidth, mAppDisplayHeight); 6319 } 6320 if (false) { 6321 Slog.i(TAG, "Set app display size: " + mAppDisplayWidth 6322 + " x " + mAppDisplayHeight); 6323 } 6324 mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight); 6325 6326 mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, 6327 mCompatDisplayMetrics); 6328 6329 if (config != null) { 6330 config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) 6331 / dm.density); 6332 config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) 6333 / dm.density); 6334 computeSizeRangesAndScreenLayout(rotated, dw, dh, dm.density, config); 6335 6336 config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); 6337 config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); 6338 config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); 6339 6340 // Update the configuration based on available input devices, lid switch, 6341 // and platform configuration. 6342 config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; 6343 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6344 config.navigation = Configuration.NAVIGATION_NONAV; 6345 6346 int keyboardPresence = 0; 6347 int navigationPresence = 0; 6348 for (InputDevice device : mInputManager.getInputDevices()) { 6349 if (!device.isVirtual()) { 6350 final int sources = device.getSources(); 6351 final int presenceFlag = device.isExternal() ? 6352 WindowManagerPolicy.PRESENCE_EXTERNAL : 6353 WindowManagerPolicy.PRESENCE_INTERNAL; 6354 6355 if ((sources & InputDevice.SOURCE_TOUCHSCREEN) != 0) { 6356 config.touchscreen = Configuration.TOUCHSCREEN_FINGER; 6357 } 6358 6359 if ((sources & InputDevice.SOURCE_TRACKBALL) != 0) { 6360 config.navigation = Configuration.NAVIGATION_TRACKBALL; 6361 navigationPresence |= presenceFlag; 6362 } else if ((sources & InputDevice.SOURCE_DPAD) != 0 6363 && config.navigation == Configuration.NAVIGATION_NONAV) { 6364 config.navigation = Configuration.NAVIGATION_DPAD; 6365 navigationPresence |= presenceFlag; 6366 } 6367 6368 if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { 6369 config.keyboard = Configuration.KEYBOARD_QWERTY; 6370 keyboardPresence |= presenceFlag; 6371 } 6372 } 6373 } 6374 6375 // Determine whether a hard keyboard is available and enabled. 6376 boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; 6377 if (hardKeyboardAvailable != mHardKeyboardAvailable) { 6378 mHardKeyboardAvailable = hardKeyboardAvailable; 6379 mHardKeyboardEnabled = hardKeyboardAvailable; 6380 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6381 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); 6382 } 6383 if (!mHardKeyboardEnabled) { 6384 config.keyboard = Configuration.KEYBOARD_NOKEYS; 6385 } 6386 6387 // Let the policy update hidden states. 6388 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; 6389 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; 6390 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; 6391 mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); 6392 } 6393 6394 return true; 6395 } 6396 6397 public boolean isHardKeyboardAvailable() { 6398 synchronized (mWindowMap) { 6399 return mHardKeyboardAvailable; 6400 } 6401 } 6402 6403 public boolean isHardKeyboardEnabled() { 6404 synchronized (mWindowMap) { 6405 return mHardKeyboardEnabled; 6406 } 6407 } 6408 6409 public void setHardKeyboardEnabled(boolean enabled) { 6410 synchronized (mWindowMap) { 6411 if (mHardKeyboardEnabled != enabled) { 6412 mHardKeyboardEnabled = enabled; 6413 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 6414 } 6415 } 6416 } 6417 6418 public void setOnHardKeyboardStatusChangeListener( 6419 OnHardKeyboardStatusChangeListener listener) { 6420 synchronized (mWindowMap) { 6421 mHardKeyboardStatusChangeListener = listener; 6422 } 6423 } 6424 6425 void notifyHardKeyboardStatusChange() { 6426 final boolean available, enabled; 6427 final OnHardKeyboardStatusChangeListener listener; 6428 synchronized (mWindowMap) { 6429 listener = mHardKeyboardStatusChangeListener; 6430 available = mHardKeyboardAvailable; 6431 enabled = mHardKeyboardEnabled; 6432 } 6433 if (listener != null) { 6434 listener.onHardKeyboardStatusChange(available, enabled); 6435 } 6436 } 6437 6438 // ------------------------------------------------------------- 6439 // Drag and drop 6440 // ------------------------------------------------------------- 6441 6442 IBinder prepareDragSurface(IWindow window, SurfaceSession session, 6443 int flags, int width, int height, Surface outSurface) { 6444 if (DEBUG_DRAG) { 6445 Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height 6446 + " flags=" + Integer.toHexString(flags) + " win=" + window 6447 + " asbinder=" + window.asBinder()); 6448 } 6449 6450 final int callerPid = Binder.getCallingPid(); 6451 final long origId = Binder.clearCallingIdentity(); 6452 IBinder token = null; 6453 6454 try { 6455 synchronized (mWindowMap) { 6456 try { 6457 if (mDragState == null) { 6458 Surface surface = new Surface(session, callerPid, "drag surface", 0, 6459 width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN); 6460 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " 6461 + surface + ": CREATE"); 6462 outSurface.copyFrom(surface); 6463 final IBinder winBinder = window.asBinder(); 6464 token = new Binder(); 6465 mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); 6466 token = mDragState.mToken = new Binder(); 6467 6468 // 5 second timeout for this window to actually begin the drag 6469 mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); 6470 Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); 6471 mH.sendMessageDelayed(msg, 5000); 6472 } else { 6473 Slog.w(TAG, "Drag already in progress"); 6474 } 6475 } catch (Surface.OutOfResourcesException e) { 6476 Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); 6477 if (mDragState != null) { 6478 mDragState.reset(); 6479 mDragState = null; 6480 } 6481 } 6482 } 6483 } finally { 6484 Binder.restoreCallingIdentity(origId); 6485 } 6486 6487 return token; 6488 } 6489 6490 // ------------------------------------------------------------- 6491 // Input Events and Focus Management 6492 // ------------------------------------------------------------- 6493 6494 final InputMonitor mInputMonitor = new InputMonitor(this); 6495 6496 public void pauseKeyDispatching(IBinder _token) { 6497 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6498 "pauseKeyDispatching()")) { 6499 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6500 } 6501 6502 synchronized (mWindowMap) { 6503 WindowToken token = mTokenMap.get(_token); 6504 if (token != null) { 6505 mInputMonitor.pauseDispatchingLw(token); 6506 } 6507 } 6508 } 6509 6510 public void resumeKeyDispatching(IBinder _token) { 6511 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6512 "resumeKeyDispatching()")) { 6513 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6514 } 6515 6516 synchronized (mWindowMap) { 6517 WindowToken token = mTokenMap.get(_token); 6518 if (token != null) { 6519 mInputMonitor.resumeDispatchingLw(token); 6520 } 6521 } 6522 } 6523 6524 public void setEventDispatching(boolean enabled) { 6525 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, 6526 "resumeKeyDispatching()")) { 6527 throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); 6528 } 6529 6530 synchronized (mWindowMap) { 6531 mInputMonitor.setEventDispatchingLw(enabled); 6532 } 6533 6534 sendScreenStatusToClients(); 6535 } 6536 6537 private WindowState getFocusedWindow() { 6538 synchronized (mWindowMap) { 6539 return getFocusedWindowLocked(); 6540 } 6541 } 6542 6543 private WindowState getFocusedWindowLocked() { 6544 return mCurrentFocus; 6545 } 6546 6547 public boolean detectSafeMode() { 6548 if (!mInputMonitor.waitForInputDevicesReady( 6549 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { 6550 Slog.w(TAG, "Devices still not ready after waiting " 6551 + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS 6552 + " milliseconds before attempting to detect safe mode."); 6553 } 6554 6555 int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6556 KeyEvent.KEYCODE_MENU); 6557 int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); 6558 int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, 6559 KeyEvent.KEYCODE_DPAD_CENTER); 6560 int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, 6561 InputManagerService.BTN_MOUSE); 6562 int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, 6563 KeyEvent.KEYCODE_VOLUME_DOWN); 6564 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 6565 || volumeDownState > 0; 6566 try { 6567 if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { 6568 mSafeMode = true; 6569 SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); 6570 } 6571 } catch (IllegalArgumentException e) { 6572 } 6573 if (mSafeMode) { 6574 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState 6575 + " dpad=" + dpadState + " trackball=" + trackballState + ")"); 6576 } else { 6577 Log.i(TAG, "SAFE MODE not enabled"); 6578 } 6579 mPolicy.setSafeMode(mSafeMode); 6580 return mSafeMode; 6581 } 6582 6583 public void displayReady() { 6584 synchronized(mWindowMap) { 6585 if (mDisplay != null) { 6586 throw new IllegalStateException("Display already initialized"); 6587 } 6588 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 6589 mDisplay = wm.getDefaultDisplay(); 6590 synchronized(mDisplaySizeLock) { 6591 mInitialDisplayWidth = mDisplay.getRawWidth(); 6592 mInitialDisplayHeight = mDisplay.getRawHeight(); 6593 int rot = mDisplay.getRotation(); 6594 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { 6595 // If the screen is currently rotated, we need to swap the 6596 // initial width and height to get the true natural values. 6597 int tmp = mInitialDisplayWidth; 6598 mInitialDisplayWidth = mInitialDisplayHeight; 6599 mInitialDisplayHeight = tmp; 6600 } 6601 mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth; 6602 mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight; 6603 mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight, 6604 mAppDisplayWidth, mAppDisplayHeight); 6605 } 6606 mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY, 6607 mDisplay.getRawWidth(), mDisplay.getRawHeight(), 6608 mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight()); 6609 mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight); 6610 } 6611 6612 try { 6613 mActivityManager.updateConfiguration(null); 6614 } catch (RemoteException e) { 6615 } 6616 6617 synchronized (mWindowMap) { 6618 readForcedDisplaySizeLocked(); 6619 } 6620 } 6621 6622 public void systemReady() { 6623 mPolicy.systemReady(); 6624 } 6625 6626 private void sendScreenStatusToClients() { 6627 final ArrayList<WindowState> windows = mWindows; 6628 final int count = windows.size(); 6629 boolean on = mPowerManager.isScreenOn(); 6630 for (int i = count - 1; i >= 0; i--) { 6631 WindowState win = mWindows.get(i); 6632 try { 6633 win.mClient.dispatchScreenState(on); 6634 } catch (RemoteException e) { 6635 // Ignored 6636 } 6637 } 6638 } 6639 6640 // ------------------------------------------------------------- 6641 // Async Handler 6642 // ------------------------------------------------------------- 6643 6644 final class H extends Handler { 6645 public static final int REPORT_FOCUS_CHANGE = 2; 6646 public static final int REPORT_LOSING_FOCUS = 3; 6647 public static final int DO_TRAVERSAL = 4; 6648 public static final int ADD_STARTING = 5; 6649 public static final int REMOVE_STARTING = 6; 6650 public static final int FINISHED_STARTING = 7; 6651 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; 6652 public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9; 6653 public static final int WINDOW_FREEZE_TIMEOUT = 11; 6654 public static final int HOLD_SCREEN_CHANGED = 12; 6655 public static final int APP_TRANSITION_TIMEOUT = 13; 6656 public static final int PERSIST_ANIMATION_SCALE = 14; 6657 public static final int FORCE_GC = 15; 6658 public static final int ENABLE_SCREEN = 16; 6659 public static final int APP_FREEZE_TIMEOUT = 17; 6660 public static final int SEND_NEW_CONFIGURATION = 18; 6661 public static final int REPORT_WINDOWS_CHANGE = 19; 6662 public static final int DRAG_START_TIMEOUT = 20; 6663 public static final int DRAG_END_TIMEOUT = 21; 6664 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 6665 public static final int BOOT_TIMEOUT = 23; 6666 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 6667 public static final int BULK_UPDATE_PARAMETERS = 25; 6668 6669 public static final int ANIMATOR_WHAT_OFFSET = 100000; 6670 public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1; 6671 public static final int SET_WALLPAPER_OFFSET = ANIMATOR_WHAT_OFFSET + 2; 6672 public static final int SET_DIM_PARAMETERS = ANIMATOR_WHAT_OFFSET + 3; 6673 public static final int SET_MOVE_ANIMATION = ANIMATOR_WHAT_OFFSET + 4; 6674 public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 5; 6675 6676 private Session mLastReportedHold; 6677 6678 public H() { 6679 } 6680 6681 @Override 6682 public void handleMessage(Message msg) { 6683 if (DEBUG_WINDOW_TRACE) { 6684 Slog.v(TAG, "handleMessage: entry what=" + msg.what); 6685 } 6686 switch (msg.what) { 6687 case REPORT_FOCUS_CHANGE: { 6688 WindowState lastFocus; 6689 WindowState newFocus; 6690 6691 synchronized(mWindowMap) { 6692 lastFocus = mLastFocus; 6693 newFocus = mCurrentFocus; 6694 if (lastFocus == newFocus) { 6695 // Focus is not changing, so nothing to do. 6696 return; 6697 } 6698 mLastFocus = newFocus; 6699 //Slog.i(TAG, "Focus moving from " + lastFocus 6700 // + " to " + newFocus); 6701 if (newFocus != null && lastFocus != null 6702 && !newFocus.isDisplayedLw()) { 6703 //Slog.i(TAG, "Delaying loss of focus..."); 6704 mLosingFocus.add(lastFocus); 6705 lastFocus = null; 6706 } 6707 } 6708 6709 if (lastFocus != newFocus) { 6710 //System.out.println("Changing focus from " + lastFocus 6711 // + " to " + newFocus); 6712 if (newFocus != null) { 6713 try { 6714 //Slog.i(TAG, "Gaining focus: " + newFocus); 6715 newFocus.mClient.windowFocusChanged(true, mInTouchMode); 6716 } catch (RemoteException e) { 6717 // Ignore if process has died. 6718 } 6719 notifyFocusChanged(); 6720 } 6721 6722 if (lastFocus != null) { 6723 try { 6724 //Slog.i(TAG, "Losing focus: " + lastFocus); 6725 lastFocus.mClient.windowFocusChanged(false, mInTouchMode); 6726 } catch (RemoteException e) { 6727 // Ignore if process has died. 6728 } 6729 } 6730 } 6731 } break; 6732 6733 case REPORT_LOSING_FOCUS: { 6734 ArrayList<WindowState> losers; 6735 6736 synchronized(mWindowMap) { 6737 losers = mLosingFocus; 6738 mLosingFocus = new ArrayList<WindowState>(); 6739 } 6740 6741 final int N = losers.size(); 6742 for (int i=0; i<N; i++) { 6743 try { 6744 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i)); 6745 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode); 6746 } catch (RemoteException e) { 6747 // Ignore if process has died. 6748 } 6749 } 6750 } break; 6751 6752 case DO_TRAVERSAL: { 6753 synchronized(mWindowMap) { 6754 mTraversalScheduled = false; 6755 performLayoutAndPlaceSurfacesLocked(); 6756 } 6757 } break; 6758 6759 case ADD_STARTING: { 6760 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6761 final StartingData sd = wtoken.startingData; 6762 6763 if (sd == null) { 6764 // Animation has been canceled... do nothing. 6765 return; 6766 } 6767 6768 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 6769 + wtoken + ": pkg=" + sd.pkg); 6770 6771 View view = null; 6772 try { 6773 view = mPolicy.addStartingWindow( 6774 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 6775 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags); 6776 } catch (Exception e) { 6777 Slog.w(TAG, "Exception when adding starting window", e); 6778 } 6779 6780 if (view != null) { 6781 boolean abort = false; 6782 6783 synchronized(mWindowMap) { 6784 if (wtoken.removed || wtoken.startingData == null) { 6785 // If the window was successfully added, then 6786 // we need to remove it. 6787 if (wtoken.startingWindow != null) { 6788 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 6789 "Aborted starting " + wtoken 6790 + ": removed=" + wtoken.removed 6791 + " startingData=" + wtoken.startingData); 6792 wtoken.startingWindow = null; 6793 wtoken.startingData = null; 6794 abort = true; 6795 } 6796 } else { 6797 wtoken.startingView = view; 6798 } 6799 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 6800 "Added starting " + wtoken 6801 + ": startingWindow=" 6802 + wtoken.startingWindow + " startingView=" 6803 + wtoken.startingView); 6804 } 6805 6806 if (abort) { 6807 try { 6808 mPolicy.removeStartingWindow(wtoken.token, view); 6809 } catch (Exception e) { 6810 Slog.w(TAG, "Exception when removing starting window", e); 6811 } 6812 } 6813 } 6814 } break; 6815 6816 case REMOVE_STARTING: { 6817 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6818 IBinder token = null; 6819 View view = null; 6820 synchronized (mWindowMap) { 6821 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 6822 + wtoken + ": startingWindow=" 6823 + wtoken.startingWindow + " startingView=" 6824 + wtoken.startingView); 6825 if (wtoken.startingWindow != null) { 6826 view = wtoken.startingView; 6827 token = wtoken.token; 6828 wtoken.startingData = null; 6829 wtoken.startingView = null; 6830 wtoken.startingWindow = null; 6831 } 6832 } 6833 if (view != null) { 6834 try { 6835 mPolicy.removeStartingWindow(token, view); 6836 } catch (Exception e) { 6837 Slog.w(TAG, "Exception when removing starting window", e); 6838 } 6839 } 6840 } break; 6841 6842 case FINISHED_STARTING: { 6843 IBinder token = null; 6844 View view = null; 6845 while (true) { 6846 synchronized (mWindowMap) { 6847 final int N = mFinishedStarting.size(); 6848 if (N <= 0) { 6849 break; 6850 } 6851 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 6852 6853 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 6854 "Finished starting " + wtoken 6855 + ": startingWindow=" + wtoken.startingWindow 6856 + " startingView=" + wtoken.startingView); 6857 6858 if (wtoken.startingWindow == null) { 6859 continue; 6860 } 6861 6862 view = wtoken.startingView; 6863 token = wtoken.token; 6864 wtoken.startingData = null; 6865 wtoken.startingView = null; 6866 wtoken.startingWindow = null; 6867 } 6868 6869 try { 6870 mPolicy.removeStartingWindow(token, view); 6871 } catch (Exception e) { 6872 Slog.w(TAG, "Exception when removing starting window", e); 6873 } 6874 } 6875 } break; 6876 6877 case REPORT_APPLICATION_TOKEN_DRAWN: { 6878 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6879 6880 try { 6881 if (DEBUG_VISIBILITY) Slog.v( 6882 TAG, "Reporting drawn in " + wtoken); 6883 wtoken.appToken.windowsDrawn(); 6884 } catch (RemoteException ex) { 6885 } 6886 } break; 6887 6888 case REPORT_APPLICATION_TOKEN_WINDOWS: { 6889 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6890 6891 boolean nowVisible = msg.arg1 != 0; 6892 boolean nowGone = msg.arg2 != 0; 6893 6894 try { 6895 if (DEBUG_VISIBILITY) Slog.v( 6896 TAG, "Reporting visible in " + wtoken 6897 + " visible=" + nowVisible 6898 + " gone=" + nowGone); 6899 if (nowVisible) { 6900 wtoken.appToken.windowsVisible(); 6901 } else { 6902 wtoken.appToken.windowsGone(); 6903 } 6904 } catch (RemoteException ex) { 6905 } 6906 } break; 6907 6908 case WINDOW_FREEZE_TIMEOUT: { 6909 synchronized (mWindowMap) { 6910 Slog.w(TAG, "Window freeze timeout expired."); 6911 int i = mWindows.size(); 6912 while (i > 0) { 6913 i--; 6914 WindowState w = mWindows.get(i); 6915 if (w.mOrientationChanging) { 6916 w.mOrientationChanging = false; 6917 Slog.w(TAG, "Force clearing orientation change: " + w); 6918 } 6919 } 6920 performLayoutAndPlaceSurfacesLocked(); 6921 } 6922 break; 6923 } 6924 6925 case HOLD_SCREEN_CHANGED: { 6926 Session oldHold; 6927 Session newHold; 6928 synchronized (mWindowMap) { 6929 oldHold = mLastReportedHold; 6930 newHold = (Session)msg.obj; 6931 mLastReportedHold = newHold; 6932 } 6933 6934 if (oldHold != newHold) { 6935 try { 6936 if (oldHold != null) { 6937 mBatteryStats.noteStopWakelock(oldHold.mUid, -1, 6938 "window", 6939 BatteryStats.WAKE_TYPE_WINDOW); 6940 } 6941 if (newHold != null) { 6942 mBatteryStats.noteStartWakelock(newHold.mUid, -1, 6943 "window", 6944 BatteryStats.WAKE_TYPE_WINDOW); 6945 } 6946 } catch (RemoteException e) { 6947 } 6948 } 6949 break; 6950 } 6951 6952 case APP_TRANSITION_TIMEOUT: { 6953 synchronized (mWindowMap) { 6954 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 6955 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 6956 "*** APP TRANSITION TIMEOUT"); 6957 mAppTransitionReady = true; 6958 mAppTransitionTimeout = true; 6959 performLayoutAndPlaceSurfacesLocked(); 6960 } 6961 } 6962 break; 6963 } 6964 6965 case PERSIST_ANIMATION_SCALE: { 6966 Settings.System.putFloat(mContext.getContentResolver(), 6967 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 6968 Settings.System.putFloat(mContext.getContentResolver(), 6969 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 6970 Settings.System.putFloat(mContext.getContentResolver(), 6971 Settings.System.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale); 6972 break; 6973 } 6974 6975 case FORCE_GC: { 6976 synchronized(mWindowMap) { 6977 if (mAnimationScheduled) { 6978 // If we are animating, don't do the gc now but 6979 // delay a bit so we don't interrupt the animation. 6980 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 6981 2000); 6982 return; 6983 } 6984 // If we are currently rotating the display, it will 6985 // schedule a new message when done. 6986 if (mDisplayFrozen) { 6987 return; 6988 } 6989 } 6990 Runtime.getRuntime().gc(); 6991 break; 6992 } 6993 6994 case ENABLE_SCREEN: { 6995 performEnableScreen(); 6996 break; 6997 } 6998 6999 case APP_FREEZE_TIMEOUT: { 7000 synchronized (mWindowMap) { 7001 synchronized (mAnimator) { 7002 Slog.w(TAG, "App freeze timeout expired."); 7003 int i = mAppTokens.size(); 7004 while (i > 0) { 7005 i--; 7006 AppWindowToken tok = mAppTokens.get(i); 7007 if (tok.mAppAnimator.freezingScreen) { 7008 Slog.w(TAG, "Force clearing freeze: " + tok); 7009 unsetAppFreezingScreenLocked(tok, true, true); 7010 } 7011 } 7012 } 7013 } 7014 break; 7015 } 7016 7017 case SEND_NEW_CONFIGURATION: { 7018 removeMessages(SEND_NEW_CONFIGURATION); 7019 sendNewConfiguration(); 7020 break; 7021 } 7022 7023 case REPORT_WINDOWS_CHANGE: { 7024 if (mWindowsChanged) { 7025 synchronized (mWindowMap) { 7026 mWindowsChanged = false; 7027 } 7028 notifyWindowsChanged(); 7029 } 7030 break; 7031 } 7032 7033 case DRAG_START_TIMEOUT: { 7034 IBinder win = (IBinder)msg.obj; 7035 if (DEBUG_DRAG) { 7036 Slog.w(TAG, "Timeout starting drag by win " + win); 7037 } 7038 synchronized (mWindowMap) { 7039 // !!! TODO: ANR the app that has failed to start the drag in time 7040 if (mDragState != null) { 7041 mDragState.unregister(); 7042 mInputMonitor.updateInputWindowsLw(true /*force*/); 7043 mDragState.reset(); 7044 mDragState = null; 7045 } 7046 } 7047 break; 7048 } 7049 7050 case DRAG_END_TIMEOUT: { 7051 IBinder win = (IBinder)msg.obj; 7052 if (DEBUG_DRAG) { 7053 Slog.w(TAG, "Timeout ending drag to win " + win); 7054 } 7055 synchronized (mWindowMap) { 7056 // !!! TODO: ANR the drag-receiving app 7057 if (mDragState != null) { 7058 mDragState.mDragResult = false; 7059 mDragState.endDragLw(); 7060 } 7061 } 7062 break; 7063 } 7064 7065 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 7066 notifyHardKeyboardStatusChange(); 7067 break; 7068 } 7069 7070 case BOOT_TIMEOUT: { 7071 performBootTimeout(); 7072 break; 7073 } 7074 7075 case WAITING_FOR_DRAWN_TIMEOUT: { 7076 Pair<WindowState, IRemoteCallback> pair; 7077 synchronized (mWindowMap) { 7078 pair = (Pair<WindowState, IRemoteCallback>)msg.obj; 7079 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first); 7080 if (!mWaitingForDrawn.remove(pair)) { 7081 return; 7082 } 7083 } 7084 try { 7085 pair.second.sendResult(null); 7086 } catch (RemoteException e) { 7087 } 7088 break; 7089 } 7090 7091 case BULK_UPDATE_PARAMETERS: { 7092 // Used to send multiple changes from the animation side to the layout side. 7093 synchronized (mWindowMap) { 7094 boolean doRequest = false; 7095 // TODO(cmautner): As the number of bits grows, use masks of bit groups to 7096 // eliminate unnecessary tests. 7097 if ((msg.arg1 & LayoutFields.SET_UPDATE_ROTATION) != 0) { 7098 mInnerFields.mUpdateRotation = true; 7099 doRequest = true; 7100 } 7101 if ((msg.arg1 & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { 7102 mInnerFields.mWallpaperMayChange = true; 7103 doRequest = true; 7104 } 7105 if ((msg.arg1 & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { 7106 mInnerFields.mWallpaperForceHidingChanged = true; 7107 doRequest = true; 7108 } 7109 if ((msg.arg1 & LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE) != 0) { 7110 mInnerFields.mOrientationChangeComplete = false; 7111 } else { 7112 mInnerFields.mOrientationChangeComplete = true; 7113 if (mWindowsFreezingScreen) { 7114 doRequest = true; 7115 } 7116 } 7117 if ((msg.arg1 & LayoutFields.SET_TURN_ON_SCREEN) != 0) { 7118 mTurnOnScreen = true; 7119 } 7120 7121 mPendingLayoutChanges |= msg.arg2; 7122 if (mPendingLayoutChanges != 0) { 7123 doRequest = true; 7124 } 7125 7126 if (doRequest) { 7127 mH.sendEmptyMessage(CLEAR_PENDING_ACTIONS); 7128 performLayoutAndPlaceSurfacesLocked(); 7129 } 7130 } 7131 break; 7132 } 7133 7134 // Animation messages. Move to Window{State}Animator 7135 case SET_TRANSPARENT_REGION: { 7136 Pair<WindowStateAnimator, Region> pair = 7137 (Pair<WindowStateAnimator, Region>) msg.obj; 7138 final WindowStateAnimator winAnimator = pair.first; 7139 winAnimator.setTransparentRegionHint(pair.second); 7140 break; 7141 } 7142 7143 case SET_WALLPAPER_OFFSET: { 7144 final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj; 7145 winAnimator.setWallpaperOffset(msg.arg1, msg.arg2); 7146 7147 scheduleAnimationLocked(); 7148 break; 7149 } 7150 7151 case SET_DIM_PARAMETERS: { 7152 mAnimator.mDimParams = (DimAnimator.Parameters) msg.obj; 7153 7154 scheduleAnimationLocked(); 7155 break; 7156 } 7157 7158 case SET_MOVE_ANIMATION: { 7159 WindowAnimator.SetAnimationParams params = 7160 (WindowAnimator.SetAnimationParams) msg.obj; 7161 WindowStateAnimator winAnimator = params.mWinAnimator; 7162 winAnimator.setAnimation(params.mAnimation); 7163 winAnimator.mAnimDw = params.mAnimDw; 7164 winAnimator.mAnimDh = params.mAnimDh; 7165 7166 scheduleAnimationLocked(); 7167 break; 7168 } 7169 7170 case CLEAR_PENDING_ACTIONS: { 7171 mAnimator.clearPendingActions(); 7172 break; 7173 } 7174 } 7175 if (DEBUG_WINDOW_TRACE) { 7176 Slog.v(TAG, "handleMessage: exit"); 7177 } 7178 } 7179 } 7180 7181 // ------------------------------------------------------------- 7182 // IWindowManager API 7183 // ------------------------------------------------------------- 7184 7185 @Override 7186 public IWindowSession openSession(IInputMethodClient client, 7187 IInputContext inputContext) { 7188 if (client == null) throw new IllegalArgumentException("null client"); 7189 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 7190 Session session = new Session(this, client, inputContext); 7191 return session; 7192 } 7193 7194 @Override 7195 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 7196 synchronized (mWindowMap) { 7197 // The focus for the client is the window immediately below 7198 // where we would place the input method window. 7199 int idx = findDesiredInputMethodWindowIndexLocked(false); 7200 WindowState imFocus; 7201 if (idx > 0) { 7202 imFocus = mWindows.get(idx-1); 7203 //Log.i(TAG, "Desired input method target: " + imFocus); 7204 //Log.i(TAG, "Current focus: " + this.mCurrentFocus); 7205 //Log.i(TAG, "Last focus: " + this.mLastFocus); 7206 if (imFocus != null) { 7207 // This may be a starting window, in which case we still want 7208 // to count it as okay. 7209 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 7210 && imFocus.mAppToken != null) { 7211 // The client has definitely started, so it really should 7212 // have a window in this app token. Let's look for it. 7213 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 7214 WindowState w = imFocus.mAppToken.windows.get(i); 7215 if (w != imFocus) { 7216 //Log.i(TAG, "Switching to real app window: " + w); 7217 imFocus = w; 7218 break; 7219 } 7220 } 7221 } 7222 //Log.i(TAG, "IM target client: " + imFocus.mSession.mClient); 7223 //if (imFocus.mSession.mClient != null) { 7224 // Log.i(TAG, "IM target client binder: " + imFocus.mSession.mClient.asBinder()); 7225 // Log.i(TAG, "Requesting client binder: " + client.asBinder()); 7226 //} 7227 if (imFocus.mSession.mClient != null && 7228 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 7229 return true; 7230 } 7231 7232 // Okay, how about this... what is the current focus? 7233 // It seems in some cases we may not have moved the IM 7234 // target window, such as when it was in a pop-up window, 7235 // so let's also look at the current focus. (An example: 7236 // go to Gmail, start searching so the keyboard goes up, 7237 // press home. Sometimes the IME won't go down.) 7238 // Would be nice to fix this more correctly, but it's 7239 // way at the end of a release, and this should be good enough. 7240 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null && 7241 mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 7242 return true; 7243 } 7244 } 7245 } 7246 } 7247 return false; 7248 } 7249 7250 public void getDisplaySize(Point size) { 7251 synchronized(mDisplaySizeLock) { 7252 size.x = mAppDisplayWidth; 7253 size.y = mAppDisplayHeight; 7254 } 7255 } 7256 7257 public void getRealDisplaySize(Point size) { 7258 synchronized(mDisplaySizeLock) { 7259 size.x = mCurDisplayWidth; 7260 size.y = mCurDisplayHeight; 7261 } 7262 } 7263 7264 public void getInitialDisplaySize(Point size) { 7265 synchronized(mDisplaySizeLock) { 7266 size.x = mInitialDisplayWidth; 7267 size.y = mInitialDisplayHeight; 7268 } 7269 } 7270 7271 public int getMaximumSizeDimension() { 7272 synchronized(mDisplaySizeLock) { 7273 // Do this based on the raw screen size, until we are smarter. 7274 return mBaseDisplayWidth > mBaseDisplayHeight 7275 ? mBaseDisplayWidth : mBaseDisplayHeight; 7276 } 7277 } 7278 7279 public void getCurrentSizeRange(Point smallestSize, Point largestSize) { 7280 synchronized(mDisplaySizeLock) { 7281 smallestSize.x = mSmallestDisplayWidth; 7282 smallestSize.y = mSmallestDisplayHeight; 7283 largestSize.x = mLargestDisplayWidth; 7284 largestSize.y = mLargestDisplayHeight; 7285 } 7286 } 7287 7288 public void setForcedDisplaySize(int longDimen, int shortDimen) { 7289 synchronized(mWindowMap) { 7290 int width, height; 7291 if (mInitialDisplayWidth < mInitialDisplayHeight) { 7292 width = shortDimen < mInitialDisplayWidth 7293 ? shortDimen : mInitialDisplayWidth; 7294 height = longDimen < mInitialDisplayHeight 7295 ? longDimen : mInitialDisplayHeight; 7296 } else { 7297 width = longDimen < mInitialDisplayWidth 7298 ? longDimen : mInitialDisplayWidth; 7299 height = shortDimen < mInitialDisplayHeight 7300 ? shortDimen : mInitialDisplayHeight; 7301 } 7302 setForcedDisplaySizeLocked(width, height); 7303 Settings.Secure.putString(mContext.getContentResolver(), 7304 Settings.Secure.DISPLAY_SIZE_FORCED, width + "," + height); 7305 } 7306 } 7307 7308 private void rebuildBlackFrame() { 7309 if (mBlackFrame != null) { 7310 mBlackFrame.kill(); 7311 mBlackFrame = null; 7312 } 7313 if (mBaseDisplayWidth < mInitialDisplayWidth 7314 || mBaseDisplayHeight < mInitialDisplayHeight) { 7315 int initW, initH, baseW, baseH; 7316 final boolean rotated = (mRotation == Surface.ROTATION_90 7317 || mRotation == Surface.ROTATION_270); 7318 if (rotated) { 7319 initW = mInitialDisplayHeight; 7320 initH = mInitialDisplayWidth; 7321 baseW = mBaseDisplayHeight; 7322 baseH = mBaseDisplayWidth; 7323 } else { 7324 initW = mInitialDisplayWidth; 7325 initH = mInitialDisplayHeight; 7326 baseW = mBaseDisplayWidth; 7327 baseH = mBaseDisplayHeight; 7328 } 7329 Rect outer = new Rect(0, 0, initW, initH); 7330 Rect inner = new Rect(0, 0, baseW, baseH); 7331 try { 7332 mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER); 7333 } catch (Surface.OutOfResourcesException e) { 7334 } 7335 } 7336 } 7337 7338 private void readForcedDisplaySizeLocked() { 7339 final String str = Settings.Secure.getString(mContext.getContentResolver(), 7340 Settings.Secure.DISPLAY_SIZE_FORCED); 7341 if (str == null || str.length() == 0) { 7342 return; 7343 } 7344 final int pos = str.indexOf(','); 7345 if (pos <= 0 || str.lastIndexOf(',') != pos) { 7346 return; 7347 } 7348 int width, height; 7349 try { 7350 width = Integer.parseInt(str.substring(0, pos)); 7351 height = Integer.parseInt(str.substring(pos+1)); 7352 } catch (NumberFormatException ex) { 7353 return; 7354 } 7355 setForcedDisplaySizeLocked(width, height); 7356 } 7357 7358 private void setForcedDisplaySizeLocked(int width, int height) { 7359 Slog.i(TAG, "Using new display size: " + width + "x" + height); 7360 7361 synchronized(mDisplaySizeLock) { 7362 mBaseDisplayWidth = width; 7363 mBaseDisplayHeight = height; 7364 } 7365 mPolicy.setInitialDisplaySize(mDisplay, mBaseDisplayWidth, mBaseDisplayHeight); 7366 7367 mLayoutNeeded = true; 7368 7369 boolean configChanged = updateOrientationFromAppTokensLocked(false); 7370 mTempConfiguration.setToDefaults(); 7371 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 7372 if (computeScreenConfigurationLocked(mTempConfiguration)) { 7373 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 7374 configChanged = true; 7375 } 7376 } 7377 7378 if (configChanged) { 7379 mWaitingForConfig = true; 7380 startFreezingDisplayLocked(false); 7381 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7382 } 7383 7384 rebuildBlackFrame(); 7385 7386 performLayoutAndPlaceSurfacesLocked(); 7387 } 7388 7389 public void clearForcedDisplaySize() { 7390 synchronized(mWindowMap) { 7391 setForcedDisplaySizeLocked(mInitialDisplayWidth, mInitialDisplayHeight); 7392 Settings.Secure.putString(mContext.getContentResolver(), 7393 Settings.Secure.DISPLAY_SIZE_FORCED, ""); 7394 } 7395 } 7396 7397 public boolean hasSystemNavBar() { 7398 return mPolicy.hasSystemNavBar(); 7399 } 7400 7401 // ------------------------------------------------------------- 7402 // Internals 7403 // ------------------------------------------------------------- 7404 7405 final WindowState windowForClientLocked(Session session, IWindow client, 7406 boolean throwOnError) { 7407 return windowForClientLocked(session, client.asBinder(), throwOnError); 7408 } 7409 7410 final WindowState windowForClientLocked(Session session, IBinder client, 7411 boolean throwOnError) { 7412 WindowState win = mWindowMap.get(client); 7413 if (localLOGV) Slog.v( 7414 TAG, "Looking up client " + client + ": " + win); 7415 if (win == null) { 7416 RuntimeException ex = new IllegalArgumentException( 7417 "Requested window " + client + " does not exist"); 7418 if (throwOnError) { 7419 throw ex; 7420 } 7421 Slog.w(TAG, "Failed looking up window", ex); 7422 return null; 7423 } 7424 if (session != null && win.mSession != session) { 7425 RuntimeException ex = new IllegalArgumentException( 7426 "Requested window " + client + " is in session " + 7427 win.mSession + ", not " + session); 7428 if (throwOnError) { 7429 throw ex; 7430 } 7431 Slog.w(TAG, "Failed looking up window", ex); 7432 return null; 7433 } 7434 7435 return win; 7436 } 7437 7438 final void rebuildAppWindowListLocked() { 7439 int NW = mWindows.size(); 7440 int i; 7441 int lastWallpaper = -1; 7442 int numRemoved = 0; 7443 7444 if (mRebuildTmp.length < NW) { 7445 mRebuildTmp = new WindowState[NW+10]; 7446 } 7447 7448 // First remove all existing app windows. 7449 i=0; 7450 while (i < NW) { 7451 WindowState w = mWindows.get(i); 7452 if (w.mAppToken != null) { 7453 WindowState win = mWindows.remove(i); 7454 win.mRebuilding = true; 7455 mRebuildTmp[numRemoved] = win; 7456 mWindowsChanged = true; 7457 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 7458 "Rebuild removing window: " + win); 7459 NW--; 7460 numRemoved++; 7461 continue; 7462 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER 7463 && lastWallpaper == i-1) { 7464 lastWallpaper = i; 7465 } 7466 i++; 7467 } 7468 7469 // The wallpaper window(s) typically live at the bottom of the stack, 7470 // so skip them before adding app tokens. 7471 lastWallpaper++; 7472 i = lastWallpaper; 7473 7474 // First add all of the exiting app tokens... these are no longer 7475 // in the main app list, but still have windows shown. We put them 7476 // in the back because now that the animation is over we no longer 7477 // will care about them. 7478 int NT = mExitingAppTokens.size(); 7479 for (int j=0; j<NT; j++) { 7480 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j)); 7481 } 7482 7483 // And add in the still active app tokens in Z order. 7484 NT = mAppTokens.size(); 7485 for (int j=0; j<NT; j++) { 7486 i = reAddAppWindowsLocked(i, mAppTokens.get(j)); 7487 } 7488 7489 i -= lastWallpaper; 7490 if (i != numRemoved) { 7491 Slog.w(TAG, "Rebuild removed " + numRemoved 7492 + " windows but added " + i); 7493 for (i=0; i<numRemoved; i++) { 7494 WindowState ws = mRebuildTmp[i]; 7495 if (ws.mRebuilding) { 7496 StringWriter sw = new StringWriter(); 7497 PrintWriter pw = new PrintWriter(sw); 7498 ws.dump(pw, "", true); 7499 pw.flush(); 7500 Slog.w(TAG, "This window was lost: " + ws); 7501 Slog.w(TAG, sw.toString()); 7502 ws.mWinAnimator.destroySurfaceLocked(); 7503 } 7504 } 7505 Slog.w(TAG, "Current app token list:"); 7506 dumpAppTokensLocked(); 7507 Slog.w(TAG, "Final window list:"); 7508 dumpWindowsLocked(); 7509 } 7510 } 7511 7512 private final void assignLayersLocked() { 7513 int N = mWindows.size(); 7514 int curBaseLayer = 0; 7515 int curLayer = 0; 7516 int i; 7517 7518 if (DEBUG_LAYERS) { 7519 RuntimeException here = new RuntimeException("here"); 7520 here.fillInStackTrace(); 7521 Slog.v(TAG, "Assigning layers", here); 7522 } 7523 7524 for (i=0; i<N; i++) { 7525 WindowState w = mWindows.get(i); 7526 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 7527 || (i > 0 && w.mIsWallpaper)) { 7528 curLayer += WINDOW_LAYER_MULTIPLIER; 7529 w.mLayer = curLayer; 7530 } else { 7531 curBaseLayer = curLayer = w.mBaseLayer; 7532 w.mLayer = curLayer; 7533 } 7534 if (w.mTargetAppToken != null) { 7535 w.mWinAnimator.mAnimLayer = 7536 w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment; 7537 } else if (w.mAppToken != null) { 7538 w.mWinAnimator.mAnimLayer = 7539 w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment; 7540 } else { 7541 w.mWinAnimator.mAnimLayer = w.mLayer; 7542 } 7543 if (w.mIsImWindow) { 7544 w.mWinAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment; 7545 } else if (w.mIsWallpaper) { 7546 w.mWinAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment; 7547 } 7548 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 7549 + w.mWinAnimator.mAnimLayer); 7550 //System.out.println( 7551 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 7552 } 7553 } 7554 7555 private boolean mInLayout = false; 7556 private final void performLayoutAndPlaceSurfacesLocked() { 7557 if (mInLayout) { 7558 if (DEBUG) { 7559 throw new RuntimeException("Recursive call!"); 7560 } 7561 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout"); 7562 return; 7563 } 7564 7565 if (mWaitingForConfig) { 7566 // Our configuration has changed (most likely rotation), but we 7567 // don't yet have the complete configuration to report to 7568 // applications. Don't do any window layout until we have it. 7569 return; 7570 } 7571 7572 if (mDisplay == null) { 7573 // Not yet initialized, nothing to do. 7574 return; 7575 } 7576 7577 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 7578 mInLayout = true; 7579 boolean recoveringMemory = false; 7580 7581 try { 7582 if (mForceRemoves != null) { 7583 recoveringMemory = true; 7584 // Wait a little bit for things to settle down, and off we go. 7585 for (int i=0; i<mForceRemoves.size(); i++) { 7586 WindowState ws = mForceRemoves.get(i); 7587 Slog.i(TAG, "Force removing: " + ws); 7588 removeWindowInnerLocked(ws.mSession, ws); 7589 } 7590 mForceRemoves = null; 7591 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 7592 Object tmp = new Object(); 7593 synchronized (tmp) { 7594 try { 7595 tmp.wait(250); 7596 } catch (InterruptedException e) { 7597 } 7598 } 7599 } 7600 } catch (RuntimeException e) { 7601 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 7602 } 7603 7604 try { 7605 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 7606 7607 final int N = mPendingRemove.size(); 7608 if (N > 0) { 7609 if (mPendingRemoveTmp.length < N) { 7610 mPendingRemoveTmp = new WindowState[N+10]; 7611 } 7612 mPendingRemove.toArray(mPendingRemoveTmp); 7613 mPendingRemove.clear(); 7614 for (int i=0; i<N; i++) { 7615 WindowState w = mPendingRemoveTmp[i]; 7616 removeWindowInnerLocked(w.mSession, w); 7617 } 7618 7619 mInLayout = false; 7620 assignLayersLocked(); 7621 mLayoutNeeded = true; 7622 // XXX this recursion seems broken! 7623 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 7624 performLayoutAndPlaceSurfacesLocked(); 7625 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); 7626 7627 } else { 7628 mInLayout = false; 7629 } 7630 7631 if (mLayoutNeeded) { 7632 if (++mLayoutRepeatCount < 6) { 7633 requestTraversalLocked(); 7634 } else { 7635 Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); 7636 mLayoutRepeatCount = 0; 7637 } 7638 } else { 7639 mLayoutRepeatCount = 0; 7640 } 7641 7642 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 7643 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 7644 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE)); 7645 } 7646 } catch (RuntimeException e) { 7647 mInLayout = false; 7648 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 7649 } 7650 7651 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 7652 } 7653 7654 private final void performLayoutLockedInner(boolean initial, boolean updateInputWindows) { 7655 if (!mLayoutNeeded) { 7656 return; 7657 } 7658 7659 mLayoutNeeded = false; 7660 7661 final int dw = mCurDisplayWidth; 7662 final int dh = mCurDisplayHeight; 7663 7664 final int NFW = mFakeWindows.size(); 7665 for (int i=0; i<NFW; i++) { 7666 mFakeWindows.get(i).layout(dw, dh); 7667 } 7668 7669 final int N = mWindows.size(); 7670 int i; 7671 7672 if (DEBUG_LAYOUT) { 7673 Slog.v(TAG, "-------------------------------------"); 7674 Slog.v(TAG, "performLayout: needed=" 7675 + mLayoutNeeded + " dw=" + dw + " dh=" + dh); 7676 } 7677 7678 mPolicy.beginLayoutLw(dw, dh, mRotation); 7679 7680 int seq = mLayoutSeq+1; 7681 if (seq < 0) seq = 0; 7682 mLayoutSeq = seq; 7683 7684 // First perform layout of any root windows (not attached 7685 // to another window). 7686 int topAttached = -1; 7687 for (i = N-1; i >= 0; i--) { 7688 final WindowState win = mWindows.get(i); 7689 7690 // Don't do layout of a window if it is not visible, or 7691 // soon won't be visible, to avoid wasting time and funky 7692 // changes while a window is animating away. 7693 final boolean gone = win.isGoneForLayoutLw(); 7694 7695 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 7696 Slog.v(TAG, "1ST PASS " + win 7697 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 7698 + " mLayoutAttached=" + win.mLayoutAttached); 7699 final AppWindowToken atoken = win.mAppToken; 7700 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" 7701 + win.mViewVisibility + " mRelayoutCalled=" 7702 + win.mRelayoutCalled + " hidden=" 7703 + win.mRootToken.hidden + " hiddenRequested=" 7704 + (atoken != null && atoken.hiddenRequested) 7705 + " mAttachedHidden=" + win.mAttachedHidden); 7706 else Slog.v(TAG, " VIS: mViewVisibility=" 7707 + win.mViewVisibility + " mRelayoutCalled=" 7708 + win.mRelayoutCalled + " hidden=" 7709 + win.mRootToken.hidden + " hiddenRequested=" 7710 + (atoken != null && atoken.hiddenRequested) 7711 + " mAttachedHidden=" + win.mAttachedHidden); 7712 } 7713 7714 // If this view is GONE, then skip it -- keep the current 7715 // frame, and let the caller know so they can ignore it 7716 // if they want. (We do the normal layout for INVISIBLE 7717 // windows, since that means "perform layout as normal, 7718 // just don't display"). 7719 if (!gone || !win.mHaveFrame || win.mLayoutNeeded) { 7720 if (!win.mLayoutAttached) { 7721 if (initial) { 7722 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7723 win.mContentChanged = false; 7724 } 7725 win.mLayoutNeeded = false; 7726 win.prelayout(); 7727 mPolicy.layoutWindowLw(win, win.mAttrs, null); 7728 win.mLayoutSeq = seq; 7729 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7730 + win.mFrame + " mContainingFrame=" 7731 + win.mContainingFrame + " mDisplayFrame=" 7732 + win.mDisplayFrame); 7733 } else { 7734 if (topAttached < 0) topAttached = i; 7735 } 7736 } 7737 } 7738 7739 // Now perform layout of attached windows, which usually 7740 // depend on the position of the window they are attached to. 7741 // XXX does not deal with windows that are attached to windows 7742 // that are themselves attached. 7743 for (i = topAttached; i >= 0; i--) { 7744 final WindowState win = mWindows.get(i); 7745 7746 if (win.mLayoutAttached) { 7747 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win 7748 + " mHaveFrame=" + win.mHaveFrame 7749 + " mViewVisibility=" + win.mViewVisibility 7750 + " mRelayoutCalled=" + win.mRelayoutCalled); 7751 // If this view is GONE, then skip it -- keep the current 7752 // frame, and let the caller know so they can ignore it 7753 // if they want. (We do the normal layout for INVISIBLE 7754 // windows, since that means "perform layout as normal, 7755 // just don't display"). 7756 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 7757 || !win.mHaveFrame || win.mLayoutNeeded) { 7758 if (initial) { 7759 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7760 win.mContentChanged = false; 7761 } 7762 win.mLayoutNeeded = false; 7763 win.prelayout(); 7764 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 7765 win.mLayoutSeq = seq; 7766 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" 7767 + win.mFrame + " mContainingFrame=" 7768 + win.mContainingFrame + " mDisplayFrame=" 7769 + win.mDisplayFrame); 7770 } 7771 } 7772 } 7773 7774 // Window frames may have changed. Tell the input dispatcher about it. 7775 mInputMonitor.setUpdateInputWindowsNeededLw(); 7776 if (updateInputWindows) { 7777 mInputMonitor.updateInputWindowsLw(false /*force*/); 7778 } 7779 7780 mPolicy.finishLayoutLw(); 7781 } 7782 7783 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 7784 // If the screen is currently frozen or off, then keep 7785 // it frozen/off until this window draws at its new 7786 // orientation. 7787 if (!okToDisplay()) { 7788 if (DEBUG_ORIENTATION) Slog.v(TAG, 7789 "Changing surface while display frozen: " + w); 7790 w.mOrientationChanging = true; 7791 mInnerFields.mOrientationChangeComplete = false; 7792 if (!mWindowsFreezingScreen) { 7793 mWindowsFreezingScreen = true; 7794 // XXX should probably keep timeout from 7795 // when we first froze the display. 7796 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 7797 mH.sendMessageDelayed(mH.obtainMessage( 7798 H.WINDOW_FREEZE_TIMEOUT), 2000); 7799 } 7800 } 7801 } 7802 7803 /** 7804 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 7805 * 7806 * @return bitmap indicating if another pass through layout must be made. 7807 */ 7808 public int handleAppTransitionReadyLocked() { 7809 int changes = 0; 7810 int i; 7811 int NN = mOpeningApps.size(); 7812 boolean goodToGo = true; 7813 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7814 "Checking " + NN + " opening apps (frozen=" 7815 + mDisplayFrozen + " timeout=" 7816 + mAppTransitionTimeout + ")..."); 7817 if (!mDisplayFrozen && !mAppTransitionTimeout) { 7818 // If the display isn't frozen, wait to do anything until 7819 // all of the apps are ready. Otherwise just go because 7820 // we'll unfreeze the display when everyone is ready. 7821 for (i=0; i<NN && goodToGo; i++) { 7822 AppWindowToken wtoken = mOpeningApps.get(i); 7823 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7824 "Check opening app" + wtoken + ": allDrawn=" 7825 + wtoken.allDrawn + " startingDisplayed=" 7826 + wtoken.startingDisplayed + " startingMoved=" 7827 + wtoken.startingMoved); 7828 if (!wtoken.allDrawn && !wtoken.startingDisplayed 7829 && !wtoken.startingMoved) { 7830 goodToGo = false; 7831 } 7832 } 7833 } 7834 if (goodToGo) { 7835 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 7836 int transit = mNextAppTransition; 7837 if (mSkipAppTransitionAnimation) { 7838 transit = WindowManagerPolicy.TRANSIT_UNSET; 7839 } 7840 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 7841 mAppTransitionReady = false; 7842 mAppTransitionRunning = true; 7843 mAppTransitionTimeout = false; 7844 mStartingIconInTransition = false; 7845 mSkipAppTransitionAnimation = false; 7846 7847 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 7848 7849 // If there are applications waiting to come to the 7850 // top of the stack, now is the time to move their windows. 7851 // (Note that we don't do apps going to the bottom 7852 // here -- we want to keep their windows in the old 7853 // Z-order until the animation completes.) 7854 if (mToTopApps.size() > 0) { 7855 NN = mAppTokens.size(); 7856 for (i=0; i<NN; i++) { 7857 AppWindowToken wtoken = mAppTokens.get(i); 7858 if (wtoken.sendingToTop) { 7859 wtoken.sendingToTop = false; 7860 moveAppWindowsLocked(wtoken, NN, false); 7861 } 7862 } 7863 mToTopApps.clear(); 7864 } 7865 7866 WindowState oldWallpaper = 7867 mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating() 7868 ? null : mWallpaperTarget; 7869 7870 adjustWallpaperWindowsLocked(); 7871 mInnerFields.mWallpaperMayChange = false; 7872 7873 // The top-most window will supply the layout params, 7874 // and we will determine it below. 7875 LayoutParams animLp = null; 7876 int bestAnimLayer = -1; 7877 boolean fullscreenAnim = false; 7878 7879 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7880 "New wallpaper target=" + mWallpaperTarget 7881 + ", lower target=" + mLowerWallpaperTarget 7882 + ", upper target=" + mUpperWallpaperTarget); 7883 int foundWallpapers = 0; 7884 // Do a first pass through the tokens for two 7885 // things: 7886 // (1) Determine if both the closing and opening 7887 // app token sets are wallpaper targets, in which 7888 // case special animations are needed 7889 // (since the wallpaper needs to stay static 7890 // behind them). 7891 // (2) Find the layout params of the top-most 7892 // application window in the tokens, which is 7893 // what will control the animation theme. 7894 final int NC = mClosingApps.size(); 7895 NN = NC + mOpeningApps.size(); 7896 for (i=0; i<NN; i++) { 7897 AppWindowToken wtoken; 7898 int mode; 7899 if (i < NC) { 7900 wtoken = mClosingApps.get(i); 7901 mode = 1; 7902 } else { 7903 wtoken = mOpeningApps.get(i-NC); 7904 mode = 2; 7905 } 7906 if (mLowerWallpaperTarget != null) { 7907 if (mLowerWallpaperTarget.mAppToken == wtoken 7908 || mUpperWallpaperTarget.mAppToken == wtoken) { 7909 foundWallpapers |= mode; 7910 } 7911 } 7912 if (wtoken.appFullscreen) { 7913 WindowState ws = wtoken.findMainWindow(); 7914 if (ws != null) { 7915 animLp = ws.mAttrs; 7916 bestAnimLayer = ws.mLayer; 7917 fullscreenAnim = true; 7918 } 7919 } else if (!fullscreenAnim) { 7920 WindowState ws = wtoken.findMainWindow(); 7921 if (ws != null) { 7922 if (ws.mLayer > bestAnimLayer) { 7923 animLp = ws.mAttrs; 7924 bestAnimLayer = ws.mLayer; 7925 } 7926 } 7927 } 7928 } 7929 7930 if (foundWallpapers == 3) { 7931 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7932 "Wallpaper animation!"); 7933 switch (transit) { 7934 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 7935 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 7936 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 7937 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN; 7938 break; 7939 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 7940 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 7941 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 7942 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE; 7943 break; 7944 } 7945 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7946 "New transit: " + transit); 7947 } else if (oldWallpaper != null) { 7948 // We are transitioning from an activity with 7949 // a wallpaper to one without. 7950 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE; 7951 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7952 "New transit away from wallpaper: " + transit); 7953 } else if (mWallpaperTarget != null) { 7954 // We are transitioning from an activity without 7955 // a wallpaper to now showing the wallpaper 7956 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN; 7957 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7958 "New transit into wallpaper: " + transit); 7959 } 7960 7961 // If all closing windows are obscured, then there is 7962 // no need to do an animation. This is the case, for 7963 // example, when this transition is being done behind 7964 // the lock screen. 7965 if (!mPolicy.allowAppAnimationsLw()) { 7966 animLp = null; 7967 } 7968 7969 AppWindowToken topOpeningApp = null; 7970 int topOpeningLayer = 0; 7971 7972 // TODO(cmautner): Move to animation side. 7973 NN = mOpeningApps.size(); 7974 for (i=0; i<NN; i++) { 7975 AppWindowToken wtoken = mOpeningApps.get(i); 7976 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); 7977 wtoken.mAppAnimator.clearThumbnail(); 7978 wtoken.reportedVisible = false; 7979 wtoken.inPendingTransaction = false; 7980 wtoken.mAppAnimator.animation = null; 7981 setTokenVisibilityLocked(wtoken, animLp, true, transit, false); 7982 wtoken.updateReportedVisibilityLocked(); 7983 wtoken.waitingToShow = false; 7984 mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked(); 7985 if (animLp != null) { 7986 int layer = -1; 7987 for (int j=0; j<wtoken.windows.size(); j++) { 7988 WindowState win = wtoken.windows.get(j); 7989 if (win.mWinAnimator.mAnimLayer > layer) { 7990 layer = win.mWinAnimator.mAnimLayer; 7991 } 7992 } 7993 if (topOpeningApp == null || layer > topOpeningLayer) { 7994 topOpeningApp = wtoken; 7995 topOpeningLayer = layer; 7996 } 7997 } 7998 } 7999 NN = mClosingApps.size(); 8000 for (i=0; i<NN; i++) { 8001 AppWindowToken wtoken = mClosingApps.get(i); 8002 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 8003 "Now closing app" + wtoken); 8004 wtoken.mAppAnimator.clearThumbnail(); 8005 wtoken.inPendingTransaction = false; 8006 wtoken.mAppAnimator.animation = null; 8007 setTokenVisibilityLocked(wtoken, animLp, false, 8008 transit, false); 8009 wtoken.updateReportedVisibilityLocked(); 8010 wtoken.waitingToHide = false; 8011 // Force the allDrawn flag, because we want to start 8012 // this guy's animations regardless of whether it's 8013 // gotten drawn. 8014 wtoken.allDrawn = true; 8015 } 8016 8017 if (mNextAppTransitionThumbnail != null && topOpeningApp != null 8018 && topOpeningApp.mAppAnimator.animation != null) { 8019 // This thumbnail animation is very special, we need to have 8020 // an extra surface with the thumbnail included with the animation. 8021 Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(), 8022 mNextAppTransitionThumbnail.getHeight()); 8023 try { 8024 Surface surface = new Surface(mFxSession, Process.myPid(), 8025 "thumbnail anim", 0, dirty.width(), dirty.height(), 8026 PixelFormat.TRANSLUCENT, Surface.HIDDEN); 8027 topOpeningApp.mAppAnimator.thumbnail = surface; 8028 if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " 8029 + surface + ": CREATE"); 8030 Surface drawSurface = new Surface(); 8031 drawSurface.copyFrom(surface); 8032 Canvas c = drawSurface.lockCanvas(dirty); 8033 c.drawBitmap(mNextAppTransitionThumbnail, 0, 0, null); 8034 drawSurface.unlockCanvasAndPost(c); 8035 drawSurface.release(); 8036 topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer; 8037 Animation anim = createThumbnailAnimationLocked(transit, true, true); 8038 topOpeningApp.mAppAnimator.thumbnailAnimation = anim; 8039 anim.restrictDuration(MAX_ANIMATION_DURATION); 8040 anim.scaleCurrentDuration(mTransitionAnimationScale); 8041 topOpeningApp.mAppAnimator.thumbnailX = mNextAppTransitionStartX; 8042 topOpeningApp.mAppAnimator.thumbnailY = mNextAppTransitionStartY; 8043 } catch (Surface.OutOfResourcesException e) { 8044 Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width() 8045 + " h=" + dirty.height(), e); 8046 topOpeningApp.mAppAnimator.clearThumbnail(); 8047 } 8048 } 8049 8050 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 8051 mNextAppTransitionPackage = null; 8052 mNextAppTransitionThumbnail = null; 8053 if (mNextAppTransitionCallback != null) { 8054 try { 8055 mNextAppTransitionCallback.sendResult(null); 8056 } catch (RemoteException e) { 8057 } 8058 } 8059 8060 mOpeningApps.clear(); 8061 mClosingApps.clear(); 8062 8063 // This has changed the visibility of windows, so perform 8064 // a new layout to get them all up-to-date. 8065 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT 8066 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 8067 mLayoutNeeded = true; 8068 if (!moveInputMethodWindowsIfNeededLocked(true)) { 8069 assignLayersLocked(); 8070 } 8071 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8072 false /*updateInputWindows*/); 8073 mFocusMayChange = false; 8074 } 8075 8076 return changes; 8077 } 8078 8079 /** 8080 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8081 * 8082 * @return bitmap indicating if another pass through layout must be made. 8083 */ 8084 private int handleAnimatingStoppedAndTransitionLocked() { 8085 int changes = 0; 8086 8087 mAppTransitionRunning = false; 8088 // Clear information about apps that were moving. 8089 mToBottomApps.clear(); 8090 8091 rebuildAppWindowListLocked(); 8092 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8093 mInnerFields.mAdjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED; 8094 moveInputMethodWindowsIfNeededLocked(false); 8095 mInnerFields.mWallpaperMayChange = true; 8096 // Since the window list has been rebuilt, focus might 8097 // have to be recomputed since the actual order of windows 8098 // might have changed again. 8099 mFocusMayChange = true; 8100 8101 return changes; 8102 } 8103 8104 /** 8105 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8106 * 8107 * @return bitmap indicating if another pass through layout must be made. 8108 */ 8109 private int animateAwayWallpaperLocked() { 8110 int changes = 0; 8111 WindowState oldWallpaper = mWallpaperTarget; 8112 if (mLowerWallpaperTarget != null 8113 && mLowerWallpaperTarget.mAppToken != null) { 8114 if (DEBUG_WALLPAPER) Slog.v(TAG, 8115 "wallpaperForceHiding changed with lower=" 8116 + mLowerWallpaperTarget); 8117 if (DEBUG_WALLPAPER) Slog.v(TAG, 8118 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden + 8119 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested); 8120 if (mLowerWallpaperTarget.mAppToken.hidden) { 8121 // The lower target has become hidden before we 8122 // actually started the animation... let's completely 8123 // re-evaluate everything. 8124 mLowerWallpaperTarget = mUpperWallpaperTarget = null; 8125 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8126 } 8127 } 8128 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 8129 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper 8130 + " NEW: " + mWallpaperTarget 8131 + " LOWER: " + mLowerWallpaperTarget); 8132 return changes; 8133 } 8134 8135 private void updateResizingWindows(final WindowState w) { 8136 final WindowStateAnimator winAnimator = w.mWinAnimator; 8137 if (w.mHasSurface && !w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) { 8138 w.mSystemInsetsChanged |= 8139 !w.mLastSystemInsets.equals(w.mSystemInsets); 8140 w.mContentInsetsChanged |= 8141 !w.mLastContentInsets.equals(w.mContentInsets); 8142 w.mVisibleInsetsChanged |= 8143 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 8144 boolean configChanged = 8145 w.mConfiguration != mCurConfiguration 8146 && (w.mConfiguration == null 8147 || mCurConfiguration.diff(w.mConfiguration) != 0); 8148 if (DEBUG_CONFIGURATION && configChanged) { 8149 Slog.v(TAG, "Win " + w + " config changed: " 8150 + mCurConfiguration); 8151 } 8152 if (localLOGV) Slog.v(TAG, "Resizing " + w 8153 + ": configChanged=" + configChanged 8154 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8155 w.mLastFrame.set(w.mFrame); 8156 if (w.mSystemInsetsChanged 8157 || w.mContentInsetsChanged 8158 || w.mVisibleInsetsChanged 8159 || winAnimator.mSurfaceResized 8160 || configChanged) { 8161 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8162 Slog.v(TAG, "Resize reasons: " 8163 + " contentInsetsChanged=" + w.mContentInsetsChanged 8164 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8165 + " surfaceResized=" + winAnimator.mSurfaceResized 8166 + " configChanged=" + configChanged); 8167 } 8168 8169 w.mLastSystemInsets.set(w.mSystemInsets); 8170 w.mLastContentInsets.set(w.mContentInsets); 8171 w.mLastVisibleInsets.set(w.mVisibleInsets); 8172 makeWindowFreezingScreenIfNeededLocked(w); 8173 // If the orientation is changing, then we need to 8174 // hold off on unfreezing the display until this 8175 // window has been redrawn; to do that, we need 8176 // to go through the process of getting informed 8177 // by the application when it has finished drawing. 8178 if (w.mOrientationChanging) { 8179 if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG, 8180 "Orientation start waiting for draw mDrawState=DRAW_PENDING in " 8181 + w + ", surface " + winAnimator.mSurface); 8182 winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; 8183 if (w.mAppToken != null) { 8184 w.mAppToken.allDrawn = false; 8185 } 8186 } 8187 if (!mResizingWindows.contains(w)) { 8188 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8189 "Resizing window " + w + " to " + winAnimator.mSurfaceW 8190 + "x" + winAnimator.mSurfaceH); 8191 mResizingWindows.add(w); 8192 } 8193 } else if (w.mOrientationChanging) { 8194 if (w.isDrawnLw()) { 8195 if (DEBUG_ORIENTATION) Slog.v(TAG, 8196 "Orientation not waiting for draw in " 8197 + w + ", surface " + winAnimator.mSurface); 8198 w.mOrientationChanging = false; 8199 } 8200 } 8201 } 8202 } 8203 8204 /** 8205 * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. 8206 * 8207 * @param w WindowState this method is applied to. 8208 * @param currentTime The time which animations use for calculating transitions. 8209 * @param innerDw Width of app window. 8210 * @param innerDh Height of app window. 8211 */ 8212 private void handleNotObscuredLocked(final WindowState w, final long currentTime, 8213 final int innerDw, final int innerDh) { 8214 final WindowManager.LayoutParams attrs = w.mAttrs; 8215 final int attrFlags = attrs.flags; 8216 final boolean canBeSeen = w.isDisplayedLw(); 8217 8218 if (w.mHasSurface) { 8219 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8220 mInnerFields.mHoldScreen = w.mSession; 8221 } 8222 if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0 8223 && mInnerFields.mScreenBrightness < 0) { 8224 mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness; 8225 } 8226 if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0 8227 && mInnerFields.mButtonBrightness < 0) { 8228 mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness; 8229 } 8230 if (canBeSeen 8231 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG 8232 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD 8233 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) { 8234 mInnerFields.mSyswin = true; 8235 } 8236 } 8237 8238 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8239 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8240 // This window completely covers everything behind it, 8241 // so we want to leave all of them as undimmed (for 8242 // performance reasons). 8243 mInnerFields.mObscured = true; 8244 } else if (canBeSeen && (attrFlags & FLAG_DIM_BEHIND) != 0 8245 && !(w.mAppToken != null && w.mAppToken.hiddenRequested)) { 8246 if (localLOGV) Slog.v(TAG, "Win " + w + " obscured=" + mInnerFields.mObscured); 8247 if (!mInnerFields.mDimming) { 8248 //Slog.i(TAG, "DIM BEHIND: " + w); 8249 mInnerFields.mDimming = true; 8250 if (!mAnimator.isDimming()) { 8251 final int width, height; 8252 if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { 8253 width = mCurDisplayWidth; 8254 height = mCurDisplayHeight; 8255 } else { 8256 width = innerDw; 8257 height = innerDh; 8258 } 8259 mAnimator.startDimming(w.mWinAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, 8260 width, height); 8261 } 8262 } 8263 } 8264 } 8265 8266 // "Something has changed! Let's make it correct now." 8267 private final void performLayoutAndPlaceSurfacesLockedInner( 8268 boolean recoveringMemory) { 8269 if (DEBUG_WINDOW_TRACE) { 8270 Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " 8271 + Debug.getCallers(3)); 8272 } 8273 if (mDisplay == null) { 8274 Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay"); 8275 return; 8276 } 8277 8278 final long currentTime = SystemClock.uptimeMillis(); 8279 final int dw = mCurDisplayWidth; 8280 final int dh = mCurDisplayHeight; 8281 final int innerDw = mAppDisplayWidth; 8282 final int innerDh = mAppDisplayHeight; 8283 8284 int i; 8285 8286 if (mFocusMayChange) { 8287 mFocusMayChange = false; 8288 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 8289 false /*updateInputWindows*/); 8290 } 8291 8292 // Initialize state of exiting tokens. 8293 for (i=mExitingTokens.size()-1; i>=0; i--) { 8294 mExitingTokens.get(i).hasVisible = false; 8295 } 8296 8297 // Initialize state of exiting applications. 8298 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8299 mExitingAppTokens.get(i).hasVisible = false; 8300 } 8301 8302 mInnerFields.mHoldScreen = null; 8303 mInnerFields.mScreenBrightness = -1; 8304 mInnerFields.mButtonBrightness = -1; 8305 8306 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8307 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 8308 8309 Surface.openTransaction(); 8310 8311 if (mWatermark != null) { 8312 mWatermark.positionSurface(dw, dh); 8313 } 8314 if (mStrictModeFlash != null) { 8315 mStrictModeFlash.positionSurface(dw, dh); 8316 } 8317 8318 try { 8319 int repeats = 0; 8320 8321 do { 8322 repeats++; 8323 if (repeats > 6) { 8324 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 8325 mLayoutNeeded = false; 8326 break; 8327 } 8328 8329 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", 8330 mPendingLayoutChanges); 8331 8332 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 8333 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8334 assignLayersLocked(); 8335 mLayoutNeeded = true; 8336 } 8337 } 8338 8339 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 8340 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 8341 if (updateOrientationFromAppTokensLocked(true)) { 8342 mLayoutNeeded = true; 8343 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8344 } 8345 } 8346 8347 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8348 mLayoutNeeded = true; 8349 } 8350 8351 // FIRST LOOP: Perform a layout, if needed. 8352 if (repeats < 4) { 8353 performLayoutLockedInner(repeats == 1, false /*updateInputWindows*/); 8354 } else { 8355 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 8356 } 8357 8358 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 8359 // it is animating. 8360 mPendingLayoutChanges = 0; 8361 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " + mLayoutRepeatCount, 8362 mPendingLayoutChanges); 8363 mPolicy.beginAnimationLw(dw, dh); 8364 for (i = mWindows.size() - 1; i >= 0; i--) { 8365 WindowState w = mWindows.get(i); 8366 if (w.mHasSurface) { 8367 mPolicy.animatingWindowLw(w, w.mAttrs); 8368 } 8369 } 8370 mPendingLayoutChanges |= mPolicy.finishAnimationLw(); 8371 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw", 8372 mPendingLayoutChanges); 8373 } while (mPendingLayoutChanges != 0); 8374 8375 final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); 8376 8377 mInnerFields.mObscured = false; 8378 mInnerFields.mDimming = false; 8379 mInnerFields.mSyswin = false; 8380 8381 boolean focusDisplayed = false; 8382 final int N = mWindows.size(); 8383 for (i=N-1; i>=0; i--) { 8384 WindowState w = mWindows.get(i); 8385 8386 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; 8387 8388 // Update effect. 8389 w.mObscured = mInnerFields.mObscured; 8390 if (!mInnerFields.mObscured) { 8391 handleNotObscuredLocked(w, currentTime, innerDw, innerDh); 8392 } 8393 8394 if (obscuredChanged && mWallpaperTarget == w) { 8395 // This is the wallpaper target and its obscured state 8396 // changed... make sure the current wallaper's visibility 8397 // has been updated accordingly. 8398 updateWallpaperVisibilityLocked(); 8399 } 8400 8401 final WindowStateAnimator winAnimator = w.mWinAnimator; 8402 8403 // If the window has moved due to its containing 8404 // content frame changing, then we'd like to animate 8405 // it. 8406 if (w.mHasSurface && w.shouldAnimateMove()) { 8407 // Frame has moved, containing content frame 8408 // has also moved, and we're not currently animating... 8409 // let's do something. 8410 Animation a = AnimationUtils.loadAnimation(mContext, 8411 com.android.internal.R.anim.window_move_from_decor); 8412 winAnimator.setAnimation(a); 8413 winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; 8414 winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; 8415 } else { 8416 winAnimator.mAnimDw = innerDw; 8417 winAnimator.mAnimDh = innerDh; 8418 } 8419 8420 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 8421 w.mContentChanged = false; 8422 8423 // Moved from updateWindowsAndWallpaperLocked(). 8424 if (w.mHasSurface) { 8425 // Take care of the window being ready to display. 8426 if (winAnimator.commitFinishDrawingLocked(currentTime)) { 8427 if ((w.mAttrs.flags 8428 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 8429 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 8430 "First draw done in potential wallpaper target " + w); 8431 mInnerFields.mWallpaperMayChange = true; 8432 mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 8433 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 8434 debugLayoutRepeats("updateWindowsAndWallpaperLocked 1", 8435 mPendingLayoutChanges); 8436 } 8437 } 8438 } 8439 8440 winAnimator.setSurfaceBoundaries(recoveringMemory); 8441 } 8442 8443 if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) { 8444 focusDisplayed = true; 8445 } 8446 8447 updateResizingWindows(w); 8448 } 8449 8450 if (focusDisplayed) { 8451 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 8452 } 8453 8454 if (!mInnerFields.mDimming && mAnimator.isDimming()) { 8455 mAnimator.stopDimming(); 8456 } 8457 } catch (RuntimeException e) { 8458 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 8459 } finally { 8460 Surface.closeTransaction(); 8461 } 8462 8463 // If we are ready to perform an app transition, check through 8464 // all of the app tokens to be shown and see if they are ready 8465 // to go. 8466 if (mAppTransitionReady) { 8467 mPendingLayoutChanges |= handleAppTransitionReadyLocked(); 8468 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", 8469 mPendingLayoutChanges); 8470 } 8471 8472 mInnerFields.mAdjResult = 0; 8473 8474 if (!mAnimator.mAnimating && mAppTransitionRunning) { 8475 // We have finished the animation of an app transition. To do 8476 // this, we have delayed a lot of operations like showing and 8477 // hiding apps, moving apps in Z-order, etc. The app token list 8478 // reflects the correct Z-order, but the window list may now 8479 // be out of sync with it. So here we will just rebuild the 8480 // entire app window list. Fun! 8481 mPendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); 8482 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", 8483 mPendingLayoutChanges); 8484 } 8485 8486 if (mInnerFields.mWallpaperForceHidingChanged && mPendingLayoutChanges == 0 && 8487 !mAppTransitionReady) { 8488 // At this point, there was a window with a wallpaper that 8489 // was force hiding other windows behind it, but now it 8490 // is going away. This may be simple -- just animate 8491 // away the wallpaper and its window -- or it may be 8492 // hard -- the wallpaper now needs to be shown behind 8493 // something that was hidden. 8494 mPendingLayoutChanges |= animateAwayWallpaperLocked(); 8495 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", 8496 mPendingLayoutChanges); 8497 } 8498 mInnerFields.mWallpaperForceHidingChanged = false; 8499 8500 if (mInnerFields.mWallpaperMayChange) { 8501 if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, 8502 "Wallpaper may change! Adjusting"); 8503 mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked(); 8504 } 8505 8506 if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8507 if (DEBUG_WALLPAPER) Slog.v(TAG, 8508 "Wallpaper layer changed: assigning layers + relayout"); 8509 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8510 assignLayersLocked(); 8511 } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { 8512 if (DEBUG_WALLPAPER) Slog.v(TAG, 8513 "Wallpaper visibility changed: relayout"); 8514 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8515 } 8516 8517 if (mFocusMayChange) { 8518 mFocusMayChange = false; 8519 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8520 false /*updateInputWindows*/)) { 8521 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8522 mInnerFields.mAdjResult = 0; 8523 } 8524 } 8525 8526 if (mLayoutNeeded) { 8527 mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8528 if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", mPendingLayoutChanges); 8529 } 8530 8531 if (!mResizingWindows.isEmpty()) { 8532 for (i = mResizingWindows.size() - 1; i >= 0; i--) { 8533 WindowState win = mResizingWindows.get(i); 8534 final WindowStateAnimator winAnimator = win.mWinAnimator; 8535 try { 8536 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8537 "Reporting new frame to " + win + ": " + win.mCompatFrame); 8538 int diff = 0; 8539 boolean configChanged = 8540 win.mConfiguration != mCurConfiguration 8541 && (win.mConfiguration == null 8542 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0); 8543 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 8544 && configChanged) { 8545 Slog.i(TAG, "Sending new config to window " + win + ": " 8546 + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH 8547 + " / " + mCurConfiguration + " / 0x" 8548 + Integer.toHexString(diff)); 8549 } 8550 win.mConfiguration = mCurConfiguration; 8551 if (DEBUG_ORIENTATION && 8552 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( 8553 TAG, "Resizing " + win + " WITH DRAW PENDING"); 8554 win.mClient.resized((int)winAnimator.mSurfaceW, 8555 (int)winAnimator.mSurfaceH, win.mLastSystemInsets, 8556 win.mLastContentInsets, win.mLastVisibleInsets, 8557 winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING, 8558 configChanged ? win.mConfiguration : null); 8559 win.mSystemInsetsChanged = false; 8560 win.mContentInsetsChanged = false; 8561 win.mVisibleInsetsChanged = false; 8562 winAnimator.mSurfaceResized = false; 8563 } catch (RemoteException e) { 8564 win.mOrientationChanging = false; 8565 } 8566 } 8567 mResizingWindows.clear(); 8568 } 8569 8570 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 8571 "With display frozen, orientationChangeComplete=" 8572 + mInnerFields.mOrientationChangeComplete); 8573 if (mInnerFields.mOrientationChangeComplete) { 8574 if (mWindowsFreezingScreen) { 8575 mWindowsFreezingScreen = false; 8576 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8577 } 8578 stopFreezingDisplayLocked(); 8579 } 8580 8581 // Destroy the surface of any windows that are no longer visible. 8582 boolean wallpaperDestroyed = false; 8583 i = mDestroySurface.size(); 8584 if (i > 0) { 8585 do { 8586 i--; 8587 WindowState win = mDestroySurface.get(i); 8588 win.mDestroying = false; 8589 if (mInputMethodWindow == win) { 8590 mInputMethodWindow = null; 8591 } 8592 if (win == mWallpaperTarget) { 8593 wallpaperDestroyed = true; 8594 } 8595 win.mWinAnimator.destroySurfaceLocked(); 8596 } while (i > 0); 8597 mDestroySurface.clear(); 8598 } 8599 8600 // Time to remove any exiting tokens? 8601 for (i=mExitingTokens.size()-1; i>=0; i--) { 8602 WindowToken token = mExitingTokens.get(i); 8603 if (!token.hasVisible) { 8604 mExitingTokens.remove(i); 8605 if (token.windowType == TYPE_WALLPAPER) { 8606 mWallpaperTokens.remove(token); 8607 } 8608 } 8609 } 8610 8611 // Time to remove any exiting applications? 8612 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8613 AppWindowToken token = mExitingAppTokens.get(i); 8614 if (!token.hasVisible && !mClosingApps.contains(token)) { 8615 // Make sure there is no animation running on this token, 8616 // so any windows associated with it will be removed as 8617 // soon as their animations are complete 8618 token.mAppAnimator.clearAnimation(); 8619 token.mAppAnimator.animating = false; 8620 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 8621 "performLayout: App token exiting now removed" + token); 8622 mAppTokens.remove(token); 8623 mExitingAppTokens.remove(i); 8624 } 8625 } 8626 8627 if (!mAnimator.mAnimating && mAppTransitionRunning) { 8628 // We have finished the animation of an app transition. To do 8629 // this, we have delayed a lot of operations like showing and 8630 // hiding apps, moving apps in Z-order, etc. The app token list 8631 // reflects the correct Z-order, but the window list may now 8632 // be out of sync with it. So here we will just rebuild the 8633 // entire app window list. Fun! 8634 mAppTransitionRunning = false; 8635 mLayoutNeeded = true; 8636 rebuildAppWindowListLocked(); 8637 assignLayersLocked(); 8638 // Clear information about apps that were moving. 8639 mToBottomApps.clear(); 8640 } 8641 8642 if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { 8643 for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { 8644 try { 8645 mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); 8646 } catch (RemoteException e) { 8647 } 8648 } 8649 mRelayoutWhileAnimating.clear(); 8650 } 8651 8652 if (wallpaperDestroyed) { 8653 mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0; 8654 } 8655 if (mPendingLayoutChanges != 0) { 8656 mLayoutNeeded = true; 8657 } 8658 8659 // Finally update all input windows now that the window changes have stabilized. 8660 mInputMonitor.updateInputWindowsLw(true /*force*/); 8661 8662 setHoldScreenLocked(mInnerFields.mHoldScreen != null); 8663 if (!mDisplayFrozen) { 8664 if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) { 8665 mPowerManager.setScreenBrightnessOverride(-1); 8666 } else { 8667 mPowerManager.setScreenBrightnessOverride((int) 8668 (mInnerFields.mScreenBrightness * Power.BRIGHTNESS_ON)); 8669 } 8670 if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) { 8671 mPowerManager.setButtonBrightnessOverride(-1); 8672 } else { 8673 mPowerManager.setButtonBrightnessOverride((int) 8674 (mInnerFields.mButtonBrightness * Power.BRIGHTNESS_ON)); 8675 } 8676 } 8677 if (mInnerFields.mHoldScreen != mHoldingScreenOn) { 8678 mHoldingScreenOn = mInnerFields.mHoldScreen; 8679 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, mInnerFields.mHoldScreen); 8680 mH.sendMessage(m); 8681 } 8682 8683 if (mTurnOnScreen) { 8684 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 8685 mPowerManager.userActivity(SystemClock.uptimeMillis(), false, 8686 LocalPowerManager.BUTTON_EVENT, true); 8687 mTurnOnScreen = false; 8688 } 8689 8690 if (mInnerFields.mUpdateRotation) { 8691 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 8692 if (updateRotationUncheckedLocked(false)) { 8693 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8694 } else { 8695 mInnerFields.mUpdateRotation = false; 8696 } 8697 } 8698 8699 if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded && 8700 !mInnerFields.mUpdateRotation) { 8701 checkDrawnWindowsLocked(); 8702 } 8703 8704 // Check to see if we are now in a state where the screen should 8705 // be enabled, because the window obscured flags have changed. 8706 enableScreenIfNeededLocked(); 8707 8708 scheduleAnimationLocked(); 8709 8710 if (DEBUG_WINDOW_TRACE) { 8711 Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mPendingLayoutChanges=" 8712 + Integer.toHexString(mPendingLayoutChanges) + " mLayoutNeeded=" + mLayoutNeeded 8713 + " animating=" + mAnimator.mAnimating); 8714 } 8715 } 8716 8717 void checkDrawnWindowsLocked() { 8718 if (mWaitingForDrawn.size() > 0) { 8719 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 8720 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 8721 WindowState win = pair.first; 8722 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 8723 // + win.mRemoved + " visible=" + win.isVisibleLw() 8724 // + " shown=" + win.mSurfaceShown); 8725 if (win.mRemoved || !win.isVisibleLw()) { 8726 // Window has been removed or made invisible; no draw 8727 // will now happen, so stop waiting. 8728 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 8729 try { 8730 pair.second.sendResult(null); 8731 } catch (RemoteException e) { 8732 } 8733 mWaitingForDrawn.remove(pair); 8734 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8735 } else if (win.mWinAnimator.mSurfaceShown) { 8736 // Window is now drawn (and shown). 8737 try { 8738 pair.second.sendResult(null); 8739 } catch (RemoteException e) { 8740 } 8741 mWaitingForDrawn.remove(pair); 8742 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8743 } 8744 } 8745 } 8746 } 8747 8748 public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 8749 synchronized (mWindowMap) { 8750 WindowState win = windowForClientLocked(null, token, true); 8751 if (win != null) { 8752 Pair<WindowState, IRemoteCallback> pair = 8753 new Pair<WindowState, IRemoteCallback>(win, callback); 8754 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8755 mH.sendMessageDelayed(m, 2000); 8756 mWaitingForDrawn.add(pair); 8757 checkDrawnWindowsLocked(); 8758 } 8759 } 8760 } 8761 8762 /** 8763 * Must be called with the main window manager lock held. 8764 */ 8765 void setHoldScreenLocked(boolean holding) { 8766 boolean state = mHoldingScreenWakeLock.isHeld(); 8767 if (holding != state) { 8768 if (holding) { 8769 mPolicy.screenOnStartedLw(); 8770 mHoldingScreenWakeLock.acquire(); 8771 } else { 8772 mPolicy.screenOnStoppedLw(); 8773 mHoldingScreenWakeLock.release(); 8774 } 8775 } 8776 } 8777 8778 void requestTraversalLocked() { 8779 if (!mTraversalScheduled) { 8780 mTraversalScheduled = true; 8781 mH.sendEmptyMessage(H.DO_TRAVERSAL); 8782 } 8783 } 8784 8785 void scheduleAnimationLocked() { 8786 if (!mAnimationScheduled) { 8787 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationRunnable, null); 8788 mAnimationScheduled = true; 8789 } 8790 } 8791 8792 boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation, 8793 boolean secure) { 8794 final Surface surface = winAnimator.mSurface; 8795 boolean leakedSurface = false; 8796 boolean killedApps = false; 8797 8798 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 8799 winAnimator.mSession.mPid, operation); 8800 8801 if (mForceRemoves == null) { 8802 mForceRemoves = new ArrayList<WindowState>(); 8803 } 8804 8805 long callingIdentity = Binder.clearCallingIdentity(); 8806 try { 8807 // There was some problem... first, do a sanity check of the 8808 // window list to make sure we haven't left any dangling surfaces 8809 // around. 8810 int N = mWindows.size(); 8811 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 8812 for (int i=0; i<N; i++) { 8813 WindowState ws = mWindows.get(i); 8814 WindowStateAnimator wsa = ws.mWinAnimator; 8815 if (wsa.mSurface != null) { 8816 if (!mSessions.contains(wsa.mSession)) { 8817 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 8818 + ws + " surface=" + wsa.mSurface 8819 + " token=" + ws.mToken 8820 + " pid=" + ws.mSession.mPid 8821 + " uid=" + ws.mSession.mUid); 8822 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 8823 wsa.mSurface.destroy(); 8824 wsa.mSurfaceShown = false; 8825 wsa.mSurface = null; 8826 ws.mHasSurface = false; 8827 mForceRemoves.add(ws); 8828 i--; 8829 N--; 8830 leakedSurface = true; 8831 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 8832 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 8833 + ws + " surface=" + wsa.mSurface 8834 + " token=" + ws.mAppToken); 8835 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 8836 wsa.mSurface.destroy(); 8837 wsa.mSurfaceShown = false; 8838 wsa.mSurface = null; 8839 ws.mHasSurface = false; 8840 leakedSurface = true; 8841 } 8842 } 8843 } 8844 8845 if (!leakedSurface) { 8846 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 8847 SparseIntArray pidCandidates = new SparseIntArray(); 8848 for (int i=0; i<N; i++) { 8849 WindowStateAnimator wsa = mWindows.get(i).mWinAnimator; 8850 if (wsa.mSurface != null) { 8851 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 8852 } 8853 } 8854 if (pidCandidates.size() > 0) { 8855 int[] pids = new int[pidCandidates.size()]; 8856 for (int i=0; i<pids.length; i++) { 8857 pids[i] = pidCandidates.keyAt(i); 8858 } 8859 try { 8860 if (mActivityManager.killPids(pids, "Free memory", secure)) { 8861 killedApps = true; 8862 } 8863 } catch (RemoteException e) { 8864 } 8865 } 8866 } 8867 8868 if (leakedSurface || killedApps) { 8869 // We managed to reclaim some memory, so get rid of the trouble 8870 // surface and ask the app to request another one. 8871 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 8872 if (surface != null) { 8873 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 8874 "RECOVER DESTROY", null); 8875 surface.destroy(); 8876 winAnimator.mSurfaceShown = false; 8877 winAnimator.mSurface = null; 8878 winAnimator.mWin.mHasSurface = false; 8879 } 8880 8881 try { 8882 winAnimator.mWin.mClient.dispatchGetNewSurface(); 8883 } catch (RemoteException e) { 8884 } 8885 } 8886 } finally { 8887 Binder.restoreCallingIdentity(callingIdentity); 8888 } 8889 8890 return leakedSurface || killedApps; 8891 } 8892 8893 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 8894 WindowState newFocus = computeFocusedWindowLocked(); 8895 if (mCurrentFocus != newFocus) { 8896 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus"); 8897 // This check makes sure that we don't already have the focus 8898 // change message pending. 8899 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 8900 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 8901 if (localLOGV) Slog.v( 8902 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 8903 final WindowState oldFocus = mCurrentFocus; 8904 mCurrentFocus = newFocus; 8905 mAnimator.setCurrentFocus(newFocus); 8906 mLosingFocus.remove(newFocus); 8907 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 8908 8909 final WindowState imWindow = mInputMethodWindow; 8910 if (newFocus != imWindow && oldFocus != imWindow) { 8911 if (moveInputMethodWindowsIfNeededLocked( 8912 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 8913 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 8914 mLayoutNeeded = true; 8915 } 8916 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 8917 performLayoutLockedInner(true /*initial*/, updateInputWindows); 8918 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8919 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 8920 // Client will do the layout, but we need to assign layers 8921 // for handleNewWindowLocked() below. 8922 assignLayersLocked(); 8923 } 8924 } 8925 8926 if ((focusChanged&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8927 // The change in focus caused us to need to do a layout. Okay. 8928 mLayoutNeeded = true; 8929 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 8930 performLayoutLockedInner(true /*initial*/, updateInputWindows); 8931 } 8932 } 8933 8934 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 8935 // If we defer assigning layers, then the caller is responsible for 8936 // doing this part. 8937 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 8938 } 8939 8940 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); 8941 return true; 8942 } 8943 return false; 8944 } 8945 8946 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 8947 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 8948 } 8949 8950 private WindowState computeFocusedWindowLocked() { 8951 WindowState result = null; 8952 WindowState win; 8953 8954 int nextAppIndex = mAppTokens.size()-1; 8955 WindowToken nextApp = nextAppIndex >= 0 8956 ? mAppTokens.get(nextAppIndex) : null; 8957 8958 for (int i = mWindows.size() - 1; i >= 0; i--) { 8959 win = mWindows.get(i); 8960 8961 if (localLOGV || DEBUG_FOCUS) Slog.v( 8962 TAG, "Looking for focus: " + i 8963 + " = " + win 8964 + ", flags=" + win.mAttrs.flags 8965 + ", canReceive=" + win.canReceiveKeys()); 8966 8967 AppWindowToken thisApp = win.mAppToken; 8968 8969 // If this window's application has been removed, just skip it. 8970 if (thisApp != null && thisApp.removed) { 8971 continue; 8972 } 8973 8974 // If there is a focused app, don't allow focus to go to any 8975 // windows below it. If this is an application window, step 8976 // through the app tokens until we find its app. 8977 if (thisApp != null && nextApp != null && thisApp != nextApp 8978 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 8979 int origAppIndex = nextAppIndex; 8980 while (nextAppIndex > 0) { 8981 if (nextApp == mFocusedApp) { 8982 // Whoops, we are below the focused app... no focus 8983 // for you! 8984 if (localLOGV || DEBUG_FOCUS) Slog.v( 8985 TAG, "Reached focused app: " + mFocusedApp); 8986 return null; 8987 } 8988 nextAppIndex--; 8989 nextApp = mAppTokens.get(nextAppIndex); 8990 if (nextApp == thisApp) { 8991 break; 8992 } 8993 } 8994 if (thisApp != nextApp) { 8995 // Uh oh, the app token doesn't exist! This shouldn't 8996 // happen, but if it does we can get totally hosed... 8997 // so restart at the original app. 8998 nextAppIndex = origAppIndex; 8999 nextApp = mAppTokens.get(nextAppIndex); 9000 } 9001 } 9002 9003 // Dispatch to this window if it is wants key events. 9004 if (win.canReceiveKeys()) { 9005 if (DEBUG_FOCUS) Slog.v( 9006 TAG, "Found focus @ " + i + " = " + win); 9007 result = win; 9008 break; 9009 } 9010 } 9011 9012 return result; 9013 } 9014 9015 private void startFreezingDisplayLocked(boolean inTransaction) { 9016 if (mDisplayFrozen) { 9017 return; 9018 } 9019 9020 if (mDisplay == null || !mPolicy.isScreenOnFully()) { 9021 // No need to freeze the screen before the system is ready or if 9022 // the screen is off. 9023 return; 9024 } 9025 9026 mScreenFrozenLock.acquire(); 9027 9028 mDisplayFrozen = true; 9029 9030 mInputMonitor.freezeInputDispatchingLw(); 9031 9032 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 9033 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 9034 mNextAppTransitionType = ActivityOptions.ANIM_NONE; 9035 mNextAppTransitionPackage = null; 9036 mNextAppTransitionThumbnail = null; 9037 mAppTransitionReady = true; 9038 } 9039 9040 if (PROFILE_ORIENTATION) { 9041 File file = new File("/data/system/frozen"); 9042 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9043 } 9044 9045 if (CUSTOM_SCREEN_ROTATION) { 9046 if (mAnimator.mScreenRotationAnimation != null) { 9047 mAnimator.mScreenRotationAnimation.kill(); 9048 mAnimator.mScreenRotationAnimation = null; 9049 } 9050 9051 mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, 9052 mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight, 9053 mDisplay.getRotation()); 9054 9055 if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) { 9056 Surface.freezeDisplay(0); 9057 } 9058 } else { 9059 Surface.freezeDisplay(0); 9060 } 9061 } 9062 9063 private void stopFreezingDisplayLocked() { 9064 if (!mDisplayFrozen) { 9065 return; 9066 } 9067 9068 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) { 9069 if (DEBUG_ORIENTATION) Slog.d(TAG, 9070 "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig 9071 + ", mAppsFreezingScreen=" + mAppsFreezingScreen 9072 + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen); 9073 return; 9074 } 9075 9076 mDisplayFrozen = false; 9077 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9078 if (PROFILE_ORIENTATION) { 9079 Debug.stopMethodTracing(); 9080 } 9081 9082 boolean updateRotation = false; 9083 9084 if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null 9085 && mAnimator.mScreenRotationAnimation.hasScreenshot()) { 9086 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 9087 if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 9088 mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { 9089 scheduleAnimationLocked(); 9090 } else { 9091 mAnimator.mScreenRotationAnimation.kill(); 9092 mAnimator.mScreenRotationAnimation = null; 9093 updateRotation = true; 9094 } 9095 } else { 9096 if (mAnimator.mScreenRotationAnimation != null) { 9097 mAnimator.mScreenRotationAnimation.kill(); 9098 mAnimator.mScreenRotationAnimation = null; 9099 } 9100 updateRotation = true; 9101 } 9102 Surface.unfreezeDisplay(0); 9103 9104 mInputMonitor.thawInputDispatchingLw(); 9105 9106 boolean configChanged; 9107 9108 // While the display is frozen we don't re-compute the orientation 9109 // to avoid inconsistent states. However, something interesting 9110 // could have actually changed during that time so re-evaluate it 9111 // now to catch that. 9112 configChanged = updateOrientationFromAppTokensLocked(false); 9113 9114 // A little kludge: a lot could have happened while the 9115 // display was frozen, so now that we are coming back we 9116 // do a gc so that any remote references the system 9117 // processes holds on others can be released if they are 9118 // no longer needed. 9119 mH.removeMessages(H.FORCE_GC); 9120 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 9121 2000); 9122 9123 mScreenFrozenLock.release(); 9124 9125 if (updateRotation) { 9126 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9127 configChanged |= updateRotationUncheckedLocked(false); 9128 } 9129 9130 if (configChanged) { 9131 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9132 } 9133 } 9134 9135 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 9136 DisplayMetrics dm) { 9137 if (index < tokens.length) { 9138 String str = tokens[index]; 9139 if (str != null && str.length() > 0) { 9140 try { 9141 int val = Integer.parseInt(str); 9142 return val; 9143 } catch (Exception e) { 9144 } 9145 } 9146 } 9147 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 9148 return defDps; 9149 } 9150 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 9151 return val; 9152 } 9153 9154 void createWatermark() { 9155 if (mWatermark != null) { 9156 return; 9157 } 9158 9159 File file = new File("/system/etc/setup.conf"); 9160 FileInputStream in = null; 9161 try { 9162 in = new FileInputStream(file); 9163 DataInputStream ind = new DataInputStream(in); 9164 String line = ind.readLine(); 9165 if (line != null) { 9166 String[] toks = line.split("%"); 9167 if (toks != null && toks.length > 0) { 9168 mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks); 9169 } 9170 } 9171 } catch (FileNotFoundException e) { 9172 } catch (IOException e) { 9173 } finally { 9174 if (in != null) { 9175 try { 9176 in.close(); 9177 } catch (IOException e) { 9178 } 9179 } 9180 } 9181 } 9182 9183 @Override 9184 public void statusBarVisibilityChanged(int visibility) { 9185 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 9186 != PackageManager.PERMISSION_GRANTED) { 9187 throw new SecurityException("Caller does not hold permission " 9188 + android.Manifest.permission.STATUS_BAR); 9189 } 9190 9191 synchronized (mWindowMap) { 9192 mLastStatusBarVisibility = visibility; 9193 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 9194 updateStatusBarVisibilityLocked(visibility); 9195 } 9196 } 9197 9198 void updateStatusBarVisibilityLocked(int visibility) { 9199 mInputManager.setSystemUiVisibility(visibility); 9200 final int N = mWindows.size(); 9201 for (int i = 0; i < N; i++) { 9202 WindowState ws = mWindows.get(i); 9203 try { 9204 int curValue = ws.mSystemUiVisibility; 9205 int diff = curValue ^ visibility; 9206 // We are only interested in differences of one of the 9207 // clearable flags... 9208 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 9209 // ...if it has actually been cleared. 9210 diff &= ~visibility; 9211 int newValue = (curValue&~diff) | (visibility&diff); 9212 if (newValue != curValue) { 9213 ws.mSeq++; 9214 ws.mSystemUiVisibility = newValue; 9215 } 9216 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 9217 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 9218 visibility, newValue, diff); 9219 } 9220 } catch (RemoteException e) { 9221 // so sorry 9222 } 9223 } 9224 } 9225 9226 @Override 9227 public void reevaluateStatusBarVisibility() { 9228 synchronized (mWindowMap) { 9229 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 9230 updateStatusBarVisibilityLocked(visibility); 9231 performLayoutAndPlaceSurfacesLocked(); 9232 } 9233 } 9234 9235 @Override 9236 public FakeWindow addFakeWindow(Looper looper, 9237 InputEventReceiver.Factory inputEventReceiverFactory, 9238 String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys, 9239 boolean hasFocus, boolean touchFullscreen) { 9240 synchronized (mWindowMap) { 9241 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory, 9242 name, windowType, 9243 layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 9244 int i=0; 9245 while (i<mFakeWindows.size()) { 9246 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 9247 break; 9248 } 9249 } 9250 mFakeWindows.add(i, fw); 9251 mInputMonitor.updateInputWindowsLw(true); 9252 return fw; 9253 } 9254 } 9255 9256 boolean removeFakeWindowLocked(FakeWindow window) { 9257 synchronized (mWindowMap) { 9258 if (mFakeWindows.remove(window)) { 9259 mInputMonitor.updateInputWindowsLw(true); 9260 return true; 9261 } 9262 return false; 9263 } 9264 } 9265 9266 @Override 9267 public boolean hasNavigationBar() { 9268 return mPolicy.hasNavigationBar(); 9269 } 9270 9271 public void lockNow() { 9272 mPolicy.lockNow(); 9273 } 9274 9275 void dumpPolicyLocked(FileDescriptor fd, PrintWriter pw, String[] args, boolean dumpAll) { 9276 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 9277 mPolicy.dump(" ", fd, pw, args); 9278 } 9279 9280 void dumpTokensLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { 9281 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 9282 if (mTokenMap.size() > 0) { 9283 pw.println(" All tokens:"); 9284 Iterator<WindowToken> it = mTokenMap.values().iterator(); 9285 while (it.hasNext()) { 9286 WindowToken token = it.next(); 9287 pw.print(" Token "); pw.print(token.token); 9288 if (dumpAll) { 9289 pw.println(':'); 9290 token.dump(pw, " "); 9291 } else { 9292 pw.println(); 9293 } 9294 } 9295 } 9296 if (mWallpaperTokens.size() > 0) { 9297 pw.println(); 9298 pw.println(" Wallpaper tokens:"); 9299 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 9300 WindowToken token = mWallpaperTokens.get(i); 9301 pw.print(" Wallpaper #"); pw.print(i); 9302 pw.print(' '); pw.print(token); 9303 if (dumpAll) { 9304 pw.println(':'); 9305 token.dump(pw, " "); 9306 } else { 9307 pw.println(); 9308 } 9309 } 9310 } 9311 if (mAppTokens.size() > 0) { 9312 pw.println(); 9313 pw.println(" Application tokens in Z order:"); 9314 for (int i=mAppTokens.size()-1; i>=0; i--) { 9315 pw.print(" App #"); pw.print(i); pw.println(": "); 9316 mAppTokens.get(i).dump(pw, " "); 9317 } 9318 } 9319 if (mFinishedStarting.size() > 0) { 9320 pw.println(); 9321 pw.println(" Finishing start of application tokens:"); 9322 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 9323 WindowToken token = mFinishedStarting.get(i); 9324 pw.print(" Finished Starting #"); pw.print(i); 9325 pw.print(' '); pw.print(token); 9326 if (dumpAll) { 9327 pw.println(':'); 9328 token.dump(pw, " "); 9329 } else { 9330 pw.println(); 9331 } 9332 } 9333 } 9334 if (mExitingTokens.size() > 0) { 9335 pw.println(); 9336 pw.println(" Exiting tokens:"); 9337 for (int i=mExitingTokens.size()-1; i>=0; i--) { 9338 WindowToken token = mExitingTokens.get(i); 9339 pw.print(" Exiting #"); pw.print(i); 9340 pw.print(' '); pw.print(token); 9341 if (dumpAll) { 9342 pw.println(':'); 9343 token.dump(pw, " "); 9344 } else { 9345 pw.println(); 9346 } 9347 } 9348 } 9349 if (mExitingAppTokens.size() > 0) { 9350 pw.println(); 9351 pw.println(" Exiting application tokens:"); 9352 for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 9353 WindowToken token = mExitingAppTokens.get(i); 9354 pw.print(" Exiting App #"); pw.print(i); 9355 pw.print(' '); pw.print(token); 9356 if (dumpAll) { 9357 pw.println(':'); 9358 token.dump(pw, " "); 9359 } else { 9360 pw.println(); 9361 } 9362 } 9363 } 9364 pw.println(); 9365 if (mOpeningApps.size() > 0) { 9366 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 9367 } 9368 if (mClosingApps.size() > 0) { 9369 pw.print(" mClosingApps="); pw.println(mClosingApps); 9370 } 9371 if (mToTopApps.size() > 0) { 9372 pw.print(" mToTopApps="); pw.println(mToTopApps); 9373 } 9374 if (mToBottomApps.size() > 0) { 9375 pw.print(" mToBottomApps="); pw.println(mToBottomApps); 9376 } 9377 } 9378 9379 void dumpSessionsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { 9380 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 9381 if (mSessions.size() > 0) { 9382 Iterator<Session> it = mSessions.iterator(); 9383 while (it.hasNext()) { 9384 Session s = it.next(); 9385 pw.print(" Session "); pw.print(s); pw.println(':'); 9386 s.dump(pw, " "); 9387 } 9388 } 9389 } 9390 9391 void dumpWindowsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, 9392 ArrayList<WindowState> windows) { 9393 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 9394 for (int i=mWindows.size()-1; i>=0; i--) { 9395 WindowState w = mWindows.get(i); 9396 if (windows == null || windows.contains(w)) { 9397 pw.print(" Window #"); pw.print(i); pw.print(' '); 9398 pw.print(w); pw.println(":"); 9399 w.dump(pw, " ", dumpAll || windows != null); 9400 } 9401 } 9402 if (mInputMethodDialogs.size() > 0) { 9403 pw.println(); 9404 pw.println(" Input method dialogs:"); 9405 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 9406 WindowState w = mInputMethodDialogs.get(i); 9407 if (windows == null || windows.contains(w)) { 9408 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 9409 } 9410 } 9411 } 9412 if (mPendingRemove.size() > 0) { 9413 pw.println(); 9414 pw.println(" Remove pending for:"); 9415 for (int i=mPendingRemove.size()-1; i>=0; i--) { 9416 WindowState w = mPendingRemove.get(i); 9417 if (windows == null || windows.contains(w)) { 9418 pw.print(" Remove #"); pw.print(i); pw.print(' '); 9419 pw.print(w); 9420 if (dumpAll) { 9421 pw.println(":"); 9422 w.dump(pw, " ", true); 9423 } else { 9424 pw.println(); 9425 } 9426 } 9427 } 9428 } 9429 if (mForceRemoves != null && mForceRemoves.size() > 0) { 9430 pw.println(); 9431 pw.println(" Windows force removing:"); 9432 for (int i=mForceRemoves.size()-1; i>=0; i--) { 9433 WindowState w = mForceRemoves.get(i); 9434 pw.print(" Removing #"); pw.print(i); pw.print(' '); 9435 pw.print(w); 9436 if (dumpAll) { 9437 pw.println(":"); 9438 w.dump(pw, " ", true); 9439 } else { 9440 pw.println(); 9441 } 9442 } 9443 } 9444 if (mDestroySurface.size() > 0) { 9445 pw.println(); 9446 pw.println(" Windows waiting to destroy their surface:"); 9447 for (int i=mDestroySurface.size()-1; i>=0; i--) { 9448 WindowState w = mDestroySurface.get(i); 9449 if (windows == null || windows.contains(w)) { 9450 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 9451 pw.print(w); 9452 if (dumpAll) { 9453 pw.println(":"); 9454 w.dump(pw, " ", true); 9455 } else { 9456 pw.println(); 9457 } 9458 } 9459 } 9460 } 9461 if (mLosingFocus.size() > 0) { 9462 pw.println(); 9463 pw.println(" Windows losing focus:"); 9464 for (int i=mLosingFocus.size()-1; i>=0; i--) { 9465 WindowState w = mLosingFocus.get(i); 9466 if (windows == null || windows.contains(w)) { 9467 pw.print(" Losing #"); pw.print(i); pw.print(' '); 9468 pw.print(w); 9469 if (dumpAll) { 9470 pw.println(":"); 9471 w.dump(pw, " ", true); 9472 } else { 9473 pw.println(); 9474 } 9475 } 9476 } 9477 } 9478 if (mResizingWindows.size() > 0) { 9479 pw.println(); 9480 pw.println(" Windows waiting to resize:"); 9481 for (int i=mResizingWindows.size()-1; i>=0; i--) { 9482 WindowState w = mResizingWindows.get(i); 9483 if (windows == null || windows.contains(w)) { 9484 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 9485 pw.print(w); 9486 if (dumpAll) { 9487 pw.println(":"); 9488 w.dump(pw, " ", true); 9489 } else { 9490 pw.println(); 9491 } 9492 } 9493 } 9494 } 9495 if (mWaitingForDrawn.size() > 0) { 9496 pw.println(); 9497 pw.println(" Clients waiting for these windows to be drawn:"); 9498 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 9499 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 9500 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 9501 pw.print(": "); pw.println(pair.second); 9502 } 9503 } 9504 pw.println(); 9505 if (mDisplay != null) { 9506 pw.print(" Display: init="); pw.print(mInitialDisplayWidth); pw.print("x"); 9507 pw.print(mInitialDisplayHeight); 9508 if (mInitialDisplayWidth != mBaseDisplayWidth 9509 || mInitialDisplayHeight != mBaseDisplayHeight) { 9510 pw.print(" base="); 9511 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 9512 } 9513 final int rawWidth = mDisplay.getRawWidth(); 9514 final int rawHeight = mDisplay.getRawHeight(); 9515 if (rawWidth != mCurDisplayWidth || rawHeight != mCurDisplayHeight) { 9516 pw.print(" raw="); pw.print(rawWidth); pw.print("x"); pw.print(rawHeight); 9517 } 9518 pw.print(" cur="); 9519 pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight); 9520 pw.print(" app="); 9521 pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight); 9522 pw.print(" rng="); pw.print(mSmallestDisplayWidth); 9523 pw.print("x"); pw.print(mSmallestDisplayHeight); 9524 pw.print("-"); pw.print(mLargestDisplayWidth); 9525 pw.print("x"); pw.println(mLargestDisplayHeight); 9526 } else { 9527 pw.println(" NO DISPLAY"); 9528 } 9529 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 9530 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 9531 if (mLastFocus != mCurrentFocus) { 9532 pw.print(" mLastFocus="); pw.println(mLastFocus); 9533 } 9534 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 9535 if (mInputMethodTarget != null) { 9536 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 9537 } 9538 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 9539 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 9540 if (dumpAll) { 9541 if (mLastStatusBarVisibility != 0) { 9542 pw.print(" mLastStatusBarVisibility=0x"); 9543 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 9544 } 9545 if (mInputMethodWindow != null) { 9546 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 9547 } 9548 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 9549 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) { 9550 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 9551 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 9552 } 9553 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 9554 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 9555 if (mInputMethodAnimLayerAdjustment != 0 || 9556 mWallpaperAnimLayerAdjustment != 0) { 9557 pw.print(" mInputMethodAnimLayerAdjustment="); 9558 pw.print(mInputMethodAnimLayerAdjustment); 9559 pw.print(" mWallpaperAnimLayerAdjustment="); 9560 pw.println(mWallpaperAnimLayerAdjustment); 9561 } 9562 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 9563 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 9564 pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded); 9565 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 9566 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); 9567 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); 9568 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); 9569 pw.print(" mRotation="); pw.print(mRotation); 9570 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 9571 pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); 9572 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 9573 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 9574 if (mAnimator.mScreenRotationAnimation != null) { 9575 pw.println(" mScreenRotationAnimation:"); 9576 mAnimator.mScreenRotationAnimation.printTo(" ", pw); 9577 } 9578 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 9579 pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale); 9580 pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale); 9581 pw.print(" mTraversalScheduled="); pw.print(mTraversalScheduled); 9582 pw.print(" mNextAppTransition=0x"); 9583 pw.print(Integer.toHexString(mNextAppTransition)); 9584 pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady); 9585 pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning); 9586 pw.print(" mAppTransitionTimeout="); pw.println(mAppTransitionTimeout); 9587 if (mNextAppTransitionType != ActivityOptions.ANIM_NONE) { 9588 pw.print(" mNextAppTransitionType="); pw.println(mNextAppTransitionType); 9589 } 9590 switch (mNextAppTransitionType) { 9591 case ActivityOptions.ANIM_CUSTOM: 9592 pw.print(" mNextAppTransitionPackage="); 9593 pw.print(mNextAppTransitionPackage); 9594 pw.print(" mNextAppTransitionEnter=0x"); 9595 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 9596 pw.print(" mNextAppTransitionExit=0x"); 9597 pw.print(Integer.toHexString(mNextAppTransitionExit)); 9598 break; 9599 case ActivityOptions.ANIM_SCALE_UP: 9600 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); 9601 pw.print(" mNextAppTransitionStartY="); 9602 pw.println(mNextAppTransitionStartY); 9603 pw.print(" mNextAppTransitionStartWidth="); 9604 pw.print(mNextAppTransitionStartWidth); 9605 pw.print(" mNextAppTransitionStartHeight="); 9606 pw.println(mNextAppTransitionStartHeight); 9607 break; 9608 case ActivityOptions.ANIM_THUMBNAIL: 9609 pw.print(" mNextAppTransitionThumbnail="); 9610 pw.print(mNextAppTransitionThumbnail); 9611 pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); 9612 pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY); 9613 break; 9614 } 9615 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 9616 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 9617 } 9618 } 9619 9620 boolean dumpWindows(FileDescriptor fd, PrintWriter pw, String name, String[] args, 9621 int opti, boolean dumpAll) { 9622 ArrayList<WindowState> windows = new ArrayList<WindowState>(); 9623 if ("visible".equals(name)) { 9624 synchronized(mWindowMap) { 9625 for (int i=mWindows.size()-1; i>=0; i--) { 9626 WindowState w = mWindows.get(i); 9627 if (w.mWinAnimator.mSurfaceShown) { 9628 windows.add(w); 9629 } 9630 } 9631 } 9632 } else { 9633 int objectId = 0; 9634 // See if this is an object ID. 9635 try { 9636 objectId = Integer.parseInt(name, 16); 9637 name = null; 9638 } catch (RuntimeException e) { 9639 } 9640 synchronized(mWindowMap) { 9641 for (int i=mWindows.size()-1; i>=0; i--) { 9642 WindowState w = mWindows.get(i); 9643 if (name != null) { 9644 if (w.mAttrs.getTitle().toString().contains(name)) { 9645 windows.add(w); 9646 } 9647 } else if (System.identityHashCode(w) == objectId) { 9648 windows.add(w); 9649 } 9650 } 9651 } 9652 } 9653 9654 if (windows.size() <= 0) { 9655 return false; 9656 } 9657 9658 synchronized(mWindowMap) { 9659 dumpWindowsLocked(fd, pw, dumpAll, windows); 9660 } 9661 return true; 9662 } 9663 9664 @Override 9665 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 9666 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 9667 != PackageManager.PERMISSION_GRANTED) { 9668 pw.println("Permission Denial: can't dump WindowManager from from pid=" 9669 + Binder.getCallingPid() 9670 + ", uid=" + Binder.getCallingUid()); 9671 return; 9672 } 9673 9674 boolean dumpAll = false; 9675 9676 int opti = 0; 9677 while (opti < args.length) { 9678 String opt = args[opti]; 9679 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 9680 break; 9681 } 9682 opti++; 9683 if ("-a".equals(opt)) { 9684 dumpAll = true; 9685 } else if ("-h".equals(opt)) { 9686 pw.println("Window manager dump options:"); 9687 pw.println(" [-a] [-h] [cmd] ..."); 9688 pw.println(" cmd may be one of:"); 9689 pw.println(" p[policy]: policy state"); 9690 pw.println(" s[essions]: active sessions"); 9691 pw.println(" t[okens]: token list"); 9692 pw.println(" w[indows]: window list"); 9693 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 9694 pw.println(" be a partial substring in a window name, a"); 9695 pw.println(" Window hex object identifier, or"); 9696 pw.println(" \"all\" for all windows, or"); 9697 pw.println(" \"visible\" for the visible windows."); 9698 pw.println(" -a: include all available server state."); 9699 return; 9700 } else { 9701 pw.println("Unknown argument: " + opt + "; use -h for help"); 9702 } 9703 } 9704 9705 // Is the caller requesting to dump a particular piece of data? 9706 if (opti < args.length) { 9707 String cmd = args[opti]; 9708 opti++; 9709 if ("policy".equals(cmd) || "p".equals(cmd)) { 9710 synchronized(mWindowMap) { 9711 dumpPolicyLocked(fd, pw, args, true); 9712 } 9713 return; 9714 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 9715 synchronized(mWindowMap) { 9716 dumpSessionsLocked(fd, pw, true); 9717 } 9718 return; 9719 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 9720 synchronized(mWindowMap) { 9721 dumpTokensLocked(fd, pw, true); 9722 } 9723 return; 9724 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 9725 synchronized(mWindowMap) { 9726 dumpWindowsLocked(fd, pw, true, null); 9727 } 9728 return; 9729 } else if ("all".equals(cmd) || "a".equals(cmd)) { 9730 synchronized(mWindowMap) { 9731 dumpWindowsLocked(fd, pw, true, null); 9732 } 9733 return; 9734 } else { 9735 // Dumping a single name? 9736 if (!dumpWindows(fd, pw, cmd, args, opti, dumpAll)) { 9737 pw.println("Bad window command, or no windows match: " + cmd); 9738 pw.println("Use -h for help."); 9739 } 9740 return; 9741 } 9742 } 9743 9744 synchronized(mWindowMap) { 9745 if (dumpAll) { 9746 pw.println("-------------------------------------------------------------------------------"); 9747 } 9748 dumpPolicyLocked(fd, pw, args, dumpAll); 9749 pw.println(); 9750 if (dumpAll) { 9751 pw.println("-------------------------------------------------------------------------------"); 9752 } 9753 dumpSessionsLocked(fd, pw, dumpAll); 9754 pw.println(); 9755 if (dumpAll) { 9756 pw.println("-------------------------------------------------------------------------------"); 9757 } 9758 dumpTokensLocked(fd, pw, dumpAll); 9759 pw.println(); 9760 if (dumpAll) { 9761 pw.println("-------------------------------------------------------------------------------"); 9762 } 9763 dumpWindowsLocked(fd, pw, dumpAll, null); 9764 } 9765 } 9766 9767 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 9768 public void monitor() { 9769 synchronized (mWindowMap) { } 9770 synchronized (mKeyguardTokenWatcher) { } 9771 } 9772 9773 public interface OnHardKeyboardStatusChangeListener { 9774 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 9775 } 9776 9777 void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { 9778 if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { 9779 Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + 9780 Integer.toHexString(pendingLayoutChanges)); 9781 } 9782 } 9783 9784 void bulkSetParameters(final int bulkUpdateParams, int pendingLayoutChanges) { 9785 mH.sendMessage(mH.obtainMessage(H.BULK_UPDATE_PARAMETERS, bulkUpdateParams, 9786 pendingLayoutChanges)); 9787 } 9788} 9789