android_view_InputEventReceiver.cpp revision 56513492ea6d4a72584cbc01979f7b3fa3c2807f
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>
3056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#include <utils/Vector.h>
3132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include <utils/threads.h>
32b93a03f841d93498bfea6cc92a22faa34bce1337Mathias Agopian#include <androidfw/InputTransport.h>
3332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include "android_os_MessageQueue.h"
3432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include "android_view_InputChannel.h"
3532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include "android_view_KeyEvent.h"
3632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#include "android_view_MotionEvent.h"
3732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
38a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown#include <ScopedLocalRef.h>
39a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown
4032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownnamespace android {
4132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
4232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic struct {
4332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    jclass clazz;
4432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
4532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    jmethodID dispatchInputEvent;
46072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    jmethodID dispatchBatchedInputEventPending;
4732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} gInputEventReceiverClassInfo;
4832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
4932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
5080a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownclass NativeInputEventReceiver : public LooperCallback {
5132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownpublic:
5232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    NativeInputEventReceiver(JNIEnv* env,
53a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            jobject receiverWeak, const sp<InputChannel>& inputChannel,
54603b44589682db3ff33ade172facb0c5e309f1beJeff Brown            const sp<MessageQueue>& messageQueue);
5532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
5632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t initialize();
5780a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    void dispose();
58072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    status_t finishInputEvent(uint32_t seq, bool handled);
59771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown    status_t consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime);
6032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
6132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownprotected:
6232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    virtual ~NativeInputEventReceiver();
6332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
6432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownprivate:
6556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    struct Finish {
6656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        uint32_t seq;
6756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        bool handled;
6856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    };
6956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
70a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    jobject mReceiverWeakGlobal;
7132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    InputConsumer mInputConsumer;
72603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    sp<MessageQueue> mMessageQueue;
7332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    PreallocatedInputEventFactory mInputEventFactory;
74072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    bool mBatchedInputEventPending;
7556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    int mFdEvents;
7656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    Vector<Finish> mFinishQueue;
7756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
7856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    void setFdEvents(int events);
7932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
8032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    const char* getInputChannelName() {
8132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return mInputConsumer.getChannel()->getName().string();
8232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
833bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown
8480a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    virtual int handleEvent(int receiveFd, int events, void* data);
8532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown};
8632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
8732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
8832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff BrownNativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
89a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown        jobject receiverWeak, const sp<InputChannel>& inputChannel,
90603b44589682db3ff33ade172facb0c5e309f1beJeff Brown        const sp<MessageQueue>& messageQueue) :
91a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
92603b44589682db3ff33ade172facb0c5e309f1beJeff Brown        mInputConsumer(inputChannel), mMessageQueue(messageQueue),
9356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        mBatchedInputEventPending(false), mFdEvents(0) {
9432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
955baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName());
9632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
9732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
9832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
9932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff BrownNativeInputEventReceiver::~NativeInputEventReceiver() {
10032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
101a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    env->DeleteGlobalRef(mReceiverWeakGlobal);
10232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
10332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
10432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatus_t NativeInputEventReceiver::initialize() {
10556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    setFdEvents(ALOOPER_EVENT_INPUT);
10632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return OK;
10732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
10832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
10980a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownvoid NativeInputEventReceiver::dispose() {
11080a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown#if DEBUG_DISPATCH_CYCLE
11180a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    ALOGD("channel '%s' ~ Disposing input event receiver.", getInputChannelName());
11280a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown#endif
11380a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown
11456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    setFdEvents(0);
11580a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown}
11680a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown
117072ec96a4900d4616574733646ee46311cb5d2cbJeff Brownstatus_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
11832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
119072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    ALOGD("channel '%s' ~ Finished input event.", getInputChannelName());
12032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
12132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
122072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
123072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    if (status) {
12456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        if (status == WOULD_BLOCK) {
12556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#if DEBUG_DISPATCH_CYCLE
12656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            ALOGD("channel '%s' ~ Could not send finished signal immediately.  "
12756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    "Enqueued for later.", getInputChannelName());
12856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#endif
12956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            Finish finish;
13056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            finish.seq = seq;
13156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            finish.handled = handled;
13256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            mFinishQueue.add(finish);
13356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            if (mFinishQueue.size() == 1) {
13456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
13556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            }
13656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            return OK;
13756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        }
138072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        ALOGW("Failed to send finished signal on channel '%s'.  status=%d",
139072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                getInputChannelName(), status);
14032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
141072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    return status;
14232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
14332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
14456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brownvoid NativeInputEventReceiver::setFdEvents(int events) {
14556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    if (mFdEvents != events) {
14656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        mFdEvents = events;
14756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        int fd = mInputConsumer.getChannel()->getFd();
14856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        if (events) {
14956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
15056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        } else {
15156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            mMessageQueue->getLooper()->removeFd(fd);
15256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        }
15356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    }
15456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown}
15556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
15680a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownint NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
15732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
15844e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown#if DEBUG_DISPATCH_CYCLE
15944e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // This error typically occurs when the publisher has closed the input channel
16044e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // as part of removing a window or finishing an IME session, in which case
16144e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // the consumer will soon be disposed as well.
16244e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred.  "
16380a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown                "events=0x%x", getInputChannelName(), events);
16444e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown#endif
16532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0; // remove the callback
16632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
16732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
16856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    if (events & ALOOPER_EVENT_INPUT) {
16956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        JNIEnv* env = AndroidRuntime::getJNIEnv();
17056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        status_t status = consumeEvents(env, false /*consumeBatches*/, -1);
17156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
17256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        return status == OK || status == NO_MEMORY ? 1 : 0;
17356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    }
17456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
17556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    if (events & ALOOPER_EVENT_OUTPUT) {
17656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        for (size_t i = 0; i < mFinishQueue.size(); i++) {
17756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            const Finish& finish = mFinishQueue.itemAt(i);
17856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
17956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            if (status) {
18056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                mFinishQueue.removeItemsAt(0, i);
18156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
18256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                if (status == WOULD_BLOCK) {
18356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#if DEBUG_DISPATCH_CYCLE
18456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    ALOGD("channel '%s' ~ Sent %u queued finish events; %u left.",
18556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                            getInputChannelName(), i, mFinishQueue.size());
18656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#endif
18756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    return 1; // keep the callback, try again later
18856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                }
18956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
19056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                ALOGW("Failed to send finished signal on channel '%s'.  status=%d",
19156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                        getInputChannelName(), status);
19256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                if (status != DEAD_OBJECT) {
19356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    JNIEnv* env = AndroidRuntime::getJNIEnv();
19456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    String8 message;
19556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    message.appendFormat("Failed to finish input event.  status=%d", status);
19656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    jniThrowRuntimeException(env, message.string());
19756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    mMessageQueue->raiseAndClearException(env, "finishInputEvent");
19856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                }
19956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                return 0; // remove the callback
20056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            }
20156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        }
20256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#if DEBUG_DISPATCH_CYCLE
20356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        ALOGD("channel '%s' ~ Sent %u queued finish events; none left.",
20456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                getInputChannelName(), mFinishQueue.size());
20556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#endif
20656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        mFinishQueue.clear();
20756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        setFdEvents(ALOOPER_EVENT_INPUT);
20832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 1;
20932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
21032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
21156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
21256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            "events=0x%x", getInputChannelName(), events);
21356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    return 1;
214072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown}
21532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
216771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brownstatus_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
217771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown        bool consumeBatches, nsecs_t frameTime) {
218072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#if DEBUG_DISPATCH_CYCLE
219771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown    ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.",
220771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown            getInputChannelName(), consumeBatches ? "true" : "false", frameTime);
221072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#endif
222072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown
223072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    if (consumeBatches) {
224072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        mBatchedInputEventPending = false;
22532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
22632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
227a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    ScopedLocalRef<jobject> receiverObj(env, NULL);
2283bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown    bool skipCallbacks = false;
229072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    for (;;) {
230072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        uint32_t seq;
231072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        InputEvent* inputEvent;
232072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        status_t status = mInputConsumer.consume(&mInputEventFactory,
233771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown                consumeBatches, frameTime, &seq, &inputEvent);
234072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        if (status) {
235072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            if (status == WOULD_BLOCK) {
2363bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                if (!skipCallbacks && !mBatchedInputEventPending
2373bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        && mInputConsumer.hasPendingBatch()) {
238072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    // There is a pending batch.  Come back later.
239a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    if (!receiverObj.get()) {
240a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                        receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
241a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                        if (!receiverObj.get()) {
242a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                            ALOGW("channel '%s' ~ Receiver object was finalized "
243a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                                    "without being disposed.", getInputChannelName());
244a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                            return DEAD_OBJECT;
245a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                        }
246a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    }
247a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown
248072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    mBatchedInputEventPending = true;
24932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
250072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    ALOGD("channel '%s' ~ Dispatching batched input event pending notification.",
251072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                            getInputChannelName());
25232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
253a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    env->CallVoidMethod(receiverObj.get(),
254072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                            gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
2553bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                    if (env->ExceptionCheck()) {
2563bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        ALOGE("Exception dispatching batched input events.");
257072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                        mBatchedInputEventPending = false; // try again later
258072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    }
259072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                }
260072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                return OK;
261072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            }
262072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            ALOGE("channel '%s' ~ Failed to consume input event.  status=%d",
263072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    getInputChannelName(), status);
264072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            return status;
265072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        }
266072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        assert(inputEvent);
26732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
2683bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown        if (!skipCallbacks) {
269a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            if (!receiverObj.get()) {
270a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
271a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                if (!receiverObj.get()) {
272a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    ALOGW("channel '%s' ~ Receiver object was finalized "
273a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                            "without being disposed.", getInputChannelName());
274a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    return DEAD_OBJECT;
275a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                }
276a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            }
277a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown
2783bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            jobject inputEventObj;
2793bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            switch (inputEvent->getType()) {
2803bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            case AINPUT_EVENT_TYPE_KEY:
28132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
2823bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGD("channel '%s' ~ Received key event.", getInputChannelName());
28332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
2843bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                inputEventObj = android_view_KeyEvent_fromNative(env,
2853bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        static_cast<KeyEvent*>(inputEvent));
2863bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                break;
28732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
2883bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            case AINPUT_EVENT_TYPE_MOTION:
289072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#if DEBUG_DISPATCH_CYCLE
2903bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGD("channel '%s' ~ Received motion event.", getInputChannelName());
291072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#endif
2923bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
2933bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        static_cast<MotionEvent*>(inputEvent));
2943bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                break;
29532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
2963bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            default:
2973bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                assert(false); // InputConsumer should prevent this from ever happening
2983bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                inputEventObj = NULL;
2993bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            }
30032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
3013bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            if (inputEventObj) {
30232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
3033bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
30432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
305a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                env->CallVoidMethod(receiverObj.get(),
3063bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
3073bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                if (env->ExceptionCheck()) {
3083bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                    ALOGE("Exception dispatching input event.");
3093bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                    skipCallbacks = true;
3103bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                }
311a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                env->DeleteLocalRef(inputEventObj);
3123bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            } else {
3133bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
3143bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                skipCallbacks = true;
3153bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            }
3163bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown        }
31732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
3183bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown        if (skipCallbacks) {
319072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            mInputConsumer.sendFinishedSignal(seq, false);
32032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        }
32132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
32232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
32332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
32432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
325a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brownstatic jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
32632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jobject inputChannelObj, jobject messageQueueObj) {
32732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
32832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            inputChannelObj);
32932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (inputChannel == NULL) {
33032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, "InputChannel is not initialized.");
33132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
33232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
33332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
334603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
335603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    if (messageQueue == NULL) {
33632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
33732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
33832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
33932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
34032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
341a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            receiverWeak, inputChannel, messageQueue);
34232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t status = receiver->initialize();
34332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (status) {
34432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        String8 message;
34532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        message.appendFormat("Failed to initialize input event receiver.  status=%d", status);
34632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, message.string());
34732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
34832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
34932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
35032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
35132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return reinterpret_cast<jint>(receiver.get());
35232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
35332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
35432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) {
35532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver =
35632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
35780a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    receiver->dispose();
35832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    receiver->decStrong(gInputEventReceiverClassInfo.clazz); // drop reference held by the object
35932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
36032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
361072ec96a4900d4616574733646ee46311cb5d2cbJeff Brownstatic void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr,
362072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        jint seq, jboolean handled) {
36332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver =
36432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
365072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    status_t status = receiver->finishInputEvent(seq, handled);
3669806a2307f3e47e847ad5e62e302eab36d3eb3e4Jeff Brown    if (status && status != DEAD_OBJECT) {
36732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        String8 message;
36832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        message.appendFormat("Failed to finish input event.  status=%d", status);
36932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, message.string());
37032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
37132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
37232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
373771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brownstatic void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr,
374771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown        jlong frameTimeNanos) {
375072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    sp<NativeInputEventReceiver> receiver =
376072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
377771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown    status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos);
3783bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown    if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
379072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        String8 message;
380072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        message.appendFormat("Failed to consume batched input event.  status=%d", status);
381072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        jniThrowRuntimeException(env, message.string());
382072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    }
383072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown}
384072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown
38532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
38632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic JNINativeMethod gMethods[] = {
38732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    /* name, signature, funcPtr */
38832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    { "nativeInit",
389a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            "(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)I",
39032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            (void*)nativeInit },
391072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    { "nativeDispose", "(I)V",
39232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            (void*)nativeDispose },
393072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    { "nativeFinishInputEvent", "(IIZ)V",
394072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            (void*)nativeFinishInputEvent },
395771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown    { "nativeConsumeBatchedInputEvents", "(IJ)V",
396072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            (void*)nativeConsumeBatchedInputEvents },
39732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown};
39832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
39932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define FIND_CLASS(var, className) \
40032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = env->FindClass(className); \
40132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className); \
40232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = jclass(env->NewGlobalRef(var));
40332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
40432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
40532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
40632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOG_FATAL_IF(! var, "Unable to find method " methodName);
40732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
40832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownint register_android_view_InputEventReceiver(JNIEnv* env) {
40932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    int res = jniRegisterNativeMethods(env, "android/view/InputEventReceiver",
41032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            gMethods, NELEM(gMethods));
41132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
41232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
41332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    FIND_CLASS(gInputEventReceiverClassInfo.clazz, "android/view/InputEventReceiver");
41432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
41532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchInputEvent,
41632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            gInputEventReceiverClassInfo.clazz,
417072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            "dispatchInputEvent", "(ILandroid/view/InputEvent;)V");
418072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchBatchedInputEventPending,
419072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            gInputEventReceiverClassInfo.clazz,
420072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            "dispatchBatchedInputEventPending", "()V");
42132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return 0;
42232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
42332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
42432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} // namespace android
425