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