android_view_InputEventReceiver.cpp revision 5baa3a62a97544669fba6d65a11c07f252e654dd
132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown/*
232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown * Copyright (C) 2011 The Android Open Source Project
332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown *
432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown * you may not use this file except in compliance with the License.
632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown * You may obtain a copy of the License at
732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown *
832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown *
1032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown * Unless required by applicable law or agreed to in writing, software
1132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown * See the License for the specific language governing permissions and
1432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown * limitations under the License.
1532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown */
1632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
1732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define LOG_TAG "InputEventReceiver"
1832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
1932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown//#define LOG_NDEBUG 0
2032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
2132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown// Log debug messages about the dispatch cycle.
2232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define DEBUG_DISPATCH_CYCLE 0
2332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
2432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
2532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include "JNIHelp.h"
2632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
2732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include <android_runtime/AndroidRuntime.h>
2832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include <utils/Log.h>
2932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include <utils/Looper.h>
3032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include <utils/threads.h>
3132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include <ui/InputTransport.h>
3232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include "android_os_MessageQueue.h"
3332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include "android_view_InputChannel.h"
3432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include "android_view_KeyEvent.h"
3532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include "android_view_MotionEvent.h"
3632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
3732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownnamespace android {
3832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
3932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic struct {
4032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    jclass clazz;
4132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
4232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    jmethodID dispatchInputEvent;
4332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} gInputEventReceiverClassInfo;
4432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
4532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
4632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownclass NativeInputEventReceiver : public RefBase {
4732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownpublic:
4832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    NativeInputEventReceiver(JNIEnv* env,
4932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            jobject receiverObj, const sp<InputChannel>& inputChannel,
5032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            const sp<Looper>& looper);
5132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
5232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t initialize();
5332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t finishInputEvent(bool handled);
5432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    static int handleReceiveCallback(int receiveFd, int events, void* data);
5532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
5632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownprotected:
5732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    virtual ~NativeInputEventReceiver();
5832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
5932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownprivate:
6032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    jobject mReceiverObjGlobal;
6132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    InputConsumer mInputConsumer;
6232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<Looper> mLooper;
6332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    bool mEventInProgress;
6432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    PreallocatedInputEventFactory mInputEventFactory;
6532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
6632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    const char* getInputChannelName() {
6732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return mInputConsumer.getChannel()->getName().string();
6832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
6932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown};
7032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
7132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
7232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff BrownNativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
7332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jobject receiverObj, const sp<InputChannel>& inputChannel, const sp<Looper>& looper) :
7432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        mReceiverObjGlobal(env->NewGlobalRef(receiverObj)),
7532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        mInputConsumer(inputChannel), mLooper(looper), mEventInProgress(false) {
7632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
775baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName());
7832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
7932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
8032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
8132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff BrownNativeInputEventReceiver::~NativeInputEventReceiver() {
8232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
835baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("channel '%s' ~ Disposing input event receiver.", getInputChannelName());
8432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
8532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
8632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    mLooper->removeFd(mInputConsumer.getChannel()->getReceivePipeFd());
8732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (mEventInProgress) {
8832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        mInputConsumer.sendFinishedSignal(false); // ignoring result
8932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
9032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
9132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
9232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    env->DeleteGlobalRef(mReceiverObjGlobal);
9332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
9432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
9532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatus_t NativeInputEventReceiver::initialize() {
9632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t result = mInputConsumer.initialize();
9732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (result) {
9832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOGW("Failed to initialize input consumer for input channel '%s', status=%d",
9932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                getInputChannelName(), result);
10032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return result;
10132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
10232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
10332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    int32_t receiveFd = mInputConsumer.getChannel()->getReceivePipeFd();
10432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
10532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return OK;
10632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
10732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
10832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatus_t NativeInputEventReceiver::finishInputEvent(bool handled) {
10932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (mEventInProgress) {
11032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
1115baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("channel '%s' ~ Finished input event.", getInputChannelName());
11232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
11332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        mEventInProgress = false;
11432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
11532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        status_t status = mInputConsumer.sendFinishedSignal(handled);
11632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        if (status) {
11732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            LOGW("Failed to send finished signal on channel '%s'.  status=%d",
11832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                    getInputChannelName(), status);
11932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        }
12032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return status;
12132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    } else {
12232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOGW("Ignoring attempt to finish input event while no event is in progress.");
12332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return OK;
12432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
12532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
12632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
12732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownint NativeInputEventReceiver::handleReceiveCallback(int receiveFd, int events, void* data) {
12832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> r = static_cast<NativeInputEventReceiver*>(data);
12932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
13032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
13132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOGE("channel '%s' ~ Publisher closed input channel or an error occurred.  "
13232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                "events=0x%x", r->getInputChannelName(), events);
13332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0; // remove the callback
13432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
13532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
13632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (!(events & ALOOPER_EVENT_INPUT)) {
13732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
13832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                "events=0x%x", r->getInputChannelName(), events);
13932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 1;
14032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
14132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
14232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t status = r->mInputConsumer.receiveDispatchSignal();
14332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (status) {
14432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOGE("channel '%s' ~ Failed to receive dispatch signal.  status=%d",
14532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                r->getInputChannelName(), status);
14632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0; // remove the callback
14732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
14832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
14932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (r->mEventInProgress) {
15032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOGW("channel '%s' ~ Publisher sent spurious dispatch signal.",
15132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                r->getInputChannelName());
15232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 1;
15332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
15432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
15532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    InputEvent* inputEvent;
15632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status = r->mInputConsumer.consume(&r->mInputEventFactory, &inputEvent);
15732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (status) {
15832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOGW("channel '%s' ~ Failed to consume input event.  status=%d",
15932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                r->getInputChannelName(), status);
16032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        r->mInputConsumer.sendFinishedSignal(false);
16132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 1;
16232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
16332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
16432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
16532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    jobject inputEventObj;
16632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    switch (inputEvent->getType()) {
16732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    case AINPUT_EVENT_TYPE_KEY:
16832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
1695baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("channel '%s' ~ Received key event.",
17032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                r->getInputChannelName());
17132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
17232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        inputEventObj = android_view_KeyEvent_fromNative(env,
17332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                static_cast<KeyEvent*>(inputEvent));
17432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        break;
17532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
17632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    case AINPUT_EVENT_TYPE_MOTION:
17732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
1785baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        ALOGD("channel '%s' ~ Received motion event.",
17932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                r->getInputChannelName());
18032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
18132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
18232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                static_cast<MotionEvent*>(inputEvent));
18332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        break;
18432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
18532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    default:
18632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        assert(false); // InputConsumer should prevent this from ever happening
18732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        inputEventObj = NULL;
18832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
18932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
19032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (!inputEventObj) {
19132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOGW("channel '%s' ~ Failed to obtain event object.",
19232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                r->getInputChannelName());
19332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        r->mInputConsumer.sendFinishedSignal(false);
19432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 1;
19532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
19632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
19732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    r->mEventInProgress = true;
19832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
19932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
2005baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("channel '%s' ~ Invoking input handler.", r->getInputChannelName());
20132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
20232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    env->CallVoidMethod(r->mReceiverObjGlobal,
20332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            gInputEventReceiverClassInfo.dispatchInputEvent, inputEventObj);
20432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
2055baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("channel '%s' ~ Returned from input handler.", r->getInputChannelName());
20632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
20732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
20832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (env->ExceptionCheck()) {
20932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOGE("channel '%s' ~ An exception occurred while dispatching an event.",
21032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown                r->getInputChannelName());
21132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOGE_EX(env);
21232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        env->ExceptionClear();
21332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
21432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        if (r->mEventInProgress) {
21532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            r->mInputConsumer.sendFinishedSignal(false);
21632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            r->mEventInProgress = false;
21732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        }
21832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
21932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
22032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    env->DeleteLocalRef(inputEventObj);
22132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return 1;
22232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
22332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
22432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
22532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
22632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jobject inputChannelObj, jobject messageQueueObj) {
22732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
22832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            inputChannelObj);
22932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (inputChannel == NULL) {
23032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, "InputChannel is not initialized.");
23132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
23232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
23332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
23432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
23532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (looper == NULL) {
23632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
23732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
23832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
23932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
24032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
24132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            receiverObj, inputChannel, looper);
24232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t status = receiver->initialize();
24332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (status) {
24432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        String8 message;
24532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        message.appendFormat("Failed to initialize input event receiver.  status=%d", status);
24632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, message.string());
24732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
24832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
24932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
25032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
25132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return reinterpret_cast<jint>(receiver.get());
25232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
25332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
25432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) {
25532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver =
25632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
25732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    receiver->decStrong(gInputEventReceiverClassInfo.clazz); // drop reference held by the object
25832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
25932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
26032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr, jboolean handled) {
26132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver =
26232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
26332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t status = receiver->finishInputEvent(handled);
26432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (status) {
26532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        String8 message;
26632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        message.appendFormat("Failed to finish input event.  status=%d", status);
26732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, message.string());
26832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
26932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
27032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
27132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
27232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic JNINativeMethod gMethods[] = {
27332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    /* name, signature, funcPtr */
27432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    { "nativeInit",
27532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            "(Landroid/view/InputEventReceiver;Landroid/view/InputChannel;Landroid/os/MessageQueue;)I",
27632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            (void*)nativeInit },
27732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    { "nativeDispose",
27832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            "(I)V",
27932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            (void*)nativeDispose },
28032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    { "nativeFinishInputEvent", "(IZ)V",
28132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            (void*)nativeFinishInputEvent }
28232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown};
28332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
28432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define FIND_CLASS(var, className) \
28532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = env->FindClass(className); \
28632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className); \
28732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = jclass(env->NewGlobalRef(var));
28832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
28932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
29032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
29132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOG_FATAL_IF(! var, "Unable to find method " methodName);
29232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
29332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownint register_android_view_InputEventReceiver(JNIEnv* env) {
29432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    int res = jniRegisterNativeMethods(env, "android/view/InputEventReceiver",
29532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            gMethods, NELEM(gMethods));
29632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
29732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
29832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    FIND_CLASS(gInputEventReceiverClassInfo.clazz, "android/view/InputEventReceiver");
29932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
30032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchInputEvent,
30132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            gInputEventReceiverClassInfo.clazz,
30232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            "dispatchInputEvent", "(Landroid/view/InputEvent;)V");
30332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return 0;
30432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
30532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
30632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} // namespace android
307