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