Skip to content

Commit d1f3de4

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Be more careful about exceptions in input callbacks."
2 parents 50a9267 + 3bdcdd8 commit d1f3de4

File tree

1 file changed

+45
-40
lines changed

1 file changed

+45
-40
lines changed

core/jni/android_view_InputEventReceiver.cpp

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ class NativeInputEventReceiver : public RefBase {
5252

5353
status_t initialize();
5454
status_t finishInputEvent(uint32_t seq, bool handled);
55-
status_t consumeEvents(bool consumeBatches);
56-
static int handleReceiveCallback(int receiveFd, int events, void* data);
55+
status_t consumeEvents(JNIEnv* env, bool consumeBatches);
5756

5857
protected:
5958
virtual ~NativeInputEventReceiver();
@@ -68,6 +67,8 @@ class NativeInputEventReceiver : public RefBase {
6867
const char* getInputChannelName() {
6968
return mInputConsumer.getChannel()->getName().string();
7069
}
70+
71+
static int handleReceiveCallback(int receiveFd, int events, void* data);
7172
};
7273

7374

@@ -128,11 +129,13 @@ int NativeInputEventReceiver::handleReceiveCallback(int receiveFd, int events, v
128129
return 1;
129130
}
130131

131-
status_t status = r->consumeEvents(false /*consumeBatches*/);
132+
JNIEnv* env = AndroidRuntime::getJNIEnv();
133+
status_t status = r->consumeEvents(env, false /*consumeBatches*/);
134+
r->mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
132135
return status == OK || status == NO_MEMORY ? 1 : 0;
133136
}
134137

135-
status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
138+
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, bool consumeBatches) {
136139
#if DEBUG_DISPATCH_CYCLE
137140
ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s.", getInputChannelName(),
138141
consumeBatches ? "true" : "false");
@@ -142,15 +145,16 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
142145
mBatchedInputEventPending = false;
143146
}
144147

145-
JNIEnv* env = AndroidRuntime::getJNIEnv();
148+
bool skipCallbacks = false;
146149
for (;;) {
147150
uint32_t seq;
148151
InputEvent* inputEvent;
149152
status_t status = mInputConsumer.consume(&mInputEventFactory,
150153
consumeBatches, &seq, &inputEvent);
151154
if (status) {
152155
if (status == WOULD_BLOCK) {
153-
if (mInputConsumer.hasPendingBatch() && !mBatchedInputEventPending) {
156+
if (!skipCallbacks && !mBatchedInputEventPending
157+
&& mInputConsumer.hasPendingBatch()) {
154158
// There is a pending batch. Come back later.
155159
mBatchedInputEventPending = true;
156160
#if DEBUG_DISPATCH_CYCLE
@@ -159,8 +163,8 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
159163
#endif
160164
env->CallVoidMethod(mReceiverObjGlobal,
161165
gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
162-
if (mMessageQueue->raiseAndClearException(
163-
env, "dispatchBatchedInputEventPending")) {
166+
if (env->ExceptionCheck()) {
167+
ALOGE("Exception dispatching batched input events.");
164168
mBatchedInputEventPending = false; // try again later
165169
}
166170
}
@@ -172,46 +176,47 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
172176
}
173177
assert(inputEvent);
174178

175-
jobject inputEventObj;
176-
switch (inputEvent->getType()) {
177-
case AINPUT_EVENT_TYPE_KEY:
179+
if (!skipCallbacks) {
180+
jobject inputEventObj;
181+
switch (inputEvent->getType()) {
182+
case AINPUT_EVENT_TYPE_KEY:
178183
#if DEBUG_DISPATCH_CYCLE
179-
ALOGD("channel '%s' ~ Received key event.", getInputChannelName());
184+
ALOGD("channel '%s' ~ Received key event.", getInputChannelName());
180185
#endif
181-
inputEventObj = android_view_KeyEvent_fromNative(env,
182-
static_cast<KeyEvent*>(inputEvent));
183-
mMessageQueue->raiseAndClearException(env, "new KeyEvent");
184-
break;
186+
inputEventObj = android_view_KeyEvent_fromNative(env,
187+
static_cast<KeyEvent*>(inputEvent));
188+
break;
185189

186-
case AINPUT_EVENT_TYPE_MOTION:
190+
case AINPUT_EVENT_TYPE_MOTION:
187191
#if DEBUG_DISPATCH_CYCLE
188-
ALOGD("channel '%s' ~ Received motion event.", getInputChannelName());
192+
ALOGD("channel '%s' ~ Received motion event.", getInputChannelName());
189193
#endif
190-
inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
191-
static_cast<MotionEvent*>(inputEvent));
192-
mMessageQueue->raiseAndClearException(env, "new MotionEvent");
193-
break;
194-
195-
default:
196-
assert(false); // InputConsumer should prevent this from ever happening
197-
inputEventObj = NULL;
198-
}
194+
inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
195+
static_cast<MotionEvent*>(inputEvent));
196+
break;
199197

200-
if (!inputEventObj) {
201-
ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
202-
mInputConsumer.sendFinishedSignal(seq, false);
203-
continue;
204-
}
198+
default:
199+
assert(false); // InputConsumer should prevent this from ever happening
200+
inputEventObj = NULL;
201+
}
205202

203+
if (inputEventObj) {
206204
#if DEBUG_DISPATCH_CYCLE
207-
ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
205+
ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
208206
#endif
209-
env->CallVoidMethod(mReceiverObjGlobal,
210-
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
211-
212-
env->DeleteLocalRef(inputEventObj);
207+
env->CallVoidMethod(mReceiverObjGlobal,
208+
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
209+
if (env->ExceptionCheck()) {
210+
ALOGE("Exception dispatching input event.");
211+
skipCallbacks = true;
212+
}
213+
} else {
214+
ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
215+
skipCallbacks = true;
216+
}
217+
}
213218

214-
if (mMessageQueue->raiseAndClearException(env, "dispatchInputEvent")) {
219+
if (skipCallbacks) {
215220
mInputConsumer.sendFinishedSignal(seq, false);
216221
}
217222
}
@@ -268,8 +273,8 @@ static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr,
268273
static void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr) {
269274
sp<NativeInputEventReceiver> receiver =
270275
reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
271-
status_t status = receiver->consumeEvents(true /*consumeBatches*/);
272-
if (status && status != DEAD_OBJECT) {
276+
status_t status = receiver->consumeEvents(env, true /*consumeBatches*/);
277+
if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
273278
String8 message;
274279
message.appendFormat("Failed to consume batched input event. status=%d", status);
275280
jniThrowRuntimeException(env, message.string());

0 commit comments

Comments
 (0)