blob: 7975c86759543702ed5695548ecbd4dc83274280 [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
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -080021#include <inttypes.h>
22
Steven Moreland2279b252017-07-19 09:50:45 -070023#include <nativehelper/JNIHelp.h>
Jeff Brown32cbc38552011-12-01 14:01:49 -080024
25#include <android_runtime/AndroidRuntime.h>
Siarhei Vishniakoud2188aa2019-02-25 16:06:37 -060026#include <log/log.h>
Jeff Brown32cbc38552011-12-01 14:01:49 -080027#include <utils/Looper.h>
Jeff Brown56513492013-05-21 20:37:51 -070028#include <utils/Vector.h>
Jeff Brown9d3b1a42013-07-01 19:07:15 -070029#include <input/InputTransport.h>
Jeff Brown32cbc38552011-12-01 14:01:49 -080030#include "android_os_MessageQueue.h"
31#include "android_view_InputChannel.h"
32#include "android_view_KeyEvent.h"
33#include "android_view_MotionEvent.h"
34
Steven Moreland2279b252017-07-19 09:50:45 -070035#include <nativehelper/ScopedLocalRef.h>
Jeff Browna4ca8ea2013-04-02 18:01:38 -070036
Andreas Gampe987f79f2014-11-18 17:29:46 -080037#include "core_jni_helpers.h"
38
Jeff Brown32cbc38552011-12-01 14:01:49 -080039namespace android {
40
Andreas Gampeed6b9df2014-11-20 22:02:20 -080041static const bool kDebugDispatchCycle = false;
42
Jeff Brown32cbc38552011-12-01 14:01:49 -080043static struct {
44 jclass clazz;
45
46 jmethodID dispatchInputEvent;
Jeff Brown072ec962012-02-07 14:46:57 -080047 jmethodID dispatchBatchedInputEventPending;
Jeff Brown32cbc38552011-12-01 14:01:49 -080048} gInputEventReceiverClassInfo;
49
50
Jeff Brown80a1de12012-05-31 16:23:11 -070051class NativeInputEventReceiver : public LooperCallback {
Jeff Brown32cbc38552011-12-01 14:01:49 -080052public:
53 NativeInputEventReceiver(JNIEnv* env,
Jeff Browna4ca8ea2013-04-02 18:01:38 -070054 jobject receiverWeak, const sp<InputChannel>& inputChannel,
Jeff Brown603b4452012-04-06 17:39:41 -070055 const sp<MessageQueue>& messageQueue);
Jeff Brown32cbc38552011-12-01 14:01:49 -080056
57 status_t initialize();
Jeff Brown80a1de12012-05-31 16:23:11 -070058 void dispose();
Jeff Brown072ec962012-02-07 14:46:57 -080059 status_t finishInputEvent(uint32_t seq, bool handled);
Michael Wright62ce65d2013-10-25 14:50:36 -070060 status_t consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime,
61 bool* outConsumedBatch);
Jeff Brown32cbc38552011-12-01 14:01:49 -080062
63protected:
64 virtual ~NativeInputEventReceiver();
65
66private:
Jeff Brown56513492013-05-21 20:37:51 -070067 struct Finish {
68 uint32_t seq;
69 bool handled;
70 };
71
Jeff Browna4ca8ea2013-04-02 18:01:38 -070072 jobject mReceiverWeakGlobal;
Jeff Brown32cbc38552011-12-01 14:01:49 -080073 InputConsumer mInputConsumer;
Jeff Brown603b4452012-04-06 17:39:41 -070074 sp<MessageQueue> mMessageQueue;
Jeff Brown32cbc38552011-12-01 14:01:49 -080075 PreallocatedInputEventFactory mInputEventFactory;
Jeff Brown072ec962012-02-07 14:46:57 -080076 bool mBatchedInputEventPending;
Jeff Brown56513492013-05-21 20:37:51 -070077 int mFdEvents;
78 Vector<Finish> mFinishQueue;
79
80 void setFdEvents(int events);
Jeff Brown32cbc38552011-12-01 14:01:49 -080081
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -080082 const std::string getInputChannelName() {
83 return mInputConsumer.getChannel()->getName();
Jeff Brown32cbc38552011-12-01 14:01:49 -080084 }
Jeff Brown3bdcdd82012-04-10 20:36:07 -070085
Jeff Brown80a1de12012-05-31 16:23:11 -070086 virtual int handleEvent(int receiveFd, int events, void* data);
Jeff Brown32cbc38552011-12-01 14:01:49 -080087};
88
89
90NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
Jeff Browna4ca8ea2013-04-02 18:01:38 -070091 jobject receiverWeak, const sp<InputChannel>& inputChannel,
Jeff Brown603b4452012-04-06 17:39:41 -070092 const sp<MessageQueue>& messageQueue) :
Jeff Browna4ca8ea2013-04-02 18:01:38 -070093 mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
Jeff Brown603b4452012-04-06 17:39:41 -070094 mInputConsumer(inputChannel), mMessageQueue(messageQueue),
Jeff Brown56513492013-05-21 20:37:51 -070095 mBatchedInputEventPending(false), mFdEvents(0) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -080096 if (kDebugDispatchCycle) {
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -080097 ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName().c_str());
Andreas Gampeed6b9df2014-11-20 22:02:20 -080098 }
Jeff Brown32cbc38552011-12-01 14:01:49 -080099}
100
101NativeInputEventReceiver::~NativeInputEventReceiver() {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800102 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700103 env->DeleteGlobalRef(mReceiverWeakGlobal);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800104}
105
106status_t NativeInputEventReceiver::initialize() {
Jeff Brown56513492013-05-21 20:37:51 -0700107 setFdEvents(ALOOPER_EVENT_INPUT);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800108 return OK;
109}
110
Jeff Brown80a1de12012-05-31 16:23:11 -0700111void NativeInputEventReceiver::dispose() {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800112 if (kDebugDispatchCycle) {
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800113 ALOGD("channel '%s' ~ Disposing input event receiver.", getInputChannelName().c_str());
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800114 }
Jeff Brown80a1de12012-05-31 16:23:11 -0700115
Jeff Brown56513492013-05-21 20:37:51 -0700116 setFdEvents(0);
Jeff Brown80a1de12012-05-31 16:23:11 -0700117}
118
Jeff Brown072ec962012-02-07 14:46:57 -0800119status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800120 if (kDebugDispatchCycle) {
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800121 ALOGD("channel '%s' ~ Finished input event.", getInputChannelName().c_str());
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800122 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800123
Jeff Brown072ec962012-02-07 14:46:57 -0800124 status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
125 if (status) {
Jeff Brown56513492013-05-21 20:37:51 -0700126 if (status == WOULD_BLOCK) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800127 if (kDebugDispatchCycle) {
128 ALOGD("channel '%s' ~ Could not send finished signal immediately. "
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800129 "Enqueued for later.", getInputChannelName().c_str());
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800130 }
Jeff Brown56513492013-05-21 20:37:51 -0700131 Finish finish;
132 finish.seq = seq;
133 finish.handled = handled;
134 mFinishQueue.add(finish);
135 if (mFinishQueue.size() == 1) {
136 setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
137 }
138 return OK;
139 }
Jeff Brown072ec962012-02-07 14:46:57 -0800140 ALOGW("Failed to send finished signal on channel '%s'. status=%d",
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800141 getInputChannelName().c_str(), status);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800142 }
Jeff Brown072ec962012-02-07 14:46:57 -0800143 return status;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800144}
145
Jeff Brown56513492013-05-21 20:37:51 -0700146void NativeInputEventReceiver::setFdEvents(int events) {
147 if (mFdEvents != events) {
148 mFdEvents = events;
149 int fd = mInputConsumer.getChannel()->getFd();
150 if (events) {
151 mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
152 } else {
153 mMessageQueue->getLooper()->removeFd(fd);
154 }
155 }
156}
157
Jeff Brown80a1de12012-05-31 16:23:11 -0700158int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800159 if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
Jeff Brown44e13ef2013-03-27 12:34:30 -0700160 // This error typically occurs when the publisher has closed the input channel
161 // as part of removing a window or finishing an IME session, in which case
162 // the consumer will soon be disposed as well.
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800163 if (kDebugDispatchCycle) {
164 ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred. "
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800165 "events=0x%x", getInputChannelName().c_str(), events);
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800166 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800167 return 0; // remove the callback
168 }
169
Jeff Brown56513492013-05-21 20:37:51 -0700170 if (events & ALOOPER_EVENT_INPUT) {
171 JNIEnv* env = AndroidRuntime::getJNIEnv();
Michael Wright62ce65d2013-10-25 14:50:36 -0700172 status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
Jeff Brown56513492013-05-21 20:37:51 -0700173 mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
174 return status == OK || status == NO_MEMORY ? 1 : 0;
175 }
176
177 if (events & ALOOPER_EVENT_OUTPUT) {
178 for (size_t i = 0; i < mFinishQueue.size(); i++) {
179 const Finish& finish = mFinishQueue.itemAt(i);
180 status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
181 if (status) {
182 mFinishQueue.removeItemsAt(0, i);
183
184 if (status == WOULD_BLOCK) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800185 if (kDebugDispatchCycle) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100186 ALOGD("channel '%s' ~ Sent %zu queued finish events; %zu left.",
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800187 getInputChannelName().c_str(), i, mFinishQueue.size());
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800188 }
Jeff Brown56513492013-05-21 20:37:51 -0700189 return 1; // keep the callback, try again later
190 }
191
192 ALOGW("Failed to send finished signal on channel '%s'. status=%d",
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800193 getInputChannelName().c_str(), status);
Jeff Brown56513492013-05-21 20:37:51 -0700194 if (status != DEAD_OBJECT) {
195 JNIEnv* env = AndroidRuntime::getJNIEnv();
196 String8 message;
197 message.appendFormat("Failed to finish input event. status=%d", status);
198 jniThrowRuntimeException(env, message.string());
199 mMessageQueue->raiseAndClearException(env, "finishInputEvent");
200 }
201 return 0; // remove the callback
202 }
203 }
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800204 if (kDebugDispatchCycle) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100205 ALOGD("channel '%s' ~ Sent %zu queued finish events; none left.",
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800206 getInputChannelName().c_str(), mFinishQueue.size());
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800207 }
Jeff Brown56513492013-05-21 20:37:51 -0700208 mFinishQueue.clear();
209 setFdEvents(ALOOPER_EVENT_INPUT);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800210 return 1;
211 }
212
Jeff Brown56513492013-05-21 20:37:51 -0700213 ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800214 "events=0x%x", getInputChannelName().c_str(), events);
Jeff Brown56513492013-05-21 20:37:51 -0700215 return 1;
Jeff Brown072ec962012-02-07 14:46:57 -0800216}
Jeff Brown32cbc38552011-12-01 14:01:49 -0800217
Jeff Brown771526c2012-04-27 15:13:25 -0700218status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
Michael Wright62ce65d2013-10-25 14:50:36 -0700219 bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800220 if (kDebugDispatchCycle) {
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800221 ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%" PRId64,
222 getInputChannelName().c_str(),
223 consumeBatches ? "true" : "false", frameTime);
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800224 }
Jeff Brown072ec962012-02-07 14:46:57 -0800225
226 if (consumeBatches) {
227 mBatchedInputEventPending = false;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800228 }
Michael Wright62ce65d2013-10-25 14:50:36 -0700229 if (outConsumedBatch) {
230 *outConsumedBatch = false;
231 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800232
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700233 ScopedLocalRef<jobject> receiverObj(env, NULL);
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700234 bool skipCallbacks = false;
Jeff Brown072ec962012-02-07 14:46:57 -0800235 for (;;) {
236 uint32_t seq;
237 InputEvent* inputEvent;
238 status_t status = mInputConsumer.consume(&mInputEventFactory,
Siarhei Vishniakou85ddfff2018-01-31 16:49:36 -0800239 consumeBatches, frameTime, &seq, &inputEvent);
Jeff Brown072ec962012-02-07 14:46:57 -0800240 if (status) {
241 if (status == WOULD_BLOCK) {
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700242 if (!skipCallbacks && !mBatchedInputEventPending
243 && mInputConsumer.hasPendingBatch()) {
Jeff Brown072ec962012-02-07 14:46:57 -0800244 // There is a pending batch. Come back later.
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700245 if (!receiverObj.get()) {
246 receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
247 if (!receiverObj.get()) {
248 ALOGW("channel '%s' ~ Receiver object was finalized "
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800249 "without being disposed.", getInputChannelName().c_str());
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700250 return DEAD_OBJECT;
251 }
252 }
253
Jeff Brown072ec962012-02-07 14:46:57 -0800254 mBatchedInputEventPending = true;
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800255 if (kDebugDispatchCycle) {
256 ALOGD("channel '%s' ~ Dispatching batched input event pending notification.",
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800257 getInputChannelName().c_str());
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800258 }
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700259 env->CallVoidMethod(receiverObj.get(),
Jeff Brown072ec962012-02-07 14:46:57 -0800260 gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700261 if (env->ExceptionCheck()) {
262 ALOGE("Exception dispatching batched input events.");
Jeff Brown072ec962012-02-07 14:46:57 -0800263 mBatchedInputEventPending = false; // try again later
264 }
265 }
266 return OK;
267 }
268 ALOGE("channel '%s' ~ Failed to consume input event. status=%d",
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800269 getInputChannelName().c_str(), status);
Jeff Brown072ec962012-02-07 14:46:57 -0800270 return status;
271 }
272 assert(inputEvent);
273
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700274 if (!skipCallbacks) {
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700275 if (!receiverObj.get()) {
276 receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
277 if (!receiverObj.get()) {
278 ALOGW("channel '%s' ~ Receiver object was finalized "
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800279 "without being disposed.", getInputChannelName().c_str());
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700280 return DEAD_OBJECT;
281 }
282 }
283
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700284 jobject inputEventObj;
285 switch (inputEvent->getType()) {
286 case AINPUT_EVENT_TYPE_KEY:
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800287 if (kDebugDispatchCycle) {
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800288 ALOGD("channel '%s' ~ Received key event.", getInputChannelName().c_str());
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800289 }
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700290 inputEventObj = android_view_KeyEvent_fromNative(env,
291 static_cast<KeyEvent*>(inputEvent));
292 break;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800293
Michael Wright62ce65d2013-10-25 14:50:36 -0700294 case AINPUT_EVENT_TYPE_MOTION: {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800295 if (kDebugDispatchCycle) {
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800296 ALOGD("channel '%s' ~ Received motion event.", getInputChannelName().c_str());
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800297 }
Michael Wright62ce65d2013-10-25 14:50:36 -0700298 MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);
299 if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) {
300 *outConsumedBatch = true;
301 }
302 inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700303 break;
Michael Wright62ce65d2013-10-25 14:50:36 -0700304 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800305
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700306 default:
307 assert(false); // InputConsumer should prevent this from ever happening
308 inputEventObj = NULL;
309 }
310
311 if (inputEventObj) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800312 if (kDebugDispatchCycle) {
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800313 ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName().c_str());
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800314 }
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700315 env->CallVoidMethod(receiverObj.get(),
Siarhei Vishniakou85ddfff2018-01-31 16:49:36 -0800316 gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700317 if (env->ExceptionCheck()) {
318 ALOGE("Exception dispatching input event.");
319 skipCallbacks = true;
320 }
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700321 env->DeleteLocalRef(inputEventObj);
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700322 } else {
Siarhei Vishniakoud6058f42018-01-04 13:00:48 -0800323 ALOGW("channel '%s' ~ Failed to obtain event object.",
324 getInputChannelName().c_str());
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700325 skipCallbacks = true;
326 }
Jeff Brown072ec962012-02-07 14:46:57 -0800327 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800328
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700329 if (skipCallbacks) {
Jeff Brown072ec962012-02-07 14:46:57 -0800330 mInputConsumer.sendFinishedSignal(seq, false);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800331 }
332 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800333}
334
335
Ashok Bhata931d5212014-01-08 14:04:51 +0000336static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
Jeff Brown32cbc38552011-12-01 14:01:49 -0800337 jobject inputChannelObj, jobject messageQueueObj) {
338 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
339 inputChannelObj);
340 if (inputChannel == NULL) {
341 jniThrowRuntimeException(env, "InputChannel is not initialized.");
342 return 0;
343 }
344
Jeff Brown603b4452012-04-06 17:39:41 -0700345 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
346 if (messageQueue == NULL) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800347 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
348 return 0;
349 }
350
351 sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
Jeff Browna4ca8ea2013-04-02 18:01:38 -0700352 receiverWeak, inputChannel, messageQueue);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800353 status_t status = receiver->initialize();
354 if (status) {
355 String8 message;
356 message.appendFormat("Failed to initialize input event receiver. status=%d", status);
357 jniThrowRuntimeException(env, message.string());
358 return 0;
359 }
360
361 receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
Ashok Bhata931d5212014-01-08 14:04:51 +0000362 return reinterpret_cast<jlong>(receiver.get());
Jeff Brown32cbc38552011-12-01 14:01:49 -0800363}
364
Ashok Bhata931d5212014-01-08 14:04:51 +0000365static void nativeDispose(JNIEnv* env, jclass clazz, jlong receiverPtr) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800366 sp<NativeInputEventReceiver> receiver =
367 reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
Jeff Brown80a1de12012-05-31 16:23:11 -0700368 receiver->dispose();
Jeff Brown32cbc38552011-12-01 14:01:49 -0800369 receiver->decStrong(gInputEventReceiverClassInfo.clazz); // drop reference held by the object
370}
371
Ashok Bhata931d5212014-01-08 14:04:51 +0000372static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
Jeff Brown072ec962012-02-07 14:46:57 -0800373 jint seq, jboolean handled) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800374 sp<NativeInputEventReceiver> receiver =
375 reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
Jeff Brown072ec962012-02-07 14:46:57 -0800376 status_t status = receiver->finishInputEvent(seq, handled);
Jeff Brown9806a232012-02-17 10:28:09 -0800377 if (status && status != DEAD_OBJECT) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800378 String8 message;
379 message.appendFormat("Failed to finish input event. status=%d", status);
380 jniThrowRuntimeException(env, message.string());
381 }
382}
383
Ashok Bhata931d5212014-01-08 14:04:51 +0000384static jboolean nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jlong receiverPtr,
Jeff Brown771526c2012-04-27 15:13:25 -0700385 jlong frameTimeNanos) {
Jeff Brown072ec962012-02-07 14:46:57 -0800386 sp<NativeInputEventReceiver> receiver =
387 reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
Michael Wright62ce65d2013-10-25 14:50:36 -0700388 bool consumedBatch;
389 status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos,
390 &consumedBatch);
Jeff Brown3bdcdd82012-04-10 20:36:07 -0700391 if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
Jeff Brown072ec962012-02-07 14:46:57 -0800392 String8 message;
393 message.appendFormat("Failed to consume batched input event. status=%d", status);
394 jniThrowRuntimeException(env, message.string());
Ashok Bhata931d5212014-01-08 14:04:51 +0000395 return JNI_FALSE;
Jeff Brown072ec962012-02-07 14:46:57 -0800396 }
Ashok Bhata931d5212014-01-08 14:04:51 +0000397 return consumedBatch ? JNI_TRUE : JNI_FALSE;
Jeff Brown072ec962012-02-07 14:46:57 -0800398}
399
Jeff Brown32cbc38552011-12-01 14:01:49 -0800400
Daniel Micay76f6a862015-09-19 17:31:01 -0400401static const JNINativeMethod gMethods[] = {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800402 /* name, signature, funcPtr */
403 { "nativeInit",
Ashok Bhata931d5212014-01-08 14:04:51 +0000404 "(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)J",
Jeff Brown32cbc38552011-12-01 14:01:49 -0800405 (void*)nativeInit },
Ashok Bhata931d5212014-01-08 14:04:51 +0000406 { "nativeDispose", "(J)V",
Jeff Brown32cbc38552011-12-01 14:01:49 -0800407 (void*)nativeDispose },
Ashok Bhata931d5212014-01-08 14:04:51 +0000408 { "nativeFinishInputEvent", "(JIZ)V",
Jeff Brown072ec962012-02-07 14:46:57 -0800409 (void*)nativeFinishInputEvent },
Ashok Bhata931d5212014-01-08 14:04:51 +0000410 { "nativeConsumeBatchedInputEvents", "(JJ)Z",
Jeff Brown072ec962012-02-07 14:46:57 -0800411 (void*)nativeConsumeBatchedInputEvents },
Jeff Brown32cbc38552011-12-01 14:01:49 -0800412};
413
Jeff Brown32cbc38552011-12-01 14:01:49 -0800414int register_android_view_InputEventReceiver(JNIEnv* env) {
Andreas Gampe987f79f2014-11-18 17:29:46 -0800415 int res = RegisterMethodsOrDie(env, "android/view/InputEventReceiver",
Jeff Brown32cbc38552011-12-01 14:01:49 -0800416 gMethods, NELEM(gMethods));
Jeff Brown32cbc38552011-12-01 14:01:49 -0800417
Andreas Gampe987f79f2014-11-18 17:29:46 -0800418 jclass clazz = FindClassOrDie(env, "android/view/InputEventReceiver");
419 gInputEventReceiverClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800420
Andreas Gampe987f79f2014-11-18 17:29:46 -0800421 gInputEventReceiverClassInfo.dispatchInputEvent = GetMethodIDOrDie(env,
Jeff Brown32cbc38552011-12-01 14:01:49 -0800422 gInputEventReceiverClassInfo.clazz,
Siarhei Vishniakou85ddfff2018-01-31 16:49:36 -0800423 "dispatchInputEvent", "(ILandroid/view/InputEvent;)V");
Andreas Gampe987f79f2014-11-18 17:29:46 -0800424 gInputEventReceiverClassInfo.dispatchBatchedInputEventPending = GetMethodIDOrDie(env,
425 gInputEventReceiverClassInfo.clazz, "dispatchBatchedInputEventPending", "()V");
426
427 return res;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800428}
429
430} // namespace android