146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown/* 246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Copyright (C) 2010 The Android Open Source Project 346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * 446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * you may not use this file except in compliance with the License. 646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * You may obtain a copy of the License at 746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * 846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * 1046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Unless required by applicable law or agreed to in writing, software 1146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * See the License for the specific language governing permissions and 1446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * limitations under the License. 1546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown */ 1646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define LOG_TAG "InputQueue-JNI" 1846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown//#define LOG_NDEBUG 0 2046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 2146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// Log debug messages about the dispatch cycle. 22349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brown#define DEBUG_DISPATCH_CYCLE 0 2346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 249c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown// Log debug messages about registrations. 25349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brown#define DEBUG_REGISTRATION 0 269c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown 2746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 2846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include "JNIHelp.h" 2946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 3046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <android_runtime/AndroidRuntime.h> 3146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <utils/Log.h> 324fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown#include <utils/Looper.h> 3346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <utils/KeyedVector.h> 3446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <utils/threads.h> 3546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <ui/InputTransport.h> 3646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include "android_os_MessageQueue.h" 3746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include "android_view_InputChannel.h" 3846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include "android_view_KeyEvent.h" 3946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include "android_view_MotionEvent.h" 4046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 4146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownnamespace android { 4246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 4346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ---------------------------------------------------------------------------- 4446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 4546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic struct { 4646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jclass clazz; 4746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 4846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jmethodID dispatchKeyEvent; 4946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jmethodID dispatchMotionEvent; 5046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} gInputQueueClassInfo; 5146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 5246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ---------------------------------------------------------------------------- 5346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 5446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownclass NativeInputQueue { 5546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownpublic: 5646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown NativeInputQueue(); 579c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown ~NativeInputQueue(); 5846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 5946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown status_t registerInputChannel(JNIEnv* env, jobject inputChannelObj, 6046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jobject inputHandlerObj, jobject messageQueueObj); 6146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 6246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown status_t unregisterInputChannel(JNIEnv* env, jobject inputChannelObj); 6346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 6446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown status_t finished(JNIEnv* env, jlong finishedToken, bool ignoreSpuriousFinish); 6546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 6646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownprivate: 6746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown class Connection : public RefBase { 6846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown protected: 6946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown virtual ~Connection(); 7046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 7146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown public: 7246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown enum Status { 7346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // Everything is peachy. 7446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown STATUS_NORMAL, 7546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // The input channel has been unregistered. 7646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown STATUS_ZOMBIE 7746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown }; 7846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 792cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown Connection(uint16_t id, 804fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown const sp<InputChannel>& inputChannel, const sp<Looper>& looper); 8146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 829c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown inline const char* getInputChannelName() const { return inputChannel->getName().string(); } 8346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 842cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown // A unique id for this connection. 852cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown uint16_t id; 862cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown 8746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown Status status; 8846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 8946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown sp<InputChannel> inputChannel; 9046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown InputConsumer inputConsumer; 914fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown sp<Looper> looper; 9246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jobject inputHandlerObjGlobal; 9346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown PreallocatedInputEventFactory inputEventFactory; 9446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 9546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // The sequence number of the current event being dispatched. 9646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // This is used as part of the finished token as a way to determine whether the finished 9746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // token is still valid before sending a finished signal back to the publisher. 982cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown uint16_t messageSeqNum; 9946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 10046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // True if a message has been received from the publisher but not yet finished. 10146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown bool messageInProgress; 10246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown }; 10346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 10446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown Mutex mLock; 1052cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown uint16_t mNextConnectionId; 10646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown KeyedVector<int32_t, sp<Connection> > mConnectionsByReceiveFd; 10746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1082cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown ssize_t getConnectionIndex(const sp<InputChannel>& inputChannel); 1092cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown 11046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown static void handleInputChannelDisposed(JNIEnv* env, 11146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data); 11246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1134fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown static int handleReceiveCallback(int receiveFd, int events, void* data); 11446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1152cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown static jlong generateFinishedToken(int32_t receiveFd, 1162cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown uint16_t connectionId, uint16_t messageSeqNum); 11746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 11846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown static void parseFinishedToken(jlong finishedToken, 1192cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown int32_t* outReceiveFd, uint16_t* outConnectionId, uint16_t* outMessageIndex); 12046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}; 12146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 12246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ---------------------------------------------------------------------------- 12346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1242cbecea4c9627d95377fc3e3b8a319116cee7febJeff BrownNativeInputQueue::NativeInputQueue() : 1252cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown mNextConnectionId(0) { 12646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 12746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 12846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff BrownNativeInputQueue::~NativeInputQueue() { 12946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 13046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 13146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatus_t NativeInputQueue::registerInputChannel(JNIEnv* env, jobject inputChannelObj, 13246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jobject inputHandlerObj, jobject messageQueueObj) { 13346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, 13446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown inputChannelObj); 13546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (inputChannel == NULL) { 13646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("Input channel is not initialized."); 13746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return BAD_VALUE; 13846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 13946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1409c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown#if DEBUG_REGISTRATION 1419c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown LOGD("channel '%s' - Registered", inputChannel->getName().string()); 1429c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown#endif 1439c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown 1444fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj); 14546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 14646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown { // acquire lock 14746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown AutoMutex _l(mLock); 14846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1492cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown if (getConnectionIndex(inputChannel) >= 0) { 15046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("Attempted to register already registered input channel '%s'", 15146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown inputChannel->getName().string()); 15246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return BAD_VALUE; 15346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 15446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1552cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown uint16_t connectionId = mNextConnectionId++; 1564fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown sp<Connection> connection = new Connection(connectionId, inputChannel, looper); 15746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown status_t result = connection->inputConsumer.initialize(); 15846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (result) { 15946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("Failed to initialize input consumer for input channel '%s', status=%d", 16046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown inputChannel->getName().string(), result); 16146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return result; 16246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 16346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 16446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->inputHandlerObjGlobal = env->NewGlobalRef(inputHandlerObj); 16546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1662cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown int32_t receiveFd = inputChannel->getReceivePipeFd(); 16746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown mConnectionsByReceiveFd.add(receiveFd, connection); 1682cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown 1694fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown looper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); 17046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } // release lock 17146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 17246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown android_view_InputChannel_setDisposeCallback(env, inputChannelObj, 17346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown handleInputChannelDisposed, this); 17446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return OK; 17546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 17646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 17746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatus_t NativeInputQueue::unregisterInputChannel(JNIEnv* env, jobject inputChannelObj) { 17846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, 17946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown inputChannelObj); 18046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (inputChannel == NULL) { 18146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("Input channel is not initialized."); 18246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return BAD_VALUE; 18346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 18446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1859c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown#if DEBUG_REGISTRATION 1869c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown LOGD("channel '%s' - Unregistered", inputChannel->getName().string()); 1879c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown#endif 1889c3cda04d969912bc46184f2b326d1db95e0aba5Jeff Brown 18946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown { // acquire lock 19046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown AutoMutex _l(mLock); 19146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1922cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown ssize_t connectionIndex = getConnectionIndex(inputChannel); 19346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (connectionIndex < 0) { 19446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("Attempted to unregister already unregistered input channel '%s'", 19546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown inputChannel->getName().string()); 19646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return BAD_VALUE; 19746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 19846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 1992cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex); 20046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown mConnectionsByReceiveFd.removeItemsAt(connectionIndex); 20146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 20246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->status = Connection::STATUS_ZOMBIE; 20346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 2044fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown connection->looper->removeFd(inputChannel->getReceivePipeFd()); 2052cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown 20646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown env->DeleteGlobalRef(connection->inputHandlerObjGlobal); 20746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->inputHandlerObjGlobal = NULL; 2082cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown 2092cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown if (connection->messageInProgress) { 2102cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown LOGI("Sending finished signal for input channel '%s' since it is being unregistered " 2112cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown "while an input message is still in progress.", 2122cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown connection->getInputChannelName()); 2132cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown connection->messageInProgress = false; 2142cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown connection->inputConsumer.sendFinishedSignal(); // ignoring result 2152cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown } 21646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } // release lock 21746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 21846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL); 21946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return OK; 22046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 22146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 2222cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brownssize_t NativeInputQueue::getConnectionIndex(const sp<InputChannel>& inputChannel) { 2232cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd()); 2242cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown if (connectionIndex >= 0) { 2252cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex); 2262cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown if (connection->inputChannel.get() == inputChannel.get()) { 2272cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown return connectionIndex; 2282cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown } 2292cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown } 2302cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown 2312cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown return -1; 2322cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown} 2332cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown 23446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatus_t NativeInputQueue::finished(JNIEnv* env, jlong finishedToken, bool ignoreSpuriousFinish) { 23546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown int32_t receiveFd; 2362cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown uint16_t connectionId; 2372cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown uint16_t messageSeqNum; 2382cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown parseFinishedToken(finishedToken, &receiveFd, &connectionId, &messageSeqNum); 23946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 24046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown { // acquire lock 24146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown AutoMutex _l(mLock); 24246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 24346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd); 24446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (connectionIndex < 0) { 24546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (! ignoreSpuriousFinish) { 2462cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown LOGI("Ignoring finish signal on channel that is no longer registered."); 24746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 24846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return DEAD_OBJECT; 24946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 25046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 25146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex); 2522cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown if (connectionId != connection->id) { 2532cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown if (! ignoreSpuriousFinish) { 2542cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown LOGI("Ignoring finish signal on channel that is no longer registered."); 2552cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown } 2562cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown return DEAD_OBJECT; 2572cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown } 2582cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown 25946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (messageSeqNum != connection->messageSeqNum || ! connection->messageInProgress) { 26046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (! ignoreSpuriousFinish) { 2612cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown LOGW("Attempted to finish input twice on channel '%s'. " 2622cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown "finished messageSeqNum=%d, current messageSeqNum=%d, messageInProgress=%d", 2632cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown connection->getInputChannelName(), 2642cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown messageSeqNum, connection->messageSeqNum, connection->messageInProgress); 26546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 26646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return INVALID_OPERATION; 26746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 26846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 26946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->messageInProgress = false; 27046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 27146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown status_t status = connection->inputConsumer.sendFinishedSignal(); 27246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (status) { 27346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("Failed to send finished signal on channel '%s'. status=%d", 27446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->getInputChannelName(), status); 27546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return status; 27646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 27746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 27846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#if DEBUG_DISPATCH_CYCLE 27946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGD("channel '%s' ~ Finished event.", 28046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->getInputChannelName()); 28146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#endif 28246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } // release lock 28346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 28446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return OK; 28546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 28646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 28746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid NativeInputQueue::handleInputChannelDisposed(JNIEnv* env, 28846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) { 28946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("Input channel object '%s' was disposed without first being unregistered with " 29046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "the input queue!", inputChannel->getName().string()); 29146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 29246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown NativeInputQueue* q = static_cast<NativeInputQueue*>(data); 29346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown q->unregisterInputChannel(env, inputChannelObj); 29446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 29546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 2964fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brownint NativeInputQueue::handleReceiveCallback(int receiveFd, int events, void* data) { 29746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown NativeInputQueue* q = static_cast<NativeInputQueue*>(data); 29846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown JNIEnv* env = AndroidRuntime::getJNIEnv(); 29946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 30046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown sp<Connection> connection; 30146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown InputEvent* inputEvent; 30246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jobject inputHandlerObjLocal; 30346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jlong finishedToken; 30446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown { // acquire lock 30546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown AutoMutex _l(q->mLock); 30646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 30746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown ssize_t connectionIndex = q->mConnectionsByReceiveFd.indexOfKey(receiveFd); 30846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (connectionIndex < 0) { 30946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGE("Received spurious receive callback for unknown input channel. " 31046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "fd=%d, events=0x%x", receiveFd, events); 3114fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown return 0; // remove the callback 31246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 31346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 31446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection = q->mConnectionsByReceiveFd.valueAt(connectionIndex); 3154fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) { 31646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGE("channel '%s' ~ Publisher closed input channel or an error occurred. " 31746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "events=0x%x", connection->getInputChannelName(), events); 3184fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown return 0; // remove the callback 31946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 32046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 3214fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown if (! (events & ALOOPER_EVENT_INPUT)) { 32246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " 32346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "events=0x%x", connection->getInputChannelName(), events); 3244fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown return 1; 32546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 32646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 32746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown status_t status = connection->inputConsumer.receiveDispatchSignal(); 32846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (status) { 32946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGE("channel '%s' ~ Failed to receive dispatch signal. status=%d", 33046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->getInputChannelName(), status); 3314fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown return 0; // remove the callback 33246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 33346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 33446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (connection->messageInProgress) { 33546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("channel '%s' ~ Publisher sent spurious dispatch signal.", 33646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->getInputChannelName()); 3374fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown return 1; 33846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 33946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 34046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown status = connection->inputConsumer.consume(& connection->inputEventFactory, & inputEvent); 34146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (status) { 34246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("channel '%s' ~ Failed to consume input event. status=%d", 34346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->getInputChannelName(), status); 34446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->inputConsumer.sendFinishedSignal(); 3454fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown return 1; 34646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 34746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 34846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->messageInProgress = true; 34946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->messageSeqNum += 1; 35046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 3512cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown finishedToken = generateFinishedToken(receiveFd, connection->id, connection->messageSeqNum); 35246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 35346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown inputHandlerObjLocal = env->NewLocalRef(connection->inputHandlerObjGlobal); 35446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } // release lock 35546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 35646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // Invoke the handler outside of the lock. 35746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // 35846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // Note: inputEvent is stored in a field of the connection object which could potentially 35946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // become disposed due to the input channel being unregistered concurrently. 36046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // For this reason, we explicitly keep the connection object alive by holding 36146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // a strong pointer to it within this scope. We also grabbed a local reference to 36246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown // the input handler object itself for the same reason. 36346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 36446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown int32_t inputEventType = inputEvent->getType(); 36546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 36646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jobject inputEventObj; 36746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jmethodID dispatchMethodId; 36846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown switch (inputEventType) { 369c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown case AINPUT_EVENT_TYPE_KEY: 37046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#if DEBUG_DISPATCH_CYCLE 37146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGD("channel '%s' ~ Received key event.", connection->getInputChannelName()); 37246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#endif 37346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown inputEventObj = android_view_KeyEvent_fromNative(env, 37446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown static_cast<KeyEvent*>(inputEvent)); 37546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown dispatchMethodId = gInputQueueClassInfo.dispatchKeyEvent; 37646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown break; 37746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 378c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown case AINPUT_EVENT_TYPE_MOTION: 37946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#if DEBUG_DISPATCH_CYCLE 38046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGD("channel '%s' ~ Received motion event.", connection->getInputChannelName()); 38146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#endif 38246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown inputEventObj = android_view_MotionEvent_fromNative(env, 38346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown static_cast<MotionEvent*>(inputEvent)); 38446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown dispatchMethodId = gInputQueueClassInfo.dispatchMotionEvent; 38546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown break; 38646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 38746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown default: 38846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown assert(false); // InputConsumer should prevent this from ever happening 38946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown inputEventObj = NULL; 39046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 39146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 39246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (! inputEventObj) { 39346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGW("channel '%s' ~ Failed to obtain DVM event object.", 39446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown connection->getInputChannelName()); 39546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown env->DeleteLocalRef(inputHandlerObjLocal); 39646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown q->finished(env, finishedToken, false); 3974fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown return 1; 39846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 39946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 40046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#if DEBUG_DISPATCH_CYCLE 40146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGD("Invoking input handler."); 40246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#endif 40346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown env->CallStaticVoidMethod(gInputQueueClassInfo.clazz, 40446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown dispatchMethodId, inputHandlerObjLocal, inputEventObj, 405c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown jlong(finishedToken)); 40646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#if DEBUG_DISPATCH_CYCLE 40746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGD("Returned from input handler."); 40846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#endif 40946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 41046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (env->ExceptionCheck()) { 41146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGE("An exception occurred while invoking the input handler for an event."); 41246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOGE_EX(env); 41346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown env->ExceptionClear(); 41446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 41546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown q->finished(env, finishedToken, true /*ignoreSpuriousFinish*/); 41646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 41746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 41846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown env->DeleteLocalRef(inputEventObj); 41946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown env->DeleteLocalRef(inputHandlerObjLocal); 4204fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown return 1; 42146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 42246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 4232cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brownjlong NativeInputQueue::generateFinishedToken(int32_t receiveFd, uint16_t connectionId, 4242cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown uint16_t messageSeqNum) { 4252cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown return (jlong(receiveFd) << 32) | (jlong(connectionId) << 16) | jlong(messageSeqNum); 42646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 42746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 42846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid NativeInputQueue::parseFinishedToken(jlong finishedToken, 4292cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown int32_t* outReceiveFd, uint16_t* outConnectionId, uint16_t* outMessageIndex) { 43046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown *outReceiveFd = int32_t(finishedToken >> 32); 4312cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown *outConnectionId = uint16_t(finishedToken >> 16); 4322cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown *outMessageIndex = uint16_t(finishedToken); 43346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 43446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 43546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ---------------------------------------------------------------------------- 43646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 4372cbecea4c9627d95377fc3e3b8a319116cee7febJeff BrownNativeInputQueue::Connection::Connection(uint16_t id, 4384fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown const sp<InputChannel>& inputChannel, const sp<Looper>& looper) : 4392cbecea4c9627d95377fc3e3b8a319116cee7febJeff Brown id(id), status(STATUS_NORMAL), inputChannel(inputChannel), inputConsumer(inputChannel), 4404fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown looper(looper), inputHandlerObjGlobal(NULL), 44146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown messageSeqNum(0), messageInProgress(false) { 44246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 44346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 44446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff BrownNativeInputQueue::Connection::~Connection() { 44546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 44646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 44746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ---------------------------------------------------------------------------- 44846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 44946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic NativeInputQueue gNativeInputQueue; 45046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 45146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void android_view_InputQueue_nativeRegisterInputChannel(JNIEnv* env, jclass clazz, 45246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jobject inputChannelObj, jobject inputHandlerObj, jobject messageQueueObj) { 45346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown status_t status = gNativeInputQueue.registerInputChannel( 45446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown env, inputChannelObj, inputHandlerObj, messageQueueObj); 455ace999b096739d376d4845c0ba94599197ff8477Jeff Brown 45646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (status) { 45746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jniThrowRuntimeException(env, "Failed to register input channel. " 45846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "Check logs for details."); 45946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 46046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 46146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 46246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void android_view_InputQueue_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz, 46346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jobject inputChannelObj) { 46446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown status_t status = gNativeInputQueue.unregisterInputChannel(env, inputChannelObj); 465ace999b096739d376d4845c0ba94599197ff8477Jeff Brown 46646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (status) { 46746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jniThrowRuntimeException(env, "Failed to unregister input channel. " 46846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "Check logs for details."); 46946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 47046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 47146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 47246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void android_view_InputQueue_nativeFinished(JNIEnv* env, jclass clazz, 47346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jlong finishedToken) { 47446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown status_t status = gNativeInputQueue.finished( 47546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown env, finishedToken, false /*ignoreSpuriousFinish*/); 476ace999b096739d376d4845c0ba94599197ff8477Jeff Brown 477ace999b096739d376d4845c0ba94599197ff8477Jeff Brown // We ignore the case where an event could not be finished because the input channel 478ace999b096739d376d4845c0ba94599197ff8477Jeff Brown // was no longer registered (DEAD_OBJECT) since it is a common race that can occur 479ace999b096739d376d4845c0ba94599197ff8477Jeff Brown // during application shutdown. The input dispatcher recovers gracefully anyways. 480ace999b096739d376d4845c0ba94599197ff8477Jeff Brown if (status != OK && status != DEAD_OBJECT) { 48146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jniThrowRuntimeException(env, "Failed to finish input event. " 48246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "Check logs for details."); 48346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown } 48446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 48546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 48646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ---------------------------------------------------------------------------- 48746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 48846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic JNINativeMethod gInputQueueMethods[] = { 48946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown /* name, signature, funcPtr */ 49046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown { "nativeRegisterInputChannel", 49146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "(Landroid/view/InputChannel;Landroid/view/InputHandler;Landroid/os/MessageQueue;)V", 49246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown (void*)android_view_InputQueue_nativeRegisterInputChannel }, 49346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown { "nativeUnregisterInputChannel", 49446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "(Landroid/view/InputChannel;)V", 49546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown (void*)android_view_InputQueue_nativeUnregisterInputChannel }, 49646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown { "nativeFinished", "(J)V", 49746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown (void*)android_view_InputQueue_nativeFinished } 49846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}; 49946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 50046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define FIND_CLASS(var, className) \ 50146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown var = env->FindClass(className); \ 50246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOG_FATAL_IF(! var, "Unable to find class " className); \ 50346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown var = jclass(env->NewGlobalRef(var)); 50446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 50546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define GET_STATIC_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 50646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown var = env->GetStaticMethodID(clazz, methodName, methodDescriptor); \ 50746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOG_FATAL_IF(! var, "Unable to find static method " methodName); 50846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 50946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownint register_android_view_InputQueue(JNIEnv* env) { 51046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown int res = jniRegisterNativeMethods(env, "android/view/InputQueue", 51146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown gInputQueueMethods, NELEM(gInputQueueMethods)); 51246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOG_FATAL_IF(res < 0, "Unable to register native methods."); 51346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 51446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown FIND_CLASS(gInputQueueClassInfo.clazz, "android/view/InputQueue"); 51546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 51646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown GET_STATIC_METHOD_ID(gInputQueueClassInfo.dispatchKeyEvent, gInputQueueClassInfo.clazz, 51746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "dispatchKeyEvent", 518c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown "(Landroid/view/InputHandler;Landroid/view/KeyEvent;J)V"); 51946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 52046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown GET_STATIC_METHOD_ID(gInputQueueClassInfo.dispatchMotionEvent, gInputQueueClassInfo.clazz, 52146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "dispatchMotionEvent", 522c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown "(Landroid/view/InputHandler;Landroid/view/MotionEvent;J)V"); 52346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return 0; 52446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 52546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 52646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} // namespace android 527