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