blob: 8e1e04abeca1f366d4cb2d25c724d23be5582b4e [file] [log] [blame]
Jeff Brown32cbc38552011-12-01 14:01:49 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "InputEventReceiver"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages about the dispatch cycle.
22#define DEBUG_DISPATCH_CYCLE 0
23
24
25#include "JNIHelp.h"
26
27#include <android_runtime/AndroidRuntime.h>
28#include <utils/Log.h>
29#include <utils/Looper.h>
Jeff Brown56513492013-05-21 20:37:51 -070030#include <utils/Vector.h>
Jeff Brown32cbc38552011-12-01 14:01:49 -080031#include <utils/threads.h>
Mathias Agopianb93a03f82012-02-17 15:34:57 -080032#include <androidfw/InputTransport.h>
Jeff Brown32cbc38552011-12-01 14:01:49 -080033#include "android_os_MessageQueue.h"
34#include "android_view_InputChannel.h"
35#include "android_view_KeyEvent.h"
36#include "android_view_MotionEvent.h"
37
Jeff Browna4ca8ea2013-04-02 18:01:38 -070038#include <ScopedLocalRef.h>
39
Jeff Brown32cbc38552011-12-01 14:01:49 -080040namespace android {
41
42static struct {
43 jclass clazz;
44
45 jmethodID dispatchInputEvent;
Jeff Brown072ec962012-02-07 14:46:57 -080046 jmethodID dispatchBatchedInputEventPending;
Jeff Brown32cbc38552011-12-01 14:01:49 -080047} gInputEventReceiverClassInfo;
48
49
Jeff Brown80a1de12012-05-31 16:23:11 -070050class NativeInputEventReceiver : public LooperCallback {
Jeff Brown32cbc38552011-12-01 14:01:49 -080051public:
52 NativeInputEventReceiver(JNIEnv* env,
Jeff Browna4ca8ea2013-04-02 18:01:38 -070053 jobject receiverWeak, const sp<InputChannel>& inputChannel,
Jeff Brown603b4452012-04-06 17:39:41 -070054 const sp<MessageQueue>& messageQueue);
Jeff Brown32cbc38552011-12-01 14:01:49 -080055
56 status_t initialize();
Jeff Brown80a1de12012-05-31 16:23:11 -070057 void dispose();
Jeff Brown072ec962012-02-07 14:46:57 -080058 status_t finishInputEvent(uint32_t seq, bool handled);
Jeff Brown771526c2012-04-27 15:13:25 -070059 status_t consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime);
Jeff Brown32cbc38552011-12-01 14:01:49 -080060
61protected:
62 virtual ~NativeInputEventReceiver();
63
64private:
Jeff Brown56513492013-05-21 20:37:51 -070065 struct Finish {
66 uint32_t seq;
67 bool handled;
68 };
69
Jeff Browna4ca8ea2013-04-02 18:01:38 -070070 jobject mReceiverWeakGlobal;
Jeff Brown32cbc38552011-12-01 14:01:49 -080071 InputConsumer mInputConsumer;
Jeff Brown603b4452012-04-06 17:39:41 -070072 sp<MessageQueue> mMessageQueue;
Jeff Brown32cbc38552011-12-01 14:01:49 -080073 PreallocatedInputEventFactory mInputEventFactory;
Jeff Brown072ec962012-02-07 14:46:57 -080074 bool mBatchedInputEventPending;
Jeff Brown56513492013-05-21 20:37:51 -070075 int mFdEvents;
76 Vector<Finish> mFinishQueue;
77
78 void setFdEvents(int events);
Jeff Brown32cbc38552011-12-01 14:01:49 -080079
80 const char* getInputChannelName() {
81 return mInputConsumer.getChannel()->getName().string();
82 }
Jeff Brown3bdcdd82012-04-10 20:36:07 -070083
Jeff Brown80a1de12012-05-31 16:23:11 -070084 virtual int handleEvent(int receiveFd, int events, void* data);
Jeff Brown32cbc38552011-12-01 14:01:49 -080085};
86
87
88NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
Jeff Browna4ca8ea2013-04-02 18:01:38 -070089 jobject receiverWeak, const sp<InputChannel>& inputChannel,
Jeff Brown603b4452012-04-06 17:39:41 -070090 const sp<MessageQueue>& messageQueue) :
Jeff Browna4ca8ea2013-04-02 18:01:38 -070091 mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
Jeff Brown603b4452012-04-06 17:39:41 -070092 mInputConsumer(inputChannel), mMessageQueue(messageQueue),
Jeff Brown56513492013-05-21 20:37:51 -070093 mBatchedInputEventPending(false), mFdEvents(0) {
Jeff Brown32cbc38552011-12-01 14:01:49 -080094#if DEBUG_DISPATCH_CYCLE
Steve Block5baa3a62011-12-20 16:23:08 +000095 ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName());
Jeff Brown32cbc38552011-12-01 14:01:49 -080096#endif
97}
98
99NativeInputEventReceiver::~NativeInputEventReceiver() {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800100 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700101 env->DeleteGlobalRef(mReceiverWeakGlobal);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800102}
103
104status_t NativeInputEventReceiver::initialize() {
Jeff Brown56513492013-05-21 20:37:51 -0700105 setFdEvents(ALOOPER_EVENT_INPUT);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800106 return OK;
107}
108
Jeff Brown80a1de12012-05-31 16:23:11 -0700109void NativeInputEventReceiver::dispose() {
110#if DEBUG_DISPATCH_CYCLE
111 ALOGD("channel '%s' ~ Disposing input event receiver.", getInputChannelName());
112#endif
113
Jeff Brown56513492013-05-21 20:37:51 -0700114 setFdEvents(0);
Jeff Brown80a1de12012-05-31 16:23:11 -0700115}
116
Jeff Brown072ec962012-02-07 14:46:57 -0800117status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800118#if DEBUG_DISPATCH_CYCLE
Jeff Brown072ec962012-02-07 14:46:57 -0800119 ALOGD("channel '%s' ~ Finished input event.", getInputChannelName());
Jeff Brown32cbc38552011-12-01 14:01:49 -0800120#endif
Jeff Brown32cbc38552011-12-01 14:01:49 -0800121
Jeff Brown072ec962012-02-07 14:46:57 -0800122 status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
123 if (status) {
Jeff Brown56513492013-05-21 20:37:51 -0700124 if (status == WOULD_BLOCK) {
125#if DEBUG_DISPATCH_CYCLE
126 ALOGD("channel '%s' ~ Could not send finished signal immediately. "
127 "Enqueued for later.", getInputChannelName());
128#endif
129 Finish finish;
130 finish.seq = seq;
131 finish.handled = handled;
132 mFinishQueue.add(finish);
133 if (mFinishQueue.size() == 1) {
134 setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
135 }
136 return OK;
137 }
Jeff Brown072ec962012-02-07 14:46:57 -0800138 ALOGW("Failed to send finished signal on channel '%s'. status=%d",
139 getInputChannelName(), status);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800140 }
Jeff Brown072ec962012-02-07 14:46:57 -0800141 return status;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800142}
143
Jeff Brown56513492013-05-21 20:37:51 -0700144void NativeInputEventReceiver::setFdEvents(int events) {
145 if (mFdEvents != events) {
146 mFdEvents = events;
147 int fd = mInputConsumer.getChannel()->getFd();
148 if (events) {
149 mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
150 } else {
151 mMessageQueue->getLooper()->removeFd(fd);
152 }
153 }
154}
155
Jeff Brown80a1de12012-05-31 16:23:11 -0700156int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800157 if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
Jeff Brown44e13ef2013-03-27 12:34:30 -0700158#if DEBUG_DISPATCH_CYCLE
159 // This error typically occurs when the publisher has closed the input channel
160 // as part of removing a window or finishing an IME session, in which case
161 // the consumer will soon be disposed as well.
162 ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred. "
Jeff Brown80a1de12012-05-31 16:23:11 -0700163 "events=0x%x", getInputChannelName(), events);
Jeff Brown44e13ef2013-03-27 12:34:30 -0700164#endif
Jeff Brown32cbc38552011-12-01 14:01:49 -0800165 return 0; // remove the callback
166 }
167
Jeff Brown56513492013-05-21 20:37:51 -0700168 if (events & ALOOPER_EVENT_INPUT) {
169 JNIEnv* env = AndroidRuntime::getJNIEnv();
170 status_t status = consumeEvents(env, false /*consumeBatches*/, -1);
171 mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
172 return status == OK || status == NO_MEMORY ? 1 : 0;
173 }
174
175 if (events & ALOOPER_EVENT_OUTPUT) {
176 for (size_t i = 0; i < mFinishQueue.size(); i++) {
177 const Finish& finish = mFinishQueue.itemAt(i);
178 status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
179 if (status) {
180 mFinishQueue.removeItemsAt(0, i);
181
182 if (status == WOULD_BLOCK) {
183#if DEBUG_DISPATCH_CYCLE
184 ALOGD("channel '%s' ~ Sent %u queued finish events; %u left.",
185 getInputChannelName(), i, mFinishQueue.size());
186#endif
187 return 1; // keep the callback, try again later
188 }
189
190 ALOGW("Failed to send finished signal on channel '%s'. status=%d",
191 getInputChannelName(), status);
192 if (status != DEAD_OBJECT) {
193 JNIEnv* env = AndroidRuntime::getJNIEnv();
194 String8 message;
195 message.appendFormat("Failed to finish input event. status=%d", status);
196 jniThrowRuntimeException(env, message.string());
197 mMessageQueue->raiseAndClearException(env, "finishInputEvent");
198 }
199 return 0; // remove the callback
200 }
201 }
202#if DEBUG_DISPATCH_CYCLE
203 ALOGD("channel '%s' ~ Sent %u queued finish events; none left.",
204 getInputChannelName(), mFinishQueue.size());
205#endif
206 mFinishQueue.clear();
207 setFdEvents(ALOOPER_EVENT_INPUT);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800208 return 1;
209 }
210
Jeff Brown56513492013-05-21 20:37:51 -0700211 ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
212 "events=0x%x", getInputChannelName(), events);
213 return 1;
Jeff Brown072ec962012-02-07 14:46:57 -0800214}
Jeff Brown32cbc38552011-12-01 14:01:49 -0800215
Jeff Brown771526c2012-04-27 15:13:25 -0700216status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
217 bool consumeBatches, nsecs_t frameTime) {
Jeff Brown072ec962012-02-07 14:46:57 -0800218#if DEBUG_DISPATCH_CYCLE
Jeff Brown771526c2012-04-27 15:13:25 -0700219 ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.",
220 getInputChannelName(), consumeBatches ? "true" : "false", frameTime);
Jeff Brown072ec962012-02-07 14:46:57 -0800221#endif
222
223 if (consumeBatches) {
224 mBatchedInputEventPending = false;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800225 }
226
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700227 ScopedLocalRef<jobject> receiverObj(env, NULL);
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700228 bool skipCallbacks = false;
Jeff Brown072ec962012-02-07 14:46:57 -0800229 for (;;) {
230 uint32_t seq;
231 InputEvent* inputEvent;
232 status_t status = mInputConsumer.consume(&mInputEventFactory,
Jeff Brown771526c2012-04-27 15:13:25 -0700233 consumeBatches, frameTime, &seq, &inputEvent);
Jeff Brown072ec962012-02-07 14:46:57 -0800234 if (status) {
235 if (status == WOULD_BLOCK) {
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700236 if (!skipCallbacks && !mBatchedInputEventPending
237 && mInputConsumer.hasPendingBatch()) {
Jeff Brown072ec962012-02-07 14:46:57 -0800238 // There is a pending batch. Come back later.
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700239 if (!receiverObj.get()) {
240 receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
241 if (!receiverObj.get()) {
242 ALOGW("channel '%s' ~ Receiver object was finalized "
243 "without being disposed.", getInputChannelName());
244 return DEAD_OBJECT;
245 }
246 }
247
Jeff Brown072ec962012-02-07 14:46:57 -0800248 mBatchedInputEventPending = true;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800249#if DEBUG_DISPATCH_CYCLE
Jeff Brown072ec962012-02-07 14:46:57 -0800250 ALOGD("channel '%s' ~ Dispatching batched input event pending notification.",
251 getInputChannelName());
Jeff Brown32cbc38552011-12-01 14:01:49 -0800252#endif
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700253 env->CallVoidMethod(receiverObj.get(),
Jeff Brown072ec962012-02-07 14:46:57 -0800254 gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700255 if (env->ExceptionCheck()) {
256 ALOGE("Exception dispatching batched input events.");
Jeff Brown072ec962012-02-07 14:46:57 -0800257 mBatchedInputEventPending = false; // try again later
258 }
259 }
260 return OK;
261 }
262 ALOGE("channel '%s' ~ Failed to consume input event. status=%d",
263 getInputChannelName(), status);
264 return status;
265 }
266 assert(inputEvent);
267
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700268 if (!skipCallbacks) {
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700269 if (!receiverObj.get()) {
270 receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
271 if (!receiverObj.get()) {
272 ALOGW("channel '%s' ~ Receiver object was finalized "
273 "without being disposed.", getInputChannelName());
274 return DEAD_OBJECT;
275 }
276 }
277
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700278 jobject inputEventObj;
279 switch (inputEvent->getType()) {
280 case AINPUT_EVENT_TYPE_KEY:
Jeff Brown32cbc38552011-12-01 14:01:49 -0800281#if DEBUG_DISPATCH_CYCLE
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700282 ALOGD("channel '%s' ~ Received key event.", getInputChannelName());
Jeff Brown32cbc38552011-12-01 14:01:49 -0800283#endif
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700284 inputEventObj = android_view_KeyEvent_fromNative(env,
285 static_cast<KeyEvent*>(inputEvent));
286 break;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800287
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700288 case AINPUT_EVENT_TYPE_MOTION:
Jeff Brown072ec962012-02-07 14:46:57 -0800289#if DEBUG_DISPATCH_CYCLE
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700290 ALOGD("channel '%s' ~ Received motion event.", getInputChannelName());
Jeff Brown072ec962012-02-07 14:46:57 -0800291#endif
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700292 inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
293 static_cast<MotionEvent*>(inputEvent));
294 break;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800295
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700296 default:
297 assert(false); // InputConsumer should prevent this from ever happening
298 inputEventObj = NULL;
299 }
300
301 if (inputEventObj) {
302#if DEBUG_DISPATCH_CYCLE
303 ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
304#endif
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700305 env->CallVoidMethod(receiverObj.get(),
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700306 gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
307 if (env->ExceptionCheck()) {
308 ALOGE("Exception dispatching input event.");
309 skipCallbacks = true;
310 }
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700311 env->DeleteLocalRef(inputEventObj);
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700312 } else {
313 ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
314 skipCallbacks = true;
315 }
Jeff Brown072ec962012-02-07 14:46:57 -0800316 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800317
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700318 if (skipCallbacks) {
Jeff Brown072ec962012-02-07 14:46:57 -0800319 mInputConsumer.sendFinishedSignal(seq, false);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800320 }
321 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800322}
323
324
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700325static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
Jeff Brown32cbc38552011-12-01 14:01:49 -0800326 jobject inputChannelObj, jobject messageQueueObj) {
327 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
328 inputChannelObj);
329 if (inputChannel == NULL) {
330 jniThrowRuntimeException(env, "InputChannel is not initialized.");
331 return 0;
332 }
333
Jeff Brown603b4452012-04-06 17:39:41 -0700334 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
335 if (messageQueue == NULL) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800336 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
337 return 0;
338 }
339
340 sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700341 receiverWeak, inputChannel, messageQueue);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800342 status_t status = receiver->initialize();
343 if (status) {
344 String8 message;
345 message.appendFormat("Failed to initialize input event receiver. status=%d", status);
346 jniThrowRuntimeException(env, message.string());
347 return 0;
348 }
349
350 receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
351 return reinterpret_cast<jint>(receiver.get());
352}
353
354static void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) {
355 sp<NativeInputEventReceiver> receiver =
356 reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
Jeff Brown80a1de12012-05-31 16:23:11 -0700357 receiver->dispose();
Jeff Brown32cbc38552011-12-01 14:01:49 -0800358 receiver->decStrong(gInputEventReceiverClassInfo.clazz); // drop reference held by the object
359}
360
Jeff Brown072ec962012-02-07 14:46:57 -0800361static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr,
362 jint seq, jboolean handled) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800363 sp<NativeInputEventReceiver> receiver =
364 reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
Jeff Brown072ec962012-02-07 14:46:57 -0800365 status_t status = receiver->finishInputEvent(seq, handled);
Jeff Brown9806a232012-02-17 10:28:09 -0800366 if (status && status != DEAD_OBJECT) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800367 String8 message;
368 message.appendFormat("Failed to finish input event. status=%d", status);
369 jniThrowRuntimeException(env, message.string());
370 }
371}
372
Jeff Brown771526c2012-04-27 15:13:25 -0700373static void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr,
374 jlong frameTimeNanos) {
Jeff Brown072ec962012-02-07 14:46:57 -0800375 sp<NativeInputEventReceiver> receiver =
376 reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
Jeff Brown771526c2012-04-27 15:13:25 -0700377 status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos);
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700378 if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
Jeff Brown072ec962012-02-07 14:46:57 -0800379 String8 message;
380 message.appendFormat("Failed to consume batched input event. status=%d", status);
381 jniThrowRuntimeException(env, message.string());
382 }
383}
384
Jeff Brown32cbc38552011-12-01 14:01:49 -0800385
386static JNINativeMethod gMethods[] = {
387 /* name, signature, funcPtr */
388 { "nativeInit",
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700389 "(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)I",
Jeff Brown32cbc38552011-12-01 14:01:49 -0800390 (void*)nativeInit },
Jeff Brown072ec962012-02-07 14:46:57 -0800391 { "nativeDispose", "(I)V",
Jeff Brown32cbc38552011-12-01 14:01:49 -0800392 (void*)nativeDispose },
Jeff Brown072ec962012-02-07 14:46:57 -0800393 { "nativeFinishInputEvent", "(IIZ)V",
394 (void*)nativeFinishInputEvent },
Jeff Brown771526c2012-04-27 15:13:25 -0700395 { "nativeConsumeBatchedInputEvents", "(IJ)V",
Jeff Brown072ec962012-02-07 14:46:57 -0800396 (void*)nativeConsumeBatchedInputEvents },
Jeff Brown32cbc38552011-12-01 14:01:49 -0800397};
398
399#define FIND_CLASS(var, className) \
400 var = env->FindClass(className); \
401 LOG_FATAL_IF(! var, "Unable to find class " className); \
402 var = jclass(env->NewGlobalRef(var));
403
404#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
405 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
406 LOG_FATAL_IF(! var, "Unable to find method " methodName);
407
408int register_android_view_InputEventReceiver(JNIEnv* env) {
409 int res = jniRegisterNativeMethods(env, "android/view/InputEventReceiver",
410 gMethods, NELEM(gMethods));
411 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
412
413 FIND_CLASS(gInputEventReceiverClassInfo.clazz, "android/view/InputEventReceiver");
414
415 GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchInputEvent,
416 gInputEventReceiverClassInfo.clazz,
Jeff Brown072ec962012-02-07 14:46:57 -0800417 "dispatchInputEvent", "(ILandroid/view/InputEvent;)V");
418 GET_METHOD_ID(gInputEventReceiverClassInfo.dispatchBatchedInputEventPending,
419 gInputEventReceiverClassInfo.clazz,
420 "dispatchBatchedInputEventPending", "()V");
Jeff Brown32cbc38552011-12-01 14:01:49 -0800421 return 0;
422}
423
424} // namespace android