1c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown/*
2c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Copyright (C) 2013 The Android Open Source Project
3c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown *
4c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * you may not use this file except in compliance with the License.
6c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * You may obtain a copy of the License at
7c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown *
8c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown *
10c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * Unless required by applicable law or agreed to in writing, software
11c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * See the License for the specific language governing permissions and
14c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown * limitations under the License.
15c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown */
16c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
17c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#define LOG_TAG "InputEventSender"
18c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
19c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown//#define LOG_NDEBUG 0
20c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
21c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown// Log debug messages about the dispatch cycle.
22c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#define DEBUG_DISPATCH_CYCLE 0
23c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
24c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
25c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include "JNIHelp.h"
26c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
27c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include <android_runtime/AndroidRuntime.h>
28c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include <utils/Log.h>
29c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include <utils/Looper.h>
30c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include <utils/threads.h>
31c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include <utils/KeyedVector.h>
329d3b1a424c5c61e24e9659d15fb353026a00d925Jeff Brown#include <input/InputTransport.h>
33c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include "android_os_MessageQueue.h"
34c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include "android_view_InputChannel.h"
35c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include "android_view_KeyEvent.h"
36c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include "android_view_MotionEvent.h"
37c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
38a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown#include <ScopedLocalRef.h>
39a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown
40c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownnamespace android {
41c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
42c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatic struct {
43c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    jclass clazz;
44c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
45c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    jmethodID dispatchInputEventFinished;
46c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown} gInputEventSenderClassInfo;
47c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
48c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
49c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownclass NativeInputEventSender : public LooperCallback {
50c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownpublic:
51c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    NativeInputEventSender(JNIEnv* env,
52a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            jobject senderWeak, const sp<InputChannel>& inputChannel,
53c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            const sp<MessageQueue>& messageQueue);
54c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
55c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t initialize();
56c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void dispose();
57c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t sendKeyEvent(uint32_t seq, const KeyEvent* event);
58c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t sendMotionEvent(uint32_t seq, const MotionEvent* event);
59c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
60c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownprotected:
61c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    virtual ~NativeInputEventSender();
62c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
63c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownprivate:
64a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    jobject mSenderWeakGlobal;
65c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    InputPublisher mInputPublisher;
66c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<MessageQueue> mMessageQueue;
67c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    KeyedVector<uint32_t, uint32_t> mPublishedSeqMap;
68c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    uint32_t mNextPublishedSeq;
69c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
70c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    const char* getInputChannelName() {
71c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return mInputPublisher.getChannel()->getName().string();
72c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
73c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
74c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    virtual int handleEvent(int receiveFd, int events, void* data);
75c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t receiveFinishedSignals(JNIEnv* env);
76c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown};
77c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
78c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
79c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff BrownNativeInputEventSender::NativeInputEventSender(JNIEnv* env,
80a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown        jobject senderWeak, const sp<InputChannel>& inputChannel,
81c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        const sp<MessageQueue>& messageQueue) :
82a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown        mSenderWeakGlobal(env->NewGlobalRef(senderWeak)),
83c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        mInputPublisher(inputChannel), mMessageQueue(messageQueue),
8410f9b0997e0bde39fa153060db022a3982b78399Michael Wright        mNextPublishedSeq(1) {
85c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#if DEBUG_DISPATCH_CYCLE
86c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    ALOGD("channel '%s' ~ Initializing input event sender.", getInputChannelName());
87c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#endif
88c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
89c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
90c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff BrownNativeInputEventSender::~NativeInputEventSender() {
91c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
92a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    env->DeleteGlobalRef(mSenderWeakGlobal);
93c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
94c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
95c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatus_t NativeInputEventSender::initialize() {
96c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    int receiveFd = mInputPublisher.getChannel()->getFd();
97c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    mMessageQueue->getLooper()->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, this, NULL);
98c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return OK;
99c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
100c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
101c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownvoid NativeInputEventSender::dispose() {
102c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#if DEBUG_DISPATCH_CYCLE
103c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    ALOGD("channel '%s' ~ Disposing input event sender.", getInputChannelName());
104c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#endif
105c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
106c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    mMessageQueue->getLooper()->removeFd(mInputPublisher.getChannel()->getFd());
107c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
108c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
109c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatus_t NativeInputEventSender::sendKeyEvent(uint32_t seq, const KeyEvent* event) {
110c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#if DEBUG_DISPATCH_CYCLE
111c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    ALOGD("channel '%s' ~ Sending key event, seq=%u.", getInputChannelName(), seq);
112c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#endif
113c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
114c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    uint32_t publishedSeq = mNextPublishedSeq++;
115c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t status = mInputPublisher.publishKeyEvent(publishedSeq,
116c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            event->getDeviceId(), event->getSource(), event->getAction(), event->getFlags(),
117c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            event->getKeyCode(), event->getScanCode(), event->getMetaState(),
118c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            event->getRepeatCount(), event->getDownTime(), event->getEventTime());
119c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (status) {
120c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        ALOGW("Failed to send key event on channel '%s'.  status=%d",
121c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                getInputChannelName(), status);
122c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return status;
123c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
124c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    mPublishedSeqMap.add(publishedSeq, seq);
125c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return OK;
126c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
127c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
128c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatus_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent* event) {
129c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#if DEBUG_DISPATCH_CYCLE
130c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    ALOGD("channel '%s' ~ Sending motion event, seq=%u.", getInputChannelName(), seq);
131c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#endif
132c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
133c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    uint32_t publishedSeq;
134c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    for (size_t i = 0; i <= event->getHistorySize(); i++) {
135c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        publishedSeq = mNextPublishedSeq++;
136c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        status_t status = mInputPublisher.publishMotionEvent(publishedSeq,
137c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getDeviceId(), event->getSource(), event->getAction(), event->getFlags(),
138c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getEdgeFlags(), event->getMetaState(), event->getButtonState(),
139c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getXOffset(), event->getYOffset(),
140c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getXPrecision(), event->getYPrecision(),
141c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getDownTime(), event->getHistoricalEventTime(i),
142c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getPointerCount(), event->getPointerProperties(),
143c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getHistoricalRawPointerCoords(0, i));
144c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (status) {
145c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ALOGW("Failed to send motion event sample on channel '%s'.  status=%d",
146c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    getInputChannelName(), status);
147c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            return status;
148c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
149c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
150c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    mPublishedSeqMap.add(publishedSeq, seq);
151c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return OK;
152c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
153c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
154c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownint NativeInputEventSender::handleEvent(int receiveFd, int events, void* data) {
155c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
15644e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown#if DEBUG_DISPATCH_CYCLE
15744e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // This error typically occurs when the consumer has closed the input channel
15844e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // as part of finishing an IME session, in which case the publisher will
15944e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // soon be disposed as well.
16044e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        ALOGD("channel '%s' ~ Consumer closed input channel or an error occurred.  "
161c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                "events=0x%x", getInputChannelName(), events);
16244e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown#endif
163c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return 0; // remove the callback
164c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
165c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
166c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (!(events & ALOOPER_EVENT_INPUT)) {
167c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
168c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                "events=0x%x", getInputChannelName(), events);
169c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return 1;
170c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
171c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
172c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
173c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t status = receiveFinishedSignals(env);
174c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
175c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return status == OK || status == NO_MEMORY ? 1 : 0;
176c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
177c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
178c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatus_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) {
179c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#if DEBUG_DISPATCH_CYCLE
180c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    ALOGD("channel '%s' ~ Receiving finished signals.", getInputChannelName());
181c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#endif
182c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
183a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    ScopedLocalRef<jobject> senderObj(env, NULL);
184c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    bool skipCallbacks = false;
185c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    for (;;) {
186c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        uint32_t publishedSeq;
187c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        bool handled;
188c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        status_t status = mInputPublisher.receiveFinishedSignal(&publishedSeq, &handled);
189c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (status) {
190c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (status == WOULD_BLOCK) {
191c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                return OK;
192c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
193c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ALOGE("channel '%s' ~ Failed to consume finished signals.  status=%d",
194c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    getInputChannelName(), status);
195c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            return status;
196c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
197c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
198c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        ssize_t index = mPublishedSeqMap.indexOfKey(publishedSeq);
199c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (index >= 0) {
200c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            uint32_t seq = mPublishedSeqMap.valueAt(index);
201c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mPublishedSeqMap.removeItemsAt(index);
202c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
203c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#if DEBUG_DISPATCH_CYCLE
204c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ALOGD("channel '%s' ~ Received finished signal, seq=%u, handled=%s, "
205c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    "pendingEvents=%u.",
206c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    getInputChannelName(), seq, handled ? "true" : "false",
207c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    mPublishedSeqMap.size());
208c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#endif
209c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
210c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (!skipCallbacks) {
211a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                if (!senderObj.get()) {
212a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    senderObj.reset(jniGetReferent(env, mSenderWeakGlobal));
213a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    if (!senderObj.get()) {
214a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                        ALOGW("channel '%s' ~ Sender object was finalized "
215a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                                "without being disposed.", getInputChannelName());
216a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                        return DEAD_OBJECT;
217a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    }
218a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                }
219a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown
220a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                env->CallVoidMethod(senderObj.get(),
221c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                        gInputEventSenderClassInfo.dispatchInputEventFinished,
222c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                        jint(seq), jboolean(handled));
223c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                if (env->ExceptionCheck()) {
224c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    ALOGE("Exception dispatching finished signal.");
225c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    skipCallbacks = true;
226c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                }
227c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
228c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
229c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
230c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
231c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
232c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
233a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jlong nativeInit(JNIEnv* env, jclass clazz, jobject senderWeak,
234c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jobject inputChannelObj, jobject messageQueueObj) {
235c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
236c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            inputChannelObj);
237c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (inputChannel == NULL) {
238c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jniThrowRuntimeException(env, "InputChannel is not initialized.");
239c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return 0;
240c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
241c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
242c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
243c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (messageQueue == NULL) {
244c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
245c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return 0;
246c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
247c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
248c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<NativeInputEventSender> sender = new NativeInputEventSender(env,
249a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            senderWeak, inputChannel, messageQueue);
250c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t status = sender->initialize();
251c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (status) {
252c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        String8 message;
253c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        message.appendFormat("Failed to initialize input event sender.  status=%d", status);
254c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jniThrowRuntimeException(env, message.string());
255c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return 0;
256c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
257c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
258c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sender->incStrong(gInputEventSenderClassInfo.clazz); // retain a reference for the object
259a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    return reinterpret_cast<jlong>(sender.get());
260c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
261c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
262a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic void nativeDispose(JNIEnv* env, jclass clazz, jlong senderPtr) {
263c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<NativeInputEventSender> sender =
264c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            reinterpret_cast<NativeInputEventSender*>(senderPtr);
265c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sender->dispose();
266c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sender->decStrong(gInputEventSenderClassInfo.clazz); // drop reference held by the object
267c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
268c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
269a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jboolean nativeSendKeyEvent(JNIEnv* env, jclass clazz, jlong senderPtr,
270c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jint seq, jobject eventObj) {
271c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<NativeInputEventSender> sender =
272c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            reinterpret_cast<NativeInputEventSender*>(senderPtr);
273c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    KeyEvent event;
274c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    android_view_KeyEvent_toNative(env, eventObj, &event);
275c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t status = sender->sendKeyEvent(seq, &event);
276c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return !status;
277c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
278c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
279a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jboolean nativeSendMotionEvent(JNIEnv* env, jclass clazz, jlong senderPtr,
280c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jint seq, jobject eventObj) {
281c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<NativeInputEventSender> sender =
282c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            reinterpret_cast<NativeInputEventSender*>(senderPtr);
283c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
284c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t status = sender->sendMotionEvent(seq, event);
285c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return !status;
286c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
287c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
288c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
289c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatic JNINativeMethod gMethods[] = {
290c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    /* name, signature, funcPtr */
291c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    { "nativeInit",
292a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat            "(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)J",
293c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            (void*)nativeInit },
294a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeDispose", "(J)V",
295c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            (void*)nativeDispose },
296a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeSendKeyEvent", "(JILandroid/view/KeyEvent;)Z",
297c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            (void*)nativeSendKeyEvent },
298a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeSendMotionEvent", "(JILandroid/view/MotionEvent;)Z",
299c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            (void*)nativeSendMotionEvent },
300c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown};
301c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
302c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#define FIND_CLASS(var, className) \
303c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        var = env->FindClass(className); \
304c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className); \
305c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        var = jclass(env->NewGlobalRef(var));
306c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
307c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
308c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
309c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        LOG_FATAL_IF(! var, "Unable to find method " methodName);
310c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
311c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownint register_android_view_InputEventSender(JNIEnv* env) {
312c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    int res = jniRegisterNativeMethods(env, "android/view/InputEventSender",
313c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            gMethods, NELEM(gMethods));
314c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
315c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
316c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    FIND_CLASS(gInputEventSenderClassInfo.clazz, "android/view/InputEventSender");
317c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
318c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    GET_METHOD_ID(gInputEventSenderClassInfo.dispatchInputEventFinished,
319c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            gInputEventSenderClassInfo.clazz,
320c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            "dispatchInputEventFinished", "(IZ)V");
321c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return 0;
322c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
323c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
324c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown} // namespace android
325