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