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