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