@@ -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
5857protected:
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,
268273static 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