blob: f33afe75fc2df6384cd1b5c003dd9982547aa462 [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
Paul Ramirezcd7488c2024-09-13 23:01:12 +000040using std::chrono::nanoseconds;
41
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080042/**
43 * Log debug messages relating to the consumer end of the transport channel.
44 * Enable this via "adb shell setprop log.tag.InputTransportConsumer DEBUG" (requires restart)
45 */
46const bool DEBUG_TRANSPORT_CONSUMER =
47 __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Consumer", ANDROID_LOG_INFO);
48
Paul Ramireze2bb1872024-08-12 20:21:13 +000049/**
50 * RealLooper is a wrapper of Looper. All the member functions exclusively call the internal looper.
51 * This class' behavior is the same as Looper.
52 */
53class RealLooper final : public LooperInterface {
54public:
55 RealLooper(sp<Looper> looper) : mLooper{looper} {}
56
57 int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback,
58 void* data) override {
59 return mLooper->addFd(fd, ident, events, callback, data);
60 }
61
62 int removeFd(int fd) override { return mLooper->removeFd(fd); }
63
64 sp<Looper> getLooper() const override { return mLooper; }
65
66private:
67 sp<Looper> mLooper;
68};
69
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070070std::unique_ptr<KeyEvent> createKeyEvent(const InputMessage& msg) {
71 std::unique_ptr<KeyEvent> event = std::make_unique<KeyEvent>();
72 event->initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
Linnan Li13bf76a2024-05-05 19:18:02 +080073 ui::LogicalDisplayId{msg.body.key.displayId}, msg.body.key.hmac,
74 msg.body.key.action, msg.body.key.flags, msg.body.key.keyCode,
75 msg.body.key.scanCode, msg.body.key.metaState, msg.body.key.repeatCount,
76 msg.body.key.downTime, msg.body.key.eventTime);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070077 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080078}
79
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070080std::unique_ptr<FocusEvent> createFocusEvent(const InputMessage& msg) {
81 std::unique_ptr<FocusEvent> event = std::make_unique<FocusEvent>();
82 event->initialize(msg.body.focus.eventId, msg.body.focus.hasFocus);
83 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080084}
85
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070086std::unique_ptr<CaptureEvent> createCaptureEvent(const InputMessage& msg) {
87 std::unique_ptr<CaptureEvent> event = std::make_unique<CaptureEvent>();
88 event->initialize(msg.body.capture.eventId, msg.body.capture.pointerCaptureEnabled);
89 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080090}
91
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070092std::unique_ptr<DragEvent> createDragEvent(const InputMessage& msg) {
93 std::unique_ptr<DragEvent> event = std::make_unique<DragEvent>();
94 event->initialize(msg.body.drag.eventId, msg.body.drag.x, msg.body.drag.y,
95 msg.body.drag.isExiting);
96 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080097}
98
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070099std::unique_ptr<MotionEvent> createMotionEvent(const InputMessage& msg) {
100 std::unique_ptr<MotionEvent> event = std::make_unique<MotionEvent>();
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800101 const uint32_t pointerCount = msg.body.motion.pointerCount;
102 std::vector<PointerProperties> pointerProperties;
103 pointerProperties.reserve(pointerCount);
104 std::vector<PointerCoords> pointerCoords;
105 pointerCoords.reserve(pointerCount);
106 for (uint32_t i = 0; i < pointerCount; i++) {
107 pointerProperties.push_back(msg.body.motion.pointers[i].properties);
108 pointerCoords.push_back(msg.body.motion.pointers[i].coords);
109 }
110
111 ui::Transform transform;
112 transform.set({msg.body.motion.dsdx, msg.body.motion.dtdx, msg.body.motion.tx,
113 msg.body.motion.dtdy, msg.body.motion.dsdy, msg.body.motion.ty, 0, 0, 1});
114 ui::Transform displayTransform;
115 displayTransform.set({msg.body.motion.dsdxRaw, msg.body.motion.dtdxRaw, msg.body.motion.txRaw,
116 msg.body.motion.dtdyRaw, msg.body.motion.dsdyRaw, msg.body.motion.tyRaw,
117 0, 0, 1});
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700118 event->initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800119 ui::LogicalDisplayId{msg.body.motion.displayId}, msg.body.motion.hmac,
120 msg.body.motion.action, msg.body.motion.actionButton, msg.body.motion.flags,
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700121 msg.body.motion.edgeFlags, msg.body.motion.metaState,
122 msg.body.motion.buttonState, msg.body.motion.classification, transform,
123 msg.body.motion.xPrecision, msg.body.motion.yPrecision,
124 msg.body.motion.xCursorPosition, msg.body.motion.yCursorPosition,
125 displayTransform, msg.body.motion.downTime, msg.body.motion.eventTime,
126 pointerCount, pointerProperties.data(), pointerCoords.data());
127 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800128}
129
130void addSample(MotionEvent& event, const InputMessage& msg) {
131 uint32_t pointerCount = msg.body.motion.pointerCount;
132 std::vector<PointerCoords> pointerCoords;
133 pointerCoords.reserve(pointerCount);
134 for (uint32_t i = 0; i < pointerCount; i++) {
135 pointerCoords.push_back(msg.body.motion.pointers[i].coords);
136 }
137
138 // TODO(b/329770983): figure out if it's safe to combine events with mismatching metaState
139 event.setMetaState(event.getMetaState() | msg.body.motion.metaState);
jioana71c6f732024-07-16 15:42:56 +0000140 event.addSample(msg.body.motion.eventTime, pointerCoords.data(), msg.body.motion.eventId);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800141}
142
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700143std::unique_ptr<TouchModeEvent> createTouchModeEvent(const InputMessage& msg) {
144 std::unique_ptr<TouchModeEvent> event = std::make_unique<TouchModeEvent>();
145 event->initialize(msg.body.touchMode.eventId, msg.body.touchMode.isInTouchMode);
146 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800147}
148
149std::string outboundMessageToString(const InputMessage& outboundMsg) {
150 switch (outboundMsg.header.type) {
151 case InputMessage::Type::FINISHED: {
152 return android::base::StringPrintf(" Finish: seq=%" PRIu32 " handled=%s",
153 outboundMsg.header.seq,
154 toString(outboundMsg.body.finished.handled));
155 }
156 case InputMessage::Type::TIMELINE: {
157 return android::base::
158 StringPrintf(" Timeline: inputEventId=%" PRId32 " gpuCompletedTime=%" PRId64
159 ", presentTime=%" PRId64,
160 outboundMsg.body.timeline.eventId,
161 outboundMsg.body.timeline
162 .graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME],
163 outboundMsg.body.timeline
164 .graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
165 }
166 default: {
167 LOG(FATAL) << "Outbound message must be FINISHED or TIMELINE, got "
168 << ftl::enum_string(outboundMsg.header.type);
169 return "Unreachable";
170 }
171 }
172}
173
174InputMessage createFinishedMessage(uint32_t seq, bool handled, nsecs_t consumeTime) {
175 InputMessage msg;
176 msg.header.type = InputMessage::Type::FINISHED;
177 msg.header.seq = seq;
178 msg.body.finished.handled = handled;
179 msg.body.finished.consumeTime = consumeTime;
180 return msg;
181}
182
183InputMessage createTimelineMessage(int32_t inputEventId, nsecs_t gpuCompletedTime,
184 nsecs_t presentTime) {
185 InputMessage msg;
186 msg.header.type = InputMessage::Type::TIMELINE;
187 msg.header.seq = 0;
188 msg.body.timeline.eventId = inputEventId;
189 msg.body.timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = gpuCompletedTime;
190 msg.body.timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = presentTime;
191 return msg;
192}
193
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000194bool isPointerEvent(const MotionEvent& motionEvent) {
195 return (motionEvent.getSource() & AINPUT_SOURCE_CLASS_POINTER) == AINPUT_SOURCE_CLASS_POINTER;
196}
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800197} // namespace
198
199using android::base::Result;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800200
201// --- InputConsumerNoResampling ---
202
203InputConsumerNoResampling::InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel,
Paul Ramireze2bb1872024-08-12 20:21:13 +0000204 std::shared_ptr<LooperInterface> looper,
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000205 InputConsumerCallbacks& callbacks,
206 std::unique_ptr<Resampler> resampler)
Paul Ramireze2bb1872024-08-12 20:21:13 +0000207 : mChannel{channel},
208 mLooper{looper},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000209 mCallbacks(callbacks),
Paul Ramireze2bb1872024-08-12 20:21:13 +0000210 mResampler{std::move(resampler)},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000211 mFdEvents(0) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800212 LOG_ALWAYS_FATAL_IF(mLooper == nullptr);
213 mCallback = sp<LooperEventCallback>::make(
214 std::bind(&InputConsumerNoResampling::handleReceiveCallback, this,
215 std::placeholders::_1));
216 // In the beginning, there are no pending outbounds events; we only care about receiving
217 // incoming data.
218 setFdEvents(ALOOPER_EVENT_INPUT);
219}
220
Paul Ramireze2bb1872024-08-12 20:21:13 +0000221InputConsumerNoResampling::InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel,
222 sp<Looper> looper,
223 InputConsumerCallbacks& callbacks,
224 std::unique_ptr<Resampler> resampler)
225 : InputConsumerNoResampling(channel, std::make_shared<RealLooper>(looper), callbacks,
226 std::move(resampler)) {}
227
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800228InputConsumerNoResampling::~InputConsumerNoResampling() {
229 ensureCalledOnLooperThread(__func__);
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000230 consumeBatchedInputEvents(/*requestedFrameTime=*/std::nullopt);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800231 while (!mOutboundQueue.empty()) {
232 processOutboundEvents();
233 // This is our last chance to ack the events. If we don't ack them here, we will get an ANR,
234 // so keep trying to send the events as long as they are present in the queue.
235 }
236 setFdEvents(0);
237}
238
239int InputConsumerNoResampling::handleReceiveCallback(int events) {
240 // Allowed return values of this function as documented in LooperCallback::handleEvent
241 constexpr int REMOVE_CALLBACK = 0;
242 constexpr int KEEP_CALLBACK = 1;
243
244 if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
245 // This error typically occurs when the publisher has closed the input channel
246 // as part of removing a window or finishing an IME session, in which case
247 // the consumer will soon be disposed as well.
248 if (DEBUG_TRANSPORT_CONSUMER) {
249 LOG(INFO) << "The channel was hung up or an error occurred: " << mChannel->getName();
250 }
251 return REMOVE_CALLBACK;
252 }
253
254 int handledEvents = 0;
255 if (events & ALOOPER_EVENT_INPUT) {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000256 handleMessages(readAllMessages());
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800257 handledEvents |= ALOOPER_EVENT_INPUT;
258 }
259
260 if (events & ALOOPER_EVENT_OUTPUT) {
261 processOutboundEvents();
262 handledEvents |= ALOOPER_EVENT_OUTPUT;
263 }
264 if (handledEvents != events) {
265 LOG(FATAL) << "Mismatch: handledEvents=" << handledEvents << ", events=" << events;
266 }
267 return KEEP_CALLBACK;
268}
269
270void InputConsumerNoResampling::processOutboundEvents() {
271 while (!mOutboundQueue.empty()) {
272 const InputMessage& outboundMsg = mOutboundQueue.front();
273
274 const status_t result = mChannel->sendMessage(&outboundMsg);
275 if (result == OK) {
276 if (outboundMsg.header.type == InputMessage::Type::FINISHED) {
277 ATRACE_ASYNC_END("InputConsumer processing", /*cookie=*/outboundMsg.header.seq);
278 }
279 // Successful send. Erase the entry and keep trying to send more
280 mOutboundQueue.pop();
281 continue;
282 }
283
284 // Publisher is busy, try again later. Keep this entry (do not erase)
285 if (result == WOULD_BLOCK) {
286 setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
287 return; // try again later
288 }
289
290 // Some other error. Give up
291 LOG(FATAL) << "Failed to send outbound event on channel '" << mChannel->getName()
292 << "'. status=" << statusToString(result) << "(" << result << ")";
293 }
294
295 // The queue is now empty. Tell looper there's no more output to expect.
296 setFdEvents(ALOOPER_EVENT_INPUT);
297}
298
299void InputConsumerNoResampling::finishInputEvent(uint32_t seq, bool handled) {
300 ensureCalledOnLooperThread(__func__);
301 mOutboundQueue.push(createFinishedMessage(seq, handled, popConsumeTime(seq)));
302 // also produce finish events for all batches for this seq (if any)
303 const auto it = mBatchedSequenceNumbers.find(seq);
304 if (it != mBatchedSequenceNumbers.end()) {
305 for (uint32_t subSeq : it->second) {
306 mOutboundQueue.push(createFinishedMessage(subSeq, handled, popConsumeTime(subSeq)));
307 }
308 mBatchedSequenceNumbers.erase(it);
309 }
310 processOutboundEvents();
311}
312
313bool InputConsumerNoResampling::probablyHasInput() const {
314 // Ideally, this would only be allowed to run on the looper thread, and in production, it will.
315 // However, for testing, it's convenient to call this while the looper thread is blocked, so
316 // we do not call ensureCalledOnLooperThread here.
317 return (!mBatches.empty()) || mChannel->probablyHasInput();
318}
319
320void InputConsumerNoResampling::reportTimeline(int32_t inputEventId, nsecs_t gpuCompletedTime,
321 nsecs_t presentTime) {
322 ensureCalledOnLooperThread(__func__);
323 mOutboundQueue.push(createTimelineMessage(inputEventId, gpuCompletedTime, presentTime));
324 processOutboundEvents();
325}
326
327nsecs_t InputConsumerNoResampling::popConsumeTime(uint32_t seq) {
328 auto it = mConsumeTimes.find(seq);
329 // Consume time will be missing if either 'finishInputEvent' is called twice, or if it was
330 // called for the wrong (synthetic?) input event. Either way, it is a bug that should be fixed.
331 LOG_ALWAYS_FATAL_IF(it == mConsumeTimes.end(), "Could not find consume time for seq=%" PRIu32,
332 seq);
333 nsecs_t consumeTime = it->second;
334 mConsumeTimes.erase(it);
335 return consumeTime;
336}
337
338void InputConsumerNoResampling::setFdEvents(int events) {
339 if (mFdEvents != events) {
340 mFdEvents = events;
341 if (events != 0) {
342 mLooper->addFd(mChannel->getFd(), 0, events, mCallback, nullptr);
343 } else {
344 mLooper->removeFd(mChannel->getFd());
345 }
346 }
347}
348
349void InputConsumerNoResampling::handleMessages(std::vector<InputMessage>&& messages) {
350 // TODO(b/297226446) : add resampling
351 for (const InputMessage& msg : messages) {
352 if (msg.header.type == InputMessage::Type::MOTION) {
353 const int32_t action = msg.body.motion.action;
354 const DeviceId deviceId = msg.body.motion.deviceId;
355 const int32_t source = msg.body.motion.source;
356 const bool batchableEvent = (action == AMOTION_EVENT_ACTION_MOVE ||
357 action == AMOTION_EVENT_ACTION_HOVER_MOVE) &&
358 (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER) ||
359 isFromSource(source, AINPUT_SOURCE_CLASS_JOYSTICK));
360 if (batchableEvent) {
361 // add it to batch
362 mBatches[deviceId].emplace(msg);
363 } else {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000364 // consume all pending batches for this device immediately
365 consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/std::nullopt);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800366 handleMessage(msg);
367 }
368 } else {
369 // Non-motion events shouldn't force the consumption of pending batched events
370 handleMessage(msg);
371 }
372 }
373 // At the end of this, if we still have pending batches, notify the receiver about it.
374
375 // We need to carefully notify the InputConsumerCallbacks about the pending batch. The receiver
376 // could choose to consume all events when notified about the batch. That means that the
377 // "mBatches" variable could change when 'InputConsumerCallbacks::onBatchedInputEventPending' is
378 // invoked. We also can't notify the InputConsumerCallbacks in a while loop until mBatches is
379 // empty, because the receiver could choose to not consume the batch immediately.
380 std::set<int32_t> pendingBatchSources;
381 for (const auto& [_, pendingMessages] : mBatches) {
382 // Assume that all messages for a given device has the same source.
383 pendingBatchSources.insert(pendingMessages.front().body.motion.source);
384 }
385 for (const int32_t source : pendingBatchSources) {
386 const bool sourceStillRemaining =
387 std::any_of(mBatches.begin(), mBatches.end(), [=](const auto& pair) {
388 return pair.second.front().body.motion.source == source;
389 });
390 if (sourceStillRemaining) {
391 mCallbacks.onBatchedInputEventPending(source);
392 }
393 }
394}
395
396std::vector<InputMessage> InputConsumerNoResampling::readAllMessages() {
397 std::vector<InputMessage> messages;
398 while (true) {
Paul Ramirez0c25e862024-06-18 21:33:33 +0000399 android::base::Result<InputMessage> result = mChannel->receiveMessage();
400 if (result.ok()) {
401 const InputMessage& msg = *result;
402 const auto [_, inserted] =
403 mConsumeTimes.emplace(msg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
404 LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
405 msg.header.seq);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800406
Paul Ramirez0c25e862024-06-18 21:33:33 +0000407 // Trace the event processing timeline - event was just read from the socket
408 // TODO(b/329777420): distinguish between multiple instances of InputConsumer
409 // in the same process.
410 ATRACE_ASYNC_BEGIN("InputConsumer processing", /*cookie=*/msg.header.seq);
411 messages.push_back(msg);
412 } else { // !result.ok()
413 switch (result.error().code()) {
414 case WOULD_BLOCK: {
415 return messages;
416 }
417 case DEAD_OBJECT: {
418 LOG(FATAL) << "Got a dead object for " << mChannel->getName();
419 break;
420 }
421 case BAD_VALUE: {
422 LOG(FATAL) << "Got a bad value for " << mChannel->getName();
423 break;
424 }
425 default: {
426 LOG(FATAL) << "Unexpected error: " << result.error().message();
427 break;
428 }
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800429 }
430 }
431 }
432}
433
434void InputConsumerNoResampling::handleMessage(const InputMessage& msg) const {
435 switch (msg.header.type) {
436 case InputMessage::Type::KEY: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700437 std::unique_ptr<KeyEvent> keyEvent = createKeyEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800438 mCallbacks.onKeyEvent(std::move(keyEvent), msg.header.seq);
439 break;
440 }
441
442 case InputMessage::Type::MOTION: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700443 std::unique_ptr<MotionEvent> motionEvent = createMotionEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800444 mCallbacks.onMotionEvent(std::move(motionEvent), msg.header.seq);
445 break;
446 }
447
448 case InputMessage::Type::FINISHED:
449 case InputMessage::Type::TIMELINE: {
Siarhei Vishniakou11d223b2024-03-26 21:52:38 +0000450 LOG(FATAL) << "Consumed a " << ftl::enum_string(msg.header.type)
451 << " message, which should never be seen by InputConsumer on "
452 << mChannel->getName();
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800453 break;
454 }
455
456 case InputMessage::Type::FOCUS: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700457 std::unique_ptr<FocusEvent> focusEvent = createFocusEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800458 mCallbacks.onFocusEvent(std::move(focusEvent), msg.header.seq);
459 break;
460 }
461
462 case InputMessage::Type::CAPTURE: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700463 std::unique_ptr<CaptureEvent> captureEvent = createCaptureEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800464 mCallbacks.onCaptureEvent(std::move(captureEvent), msg.header.seq);
465 break;
466 }
467
468 case InputMessage::Type::DRAG: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700469 std::unique_ptr<DragEvent> dragEvent = createDragEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800470 mCallbacks.onDragEvent(std::move(dragEvent), msg.header.seq);
471 break;
472 }
473
474 case InputMessage::Type::TOUCH_MODE: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700475 std::unique_ptr<TouchModeEvent> touchModeEvent = createTouchModeEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800476 mCallbacks.onTouchModeEvent(std::move(touchModeEvent), msg.header.seq);
477 break;
478 }
479 }
480}
481
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000482std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>>
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000483InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrameTime,
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000484 std::queue<InputMessage>& messages) {
485 std::unique_ptr<MotionEvent> motionEvent;
486 std::optional<uint32_t> firstSeqForBatch;
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000487 const nanoseconds resampleLatency =
488 (mResampler != nullptr) ? mResampler->getResampleLatency() : nanoseconds{0};
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000489 const nanoseconds adjustedFrameTime = nanoseconds{requestedFrameTime} - resampleLatency;
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000490
491 while (!messages.empty() &&
492 (messages.front().body.motion.eventTime <= adjustedFrameTime.count())) {
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000493 if (motionEvent == nullptr) {
494 motionEvent = createMotionEvent(messages.front());
495 firstSeqForBatch = messages.front().header.seq;
496 const auto [_, inserted] = mBatchedSequenceNumbers.insert({*firstSeqForBatch, {}});
497 LOG_IF(FATAL, !inserted)
498 << "The sequence " << messages.front().header.seq << " was already present!";
499 } else {
500 addSample(*motionEvent, messages.front());
501 mBatchedSequenceNumbers[*firstSeqForBatch].push_back(messages.front().header.seq);
502 }
503 messages.pop();
504 }
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000505 // Check if resampling should be performed.
506 if (motionEvent != nullptr && isPointerEvent(*motionEvent) && mResampler != nullptr) {
507 InputMessage* futureSample = nullptr;
508 if (!messages.empty()) {
509 futureSample = &messages.front();
510 }
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000511 mResampler->resampleMotionEvent(nanoseconds{requestedFrameTime}, *motionEvent,
512 futureSample);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000513 }
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000514 return std::make_pair(std::move(motionEvent), firstSeqForBatch);
515}
516
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800517bool InputConsumerNoResampling::consumeBatchedInputEvents(
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000518 std::optional<DeviceId> deviceId, std::optional<nsecs_t> requestedFrameTime) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800519 ensureCalledOnLooperThread(__func__);
520 // When batching is not enabled, we want to consume all events. That's equivalent to having an
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000521 // infinite requestedFrameTime.
522 requestedFrameTime = requestedFrameTime.value_or(std::numeric_limits<nsecs_t>::max());
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800523 bool producedEvents = false;
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000524
525 for (auto deviceIdIter = (deviceId.has_value()) ? (mBatches.find(*deviceId))
526 : (mBatches.begin());
527 deviceIdIter != mBatches.cend(); ++deviceIdIter) {
528 std::queue<InputMessage>& messages = deviceIdIter->second;
529 auto [motion, firstSeqForBatch] = createBatchedMotionEvent(*requestedFrameTime, messages);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700530 if (motion != nullptr) {
531 LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value());
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800532 mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch);
533 producedEvents = true;
534 } else {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000535 // This is OK, it just means that the requestedFrameTime is too old (all events that we
536 // have pending are in the future of the requestedFrameTime). Maybe print a warning? If
537 // there are multiple devices active though, this might be normal and can just be
538 // ignored, unless none of them resulted in any consumption (in that case, this function
539 // would already return "false" so we could just leave it up to the caller).
540 }
541
542 if (deviceId.has_value()) {
543 // We already consumed events for this device. Break here to prevent iterating over the
544 // other devices.
545 break;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800546 }
547 }
548 std::erase_if(mBatches, [](const auto& pair) { return pair.second.empty(); });
549 return producedEvents;
550}
551
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000552bool InputConsumerNoResampling::consumeBatchedInputEvents(
553 std::optional<nsecs_t> requestedFrameTime) {
554 return consumeBatchedInputEvents(/*deviceId=*/std::nullopt, requestedFrameTime);
555}
556
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800557void InputConsumerNoResampling::ensureCalledOnLooperThread(const char* func) const {
558 sp<Looper> callingThreadLooper = Looper::getForThread();
Paul Ramireze2bb1872024-08-12 20:21:13 +0000559 if (callingThreadLooper != mLooper->getLooper()) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800560 LOG(FATAL) << "The function " << func << " can only be called on the looper thread";
561 }
562}
563
564std::string InputConsumerNoResampling::dump() const {
565 ensureCalledOnLooperThread(__func__);
566 std::string out;
567 if (mOutboundQueue.empty()) {
568 out += "mOutboundQueue: <empty>\n";
569 } else {
570 out += "mOutboundQueue:\n";
571 // Make a copy of mOutboundQueue for printing destructively. Unfortunately std::queue
572 // doesn't provide a good way to iterate over the entire container.
573 std::queue<InputMessage> tmpQueue = mOutboundQueue;
574 while (!tmpQueue.empty()) {
575 out += std::string(" ") + outboundMessageToString(tmpQueue.front()) + "\n";
576 tmpQueue.pop();
577 }
578 }
579
580 if (mBatches.empty()) {
581 out += "mBatches: <empty>\n";
582 } else {
583 out += "mBatches:\n";
584 for (const auto& [deviceId, messages] : mBatches) {
585 out += " Device id ";
586 out += std::to_string(deviceId);
587 out += ":\n";
588 // Make a copy of mOutboundQueue for printing destructively. Unfortunately std::queue
589 // doesn't provide a good way to iterate over the entire container.
590 std::queue<InputMessage> tmpQueue = messages;
591 while (!tmpQueue.empty()) {
592 LOG_ALWAYS_FATAL_IF(tmpQueue.front().header.type != InputMessage::Type::MOTION);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700593 std::unique_ptr<MotionEvent> motion = createMotionEvent(tmpQueue.front());
594 out += std::string(" ") + streamableToString(*motion) + "\n";
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800595 tmpQueue.pop();
596 }
597 }
598 }
599
600 return out;
601}
602
603} // namespace android