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