1a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright/*
2a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright * Copyright (C) 2013 The Android Open Source Project
3a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright *
4a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright * Licensed under the Apache License, Version 2.0 (the "License");
5a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright * you may not use this file except in compliance with the License.
6a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright * You may obtain a copy of the License at
7a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright *
8a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright *      http://www.apache.org/licenses/LICENSE-2.0
9a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright *
10a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright * Unless required by applicable law or agreed to in writing, software
11a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright * distributed under the License is distributed on an "AS IS" BASIS,
12a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright * See the License for the specific language governing permissions and
14a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright * limitations under the License.
15a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright */
16a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
17a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#define LOG_TAG "InputQueue"
18a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
19a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include <fcntl.h>
20a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include <string.h>
21a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include <unistd.h>
22a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
23a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include <android/input.h>
24a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include <android_runtime/AndroidRuntime.h>
25a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include <android_runtime/android_view_InputQueue.h>
269d3b1a424c5c61e24e9659d15fb353026a00d925Jeff Brown#include <input/Input.h>
27a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include <utils/Looper.h>
28a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include <utils/TypeHelpers.h>
29a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include <ScopedLocalRef.h>
30a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
31a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include "JNIHelp.h"
32a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include "android_os_MessageQueue.h"
33a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include "android_view_KeyEvent.h"
34a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#include "android_view_MotionEvent.h"
35a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
36987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe#include "core_jni_helpers.h"
37987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe
38a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightnamespace android {
39a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
40a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightstatic struct {
41a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    jmethodID finishInputEvent;
42a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright} gInputQueueClassInfo;
43a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
44a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightenum {
45a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    MSG_FINISH_INPUT = 1,
46a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright};
47a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
48a44dd26a75e24cc021802288fb81f4761e47be6bMichael WrightInputQueue::InputQueue(jobject inputQueueObj, const sp<Looper>& looper,
49a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        int dispatchReadFd, int dispatchWriteFd) :
50a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        mDispatchReadFd(dispatchReadFd), mDispatchWriteFd(dispatchWriteFd),
51a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        mDispatchLooper(looper), mHandler(new WeakMessageHandler(this)) {
52a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    JNIEnv* env = AndroidRuntime::getJNIEnv();
53a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mInputQueueWeakGlobal = env->NewGlobalRef(inputQueueObj);
54a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
55a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
56a44dd26a75e24cc021802288fb81f4761e47be6bMichael WrightInputQueue::~InputQueue() {
57a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mDispatchLooper->removeMessages(mHandler);
58a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    JNIEnv* env = AndroidRuntime::getJNIEnv();
59a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    env->DeleteGlobalRef(mInputQueueWeakGlobal);
60a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    close(mDispatchReadFd);
61a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    close(mDispatchWriteFd);
62a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
63a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
64a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::attachLooper(Looper* looper, int ident,
65a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        ALooper_callbackFunc callback, void* data) {
66a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
67a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    for (size_t i = 0; i < mAppLoopers.size(); i++) {
68a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        if (looper == mAppLoopers[i]) {
69a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            return;
70a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        }
71a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
72a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mAppLoopers.push(looper);
73a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    looper->addFd(mDispatchReadFd, ident, ALOOPER_EVENT_INPUT, callback, data);
74a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
75a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
76a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::detachLooper() {
77a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
78a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    detachLooperLocked();
79a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
80a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
81a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::detachLooperLocked() {
82a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    for (size_t i = 0; i < mAppLoopers.size(); i++) {
83a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        mAppLoopers[i]->removeFd(mDispatchReadFd);
84a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
85a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mAppLoopers.clear();
86a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
87a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
88a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightbool InputQueue::hasEvents() {
89a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
90a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return mPendingEvents.size() > 0;
91a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
92a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
93a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightstatus_t InputQueue::getEvent(InputEvent** outEvent) {
94a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
95a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    *outEvent = NULL;
96a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (!mPendingEvents.isEmpty()) {
97a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        *outEvent = mPendingEvents[0];
98a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        mPendingEvents.removeAt(0);
99a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
100a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
101a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (mPendingEvents.isEmpty()) {
102a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        char byteread[16];
103a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        ssize_t nRead;
104a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        do {
105a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            nRead = TEMP_FAILURE_RETRY(read(mDispatchReadFd, &byteread, sizeof(byteread)));
106a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            if (nRead < 0 && errno != EAGAIN) {
107a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                ALOGW("Failed to read from native dispatch pipe: %s", strerror(errno));
108a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            }
109a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        } while (nRead > 0);
110a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
111a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
112a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return *outEvent != NULL ? OK : WOULD_BLOCK;
113a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
114a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
115a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightbool InputQueue::preDispatchEvent(InputEvent* e) {
116a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (e->getType() == AINPUT_EVENT_TYPE_KEY) {
117a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        KeyEvent* keyEvent = static_cast<KeyEvent*>(e);
118a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        if (keyEvent->getFlags() & AKEY_EVENT_FLAG_PREDISPATCH) {
119a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            finishEvent(e, false);
120a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            return true;
121a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        }
122a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
123a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return false;
124a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
125a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
126a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::finishEvent(InputEvent* event, bool handled) {
127a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
128a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mFinishedEvents.push(key_value_pair_t<InputEvent*, bool>(event, handled));
129a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (mFinishedEvents.size() == 1) {
130a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        mDispatchLooper->sendMessage(this, Message(MSG_FINISH_INPUT));
131a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
132a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
133a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
134a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::handleMessage(const Message& message) {
135a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    switch(message.what) {
136a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    case MSG_FINISH_INPUT:
137a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        JNIEnv* env = AndroidRuntime::getJNIEnv();
138a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        ScopedLocalRef<jobject> inputQueueObj(env, jniGetReferent(env, mInputQueueWeakGlobal));
139a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        if (!inputQueueObj.get()) {
140a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            ALOGW("InputQueue was finalized without being disposed");
141a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            return;
142a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        }
143a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        while (true) {
144a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            InputEvent* event;
145a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            bool handled;
146a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            {
147a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                Mutex::Autolock _l(mLock);
148a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                if (mFinishedEvents.isEmpty()) {
149a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                    break;
150a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                }
151a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                event = mFinishedEvents[0].getKey();
152a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                handled = mFinishedEvents[0].getValue();
153a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                mFinishedEvents.removeAt(0);
154a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            }
155a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            env->CallVoidMethod(inputQueueObj.get(), gInputQueueClassInfo.finishInputEvent,
156a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat                    reinterpret_cast<jlong>(event), handled);
157a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            recycleInputEvent(event);
158a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        }
159a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        break;
160a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
161a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
162a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
163a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::recycleInputEvent(InputEvent* event) {
164a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mPooledInputEventFactory.recycle(event);
165a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
166a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
167a44dd26a75e24cc021802288fb81f4761e47be6bMichael WrightKeyEvent* InputQueue::createKeyEvent() {
168a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return mPooledInputEventFactory.createKeyEvent();
169a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
170a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
171a44dd26a75e24cc021802288fb81f4761e47be6bMichael WrightMotionEvent* InputQueue::createMotionEvent() {
172a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return mPooledInputEventFactory.createMotionEvent();
173a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
174a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
175a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::enqueueEvent(InputEvent* event) {
176a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
177a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mPendingEvents.push(event);
178a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (mPendingEvents.size() == 1) {
179a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        char dummy = 0;
180a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        int res = TEMP_FAILURE_RETRY(write(mDispatchWriteFd, &dummy, sizeof(dummy)));
181a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        if (res < 0 && errno != EAGAIN) {
182a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            ALOGW("Failed writing to dispatch fd: %s", strerror(errno));
183a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        }
184a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
185a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
186a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
187a44dd26a75e24cc021802288fb81f4761e47be6bMichael WrightInputQueue* InputQueue::createQueue(jobject inputQueueObj, const sp<Looper>& looper) {
188a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    int pipeFds[2];
189a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (pipe(pipeFds)) {
190a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        ALOGW("Could not create native input dispatching pipe: %s", strerror(errno));
191a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        return NULL;
192a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
193a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    fcntl(pipeFds[0], F_SETFL, O_NONBLOCK);
194a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    fcntl(pipeFds[1], F_SETFL, O_NONBLOCK);
195a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return new InputQueue(inputQueueObj, looper, pipeFds[0], pipeFds[1]);
196a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
197a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
198a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jlong nativeInit(JNIEnv* env, jobject clazz, jobject queueWeak, jobject jMsgQueue) {
199a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, jMsgQueue);
200a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (messageQueue == NULL) {
201a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
202a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        return 0;
203a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
204a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    sp<InputQueue> queue = InputQueue::createQueue(queueWeak, messageQueue->getLooper());
205a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (!queue.get()) {
206a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        jniThrowRuntimeException(env, "InputQueue failed to initialize");
207a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        return 0;
208a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
209a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    queue->incStrong(&gInputQueueClassInfo);
210a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    return reinterpret_cast<jlong>(queue.get());
211a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
212a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
213a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic void nativeDispose(JNIEnv* env, jobject clazz, jlong ptr) {
214a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    sp<InputQueue> queue = reinterpret_cast<InputQueue*>(ptr);
215a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    queue->detachLooper();
216a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    queue->decStrong(&gInputQueueClassInfo);
217a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
218a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
219a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jlong nativeSendKeyEvent(JNIEnv* env, jobject clazz, jlong ptr, jobject eventObj,
220a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        jboolean predispatch) {
221a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    InputQueue* queue = reinterpret_cast<InputQueue*>(ptr);
222a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    KeyEvent* event = queue->createKeyEvent();
223a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    status_t status = android_view_KeyEvent_toNative(env, eventObj, event);
224a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (status) {
225a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        queue->recycleInputEvent(event);
226a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
227a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        return -1;
228a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
229a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
230a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (predispatch) {
231a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        event->setFlags(event->getFlags() | AKEY_EVENT_FLAG_PREDISPATCH);
232a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
233a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
234a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    queue->enqueueEvent(event);
235a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    return reinterpret_cast<jlong>(event);
236a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
237a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
238a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jlong nativeSendMotionEvent(JNIEnv* env, jobject clazz, jlong ptr, jobject eventObj) {
239a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    sp<InputQueue> queue = reinterpret_cast<InputQueue*>(ptr);
240a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    MotionEvent* originalEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
241a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (!originalEvent) {
242a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        jniThrowRuntimeException(env, "Could not obtain MotionEvent pointer.");
243a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        return -1;
244a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
245a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    MotionEvent* event = queue->createMotionEvent();
246a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    event->copyFrom(originalEvent, true /* keepHistory */);
247a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    queue->enqueueEvent(event);
248a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    return reinterpret_cast<jlong>(event);
249a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
250a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
251a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightstatic const JNINativeMethod g_methods[] = {
252a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeInit", "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;)J",
253a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        (void*) nativeInit },
254a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeDispose", "(J)V", (void*) nativeDispose },
255a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeSendKeyEvent", "(JLandroid/view/KeyEvent;Z)J", (void*) nativeSendKeyEvent },
256a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeSendMotionEvent", "(JLandroid/view/MotionEvent;)J", (void*) nativeSendMotionEvent },
257a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright};
258a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
259a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightstatic const char* const kInputQueuePathName = "android/view/InputQueue";
260a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
261a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightint register_android_view_InputQueue(JNIEnv* env)
262a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright{
263987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    jclass clazz = FindClassOrDie(env, kInputQueuePathName);
264987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gInputQueueClassInfo.finishInputEvent = GetMethodIDOrDie(env, clazz, "finishInputEvent",
265987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe                                                             "(JZ)V");
266a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
267987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    return RegisterMethodsOrDie(env, kInputQueuePathName, g_methods, NELEM(g_methods));
268a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
269a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
270a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright} // namespace android
271