android_view_InputEventReceiver.cpp revision 44e13ef1a1aee36b4ce667670345de8ce4e6bb7b
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)) { 12144e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown#if DEBUG_DISPATCH_CYCLE 12244e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown // This error typically occurs when the publisher has closed the input channel 12344e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown // as part of removing a window or finishing an IME session, in which case 12444e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown // the consumer will soon be disposed as well. 12544e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred. " 12680a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown "events=0x%x", getInputChannelName(), events); 12744e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown#endif 12832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown return 0; // remove the callback 12932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown } 13032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 13132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown if (!(events & ALOOPER_EVENT_INPUT)) { 1328564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " 13380a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown "events=0x%x", getInputChannelName(), events); 13432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown return 1; 13532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown } 13632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 1373bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown JNIEnv* env = AndroidRuntime::getJNIEnv(); 13880a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown status_t status = consumeEvents(env, false /*consumeBatches*/, -1); 13980a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown mMessageQueue->raiseAndClearException(env, "handleReceiveCallback"); 140072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown return status == OK || status == NO_MEMORY ? 1 : 0; 141072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown} 14232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 143771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brownstatus_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, 144771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown bool consumeBatches, nsecs_t frameTime) { 145072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#if DEBUG_DISPATCH_CYCLE 146771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.", 147771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown getInputChannelName(), consumeBatches ? "true" : "false", frameTime); 148072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#endif 149072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown 150072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown if (consumeBatches) { 151072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown mBatchedInputEventPending = false; 15232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown } 15332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 1543bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown bool skipCallbacks = false; 155072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown for (;;) { 156072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown uint32_t seq; 157072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown InputEvent* inputEvent; 158072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown status_t status = mInputConsumer.consume(&mInputEventFactory, 159771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown consumeBatches, frameTime, &seq, &inputEvent); 160072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown if (status) { 161072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown if (status == WOULD_BLOCK) { 1623bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown if (!skipCallbacks && !mBatchedInputEventPending 1633bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown && mInputConsumer.hasPendingBatch()) { 164072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown // There is a pending batch. Come back later. 165072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown mBatchedInputEventPending = true; 16632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE 167072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown ALOGD("channel '%s' ~ Dispatching batched input event pending notification.", 168072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown getInputChannelName()); 16932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif 170072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown env->CallVoidMethod(mReceiverObjGlobal, 171072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown gInputEventReceiverClassInfo.dispatchBatchedInputEventPending); 1723bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown if (env->ExceptionCheck()) { 1733bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown ALOGE("Exception dispatching batched input events."); 174072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown mBatchedInputEventPending = false; // try again later 175072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown } 176072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown } 177072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown return OK; 178072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown } 179072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown ALOGE("channel '%s' ~ Failed to consume input event. status=%d", 180072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown getInputChannelName(), status); 181072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown return status; 182072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown } 183072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown assert(inputEvent); 18432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 1853bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown if (!skipCallbacks) { 1863bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown jobject inputEventObj; 1873bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown switch (inputEvent->getType()) { 1883bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown case AINPUT_EVENT_TYPE_KEY: 18932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE 1903bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown ALOGD("channel '%s' ~ Received key event.", getInputChannelName()); 19132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif 1923bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown inputEventObj = android_view_KeyEvent_fromNative(env, 1933bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown static_cast<KeyEvent*>(inputEvent)); 1943bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown break; 19532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 1963bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown case AINPUT_EVENT_TYPE_MOTION: 197072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#if DEBUG_DISPATCH_CYCLE 1983bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown ALOGD("channel '%s' ~ Received motion event.", getInputChannelName()); 199072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown#endif 2003bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown inputEventObj = android_view_MotionEvent_obtainAsCopy(env, 2013bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown static_cast<MotionEvent*>(inputEvent)); 2023bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown break; 20332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 2043bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown default: 2053bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown assert(false); // InputConsumer should prevent this from ever happening 2063bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown inputEventObj = NULL; 2073bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown } 20832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 2093bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown if (inputEventObj) { 21032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#if DEBUG_DISPATCH_CYCLE 2113bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName()); 21232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#endif 2133bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown env->CallVoidMethod(mReceiverObjGlobal, 2143bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj); 2153bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown if (env->ExceptionCheck()) { 2163bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown ALOGE("Exception dispatching input event."); 2173bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown skipCallbacks = true; 2183bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown } 2193bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown } else { 2203bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName()); 2213bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown skipCallbacks = true; 2223bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown } 2233bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown } 22432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 2253bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown if (skipCallbacks) { 226072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown mInputConsumer.sendFinishedSignal(seq, false); 22732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown } 22832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown } 22932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} 23032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 23132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 23232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj, 23332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown jobject inputChannelObj, jobject messageQueueObj) { 23432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, 23532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown inputChannelObj); 23632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown if (inputChannel == NULL) { 23732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown jniThrowRuntimeException(env, "InputChannel is not initialized."); 23832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown return 0; 23932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown } 24032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 241603b44589682db3ff33ade172facb0c5e309f1beJeff Brown sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); 242603b44589682db3ff33ade172facb0c5e309f1beJeff Brown if (messageQueue == NULL) { 24332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown jniThrowRuntimeException(env, "MessageQueue is not initialized."); 24432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown return 0; 24532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown } 24632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 24732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env, 248603b44589682db3ff33ade172facb0c5e309f1beJeff Brown receiverObj, inputChannel, messageQueue); 24932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown status_t status = receiver->initialize(); 25032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown if (status) { 25132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown String8 message; 25232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown message.appendFormat("Failed to initialize input event receiver. status=%d", status); 25332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown jniThrowRuntimeException(env, message.string()); 25432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown return 0; 25532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown } 25632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 25732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object 25832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown return reinterpret_cast<jint>(receiver.get()); 25932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} 26032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 26132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) { 26232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown sp<NativeInputEventReceiver> receiver = 26332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown reinterpret_cast<NativeInputEventReceiver*>(receiverPtr); 26480a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown receiver->dispose(); 26532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown receiver->decStrong(gInputEventReceiverClassInfo.clazz); // drop reference held by the object 26632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} 26732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 268072ec96a4900d4616574733646ee46311cb5d2cbJeff Brownstatic void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr, 269072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown jint seq, jboolean handled) { 27032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown sp<NativeInputEventReceiver> receiver = 27132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown reinterpret_cast<NativeInputEventReceiver*>(receiverPtr); 272072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown status_t status = receiver->finishInputEvent(seq, handled); 2739806a2307f3e47e847ad5e62e302eab36d3eb3e4Jeff Brown if (status && status != DEAD_OBJECT) { 27432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown String8 message; 27532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown message.appendFormat("Failed to finish input event. status=%d", status); 27632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown jniThrowRuntimeException(env, message.string()); 27732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown } 27832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} 27932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 280771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brownstatic void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr, 281771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown jlong frameTimeNanos) { 282072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown sp<NativeInputEventReceiver> receiver = 283072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown reinterpret_cast<NativeInputEventReceiver*>(receiverPtr); 284771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos); 2853bdcdd8531781569d501e7023c22e25e2bae0dd1Jeff Brown if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) { 286072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown String8 message; 287072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown message.appendFormat("Failed to consume batched input event. status=%d", status); 288072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown jniThrowRuntimeException(env, message.string()); 289072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown } 290072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown} 291072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown 29232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 29332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownstatic JNINativeMethod gMethods[] = { 29432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown /* name, signature, funcPtr */ 29532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown { "nativeInit", 29632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown "(Landroid/view/InputEventReceiver;Landroid/view/InputChannel;Landroid/os/MessageQueue;)I", 29732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown (void*)nativeInit }, 298072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown { "nativeDispose", "(I)V", 29932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown (void*)nativeDispose }, 300072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown { "nativeFinishInputEvent", "(IIZ)V", 301072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown (void*)nativeFinishInputEvent }, 302771526c88f5cc4b56a41cb12aa06a28d377a07d5Jeff Brown { "nativeConsumeBatchedInputEvents", "(IJ)V", 303072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown (void*)nativeConsumeBatchedInputEvents }, 30432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown}; 30532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 30632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define FIND_CLASS(var, className) \ 30732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown var = env->FindClass(className); \ 30832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown LOG_FATAL_IF(! var, "Unable to find class " className); \ 30932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown var = jclass(env->NewGlobalRef(var)); 31032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 31132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 31232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 31332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown LOG_FATAL_IF(! var, "Unable to find method " methodName); 31432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 31532cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brownint register_android_view_InputEventReceiver(JNIEnv* env) { 31632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown int res = jniRegisterNativeMethods(env, "android/view/InputEventReceiver", 31732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown gMethods, NELEM(gMethods)); 31832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown LOG_FATAL_IF(res < 0, "Unable to register native methods."); 31932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 32032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown FIND_CLASS(gInputEventReceiverClassInfo.clazz, "android/view/InputEventReceiver"); 32132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 32232cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchInputEvent, 32332cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown gInputEventReceiverClassInfo.clazz, 324072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown "dispatchInputEvent", "(ILandroid/view/InputEvent;)V"); 325072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchBatchedInputEventPending, 326072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown gInputEventReceiverClassInfo.clazz, 327072ec96a4900d4616574733646ee46311cb5d2cbJeff Brown "dispatchBatchedInputEventPending", "()V"); 32832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown return 0; 32932cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} 33032cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown 33132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown} // namespace android 332