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