Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1f3de40 authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

Merge "Be more careful about exceptions in input callbacks."

parents 50a92678 3bdcdd85
Loading
Loading
Loading
Loading
+45 −40
Original line number Original line Diff line number Diff line
@@ -52,8 +52,7 @@ public:


    status_t initialize();
    status_t initialize();
    status_t finishInputEvent(uint32_t seq, bool handled);
    status_t finishInputEvent(uint32_t seq, bool handled);
    status_t consumeEvents(bool consumeBatches);
    status_t consumeEvents(JNIEnv* env, bool consumeBatches);
    static int handleReceiveCallback(int receiveFd, int events, void* data);


protected:
protected:
    virtual ~NativeInputEventReceiver();
    virtual ~NativeInputEventReceiver();
@@ -68,6 +67,8 @@ private:
    const char* getInputChannelName() {
    const char* getInputChannelName() {
        return mInputConsumer.getChannel()->getName().string();
        return mInputConsumer.getChannel()->getName().string();
    }
    }

    static int handleReceiveCallback(int receiveFd, int events, void* data);
};
};




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


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


status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, bool consumeBatches) {
#if DEBUG_DISPATCH_CYCLE
#if DEBUG_DISPATCH_CYCLE
    ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s.", getInputChannelName(),
    ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s.", getInputChannelName(),
            consumeBatches ? "true" : "false");
            consumeBatches ? "true" : "false");
@@ -142,7 +145,7 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
        mBatchedInputEventPending = false;
        mBatchedInputEventPending = false;
    }
    }


    JNIEnv* env = AndroidRuntime::getJNIEnv();
    bool skipCallbacks = false;
    for (;;) {
    for (;;) {
        uint32_t seq;
        uint32_t seq;
        InputEvent* inputEvent;
        InputEvent* inputEvent;
@@ -150,7 +153,8 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
                consumeBatches, &seq, &inputEvent);
                consumeBatches, &seq, &inputEvent);
        if (status) {
        if (status) {
            if (status == WOULD_BLOCK) {
            if (status == WOULD_BLOCK) {
                if (mInputConsumer.hasPendingBatch() && !mBatchedInputEventPending) {
                if (!skipCallbacks && !mBatchedInputEventPending
                        && mInputConsumer.hasPendingBatch()) {
                    // There is a pending batch.  Come back later.
                    // There is a pending batch.  Come back later.
                    mBatchedInputEventPending = true;
                    mBatchedInputEventPending = true;
#if DEBUG_DISPATCH_CYCLE
#if DEBUG_DISPATCH_CYCLE
@@ -159,8 +163,8 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
#endif
#endif
                    env->CallVoidMethod(mReceiverObjGlobal,
                    env->CallVoidMethod(mReceiverObjGlobal,
                            gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
                            gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
                    if (mMessageQueue->raiseAndClearException(
                    if (env->ExceptionCheck()) {
                            env, "dispatchBatchedInputEventPending")) {
                        ALOGE("Exception dispatching batched input events.");
                        mBatchedInputEventPending = false; // try again later
                        mBatchedInputEventPending = false; // try again later
                    }
                    }
                }
                }
@@ -172,6 +176,7 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
        }
        }
        assert(inputEvent);
        assert(inputEvent);


        if (!skipCallbacks) {
            jobject inputEventObj;
            jobject inputEventObj;
            switch (inputEvent->getType()) {
            switch (inputEvent->getType()) {
            case AINPUT_EVENT_TYPE_KEY:
            case AINPUT_EVENT_TYPE_KEY:
@@ -180,7 +185,6 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
#endif
#endif
                inputEventObj = android_view_KeyEvent_fromNative(env,
                inputEventObj = android_view_KeyEvent_fromNative(env,
                        static_cast<KeyEvent*>(inputEvent));
                        static_cast<KeyEvent*>(inputEvent));
            mMessageQueue->raiseAndClearException(env, "new KeyEvent");
                break;
                break;


            case AINPUT_EVENT_TYPE_MOTION:
            case AINPUT_EVENT_TYPE_MOTION:
@@ -189,7 +193,6 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
#endif
#endif
                inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
                inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
                        static_cast<MotionEvent*>(inputEvent));
                        static_cast<MotionEvent*>(inputEvent));
            mMessageQueue->raiseAndClearException(env, "new MotionEvent");
                break;
                break;


            default:
            default:
@@ -197,21 +200,23 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
                inputEventObj = NULL;
                inputEventObj = NULL;
            }
            }


        if (!inputEventObj) {
            if (inputEventObj) {
            ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
            mInputConsumer.sendFinishedSignal(seq, false);
            continue;
        }

#if DEBUG_DISPATCH_CYCLE
#if DEBUG_DISPATCH_CYCLE
                ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
                ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
#endif
#endif
                env->CallVoidMethod(mReceiverObjGlobal,
                env->CallVoidMethod(mReceiverObjGlobal,
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
                if (env->ExceptionCheck()) {
                    ALOGE("Exception dispatching input event.");
                    skipCallbacks = true;
                }
            } else {
                ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
                skipCallbacks = true;
            }
        }


        env->DeleteLocalRef(inputEventObj);
        if (skipCallbacks) {

        if (mMessageQueue->raiseAndClearException(env, "dispatchInputEvent")) {
            mInputConsumer.sendFinishedSignal(seq, false);
            mInputConsumer.sendFinishedSignal(seq, false);
        }
        }
    }
    }
@@ -268,8 +273,8 @@ static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr,
static void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr) {
static void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr) {
    sp<NativeInputEventReceiver> receiver =
    sp<NativeInputEventReceiver> receiver =
            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
    status_t status = receiver->consumeEvents(true /*consumeBatches*/);
    status_t status = receiver->consumeEvents(env, true /*consumeBatches*/);
    if (status && status != DEAD_OBJECT) {
    if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
        String8 message;
        String8 message;
        message.appendFormat("Failed to consume batched input event.  status=%d", status);
        message.appendFormat("Failed to consume batched input event.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
        jniThrowRuntimeException(env, message.string());