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>
329d3b1a424c5c61e24e9659d15fb353026a00d925Jeff Brown#include <input/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);
5962ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright    status_t consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime,
6062ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright            bool* outConsumedBatch);
6132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
6232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownprotected:
6332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    virtual ~NativeInputEventReceiver();
6432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
6532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownprivate:
6656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    struct Finish {
6756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        uint32_t seq;
6856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        bool handled;
6956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    };
7056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
71a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    jobject mReceiverWeakGlobal;
7232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    InputConsumer mInputConsumer;
73603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    sp<MessageQueue> mMessageQueue;
7432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    PreallocatedInputEventFactory mInputEventFactory;
75072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    bool mBatchedInputEventPending;
7656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    int mFdEvents;
7756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    Vector<Finish> mFinishQueue;
7856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
7956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    void setFdEvents(int events);
8032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
8132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    const char* getInputChannelName() {
8232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return mInputConsumer.getChannel()->getName().string();
8332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
843bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown
8580a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    virtual int handleEvent(int receiveFd, int events, void* data);
8632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown};
8732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
8832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
8932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff BrownNativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
90a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown        jobject receiverWeak, const sp<InputChannel>& inputChannel,
91603b44589682db3ff33ade172facb0c5e309f1beJeff Brown        const sp<MessageQueue>& messageQueue) :
92a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
93603b44589682db3ff33ade172facb0c5e309f1beJeff Brown        mInputConsumer(inputChannel), mMessageQueue(messageQueue),
9456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        mBatchedInputEventPending(false), mFdEvents(0) {
9532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
965baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName());
9732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
9832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
9932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
10032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff BrownNativeInputEventReceiver::~NativeInputEventReceiver() {
10132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
102a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    env->DeleteGlobalRef(mReceiverWeakGlobal);
10332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
10432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
10532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatus_t NativeInputEventReceiver::initialize() {
10656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    setFdEvents(ALOOPER_EVENT_INPUT);
10732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return OK;
10832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
10932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
11080a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownvoid NativeInputEventReceiver::dispose() {
11180a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown#if DEBUG_DISPATCH_CYCLE
11280a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    ALOGD("channel '%s' ~ Disposing input event receiver.", getInputChannelName());
11380a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown#endif
11480a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown
11556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    setFdEvents(0);
11680a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown}
11780a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown
118072ec96a4900d4616574733646ee46311cb5d2cbJeff Brownstatus_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
11932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
120072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    ALOGD("channel '%s' ~ Finished input event.", getInputChannelName());
12132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
12232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
123072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
124072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    if (status) {
12556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        if (status == WOULD_BLOCK) {
12656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#if DEBUG_DISPATCH_CYCLE
12756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            ALOGD("channel '%s' ~ Could not send finished signal immediately.  "
12856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    "Enqueued for later.", getInputChannelName());
12956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#endif
13056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            Finish finish;
13156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            finish.seq = seq;
13256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            finish.handled = handled;
13356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            mFinishQueue.add(finish);
13456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            if (mFinishQueue.size() == 1) {
13556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
13656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            }
13756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            return OK;
13856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        }
139072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        ALOGW("Failed to send finished signal on channel '%s'.  status=%d",
140072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                getInputChannelName(), status);
14132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
142072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    return status;
14332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
14432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
14556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brownvoid NativeInputEventReceiver::setFdEvents(int events) {
14656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    if (mFdEvents != events) {
14756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        mFdEvents = events;
14856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        int fd = mInputConsumer.getChannel()->getFd();
14956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        if (events) {
15056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
15156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        } else {
15256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            mMessageQueue->getLooper()->removeFd(fd);
15356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        }
15456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    }
15556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown}
15656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
15780a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownint NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
15832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
15944e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown#if DEBUG_DISPATCH_CYCLE
16044e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // This error typically occurs when the publisher has closed the input channel
16144e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // as part of removing a window or finishing an IME session, in which case
16244e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // the consumer will soon be disposed as well.
16344e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred.  "
16480a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown                "events=0x%x", getInputChannelName(), events);
16544e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown#endif
16632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0; // remove the callback
16732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
16832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
16956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    if (events & ALOOPER_EVENT_INPUT) {
17056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        JNIEnv* env = AndroidRuntime::getJNIEnv();
17162ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
17256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
17356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        return status == OK || status == NO_MEMORY ? 1 : 0;
17456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    }
17556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
17656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    if (events & ALOOPER_EVENT_OUTPUT) {
17756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        for (size_t i = 0; i < mFinishQueue.size(); i++) {
17856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            const Finish& finish = mFinishQueue.itemAt(i);
17956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
18056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            if (status) {
18156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                mFinishQueue.removeItemsAt(0, i);
18256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
18356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                if (status == WOULD_BLOCK) {
18456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#if DEBUG_DISPATCH_CYCLE
18556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    ALOGD("channel '%s' ~ Sent %u queued finish events; %u left.",
18656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                            getInputChannelName(), i, mFinishQueue.size());
18756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#endif
18856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    return 1; // keep the callback, try again later
18956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                }
19056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown
19156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                ALOGW("Failed to send finished signal on channel '%s'.  status=%d",
19256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                        getInputChannelName(), status);
19356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                if (status != DEAD_OBJECT) {
19456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    JNIEnv* env = AndroidRuntime::getJNIEnv();
19556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    String8 message;
19656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    message.appendFormat("Failed to finish input event.  status=%d", status);
19756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    jniThrowRuntimeException(env, message.string());
19856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                    mMessageQueue->raiseAndClearException(env, "finishInputEvent");
19956513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                }
20056513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                return 0; // remove the callback
20156513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            }
20256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        }
20356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#if DEBUG_DISPATCH_CYCLE
20456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        ALOGD("channel '%s' ~ Sent %u queued finish events; none left.",
20556513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown                getInputChannelName(), mFinishQueue.size());
20656513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown#endif
20756513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        mFinishQueue.clear();
20856513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown        setFdEvents(ALOOPER_EVENT_INPUT);
20932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 1;
21032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
21132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
21256513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
21356513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown            "events=0x%x", getInputChannelName(), events);
21456513492ea6d4a72584cbc01979f7b3fa3c2807fJeff Brown    return 1;
215072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown}
21632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
217771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brownstatus_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
21862ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
219072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#if DEBUG_DISPATCH_CYCLE
220771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown    ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.",
221771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown            getInputChannelName(), consumeBatches ? "true" : "false", frameTime);
222072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#endif
223072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown
224072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    if (consumeBatches) {
225072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        mBatchedInputEventPending = false;
22632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
22762ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright    if (outConsumedBatch) {
22862ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright        *outConsumedBatch = false;
22962ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright    }
23032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
231a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    ScopedLocalRef<jobject> receiverObj(env, NULL);
2323bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown    bool skipCallbacks = false;
233072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    for (;;) {
234072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        uint32_t seq;
235072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        InputEvent* inputEvent;
236072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        status_t status = mInputConsumer.consume(&mInputEventFactory,
237771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown                consumeBatches, frameTime, &seq, &inputEvent);
238072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        if (status) {
239072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            if (status == WOULD_BLOCK) {
2403bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                if (!skipCallbacks && !mBatchedInputEventPending
2413bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        && mInputConsumer.hasPendingBatch()) {
242072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    // There is a pending batch.  Come back later.
243a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    if (!receiverObj.get()) {
244a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                        receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
245a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                        if (!receiverObj.get()) {
246a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                            ALOGW("channel '%s' ~ Receiver object was finalized "
247a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                                    "without being disposed.", getInputChannelName());
248a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                            return DEAD_OBJECT;
249a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                        }
250a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    }
251a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown
252072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    mBatchedInputEventPending = true;
25332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
254072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    ALOGD("channel '%s' ~ Dispatching batched input event pending notification.",
255072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                            getInputChannelName());
25632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
257a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    env->CallVoidMethod(receiverObj.get(),
258072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                            gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
2593bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                    if (env->ExceptionCheck()) {
2603bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        ALOGE("Exception dispatching batched input events.");
261072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                        mBatchedInputEventPending = false; // try again later
262072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    }
263072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                }
264072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                return OK;
265072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            }
266072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            ALOGE("channel '%s' ~ Failed to consume input event.  status=%d",
267072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    getInputChannelName(), status);
268072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            return status;
269072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        }
270072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        assert(inputEvent);
27132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
2723bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown        if (!skipCallbacks) {
273a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            if (!receiverObj.get()) {
274a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
275a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                if (!receiverObj.get()) {
276a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    ALOGW("channel '%s' ~ Receiver object was finalized "
277a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                            "without being disposed.", getInputChannelName());
278a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    return DEAD_OBJECT;
279a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                }
280a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            }
281a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown
2823bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            jobject inputEventObj;
2833bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            switch (inputEvent->getType()) {
2843bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            case AINPUT_EVENT_TYPE_KEY:
28532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
2863bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGD("channel '%s' ~ Received key event.", getInputChannelName());
28732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
2883bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                inputEventObj = android_view_KeyEvent_fromNative(env,
2893bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        static_cast<KeyEvent*>(inputEvent));
2903bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                break;
29132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
29262ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright            case AINPUT_EVENT_TYPE_MOTION: {
293072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#if DEBUG_DISPATCH_CYCLE
2943bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGD("channel '%s' ~ Received motion event.", getInputChannelName());
295072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#endif
29662ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright                MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);
29762ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright                if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) {
29862ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright                    *outConsumedBatch = true;
29962ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright                }
30062ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright                inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
3013bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                break;
30262ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright            }
30332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
3043bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            default:
3053bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                assert(false); // InputConsumer should prevent this from ever happening
3063bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                inputEventObj = NULL;
3073bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            }
30832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
3093bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            if (inputEventObj) {
31032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
3113bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
31232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
313a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                env->CallVoidMethod(receiverObj.get(),
3143bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
3153bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                if (env->ExceptionCheck()) {
3163bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                    ALOGE("Exception dispatching input event.");
3173bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                    skipCallbacks = true;
3183bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                }
319a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                env->DeleteLocalRef(inputEventObj);
3203bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            } else {
3213bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
3223bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                skipCallbacks = true;
3233bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            }
3243bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown        }
32532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
3263bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown        if (skipCallbacks) {
327072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            mInputConsumer.sendFinishedSignal(seq, false);
32832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        }
32932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
33032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
33132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
33232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
333a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brownstatic jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
33432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jobject inputChannelObj, jobject messageQueueObj) {
33532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
33632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            inputChannelObj);
33732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (inputChannel == NULL) {
33832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, "InputChannel is not initialized.");
33932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
34032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
34132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
342603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
343603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    if (messageQueue == NULL) {
34432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
34532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
34632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
34732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
34832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
349a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            receiverWeak, inputChannel, messageQueue);
35032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t status = receiver->initialize();
35132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (status) {
35232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        String8 message;
35332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        message.appendFormat("Failed to initialize input event receiver.  status=%d", status);
35432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, message.string());
35532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
35632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
35732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
35832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
35932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return reinterpret_cast<jint>(receiver.get());
36032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
36132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
36232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) {
36332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver =
36432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
36580a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    receiver->dispose();
36632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    receiver->decStrong(gInputEventReceiverClassInfo.clazz); // drop reference held by the object
36732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
36832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
369072ec96a4900d4616574733646ee46311cb5d2cbJeff Brownstatic void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr,
370072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        jint seq, jboolean handled) {
37132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver =
37232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
373072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    status_t status = receiver->finishInputEvent(seq, handled);
3749806a2307f3e47e847ad5e62e302eab36d3eb3e4Jeff Brown    if (status && status != DEAD_OBJECT) {
37532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        String8 message;
37632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        message.appendFormat("Failed to finish input event.  status=%d", status);
37732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, message.string());
37832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
37932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
38032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
38162ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wrightstatic bool nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr,
382771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown        jlong frameTimeNanos) {
383072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    sp<NativeInputEventReceiver> receiver =
384072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
38562ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright    bool consumedBatch;
38662ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright    status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos,
38762ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright            &consumedBatch);
3883bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown    if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
389072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        String8 message;
390072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        message.appendFormat("Failed to consume batched input event.  status=%d", status);
391072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        jniThrowRuntimeException(env, message.string());
39262ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright        return false;
393072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    }
39462ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright    return consumedBatch;
395072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown}
396072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown
39732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
39832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic JNINativeMethod gMethods[] = {
39932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    /* name, signature, funcPtr */
40032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    { "nativeInit",
401a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            "(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)I",
40232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            (void*)nativeInit },
403072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    { "nativeDispose", "(I)V",
40432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            (void*)nativeDispose },
405072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    { "nativeFinishInputEvent", "(IIZ)V",
406072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            (void*)nativeFinishInputEvent },
40762ce65d6edbc2c34c63b0e2f2fef9cb08e28c783Michael Wright    { "nativeConsumeBatchedInputEvents", "(IJ)Z",
408072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            (void*)nativeConsumeBatchedInputEvents },
40932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown};
41032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
41132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define FIND_CLASS(var, className) \
41232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = env->FindClass(className); \
41332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className); \
41432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = jclass(env->NewGlobalRef(var));
41532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
41632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
41732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
41832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOG_FATAL_IF(! var, "Unable to find method " methodName);
41932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
42032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownint register_android_view_InputEventReceiver(JNIEnv* env) {
42132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    int res = jniRegisterNativeMethods(env, "android/view/InputEventReceiver",
42232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            gMethods, NELEM(gMethods));
42332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
42432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
42532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    FIND_CLASS(gInputEventReceiverClassInfo.clazz, "android/view/InputEventReceiver");
42632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
42732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchInputEvent,
42832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            gInputEventReceiverClassInfo.clazz,
429072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            "dispatchInputEvent", "(ILandroid/view/InputEvent;)V");
430072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchBatchedInputEventPending,
431072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            gInputEventReceiverClassInfo.clazz,
432072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            "dispatchBatchedInputEventPending", "()V");
43332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return 0;
43432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
43532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
43632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} // namespace android
437