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