blob: 9578639e2b1f605321efbc7f091119c833e7d6d0 [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
20#include <inttypes.h>
Siarhei Vishniakoue7ffef72025-01-24 15:24:27 -080021#include <set>
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080022
23#include <android-base/logging.h>
24#include <android-base/properties.h>
25#include <android-base/stringprintf.h>
26#include <cutils/properties.h>
27#include <ftl/enum.h>
28#include <utils/Trace.h>
29
30#include <com_android_input_flags.h>
31#include <input/InputConsumerNoResampling.h>
32#include <input/PrintTools.h>
33#include <input/TraceTools.h>
34
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080035namespace android {
36
37namespace {
38
Paul Ramirezcd7488c2024-09-13 23:01:12 +000039using std::chrono::nanoseconds;
40
Paul Ramireze37f8342024-08-28 18:42:21 +000041using android::base::Result;
42
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080043/**
44 * Log debug messages relating to the consumer end of the transport channel.
45 * Enable this via "adb shell setprop log.tag.InputTransportConsumer DEBUG" (requires restart)
46 */
47const bool DEBUG_TRANSPORT_CONSUMER =
48 __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Consumer", ANDROID_LOG_INFO);
49
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070050std::unique_ptr<KeyEvent> createKeyEvent(const InputMessage& msg) {
51 std::unique_ptr<KeyEvent> event = std::make_unique<KeyEvent>();
52 event->initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
Linnan Li13bf76a2024-05-05 19:18:02 +080053 ui::LogicalDisplayId{msg.body.key.displayId}, msg.body.key.hmac,
54 msg.body.key.action, msg.body.key.flags, msg.body.key.keyCode,
55 msg.body.key.scanCode, msg.body.key.metaState, msg.body.key.repeatCount,
56 msg.body.key.downTime, msg.body.key.eventTime);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070057 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080058}
59
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070060std::unique_ptr<FocusEvent> createFocusEvent(const InputMessage& msg) {
61 std::unique_ptr<FocusEvent> event = std::make_unique<FocusEvent>();
62 event->initialize(msg.body.focus.eventId, msg.body.focus.hasFocus);
63 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080064}
65
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070066std::unique_ptr<CaptureEvent> createCaptureEvent(const InputMessage& msg) {
67 std::unique_ptr<CaptureEvent> event = std::make_unique<CaptureEvent>();
68 event->initialize(msg.body.capture.eventId, msg.body.capture.pointerCaptureEnabled);
69 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080070}
71
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070072std::unique_ptr<DragEvent> createDragEvent(const InputMessage& msg) {
73 std::unique_ptr<DragEvent> event = std::make_unique<DragEvent>();
74 event->initialize(msg.body.drag.eventId, msg.body.drag.x, msg.body.drag.y,
75 msg.body.drag.isExiting);
76 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080077}
78
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070079std::unique_ptr<MotionEvent> createMotionEvent(const InputMessage& msg) {
80 std::unique_ptr<MotionEvent> event = std::make_unique<MotionEvent>();
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080081 const uint32_t pointerCount = msg.body.motion.pointerCount;
82 std::vector<PointerProperties> pointerProperties;
83 pointerProperties.reserve(pointerCount);
84 std::vector<PointerCoords> pointerCoords;
85 pointerCoords.reserve(pointerCount);
86 for (uint32_t i = 0; i < pointerCount; i++) {
87 pointerProperties.push_back(msg.body.motion.pointers[i].properties);
88 pointerCoords.push_back(msg.body.motion.pointers[i].coords);
89 }
90
91 ui::Transform transform;
92 transform.set({msg.body.motion.dsdx, msg.body.motion.dtdx, msg.body.motion.tx,
93 msg.body.motion.dtdy, msg.body.motion.dsdy, msg.body.motion.ty, 0, 0, 1});
94 ui::Transform displayTransform;
95 displayTransform.set({msg.body.motion.dsdxRaw, msg.body.motion.dtdxRaw, msg.body.motion.txRaw,
96 msg.body.motion.dtdyRaw, msg.body.motion.dsdyRaw, msg.body.motion.tyRaw,
97 0, 0, 1});
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070098 event->initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
Linnan Li13bf76a2024-05-05 19:18:02 +080099 ui::LogicalDisplayId{msg.body.motion.displayId}, msg.body.motion.hmac,
100 msg.body.motion.action, msg.body.motion.actionButton, msg.body.motion.flags,
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700101 msg.body.motion.edgeFlags, msg.body.motion.metaState,
102 msg.body.motion.buttonState, msg.body.motion.classification, transform,
103 msg.body.motion.xPrecision, msg.body.motion.yPrecision,
104 msg.body.motion.xCursorPosition, msg.body.motion.yCursorPosition,
105 displayTransform, msg.body.motion.downTime, msg.body.motion.eventTime,
106 pointerCount, pointerProperties.data(), pointerCoords.data());
107 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800108}
109
110void addSample(MotionEvent& event, const InputMessage& msg) {
111 uint32_t pointerCount = msg.body.motion.pointerCount;
112 std::vector<PointerCoords> pointerCoords;
113 pointerCoords.reserve(pointerCount);
114 for (uint32_t i = 0; i < pointerCount; i++) {
115 pointerCoords.push_back(msg.body.motion.pointers[i].coords);
116 }
117
118 // TODO(b/329770983): figure out if it's safe to combine events with mismatching metaState
119 event.setMetaState(event.getMetaState() | msg.body.motion.metaState);
jioana71c6f732024-07-16 15:42:56 +0000120 event.addSample(msg.body.motion.eventTime, pointerCoords.data(), msg.body.motion.eventId);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800121}
122
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700123std::unique_ptr<TouchModeEvent> createTouchModeEvent(const InputMessage& msg) {
124 std::unique_ptr<TouchModeEvent> event = std::make_unique<TouchModeEvent>();
125 event->initialize(msg.body.touchMode.eventId, msg.body.touchMode.isInTouchMode);
126 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800127}
128
129std::string outboundMessageToString(const InputMessage& outboundMsg) {
130 switch (outboundMsg.header.type) {
131 case InputMessage::Type::FINISHED: {
132 return android::base::StringPrintf(" Finish: seq=%" PRIu32 " handled=%s",
133 outboundMsg.header.seq,
134 toString(outboundMsg.body.finished.handled));
135 }
136 case InputMessage::Type::TIMELINE: {
137 return android::base::
138 StringPrintf(" Timeline: inputEventId=%" PRId32 " gpuCompletedTime=%" PRId64
139 ", presentTime=%" PRId64,
140 outboundMsg.body.timeline.eventId,
141 outboundMsg.body.timeline
142 .graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME],
143 outboundMsg.body.timeline
144 .graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
145 }
146 default: {
147 LOG(FATAL) << "Outbound message must be FINISHED or TIMELINE, got "
148 << ftl::enum_string(outboundMsg.header.type);
149 return "Unreachable";
150 }
151 }
152}
153
154InputMessage createFinishedMessage(uint32_t seq, bool handled, nsecs_t consumeTime) {
155 InputMessage msg;
156 msg.header.type = InputMessage::Type::FINISHED;
157 msg.header.seq = seq;
158 msg.body.finished.handled = handled;
159 msg.body.finished.consumeTime = consumeTime;
160 return msg;
161}
162
163InputMessage createTimelineMessage(int32_t inputEventId, nsecs_t gpuCompletedTime,
164 nsecs_t presentTime) {
165 InputMessage msg;
166 msg.header.type = InputMessage::Type::TIMELINE;
167 msg.header.seq = 0;
168 msg.body.timeline.eventId = inputEventId;
169 msg.body.timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = gpuCompletedTime;
170 msg.body.timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = presentTime;
171 return msg;
172}
Siarhei Vishniakoueb63bbf2024-11-13 15:13:29 -0800173
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800174} // namespace
175
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800176// --- InputConsumerNoResampling ---
177
Paul Ramireze37f8342024-08-28 18:42:21 +0000178InputConsumerNoResampling::InputConsumerNoResampling(
179 const std::shared_ptr<InputChannel>& channel, sp<Looper> looper,
180 InputConsumerCallbacks& callbacks,
181 std::function<std::unique_ptr<Resampler>()> resamplerCreator)
Paul Ramireze2bb1872024-08-12 20:21:13 +0000182 : mChannel{channel},
183 mLooper{looper},
Paul Ramirez87f1c012024-09-18 18:23:14 +0000184 mCallbacks{callbacks},
Paul Ramireze37f8342024-08-28 18:42:21 +0000185 mResamplerCreator{std::move(resamplerCreator)},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000186 mFdEvents(0) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800187 LOG_ALWAYS_FATAL_IF(mLooper == nullptr);
188 mCallback = sp<LooperEventCallback>::make(
189 std::bind(&InputConsumerNoResampling::handleReceiveCallback, this,
190 std::placeholders::_1));
191 // In the beginning, there are no pending outbounds events; we only care about receiving
192 // incoming data.
193 setFdEvents(ALOOPER_EVENT_INPUT);
194}
195
196InputConsumerNoResampling::~InputConsumerNoResampling() {
197 ensureCalledOnLooperThread(__func__);
Siarhei Vishniakoubc723092024-10-08 15:41:51 -0700198 // If there are any remaining unread batches, send an ack for them and don't deliver
199 // them to callbacks.
200 for (auto& [_, batches] : mBatches) {
201 while (!batches.empty()) {
202 finishInputEvent(batches.front().header.seq, /*handled=*/false);
203 batches.pop();
204 }
205 }
Siarhei Vishniakou362fa222024-10-17 14:19:52 -0700206
207 while (!mOutboundQueue.empty()) {
208 processOutboundEvents();
209 // This is our last chance to ack the events. If we don't ack them here, we will get an ANR,
210 // so keep trying to send the events as long as they are present in the queue.
211 }
Siarhei Vishniakoubc723092024-10-08 15:41:51 -0700212 // However, it is still up to the app to finish any events that have already been delivered
213 // to the callbacks. If we wanted to change that behaviour and auto-finish all unfinished events
214 // that were already sent to callbacks, we could potentially loop through "mConsumeTimes"
215 // instead. We can't use "mBatchedSequenceNumbers" for this purpose, because it only contains
216 // batchable (i.e., ACTION_MOVE) events that were sent to the callbacks.
217 const size_t unfinishedEvents = mConsumeTimes.size();
218 LOG_IF(INFO, unfinishedEvents != 0)
219 << getName() << " has " << unfinishedEvents << " unfinished event(s)";
Siarhei Vishniakou362fa222024-10-17 14:19:52 -0700220 // Remove the fd from epoll, so that Looper does not call 'handleReceiveCallback' anymore.
221 // This must be done at the end of the destructor; otherwise, some of the other functions may
222 // call 'setFdEvents' as a side-effect, thus adding the fd back to the epoll set of the looper.
223 setFdEvents(0);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800224}
225
226int InputConsumerNoResampling::handleReceiveCallback(int events) {
227 // Allowed return values of this function as documented in LooperCallback::handleEvent
228 constexpr int REMOVE_CALLBACK = 0;
229 constexpr int KEEP_CALLBACK = 1;
230
231 if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
232 // This error typically occurs when the publisher has closed the input channel
233 // as part of removing a window or finishing an IME session, in which case
234 // the consumer will soon be disposed as well.
235 if (DEBUG_TRANSPORT_CONSUMER) {
236 LOG(INFO) << "The channel was hung up or an error occurred: " << mChannel->getName();
237 }
238 return REMOVE_CALLBACK;
239 }
240
241 int handledEvents = 0;
242 if (events & ALOOPER_EVENT_INPUT) {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000243 handleMessages(readAllMessages());
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800244 handledEvents |= ALOOPER_EVENT_INPUT;
245 }
246
247 if (events & ALOOPER_EVENT_OUTPUT) {
248 processOutboundEvents();
249 handledEvents |= ALOOPER_EVENT_OUTPUT;
250 }
251 if (handledEvents != events) {
252 LOG(FATAL) << "Mismatch: handledEvents=" << handledEvents << ", events=" << events;
253 }
254 return KEEP_CALLBACK;
255}
256
257void InputConsumerNoResampling::processOutboundEvents() {
258 while (!mOutboundQueue.empty()) {
259 const InputMessage& outboundMsg = mOutboundQueue.front();
260
261 const status_t result = mChannel->sendMessage(&outboundMsg);
262 if (result == OK) {
263 if (outboundMsg.header.type == InputMessage::Type::FINISHED) {
264 ATRACE_ASYNC_END("InputConsumer processing", /*cookie=*/outboundMsg.header.seq);
265 }
266 // Successful send. Erase the entry and keep trying to send more
267 mOutboundQueue.pop();
268 continue;
269 }
270
271 // Publisher is busy, try again later. Keep this entry (do not erase)
272 if (result == WOULD_BLOCK) {
273 setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
274 return; // try again later
275 }
276
Siarhei Vishniakoueb63bbf2024-11-13 15:13:29 -0800277 if (result == DEAD_OBJECT) {
278 // If there's no one to receive events in the channel, there's no point in sending them.
279 // Drop all outbound events.
280 LOG(INFO) << "Channel " << mChannel->getName() << " died. Dropping outbound event "
281 << outboundMsg;
282 mOutboundQueue.pop();
283 setFdEvents(0);
284 continue;
285 }
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800286 // Some other error. Give up
287 LOG(FATAL) << "Failed to send outbound event on channel '" << mChannel->getName()
288 << "'. status=" << statusToString(result) << "(" << result << ")";
289 }
290
291 // The queue is now empty. Tell looper there's no more output to expect.
292 setFdEvents(ALOOPER_EVENT_INPUT);
293}
294
295void InputConsumerNoResampling::finishInputEvent(uint32_t seq, bool handled) {
296 ensureCalledOnLooperThread(__func__);
297 mOutboundQueue.push(createFinishedMessage(seq, handled, popConsumeTime(seq)));
298 // also produce finish events for all batches for this seq (if any)
299 const auto it = mBatchedSequenceNumbers.find(seq);
300 if (it != mBatchedSequenceNumbers.end()) {
301 for (uint32_t subSeq : it->second) {
302 mOutboundQueue.push(createFinishedMessage(subSeq, handled, popConsumeTime(subSeq)));
303 }
304 mBatchedSequenceNumbers.erase(it);
305 }
306 processOutboundEvents();
307}
308
309bool InputConsumerNoResampling::probablyHasInput() const {
310 // Ideally, this would only be allowed to run on the looper thread, and in production, it will.
311 // However, for testing, it's convenient to call this while the looper thread is blocked, so
312 // we do not call ensureCalledOnLooperThread here.
313 return (!mBatches.empty()) || mChannel->probablyHasInput();
314}
315
316void InputConsumerNoResampling::reportTimeline(int32_t inputEventId, nsecs_t gpuCompletedTime,
317 nsecs_t presentTime) {
318 ensureCalledOnLooperThread(__func__);
319 mOutboundQueue.push(createTimelineMessage(inputEventId, gpuCompletedTime, presentTime));
320 processOutboundEvents();
321}
322
323nsecs_t InputConsumerNoResampling::popConsumeTime(uint32_t seq) {
324 auto it = mConsumeTimes.find(seq);
325 // Consume time will be missing if either 'finishInputEvent' is called twice, or if it was
326 // called for the wrong (synthetic?) input event. Either way, it is a bug that should be fixed.
327 LOG_ALWAYS_FATAL_IF(it == mConsumeTimes.end(), "Could not find consume time for seq=%" PRIu32,
328 seq);
329 nsecs_t consumeTime = it->second;
330 mConsumeTimes.erase(it);
331 return consumeTime;
332}
333
334void InputConsumerNoResampling::setFdEvents(int events) {
335 if (mFdEvents != events) {
336 mFdEvents = events;
337 if (events != 0) {
338 mLooper->addFd(mChannel->getFd(), 0, events, mCallback, nullptr);
339 } else {
340 mLooper->removeFd(mChannel->getFd());
341 }
342 }
343}
344
345void InputConsumerNoResampling::handleMessages(std::vector<InputMessage>&& messages) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800346 for (const InputMessage& msg : messages) {
347 if (msg.header.type == InputMessage::Type::MOTION) {
348 const int32_t action = msg.body.motion.action;
349 const DeviceId deviceId = msg.body.motion.deviceId;
350 const int32_t source = msg.body.motion.source;
351 const bool batchableEvent = (action == AMOTION_EVENT_ACTION_MOVE ||
352 action == AMOTION_EVENT_ACTION_HOVER_MOVE) &&
353 (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER) ||
354 isFromSource(source, AINPUT_SOURCE_CLASS_JOYSTICK));
Paul Ramireze37f8342024-08-28 18:42:21 +0000355
356 const bool canResample = (mResamplerCreator != nullptr) &&
357 (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER));
358 if (canResample) {
359 if (action == AMOTION_EVENT_ACTION_DOWN) {
360 if (std::unique_ptr<Resampler> resampler = mResamplerCreator();
361 resampler != nullptr) {
362 const auto [_, inserted] =
363 mResamplers.insert(std::pair(deviceId, std::move(resampler)));
364 LOG_IF(WARNING, !inserted) << deviceId << "already exists in mResamplers";
365 }
366 }
367 }
368
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800369 if (batchableEvent) {
370 // add it to batch
371 mBatches[deviceId].emplace(msg);
372 } else {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000373 // consume all pending batches for this device immediately
Paul Ramirez37242c82024-10-18 23:16:43 +0000374 consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/
375 std::numeric_limits<nsecs_t>::max());
Paul Ramireze37f8342024-08-28 18:42:21 +0000376 if (canResample &&
377 (action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL)) {
378 LOG_IF(INFO, mResamplers.erase(deviceId) == 0)
379 << deviceId << "does not exist in mResamplers";
380 }
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800381 handleMessage(msg);
382 }
383 } else {
384 // Non-motion events shouldn't force the consumption of pending batched events
385 handleMessage(msg);
386 }
387 }
388 // At the end of this, if we still have pending batches, notify the receiver about it.
389
390 // We need to carefully notify the InputConsumerCallbacks about the pending batch. The receiver
391 // could choose to consume all events when notified about the batch. That means that the
392 // "mBatches" variable could change when 'InputConsumerCallbacks::onBatchedInputEventPending' is
393 // invoked. We also can't notify the InputConsumerCallbacks in a while loop until mBatches is
394 // empty, because the receiver could choose to not consume the batch immediately.
395 std::set<int32_t> pendingBatchSources;
396 for (const auto& [_, pendingMessages] : mBatches) {
397 // Assume that all messages for a given device has the same source.
398 pendingBatchSources.insert(pendingMessages.front().body.motion.source);
399 }
400 for (const int32_t source : pendingBatchSources) {
401 const bool sourceStillRemaining =
402 std::any_of(mBatches.begin(), mBatches.end(), [=](const auto& pair) {
403 return pair.second.front().body.motion.source == source;
404 });
405 if (sourceStillRemaining) {
406 mCallbacks.onBatchedInputEventPending(source);
407 }
408 }
409}
410
411std::vector<InputMessage> InputConsumerNoResampling::readAllMessages() {
412 std::vector<InputMessage> messages;
413 while (true) {
Paul Ramirez0c25e862024-06-18 21:33:33 +0000414 android::base::Result<InputMessage> result = mChannel->receiveMessage();
415 if (result.ok()) {
416 const InputMessage& msg = *result;
417 const auto [_, inserted] =
418 mConsumeTimes.emplace(msg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
419 LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
420 msg.header.seq);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800421
Paul Ramirez0c25e862024-06-18 21:33:33 +0000422 // Trace the event processing timeline - event was just read from the socket
423 // TODO(b/329777420): distinguish between multiple instances of InputConsumer
424 // in the same process.
425 ATRACE_ASYNC_BEGIN("InputConsumer processing", /*cookie=*/msg.header.seq);
426 messages.push_back(msg);
427 } else { // !result.ok()
428 switch (result.error().code()) {
429 case WOULD_BLOCK: {
430 return messages;
431 }
432 case DEAD_OBJECT: {
433 LOG(FATAL) << "Got a dead object for " << mChannel->getName();
434 break;
435 }
436 case BAD_VALUE: {
437 LOG(FATAL) << "Got a bad value for " << mChannel->getName();
438 break;
439 }
440 default: {
441 LOG(FATAL) << "Unexpected error: " << result.error().message();
442 break;
443 }
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800444 }
445 }
446 }
447}
448
449void InputConsumerNoResampling::handleMessage(const InputMessage& msg) const {
450 switch (msg.header.type) {
451 case InputMessage::Type::KEY: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700452 std::unique_ptr<KeyEvent> keyEvent = createKeyEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800453 mCallbacks.onKeyEvent(std::move(keyEvent), msg.header.seq);
454 break;
455 }
456
457 case InputMessage::Type::MOTION: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700458 std::unique_ptr<MotionEvent> motionEvent = createMotionEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800459 mCallbacks.onMotionEvent(std::move(motionEvent), msg.header.seq);
460 break;
461 }
462
463 case InputMessage::Type::FINISHED:
464 case InputMessage::Type::TIMELINE: {
Siarhei Vishniakou11d223b2024-03-26 21:52:38 +0000465 LOG(FATAL) << "Consumed a " << ftl::enum_string(msg.header.type)
466 << " message, which should never be seen by InputConsumer on "
467 << mChannel->getName();
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800468 break;
469 }
470
471 case InputMessage::Type::FOCUS: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700472 std::unique_ptr<FocusEvent> focusEvent = createFocusEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800473 mCallbacks.onFocusEvent(std::move(focusEvent), msg.header.seq);
474 break;
475 }
476
477 case InputMessage::Type::CAPTURE: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700478 std::unique_ptr<CaptureEvent> captureEvent = createCaptureEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800479 mCallbacks.onCaptureEvent(std::move(captureEvent), msg.header.seq);
480 break;
481 }
482
483 case InputMessage::Type::DRAG: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700484 std::unique_ptr<DragEvent> dragEvent = createDragEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800485 mCallbacks.onDragEvent(std::move(dragEvent), msg.header.seq);
486 break;
487 }
488
489 case InputMessage::Type::TOUCH_MODE: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700490 std::unique_ptr<TouchModeEvent> touchModeEvent = createTouchModeEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800491 mCallbacks.onTouchModeEvent(std::move(touchModeEvent), msg.header.seq);
492 break;
493 }
494 }
495}
496
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000497std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>>
Paul Ramirez37242c82024-10-18 23:16:43 +0000498InputConsumerNoResampling::createBatchedMotionEvent(const std::optional<nsecs_t> requestedFrameTime,
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000499 std::queue<InputMessage>& messages) {
500 std::unique_ptr<MotionEvent> motionEvent;
501 std::optional<uint32_t> firstSeqForBatch;
Paul Ramireze37f8342024-08-28 18:42:21 +0000502
503 LOG_IF(FATAL, messages.empty()) << "messages queue is empty!";
504 const DeviceId deviceId = messages.front().body.motion.deviceId;
505 const auto resampler = mResamplers.find(deviceId);
506 const nanoseconds resampleLatency = (resampler != mResamplers.cend())
507 ? resampler->second->getResampleLatency()
508 : nanoseconds{0};
Paul Ramirez37242c82024-10-18 23:16:43 +0000509 // When batching is not enabled, we want to consume all events. That's equivalent to having an
510 // infinite requestedFrameTime.
511 const nanoseconds adjustedFrameTime = (requestedFrameTime.has_value())
512 ? (nanoseconds{*requestedFrameTime} - resampleLatency)
513 : nanoseconds{std::numeric_limits<nsecs_t>::max()};
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000514
515 while (!messages.empty() &&
516 (messages.front().body.motion.eventTime <= adjustedFrameTime.count())) {
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000517 if (motionEvent == nullptr) {
518 motionEvent = createMotionEvent(messages.front());
519 firstSeqForBatch = messages.front().header.seq;
520 const auto [_, inserted] = mBatchedSequenceNumbers.insert({*firstSeqForBatch, {}});
521 LOG_IF(FATAL, !inserted)
522 << "The sequence " << messages.front().header.seq << " was already present!";
523 } else {
524 addSample(*motionEvent, messages.front());
525 mBatchedSequenceNumbers[*firstSeqForBatch].push_back(messages.front().header.seq);
526 }
527 messages.pop();
528 }
Paul Ramireze37f8342024-08-28 18:42:21 +0000529
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000530 // Check if resampling should be performed.
Paul Ramireze37f8342024-08-28 18:42:21 +0000531 InputMessage* futureSample = nullptr;
532 if (!messages.empty()) {
533 futureSample = &messages.front();
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000534 }
Paul Ramirez37242c82024-10-18 23:16:43 +0000535 if ((motionEvent != nullptr) && (resampler != mResamplers.cend()) &&
536 (requestedFrameTime.has_value())) {
537 resampler->second->resampleMotionEvent(nanoseconds{*requestedFrameTime}, *motionEvent,
Paul Ramireze37f8342024-08-28 18:42:21 +0000538 futureSample);
539 }
540
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000541 return std::make_pair(std::move(motionEvent), firstSeqForBatch);
542}
543
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800544bool InputConsumerNoResampling::consumeBatchedInputEvents(
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000545 std::optional<DeviceId> deviceId, std::optional<nsecs_t> requestedFrameTime) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800546 ensureCalledOnLooperThread(__func__);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800547 bool producedEvents = false;
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000548
549 for (auto deviceIdIter = (deviceId.has_value()) ? (mBatches.find(*deviceId))
550 : (mBatches.begin());
551 deviceIdIter != mBatches.cend(); ++deviceIdIter) {
552 std::queue<InputMessage>& messages = deviceIdIter->second;
Paul Ramirez37242c82024-10-18 23:16:43 +0000553 auto [motion, firstSeqForBatch] = createBatchedMotionEvent(requestedFrameTime, messages);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700554 if (motion != nullptr) {
555 LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value());
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800556 mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch);
557 producedEvents = true;
558 } else {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000559 // This is OK, it just means that the requestedFrameTime is too old (all events that we
560 // have pending are in the future of the requestedFrameTime). Maybe print a warning? If
561 // there are multiple devices active though, this might be normal and can just be
562 // ignored, unless none of them resulted in any consumption (in that case, this function
563 // would already return "false" so we could just leave it up to the caller).
564 }
565
566 if (deviceId.has_value()) {
567 // We already consumed events for this device. Break here to prevent iterating over the
568 // other devices.
569 break;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800570 }
571 }
572 std::erase_if(mBatches, [](const auto& pair) { return pair.second.empty(); });
573 return producedEvents;
574}
575
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000576bool InputConsumerNoResampling::consumeBatchedInputEvents(
577 std::optional<nsecs_t> requestedFrameTime) {
578 return consumeBatchedInputEvents(/*deviceId=*/std::nullopt, requestedFrameTime);
579}
580
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800581void InputConsumerNoResampling::ensureCalledOnLooperThread(const char* func) const {
582 sp<Looper> callingThreadLooper = Looper::getForThread();
Paul Ramirez87f1c012024-09-18 18:23:14 +0000583 if (callingThreadLooper != mLooper) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800584 LOG(FATAL) << "The function " << func << " can only be called on the looper thread";
585 }
586}
587
588std::string InputConsumerNoResampling::dump() const {
589 ensureCalledOnLooperThread(__func__);
590 std::string out;
591 if (mOutboundQueue.empty()) {
592 out += "mOutboundQueue: <empty>\n";
593 } else {
594 out += "mOutboundQueue:\n";
595 // Make a copy of mOutboundQueue for printing destructively. Unfortunately std::queue
596 // doesn't provide a good way to iterate over the entire container.
597 std::queue<InputMessage> tmpQueue = mOutboundQueue;
598 while (!tmpQueue.empty()) {
599 out += std::string(" ") + outboundMessageToString(tmpQueue.front()) + "\n";
600 tmpQueue.pop();
601 }
602 }
603
604 if (mBatches.empty()) {
605 out += "mBatches: <empty>\n";
606 } else {
607 out += "mBatches:\n";
608 for (const auto& [deviceId, messages] : mBatches) {
609 out += " Device id ";
610 out += std::to_string(deviceId);
611 out += ":\n";
612 // Make a copy of mOutboundQueue for printing destructively. Unfortunately std::queue
613 // doesn't provide a good way to iterate over the entire container.
614 std::queue<InputMessage> tmpQueue = messages;
615 while (!tmpQueue.empty()) {
616 LOG_ALWAYS_FATAL_IF(tmpQueue.front().header.type != InputMessage::Type::MOTION);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700617 std::unique_ptr<MotionEvent> motion = createMotionEvent(tmpQueue.front());
618 out += std::string(" ") + streamableToString(*motion) + "\n";
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800619 tmpQueue.pop();
620 }
621 }
622 }
623
624 return out;
625}
626
627} // namespace android