1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "InputEventSender"
18 
19 //#define LOG_NDEBUG 0
20 
21 #include <android_runtime/AndroidRuntime.h>
22 #include <input/InputTransport.h>
23 #include <inttypes.h>
24 #include <log/log.h>
25 #include <nativehelper/JNIHelp.h>
26 #include <nativehelper/ScopedLocalRef.h>
27 #include <utils/Looper.h>
28 
29 #include <optional>
30 #include <unordered_map>
31 
32 #include "android_os_MessageQueue.h"
33 #include "android_view_InputChannel.h"
34 #include "android_view_KeyEvent.h"
35 #include "android_view_MotionEvent.h"
36 #include "core_jni_helpers.h"
37 
38 using android::base::Result;
39 
40 namespace android {
41 
42 // Log debug messages about the dispatch cycle.
43 static constexpr bool kDebugDispatchCycle = false;
44 
45 static struct {
46     jclass clazz;
47 
48     jmethodID dispatchInputEventFinished;
49     jmethodID dispatchTimelineReported;
50 } gInputEventSenderClassInfo;
51 
52 
53 class NativeInputEventSender : public LooperCallback {
54 public:
55     NativeInputEventSender(JNIEnv* env, jobject senderWeak,
56                            const std::shared_ptr<InputChannel>& inputChannel,
57                            const sp<MessageQueue>& messageQueue);
58 
59     status_t initialize();
60     void dispose();
61     status_t sendKeyEvent(uint32_t seq, const KeyEvent* event);
62     status_t sendMotionEvent(uint32_t seq, const MotionEvent* event);
63 
64 protected:
65     virtual ~NativeInputEventSender();
66 
67 private:
68     jobject mSenderWeakGlobal;
69     InputPublisher mInputPublisher;
70     sp<MessageQueue> mMessageQueue;
71     std::unordered_map<uint32_t, std::optional<uint32_t>> mPublishedSeqMap;
72 
73     uint32_t mNextPublishedSeq;
74 
getInputChannelName()75     const std::string getInputChannelName() {
76         return mInputPublisher.getChannel()->getName();
77     }
78 
79     int handleEvent(int receiveFd, int events, void* data) override;
80     status_t processConsumerResponse(JNIEnv* env);
81     bool notifyConsumerResponse(JNIEnv* env, jobject sender,
82                                 const InputPublisher::ConsumerResponse& response,
83                                 bool skipCallbacks);
84 };
85 
NativeInputEventSender(JNIEnv * env,jobject senderWeak,const std::shared_ptr<InputChannel> & inputChannel,const sp<MessageQueue> & messageQueue)86 NativeInputEventSender::NativeInputEventSender(JNIEnv* env, jobject senderWeak,
87                                                const std::shared_ptr<InputChannel>& inputChannel,
88                                                const sp<MessageQueue>& messageQueue)
89       : mSenderWeakGlobal(env->NewGlobalRef(senderWeak)),
90         mInputPublisher(inputChannel),
91         mMessageQueue(messageQueue),
92         mNextPublishedSeq(1) {
93     if (kDebugDispatchCycle) {
94         ALOGD("channel '%s' ~ Initializing input event sender.", getInputChannelName().c_str());
95     }
96 }
97 
~NativeInputEventSender()98 NativeInputEventSender::~NativeInputEventSender() {
99     JNIEnv* env = AndroidRuntime::getJNIEnv();
100     env->DeleteGlobalRef(mSenderWeakGlobal);
101 }
102 
initialize()103 status_t NativeInputEventSender::initialize() {
104     int receiveFd = mInputPublisher.getChannel()->getFd();
105     mMessageQueue->getLooper()->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, this, NULL);
106     return OK;
107 }
108 
dispose()109 void NativeInputEventSender::dispose() {
110     if (kDebugDispatchCycle) {
111         ALOGD("channel '%s' ~ Disposing input event sender.", getInputChannelName().c_str());
112     }
113 
114     mMessageQueue->getLooper()->removeFd(mInputPublisher.getChannel()->getFd());
115 }
116 
sendKeyEvent(uint32_t seq,const KeyEvent * event)117 status_t NativeInputEventSender::sendKeyEvent(uint32_t seq, const KeyEvent* event) {
118     if (kDebugDispatchCycle) {
119         ALOGD("channel '%s' ~ Sending key event, seq=%u.", getInputChannelName().c_str(), seq);
120     }
121 
122     uint32_t publishedSeq = mNextPublishedSeq++;
123     status_t status =
124             mInputPublisher.publishKeyEvent(publishedSeq, event->getId(), event->getDeviceId(),
125                                             event->getSource(), event->getDisplayId(),
126                                             event->getHmac(), event->getAction(), event->getFlags(),
127                                             event->getKeyCode(), event->getScanCode(),
128                                             event->getMetaState(), event->getRepeatCount(),
129                                             event->getDownTime(), event->getEventTime());
130     if (status) {
131         ALOGW("Failed to send key event on channel '%s'.  status=%d",
132                 getInputChannelName().c_str(), status);
133         return status;
134     }
135     mPublishedSeqMap.emplace(publishedSeq, seq);
136     return OK;
137 }
138 
sendMotionEvent(uint32_t seq,const MotionEvent * event)139 status_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent* event) {
140     if (kDebugDispatchCycle) {
141         ALOGD("channel '%s' ~ Sending motion event, seq=%u.", getInputChannelName().c_str(), seq);
142     }
143 
144     uint32_t publishedSeq;
145     for (size_t i = 0; i <= event->getHistorySize(); i++) {
146         publishedSeq = mNextPublishedSeq++;
147         status_t status =
148                 mInputPublisher.publishMotionEvent(publishedSeq, event->getId(),
149                                                    event->getDeviceId(), event->getSource(),
150                                                    event->getDisplayId(), event->getHmac(),
151                                                    event->getAction(), event->getActionButton(),
152                                                    event->getFlags(), event->getEdgeFlags(),
153                                                    event->getMetaState(), event->getButtonState(),
154                                                    event->getClassification(),
155                                                    event->getTransform(), event->getXPrecision(),
156                                                    event->getYPrecision(),
157                                                    event->getRawXCursorPosition(),
158                                                    event->getRawYCursorPosition(),
159                                                    event->getRawTransform(), event->getDownTime(),
160                                                    event->getHistoricalEventTime(i),
161                                                    event->getPointerCount(),
162                                                    event->getPointerProperties(),
163                                                    event->getHistoricalRawPointerCoords(0, i));
164         if (status) {
165             ALOGW("Failed to send motion event sample on channel '%s'.  status=%d",
166                     getInputChannelName().c_str(), status);
167             return status;
168         }
169         // mPublishedSeqMap tracks all sequences published from this sender. Only the last
170         // sequence number is used to signal this motion event is finished.
171         if (i == event->getHistorySize()) {
172             mPublishedSeqMap.emplace(publishedSeq, seq);
173         } else {
174             mPublishedSeqMap.emplace(publishedSeq, std::nullopt);
175         }
176     }
177     return OK;
178 }
179 
handleEvent(int receiveFd,int events,void * data)180 int NativeInputEventSender::handleEvent(int receiveFd, int events, void* data) {
181     if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
182         // This error typically occurs when the consumer has closed the input channel
183         // as part of finishing an IME session, in which case the publisher will
184         // soon be disposed as well.
185         if (kDebugDispatchCycle) {
186             ALOGD("channel '%s' ~ Consumer closed input channel or an error occurred.  events=0x%x",
187                   getInputChannelName().c_str(), events);
188         }
189 
190         return 0; // remove the callback
191     }
192 
193     if (!(events & ALOOPER_EVENT_INPUT)) {
194         ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  events=0x%x",
195               getInputChannelName().c_str(), events);
196         return 1;
197     }
198 
199     JNIEnv* env = AndroidRuntime::getJNIEnv();
200     status_t status = processConsumerResponse(env);
201     mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
202     return status == OK || status == NO_MEMORY ? 1 : 0;
203 }
204 
processConsumerResponse(JNIEnv * env)205 status_t NativeInputEventSender::processConsumerResponse(JNIEnv* env) {
206     if (kDebugDispatchCycle) {
207         ALOGD("channel '%s' ~ Receiving finished signals.", getInputChannelName().c_str());
208     }
209 
210     ScopedLocalRef<jobject> senderObj(env, GetReferent(env, mSenderWeakGlobal));
211     if (!senderObj.get()) {
212         ALOGW("channel '%s' ~ Sender object was finalized without being disposed.",
213               getInputChannelName().c_str());
214         return DEAD_OBJECT;
215     }
216     bool skipCallbacks = false; // stop calling Java functions after an exception occurs
217     for (;;) {
218         Result<InputPublisher::ConsumerResponse> result = mInputPublisher.receiveConsumerResponse();
219         if (!result.ok()) {
220             const status_t status = result.error().code();
221             if (status == WOULD_BLOCK) {
222                 return OK;
223             }
224             ALOGE("channel '%s' ~ Failed to process consumer response.  status=%d",
225                   getInputChannelName().c_str(), status);
226             return status;
227         }
228 
229         const bool notified = notifyConsumerResponse(env, senderObj.get(), *result, skipCallbacks);
230         if (!notified) {
231             skipCallbacks = true;
232         }
233     }
234 }
235 
236 /**
237  * Invoke the corresponding Java function for the different variants of response.
238  * If the response is a Finished object, invoke dispatchInputEventFinished.
239  * If the response is a Timeline object, invoke dispatchTimelineReported.
240  * Set 'skipCallbacks' to 'true' if a Java exception occurred.
241  * Java function will only be called if 'skipCallbacks' is originally 'false'.
242  *
243  * Return "false" if an exception occurred while calling the Java function
244  *        "true" otherwise
245  */
notifyConsumerResponse(JNIEnv * env,jobject sender,const InputPublisher::ConsumerResponse & response,bool skipCallbacks)246 bool NativeInputEventSender::notifyConsumerResponse(
247         JNIEnv* env, jobject sender, const InputPublisher::ConsumerResponse& response,
248         bool skipCallbacks) {
249     if (std::holds_alternative<InputPublisher::Timeline>(response)) {
250         const InputPublisher::Timeline& timeline = std::get<InputPublisher::Timeline>(response);
251 
252         if (kDebugDispatchCycle) {
253             ALOGD("channel '%s' ~ Received timeline, inputEventId=%" PRId32
254                   ", gpuCompletedTime=%" PRId64 ", presentTime=%" PRId64,
255                   getInputChannelName().c_str(), timeline.inputEventId,
256                   timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME],
257                   timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
258         }
259 
260         if (skipCallbacks) {
261             ALOGW("Java exception occurred. Skipping dispatchTimelineReported for "
262                   "inputEventId=%" PRId32,
263                   timeline.inputEventId);
264             return true;
265         }
266 
267         env->CallVoidMethod(sender, gInputEventSenderClassInfo.dispatchTimelineReported,
268                             timeline.inputEventId, timeline.graphicsTimeline);
269         if (env->ExceptionCheck()) {
270             ALOGE("Exception dispatching timeline, inputEventId=%" PRId32, timeline.inputEventId);
271             return false;
272         }
273 
274         return true;
275     }
276 
277     // Must be a Finished event
278     const InputPublisher::Finished& finished = std::get<InputPublisher::Finished>(response);
279 
280     auto it = mPublishedSeqMap.find(finished.seq);
281     if (it == mPublishedSeqMap.end()) {
282         ALOGW("Received 'finished' signal for unknown seq number = %" PRIu32, finished.seq);
283         // Since this is coming from the receiver (typically app), it's possible that an app
284         // does something wrong and sends bad data. Just ignore and process other events.
285         return true;
286     }
287 
288     const std::optional<uint32_t> seqOptional = it->second;
289     mPublishedSeqMap.erase(it);
290     // If this optional does not have a value, it means we are processing an event that had history
291     // and was split. There are more events coming, so we can't call 'dispatchInputEventFinished'
292     // yet. The final split event will have a valid sequence number.
293     if (!seqOptional.has_value()) {
294         return true;
295     }
296     const uint32_t seq = seqOptional.value();
297 
298     if (kDebugDispatchCycle) {
299         ALOGD("channel '%s' ~ Received finished signal, seq=%u, handled=%s, pendingEvents=%zu.",
300               getInputChannelName().c_str(), seq, finished.handled ? "true" : "false",
301               mPublishedSeqMap.size());
302     }
303     if (skipCallbacks) {
304         return true;
305     }
306 
307     env->CallVoidMethod(sender, gInputEventSenderClassInfo.dispatchInputEventFinished,
308                         static_cast<jint>(seq), static_cast<jboolean>(finished.handled));
309     if (env->ExceptionCheck()) {
310         ALOGE("Exception dispatching finished signal for seq=%" PRIu32, seq);
311         return false;
312     }
313     return true;
314 }
315 
nativeInit(JNIEnv * env,jclass clazz,jobject senderWeak,jobject inputChannelObj,jobject messageQueueObj)316 static jlong nativeInit(JNIEnv* env, jclass clazz, jobject senderWeak,
317         jobject inputChannelObj, jobject messageQueueObj) {
318     std::shared_ptr<InputChannel> inputChannel =
319             android_view_InputChannel_getInputChannel(env, inputChannelObj);
320     if (inputChannel == NULL) {
321         jniThrowRuntimeException(env, "InputChannel is not initialized.");
322         return 0;
323     }
324 
325     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
326     if (messageQueue == NULL) {
327         jniThrowRuntimeException(env, "MessageQueue is not initialized.");
328         return 0;
329     }
330 
331     sp<NativeInputEventSender> sender = new NativeInputEventSender(env,
332             senderWeak, inputChannel, messageQueue);
333     status_t status = sender->initialize();
334     if (status) {
335         String8 message;
336         message.appendFormat("Failed to initialize input event sender.  status=%d", status);
337         jniThrowRuntimeException(env, message.string());
338         return 0;
339     }
340 
341     sender->incStrong(gInputEventSenderClassInfo.clazz); // retain a reference for the object
342     return reinterpret_cast<jlong>(sender.get());
343 }
344 
nativeDispose(JNIEnv * env,jclass clazz,jlong senderPtr)345 static void nativeDispose(JNIEnv* env, jclass clazz, jlong senderPtr) {
346     sp<NativeInputEventSender> sender =
347             reinterpret_cast<NativeInputEventSender*>(senderPtr);
348     sender->dispose();
349     sender->decStrong(gInputEventSenderClassInfo.clazz); // drop reference held by the object
350 }
351 
nativeSendKeyEvent(JNIEnv * env,jclass clazz,jlong senderPtr,jint seq,jobject eventObj)352 static jboolean nativeSendKeyEvent(JNIEnv* env, jclass clazz, jlong senderPtr,
353         jint seq, jobject eventObj) {
354     sp<NativeInputEventSender> sender =
355             reinterpret_cast<NativeInputEventSender*>(senderPtr);
356     const KeyEvent event = android_view_KeyEvent_toNative(env, eventObj);
357     status_t status = sender->sendKeyEvent(seq, &event);
358     return !status;
359 }
360 
nativeSendMotionEvent(JNIEnv * env,jclass clazz,jlong senderPtr,jint seq,jobject eventObj)361 static jboolean nativeSendMotionEvent(JNIEnv* env, jclass clazz, jlong senderPtr,
362         jint seq, jobject eventObj) {
363     sp<NativeInputEventSender> sender =
364             reinterpret_cast<NativeInputEventSender*>(senderPtr);
365     MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
366     status_t status = sender->sendMotionEvent(seq, event);
367     return !status;
368 }
369 
370 
371 static const JNINativeMethod gMethods[] = {
372     /* name, signature, funcPtr */
373     { "nativeInit",
374             "(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)J",
375             (void*)nativeInit },
376     { "nativeDispose", "(J)V",
377             (void*)nativeDispose },
378     { "nativeSendKeyEvent", "(JILandroid/view/KeyEvent;)Z",
379             (void*)nativeSendKeyEvent },
380     { "nativeSendMotionEvent", "(JILandroid/view/MotionEvent;)Z",
381             (void*)nativeSendMotionEvent },
382 };
383 
register_android_view_InputEventSender(JNIEnv * env)384 int register_android_view_InputEventSender(JNIEnv* env) {
385     int res = RegisterMethodsOrDie(env, "android/view/InputEventSender", gMethods, NELEM(gMethods));
386 
387     jclass clazz = FindClassOrDie(env, "android/view/InputEventSender");
388     gInputEventSenderClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
389 
390     gInputEventSenderClassInfo.dispatchInputEventFinished = GetMethodIDOrDie(
391             env, gInputEventSenderClassInfo.clazz, "dispatchInputEventFinished", "(IZ)V");
392     gInputEventSenderClassInfo.dispatchTimelineReported =
393             GetMethodIDOrDie(env, gInputEventSenderClassInfo.clazz, "dispatchTimelineReported",
394                              "(IJJ)V");
395 
396     return res;
397 }
398 
399 } // namespace android
400