blob: eb419180e747eb853ec09fda7c3039e77a278fab [file] [log] [blame]
Siarhei Vishniakou2b920272024-02-27 19:49:51 -08001/**
2 * Copyright 2024 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
Paul Ramireze2bb1872024-08-12 20:21:13 +000017#define LOG_TAG "InputConsumerNoResampling"
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080018#define ATRACE_TAG ATRACE_TAG_INPUT
19
Paul Ramirezbe9c5442024-07-10 00:12:41 +000020#include <chrono>
21
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080022#include <inttypes.h>
23
24#include <android-base/logging.h>
25#include <android-base/properties.h>
26#include <android-base/stringprintf.h>
27#include <cutils/properties.h>
28#include <ftl/enum.h>
29#include <utils/Trace.h>
30
31#include <com_android_input_flags.h>
32#include <input/InputConsumerNoResampling.h>
33#include <input/PrintTools.h>
34#include <input/TraceTools.h>
35
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080036namespace android {
37
38namespace {
39
40/**
41 * Log debug messages relating to the consumer end of the transport channel.
42 * Enable this via "adb shell setprop log.tag.InputTransportConsumer DEBUG" (requires restart)
43 */
44const bool DEBUG_TRANSPORT_CONSUMER =
45 __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Consumer", ANDROID_LOG_INFO);
46
Paul Ramireze2bb1872024-08-12 20:21:13 +000047/**
48 * RealLooper is a wrapper of Looper. All the member functions exclusively call the internal looper.
49 * This class' behavior is the same as Looper.
50 */
51class RealLooper final : public LooperInterface {
52public:
53 RealLooper(sp<Looper> looper) : mLooper{looper} {}
54
55 int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback,
56 void* data) override {
57 return mLooper->addFd(fd, ident, events, callback, data);
58 }
59
60 int removeFd(int fd) override { return mLooper->removeFd(fd); }
61
62 sp<Looper> getLooper() const override { return mLooper; }
63
64private:
65 sp<Looper> mLooper;
66};
67
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070068std::unique_ptr<KeyEvent> createKeyEvent(const InputMessage& msg) {
69 std::unique_ptr<KeyEvent> event = std::make_unique<KeyEvent>();
70 event->initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
Linnan Li13bf76a2024-05-05 19:18:02 +080071 ui::LogicalDisplayId{msg.body.key.displayId}, msg.body.key.hmac,
72 msg.body.key.action, msg.body.key.flags, msg.body.key.keyCode,
73 msg.body.key.scanCode, msg.body.key.metaState, msg.body.key.repeatCount,
74 msg.body.key.downTime, msg.body.key.eventTime);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070075 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080076}
77
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070078std::unique_ptr<FocusEvent> createFocusEvent(const InputMessage& msg) {
79 std::unique_ptr<FocusEvent> event = std::make_unique<FocusEvent>();
80 event->initialize(msg.body.focus.eventId, msg.body.focus.hasFocus);
81 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080082}
83
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070084std::unique_ptr<CaptureEvent> createCaptureEvent(const InputMessage& msg) {
85 std::unique_ptr<CaptureEvent> event = std::make_unique<CaptureEvent>();
86 event->initialize(msg.body.capture.eventId, msg.body.capture.pointerCaptureEnabled);
87 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080088}
89
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070090std::unique_ptr<DragEvent> createDragEvent(const InputMessage& msg) {
91 std::unique_ptr<DragEvent> event = std::make_unique<DragEvent>();
92 event->initialize(msg.body.drag.eventId, msg.body.drag.x, msg.body.drag.y,
93 msg.body.drag.isExiting);
94 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080095}
96
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070097std::unique_ptr<MotionEvent> createMotionEvent(const InputMessage& msg) {
98 std::unique_ptr<MotionEvent> event = std::make_unique<MotionEvent>();
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080099 const uint32_t pointerCount = msg.body.motion.pointerCount;
100 std::vector<PointerProperties> pointerProperties;
101 pointerProperties.reserve(pointerCount);
102 std::vector<PointerCoords> pointerCoords;
103 pointerCoords.reserve(pointerCount);
104 for (uint32_t i = 0; i < pointerCount; i++) {
105 pointerProperties.push_back(msg.body.motion.pointers[i].properties);
106 pointerCoords.push_back(msg.body.motion.pointers[i].coords);
107 }
108
109 ui::Transform transform;
110 transform.set({msg.body.motion.dsdx, msg.body.motion.dtdx, msg.body.motion.tx,
111 msg.body.motion.dtdy, msg.body.motion.dsdy, msg.body.motion.ty, 0, 0, 1});
112 ui::Transform displayTransform;
113 displayTransform.set({msg.body.motion.dsdxRaw, msg.body.motion.dtdxRaw, msg.body.motion.txRaw,
114 msg.body.motion.dtdyRaw, msg.body.motion.dsdyRaw, msg.body.motion.tyRaw,
115 0, 0, 1});
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700116 event->initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800117 ui::LogicalDisplayId{msg.body.motion.displayId}, msg.body.motion.hmac,
118 msg.body.motion.action, msg.body.motion.actionButton, msg.body.motion.flags,
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700119 msg.body.motion.edgeFlags, msg.body.motion.metaState,
120 msg.body.motion.buttonState, msg.body.motion.classification, transform,
121 msg.body.motion.xPrecision, msg.body.motion.yPrecision,
122 msg.body.motion.xCursorPosition, msg.body.motion.yCursorPosition,
123 displayTransform, msg.body.motion.downTime, msg.body.motion.eventTime,
124 pointerCount, pointerProperties.data(), pointerCoords.data());
125 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800126}
127
128void addSample(MotionEvent& event, const InputMessage& msg) {
129 uint32_t pointerCount = msg.body.motion.pointerCount;
130 std::vector<PointerCoords> pointerCoords;
131 pointerCoords.reserve(pointerCount);
132 for (uint32_t i = 0; i < pointerCount; i++) {
133 pointerCoords.push_back(msg.body.motion.pointers[i].coords);
134 }
135
136 // TODO(b/329770983): figure out if it's safe to combine events with mismatching metaState
137 event.setMetaState(event.getMetaState() | msg.body.motion.metaState);
jioana71c6f732024-07-16 15:42:56 +0000138 event.addSample(msg.body.motion.eventTime, pointerCoords.data(), msg.body.motion.eventId);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800139}
140
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700141std::unique_ptr<TouchModeEvent> createTouchModeEvent(const InputMessage& msg) {
142 std::unique_ptr<TouchModeEvent> event = std::make_unique<TouchModeEvent>();
143 event->initialize(msg.body.touchMode.eventId, msg.body.touchMode.isInTouchMode);
144 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800145}
146
147std::string outboundMessageToString(const InputMessage& outboundMsg) {
148 switch (outboundMsg.header.type) {
149 case InputMessage::Type::FINISHED: {
150 return android::base::StringPrintf(" Finish: seq=%" PRIu32 " handled=%s",
151 outboundMsg.header.seq,
152 toString(outboundMsg.body.finished.handled));
153 }
154 case InputMessage::Type::TIMELINE: {
155 return android::base::
156 StringPrintf(" Timeline: inputEventId=%" PRId32 " gpuCompletedTime=%" PRId64
157 ", presentTime=%" PRId64,
158 outboundMsg.body.timeline.eventId,
159 outboundMsg.body.timeline
160 .graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME],
161 outboundMsg.body.timeline
162 .graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
163 }
164 default: {
165 LOG(FATAL) << "Outbound message must be FINISHED or TIMELINE, got "
166 << ftl::enum_string(outboundMsg.header.type);
167 return "Unreachable";
168 }
169 }
170}
171
172InputMessage createFinishedMessage(uint32_t seq, bool handled, nsecs_t consumeTime) {
173 InputMessage msg;
174 msg.header.type = InputMessage::Type::FINISHED;
175 msg.header.seq = seq;
176 msg.body.finished.handled = handled;
177 msg.body.finished.consumeTime = consumeTime;
178 return msg;
179}
180
181InputMessage createTimelineMessage(int32_t inputEventId, nsecs_t gpuCompletedTime,
182 nsecs_t presentTime) {
183 InputMessage msg;
184 msg.header.type = InputMessage::Type::TIMELINE;
185 msg.header.seq = 0;
186 msg.body.timeline.eventId = inputEventId;
187 msg.body.timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = gpuCompletedTime;
188 msg.body.timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = presentTime;
189 return msg;
190}
191
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000192bool isPointerEvent(const MotionEvent& motionEvent) {
193 return (motionEvent.getSource() & AINPUT_SOURCE_CLASS_POINTER) == AINPUT_SOURCE_CLASS_POINTER;
194}
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800195} // namespace
196
197using android::base::Result;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800198
199// --- InputConsumerNoResampling ---
200
201InputConsumerNoResampling::InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel,
Paul Ramireze2bb1872024-08-12 20:21:13 +0000202 std::shared_ptr<LooperInterface> looper,
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000203 InputConsumerCallbacks& callbacks,
204 std::unique_ptr<Resampler> resampler)
Paul Ramireze2bb1872024-08-12 20:21:13 +0000205 : mChannel{channel},
206 mLooper{looper},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000207 mCallbacks(callbacks),
Paul Ramireze2bb1872024-08-12 20:21:13 +0000208 mResampler{std::move(resampler)},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000209 mFdEvents(0) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800210 LOG_ALWAYS_FATAL_IF(mLooper == nullptr);
211 mCallback = sp<LooperEventCallback>::make(
212 std::bind(&InputConsumerNoResampling::handleReceiveCallback, this,
213 std::placeholders::_1));
214 // In the beginning, there are no pending outbounds events; we only care about receiving
215 // incoming data.
216 setFdEvents(ALOOPER_EVENT_INPUT);
217}
218
Paul Ramireze2bb1872024-08-12 20:21:13 +0000219InputConsumerNoResampling::InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel,
220 sp<Looper> looper,
221 InputConsumerCallbacks& callbacks,
222 std::unique_ptr<Resampler> resampler)
223 : InputConsumerNoResampling(channel, std::make_shared<RealLooper>(looper), callbacks,
224 std::move(resampler)) {}
225
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800226InputConsumerNoResampling::~InputConsumerNoResampling() {
227 ensureCalledOnLooperThread(__func__);
228 consumeBatchedInputEvents(std::nullopt);
229 while (!mOutboundQueue.empty()) {
230 processOutboundEvents();
231 // This is our last chance to ack the events. If we don't ack them here, we will get an ANR,
232 // so keep trying to send the events as long as they are present in the queue.
233 }
234 setFdEvents(0);
235}
236
237int InputConsumerNoResampling::handleReceiveCallback(int events) {
238 // Allowed return values of this function as documented in LooperCallback::handleEvent
239 constexpr int REMOVE_CALLBACK = 0;
240 constexpr int KEEP_CALLBACK = 1;
241
242 if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
243 // This error typically occurs when the publisher has closed the input channel
244 // as part of removing a window or finishing an IME session, in which case
245 // the consumer will soon be disposed as well.
246 if (DEBUG_TRANSPORT_CONSUMER) {
247 LOG(INFO) << "The channel was hung up or an error occurred: " << mChannel->getName();
248 }
249 return REMOVE_CALLBACK;
250 }
251
252 int handledEvents = 0;
253 if (events & ALOOPER_EVENT_INPUT) {
254 std::vector<InputMessage> messages = readAllMessages();
255 handleMessages(std::move(messages));
256 handledEvents |= ALOOPER_EVENT_INPUT;
257 }
258
259 if (events & ALOOPER_EVENT_OUTPUT) {
260 processOutboundEvents();
261 handledEvents |= ALOOPER_EVENT_OUTPUT;
262 }
263 if (handledEvents != events) {
264 LOG(FATAL) << "Mismatch: handledEvents=" << handledEvents << ", events=" << events;
265 }
266 return KEEP_CALLBACK;
267}
268
269void InputConsumerNoResampling::processOutboundEvents() {
270 while (!mOutboundQueue.empty()) {
271 const InputMessage& outboundMsg = mOutboundQueue.front();
272
273 const status_t result = mChannel->sendMessage(&outboundMsg);
274 if (result == OK) {
275 if (outboundMsg.header.type == InputMessage::Type::FINISHED) {
276 ATRACE_ASYNC_END("InputConsumer processing", /*cookie=*/outboundMsg.header.seq);
277 }
278 // Successful send. Erase the entry and keep trying to send more
279 mOutboundQueue.pop();
280 continue;
281 }
282
283 // Publisher is busy, try again later. Keep this entry (do not erase)
284 if (result == WOULD_BLOCK) {
285 setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
286 return; // try again later
287 }
288
289 // Some other error. Give up
290 LOG(FATAL) << "Failed to send outbound event on channel '" << mChannel->getName()
291 << "'. status=" << statusToString(result) << "(" << result << ")";
292 }
293
294 // The queue is now empty. Tell looper there's no more output to expect.
295 setFdEvents(ALOOPER_EVENT_INPUT);
296}
297
298void InputConsumerNoResampling::finishInputEvent(uint32_t seq, bool handled) {
299 ensureCalledOnLooperThread(__func__);
300 mOutboundQueue.push(createFinishedMessage(seq, handled, popConsumeTime(seq)));
301 // also produce finish events for all batches for this seq (if any)
302 const auto it = mBatchedSequenceNumbers.find(seq);
303 if (it != mBatchedSequenceNumbers.end()) {
304 for (uint32_t subSeq : it->second) {
305 mOutboundQueue.push(createFinishedMessage(subSeq, handled, popConsumeTime(subSeq)));
306 }
307 mBatchedSequenceNumbers.erase(it);
308 }
309 processOutboundEvents();
310}
311
312bool InputConsumerNoResampling::probablyHasInput() const {
313 // Ideally, this would only be allowed to run on the looper thread, and in production, it will.
314 // However, for testing, it's convenient to call this while the looper thread is blocked, so
315 // we do not call ensureCalledOnLooperThread here.
316 return (!mBatches.empty()) || mChannel->probablyHasInput();
317}
318
319void InputConsumerNoResampling::reportTimeline(int32_t inputEventId, nsecs_t gpuCompletedTime,
320 nsecs_t presentTime) {
321 ensureCalledOnLooperThread(__func__);
322 mOutboundQueue.push(createTimelineMessage(inputEventId, gpuCompletedTime, presentTime));
323 processOutboundEvents();
324}
325
326nsecs_t InputConsumerNoResampling::popConsumeTime(uint32_t seq) {
327 auto it = mConsumeTimes.find(seq);
328 // Consume time will be missing if either 'finishInputEvent' is called twice, or if it was
329 // called for the wrong (synthetic?) input event. Either way, it is a bug that should be fixed.
330 LOG_ALWAYS_FATAL_IF(it == mConsumeTimes.end(), "Could not find consume time for seq=%" PRIu32,
331 seq);
332 nsecs_t consumeTime = it->second;
333 mConsumeTimes.erase(it);
334 return consumeTime;
335}
336
337void InputConsumerNoResampling::setFdEvents(int events) {
338 if (mFdEvents != events) {
339 mFdEvents = events;
340 if (events != 0) {
341 mLooper->addFd(mChannel->getFd(), 0, events, mCallback, nullptr);
342 } else {
343 mLooper->removeFd(mChannel->getFd());
344 }
345 }
346}
347
348void InputConsumerNoResampling::handleMessages(std::vector<InputMessage>&& messages) {
349 // TODO(b/297226446) : add resampling
350 for (const InputMessage& msg : messages) {
351 if (msg.header.type == InputMessage::Type::MOTION) {
352 const int32_t action = msg.body.motion.action;
353 const DeviceId deviceId = msg.body.motion.deviceId;
354 const int32_t source = msg.body.motion.source;
355 const bool batchableEvent = (action == AMOTION_EVENT_ACTION_MOVE ||
356 action == AMOTION_EVENT_ACTION_HOVER_MOVE) &&
357 (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER) ||
358 isFromSource(source, AINPUT_SOURCE_CLASS_JOYSTICK));
359 if (batchableEvent) {
360 // add it to batch
361 mBatches[deviceId].emplace(msg);
362 } else {
363 // consume all pending batches for this event immediately
364 // TODO(b/329776327): figure out if this could be smarter by limiting the
365 // consumption only to the current device.
366 consumeBatchedInputEvents(std::nullopt);
367 handleMessage(msg);
368 }
369 } else {
370 // Non-motion events shouldn't force the consumption of pending batched events
371 handleMessage(msg);
372 }
373 }
374 // At the end of this, if we still have pending batches, notify the receiver about it.
375
376 // We need to carefully notify the InputConsumerCallbacks about the pending batch. The receiver
377 // could choose to consume all events when notified about the batch. That means that the
378 // "mBatches" variable could change when 'InputConsumerCallbacks::onBatchedInputEventPending' is
379 // invoked. We also can't notify the InputConsumerCallbacks in a while loop until mBatches is
380 // empty, because the receiver could choose to not consume the batch immediately.
381 std::set<int32_t> pendingBatchSources;
382 for (const auto& [_, pendingMessages] : mBatches) {
383 // Assume that all messages for a given device has the same source.
384 pendingBatchSources.insert(pendingMessages.front().body.motion.source);
385 }
386 for (const int32_t source : pendingBatchSources) {
387 const bool sourceStillRemaining =
388 std::any_of(mBatches.begin(), mBatches.end(), [=](const auto& pair) {
389 return pair.second.front().body.motion.source == source;
390 });
391 if (sourceStillRemaining) {
392 mCallbacks.onBatchedInputEventPending(source);
393 }
394 }
395}
396
397std::vector<InputMessage> InputConsumerNoResampling::readAllMessages() {
398 std::vector<InputMessage> messages;
399 while (true) {
Paul Ramirez0c25e862024-06-18 21:33:33 +0000400 android::base::Result<InputMessage> result = mChannel->receiveMessage();
401 if (result.ok()) {
402 const InputMessage& msg = *result;
403 const auto [_, inserted] =
404 mConsumeTimes.emplace(msg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
405 LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
406 msg.header.seq);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800407
Paul Ramirez0c25e862024-06-18 21:33:33 +0000408 // Trace the event processing timeline - event was just read from the socket
409 // TODO(b/329777420): distinguish between multiple instances of InputConsumer
410 // in the same process.
411 ATRACE_ASYNC_BEGIN("InputConsumer processing", /*cookie=*/msg.header.seq);
412 messages.push_back(msg);
413 } else { // !result.ok()
414 switch (result.error().code()) {
415 case WOULD_BLOCK: {
416 return messages;
417 }
418 case DEAD_OBJECT: {
419 LOG(FATAL) << "Got a dead object for " << mChannel->getName();
420 break;
421 }
422 case BAD_VALUE: {
423 LOG(FATAL) << "Got a bad value for " << mChannel->getName();
424 break;
425 }
426 default: {
427 LOG(FATAL) << "Unexpected error: " << result.error().message();
428 break;
429 }
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800430 }
431 }
432 }
433}
434
435void InputConsumerNoResampling::handleMessage(const InputMessage& msg) const {
436 switch (msg.header.type) {
437 case InputMessage::Type::KEY: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700438 std::unique_ptr<KeyEvent> keyEvent = createKeyEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800439 mCallbacks.onKeyEvent(std::move(keyEvent), msg.header.seq);
440 break;
441 }
442
443 case InputMessage::Type::MOTION: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700444 std::unique_ptr<MotionEvent> motionEvent = createMotionEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800445 mCallbacks.onMotionEvent(std::move(motionEvent), msg.header.seq);
446 break;
447 }
448
449 case InputMessage::Type::FINISHED:
450 case InputMessage::Type::TIMELINE: {
Siarhei Vishniakou11d223b2024-03-26 21:52:38 +0000451 LOG(FATAL) << "Consumed a " << ftl::enum_string(msg.header.type)
452 << " message, which should never be seen by InputConsumer on "
453 << mChannel->getName();
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800454 break;
455 }
456
457 case InputMessage::Type::FOCUS: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700458 std::unique_ptr<FocusEvent> focusEvent = createFocusEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800459 mCallbacks.onFocusEvent(std::move(focusEvent), msg.header.seq);
460 break;
461 }
462
463 case InputMessage::Type::CAPTURE: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700464 std::unique_ptr<CaptureEvent> captureEvent = createCaptureEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800465 mCallbacks.onCaptureEvent(std::move(captureEvent), msg.header.seq);
466 break;
467 }
468
469 case InputMessage::Type::DRAG: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700470 std::unique_ptr<DragEvent> dragEvent = createDragEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800471 mCallbacks.onDragEvent(std::move(dragEvent), msg.header.seq);
472 break;
473 }
474
475 case InputMessage::Type::TOUCH_MODE: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700476 std::unique_ptr<TouchModeEvent> touchModeEvent = createTouchModeEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800477 mCallbacks.onTouchModeEvent(std::move(touchModeEvent), msg.header.seq);
478 break;
479 }
480 }
481}
482
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000483std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>>
484InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t frameTime,
485 std::queue<InputMessage>& messages) {
486 std::unique_ptr<MotionEvent> motionEvent;
487 std::optional<uint32_t> firstSeqForBatch;
488 while (!messages.empty() && !(messages.front().body.motion.eventTime > frameTime)) {
489 if (motionEvent == nullptr) {
490 motionEvent = createMotionEvent(messages.front());
491 firstSeqForBatch = messages.front().header.seq;
492 const auto [_, inserted] = mBatchedSequenceNumbers.insert({*firstSeqForBatch, {}});
493 LOG_IF(FATAL, !inserted)
494 << "The sequence " << messages.front().header.seq << " was already present!";
495 } else {
496 addSample(*motionEvent, messages.front());
497 mBatchedSequenceNumbers[*firstSeqForBatch].push_back(messages.front().header.seq);
498 }
499 messages.pop();
500 }
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000501 // Check if resampling should be performed.
502 if (motionEvent != nullptr && isPointerEvent(*motionEvent) && mResampler != nullptr) {
503 InputMessage* futureSample = nullptr;
504 if (!messages.empty()) {
505 futureSample = &messages.front();
506 }
507 mResampler->resampleMotionEvent(static_cast<std::chrono::nanoseconds>(frameTime),
508 *motionEvent, futureSample);
509 }
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000510 return std::make_pair(std::move(motionEvent), firstSeqForBatch);
511}
512
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800513bool InputConsumerNoResampling::consumeBatchedInputEvents(
514 std::optional<nsecs_t> requestedFrameTime) {
515 ensureCalledOnLooperThread(__func__);
516 // When batching is not enabled, we want to consume all events. That's equivalent to having an
517 // infinite frameTime.
518 const nsecs_t frameTime = requestedFrameTime.value_or(std::numeric_limits<nsecs_t>::max());
519 bool producedEvents = false;
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000520 for (auto& [_, messages] : mBatches) {
521 auto [motion, firstSeqForBatch] = createBatchedMotionEvent(frameTime, messages);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700522 if (motion != nullptr) {
523 LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value());
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800524 mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch);
525 producedEvents = true;
526 } else {
527 // This is OK, it just means that the frameTime is too old (all events that we have
528 // pending are in the future of the frametime). Maybe print a
529 // warning? If there are multiple devices active though, this might be normal and can
530 // just be ignored, unless none of them resulted in any consumption (in that case, this
531 // function would already return "false" so we could just leave it up to the caller).
532 }
533 }
534 std::erase_if(mBatches, [](const auto& pair) { return pair.second.empty(); });
535 return producedEvents;
536}
537
538void InputConsumerNoResampling::ensureCalledOnLooperThread(const char* func) const {
539 sp<Looper> callingThreadLooper = Looper::getForThread();
Paul Ramireze2bb1872024-08-12 20:21:13 +0000540 if (callingThreadLooper != mLooper->getLooper()) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800541 LOG(FATAL) << "The function " << func << " can only be called on the looper thread";
542 }
543}
544
545std::string InputConsumerNoResampling::dump() const {
546 ensureCalledOnLooperThread(__func__);
547 std::string out;
548 if (mOutboundQueue.empty()) {
549 out += "mOutboundQueue: <empty>\n";
550 } else {
551 out += "mOutboundQueue:\n";
552 // Make a copy of mOutboundQueue for printing destructively. Unfortunately std::queue
553 // doesn't provide a good way to iterate over the entire container.
554 std::queue<InputMessage> tmpQueue = mOutboundQueue;
555 while (!tmpQueue.empty()) {
556 out += std::string(" ") + outboundMessageToString(tmpQueue.front()) + "\n";
557 tmpQueue.pop();
558 }
559 }
560
561 if (mBatches.empty()) {
562 out += "mBatches: <empty>\n";
563 } else {
564 out += "mBatches:\n";
565 for (const auto& [deviceId, messages] : mBatches) {
566 out += " Device id ";
567 out += std::to_string(deviceId);
568 out += ":\n";
569 // Make a copy of mOutboundQueue for printing destructively. Unfortunately std::queue
570 // doesn't provide a good way to iterate over the entire container.
571 std::queue<InputMessage> tmpQueue = messages;
572 while (!tmpQueue.empty()) {
573 LOG_ALWAYS_FATAL_IF(tmpQueue.front().header.type != InputMessage::Type::MOTION);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700574 std::unique_ptr<MotionEvent> motion = createMotionEvent(tmpQueue.front());
575 out += std::string(" ") + streamableToString(*motion) + "\n";
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800576 tmpQueue.pop();
577 }
578 }
579 }
580
581 return out;
582}
583
584} // namespace android