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