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