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#include "JNIHelp.h"
22c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
23c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include <android_runtime/AndroidRuntime.h>
24c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include <utils/Log.h>
25c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include <utils/Looper.h>
26c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include <utils/threads.h>
27c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include <utils/KeyedVector.h>
289d3b1a424c5c61e24e9659d15fb353026a00d925Jeff Brown#include <input/InputTransport.h>
29c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include "android_os_MessageQueue.h"
30c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include "android_view_InputChannel.h"
31c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include "android_view_KeyEvent.h"
32c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown#include "android_view_MotionEvent.h"
33c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
34a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown#include <ScopedLocalRef.h>
35a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown
36987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe#include "core_jni_helpers.h"
37987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe
38c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownnamespace android {
39c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
40ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe// Log debug messages about the dispatch cycle.
41ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampestatic const bool kDebugDispatchCycle = false;
42ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
43c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatic struct {
44c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    jclass clazz;
45c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
46c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    jmethodID dispatchInputEventFinished;
47c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown} gInputEventSenderClassInfo;
48c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
49c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
50c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownclass NativeInputEventSender : public LooperCallback {
51c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownpublic:
52c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    NativeInputEventSender(JNIEnv* env,
53a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            jobject senderWeak, const sp<InputChannel>& inputChannel,
54c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            const sp<MessageQueue>& messageQueue);
55c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
56c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t initialize();
57c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void dispose();
58c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t sendKeyEvent(uint32_t seq, const KeyEvent* event);
59c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t sendMotionEvent(uint32_t seq, const MotionEvent* event);
60c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
61c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownprotected:
62c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    virtual ~NativeInputEventSender();
63c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
64c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownprivate:
65a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    jobject mSenderWeakGlobal;
66c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    InputPublisher mInputPublisher;
67c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<MessageQueue> mMessageQueue;
68c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    KeyedVector<uint32_t, uint32_t> mPublishedSeqMap;
69c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    uint32_t mNextPublishedSeq;
70c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
71c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    const char* getInputChannelName() {
72c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return mInputPublisher.getChannel()->getName().string();
73c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
74c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
75c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    virtual int handleEvent(int receiveFd, int events, void* data);
76c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t receiveFinishedSignals(JNIEnv* env);
77c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown};
78c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
79c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
80c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff BrownNativeInputEventSender::NativeInputEventSender(JNIEnv* env,
81a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown        jobject senderWeak, const sp<InputChannel>& inputChannel,
82c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        const sp<MessageQueue>& messageQueue) :
83a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown        mSenderWeakGlobal(env->NewGlobalRef(senderWeak)),
84c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        mInputPublisher(inputChannel), mMessageQueue(messageQueue),
8510f9b0997e0bde39fa153060db022a3982b78399Michael Wright        mNextPublishedSeq(1) {
86ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    if (kDebugDispatchCycle) {
87ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe        ALOGD("channel '%s' ~ Initializing input event sender.", getInputChannelName());
88ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    }
89c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
90c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
91c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff BrownNativeInputEventSender::~NativeInputEventSender() {
92c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
93a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    env->DeleteGlobalRef(mSenderWeakGlobal);
94c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
95c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
96c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatus_t NativeInputEventSender::initialize() {
97c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    int receiveFd = mInputPublisher.getChannel()->getFd();
98c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    mMessageQueue->getLooper()->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, this, NULL);
99c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return OK;
100c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
101c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
102c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownvoid NativeInputEventSender::dispose() {
103ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    if (kDebugDispatchCycle) {
104ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe        ALOGD("channel '%s' ~ Disposing input event sender.", getInputChannelName());
105ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    }
106c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
107c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    mMessageQueue->getLooper()->removeFd(mInputPublisher.getChannel()->getFd());
108c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
109c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
110c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatus_t NativeInputEventSender::sendKeyEvent(uint32_t seq, const KeyEvent* event) {
111ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    if (kDebugDispatchCycle) {
112ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe        ALOGD("channel '%s' ~ Sending key event, seq=%u.", getInputChannelName(), seq);
113ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    }
114c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
115c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    uint32_t publishedSeq = mNextPublishedSeq++;
116c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t status = mInputPublisher.publishKeyEvent(publishedSeq,
117c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            event->getDeviceId(), event->getSource(), event->getAction(), event->getFlags(),
118c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            event->getKeyCode(), event->getScanCode(), event->getMetaState(),
119c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            event->getRepeatCount(), event->getDownTime(), event->getEventTime());
120c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (status) {
121c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        ALOGW("Failed to send key event on channel '%s'.  status=%d",
122c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                getInputChannelName(), status);
123c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return status;
124c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
125c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    mPublishedSeqMap.add(publishedSeq, seq);
126c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return OK;
127c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
128c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
129c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatus_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent* event) {
130ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    if (kDebugDispatchCycle) {
131ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe        ALOGD("channel '%s' ~ Sending motion event, seq=%u.", getInputChannelName(), seq);
132ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    }
133c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
134c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    uint32_t publishedSeq;
135c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    for (size_t i = 0; i <= event->getHistorySize(); i++) {
136c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        publishedSeq = mNextPublishedSeq++;
137c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        status_t status = mInputPublisher.publishMotionEvent(publishedSeq,
1385bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright                event->getDeviceId(), event->getSource(),
1395bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright                event->getAction(), event->getActionButton(), event->getFlags(),
140c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getEdgeFlags(), event->getMetaState(), event->getButtonState(),
141c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getXOffset(), event->getYOffset(),
142c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getXPrecision(), event->getYPrecision(),
143c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getDownTime(), event->getHistoricalEventTime(i),
144c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getPointerCount(), event->getPointerProperties(),
145c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                event->getHistoricalRawPointerCoords(0, i));
146c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (status) {
147c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ALOGW("Failed to send motion event sample on channel '%s'.  status=%d",
148c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    getInputChannelName(), status);
149c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            return status;
150c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
151c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
152c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    mPublishedSeqMap.add(publishedSeq, seq);
153c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return OK;
154c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
155c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
156c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownint NativeInputEventSender::handleEvent(int receiveFd, int events, void* data) {
157c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
15844e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // This error typically occurs when the consumer has closed the input channel
15944e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // as part of finishing an IME session, in which case the publisher will
16044e13ef1a1aee36b4ce667670345de8ce4e6bb7bJeff Brown        // soon be disposed as well.
161ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe        if (kDebugDispatchCycle) {
162ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            ALOGD("channel '%s' ~ Consumer closed input channel or an error occurred.  "
163ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                    "events=0x%x", getInputChannelName(), events);
164ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe        }
165ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
166c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return 0; // remove the callback
167c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
168c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
169c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (!(events & ALOOPER_EVENT_INPUT)) {
170c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
171c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                "events=0x%x", getInputChannelName(), events);
172c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return 1;
173c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
174c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
175c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
176c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t status = receiveFinishedSignals(env);
177c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
178c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return status == OK || status == NO_MEMORY ? 1 : 0;
179c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
180c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
181c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownstatus_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) {
182ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    if (kDebugDispatchCycle) {
183ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe        ALOGD("channel '%s' ~ Receiving finished signals.", getInputChannelName());
184ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    }
185c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
186a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown    ScopedLocalRef<jobject> senderObj(env, NULL);
187c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    bool skipCallbacks = false;
188c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    for (;;) {
189c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        uint32_t publishedSeq;
190c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        bool handled;
191c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        status_t status = mInputPublisher.receiveFinishedSignal(&publishedSeq, &handled);
192c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (status) {
193c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (status == WOULD_BLOCK) {
194c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                return OK;
195c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
196c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ALOGE("channel '%s' ~ Failed to consume finished signals.  status=%d",
197c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    getInputChannelName(), status);
198c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            return status;
199c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
200c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
201c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        ssize_t index = mPublishedSeqMap.indexOfKey(publishedSeq);
202c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (index >= 0) {
203c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            uint32_t seq = mPublishedSeqMap.valueAt(index);
204c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mPublishedSeqMap.removeItemsAt(index);
205c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
206ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            if (kDebugDispatchCycle) {
207ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                ALOGD("channel '%s' ~ Received finished signal, seq=%u, handled=%s, "
20846c82b4cd241a447834ed2f5a6be16777b7a990bBernhard Rosenkränzer                        "pendingEvents=%zu.",
209ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                        getInputChannelName(), seq, handled ? "true" : "false",
210ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                        mPublishedSeqMap.size());
211ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            }
212c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
213c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (!skipCallbacks) {
214a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                if (!senderObj.get()) {
215a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    senderObj.reset(jniGetReferent(env, mSenderWeakGlobal));
216a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    if (!senderObj.get()) {
217a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                        ALOGW("channel '%s' ~ Sender object was finalized "
218a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                                "without being disposed.", getInputChannelName());
219a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                        return DEAD_OBJECT;
220a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                    }
221a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                }
222a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown
223a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown                env->CallVoidMethod(senderObj.get(),
224c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                        gInputEventSenderClassInfo.dispatchInputEventFinished,
225c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                        jint(seq), jboolean(handled));
226c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                if (env->ExceptionCheck()) {
227c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    ALOGE("Exception dispatching finished signal.");
228c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    skipCallbacks = true;
229c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                }
230c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
231c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
232c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
233c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
234c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
235c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
236a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jlong nativeInit(JNIEnv* env, jclass clazz, jobject senderWeak,
237c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jobject inputChannelObj, jobject messageQueueObj) {
238c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
239c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            inputChannelObj);
240c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (inputChannel == NULL) {
241c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jniThrowRuntimeException(env, "InputChannel is not initialized.");
242c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return 0;
243c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
244c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
245c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
246c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (messageQueue == NULL) {
247c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
248c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return 0;
249c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
250c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
251c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<NativeInputEventSender> sender = new NativeInputEventSender(env,
252a4ca8ea0ad14c509d1ced46482e83c1b8a518982Jeff Brown            senderWeak, inputChannel, messageQueue);
253c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t status = sender->initialize();
254c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    if (status) {
255c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        String8 message;
256c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        message.appendFormat("Failed to initialize input event sender.  status=%d", status);
257c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jniThrowRuntimeException(env, message.string());
258c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        return 0;
259c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
260c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
261c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sender->incStrong(gInputEventSenderClassInfo.clazz); // retain a reference for the object
262a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    return reinterpret_cast<jlong>(sender.get());
263c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
264c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
265a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic void nativeDispose(JNIEnv* env, jclass clazz, jlong senderPtr) {
266c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<NativeInputEventSender> sender =
267c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            reinterpret_cast<NativeInputEventSender*>(senderPtr);
268c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sender->dispose();
269c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sender->decStrong(gInputEventSenderClassInfo.clazz); // drop reference held by the object
270c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
271c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
272a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jboolean nativeSendKeyEvent(JNIEnv* env, jclass clazz, jlong senderPtr,
273c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jint seq, jobject eventObj) {
274c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<NativeInputEventSender> sender =
275c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            reinterpret_cast<NativeInputEventSender*>(senderPtr);
276c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    KeyEvent event;
277c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    android_view_KeyEvent_toNative(env, eventObj, &event);
278c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t status = sender->sendKeyEvent(seq, &event);
279c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return !status;
280c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
281c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
282a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhatstatic jboolean nativeSendMotionEvent(JNIEnv* env, jclass clazz, jlong senderPtr,
283c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        jint seq, jobject eventObj) {
284c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    sp<NativeInputEventSender> sender =
285c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            reinterpret_cast<NativeInputEventSender*>(senderPtr);
286c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
287c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    status_t status = sender->sendMotionEvent(seq, event);
288c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    return !status;
289c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
290c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
291c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
29276f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = {
293c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    /* name, signature, funcPtr */
294c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    { "nativeInit",
295a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat            "(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)J",
296c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            (void*)nativeInit },
297a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeDispose", "(J)V",
298c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            (void*)nativeDispose },
299a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeSendKeyEvent", "(JILandroid/view/KeyEvent;)Z",
300c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            (void*)nativeSendKeyEvent },
301a931d5218cfee89c7629ffa6cde324fa966449f9Ashok Bhat    { "nativeSendMotionEvent", "(JILandroid/view/MotionEvent;)Z",
302c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            (void*)nativeSendMotionEvent },
303c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown};
304c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
305c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownint register_android_view_InputEventSender(JNIEnv* env) {
306987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    int res = RegisterMethodsOrDie(env, "android/view/InputEventSender", gMethods, NELEM(gMethods));
307987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe
308987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    jclass clazz = FindClassOrDie(env, "android/view/InputEventSender");
309987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gInputEventSenderClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
310c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
311987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gInputEventSenderClassInfo.dispatchInputEventFinished = GetMethodIDOrDie(
312987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe            env, gInputEventSenderClassInfo.clazz, "dispatchInputEventFinished", "(IZ)V");
313c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
314987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    return res;
315c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown}
316c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
317c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown} // namespace android
318