Created
July 4, 2014 23:57
-
-
Save omo/2790ecf8a9434f5f41c4 to your computer and use it in GitHub Desktop.
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) { | |
.... | |
if (events & ALOOPER_EVENT_INPUT) { | |
JNIEnv* env = AndroidRuntime::getJNIEnv(); | |
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL); | |
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback"); | |
return status == OK || status == NO_MEMORY ? 1 : 0; | |
} | |
if (events & ALOOPER_EVENT_OUTPUT) { | |
for (size_t i = 0; i < mFinishQueue.size(); i++) { | |
const Finish& finish = mFinishQueue.itemAt(i); | |
status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled); | |
... | |
} | |
mFinishQueue.clear(); | |
setFdEvents(ALOOPER_EVENT_INPUT); | |
return 1; | |
} | |
} | |
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, | |
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) { | |
#if DEBUG_DISPATCH_CYCLE | |
ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.", | |
getInputChannelName(), consumeBatches ? "true" : "false", frameTime); | |
#endif | |
if (consumeBatches) { | |
mBatchedInputEventPending = false; | |
} | |
if (outConsumedBatch) { | |
*outConsumedBatch = false; | |
} | |
ScopedLocalRef<jobject> receiverObj(env, NULL); | |
bool skipCallbacks = false; | |
for (;;) { | |
uint32_t seq; | |
InputEvent* inputEvent; | |
status_t status = mInputConsumer.consume(&mInputEventFactory, | |
consumeBatches, frameTime, &seq, &inputEvent); | |
if (status) { | |
if (status == WOULD_BLOCK) { | |
if (!skipCallbacks && !mBatchedInputEventPending | |
&& mInputConsumer.hasPendingBatch()) { | |
// There is a pending batch. Come back later. | |
if (!receiverObj.get()) { | |
receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal)); | |
if (!receiverObj.get()) { | |
ALOGW("channel '%s' ~ Receiver object was finalized " | |
"without being disposed.", getInputChannelName()); | |
return DEAD_OBJECT; | |
} | |
} | |
mBatchedInputEventPending = true; | |
#if DEBUG_DISPATCH_CYCLE | |
ALOGD("channel '%s' ~ Dispatching batched input event pending notification.", | |
getInputChannelName()); | |
#endif | |
env->CallVoidMethod(receiverObj.get(), | |
gInputEventReceiverClassInfo.dispatchBatchedInputEventPending); | |
if (env->ExceptionCheck()) { | |
ALOGE("Exception dispatching batched input events."); | |
mBatchedInputEventPending = false; // try again later | |
} | |
} | |
return OK; | |
} | |
ALOGE("channel '%s' ~ Failed to consume input event. status=%d", | |
getInputChannelName(), status); | |
return status; | |
} | |
assert(inputEvent); | |
if (!skipCallbacks) { | |
if (!receiverObj.get()) { | |
receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal)); | |
if (!receiverObj.get()) { | |
ALOGW("channel '%s' ~ Receiver object was finalized " | |
"without being disposed.", getInputChannelName()); | |
return DEAD_OBJECT; | |
} | |
} | |
jobject inputEventObj; | |
switch (inputEvent->getType()) { | |
case AINPUT_EVENT_TYPE_KEY: | |
#if DEBUG_DISPATCH_CYCLE | |
ALOGD("channel '%s' ~ Received key event.", getInputChannelName()); | |
#endif | |
inputEventObj = android_view_KeyEvent_fromNative(env, | |
static_cast<KeyEvent*>(inputEvent)); | |
break; | |
case AINPUT_EVENT_TYPE_MOTION: { | |
#if DEBUG_DISPATCH_CYCLE | |
ALOGD("channel '%s' ~ Received motion event.", getInputChannelName()); | |
#endif | |
MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent); | |
if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) { | |
*outConsumedBatch = true; | |
} | |
inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent); | |
break; | |
} | |
default: | |
assert(false); // InputConsumer should prevent this from ever happening | |
inputEventObj = NULL; | |
} | |
if (inputEventObj) { | |
#if DEBUG_DISPATCH_CYCLE | |
ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName()); | |
#endif | |
env->CallVoidMethod(receiverObj.get(), | |
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj); | |
if (env->ExceptionCheck()) { | |
ALOGE("Exception dispatching input event."); | |
skipCallbacks = true; | |
} | |
env->DeleteLocalRef(inputEventObj); | |
} else { | |
ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName()); | |
skipCallbacks = true; | |
} | |
} | |
if (skipCallbacks) { | |
mInputConsumer.sendFinishedSignal(seq, false); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment