WindowManagerService.java revision a8e5a2bcd6a0d35893187c6df42425c03be005da
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 WINDOW_FREEZE_TIMEOUT = 11; 6390 public static final int HOLD_SCREEN_CHANGED = 12; 6391 public static final int APP_TRANSITION_TIMEOUT = 13; 6392 public static final int PERSIST_ANIMATION_SCALE = 14; 6393 public static final int FORCE_GC = 15; 6394 public static final int ENABLE_SCREEN = 16; 6395 public static final int APP_FREEZE_TIMEOUT = 17; 6396 public static final int SEND_NEW_CONFIGURATION = 18; 6397 public static final int REPORT_WINDOWS_CHANGE = 19; 6398 public static final int DRAG_START_TIMEOUT = 20; 6399 public static final int DRAG_END_TIMEOUT = 21; 6400 public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; 6401 public static final int BOOT_TIMEOUT = 23; 6402 public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; 6403 6404 private Session mLastReportedHold; 6405 6406 public H() { 6407 } 6408 6409 @Override 6410 public void handleMessage(Message msg) { 6411 switch (msg.what) { 6412 case REPORT_FOCUS_CHANGE: { 6413 WindowState lastFocus; 6414 WindowState newFocus; 6415 6416 synchronized(mWindowMap) { 6417 lastFocus = mLastFocus; 6418 newFocus = mCurrentFocus; 6419 if (lastFocus == newFocus) { 6420 // Focus is not changing, so nothing to do. 6421 return; 6422 } 6423 mLastFocus = newFocus; 6424 //Slog.i(TAG, "Focus moving from " + lastFocus 6425 // + " to " + newFocus); 6426 if (newFocus != null && lastFocus != null 6427 && !newFocus.isDisplayedLw()) { 6428 //Slog.i(TAG, "Delaying loss of focus..."); 6429 mLosingFocus.add(lastFocus); 6430 lastFocus = null; 6431 } 6432 } 6433 6434 if (lastFocus != newFocus) { 6435 //System.out.println("Changing focus from " + lastFocus 6436 // + " to " + newFocus); 6437 if (newFocus != null) { 6438 try { 6439 //Slog.i(TAG, "Gaining focus: " + newFocus); 6440 newFocus.mClient.windowFocusChanged(true, mInTouchMode); 6441 } catch (RemoteException e) { 6442 // Ignore if process has died. 6443 } 6444 notifyFocusChanged(); 6445 } 6446 6447 if (lastFocus != null) { 6448 try { 6449 //Slog.i(TAG, "Losing focus: " + lastFocus); 6450 lastFocus.mClient.windowFocusChanged(false, mInTouchMode); 6451 } catch (RemoteException e) { 6452 // Ignore if process has died. 6453 } 6454 } 6455 } 6456 } break; 6457 6458 case REPORT_LOSING_FOCUS: { 6459 ArrayList<WindowState> losers; 6460 6461 synchronized(mWindowMap) { 6462 losers = mLosingFocus; 6463 mLosingFocus = new ArrayList<WindowState>(); 6464 } 6465 6466 final int N = losers.size(); 6467 for (int i=0; i<N; i++) { 6468 try { 6469 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i)); 6470 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode); 6471 } catch (RemoteException e) { 6472 // Ignore if process has died. 6473 } 6474 } 6475 } break; 6476 6477 case ANIMATE: { 6478 synchronized(mWindowMap) { 6479 mAnimationPending = false; 6480 performLayoutAndPlaceSurfacesLocked(); 6481 } 6482 } break; 6483 6484 case ADD_STARTING: { 6485 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6486 final StartingData sd = wtoken.startingData; 6487 6488 if (sd == null) { 6489 // Animation has been canceled... do nothing. 6490 return; 6491 } 6492 6493 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " 6494 + wtoken + ": pkg=" + sd.pkg); 6495 6496 View view = null; 6497 try { 6498 view = mPolicy.addStartingWindow( 6499 wtoken.token, sd.pkg, sd.theme, sd.compatInfo, 6500 sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags); 6501 } catch (Exception e) { 6502 Slog.w(TAG, "Exception when adding starting window", e); 6503 } 6504 6505 if (view != null) { 6506 boolean abort = false; 6507 6508 synchronized(mWindowMap) { 6509 if (wtoken.removed || wtoken.startingData == null) { 6510 // If the window was successfully added, then 6511 // we need to remove it. 6512 if (wtoken.startingWindow != null) { 6513 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 6514 "Aborted starting " + wtoken 6515 + ": removed=" + wtoken.removed 6516 + " startingData=" + wtoken.startingData); 6517 wtoken.startingWindow = null; 6518 wtoken.startingData = null; 6519 abort = true; 6520 } 6521 } else { 6522 wtoken.startingView = view; 6523 } 6524 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, 6525 "Added starting " + wtoken 6526 + ": startingWindow=" 6527 + wtoken.startingWindow + " startingView=" 6528 + wtoken.startingView); 6529 } 6530 6531 if (abort) { 6532 try { 6533 mPolicy.removeStartingWindow(wtoken.token, view); 6534 } catch (Exception e) { 6535 Slog.w(TAG, "Exception when removing starting window", e); 6536 } 6537 } 6538 } 6539 } break; 6540 6541 case REMOVE_STARTING: { 6542 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6543 IBinder token = null; 6544 View view = null; 6545 synchronized (mWindowMap) { 6546 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " 6547 + wtoken + ": startingWindow=" 6548 + wtoken.startingWindow + " startingView=" 6549 + wtoken.startingView); 6550 if (wtoken.startingWindow != null) { 6551 view = wtoken.startingView; 6552 token = wtoken.token; 6553 wtoken.startingData = null; 6554 wtoken.startingView = null; 6555 wtoken.startingWindow = null; 6556 } 6557 } 6558 if (view != null) { 6559 try { 6560 mPolicy.removeStartingWindow(token, view); 6561 } catch (Exception e) { 6562 Slog.w(TAG, "Exception when removing starting window", e); 6563 } 6564 } 6565 } break; 6566 6567 case FINISHED_STARTING: { 6568 IBinder token = null; 6569 View view = null; 6570 while (true) { 6571 synchronized (mWindowMap) { 6572 final int N = mFinishedStarting.size(); 6573 if (N <= 0) { 6574 break; 6575 } 6576 AppWindowToken wtoken = mFinishedStarting.remove(N-1); 6577 6578 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, 6579 "Finished starting " + wtoken 6580 + ": startingWindow=" + wtoken.startingWindow 6581 + " startingView=" + wtoken.startingView); 6582 6583 if (wtoken.startingWindow == null) { 6584 continue; 6585 } 6586 6587 view = wtoken.startingView; 6588 token = wtoken.token; 6589 wtoken.startingData = null; 6590 wtoken.startingView = null; 6591 wtoken.startingWindow = null; 6592 } 6593 6594 try { 6595 mPolicy.removeStartingWindow(token, view); 6596 } catch (Exception e) { 6597 Slog.w(TAG, "Exception when removing starting window", e); 6598 } 6599 } 6600 } break; 6601 6602 case REPORT_APPLICATION_TOKEN_WINDOWS: { 6603 final AppWindowToken wtoken = (AppWindowToken)msg.obj; 6604 6605 boolean nowVisible = msg.arg1 != 0; 6606 boolean nowGone = msg.arg2 != 0; 6607 6608 try { 6609 if (DEBUG_VISIBILITY) Slog.v( 6610 TAG, "Reporting visible in " + wtoken 6611 + " visible=" + nowVisible 6612 + " gone=" + nowGone); 6613 if (nowVisible) { 6614 wtoken.appToken.windowsVisible(); 6615 } else { 6616 wtoken.appToken.windowsGone(); 6617 } 6618 } catch (RemoteException ex) { 6619 } 6620 } break; 6621 6622 case WINDOW_FREEZE_TIMEOUT: { 6623 synchronized (mWindowMap) { 6624 Slog.w(TAG, "Window freeze timeout expired."); 6625 int i = mWindows.size(); 6626 while (i > 0) { 6627 i--; 6628 WindowState w = mWindows.get(i); 6629 if (w.mOrientationChanging) { 6630 w.mOrientationChanging = false; 6631 Slog.w(TAG, "Force clearing orientation change: " + w); 6632 } 6633 } 6634 performLayoutAndPlaceSurfacesLocked(); 6635 } 6636 break; 6637 } 6638 6639 case HOLD_SCREEN_CHANGED: { 6640 Session oldHold; 6641 Session newHold; 6642 synchronized (mWindowMap) { 6643 oldHold = mLastReportedHold; 6644 newHold = (Session)msg.obj; 6645 mLastReportedHold = newHold; 6646 } 6647 6648 if (oldHold != newHold) { 6649 try { 6650 if (oldHold != null) { 6651 mBatteryStats.noteStopWakelock(oldHold.mUid, -1, 6652 "window", 6653 BatteryStats.WAKE_TYPE_WINDOW); 6654 } 6655 if (newHold != null) { 6656 mBatteryStats.noteStartWakelock(newHold.mUid, -1, 6657 "window", 6658 BatteryStats.WAKE_TYPE_WINDOW); 6659 } 6660 } catch (RemoteException e) { 6661 } 6662 } 6663 break; 6664 } 6665 6666 case APP_TRANSITION_TIMEOUT: { 6667 synchronized (mWindowMap) { 6668 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 6669 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 6670 "*** APP TRANSITION TIMEOUT"); 6671 mAppTransitionReady = true; 6672 mAppTransitionTimeout = true; 6673 performLayoutAndPlaceSurfacesLocked(); 6674 } 6675 } 6676 break; 6677 } 6678 6679 case PERSIST_ANIMATION_SCALE: { 6680 Settings.System.putFloat(mContext.getContentResolver(), 6681 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); 6682 Settings.System.putFloat(mContext.getContentResolver(), 6683 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); 6684 break; 6685 } 6686 6687 case FORCE_GC: { 6688 synchronized(mWindowMap) { 6689 if (mAnimationPending) { 6690 // If we are animating, don't do the gc now but 6691 // delay a bit so we don't interrupt the animation. 6692 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 6693 2000); 6694 return; 6695 } 6696 // If we are currently rotating the display, it will 6697 // schedule a new message when done. 6698 if (mDisplayFrozen) { 6699 return; 6700 } 6701 } 6702 Runtime.getRuntime().gc(); 6703 break; 6704 } 6705 6706 case ENABLE_SCREEN: { 6707 performEnableScreen(); 6708 break; 6709 } 6710 6711 case APP_FREEZE_TIMEOUT: { 6712 synchronized (mWindowMap) { 6713 Slog.w(TAG, "App freeze timeout expired."); 6714 int i = mAppTokens.size(); 6715 while (i > 0) { 6716 i--; 6717 AppWindowToken tok = mAppTokens.get(i); 6718 if (tok.freezingScreen) { 6719 Slog.w(TAG, "Force clearing freeze: " + tok); 6720 unsetAppFreezingScreenLocked(tok, true, true); 6721 } 6722 } 6723 } 6724 break; 6725 } 6726 6727 case SEND_NEW_CONFIGURATION: { 6728 removeMessages(SEND_NEW_CONFIGURATION); 6729 sendNewConfiguration(); 6730 break; 6731 } 6732 6733 case REPORT_WINDOWS_CHANGE: { 6734 if (mWindowsChanged) { 6735 synchronized (mWindowMap) { 6736 mWindowsChanged = false; 6737 } 6738 notifyWindowsChanged(); 6739 } 6740 break; 6741 } 6742 6743 case DRAG_START_TIMEOUT: { 6744 IBinder win = (IBinder)msg.obj; 6745 if (DEBUG_DRAG) { 6746 Slog.w(TAG, "Timeout starting drag by win " + win); 6747 } 6748 synchronized (mWindowMap) { 6749 // !!! TODO: ANR the app that has failed to start the drag in time 6750 if (mDragState != null) { 6751 mDragState.unregister(); 6752 mInputMonitor.updateInputWindowsLw(true /*force*/); 6753 mDragState.reset(); 6754 mDragState = null; 6755 } 6756 } 6757 break; 6758 } 6759 6760 case DRAG_END_TIMEOUT: { 6761 IBinder win = (IBinder)msg.obj; 6762 if (DEBUG_DRAG) { 6763 Slog.w(TAG, "Timeout ending drag to win " + win); 6764 } 6765 synchronized (mWindowMap) { 6766 // !!! TODO: ANR the drag-receiving app 6767 if (mDragState != null) { 6768 mDragState.mDragResult = false; 6769 mDragState.endDragLw(); 6770 } 6771 } 6772 break; 6773 } 6774 6775 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { 6776 notifyHardKeyboardStatusChange(); 6777 break; 6778 } 6779 6780 case BOOT_TIMEOUT: { 6781 performBootTimeout(); 6782 break; 6783 } 6784 6785 case WAITING_FOR_DRAWN_TIMEOUT: { 6786 Pair<WindowState, IRemoteCallback> pair; 6787 synchronized (mWindowMap) { 6788 pair = (Pair<WindowState, IRemoteCallback>)msg.obj; 6789 Slog.w(TAG, "Timeout waiting for drawn: " + pair.first); 6790 if (!mWaitingForDrawn.remove(pair)) { 6791 return; 6792 } 6793 } 6794 try { 6795 pair.second.sendResult(null); 6796 } catch (RemoteException e) { 6797 } 6798 break; 6799 } 6800 } 6801 } 6802 } 6803 6804 // ------------------------------------------------------------- 6805 // IWindowManager API 6806 // ------------------------------------------------------------- 6807 6808 public IWindowSession openSession(IInputMethodClient client, 6809 IInputContext inputContext) { 6810 if (client == null) throw new IllegalArgumentException("null client"); 6811 if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 6812 Session session = new Session(this, client, inputContext); 6813 return session; 6814 } 6815 6816 public boolean inputMethodClientHasFocus(IInputMethodClient client) { 6817 synchronized (mWindowMap) { 6818 // The focus for the client is the window immediately below 6819 // where we would place the input method window. 6820 int idx = findDesiredInputMethodWindowIndexLocked(false); 6821 WindowState imFocus; 6822 if (idx > 0) { 6823 imFocus = mWindows.get(idx-1); 6824 //Log.i(TAG, "Desired input method target: " + imFocus); 6825 //Log.i(TAG, "Current focus: " + this.mCurrentFocus); 6826 //Log.i(TAG, "Last focus: " + this.mLastFocus); 6827 if (imFocus != null) { 6828 // This may be a starting window, in which case we still want 6829 // to count it as okay. 6830 if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING 6831 && imFocus.mAppToken != null) { 6832 // The client has definitely started, so it really should 6833 // have a window in this app token. Let's look for it. 6834 for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { 6835 WindowState w = imFocus.mAppToken.windows.get(i); 6836 if (w != imFocus) { 6837 //Log.i(TAG, "Switching to real app window: " + w); 6838 imFocus = w; 6839 break; 6840 } 6841 } 6842 } 6843 //Log.i(TAG, "IM target client: " + imFocus.mSession.mClient); 6844 //if (imFocus.mSession.mClient != null) { 6845 // Log.i(TAG, "IM target client binder: " + imFocus.mSession.mClient.asBinder()); 6846 // Log.i(TAG, "Requesting client binder: " + client.asBinder()); 6847 //} 6848 if (imFocus.mSession.mClient != null && 6849 imFocus.mSession.mClient.asBinder() == client.asBinder()) { 6850 return true; 6851 } 6852 6853 // Okay, how about this... what is the current focus? 6854 // It seems in some cases we may not have moved the IM 6855 // target window, such as when it was in a pop-up window, 6856 // so let's also look at the current focus. (An example: 6857 // go to Gmail, start searching so the keyboard goes up, 6858 // press home. Sometimes the IME won't go down.) 6859 // Would be nice to fix this more correctly, but it's 6860 // way at the end of a release, and this should be good enough. 6861 if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null && 6862 mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { 6863 return true; 6864 } 6865 } 6866 } 6867 } 6868 return false; 6869 } 6870 6871 public void getDisplaySize(Point size) { 6872 synchronized(mWindowMap) { 6873 size.x = mAppDisplayWidth; 6874 size.y = mAppDisplayHeight; 6875 } 6876 } 6877 6878 public void getRealDisplaySize(Point size) { 6879 synchronized(mWindowMap) { 6880 size.x = mCurDisplayWidth; 6881 size.y = mCurDisplayHeight; 6882 } 6883 } 6884 6885 public void getInitialDisplaySize(Point size) { 6886 synchronized(mWindowMap) { 6887 size.x = mInitialDisplayWidth; 6888 size.y = mInitialDisplayHeight; 6889 } 6890 } 6891 6892 public int getMaximumSizeDimension() { 6893 synchronized(mWindowMap) { 6894 // Do this based on the raw screen size, until we are smarter. 6895 return mBaseDisplayWidth > mBaseDisplayHeight 6896 ? mBaseDisplayWidth : mBaseDisplayHeight; 6897 } 6898 } 6899 6900 public void setForcedDisplaySize(int longDimen, int shortDimen) { 6901 synchronized(mWindowMap) { 6902 int width, height; 6903 if (mInitialDisplayWidth < mInitialDisplayHeight) { 6904 width = shortDimen < mInitialDisplayWidth 6905 ? shortDimen : mInitialDisplayWidth; 6906 height = longDimen < mInitialDisplayHeight 6907 ? longDimen : mInitialDisplayHeight; 6908 } else { 6909 width = longDimen < mInitialDisplayWidth 6910 ? longDimen : mInitialDisplayWidth; 6911 height = shortDimen < mInitialDisplayHeight 6912 ? shortDimen : mInitialDisplayHeight; 6913 } 6914 setForcedDisplaySizeLocked(width, height); 6915 Settings.Secure.putString(mContext.getContentResolver(), 6916 Settings.Secure.DISPLAY_SIZE_FORCED, width + "," + height); 6917 } 6918 } 6919 6920 private void rebuildBlackFrame(boolean inTransaction) { 6921 if (!inTransaction) { 6922 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 6923 ">>> OPEN TRANSACTION rebuildBlackFrame"); 6924 Surface.openTransaction(); 6925 } 6926 try { 6927 if (mBlackFrame != null) { 6928 mBlackFrame.kill(); 6929 mBlackFrame = null; 6930 } 6931 if (mBaseDisplayWidth < mInitialDisplayWidth 6932 || mBaseDisplayHeight < mInitialDisplayHeight) { 6933 int initW, initH, baseW, baseH; 6934 final boolean rotated = (mRotation == Surface.ROTATION_90 6935 || mRotation == Surface.ROTATION_270); 6936 if (rotated) { 6937 initW = mInitialDisplayHeight; 6938 initH = mInitialDisplayWidth; 6939 baseW = mBaseDisplayHeight; 6940 baseH = mBaseDisplayWidth; 6941 } else { 6942 initW = mInitialDisplayWidth; 6943 initH = mInitialDisplayHeight; 6944 baseW = mBaseDisplayWidth; 6945 baseH = mBaseDisplayHeight; 6946 } 6947 Rect outer = new Rect(0, 0, initW, initH); 6948 Rect inner = new Rect(0, 0, baseW, baseH); 6949 try { 6950 mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER); 6951 } catch (Surface.OutOfResourcesException e) { 6952 } 6953 } 6954 } finally { 6955 if (!inTransaction) { 6956 Surface.closeTransaction(); 6957 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 6958 "<<< CLOSE TRANSACTION rebuildBlackFrame"); 6959 } 6960 } 6961 } 6962 6963 private void readForcedDisplaySizeLocked() { 6964 final String str = Settings.Secure.getString(mContext.getContentResolver(), 6965 Settings.Secure.DISPLAY_SIZE_FORCED); 6966 if (str == null || str.length() == 0) { 6967 return; 6968 } 6969 final int pos = str.indexOf(','); 6970 if (pos <= 0 || str.lastIndexOf(',') != pos) { 6971 return; 6972 } 6973 int width, height; 6974 try { 6975 width = Integer.parseInt(str.substring(0, pos)); 6976 height = Integer.parseInt(str.substring(pos+1)); 6977 } catch (NumberFormatException ex) { 6978 return; 6979 } 6980 setForcedDisplaySizeLocked(width, height); 6981 } 6982 6983 private void setForcedDisplaySizeLocked(int width, int height) { 6984 Slog.i(TAG, "Using new display size: " + width + "x" + height); 6985 6986 mBaseDisplayWidth = width; 6987 mBaseDisplayHeight = height; 6988 mPolicy.setInitialDisplaySize(mBaseDisplayWidth, mBaseDisplayHeight); 6989 6990 mLayoutNeeded = true; 6991 6992 boolean configChanged = updateOrientationFromAppTokensLocked(false); 6993 mTempConfiguration.setToDefaults(); 6994 mTempConfiguration.fontScale = mCurConfiguration.fontScale; 6995 if (computeNewConfigurationLocked(mTempConfiguration)) { 6996 if (mCurConfiguration.diff(mTempConfiguration) != 0) { 6997 configChanged = true; 6998 } 6999 } 7000 7001 if (configChanged) { 7002 mWaitingForConfig = true; 7003 startFreezingDisplayLocked(false); 7004 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7005 } 7006 7007 rebuildBlackFrame(false); 7008 7009 performLayoutAndPlaceSurfacesLocked(); 7010 } 7011 7012 public void clearForcedDisplaySize() { 7013 synchronized(mWindowMap) { 7014 setForcedDisplaySizeLocked(mInitialDisplayWidth, mInitialDisplayHeight); 7015 Settings.Secure.putString(mContext.getContentResolver(), 7016 Settings.Secure.DISPLAY_SIZE_FORCED, ""); 7017 } 7018 } 7019 7020 public boolean canStatusBarHide() { 7021 return mPolicy.canStatusBarHide(); 7022 } 7023 7024 // ------------------------------------------------------------- 7025 // Internals 7026 // ------------------------------------------------------------- 7027 7028 final WindowState windowForClientLocked(Session session, IWindow client, 7029 boolean throwOnError) { 7030 return windowForClientLocked(session, client.asBinder(), throwOnError); 7031 } 7032 7033 final WindowState windowForClientLocked(Session session, IBinder client, 7034 boolean throwOnError) { 7035 WindowState win = mWindowMap.get(client); 7036 if (localLOGV) Slog.v( 7037 TAG, "Looking up client " + client + ": " + win); 7038 if (win == null) { 7039 RuntimeException ex = new IllegalArgumentException( 7040 "Requested window " + client + " does not exist"); 7041 if (throwOnError) { 7042 throw ex; 7043 } 7044 Slog.w(TAG, "Failed looking up window", ex); 7045 return null; 7046 } 7047 if (session != null && win.mSession != session) { 7048 RuntimeException ex = new IllegalArgumentException( 7049 "Requested window " + client + " is in session " + 7050 win.mSession + ", not " + session); 7051 if (throwOnError) { 7052 throw ex; 7053 } 7054 Slog.w(TAG, "Failed looking up window", ex); 7055 return null; 7056 } 7057 7058 return win; 7059 } 7060 7061 final void rebuildAppWindowListLocked() { 7062 int NW = mWindows.size(); 7063 int i; 7064 int lastWallpaper = -1; 7065 int numRemoved = 0; 7066 7067 if (mRebuildTmp.length < NW) { 7068 mRebuildTmp = new WindowState[NW+10]; 7069 } 7070 7071 // First remove all existing app windows. 7072 i=0; 7073 while (i < NW) { 7074 WindowState w = mWindows.get(i); 7075 if (w.mAppToken != null) { 7076 WindowState win = mWindows.remove(i); 7077 win.mRebuilding = true; 7078 mRebuildTmp[numRemoved] = win; 7079 mWindowsChanged = true; 7080 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, 7081 "Rebuild removing window: " + win); 7082 NW--; 7083 numRemoved++; 7084 continue; 7085 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER 7086 && lastWallpaper == i-1) { 7087 lastWallpaper = i; 7088 } 7089 i++; 7090 } 7091 7092 // The wallpaper window(s) typically live at the bottom of the stack, 7093 // so skip them before adding app tokens. 7094 lastWallpaper++; 7095 i = lastWallpaper; 7096 7097 // First add all of the exiting app tokens... these are no longer 7098 // in the main app list, but still have windows shown. We put them 7099 // in the back because now that the animation is over we no longer 7100 // will care about them. 7101 int NT = mExitingAppTokens.size(); 7102 for (int j=0; j<NT; j++) { 7103 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j)); 7104 } 7105 7106 // And add in the still active app tokens in Z order. 7107 NT = mAppTokens.size(); 7108 for (int j=0; j<NT; j++) { 7109 i = reAddAppWindowsLocked(i, mAppTokens.get(j)); 7110 } 7111 7112 i -= lastWallpaper; 7113 if (i != numRemoved) { 7114 Slog.w(TAG, "Rebuild removed " + numRemoved 7115 + " windows but added " + i); 7116 for (i=0; i<numRemoved; i++) { 7117 WindowState ws = mRebuildTmp[i]; 7118 if (ws.mRebuilding) { 7119 StringWriter sw = new StringWriter(); 7120 PrintWriter pw = new PrintWriter(sw); 7121 ws.dump(pw, "", true); 7122 pw.flush(); 7123 Slog.w(TAG, "This window was lost: " + ws); 7124 Slog.w(TAG, sw.toString()); 7125 } 7126 } 7127 Slog.w(TAG, "Current app token list:"); 7128 dumpAppTokensLocked(); 7129 Slog.w(TAG, "Final window list:"); 7130 dumpWindowsLocked(); 7131 } 7132 } 7133 7134 private final void assignLayersLocked() { 7135 int N = mWindows.size(); 7136 int curBaseLayer = 0; 7137 int curLayer = 0; 7138 int i; 7139 7140 if (DEBUG_LAYERS) { 7141 RuntimeException here = new RuntimeException("here"); 7142 here.fillInStackTrace(); 7143 Slog.v(TAG, "Assigning layers", here); 7144 } 7145 7146 for (i=0; i<N; i++) { 7147 WindowState w = mWindows.get(i); 7148 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow 7149 || (i > 0 && w.mIsWallpaper)) { 7150 curLayer += WINDOW_LAYER_MULTIPLIER; 7151 w.mLayer = curLayer; 7152 } else { 7153 curBaseLayer = curLayer = w.mBaseLayer; 7154 w.mLayer = curLayer; 7155 } 7156 if (w.mTargetAppToken != null) { 7157 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment; 7158 } else if (w.mAppToken != null) { 7159 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment; 7160 } else { 7161 w.mAnimLayer = w.mLayer; 7162 } 7163 if (w.mIsImWindow) { 7164 w.mAnimLayer += mInputMethodAnimLayerAdjustment; 7165 } else if (w.mIsWallpaper) { 7166 w.mAnimLayer += mWallpaperAnimLayerAdjustment; 7167 } 7168 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " 7169 + w.mAnimLayer); 7170 //System.out.println( 7171 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); 7172 } 7173 } 7174 7175 private boolean mInLayout = false; 7176 private final void performLayoutAndPlaceSurfacesLocked() { 7177 if (mInLayout) { 7178 if (DEBUG) { 7179 throw new RuntimeException("Recursive call!"); 7180 } 7181 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout"); 7182 return; 7183 } 7184 7185 if (mWaitingForConfig) { 7186 // Our configuration has changed (most likely rotation), but we 7187 // don't yet have the complete configuration to report to 7188 // applications. Don't do any window layout until we have it. 7189 return; 7190 } 7191 7192 if (mDisplay == null) { 7193 // Not yet initialized, nothing to do. 7194 return; 7195 } 7196 7197 mInLayout = true; 7198 boolean recoveringMemory = false; 7199 7200 try { 7201 if (mForceRemoves != null) { 7202 recoveringMemory = true; 7203 // Wait a little bit for things to settle down, and off we go. 7204 for (int i=0; i<mForceRemoves.size(); i++) { 7205 WindowState ws = mForceRemoves.get(i); 7206 Slog.i(TAG, "Force removing: " + ws); 7207 removeWindowInnerLocked(ws.mSession, ws); 7208 } 7209 mForceRemoves = null; 7210 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); 7211 Object tmp = new Object(); 7212 synchronized (tmp) { 7213 try { 7214 tmp.wait(250); 7215 } catch (InterruptedException e) { 7216 } 7217 } 7218 } 7219 } catch (RuntimeException e) { 7220 Log.wtf(TAG, "Unhandled exception while force removing for memory", e); 7221 } 7222 7223 try { 7224 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); 7225 7226 int N = mPendingRemove.size(); 7227 if (N > 0) { 7228 if (mPendingRemoveTmp.length < N) { 7229 mPendingRemoveTmp = new WindowState[N+10]; 7230 } 7231 mPendingRemove.toArray(mPendingRemoveTmp); 7232 mPendingRemove.clear(); 7233 for (int i=0; i<N; i++) { 7234 WindowState w = mPendingRemoveTmp[i]; 7235 removeWindowInnerLocked(w.mSession, w); 7236 } 7237 7238 mInLayout = false; 7239 assignLayersLocked(); 7240 mLayoutNeeded = true; 7241 performLayoutAndPlaceSurfacesLocked(); 7242 7243 } else { 7244 mInLayout = false; 7245 if (mLayoutNeeded) { 7246 requestAnimationLocked(0); 7247 } 7248 } 7249 if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { 7250 mH.removeMessages(H.REPORT_WINDOWS_CHANGE); 7251 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE)); 7252 } 7253 } catch (RuntimeException e) { 7254 mInLayout = false; 7255 Log.wtf(TAG, "Unhandled exception while laying out windows", e); 7256 } 7257 } 7258 7259 private final int performLayoutLockedInner(boolean initial, boolean updateInputWindows) { 7260 if (!mLayoutNeeded) { 7261 return 0; 7262 } 7263 7264 mLayoutNeeded = false; 7265 7266 final int dw = mCurDisplayWidth; 7267 final int dh = mCurDisplayHeight; 7268 7269 final int NFW = mFakeWindows.size(); 7270 for (int i=0; i<NFW; i++) { 7271 mFakeWindows.get(i).layout(dw, dh); 7272 } 7273 7274 final int N = mWindows.size(); 7275 int i; 7276 7277 if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed=" 7278 + mLayoutNeeded + " dw=" + dw + " dh=" + dh); 7279 7280 mPolicy.beginLayoutLw(dw, dh, mRotation); 7281 7282 int seq = mLayoutSeq+1; 7283 if (seq < 0) seq = 0; 7284 mLayoutSeq = seq; 7285 7286 // First perform layout of any root windows (not attached 7287 // to another window). 7288 int topAttached = -1; 7289 for (i = N-1; i >= 0; i--) { 7290 WindowState win = mWindows.get(i); 7291 7292 // Don't do layout of a window if it is not visible, or 7293 // soon won't be visible, to avoid wasting time and funky 7294 // changes while a window is animating away. 7295 final AppWindowToken atoken = win.mAppToken; 7296 final boolean gone = win.mViewVisibility == View.GONE 7297 || !win.mRelayoutCalled 7298 || (atoken == null && win.mRootToken.hidden) 7299 || (atoken != null && atoken.hiddenRequested) 7300 || win.mAttachedHidden 7301 || win.mExiting || win.mDestroying; 7302 7303 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 7304 Slog.v(TAG, "First pass " + win 7305 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 7306 + " mLayoutAttached=" + win.mLayoutAttached); 7307 if (gone) Slog.v(TAG, " (mViewVisibility=" 7308 + win.mViewVisibility + " mRelayoutCalled=" 7309 + win.mRelayoutCalled + " hidden=" 7310 + win.mRootToken.hidden + " hiddenRequested=" 7311 + (atoken != null && atoken.hiddenRequested) 7312 + " mAttachedHidden=" + win.mAttachedHidden); 7313 } 7314 7315 // If this view is GONE, then skip it -- keep the current 7316 // frame, and let the caller know so they can ignore it 7317 // if they want. (We do the normal layout for INVISIBLE 7318 // windows, since that means "perform layout as normal, 7319 // just don't display"). 7320 if (!gone || !win.mHaveFrame) { 7321 if (!win.mLayoutAttached) { 7322 if (initial) { 7323 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7324 win.mContentChanged = false; 7325 } 7326 win.prelayout(); 7327 mPolicy.layoutWindowLw(win, win.mAttrs, null); 7328 win.mLayoutSeq = seq; 7329 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame=" 7330 + win.mFrame + " mContainingFrame=" 7331 + win.mContainingFrame + " mDisplayFrame=" 7332 + win.mDisplayFrame); 7333 } else { 7334 if (topAttached < 0) topAttached = i; 7335 } 7336 } 7337 } 7338 7339 // Now perform layout of attached windows, which usually 7340 // depend on the position of the window they are attached to. 7341 // XXX does not deal with windows that are attached to windows 7342 // that are themselves attached. 7343 for (i = topAttached; i >= 0; i--) { 7344 WindowState win = mWindows.get(i); 7345 7346 if (win.mLayoutAttached) { 7347 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win 7348 + " mHaveFrame=" + win.mHaveFrame 7349 + " mViewVisibility=" + win.mViewVisibility 7350 + " mRelayoutCalled=" + win.mRelayoutCalled); 7351 // If this view is GONE, then skip it -- keep the current 7352 // frame, and let the caller know so they can ignore it 7353 // if they want. (We do the normal layout for INVISIBLE 7354 // windows, since that means "perform layout as normal, 7355 // just don't display"). 7356 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) 7357 || !win.mHaveFrame) { 7358 if (initial) { 7359 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 7360 win.mContentChanged = false; 7361 } 7362 win.prelayout(); 7363 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); 7364 win.mLayoutSeq = seq; 7365 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame=" 7366 + win.mFrame + " mContainingFrame=" 7367 + win.mContainingFrame + " mDisplayFrame=" 7368 + win.mDisplayFrame); 7369 } 7370 } 7371 } 7372 7373 // Window frames may have changed. Tell the input dispatcher about it. 7374 mInputMonitor.setUpdateInputWindowsNeededLw(); 7375 if (updateInputWindows) { 7376 mInputMonitor.updateInputWindowsLw(false /*force*/); 7377 } 7378 7379 return mPolicy.finishLayoutLw(); 7380 } 7381 7382 void makeWindowFreezingScreenIfNeededLocked(WindowState w) { 7383 // If the screen is currently frozen or off, then keep 7384 // it frozen/off until this window draws at its new 7385 // orientation. 7386 if (mDisplayFrozen || !mPolicy.isScreenOnFully()) { 7387 if (DEBUG_ORIENTATION) Slog.v(TAG, 7388 "Changing surface while display frozen: " + w); 7389 w.mOrientationChanging = true; 7390 if (!mWindowsFreezingScreen) { 7391 mWindowsFreezingScreen = true; 7392 // XXX should probably keep timeout from 7393 // when we first froze the display. 7394 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 7395 mH.sendMessageDelayed(mH.obtainMessage( 7396 H.WINDOW_FREEZE_TIMEOUT), 2000); 7397 } 7398 } 7399 } 7400 7401 // "Something has changed! Let's make it correct now." 7402 private final void performLayoutAndPlaceSurfacesLockedInner( 7403 boolean recoveringMemory) { 7404 if (mDisplay == null) { 7405 Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay"); 7406 return; 7407 } 7408 7409 final long currentTime = SystemClock.uptimeMillis(); 7410 final int dw = mCurDisplayWidth; 7411 final int dh = mCurDisplayHeight; 7412 final int innerDw = mAppDisplayWidth; 7413 final int innerDh = mAppDisplayHeight; 7414 7415 int i; 7416 7417 if (mFocusMayChange) { 7418 mFocusMayChange = false; 7419 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 7420 false /*updateInputWindows*/); 7421 } 7422 7423 // Initialize state of exiting tokens. 7424 for (i=mExitingTokens.size()-1; i>=0; i--) { 7425 mExitingTokens.get(i).hasVisible = false; 7426 } 7427 7428 // Initialize state of exiting applications. 7429 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 7430 mExitingAppTokens.get(i).hasVisible = false; 7431 } 7432 7433 boolean orientationChangeComplete = true; 7434 Session holdScreen = null; 7435 float screenBrightness = -1; 7436 float buttonBrightness = -1; 7437 boolean focusDisplayed = false; 7438 boolean animating = false; 7439 boolean createWatermark = false; 7440 boolean updateRotation = false; 7441 boolean screenRotationFinished = false; 7442 7443 if (mFxSession == null) { 7444 mFxSession = new SurfaceSession(); 7445 createWatermark = true; 7446 } 7447 7448 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 7449 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 7450 7451 Surface.openTransaction(); 7452 7453 if (createWatermark) { 7454 createWatermark(); 7455 } 7456 if (mWatermark != null) { 7457 mWatermark.positionSurface(dw, dh); 7458 } 7459 if (mStrictModeFlash != null) { 7460 mStrictModeFlash.positionSurface(dw, dh); 7461 } 7462 7463 try { 7464 boolean wallpaperForceHidingChanged = false; 7465 int repeats = 0; 7466 int changes = 0; 7467 7468 do { 7469 repeats++; 7470 if (repeats > 6) { 7471 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 7472 mLayoutNeeded = false; 7473 break; 7474 } 7475 7476 if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER 7477 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG 7478 | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) { 7479 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 7480 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 7481 assignLayersLocked(); 7482 mLayoutNeeded = true; 7483 } 7484 } 7485 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { 7486 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 7487 if (updateOrientationFromAppTokensLocked(true)) { 7488 mLayoutNeeded = true; 7489 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 7490 } 7491 } 7492 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 7493 mLayoutNeeded = true; 7494 } 7495 } 7496 7497 // FIRST LOOP: Perform a layout, if needed. 7498 if (repeats < 4) { 7499 changes = performLayoutLockedInner(repeats == 0, false /*updateInputWindows*/); 7500 if (changes != 0) { 7501 continue; 7502 } 7503 } else { 7504 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 7505 changes = 0; 7506 } 7507 7508 final int transactionSequence = ++mTransactionSequence; 7509 7510 // Update animations of all applications, including those 7511 // associated with exiting/removed apps 7512 boolean tokensAnimating = false; 7513 final int NAT = mAppTokens.size(); 7514 for (i=0; i<NAT; i++) { 7515 if (mAppTokens.get(i).stepAnimationLocked(currentTime, 7516 innerDw, innerDh)) { 7517 tokensAnimating = true; 7518 } 7519 } 7520 final int NEAT = mExitingAppTokens.size(); 7521 for (i=0; i<NEAT; i++) { 7522 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, 7523 innerDw, innerDh)) { 7524 tokensAnimating = true; 7525 } 7526 } 7527 7528 // SECOND LOOP: Execute animations and update visibility of windows. 7529 7530 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq=" 7531 + transactionSequence + " tokensAnimating=" 7532 + tokensAnimating); 7533 7534 animating = tokensAnimating; 7535 7536 if (mScreenRotationAnimation != null) { 7537 if (mScreenRotationAnimation.isAnimating()) { 7538 if (mScreenRotationAnimation.stepAnimation(currentTime)) { 7539 animating = true; 7540 } else { 7541 screenRotationFinished = true; 7542 updateRotation = true; 7543 } 7544 } 7545 } 7546 7547 boolean tokenMayBeDrawn = false; 7548 boolean wallpaperMayChange = false; 7549 boolean forceHiding = false; 7550 WindowState windowDetachedWallpaper = null; 7551 WindowState windowAnimationBackground = null; 7552 int windowAnimationBackgroundColor = 0; 7553 7554 mPolicy.beginAnimationLw(dw, dh); 7555 7556 final int N = mWindows.size(); 7557 7558 for (i=N-1; i>=0; i--) { 7559 WindowState w = mWindows.get(i); 7560 7561 final WindowManager.LayoutParams attrs = w.mAttrs; 7562 7563 if (w.mSurface != null) { 7564 // Take care of the window being ready to display. 7565 if (w.commitFinishDrawingLocked(currentTime)) { 7566 if ((w.mAttrs.flags 7567 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 7568 if (DEBUG_WALLPAPER) Slog.v(TAG, 7569 "First draw done in potential wallpaper target " + w); 7570 wallpaperMayChange = true; 7571 } 7572 } 7573 7574 final boolean wasAnimating = w.mAnimating; 7575 7576 int animDw = innerDw; 7577 int animDh = innerDh; 7578 7579 // If the window has moved due to its containing 7580 // content frame changing, then we'd like to animate 7581 // it. The checks here are ordered by what is least 7582 // likely to be true first. 7583 if (w.shouldAnimateMove()) { 7584 // Frame has moved, containing content frame 7585 // has also moved, and we're not currently animating... 7586 // let's do something. 7587 Animation a = AnimationUtils.loadAnimation(mContext, 7588 com.android.internal.R.anim.window_move_from_decor); 7589 w.setAnimation(a); 7590 animDw = w.mLastFrame.left - w.mFrame.left; 7591 animDh = w.mLastFrame.top - w.mFrame.top; 7592 } 7593 7594 // Execute animation. 7595 final boolean nowAnimating = w.stepAnimationLocked(currentTime, 7596 animDw, animDh); 7597 7598 // If this window is animating, make a note that we have 7599 // an animating window and take care of a request to run 7600 // a detached wallpaper animation. 7601 if (nowAnimating) { 7602 if (w.mAnimation != null) { 7603 if (w.mAnimation.getDetachWallpaper()) { 7604 windowDetachedWallpaper = w; 7605 } 7606 if (w.mAnimation.getBackgroundColor() != 0) { 7607 if (windowAnimationBackground == null || w.mAnimLayer < 7608 windowAnimationBackground.mAnimLayer) { 7609 windowAnimationBackground = w; 7610 windowAnimationBackgroundColor = 7611 w.mAnimation.getBackgroundColor(); 7612 } 7613 } 7614 } 7615 animating = true; 7616 } 7617 7618 // If this window's app token is running a detached wallpaper 7619 // animation, make a note so we can ensure the wallpaper is 7620 // displayed behind it. 7621 if (w.mAppToken != null && w.mAppToken.animation != null 7622 && w.mAppToken.animating) { 7623 if (w.mAppToken.animation.getDetachWallpaper()) { 7624 windowDetachedWallpaper = w; 7625 } 7626 if (w.mAppToken.animation.getBackgroundColor() != 0) { 7627 if (windowAnimationBackground == null || w.mAnimLayer < 7628 windowAnimationBackground.mAnimLayer) { 7629 windowAnimationBackground = w; 7630 windowAnimationBackgroundColor = 7631 w.mAppToken.animation.getBackgroundColor(); 7632 } 7633 } 7634 } 7635 7636 if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) { 7637 wallpaperMayChange = true; 7638 } 7639 7640 if (mPolicy.doesForceHide(w, attrs)) { 7641 if (!wasAnimating && nowAnimating) { 7642 if (DEBUG_VISIBILITY) Slog.v(TAG, 7643 "Animation started that could impact force hide: " 7644 + w); 7645 wallpaperForceHidingChanged = true; 7646 mFocusMayChange = true; 7647 } else if (w.isReadyForDisplay() && w.mAnimation == null) { 7648 forceHiding = true; 7649 } 7650 } else if (mPolicy.canBeForceHidden(w, attrs)) { 7651 boolean changed; 7652 if (forceHiding) { 7653 changed = w.hideLw(false, false); 7654 if (DEBUG_VISIBILITY && changed) Slog.v(TAG, 7655 "Now policy hidden: " + w); 7656 } else { 7657 changed = w.showLw(false, false); 7658 if (DEBUG_VISIBILITY && changed) Slog.v(TAG, 7659 "Now policy shown: " + w); 7660 if (changed) { 7661 if (wallpaperForceHidingChanged 7662 && w.isVisibleNow() /*w.isReadyForDisplay()*/) { 7663 // Assume we will need to animate. If 7664 // we don't (because the wallpaper will 7665 // stay with the lock screen), then we will 7666 // clean up later. 7667 Animation a = mPolicy.createForceHideEnterAnimation(); 7668 if (a != null) { 7669 w.setAnimation(a); 7670 } 7671 } 7672 if (mCurrentFocus == null || 7673 mCurrentFocus.mLayer < w.mLayer) { 7674 // We are showing on to of the current 7675 // focus, so re-evaluate focus to make 7676 // sure it is correct. 7677 mFocusMayChange = true; 7678 } 7679 } 7680 } 7681 if (changed && (attrs.flags 7682 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 7683 wallpaperMayChange = true; 7684 } 7685 } 7686 7687 mPolicy.animatingWindowLw(w, attrs); 7688 } 7689 7690 final AppWindowToken atoken = w.mAppToken; 7691 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) { 7692 if (atoken.lastTransactionSequence != transactionSequence) { 7693 atoken.lastTransactionSequence = transactionSequence; 7694 atoken.numInterestingWindows = atoken.numDrawnWindows = 0; 7695 atoken.startingDisplayed = false; 7696 } 7697 if ((w.isOnScreen() || w.mAttrs.type 7698 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION) 7699 && !w.mExiting && !w.mDestroying) { 7700 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 7701 Slog.v(TAG, "Eval win " + w + ": isDrawn=" 7702 + w.isDrawnLw() 7703 + ", isAnimating=" + w.isAnimating()); 7704 if (!w.isDrawnLw()) { 7705 Slog.v(TAG, "Not displayed: s=" + w.mSurface 7706 + " pv=" + w.mPolicyVisibility 7707 + " dp=" + w.mDrawPending 7708 + " cdp=" + w.mCommitDrawPending 7709 + " ah=" + w.mAttachedHidden 7710 + " th=" + atoken.hiddenRequested 7711 + " a=" + w.mAnimating); 7712 } 7713 } 7714 if (w != atoken.startingWindow) { 7715 if (!atoken.freezingScreen || !w.mAppFreezing) { 7716 atoken.numInterestingWindows++; 7717 if (w.isDrawnLw()) { 7718 atoken.numDrawnWindows++; 7719 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 7720 "tokenMayBeDrawn: " + atoken 7721 + " freezingScreen=" + atoken.freezingScreen 7722 + " mAppFreezing=" + w.mAppFreezing); 7723 tokenMayBeDrawn = true; 7724 } 7725 } 7726 } else if (w.isDrawnLw()) { 7727 atoken.startingDisplayed = true; 7728 } 7729 } 7730 } else if (w.mReadyToShow) { 7731 w.performShowLocked(); 7732 } 7733 } 7734 7735 changes |= mPolicy.finishAnimationLw(); 7736 7737 if (tokenMayBeDrawn) { 7738 // See if any windows have been drawn, so they (and others 7739 // associated with them) can now be shown. 7740 final int NT = mAppTokens.size(); 7741 for (i=0; i<NT; i++) { 7742 AppWindowToken wtoken = mAppTokens.get(i); 7743 if (wtoken.freezingScreen) { 7744 int numInteresting = wtoken.numInterestingWindows; 7745 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 7746 if (DEBUG_VISIBILITY) Slog.v(TAG, 7747 "allDrawn: " + wtoken 7748 + " interesting=" + numInteresting 7749 + " drawn=" + wtoken.numDrawnWindows); 7750 wtoken.showAllWindowsLocked(); 7751 unsetAppFreezingScreenLocked(wtoken, false, true); 7752 if (DEBUG_ORIENTATION) Slog.i(TAG, 7753 "Setting orientationChangeComplete=true because wtoken " 7754 + wtoken + " numInteresting=" + numInteresting 7755 + " numDrawn=" + wtoken.numDrawnWindows); 7756 orientationChangeComplete = true; 7757 } 7758 } else if (!wtoken.allDrawn) { 7759 int numInteresting = wtoken.numInterestingWindows; 7760 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { 7761 if (DEBUG_VISIBILITY) Slog.v(TAG, 7762 "allDrawn: " + wtoken 7763 + " interesting=" + numInteresting 7764 + " drawn=" + wtoken.numDrawnWindows); 7765 wtoken.allDrawn = true; 7766 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 7767 7768 // We can now show all of the drawn windows! 7769 if (!mOpeningApps.contains(wtoken)) { 7770 wtoken.showAllWindowsLocked(); 7771 } 7772 } 7773 } 7774 } 7775 } 7776 7777 // If we are ready to perform an app transition, check through 7778 // all of the app tokens to be shown and see if they are ready 7779 // to go. 7780 if (mAppTransitionReady) { 7781 int NN = mOpeningApps.size(); 7782 boolean goodToGo = true; 7783 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7784 "Checking " + NN + " opening apps (frozen=" 7785 + mDisplayFrozen + " timeout=" 7786 + mAppTransitionTimeout + ")..."); 7787 if (!mDisplayFrozen && !mAppTransitionTimeout) { 7788 // If the display isn't frozen, wait to do anything until 7789 // all of the apps are ready. Otherwise just go because 7790 // we'll unfreeze the display when everyone is ready. 7791 for (i=0; i<NN && goodToGo; i++) { 7792 AppWindowToken wtoken = mOpeningApps.get(i); 7793 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7794 "Check opening app" + wtoken + ": allDrawn=" 7795 + wtoken.allDrawn + " startingDisplayed=" 7796 + wtoken.startingDisplayed); 7797 if (!wtoken.allDrawn && !wtoken.startingDisplayed 7798 && !wtoken.startingMoved) { 7799 goodToGo = false; 7800 } 7801 } 7802 } 7803 if (goodToGo) { 7804 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); 7805 int transit = mNextAppTransition; 7806 if (mSkipAppTransitionAnimation) { 7807 transit = WindowManagerPolicy.TRANSIT_UNSET; 7808 } 7809 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 7810 mAppTransitionReady = false; 7811 mAppTransitionRunning = true; 7812 mAppTransitionTimeout = false; 7813 mStartingIconInTransition = false; 7814 mSkipAppTransitionAnimation = false; 7815 7816 mH.removeMessages(H.APP_TRANSITION_TIMEOUT); 7817 7818 // If there are applications waiting to come to the 7819 // top of the stack, now is the time to move their windows. 7820 // (Note that we don't do apps going to the bottom 7821 // here -- we want to keep their windows in the old 7822 // Z-order until the animation completes.) 7823 if (mToTopApps.size() > 0) { 7824 NN = mAppTokens.size(); 7825 for (i=0; i<NN; i++) { 7826 AppWindowToken wtoken = mAppTokens.get(i); 7827 if (wtoken.sendingToTop) { 7828 wtoken.sendingToTop = false; 7829 moveAppWindowsLocked(wtoken, NN, false); 7830 } 7831 } 7832 mToTopApps.clear(); 7833 } 7834 7835 WindowState oldWallpaper = mWallpaperTarget; 7836 7837 adjustWallpaperWindowsLocked(); 7838 wallpaperMayChange = false; 7839 7840 // The top-most window will supply the layout params, 7841 // and we will determine it below. 7842 LayoutParams animLp = null; 7843 int bestAnimLayer = -1; 7844 boolean fullscreenAnim = false; 7845 7846 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7847 "New wallpaper target=" + mWallpaperTarget 7848 + ", lower target=" + mLowerWallpaperTarget 7849 + ", upper target=" + mUpperWallpaperTarget); 7850 int foundWallpapers = 0; 7851 // Do a first pass through the tokens for two 7852 // things: 7853 // (1) Determine if both the closing and opening 7854 // app token sets are wallpaper targets, in which 7855 // case special animations are needed 7856 // (since the wallpaper needs to stay static 7857 // behind them). 7858 // (2) Find the layout params of the top-most 7859 // application window in the tokens, which is 7860 // what will control the animation theme. 7861 final int NC = mClosingApps.size(); 7862 NN = NC + mOpeningApps.size(); 7863 for (i=0; i<NN; i++) { 7864 AppWindowToken wtoken; 7865 int mode; 7866 if (i < NC) { 7867 wtoken = mClosingApps.get(i); 7868 mode = 1; 7869 } else { 7870 wtoken = mOpeningApps.get(i-NC); 7871 mode = 2; 7872 } 7873 if (mLowerWallpaperTarget != null) { 7874 if (mLowerWallpaperTarget.mAppToken == wtoken 7875 || mUpperWallpaperTarget.mAppToken == wtoken) { 7876 foundWallpapers |= mode; 7877 } 7878 } 7879 if (wtoken.appFullscreen) { 7880 WindowState ws = wtoken.findMainWindow(); 7881 if (ws != null) { 7882 animLp = ws.mAttrs; 7883 bestAnimLayer = ws.mLayer; 7884 fullscreenAnim = true; 7885 } 7886 } else if (!fullscreenAnim) { 7887 WindowState ws = wtoken.findMainWindow(); 7888 if (ws != null) { 7889 if (ws.mLayer > bestAnimLayer) { 7890 animLp = ws.mAttrs; 7891 bestAnimLayer = ws.mLayer; 7892 } 7893 } 7894 } 7895 } 7896 7897 if (foundWallpapers == 3) { 7898 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7899 "Wallpaper animation!"); 7900 switch (transit) { 7901 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: 7902 case WindowManagerPolicy.TRANSIT_TASK_OPEN: 7903 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: 7904 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN; 7905 break; 7906 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: 7907 case WindowManagerPolicy.TRANSIT_TASK_CLOSE: 7908 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: 7909 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE; 7910 break; 7911 } 7912 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7913 "New transit: " + transit); 7914 } else if (oldWallpaper != null) { 7915 // We are transitioning from an activity with 7916 // a wallpaper to one without. 7917 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE; 7918 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7919 "New transit away from wallpaper: " + transit); 7920 } else if (mWallpaperTarget != null) { 7921 // We are transitioning from an activity without 7922 // a wallpaper to now showing the wallpaper 7923 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN; 7924 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7925 "New transit into wallpaper: " + transit); 7926 } 7927 7928 // If all closing windows are obscured, then there is 7929 // no need to do an animation. This is the case, for 7930 // example, when this transition is being done behind 7931 // the lock screen. 7932 if (!mPolicy.allowAppAnimationsLw()) { 7933 animLp = null; 7934 } 7935 7936 NN = mOpeningApps.size(); 7937 for (i=0; i<NN; i++) { 7938 AppWindowToken wtoken = mOpeningApps.get(i); 7939 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7940 "Now opening app" + wtoken); 7941 wtoken.reportedVisible = false; 7942 wtoken.inPendingTransaction = false; 7943 wtoken.animation = null; 7944 setTokenVisibilityLocked(wtoken, animLp, true, 7945 transit, false); 7946 wtoken.updateReportedVisibilityLocked(); 7947 wtoken.waitingToShow = false; 7948 wtoken.showAllWindowsLocked(); 7949 } 7950 NN = mClosingApps.size(); 7951 for (i=0; i<NN; i++) { 7952 AppWindowToken wtoken = mClosingApps.get(i); 7953 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, 7954 "Now closing app" + wtoken); 7955 wtoken.inPendingTransaction = false; 7956 wtoken.animation = null; 7957 setTokenVisibilityLocked(wtoken, animLp, false, 7958 transit, false); 7959 wtoken.updateReportedVisibilityLocked(); 7960 wtoken.waitingToHide = false; 7961 // Force the allDrawn flag, because we want to start 7962 // this guy's animations regardless of whether it's 7963 // gotten drawn. 7964 wtoken.allDrawn = true; 7965 } 7966 7967 mNextAppTransitionPackage = null; 7968 7969 mOpeningApps.clear(); 7970 mClosingApps.clear(); 7971 7972 // This has changed the visibility of windows, so perform 7973 // a new layout to get them all up-to-date. 7974 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT 7975 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 7976 mLayoutNeeded = true; 7977 if (!moveInputMethodWindowsIfNeededLocked(true)) { 7978 assignLayersLocked(); 7979 } 7980 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 7981 false /*updateInputWindows*/); 7982 mFocusMayChange = false; 7983 } 7984 } 7985 7986 int adjResult = 0; 7987 7988 if (!animating && mAppTransitionRunning) { 7989 // We have finished the animation of an app transition. To do 7990 // this, we have delayed a lot of operations like showing and 7991 // hiding apps, moving apps in Z-order, etc. The app token list 7992 // reflects the correct Z-order, but the window list may now 7993 // be out of sync with it. So here we will just rebuild the 7994 // entire app window list. Fun! 7995 mAppTransitionRunning = false; 7996 // Clear information about apps that were moving. 7997 mToBottomApps.clear(); 7998 7999 rebuildAppWindowListLocked(); 8000 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8001 adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED; 8002 moveInputMethodWindowsIfNeededLocked(false); 8003 wallpaperMayChange = true; 8004 // Since the window list has been rebuilt, focus might 8005 // have to be recomputed since the actual order of windows 8006 // might have changed again. 8007 mFocusMayChange = true; 8008 } 8009 8010 if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) { 8011 // At this point, there was a window with a wallpaper that 8012 // was force hiding other windows behind it, but now it 8013 // is going away. This may be simple -- just animate 8014 // away the wallpaper and its window -- or it may be 8015 // hard -- the wallpaper now needs to be shown behind 8016 // something that was hidden. 8017 WindowState oldWallpaper = mWallpaperTarget; 8018 if (mLowerWallpaperTarget != null 8019 && mLowerWallpaperTarget.mAppToken != null) { 8020 if (DEBUG_WALLPAPER) Slog.v(TAG, 8021 "wallpaperForceHiding changed with lower=" 8022 + mLowerWallpaperTarget); 8023 if (DEBUG_WALLPAPER) Slog.v(TAG, 8024 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden + 8025 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested); 8026 if (mLowerWallpaperTarget.mAppToken.hidden) { 8027 // The lower target has become hidden before we 8028 // actually started the animation... let's completely 8029 // re-evaluate everything. 8030 mLowerWallpaperTarget = mUpperWallpaperTarget = null; 8031 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8032 } 8033 } 8034 adjResult |= adjustWallpaperWindowsLocked(); 8035 wallpaperMayChange = false; 8036 wallpaperForceHidingChanged = false; 8037 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper 8038 + " NEW: " + mWallpaperTarget 8039 + " LOWER: " + mLowerWallpaperTarget); 8040 if (mLowerWallpaperTarget == null) { 8041 // Whoops, we don't need a special wallpaper animation. 8042 // Clear them out. 8043 forceHiding = false; 8044 for (i=N-1; i>=0; i--) { 8045 WindowState w = mWindows.get(i); 8046 if (w.mSurface != null) { 8047 final WindowManager.LayoutParams attrs = w.mAttrs; 8048 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) { 8049 if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows"); 8050 forceHiding = true; 8051 } else if (mPolicy.canBeForceHidden(w, attrs)) { 8052 if (!w.mAnimating) { 8053 // We set the animation above so it 8054 // is not yet running. 8055 w.clearAnimation(); 8056 } 8057 } 8058 } 8059 } 8060 } 8061 } 8062 8063 if (mWindowDetachedWallpaper != windowDetachedWallpaper) { 8064 if (DEBUG_WALLPAPER) Slog.v(TAG, 8065 "Detached wallpaper changed from " + mWindowDetachedWallpaper 8066 + " to " + windowDetachedWallpaper); 8067 mWindowDetachedWallpaper = windowDetachedWallpaper; 8068 wallpaperMayChange = true; 8069 } 8070 8071 if (windowAnimationBackgroundColor != 0) { 8072 // If the window that wants black is the current wallpaper 8073 // target, then the black goes *below* the wallpaper so we 8074 // don't cause the wallpaper to suddenly disappear. 8075 WindowState target = windowAnimationBackground; 8076 if (mWallpaperTarget == windowAnimationBackground 8077 || mLowerWallpaperTarget == windowAnimationBackground 8078 || mUpperWallpaperTarget == windowAnimationBackground) { 8079 for (i=0; i<mWindows.size(); i++) { 8080 WindowState w = mWindows.get(i); 8081 if (w.mIsWallpaper) { 8082 target = w; 8083 break; 8084 } 8085 } 8086 } 8087 if (mWindowAnimationBackgroundSurface == null) { 8088 mWindowAnimationBackgroundSurface = new DimSurface(mFxSession); 8089 } 8090 mWindowAnimationBackgroundSurface.show(dw, dh, 8091 target.mAnimLayer - LAYER_OFFSET_DIM, 8092 windowAnimationBackgroundColor); 8093 } else if (mWindowAnimationBackgroundSurface != null) { 8094 mWindowAnimationBackgroundSurface.hide(); 8095 } 8096 8097 if (wallpaperMayChange) { 8098 if (DEBUG_WALLPAPER) Slog.v(TAG, 8099 "Wallpaper may change! Adjusting"); 8100 adjResult |= adjustWallpaperWindowsLocked(); 8101 } 8102 8103 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { 8104 if (DEBUG_WALLPAPER) Slog.v(TAG, 8105 "Wallpaper layer changed: assigning layers + relayout"); 8106 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8107 assignLayersLocked(); 8108 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { 8109 if (DEBUG_WALLPAPER) Slog.v(TAG, 8110 "Wallpaper visibility changed: relayout"); 8111 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8112 } 8113 8114 if (mFocusMayChange) { 8115 mFocusMayChange = false; 8116 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 8117 false /*updateInputWindows*/)) { 8118 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; 8119 adjResult = 0; 8120 } 8121 } 8122 8123 if (mLayoutNeeded) { 8124 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; 8125 } 8126 8127 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x" 8128 + Integer.toHexString(changes)); 8129 } while (changes != 0); 8130 8131 // THIRD LOOP: Update the surfaces of all windows. 8132 8133 final boolean someoneLosingFocus = mLosingFocus.size() != 0; 8134 8135 boolean obscured = false; 8136 boolean blurring = false; 8137 boolean dimming = false; 8138 boolean covered = false; 8139 boolean syswin = false; 8140 8141 final int N = mWindows.size(); 8142 8143 for (i=N-1; i>=0; i--) { 8144 WindowState w = mWindows.get(i); 8145 8146 boolean displayed = false; 8147 final WindowManager.LayoutParams attrs = w.mAttrs; 8148 final int attrFlags = attrs.flags; 8149 8150 if (w.mSurface != null) { 8151 // XXX NOTE: The logic here could be improved. We have 8152 // the decision about whether to resize a window separated 8153 // from whether to hide the surface. This can cause us to 8154 // resize a surface even if we are going to hide it. You 8155 // can see this by (1) holding device in landscape mode on 8156 // home screen; (2) tapping browser icon (device will rotate 8157 // to landscape; (3) tap home. The wallpaper will be resized 8158 // in step 2 but then immediately hidden, causing us to 8159 // have to resize and then redraw it again in step 3. It 8160 // would be nice to figure out how to avoid this, but it is 8161 // difficult because we do need to resize surfaces in some 8162 // cases while they are hidden such as when first showing a 8163 // window. 8164 8165 w.computeShownFrameLocked(); 8166 if (localLOGV) Slog.v( 8167 TAG, "Placing surface #" + i + " " + w.mSurface 8168 + ": new=" + w.mShownFrame); 8169 8170 if (w.mSurface != null) { 8171 int width, height; 8172 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) { 8173 // for a scaled surface, we just want to use 8174 // the requested size. 8175 width = w.mRequestedWidth; 8176 height = w.mRequestedHeight; 8177 } else { 8178 width = w.mCompatFrame.width(); 8179 height = w.mCompatFrame.height(); 8180 } 8181 8182 if (width < 1) { 8183 width = 1; 8184 } 8185 if (height < 1) { 8186 height = 1; 8187 } 8188 final boolean surfaceResized = w.mSurfaceW != width || w.mSurfaceH != height; 8189 if (surfaceResized) { 8190 w.mSurfaceW = width; 8191 w.mSurfaceH = height; 8192 } 8193 8194 if (w.mSurfaceX != w.mShownFrame.left 8195 || w.mSurfaceY != w.mShownFrame.top) { 8196 try { 8197 if (SHOW_TRANSACTIONS) logSurface(w, 8198 "POS " + w.mShownFrame.left 8199 + ", " + w.mShownFrame.top, null); 8200 w.mSurfaceX = w.mShownFrame.left; 8201 w.mSurfaceY = w.mShownFrame.top; 8202 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top); 8203 } catch (RuntimeException e) { 8204 Slog.w(TAG, "Error positioning surface of " + w 8205 + " pos=(" + w.mShownFrame.left 8206 + "," + w.mShownFrame.top + ")", e); 8207 if (!recoveringMemory) { 8208 reclaimSomeSurfaceMemoryLocked(w, "position", true); 8209 } 8210 } 8211 } 8212 8213 if (surfaceResized) { 8214 try { 8215 if (SHOW_TRANSACTIONS) logSurface(w, 8216 "SIZE " + width + "x" + height, null); 8217 w.mSurfaceResized = true; 8218 w.mSurface.setSize(width, height); 8219 } catch (RuntimeException e) { 8220 // If something goes wrong with the surface (such 8221 // as running out of memory), don't take down the 8222 // entire system. 8223 Slog.e(TAG, "Error resizing surface of " + w 8224 + " size=(" + width + "x" + height + ")", e); 8225 if (!recoveringMemory) { 8226 reclaimSomeSurfaceMemoryLocked(w, "size", true); 8227 } 8228 } 8229 } 8230 } 8231 8232 if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) { 8233 w.mContentInsetsChanged |= 8234 !w.mLastContentInsets.equals(w.mContentInsets); 8235 w.mVisibleInsetsChanged |= 8236 !w.mLastVisibleInsets.equals(w.mVisibleInsets); 8237 boolean configChanged = 8238 w.mConfiguration != mCurConfiguration 8239 && (w.mConfiguration == null 8240 || mCurConfiguration.diff(w.mConfiguration) != 0); 8241 if (DEBUG_CONFIGURATION && configChanged) { 8242 Slog.v(TAG, "Win " + w + " config changed: " 8243 + mCurConfiguration); 8244 } 8245 if (localLOGV) Slog.v(TAG, "Resizing " + w 8246 + ": configChanged=" + configChanged 8247 + " last=" + w.mLastFrame + " frame=" + w.mFrame); 8248 w.mLastFrame.set(w.mFrame); 8249 if (w.mContentInsetsChanged 8250 || w.mVisibleInsetsChanged 8251 || w.mSurfaceResized 8252 || configChanged) { 8253 if (DEBUG_RESIZE || DEBUG_ORIENTATION) { 8254 Slog.v(TAG, "Resize reasons: " 8255 + " contentInsetsChanged=" + w.mContentInsetsChanged 8256 + " visibleInsetsChanged=" + w.mVisibleInsetsChanged 8257 + " surfaceResized=" + w.mSurfaceResized 8258 + " configChanged=" + configChanged); 8259 } 8260 8261 w.mLastContentInsets.set(w.mContentInsets); 8262 w.mLastVisibleInsets.set(w.mVisibleInsets); 8263 makeWindowFreezingScreenIfNeededLocked(w); 8264 // If the orientation is changing, then we need to 8265 // hold off on unfreezing the display until this 8266 // window has been redrawn; to do that, we need 8267 // to go through the process of getting informed 8268 // by the application when it has finished drawing. 8269 if (w.mOrientationChanging) { 8270 if (DEBUG_ORIENTATION) Slog.v(TAG, 8271 "Orientation start waiting for draw in " 8272 + w + ", surface " + w.mSurface); 8273 w.mDrawPending = true; 8274 w.mCommitDrawPending = false; 8275 w.mReadyToShow = false; 8276 if (w.mAppToken != null) { 8277 w.mAppToken.allDrawn = false; 8278 } 8279 } 8280 if (!mResizingWindows.contains(w)) { 8281 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8282 "Resizing window " + w + " to " + w.mSurfaceW 8283 + "x" + w.mSurfaceH); 8284 mResizingWindows.add(w); 8285 } 8286 } else if (w.mOrientationChanging) { 8287 if (!w.mDrawPending && !w.mCommitDrawPending) { 8288 if (DEBUG_ORIENTATION) Slog.v(TAG, 8289 "Orientation not waiting for draw in " 8290 + w + ", surface " + w.mSurface); 8291 w.mOrientationChanging = false; 8292 } 8293 } 8294 } 8295 8296 if (w.mAttachedHidden || !w.isReadyForDisplay()) { 8297 if (!w.mLastHidden) { 8298 //dump(); 8299 w.mLastHidden = true; 8300 if (SHOW_TRANSACTIONS) logSurface(w, 8301 "HIDE (performLayout)", null); 8302 if (w.mSurface != null) { 8303 w.mSurfaceShown = false; 8304 try { 8305 w.mSurface.hide(); 8306 } catch (RuntimeException e) { 8307 Slog.w(TAG, "Exception hiding surface in " + w); 8308 } 8309 } 8310 } 8311 // If we are waiting for this window to handle an 8312 // orientation change, well, it is hidden, so 8313 // doesn't really matter. Note that this does 8314 // introduce a potential glitch if the window 8315 // becomes unhidden before it has drawn for the 8316 // new orientation. 8317 if (w.mOrientationChanging) { 8318 w.mOrientationChanging = false; 8319 if (DEBUG_ORIENTATION) Slog.v(TAG, 8320 "Orientation change skips hidden " + w); 8321 } 8322 } else if (w.mLastLayer != w.mAnimLayer 8323 || w.mLastAlpha != w.mShownAlpha 8324 || w.mLastDsDx != w.mDsDx 8325 || w.mLastDtDx != w.mDtDx 8326 || w.mLastDsDy != w.mDsDy 8327 || w.mLastDtDy != w.mDtDy 8328 || w.mLastHScale != w.mHScale 8329 || w.mLastVScale != w.mVScale 8330 || w.mLastHidden) { 8331 displayed = true; 8332 w.mLastAlpha = w.mShownAlpha; 8333 w.mLastLayer = w.mAnimLayer; 8334 w.mLastDsDx = w.mDsDx; 8335 w.mLastDtDx = w.mDtDx; 8336 w.mLastDsDy = w.mDsDy; 8337 w.mLastDtDy = w.mDtDy; 8338 w.mLastHScale = w.mHScale; 8339 w.mLastVScale = w.mVScale; 8340 if (SHOW_TRANSACTIONS) logSurface(w, 8341 "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer 8342 + " matrix=[" + (w.mDsDx*w.mHScale) 8343 + "," + (w.mDtDx*w.mVScale) 8344 + "][" + (w.mDsDy*w.mHScale) 8345 + "," + (w.mDtDy*w.mVScale) + "]", null); 8346 if (w.mSurface != null) { 8347 try { 8348 w.mSurfaceAlpha = w.mShownAlpha; 8349 w.mSurface.setAlpha(w.mShownAlpha); 8350 w.mSurfaceLayer = w.mAnimLayer; 8351 w.mSurface.setLayer(w.mAnimLayer); 8352 w.mSurface.setMatrix( 8353 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale, 8354 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale); 8355 } catch (RuntimeException e) { 8356 Slog.w(TAG, "Error updating surface in " + w, e); 8357 if (!recoveringMemory) { 8358 reclaimSomeSurfaceMemoryLocked(w, "update", true); 8359 } 8360 } 8361 } 8362 8363 if (w.mLastHidden && !w.mDrawPending 8364 && !w.mCommitDrawPending 8365 && !w.mReadyToShow) { 8366 if (SHOW_TRANSACTIONS) logSurface(w, 8367 "SHOW (performLayout)", null); 8368 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w 8369 + " during relayout"); 8370 if (showSurfaceRobustlyLocked(w)) { 8371 w.mHasDrawn = true; 8372 w.mLastHidden = false; 8373 } else { 8374 w.mOrientationChanging = false; 8375 } 8376 } 8377 if (w.mSurface != null) { 8378 w.mToken.hasVisible = true; 8379 } 8380 } else { 8381 displayed = true; 8382 } 8383 8384 if (displayed) { 8385 if (!covered) { 8386 if (attrs.width == LayoutParams.MATCH_PARENT 8387 && attrs.height == LayoutParams.MATCH_PARENT) { 8388 covered = true; 8389 } 8390 } 8391 if (w.mOrientationChanging) { 8392 if (w.mDrawPending || w.mCommitDrawPending) { 8393 orientationChangeComplete = false; 8394 if (DEBUG_ORIENTATION) Slog.v(TAG, 8395 "Orientation continue waiting for draw in " + w); 8396 } else { 8397 w.mOrientationChanging = false; 8398 if (DEBUG_ORIENTATION) Slog.v(TAG, 8399 "Orientation change complete in " + w); 8400 } 8401 } 8402 w.mToken.hasVisible = true; 8403 } 8404 } else if (w.mOrientationChanging) { 8405 if (DEBUG_ORIENTATION) Slog.v(TAG, 8406 "Orientation change skips hidden " + w); 8407 w.mOrientationChanging = false; 8408 } 8409 8410 if (w.mContentChanged) { 8411 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 8412 w.mContentChanged = false; 8413 } 8414 8415 final boolean canBeSeen = w.isDisplayedLw(); 8416 8417 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) { 8418 focusDisplayed = true; 8419 } 8420 8421 final boolean obscuredChanged = w.mObscured != obscured; 8422 8423 // Update effect. 8424 if (!(w.mObscured=obscured)) { 8425 if (w.mSurface != null) { 8426 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { 8427 holdScreen = w.mSession; 8428 } 8429 if (!syswin && w.mAttrs.screenBrightness >= 0 8430 && screenBrightness < 0) { 8431 screenBrightness = w.mAttrs.screenBrightness; 8432 } 8433 if (!syswin && w.mAttrs.buttonBrightness >= 0 8434 && buttonBrightness < 0) { 8435 buttonBrightness = w.mAttrs.buttonBrightness; 8436 } 8437 if (canBeSeen 8438 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG 8439 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD 8440 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) { 8441 syswin = true; 8442 } 8443 } 8444 8445 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); 8446 if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { 8447 // This window completely covers everything behind it, 8448 // so we want to leave all of them as unblurred (for 8449 // performance reasons). 8450 obscured = true; 8451 } else if (canBeSeen && !obscured && 8452 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) { 8453 if (localLOGV) Slog.v(TAG, "Win " + w 8454 + ": blurring=" + blurring 8455 + " obscured=" + obscured 8456 + " displayed=" + displayed); 8457 if ((attrFlags&FLAG_DIM_BEHIND) != 0) { 8458 if (!dimming) { 8459 //Slog.i(TAG, "DIM BEHIND: " + w); 8460 dimming = true; 8461 if (mDimAnimator == null) { 8462 mDimAnimator = new DimAnimator(mFxSession); 8463 } 8464 mDimAnimator.show(innerDw, innerDh); 8465 mDimAnimator.updateParameters(mContext.getResources(), 8466 w, currentTime); 8467 } 8468 } 8469 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) { 8470 if (!blurring) { 8471 //Slog.i(TAG, "BLUR BEHIND: " + w); 8472 blurring = true; 8473 if (mBlurSurface == null) { 8474 try { 8475 mBlurSurface = new Surface(mFxSession, 0, 8476 "BlurSurface", 8477 -1, 16, 16, 8478 PixelFormat.OPAQUE, 8479 Surface.FX_SURFACE_BLUR); 8480 } catch (Exception e) { 8481 Slog.e(TAG, "Exception creating Blur surface", e); 8482 } 8483 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " 8484 + mBlurSurface + ": CREATE"); 8485 } 8486 if (mBlurSurface != null) { 8487 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " 8488 + mBlurSurface + ": pos=(0,0) (" + 8489 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1)); 8490 mBlurSurface.setPosition(0, 0); 8491 mBlurSurface.setSize(dw, dh); 8492 mBlurSurface.setLayer(w.mAnimLayer-LAYER_OFFSET_BLUR); 8493 if (!mBlurShown) { 8494 try { 8495 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " 8496 + mBlurSurface + ": SHOW"); 8497 mBlurSurface.show(); 8498 } catch (RuntimeException e) { 8499 Slog.w(TAG, "Failure showing blur surface", e); 8500 } 8501 mBlurShown = true; 8502 } 8503 } 8504 } 8505 } 8506 } 8507 } 8508 8509 if (obscuredChanged && mWallpaperTarget == w) { 8510 // This is the wallpaper target and its obscured state 8511 // changed... make sure the current wallaper's visibility 8512 // has been updated accordingly. 8513 updateWallpaperVisibilityLocked(); 8514 } 8515 } 8516 8517 if (mDimAnimator != null && mDimAnimator.mDimShown) { 8518 animating |= mDimAnimator.updateSurface(dimming, currentTime, 8519 mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOnFully()); 8520 } 8521 8522 if (!blurring && mBlurShown) { 8523 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " + mBlurSurface 8524 + ": HIDE"); 8525 try { 8526 mBlurSurface.hide(); 8527 } catch (IllegalArgumentException e) { 8528 Slog.w(TAG, "Illegal argument exception hiding blur surface"); 8529 } 8530 mBlurShown = false; 8531 } 8532 8533 if (mBlackFrame != null) { 8534 if (mScreenRotationAnimation != null) { 8535 mBlackFrame.setMatrix( 8536 mScreenRotationAnimation.getEnterTransformation().getMatrix()); 8537 } else { 8538 mBlackFrame.clearMatrix(); 8539 } 8540 } 8541 } catch (RuntimeException e) { 8542 Log.wtf(TAG, "Unhandled exception in Window Manager", e); 8543 } 8544 8545 Surface.closeTransaction(); 8546 8547 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 8548 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 8549 8550 if (mWatermark != null) { 8551 mWatermark.drawIfNeeded(); 8552 } 8553 8554 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, 8555 "With display frozen, orientationChangeComplete=" 8556 + orientationChangeComplete); 8557 if (orientationChangeComplete) { 8558 if (mWindowsFreezingScreen) { 8559 mWindowsFreezingScreen = false; 8560 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); 8561 } 8562 stopFreezingDisplayLocked(); 8563 } 8564 8565 i = mResizingWindows.size(); 8566 if (i > 0) { 8567 do { 8568 i--; 8569 WindowState win = mResizingWindows.get(i); 8570 try { 8571 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, 8572 "Reporting new frame to " + win + ": " + win.mCompatFrame); 8573 int diff = 0; 8574 boolean configChanged = 8575 win.mConfiguration != mCurConfiguration 8576 && (win.mConfiguration == null 8577 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0); 8578 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) 8579 && configChanged) { 8580 Slog.i(TAG, "Sending new config to window " + win + ": " 8581 + win.mSurfaceW + "x" + win.mSurfaceH 8582 + " / " + mCurConfiguration + " / 0x" 8583 + Integer.toHexString(diff)); 8584 } 8585 win.mConfiguration = mCurConfiguration; 8586 if (DEBUG_ORIENTATION && win.mDrawPending) Slog.i( 8587 TAG, "Resizing " + win + " WITH DRAW PENDING"); 8588 win.mClient.resized((int)win.mSurfaceW, (int)win.mSurfaceH, 8589 win.mLastContentInsets, win.mLastVisibleInsets, win.mDrawPending, 8590 configChanged ? win.mConfiguration : null); 8591 win.mContentInsetsChanged = false; 8592 win.mVisibleInsetsChanged = false; 8593 win.mSurfaceResized = false; 8594 } catch (RemoteException e) { 8595 win.mOrientationChanging = false; 8596 } 8597 } while (i > 0); 8598 mResizingWindows.clear(); 8599 } 8600 8601 // Destroy the surface of any windows that are no longer visible. 8602 boolean wallpaperDestroyed = false; 8603 i = mDestroySurface.size(); 8604 if (i > 0) { 8605 do { 8606 i--; 8607 WindowState win = mDestroySurface.get(i); 8608 win.mDestroying = false; 8609 if (mInputMethodWindow == win) { 8610 mInputMethodWindow = null; 8611 } 8612 if (win == mWallpaperTarget) { 8613 wallpaperDestroyed = true; 8614 } 8615 win.destroySurfaceLocked(); 8616 } while (i > 0); 8617 mDestroySurface.clear(); 8618 } 8619 8620 // Time to remove any exiting tokens? 8621 for (i=mExitingTokens.size()-1; i>=0; i--) { 8622 WindowToken token = mExitingTokens.get(i); 8623 if (!token.hasVisible) { 8624 mExitingTokens.remove(i); 8625 if (token.windowType == TYPE_WALLPAPER) { 8626 mWallpaperTokens.remove(token); 8627 } 8628 } 8629 } 8630 8631 // Time to remove any exiting applications? 8632 for (i=mExitingAppTokens.size()-1; i>=0; i--) { 8633 AppWindowToken token = mExitingAppTokens.get(i); 8634 if (!token.hasVisible && !mClosingApps.contains(token)) { 8635 // Make sure there is no animation running on this token, 8636 // so any windows associated with it will be removed as 8637 // soon as their animations are complete 8638 token.animation = null; 8639 token.animating = false; 8640 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 8641 "performLayout: App token exiting now removed" + token); 8642 mAppTokens.remove(token); 8643 mExitingAppTokens.remove(i); 8644 } 8645 } 8646 8647 boolean needRelayout = false; 8648 8649 if (!animating && mAppTransitionRunning) { 8650 // We have finished the animation of an app transition. To do 8651 // this, we have delayed a lot of operations like showing and 8652 // hiding apps, moving apps in Z-order, etc. The app token list 8653 // reflects the correct Z-order, but the window list may now 8654 // be out of sync with it. So here we will just rebuild the 8655 // entire app window list. Fun! 8656 mAppTransitionRunning = false; 8657 needRelayout = true; 8658 rebuildAppWindowListLocked(); 8659 assignLayersLocked(); 8660 // Clear information about apps that were moving. 8661 mToBottomApps.clear(); 8662 } 8663 8664 if (focusDisplayed) { 8665 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); 8666 } 8667 if (wallpaperDestroyed) { 8668 needRelayout = adjustWallpaperWindowsLocked() != 0; 8669 } 8670 if (needRelayout) { 8671 requestAnimationLocked(0); 8672 } else if (animating) { 8673 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis()); 8674 } 8675 8676 // Finally update all input windows now that the window changes have stabilized. 8677 mInputMonitor.updateInputWindowsLw(true /*force*/); 8678 8679 setHoldScreenLocked(holdScreen != null); 8680 if (!mDisplayFrozen) { 8681 if (screenBrightness < 0 || screenBrightness > 1.0f) { 8682 mPowerManager.setScreenBrightnessOverride(-1); 8683 } else { 8684 mPowerManager.setScreenBrightnessOverride((int) 8685 (screenBrightness * Power.BRIGHTNESS_ON)); 8686 } 8687 if (buttonBrightness < 0 || buttonBrightness > 1.0f) { 8688 mPowerManager.setButtonBrightnessOverride(-1); 8689 } else { 8690 mPowerManager.setButtonBrightnessOverride((int) 8691 (buttonBrightness * Power.BRIGHTNESS_ON)); 8692 } 8693 } 8694 if (holdScreen != mHoldingScreenOn) { 8695 mHoldingScreenOn = holdScreen; 8696 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen); 8697 mH.sendMessage(m); 8698 } 8699 8700 if (mTurnOnScreen) { 8701 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); 8702 mPowerManager.userActivity(SystemClock.uptimeMillis(), false, 8703 LocalPowerManager.BUTTON_EVENT, true); 8704 mTurnOnScreen = false; 8705 } 8706 8707 if (screenRotationFinished && mScreenRotationAnimation != null) { 8708 mScreenRotationAnimation.kill(); 8709 mScreenRotationAnimation = null; 8710 } 8711 8712 if (updateRotation) { 8713 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 8714 boolean changed = updateRotationUncheckedLocked(false); 8715 if (changed) { 8716 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 8717 } else { 8718 updateRotation = false; 8719 } 8720 } 8721 8722 if (orientationChangeComplete && !needRelayout && !updateRotation) { 8723 checkDrawnWindowsLocked(); 8724 } 8725 8726 // Check to see if we are now in a state where the screen should 8727 // be enabled, because the window obscured flags have changed. 8728 enableScreenIfNeededLocked(); 8729 } 8730 8731 void checkDrawnWindowsLocked() { 8732 if (mWaitingForDrawn.size() > 0) { 8733 for (int j=mWaitingForDrawn.size()-1; j>=0; j--) { 8734 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j); 8735 WindowState win = pair.first; 8736 //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" 8737 // + win.mRemoved + " visible=" + win.isVisibleLw() 8738 // + " shown=" + win.mSurfaceShown); 8739 if (win.mRemoved || !win.isVisibleLw()) { 8740 // Window has been removed or made invisible; no draw 8741 // will now happen, so stop waiting. 8742 Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); 8743 try { 8744 pair.second.sendResult(null); 8745 } catch (RemoteException e) { 8746 } 8747 mWaitingForDrawn.remove(pair); 8748 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8749 } else if (win.mSurfaceShown) { 8750 // Window is now drawn (and shown). 8751 try { 8752 pair.second.sendResult(null); 8753 } catch (RemoteException e) { 8754 } 8755 mWaitingForDrawn.remove(pair); 8756 mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8757 } 8758 } 8759 } 8760 } 8761 8762 public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) { 8763 synchronized (mWindowMap) { 8764 WindowState win = windowForClientLocked(null, token, true); 8765 if (win != null) { 8766 Pair<WindowState, IRemoteCallback> pair = 8767 new Pair<WindowState, IRemoteCallback>(win, callback); 8768 Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair); 8769 mH.sendMessageDelayed(m, 2000); 8770 mWaitingForDrawn.add(pair); 8771 checkDrawnWindowsLocked(); 8772 } 8773 } 8774 } 8775 8776 /** 8777 * Must be called with the main window manager lock held. 8778 */ 8779 void setHoldScreenLocked(boolean holding) { 8780 boolean state = mHoldingScreenWakeLock.isHeld(); 8781 if (holding != state) { 8782 if (holding) { 8783 mPolicy.screenOnStartedLw(); 8784 mHoldingScreenWakeLock.acquire(); 8785 } else { 8786 mPolicy.screenOnStoppedLw(); 8787 mHoldingScreenWakeLock.release(); 8788 } 8789 } 8790 } 8791 8792 void requestAnimationLocked(long delay) { 8793 if (!mAnimationPending) { 8794 mAnimationPending = true; 8795 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay); 8796 } 8797 } 8798 8799 /** 8800 * Have the surface flinger show a surface, robustly dealing with 8801 * error conditions. In particular, if there is not enough memory 8802 * to show the surface, then we will try to get rid of other surfaces 8803 * in order to succeed. 8804 * 8805 * @return Returns true if the surface was successfully shown. 8806 */ 8807 boolean showSurfaceRobustlyLocked(WindowState win) { 8808 try { 8809 if (win.mSurface != null) { 8810 win.mSurfaceShown = true; 8811 win.mSurface.show(); 8812 if (win.mTurnOnScreen) { 8813 if (DEBUG_VISIBILITY) Slog.v(TAG, 8814 "Show surface turning screen on: " + win); 8815 win.mTurnOnScreen = false; 8816 mTurnOnScreen = true; 8817 } 8818 } 8819 return true; 8820 } catch (RuntimeException e) { 8821 Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win, e); 8822 } 8823 8824 reclaimSomeSurfaceMemoryLocked(win, "show", true); 8825 8826 return false; 8827 } 8828 8829 boolean reclaimSomeSurfaceMemoryLocked(WindowState win, String operation, boolean secure) { 8830 final Surface surface = win.mSurface; 8831 boolean leakedSurface = false; 8832 boolean killedApps = false; 8833 8834 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(), 8835 win.mSession.mPid, operation); 8836 8837 if (mForceRemoves == null) { 8838 mForceRemoves = new ArrayList<WindowState>(); 8839 } 8840 8841 long callingIdentity = Binder.clearCallingIdentity(); 8842 try { 8843 // There was some problem... first, do a sanity check of the 8844 // window list to make sure we haven't left any dangling surfaces 8845 // around. 8846 int N = mWindows.size(); 8847 Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); 8848 for (int i=0; i<N; i++) { 8849 WindowState ws = mWindows.get(i); 8850 if (ws.mSurface != null) { 8851 if (!mSessions.contains(ws.mSession)) { 8852 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " 8853 + ws + " surface=" + ws.mSurface 8854 + " token=" + win.mToken 8855 + " pid=" + ws.mSession.mPid 8856 + " uid=" + ws.mSession.mUid); 8857 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 8858 ws.mSurface.destroy(); 8859 ws.mSurfaceShown = false; 8860 ws.mSurface = null; 8861 mForceRemoves.add(ws); 8862 i--; 8863 N--; 8864 leakedSurface = true; 8865 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 8866 Slog.w(TAG, "LEAKED SURFACE (app token hidden): " 8867 + ws + " surface=" + ws.mSurface 8868 + " token=" + win.mAppToken); 8869 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); 8870 ws.mSurface.destroy(); 8871 ws.mSurfaceShown = false; 8872 ws.mSurface = null; 8873 leakedSurface = true; 8874 } 8875 } 8876 } 8877 8878 if (!leakedSurface) { 8879 Slog.w(TAG, "No leaked surfaces; killing applicatons!"); 8880 SparseIntArray pidCandidates = new SparseIntArray(); 8881 for (int i=0; i<N; i++) { 8882 WindowState ws = mWindows.get(i); 8883 if (ws.mSurface != null) { 8884 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid); 8885 } 8886 } 8887 if (pidCandidates.size() > 0) { 8888 int[] pids = new int[pidCandidates.size()]; 8889 for (int i=0; i<pids.length; i++) { 8890 pids[i] = pidCandidates.keyAt(i); 8891 } 8892 try { 8893 if (mActivityManager.killPids(pids, "Free memory", secure)) { 8894 killedApps = true; 8895 } 8896 } catch (RemoteException e) { 8897 } 8898 } 8899 } 8900 8901 if (leakedSurface || killedApps) { 8902 // We managed to reclaim some memory, so get rid of the trouble 8903 // surface and ask the app to request another one. 8904 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); 8905 if (surface != null) { 8906 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(win, 8907 "RECOVER DESTROY", null); 8908 surface.destroy(); 8909 win.mSurfaceShown = false; 8910 win.mSurface = null; 8911 } 8912 8913 try { 8914 win.mClient.dispatchGetNewSurface(); 8915 } catch (RemoteException e) { 8916 } 8917 } 8918 } finally { 8919 Binder.restoreCallingIdentity(callingIdentity); 8920 } 8921 8922 return leakedSurface || killedApps; 8923 } 8924 8925 private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 8926 WindowState newFocus = computeFocusedWindowLocked(); 8927 if (mCurrentFocus != newFocus) { 8928 // This check makes sure that we don't already have the focus 8929 // change message pending. 8930 mH.removeMessages(H.REPORT_FOCUS_CHANGE); 8931 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); 8932 if (localLOGV) Slog.v( 8933 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); 8934 final WindowState oldFocus = mCurrentFocus; 8935 mCurrentFocus = newFocus; 8936 mLosingFocus.remove(newFocus); 8937 int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); 8938 8939 final WindowState imWindow = mInputMethodWindow; 8940 if (newFocus != imWindow && oldFocus != imWindow) { 8941 if (moveInputMethodWindowsIfNeededLocked( 8942 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && 8943 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { 8944 mLayoutNeeded = true; 8945 } 8946 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 8947 performLayoutLockedInner(true /*initial*/, updateInputWindows); 8948 focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 8949 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { 8950 // Client will do the layout, but we need to assign layers 8951 // for handleNewWindowLocked() below. 8952 assignLayersLocked(); 8953 } 8954 } 8955 8956 if ((focusChanged&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { 8957 // The change in focus caused us to need to do a layout. Okay. 8958 mLayoutNeeded = true; 8959 if (mode == UPDATE_FOCUS_PLACING_SURFACES) { 8960 performLayoutLockedInner(true /*initial*/, updateInputWindows); 8961 } 8962 } 8963 8964 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { 8965 // If we defer assigning layers, then the caller is responsible for 8966 // doing this part. 8967 finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); 8968 } 8969 return true; 8970 } 8971 return false; 8972 } 8973 8974 private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { 8975 mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); 8976 } 8977 8978 private WindowState computeFocusedWindowLocked() { 8979 WindowState result = null; 8980 WindowState win; 8981 8982 int i = mWindows.size() - 1; 8983 int nextAppIndex = mAppTokens.size()-1; 8984 WindowToken nextApp = nextAppIndex >= 0 8985 ? mAppTokens.get(nextAppIndex) : null; 8986 8987 while (i >= 0) { 8988 win = mWindows.get(i); 8989 8990 if (localLOGV || DEBUG_FOCUS) Slog.v( 8991 TAG, "Looking for focus: " + i 8992 + " = " + win 8993 + ", flags=" + win.mAttrs.flags 8994 + ", canReceive=" + win.canReceiveKeys()); 8995 8996 AppWindowToken thisApp = win.mAppToken; 8997 8998 // If this window's application has been removed, just skip it. 8999 if (thisApp != null && thisApp.removed) { 9000 i--; 9001 continue; 9002 } 9003 9004 // If there is a focused app, don't allow focus to go to any 9005 // windows below it. If this is an application window, step 9006 // through the app tokens until we find its app. 9007 if (thisApp != null && nextApp != null && thisApp != nextApp 9008 && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 9009 int origAppIndex = nextAppIndex; 9010 while (nextAppIndex > 0) { 9011 if (nextApp == mFocusedApp) { 9012 // Whoops, we are below the focused app... no focus 9013 // for you! 9014 if (localLOGV || DEBUG_FOCUS) Slog.v( 9015 TAG, "Reached focused app: " + mFocusedApp); 9016 return null; 9017 } 9018 nextAppIndex--; 9019 nextApp = mAppTokens.get(nextAppIndex); 9020 if (nextApp == thisApp) { 9021 break; 9022 } 9023 } 9024 if (thisApp != nextApp) { 9025 // Uh oh, the app token doesn't exist! This shouldn't 9026 // happen, but if it does we can get totally hosed... 9027 // so restart at the original app. 9028 nextAppIndex = origAppIndex; 9029 nextApp = mAppTokens.get(nextAppIndex); 9030 } 9031 } 9032 9033 // Dispatch to this window if it is wants key events. 9034 if (win.canReceiveKeys()) { 9035 if (DEBUG_FOCUS) Slog.v( 9036 TAG, "Found focus @ " + i + " = " + win); 9037 result = win; 9038 break; 9039 } 9040 9041 i--; 9042 } 9043 9044 return result; 9045 } 9046 9047 private void startFreezingDisplayLocked(boolean inTransaction) { 9048 if (mDisplayFrozen) { 9049 return; 9050 } 9051 9052 if (mDisplay == null || !mPolicy.isScreenOnFully()) { 9053 // No need to freeze the screen before the system is ready or if 9054 // the screen is off. 9055 return; 9056 } 9057 9058 mScreenFrozenLock.acquire(); 9059 9060 mDisplayFrozen = true; 9061 9062 mInputMonitor.freezeInputDispatchingLw(); 9063 9064 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { 9065 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; 9066 mNextAppTransitionPackage = null; 9067 mAppTransitionReady = true; 9068 } 9069 9070 if (PROFILE_ORIENTATION) { 9071 File file = new File("/data/system/frozen"); 9072 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 9073 } 9074 9075 if (CUSTOM_SCREEN_ROTATION) { 9076 if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) { 9077 mScreenRotationAnimation.kill(); 9078 mScreenRotationAnimation = null; 9079 } 9080 if (mScreenRotationAnimation == null) { 9081 mScreenRotationAnimation = new ScreenRotationAnimation(mContext, 9082 mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight, 9083 mDisplay.getRotation()); 9084 } 9085 if (!mScreenRotationAnimation.hasScreenshot()) { 9086 Surface.freezeDisplay(0); 9087 } 9088 } else { 9089 Surface.freezeDisplay(0); 9090 } 9091 } 9092 9093 private void stopFreezingDisplayLocked() { 9094 if (!mDisplayFrozen) { 9095 return; 9096 } 9097 9098 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) { 9099 return; 9100 } 9101 9102 mDisplayFrozen = false; 9103 mH.removeMessages(H.APP_FREEZE_TIMEOUT); 9104 if (PROFILE_ORIENTATION) { 9105 Debug.stopMethodTracing(); 9106 } 9107 9108 boolean updateRotation = false; 9109 9110 if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null 9111 && mScreenRotationAnimation.hasScreenshot()) { 9112 if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); 9113 if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, 9114 mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { 9115 requestAnimationLocked(0); 9116 } else { 9117 mScreenRotationAnimation = null; 9118 updateRotation = true; 9119 } 9120 } else { 9121 if (mScreenRotationAnimation != null) { 9122 mScreenRotationAnimation.kill(); 9123 mScreenRotationAnimation = null; 9124 } 9125 updateRotation = true; 9126 } 9127 Surface.unfreezeDisplay(0); 9128 9129 mInputMonitor.thawInputDispatchingLw(); 9130 9131 boolean configChanged; 9132 9133 // While the display is frozen we don't re-compute the orientation 9134 // to avoid inconsistent states. However, something interesting 9135 // could have actually changed during that time so re-evaluate it 9136 // now to catch that. 9137 configChanged = updateOrientationFromAppTokensLocked(false); 9138 9139 // A little kludge: a lot could have happened while the 9140 // display was frozen, so now that we are coming back we 9141 // do a gc so that any remote references the system 9142 // processes holds on others can be released if they are 9143 // no longer needed. 9144 mH.removeMessages(H.FORCE_GC); 9145 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 9146 2000); 9147 9148 mScreenFrozenLock.release(); 9149 9150 if (updateRotation) { 9151 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 9152 configChanged |= updateRotationUncheckedLocked(false); 9153 } 9154 9155 if (configChanged) { 9156 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); 9157 } 9158 } 9159 9160 static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, 9161 DisplayMetrics dm) { 9162 if (index < tokens.length) { 9163 String str = tokens[index]; 9164 if (str != null && str.length() > 0) { 9165 try { 9166 int val = Integer.parseInt(str); 9167 return val; 9168 } catch (Exception e) { 9169 } 9170 } 9171 } 9172 if (defUnits == TypedValue.COMPLEX_UNIT_PX) { 9173 return defDps; 9174 } 9175 int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); 9176 return val; 9177 } 9178 9179 void createWatermark() { 9180 if (mWatermark != null) { 9181 return; 9182 } 9183 9184 File file = new File("/system/etc/setup.conf"); 9185 FileInputStream in = null; 9186 try { 9187 in = new FileInputStream(file); 9188 DataInputStream ind = new DataInputStream(in); 9189 String line = ind.readLine(); 9190 if (line != null) { 9191 String[] toks = line.split("%"); 9192 if (toks != null && toks.length > 0) { 9193 mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks); 9194 } 9195 } 9196 } catch (FileNotFoundException e) { 9197 } catch (IOException e) { 9198 } finally { 9199 if (in != null) { 9200 try { 9201 in.close(); 9202 } catch (IOException e) { 9203 } 9204 } 9205 } 9206 } 9207 9208 @Override 9209 public void statusBarVisibilityChanged(int visibility) { 9210 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) 9211 != PackageManager.PERMISSION_GRANTED) { 9212 throw new SecurityException("Caller does not hold permission " 9213 + android.Manifest.permission.STATUS_BAR); 9214 } 9215 9216 synchronized (mWindowMap) { 9217 mLastStatusBarVisibility = visibility; 9218 visibility = mPolicy.adjustSystemUiVisibilityLw(visibility); 9219 updateStatusBarVisibilityLocked(visibility); 9220 } 9221 } 9222 9223 void updateStatusBarVisibilityLocked(int visibility) { 9224 mInputManager.setSystemUiVisibility(visibility); 9225 final int N = mWindows.size(); 9226 for (int i = 0; i < N; i++) { 9227 WindowState ws = mWindows.get(i); 9228 try { 9229 int curValue = ws.mSystemUiVisibility; 9230 int diff = curValue ^ visibility; 9231 // We are only interested in differences of one of the 9232 // clearable flags... 9233 diff &= View.SYSTEM_UI_CLEARABLE_FLAGS; 9234 // ...if it has actually been cleared. 9235 diff &= ~visibility; 9236 int newValue = (curValue&~diff) | (visibility&diff); 9237 if (newValue != curValue) { 9238 ws.mSeq++; 9239 ws.mSystemUiVisibility = newValue; 9240 } 9241 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 9242 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 9243 visibility, newValue, diff); 9244 } 9245 } catch (RemoteException e) { 9246 // so sorry 9247 } 9248 } 9249 } 9250 9251 @Override 9252 public void reevaluateStatusBarVisibility() { 9253 synchronized (mWindowMap) { 9254 int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility); 9255 updateStatusBarVisibilityLocked(visibility); 9256 performLayoutAndPlaceSurfacesLocked(); 9257 } 9258 } 9259 9260 @Override 9261 public FakeWindow addFakeWindow(Looper looper, InputHandler inputHandler, 9262 String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys, 9263 boolean hasFocus, boolean touchFullscreen) { 9264 synchronized (mWindowMap) { 9265 FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputHandler, name, windowType, 9266 layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen); 9267 int i=0; 9268 while (i<mFakeWindows.size()) { 9269 if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) { 9270 break; 9271 } 9272 } 9273 mFakeWindows.add(i, fw); 9274 mInputMonitor.updateInputWindowsLw(true); 9275 return fw; 9276 } 9277 } 9278 9279 boolean removeFakeWindowLocked(FakeWindow window) { 9280 synchronized (mWindowMap) { 9281 if (mFakeWindows.remove(window)) { 9282 mInputMonitor.updateInputWindowsLw(true); 9283 return true; 9284 } 9285 return false; 9286 } 9287 } 9288 9289 @Override 9290 public boolean hasNavigationBar() { 9291 return mPolicy.hasNavigationBar(); 9292 } 9293 9294 void dumpInput(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { 9295 pw.println("WINDOW MANAGER INPUT (dumpsys window input)"); 9296 mInputManager.dump(pw); 9297 } 9298 9299 void dumpPolicyLocked(FileDescriptor fd, PrintWriter pw, String[] args, boolean dumpAll) { 9300 pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); 9301 mPolicy.dump(" ", fd, pw, args); 9302 } 9303 9304 void dumpTokensLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { 9305 pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); 9306 if (mTokenMap.size() > 0) { 9307 pw.println(" All tokens:"); 9308 Iterator<WindowToken> it = mTokenMap.values().iterator(); 9309 while (it.hasNext()) { 9310 WindowToken token = it.next(); 9311 pw.print(" Token "); pw.print(token.token); 9312 if (dumpAll) { 9313 pw.println(':'); 9314 token.dump(pw, " "); 9315 } else { 9316 pw.println(); 9317 } 9318 } 9319 } 9320 if (mWallpaperTokens.size() > 0) { 9321 pw.println(); 9322 pw.println(" Wallpaper tokens:"); 9323 for (int i=mWallpaperTokens.size()-1; i>=0; i--) { 9324 WindowToken token = mWallpaperTokens.get(i); 9325 pw.print(" Wallpaper #"); pw.print(i); 9326 pw.print(' '); pw.print(token); 9327 if (dumpAll) { 9328 pw.println(':'); 9329 token.dump(pw, " "); 9330 } else { 9331 pw.println(); 9332 } 9333 } 9334 } 9335 if (mAppTokens.size() > 0) { 9336 pw.println(); 9337 pw.println(" Application tokens in Z order:"); 9338 for (int i=mAppTokens.size()-1; i>=0; i--) { 9339 pw.print(" App #"); pw.print(i); pw.print(": "); 9340 pw.println(mAppTokens.get(i)); 9341 } 9342 } 9343 if (mFinishedStarting.size() > 0) { 9344 pw.println(); 9345 pw.println(" Finishing start of application tokens:"); 9346 for (int i=mFinishedStarting.size()-1; i>=0; i--) { 9347 WindowToken token = mFinishedStarting.get(i); 9348 pw.print(" Finished Starting #"); pw.print(i); 9349 pw.print(' '); pw.print(token); 9350 if (dumpAll) { 9351 pw.println(':'); 9352 token.dump(pw, " "); 9353 } else { 9354 pw.println(); 9355 } 9356 } 9357 } 9358 if (mExitingTokens.size() > 0) { 9359 pw.println(); 9360 pw.println(" Exiting tokens:"); 9361 for (int i=mExitingTokens.size()-1; i>=0; i--) { 9362 WindowToken token = mExitingTokens.get(i); 9363 pw.print(" Exiting #"); pw.print(i); 9364 pw.print(' '); pw.print(token); 9365 if (dumpAll) { 9366 pw.println(':'); 9367 token.dump(pw, " "); 9368 } else { 9369 pw.println(); 9370 } 9371 } 9372 } 9373 if (mExitingAppTokens.size() > 0) { 9374 pw.println(); 9375 pw.println(" Exiting application tokens:"); 9376 for (int i=mExitingAppTokens.size()-1; i>=0; i--) { 9377 WindowToken token = mExitingAppTokens.get(i); 9378 pw.print(" Exiting App #"); pw.print(i); 9379 pw.print(' '); pw.print(token); 9380 if (dumpAll) { 9381 pw.println(':'); 9382 token.dump(pw, " "); 9383 } else { 9384 pw.println(); 9385 } 9386 } 9387 } 9388 pw.println(); 9389 if (mOpeningApps.size() > 0) { 9390 pw.print(" mOpeningApps="); pw.println(mOpeningApps); 9391 } 9392 if (mClosingApps.size() > 0) { 9393 pw.print(" mClosingApps="); pw.println(mClosingApps); 9394 } 9395 if (mToTopApps.size() > 0) { 9396 pw.print(" mToTopApps="); pw.println(mToTopApps); 9397 } 9398 if (mToBottomApps.size() > 0) { 9399 pw.print(" mToBottomApps="); pw.println(mToBottomApps); 9400 } 9401 } 9402 9403 void dumpSessionsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { 9404 pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)"); 9405 if (mSessions.size() > 0) { 9406 Iterator<Session> it = mSessions.iterator(); 9407 while (it.hasNext()) { 9408 Session s = it.next(); 9409 pw.print(" Session "); pw.print(s); pw.println(':'); 9410 s.dump(pw, " "); 9411 } 9412 } 9413 } 9414 9415 void dumpWindowsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, 9416 ArrayList<WindowState> windows) { 9417 pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); 9418 for (int i=mWindows.size()-1; i>=0; i--) { 9419 WindowState w = mWindows.get(i); 9420 if (windows == null || windows.contains(w)) { 9421 pw.print(" Window #"); pw.print(i); pw.print(' '); 9422 pw.print(w); pw.println(":"); 9423 w.dump(pw, " ", dumpAll || windows != null); 9424 } 9425 } 9426 if (mInputMethodDialogs.size() > 0) { 9427 pw.println(); 9428 pw.println(" Input method dialogs:"); 9429 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { 9430 WindowState w = mInputMethodDialogs.get(i); 9431 if (windows == null || windows.contains(w)) { 9432 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); 9433 } 9434 } 9435 } 9436 if (mPendingRemove.size() > 0) { 9437 pw.println(); 9438 pw.println(" Remove pending for:"); 9439 for (int i=mPendingRemove.size()-1; i>=0; i--) { 9440 WindowState w = mPendingRemove.get(i); 9441 if (windows == null || windows.contains(w)) { 9442 pw.print(" Remove #"); pw.print(i); pw.print(' '); 9443 pw.print(w); 9444 if (dumpAll) { 9445 pw.println(":"); 9446 w.dump(pw, " ", true); 9447 } else { 9448 pw.println(); 9449 } 9450 } 9451 } 9452 } 9453 if (mForceRemoves != null && mForceRemoves.size() > 0) { 9454 pw.println(); 9455 pw.println(" Windows force removing:"); 9456 for (int i=mForceRemoves.size()-1; i>=0; i--) { 9457 WindowState w = mForceRemoves.get(i); 9458 pw.print(" Removing #"); pw.print(i); pw.print(' '); 9459 pw.print(w); 9460 if (dumpAll) { 9461 pw.println(":"); 9462 w.dump(pw, " ", true); 9463 } else { 9464 pw.println(); 9465 } 9466 } 9467 } 9468 if (mDestroySurface.size() > 0) { 9469 pw.println(); 9470 pw.println(" Windows waiting to destroy their surface:"); 9471 for (int i=mDestroySurface.size()-1; i>=0; i--) { 9472 WindowState w = mDestroySurface.get(i); 9473 if (windows == null || windows.contains(w)) { 9474 pw.print(" Destroy #"); pw.print(i); pw.print(' '); 9475 pw.print(w); 9476 if (dumpAll) { 9477 pw.println(":"); 9478 w.dump(pw, " ", true); 9479 } else { 9480 pw.println(); 9481 } 9482 } 9483 } 9484 } 9485 if (mLosingFocus.size() > 0) { 9486 pw.println(); 9487 pw.println(" Windows losing focus:"); 9488 for (int i=mLosingFocus.size()-1; i>=0; i--) { 9489 WindowState w = mLosingFocus.get(i); 9490 if (windows == null || windows.contains(w)) { 9491 pw.print(" Losing #"); pw.print(i); pw.print(' '); 9492 pw.print(w); 9493 if (dumpAll) { 9494 pw.println(":"); 9495 w.dump(pw, " ", true); 9496 } else { 9497 pw.println(); 9498 } 9499 } 9500 } 9501 } 9502 if (mResizingWindows.size() > 0) { 9503 pw.println(); 9504 pw.println(" Windows waiting to resize:"); 9505 for (int i=mResizingWindows.size()-1; i>=0; i--) { 9506 WindowState w = mResizingWindows.get(i); 9507 if (windows == null || windows.contains(w)) { 9508 pw.print(" Resizing #"); pw.print(i); pw.print(' '); 9509 pw.print(w); 9510 if (dumpAll) { 9511 pw.println(":"); 9512 w.dump(pw, " ", true); 9513 } else { 9514 pw.println(); 9515 } 9516 } 9517 } 9518 } 9519 if (mWaitingForDrawn.size() > 0) { 9520 pw.println(); 9521 pw.println(" Clients waiting for these windows to be drawn:"); 9522 for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { 9523 Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i); 9524 pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first); 9525 pw.print(": "); pw.println(pair.second); 9526 } 9527 } 9528 pw.println(); 9529 if (mDisplay != null) { 9530 pw.print(" Display: init="); pw.print(mInitialDisplayWidth); pw.print("x"); 9531 pw.print(mInitialDisplayHeight); pw.print(" base="); 9532 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 9533 pw.print(" cur="); 9534 pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight); 9535 pw.print(" app="); 9536 pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight); 9537 pw.print(" raw="); pw.print(mDisplay.getRawWidth()); 9538 pw.print("x"); pw.println(mDisplay.getRawHeight()); 9539 } else { 9540 pw.println(" NO DISPLAY"); 9541 } 9542 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); 9543 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); 9544 if (mLastFocus != mCurrentFocus) { 9545 pw.print(" mLastFocus="); pw.println(mLastFocus); 9546 } 9547 pw.print(" mFocusedApp="); pw.println(mFocusedApp); 9548 if (mInputMethodTarget != null) { 9549 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); 9550 } 9551 pw.print(" mInTouchMode="); pw.print(mInTouchMode); 9552 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); 9553 if (dumpAll) { 9554 if (mLastStatusBarVisibility != 0) { 9555 pw.print(" mLastStatusBarVisibility=0x"); 9556 pw.println(Integer.toHexString(mLastStatusBarVisibility)); 9557 } 9558 if (mInputMethodWindow != null) { 9559 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); 9560 } 9561 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); 9562 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) { 9563 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); 9564 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); 9565 } 9566 if (mWindowDetachedWallpaper != null) { 9567 pw.print(" mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper); 9568 } 9569 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); 9570 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); 9571 if (mInputMethodAnimLayerAdjustment != 0 || 9572 mWallpaperAnimLayerAdjustment != 0) { 9573 pw.print(" mInputMethodAnimLayerAdjustment="); 9574 pw.print(mInputMethodAnimLayerAdjustment); 9575 pw.print(" mWallpaperAnimLayerAdjustment="); 9576 pw.println(mWallpaperAnimLayerAdjustment); 9577 } 9578 if (mWindowAnimationBackgroundSurface != null) { 9579 pw.println(" mWindowAnimationBackgroundSurface:"); 9580 mWindowAnimationBackgroundSurface.printTo(" ", pw); 9581 } 9582 pw.print(" mSystemBooted="); pw.print(mSystemBooted); 9583 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); 9584 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); 9585 pw.print(" mBlurShown="); pw.println(mBlurShown); 9586 if (mDimAnimator != null) { 9587 pw.println(" mDimAnimator:"); 9588 mDimAnimator.printTo(" ", pw); 9589 } else { 9590 pw.println( " no DimAnimator "); 9591 } 9592 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); 9593 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); 9594 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); 9595 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); 9596 pw.print(" mRotation="); pw.print(mRotation); 9597 pw.print(" mAltOrientation="); pw.println(mAltOrientation); 9598 pw.print(" mLastWindowForcedOrientation"); pw.print(mLastWindowForcedOrientation); 9599 pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); 9600 pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); 9601 pw.print(" mAnimationPending="); pw.print(mAnimationPending); 9602 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); 9603 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale); 9604 pw.print(" mNextAppTransition=0x"); 9605 pw.print(Integer.toHexString(mNextAppTransition)); 9606 pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady); 9607 pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning); 9608 pw.print(" mAppTransitionTimeout="); pw.println( mAppTransitionTimeout); 9609 if (mNextAppTransitionPackage != null) { 9610 pw.print(" mNextAppTransitionPackage="); 9611 pw.print(mNextAppTransitionPackage); 9612 pw.print(" mNextAppTransitionEnter=0x"); 9613 pw.print(Integer.toHexString(mNextAppTransitionEnter)); 9614 pw.print(" mNextAppTransitionExit=0x"); 9615 pw.print(Integer.toHexString(mNextAppTransitionExit)); 9616 } 9617 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); 9618 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); 9619 } 9620 } 9621 9622 boolean dumpWindows(FileDescriptor fd, PrintWriter pw, String name, String[] args, 9623 int opti, boolean dumpAll) { 9624 ArrayList<WindowState> windows = new ArrayList<WindowState>(); 9625 if ("visible".equals(name)) { 9626 synchronized(mWindowMap) { 9627 for (int i=mWindows.size()-1; i>=0; i--) { 9628 WindowState w = mWindows.get(i); 9629 if (w.mSurfaceShown) { 9630 windows.add(w); 9631 } 9632 } 9633 } 9634 } else { 9635 int objectId = 0; 9636 // See if this is an object ID. 9637 try { 9638 objectId = Integer.parseInt(name, 16); 9639 name = null; 9640 } catch (RuntimeException e) { 9641 } 9642 synchronized(mWindowMap) { 9643 for (int i=mWindows.size()-1; i>=0; i--) { 9644 WindowState w = mWindows.get(i); 9645 if (name != null) { 9646 if (w.mAttrs.getTitle().toString().contains(name)) { 9647 windows.add(w); 9648 } 9649 } else if (System.identityHashCode(w) == objectId) { 9650 windows.add(w); 9651 } 9652 } 9653 } 9654 } 9655 9656 if (windows.size() <= 0) { 9657 return false; 9658 } 9659 9660 synchronized(mWindowMap) { 9661 dumpWindowsLocked(fd, pw, dumpAll, windows); 9662 } 9663 return true; 9664 } 9665 9666 @Override 9667 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 9668 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") 9669 != PackageManager.PERMISSION_GRANTED) { 9670 pw.println("Permission Denial: can't dump WindowManager from from pid=" 9671 + Binder.getCallingPid() 9672 + ", uid=" + Binder.getCallingUid()); 9673 return; 9674 } 9675 9676 boolean dumpAll = false; 9677 9678 int opti = 0; 9679 while (opti < args.length) { 9680 String opt = args[opti]; 9681 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 9682 break; 9683 } 9684 opti++; 9685 if ("-a".equals(opt)) { 9686 dumpAll = true; 9687 } else if ("-h".equals(opt)) { 9688 pw.println("Window manager dump options:"); 9689 pw.println(" [-a] [-h] [cmd] ..."); 9690 pw.println(" cmd may be one of:"); 9691 pw.println(" i[input]: input subsystem state"); 9692 pw.println(" p[policy]: policy state"); 9693 pw.println(" s[essions]: active sessions"); 9694 pw.println(" t[okens]: token list"); 9695 pw.println(" w[indows]: window list"); 9696 pw.println(" cmd may also be a NAME to dump windows. NAME may"); 9697 pw.println(" be a partial substring in a window name, a"); 9698 pw.println(" Window hex object identifier, or"); 9699 pw.println(" \"all\" for all windows, or"); 9700 pw.println(" \"visible\" for the visible windows."); 9701 pw.println(" -a: include all available server state."); 9702 return; 9703 } else { 9704 pw.println("Unknown argument: " + opt + "; use -h for help"); 9705 } 9706 } 9707 9708 // Is the caller requesting to dump a particular piece of data? 9709 if (opti < args.length) { 9710 String cmd = args[opti]; 9711 opti++; 9712 if ("input".equals(cmd) || "i".equals(cmd)) { 9713 dumpInput(fd, pw, true); 9714 return; 9715 } else if ("policy".equals(cmd) || "p".equals(cmd)) { 9716 synchronized(mWindowMap) { 9717 dumpPolicyLocked(fd, pw, args, true); 9718 } 9719 return; 9720 } else if ("sessions".equals(cmd) || "s".equals(cmd)) { 9721 synchronized(mWindowMap) { 9722 dumpSessionsLocked(fd, pw, true); 9723 } 9724 return; 9725 } else if ("tokens".equals(cmd) || "t".equals(cmd)) { 9726 synchronized(mWindowMap) { 9727 dumpTokensLocked(fd, pw, true); 9728 } 9729 return; 9730 } else if ("windows".equals(cmd) || "w".equals(cmd)) { 9731 synchronized(mWindowMap) { 9732 dumpWindowsLocked(fd, pw, true, null); 9733 } 9734 return; 9735 } else if ("all".equals(cmd) || "a".equals(cmd)) { 9736 synchronized(mWindowMap) { 9737 dumpWindowsLocked(fd, pw, true, null); 9738 } 9739 return; 9740 } else { 9741 // Dumping a single name? 9742 if (!dumpWindows(fd, pw, cmd, args, opti, dumpAll)) { 9743 pw.println("Bad window command, or no windows match: " + cmd); 9744 pw.println("Use -h for help."); 9745 } 9746 return; 9747 } 9748 } 9749 9750 dumpInput(fd, pw, dumpAll); 9751 9752 synchronized(mWindowMap) { 9753 if (dumpAll) { 9754 pw.println("-------------------------------------------------------------------------------"); 9755 } 9756 dumpPolicyLocked(fd, pw, args, dumpAll); 9757 pw.println(); 9758 if (dumpAll) { 9759 pw.println("-------------------------------------------------------------------------------"); 9760 } 9761 dumpSessionsLocked(fd, pw, dumpAll); 9762 pw.println(); 9763 if (dumpAll) { 9764 pw.println("-------------------------------------------------------------------------------"); 9765 } 9766 dumpTokensLocked(fd, pw, dumpAll); 9767 pw.println(); 9768 if (dumpAll) { 9769 pw.println("-------------------------------------------------------------------------------"); 9770 } 9771 dumpWindowsLocked(fd, pw, dumpAll, null); 9772 } 9773 } 9774 9775 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). 9776 public void monitor() { 9777 synchronized (mWindowMap) { } 9778 synchronized (mKeyguardTokenWatcher) { } 9779 } 9780 9781 public interface OnHardKeyboardStatusChangeListener { 9782 public void onHardKeyboardStatusChange(boolean available, boolean enabled); 9783 } 9784} 9785