From 136b1f927f9d11cb0a9d3202ca3f77471afda556 Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Thu, 11 Feb 2010 17:51:24 -0800 Subject: [PATCH] Fix spurious ANRs involving window shuffling and non-fullscreen activities Force the event-target bookkeeping to reset when an app explicitly acknowledges event receipt. Furthermore, notify the event dispatcher whenever a new window is created, even if there is nominally an existing event target window. These changes in tandem address a subtle race bug in which the event dispatcher believes that there is an event recipient that it is still waiting for even when the event in question has been acknowledged; this results in a spurious ANR. There were checks in the existing code that wound up doing the right thing in the case of windows becoming hidden, but the case of non-fullscreen activities floating over them [unavailable for input but still visible] exposed the race condition. Bug: 2432828 Change-Id: I29fb741aace34736b029f9ba43f2c43184366258 --- .../android/server/WindowManagerService.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 73223ee648e0d..b5e652085821a 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -5610,7 +5610,7 @@ public class WindowManagerService extends IWindowManager.Stub // If an app switch key has been pressed, and we have // waited too long for the current app to finish // processing keys, then wait no more! - doFinishedKeyLocked(true); + doFinishedKeyLocked(false); continue; } long switchTimeout = mTimeToSwitch - now; @@ -6008,7 +6008,7 @@ public class WindowManagerService extends IWindowManager.Stub + ((mLastWin != null) ? mLastWin.mToken.paused : "null")); if (mLastWin != null && (!mLastWin.mToken.paused || force || !mEventDispatching)) { - doFinishedKeyLocked(false); + doFinishedKeyLocked(true); } else { // Make sure to wake up anyone currently waiting to // dispatch a key, so they can re-evaluate their @@ -6086,13 +6086,9 @@ public class WindowManagerService extends IWindowManager.Stub // The new window is above the old; finish pending input to the last // window and start directing it to the new one. mLastWin.mToken.paused = false; - doFinishedKeyLocked(true); // does a notifyAll() + doFinishedKeyLocked(false); // does a notifyAll() + return; } - // Either the new window is lower, so there is no need to wake key waiters, - // or we just finished key input to the previous window, which implicitly - // notified the key waiters. In both cases, we don't need to issue the - // notification here. - return; } // Now that we've put a new window state in place, make the event waiter @@ -6134,7 +6130,7 @@ public class WindowManagerService extends IWindowManager.Stub + token.paused); token.paused = false; if (mLastWin != null && mLastWin.mToken == token && mFinished) { - doFinishedKeyLocked(true); + doFinishedKeyLocked(false); } else { notifyAll(); } @@ -6162,14 +6158,14 @@ public class WindowManagerService extends IWindowManager.Stub } } - private final void doFinishedKeyLocked(boolean doRecycle) { + private final void doFinishedKeyLocked(boolean force) { if (mLastWin != null) { releasePendingPointerLocked(mLastWin.mSession); releasePendingTrackballLocked(mLastWin.mSession); } - if (mLastWin == null || !mLastWin.mToken.paused - || !mLastWin.isVisibleLw()) { + if (force || mLastWin == null || !mLastWin.mToken.paused + || !mLastWin.isVisibleLw()) { // If the current window has been paused, we aren't -really- // finished... so let the waiters still wait. mLastWin = null;