android_view_InputEventReceiver.cpp revision 80a1de1007ddc62e1af2a4746008f499145aeaab
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>
31b93a03f841d93498bfea6cc92a22faa34bce1337Mathias Agopian#include <androidfw/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;
43072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    jmethodID dispatchBatchedInputEventPending;
4432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} gInputEventReceiverClassInfo;
4532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
4632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
4780a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownclass NativeInputEventReceiver : public LooperCallback {
4832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownpublic:
4932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    NativeInputEventReceiver(JNIEnv* env,
5032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            jobject receiverObj, const sp<InputChannel>& inputChannel,
51603b44589682db3ff33ade172facb0c5e309f1beJeff Brown            const sp<MessageQueue>& messageQueue);
5232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
5332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t initialize();
5480a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    void dispose();
55072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    status_t finishInputEvent(uint32_t seq, bool handled);
56771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown    status_t consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime);
5732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
5832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownprotected:
5932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    virtual ~NativeInputEventReceiver();
6032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
6132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownprivate:
6232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    jobject mReceiverObjGlobal;
6332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    InputConsumer mInputConsumer;
64603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    sp<MessageQueue> mMessageQueue;
6532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    PreallocatedInputEventFactory mInputEventFactory;
66072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    bool mBatchedInputEventPending;
6732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
6832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    const char* getInputChannelName() {
6932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return mInputConsumer.getChannel()->getName().string();
7032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
713bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown
7280a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    virtual int handleEvent(int receiveFd, int events, void* data);
7332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown};
7432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
7532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
7632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff BrownNativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
77603b44589682db3ff33ade172facb0c5e309f1beJeff Brown        jobject receiverObj, const sp<InputChannel>& inputChannel,
78603b44589682db3ff33ade172facb0c5e309f1beJeff Brown        const sp<MessageQueue>& messageQueue) :
7932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        mReceiverObjGlobal(env->NewGlobalRef(receiverObj)),
80603b44589682db3ff33ade172facb0c5e309f1beJeff Brown        mInputConsumer(inputChannel), mMessageQueue(messageQueue),
81072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        mBatchedInputEventPending(false) {
8232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
835baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName());
8432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
8532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
8632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
8732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff BrownNativeInputEventReceiver::~NativeInputEventReceiver() {
8832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
8932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    env->DeleteGlobalRef(mReceiverObjGlobal);
9032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
9132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
9232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatus_t NativeInputEventReceiver::initialize() {
9391e328984c0d1e0f95b3d37f779d9d4fa9bfe8f8Jeff Brown    int receiveFd = mInputConsumer.getChannel()->getFd();
9480a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    mMessageQueue->getLooper()->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, this, NULL);
9532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return OK;
9632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
9732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
9880a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownvoid NativeInputEventReceiver::dispose() {
9980a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown#if DEBUG_DISPATCH_CYCLE
10080a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    ALOGD("channel '%s' ~ Disposing input event receiver.", getInputChannelName());
10180a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown#endif
10280a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown
10380a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    mMessageQueue->getLooper()->removeFd(mInputConsumer.getChannel()->getFd());
10480a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown}
10580a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown
106072ec96a4900d4616574733646ee46311cb5d2cbJeff Brownstatus_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
10732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
108072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    ALOGD("channel '%s' ~ Finished input event.", getInputChannelName());
10932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
11032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
111072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
112072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    if (status) {
113072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        ALOGW("Failed to send finished signal on channel '%s'.  status=%d",
114072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                getInputChannelName(), status);
11532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
116072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    return status;
11732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
11832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
11980a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownint NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
12032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
1213762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("channel '%s' ~ Publisher closed input channel or an error occurred.  "
12280a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown                "events=0x%x", getInputChannelName(), events);
12332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0; // remove the callback
12432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
12532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
12632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (!(events & ALOOPER_EVENT_INPUT)) {
1278564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
12880a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown                "events=0x%x", getInputChannelName(), events);
12932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 1;
13032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
13132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
1323bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
13380a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    status_t status = consumeEvents(env, false /*consumeBatches*/, -1);
13480a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
135072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    return status == OK || status == NO_MEMORY ? 1 : 0;
136072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown}
13732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
138771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brownstatus_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
139771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown        bool consumeBatches, nsecs_t frameTime) {
140072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#if DEBUG_DISPATCH_CYCLE
141771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown    ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.",
142771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown            getInputChannelName(), consumeBatches ? "true" : "false", frameTime);
143072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#endif
144072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown
145072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    if (consumeBatches) {
146072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        mBatchedInputEventPending = false;
14732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
14832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
1493bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown    bool skipCallbacks = false;
150072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    for (;;) {
151072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        uint32_t seq;
152072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        InputEvent* inputEvent;
153072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        status_t status = mInputConsumer.consume(&mInputEventFactory,
154771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown                consumeBatches, frameTime, &seq, &inputEvent);
155072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        if (status) {
156072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            if (status == WOULD_BLOCK) {
1573bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                if (!skipCallbacks && !mBatchedInputEventPending
1583bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        && mInputConsumer.hasPendingBatch()) {
159072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    // There is a pending batch.  Come back later.
160072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    mBatchedInputEventPending = true;
16132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
162072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    ALOGD("channel '%s' ~ Dispatching batched input event pending notification.",
163072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                            getInputChannelName());
16432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
165072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    env->CallVoidMethod(mReceiverObjGlobal,
166072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                            gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
1673bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                    if (env->ExceptionCheck()) {
1683bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        ALOGE("Exception dispatching batched input events.");
169072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                        mBatchedInputEventPending = false; // try again later
170072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    }
171072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                }
172072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                return OK;
173072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            }
174072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            ALOGE("channel '%s' ~ Failed to consume input event.  status=%d",
175072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown                    getInputChannelName(), status);
176072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            return status;
177072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        }
178072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        assert(inputEvent);
17932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
1803bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown        if (!skipCallbacks) {
1813bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            jobject inputEventObj;
1823bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            switch (inputEvent->getType()) {
1833bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            case AINPUT_EVENT_TYPE_KEY:
18432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
1853bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGD("channel '%s' ~ Received key event.", getInputChannelName());
18632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
1873bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                inputEventObj = android_view_KeyEvent_fromNative(env,
1883bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        static_cast<KeyEvent*>(inputEvent));
1893bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                break;
19032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
1913bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            case AINPUT_EVENT_TYPE_MOTION:
192072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#if DEBUG_DISPATCH_CYCLE
1933bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGD("channel '%s' ~ Received motion event.", getInputChannelName());
194072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#endif
1953bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
1963bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        static_cast<MotionEvent*>(inputEvent));
1973bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                break;
19832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
1993bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            default:
2003bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                assert(false); // InputConsumer should prevent this from ever happening
2013bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                inputEventObj = NULL;
2023bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            }
20332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
2043bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            if (inputEventObj) {
20532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE
2063bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
20732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif
2083bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                env->CallVoidMethod(mReceiverObjGlobal,
2093bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
2103bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                if (env->ExceptionCheck()) {
2113bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                    ALOGE("Exception dispatching input event.");
2123bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                    skipCallbacks = true;
2133bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                }
2143bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            } else {
2153bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
2163bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown                skipCallbacks = true;
2173bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown            }
2183bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown        }
21932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
2203bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown        if (skipCallbacks) {
221072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            mInputConsumer.sendFinishedSignal(seq, false);
22232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        }
22332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
22432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
22532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
22632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
22732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
22832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jobject inputChannelObj, jobject messageQueueObj) {
22932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
23032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            inputChannelObj);
23132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (inputChannel == NULL) {
23232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, "InputChannel is not initialized.");
23332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
23432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
23532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
236603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
237603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    if (messageQueue == NULL) {
23832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
23932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
24032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
24132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
24232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
243603b44589682db3ff33ade172facb0c5e309f1beJeff Brown            receiverObj, inputChannel, messageQueue);
24432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    status_t status = receiver->initialize();
24532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    if (status) {
24632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        String8 message;
24732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        message.appendFormat("Failed to initialize input event receiver.  status=%d", status);
24832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, message.string());
24932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        return 0;
25032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
25132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
25232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
25332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return reinterpret_cast<jint>(receiver.get());
25432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
25532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
25632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) {
25732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver =
25832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
25980a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    receiver->dispose();
26032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    receiver->decStrong(gInputEventReceiverClassInfo.clazz); // drop reference held by the object
26132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
26232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
263072ec96a4900d4616574733646ee46311cb5d2cbJeff Brownstatic void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr,
264072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        jint seq, jboolean handled) {
26532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    sp<NativeInputEventReceiver> receiver =
26632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
267072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    status_t status = receiver->finishInputEvent(seq, handled);
2689806a2307f3e47e847ad5e62e302eab36d3eb3e4Jeff Brown    if (status && status != DEAD_OBJECT) {
26932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        String8 message;
27032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        message.appendFormat("Failed to finish input event.  status=%d", status);
27132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        jniThrowRuntimeException(env, message.string());
27232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    }
27332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
27432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
275771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brownstatic void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr,
276771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown        jlong frameTimeNanos) {
277072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    sp<NativeInputEventReceiver> receiver =
278072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
279771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown    status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos);
2803bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown    if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
281072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        String8 message;
282072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        message.appendFormat("Failed to consume batched input event.  status=%d", status);
283072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown        jniThrowRuntimeException(env, message.string());
284072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    }
285072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown}
286072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown
28732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
28832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic JNINativeMethod gMethods[] = {
28932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    /* name, signature, funcPtr */
29032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    { "nativeInit",
29132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            "(Landroid/view/InputEventReceiver;Landroid/view/InputChannel;Landroid/os/MessageQueue;)I",
29232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            (void*)nativeInit },
293072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    { "nativeDispose", "(I)V",
29432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            (void*)nativeDispose },
295072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    { "nativeFinishInputEvent", "(IIZ)V",
296072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            (void*)nativeFinishInputEvent },
297771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown    { "nativeConsumeBatchedInputEvents", "(IJ)V",
298072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            (void*)nativeConsumeBatchedInputEvents },
29932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown};
30032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
30132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define FIND_CLASS(var, className) \
30232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = env->FindClass(className); \
30332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className); \
30432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = jclass(env->NewGlobalRef(var));
30532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
30632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
30732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
30832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown        LOG_FATAL_IF(! var, "Unable to find method " methodName);
30932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
31032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownint register_android_view_InputEventReceiver(JNIEnv* env) {
31132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    int res = jniRegisterNativeMethods(env, "android/view/InputEventReceiver",
31232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            gMethods, NELEM(gMethods));
31332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
31432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
31532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    FIND_CLASS(gInputEventReceiverClassInfo.clazz, "android/view/InputEventReceiver");
31632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
31732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchInputEvent,
31832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown            gInputEventReceiverClassInfo.clazz,
319072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            "dispatchInputEvent", "(ILandroid/view/InputEvent;)V");
320072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown    GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchBatchedInputEventPending,
321072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            gInputEventReceiverClassInfo.clazz,
322072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown            "dispatchBatchedInputEventPending", "()V");
32332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown    return 0;
32432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}
32532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown
32632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} // namespace android
327