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