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
36a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightnamespace android {
37a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
38a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightstatic struct {
39a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    jmethodID finishInputEvent;
40a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright} gInputQueueClassInfo;
41a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
42a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightenum {
43a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    MSG_FINISH_INPUT = 1,
44a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright};
45a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
46a44dd26a75e24cc021802288fb81f4761e47be6bMichael WrightInputQueue::InputQueue(jobject inputQueueObj, const sp<Looper>& looper,
47a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        int dispatchReadFd, int dispatchWriteFd) :
48a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        mDispatchReadFd(dispatchReadFd), mDispatchWriteFd(dispatchWriteFd),
49a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        mDispatchLooper(looper), mHandler(new WeakMessageHandler(this)) {
50a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    JNIEnv* env = AndroidRuntime::getJNIEnv();
51a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mInputQueueWeakGlobal = env->NewGlobalRef(inputQueueObj);
52a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
53a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
54a44dd26a75e24cc021802288fb81f4761e47be6bMichael WrightInputQueue::~InputQueue() {
55a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mDispatchLooper->removeMessages(mHandler);
56a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    JNIEnv* env = AndroidRuntime::getJNIEnv();
57a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    env->DeleteGlobalRef(mInputQueueWeakGlobal);
58a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    close(mDispatchReadFd);
59a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    close(mDispatchWriteFd);
60a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
61a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
62a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::attachLooper(Looper* looper, int ident,
63a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        ALooper_callbackFunc callback, void* data) {
64a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
65a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    for (size_t i = 0; i < mAppLoopers.size(); i++) {
66a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        if (looper == mAppLoopers[i]) {
67a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            return;
68a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        }
69a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
70a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mAppLoopers.push(looper);
71a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    looper->addFd(mDispatchReadFd, ident, ALOOPER_EVENT_INPUT, callback, data);
72a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
73a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
74a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::detachLooper() {
75a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
76a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    detachLooperLocked();
77a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
78a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
79a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::detachLooperLocked() {
80a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    for (size_t i = 0; i < mAppLoopers.size(); i++) {
81a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        mAppLoopers[i]->removeFd(mDispatchReadFd);
82a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
83a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mAppLoopers.clear();
84a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
85a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
86a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightbool InputQueue::hasEvents() {
87a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
88a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return mPendingEvents.size() > 0;
89a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
90a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
91a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightstatus_t InputQueue::getEvent(InputEvent** outEvent) {
92a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
93a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    *outEvent = NULL;
94a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (!mPendingEvents.isEmpty()) {
95a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        *outEvent = mPendingEvents[0];
96a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        mPendingEvents.removeAt(0);
97a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
98a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
99a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (mPendingEvents.isEmpty()) {
100a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        char byteread[16];
101a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        ssize_t nRead;
102a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        do {
103a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            nRead = TEMP_FAILURE_RETRY(read(mDispatchReadFd, &byteread, sizeof(byteread)));
104a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            if (nRead < 0 && errno != EAGAIN) {
105a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                ALOGW("Failed to read from native dispatch pipe: %s", strerror(errno));
106a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            }
107a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        } while (nRead > 0);
108a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
109a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
110a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return *outEvent != NULL ? OK : WOULD_BLOCK;
111a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
112a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
113a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightbool InputQueue::preDispatchEvent(InputEvent* e) {
114a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (e->getType() == AINPUT_EVENT_TYPE_KEY) {
115a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        KeyEvent* keyEvent = static_cast<KeyEvent*>(e);
116a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        if (keyEvent->getFlags() & AKEY_EVENT_FLAG_PREDISPATCH) {
117a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            finishEvent(e, false);
118a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            return true;
119a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        }
120a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
121a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return false;
122a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
123a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
124a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::finishEvent(InputEvent* event, bool handled) {
125a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
126a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mFinishedEvents.push(key_value_pair_t<InputEvent*, bool>(event, handled));
127a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (mFinishedEvents.size() == 1) {
128a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        mDispatchLooper->sendMessage(this, Message(MSG_FINISH_INPUT));
129a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
130a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
131a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
132a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::handleMessage(const Message& message) {
133a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    switch(message.what) {
134a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    case MSG_FINISH_INPUT:
135a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        JNIEnv* env = AndroidRuntime::getJNIEnv();
136a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        ScopedLocalRef<jobject> inputQueueObj(env, jniGetReferent(env, mInputQueueWeakGlobal));
137a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        if (!inputQueueObj.get()) {
138a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            ALOGW("InputQueue was finalized without being disposed");
139a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            return;
140a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        }
141a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        while (true) {
142a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            InputEvent* event;
143a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            bool handled;
144a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            {
145a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                Mutex::Autolock _l(mLock);
146a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                if (mFinishedEvents.isEmpty()) {
147a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                    break;
148a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                }
149a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                event = mFinishedEvents[0].getKey();
150a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                handled = mFinishedEvents[0].getValue();
151a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright                mFinishedEvents.removeAt(0);
152a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            }
153a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            env->CallVoidMethod(inputQueueObj.get(), gInputQueueClassInfo.finishInputEvent,
154a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat                    reinterpret_cast<jlong>(event), handled);
155a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            recycleInputEvent(event);
156a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        }
157a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        break;
158a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
159a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
160a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
161a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::recycleInputEvent(InputEvent* event) {
162a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mPooledInputEventFactory.recycle(event);
163a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
164a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
165a44dd26a75e24cc021802288fb81f4761e47be6bMichael WrightKeyEvent* InputQueue::createKeyEvent() {
166a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return mPooledInputEventFactory.createKeyEvent();
167a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
168a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
169a44dd26a75e24cc021802288fb81f4761e47be6bMichael WrightMotionEvent* InputQueue::createMotionEvent() {
170a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return mPooledInputEventFactory.createMotionEvent();
171a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
172a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
173a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightvoid InputQueue::enqueueEvent(InputEvent* event) {
174a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    Mutex::Autolock _l(mLock);
175a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    mPendingEvents.push(event);
176a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (mPendingEvents.size() == 1) {
177a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        char dummy = 0;
178a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        int res = TEMP_FAILURE_RETRY(write(mDispatchWriteFd, &dummy, sizeof(dummy)));
179a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        if (res < 0 && errno != EAGAIN) {
180a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright            ALOGW("Failed writing to dispatch fd: %s", strerror(errno));
181a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        }
182a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
183a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
184a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
185a44dd26a75e24cc021802288fb81f4761e47be6bMichael WrightInputQueue* InputQueue::createQueue(jobject inputQueueObj, const sp<Looper>& looper) {
186a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    int pipeFds[2];
187a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (pipe(pipeFds)) {
188a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        ALOGW("Could not create native input dispatching pipe: %s", strerror(errno));
189a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        return NULL;
190a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
191a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    fcntl(pipeFds[0], F_SETFL, O_NONBLOCK);
192a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    fcntl(pipeFds[1], F_SETFL, O_NONBLOCK);
193a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return new InputQueue(inputQueueObj, looper, pipeFds[0], pipeFds[1]);
194a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
195a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
196a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jlong nativeInit(JNIEnv* env, jobject clazz, jobject queueWeak, jobject jMsgQueue) {
197a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, jMsgQueue);
198a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (messageQueue == NULL) {
199a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
200a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        return 0;
201a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
202a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    sp<InputQueue> queue = InputQueue::createQueue(queueWeak, messageQueue->getLooper());
203a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (!queue.get()) {
204a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        jniThrowRuntimeException(env, "InputQueue failed to initialize");
205a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        return 0;
206a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
207a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    queue->incStrong(&gInputQueueClassInfo);
208a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    return reinterpret_cast<jlong>(queue.get());
209a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
210a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
211a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic void nativeDispose(JNIEnv* env, jobject clazz, jlong ptr) {
212a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    sp<InputQueue> queue = reinterpret_cast<InputQueue*>(ptr);
213a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    queue->detachLooper();
214a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    queue->decStrong(&gInputQueueClassInfo);
215a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
216a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
217a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jlong nativeSendKeyEvent(JNIEnv* env, jobject clazz, jlong ptr, jobject eventObj,
218a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        jboolean predispatch) {
219a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    InputQueue* queue = reinterpret_cast<InputQueue*>(ptr);
220a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    KeyEvent* event = queue->createKeyEvent();
221a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    status_t status = android_view_KeyEvent_toNative(env, eventObj, event);
222a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (status) {
223a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        queue->recycleInputEvent(event);
224a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
225a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        return -1;
226a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
227a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
228a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (predispatch) {
229a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        event->setFlags(event->getFlags() | AKEY_EVENT_FLAG_PREDISPATCH);
230a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
231a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
232a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    queue->enqueueEvent(event);
233a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    return reinterpret_cast<jlong>(event);
234a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
235a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
236a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jlong nativeSendMotionEvent(JNIEnv* env, jobject clazz, jlong ptr, jobject eventObj) {
237a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    sp<InputQueue> queue = reinterpret_cast<InputQueue*>(ptr);
238a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    MotionEvent* originalEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
239a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    if (!originalEvent) {
240a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        jniThrowRuntimeException(env, "Could not obtain MotionEvent pointer.");
241a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        return -1;
242a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    }
243a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    MotionEvent* event = queue->createMotionEvent();
244a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    event->copyFrom(originalEvent, true /* keepHistory */);
245a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    queue->enqueueEvent(event);
246a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    return reinterpret_cast<jlong>(event);
247a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
248a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
249a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightstatic const JNINativeMethod g_methods[] = {
250a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeInit", "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;)J",
251a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        (void*) nativeInit },
252a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeDispose", "(J)V", (void*) nativeDispose },
253a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeSendKeyEvent", "(JLandroid/view/KeyEvent;Z)J", (void*) nativeSendKeyEvent },
254a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeSendMotionEvent", "(JLandroid/view/MotionEvent;)J", (void*) nativeSendMotionEvent },
255a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright};
256a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
257a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightstatic const char* const kInputQueuePathName = "android/view/InputQueue";
258a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
259a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#define FIND_CLASS(var, className) \
260a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        do { \
261a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        var = env->FindClass(className); \
262a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        LOG_FATAL_IF(! var, "Unable to find class %s", className); \
263a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        } while(0)
264a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
265a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
266a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        do { \
267a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
268a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        LOG_FATAL_IF(! var, "Unable to find method" methodName); \
269a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        } while(0)
270a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
271a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wrightint register_android_view_InputQueue(JNIEnv* env)
272a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright{
273a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    jclass clazz;
274a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    FIND_CLASS(clazz, kInputQueuePathName);
275a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    GET_METHOD_ID(gInputQueueClassInfo.finishInputEvent, clazz, "finishInputEvent", "(JZ)V");
276a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
277a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright    return AndroidRuntime::registerNativeMethods(
278a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        env, kInputQueuePathName,
279a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright        g_methods, NELEM(g_methods));
280a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright}
281a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright
282a44dd26a75e24cc021802288fb81f4761e47be6bMichael Wright} // namespace android
283