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
This commit is contained in:
Christopher Tate
2010-02-11 17:51:24 -08:00
parent 5a4b1d9e63
commit 136b1f927f

View File

@@ -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;