blob: ce8bb43a76cc978cfbfdceda552b1a330ff4b5fb [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>
21
22#include <android-base/logging.h>
23#include <android-base/properties.h>
24#include <android-base/stringprintf.h>
25#include <cutils/properties.h>
26#include <ftl/enum.h>
27#include <utils/Trace.h>
28
29#include <com_android_input_flags.h>
30#include <input/InputConsumerNoResampling.h>
31#include <input/PrintTools.h>
32#include <input/TraceTools.h>
33
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080034namespace android {
35
36namespace {
37
Paul Ramirezcd7488c2024-09-13 23:01:12 +000038using std::chrono::nanoseconds;
39
Paul Ramireze37f8342024-08-28 18:42:21 +000040using android::base::Result;
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
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070049std::unique_ptr<KeyEvent> createKeyEvent(const InputMessage& msg) {
50 std::unique_ptr<KeyEvent> event = std::make_unique<KeyEvent>();
51 event->initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
Linnan Li13bf76a2024-05-05 19:18:02 +080052 ui::LogicalDisplayId{msg.body.key.displayId}, msg.body.key.hmac,
53 msg.body.key.action, msg.body.key.flags, msg.body.key.keyCode,
54 msg.body.key.scanCode, msg.body.key.metaState, msg.body.key.repeatCount,
55 msg.body.key.downTime, msg.body.key.eventTime);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070056 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080057}
58
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070059std::unique_ptr<FocusEvent> createFocusEvent(const InputMessage& msg) {
60 std::unique_ptr<FocusEvent> event = std::make_unique<FocusEvent>();
61 event->initialize(msg.body.focus.eventId, msg.body.focus.hasFocus);
62 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080063}
64
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070065std::unique_ptr<CaptureEvent> createCaptureEvent(const InputMessage& msg) {
66 std::unique_ptr<CaptureEvent> event = std::make_unique<CaptureEvent>();
67 event->initialize(msg.body.capture.eventId, msg.body.capture.pointerCaptureEnabled);
68 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080069}
70
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070071std::unique_ptr<DragEvent> createDragEvent(const InputMessage& msg) {
72 std::unique_ptr<DragEvent> event = std::make_unique<DragEvent>();
73 event->initialize(msg.body.drag.eventId, msg.body.drag.x, msg.body.drag.y,
74 msg.body.drag.isExiting);
75 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080076}
77
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070078std::unique_ptr<MotionEvent> createMotionEvent(const InputMessage& msg) {
79 std::unique_ptr<MotionEvent> event = std::make_unique<MotionEvent>();
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080080 const uint32_t pointerCount = msg.body.motion.pointerCount;
81 std::vector<PointerProperties> pointerProperties;
82 pointerProperties.reserve(pointerCount);
83 std::vector<PointerCoords> pointerCoords;
84 pointerCoords.reserve(pointerCount);
85 for (uint32_t i = 0; i < pointerCount; i++) {
86 pointerProperties.push_back(msg.body.motion.pointers[i].properties);
87 pointerCoords.push_back(msg.body.motion.pointers[i].coords);
88 }
89
90 ui::Transform transform;
91 transform.set({msg.body.motion.dsdx, msg.body.motion.dtdx, msg.body.motion.tx,
92 msg.body.motion.dtdy, msg.body.motion.dsdy, msg.body.motion.ty, 0, 0, 1});
93 ui::Transform displayTransform;
94 displayTransform.set({msg.body.motion.dsdxRaw, msg.body.motion.dtdxRaw, msg.body.motion.txRaw,
95 msg.body.motion.dtdyRaw, msg.body.motion.dsdyRaw, msg.body.motion.tyRaw,
96 0, 0, 1});
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070097 event->initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
Linnan Li13bf76a2024-05-05 19:18:02 +080098 ui::LogicalDisplayId{msg.body.motion.displayId}, msg.body.motion.hmac,
99 msg.body.motion.action, msg.body.motion.actionButton, msg.body.motion.flags,
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700100 msg.body.motion.edgeFlags, msg.body.motion.metaState,
101 msg.body.motion.buttonState, msg.body.motion.classification, transform,
102 msg.body.motion.xPrecision, msg.body.motion.yPrecision,
103 msg.body.motion.xCursorPosition, msg.body.motion.yCursorPosition,
104 displayTransform, msg.body.motion.downTime, msg.body.motion.eventTime,
105 pointerCount, pointerProperties.data(), pointerCoords.data());
106 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800107}
108
109void addSample(MotionEvent& event, const InputMessage& msg) {
110 uint32_t pointerCount = msg.body.motion.pointerCount;
111 std::vector<PointerCoords> pointerCoords;
112 pointerCoords.reserve(pointerCount);
113 for (uint32_t i = 0; i < pointerCount; i++) {
114 pointerCoords.push_back(msg.body.motion.pointers[i].coords);
115 }
116
117 // TODO(b/329770983): figure out if it's safe to combine events with mismatching metaState
118 event.setMetaState(event.getMetaState() | msg.body.motion.metaState);
jioana71c6f732024-07-16 15:42:56 +0000119 event.addSample(msg.body.motion.eventTime, pointerCoords.data(), msg.body.motion.eventId);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800120}
121
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700122std::unique_ptr<TouchModeEvent> createTouchModeEvent(const InputMessage& msg) {
123 std::unique_ptr<TouchModeEvent> event = std::make_unique<TouchModeEvent>();
124 event->initialize(msg.body.touchMode.eventId, msg.body.touchMode.isInTouchMode);
125 return event;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800126}
127
128std::string outboundMessageToString(const InputMessage& outboundMsg) {
129 switch (outboundMsg.header.type) {
130 case InputMessage::Type::FINISHED: {
131 return android::base::StringPrintf(" Finish: seq=%" PRIu32 " handled=%s",
132 outboundMsg.header.seq,
133 toString(outboundMsg.body.finished.handled));
134 }
135 case InputMessage::Type::TIMELINE: {
136 return android::base::
137 StringPrintf(" Timeline: inputEventId=%" PRId32 " gpuCompletedTime=%" PRId64
138 ", presentTime=%" PRId64,
139 outboundMsg.body.timeline.eventId,
140 outboundMsg.body.timeline
141 .graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME],
142 outboundMsg.body.timeline
143 .graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
144 }
145 default: {
146 LOG(FATAL) << "Outbound message must be FINISHED or TIMELINE, got "
147 << ftl::enum_string(outboundMsg.header.type);
148 return "Unreachable";
149 }
150 }
151}
152
153InputMessage createFinishedMessage(uint32_t seq, bool handled, nsecs_t consumeTime) {
154 InputMessage msg;
155 msg.header.type = InputMessage::Type::FINISHED;
156 msg.header.seq = seq;
157 msg.body.finished.handled = handled;
158 msg.body.finished.consumeTime = consumeTime;
159 return msg;
160}
161
162InputMessage createTimelineMessage(int32_t inputEventId, nsecs_t gpuCompletedTime,
163 nsecs_t presentTime) {
164 InputMessage msg;
165 msg.header.type = InputMessage::Type::TIMELINE;
166 msg.header.seq = 0;
167 msg.body.timeline.eventId = inputEventId;
168 msg.body.timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = gpuCompletedTime;
169 msg.body.timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = presentTime;
170 return msg;
171}
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800172} // namespace
173
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800174// --- InputConsumerNoResampling ---
175
Paul Ramireze37f8342024-08-28 18:42:21 +0000176InputConsumerNoResampling::InputConsumerNoResampling(
177 const std::shared_ptr<InputChannel>& channel, sp<Looper> looper,
178 InputConsumerCallbacks& callbacks,
179 std::function<std::unique_ptr<Resampler>()> resamplerCreator)
Paul Ramireze2bb1872024-08-12 20:21:13 +0000180 : mChannel{channel},
181 mLooper{looper},
Paul Ramirez87f1c012024-09-18 18:23:14 +0000182 mCallbacks{callbacks},
Paul Ramireze37f8342024-08-28 18:42:21 +0000183 mResamplerCreator{std::move(resamplerCreator)},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000184 mFdEvents(0) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800185 LOG_ALWAYS_FATAL_IF(mLooper == nullptr);
186 mCallback = sp<LooperEventCallback>::make(
187 std::bind(&InputConsumerNoResampling::handleReceiveCallback, this,
188 std::placeholders::_1));
189 // In the beginning, there are no pending outbounds events; we only care about receiving
190 // incoming data.
191 setFdEvents(ALOOPER_EVENT_INPUT);
192}
193
194InputConsumerNoResampling::~InputConsumerNoResampling() {
195 ensureCalledOnLooperThread(__func__);
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000196 consumeBatchedInputEvents(/*requestedFrameTime=*/std::nullopt);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800197 while (!mOutboundQueue.empty()) {
198 processOutboundEvents();
199 // This is our last chance to ack the events. If we don't ack them here, we will get an ANR,
200 // so keep trying to send the events as long as they are present in the queue.
201 }
202 setFdEvents(0);
203}
204
205int InputConsumerNoResampling::handleReceiveCallback(int events) {
206 // Allowed return values of this function as documented in LooperCallback::handleEvent
207 constexpr int REMOVE_CALLBACK = 0;
208 constexpr int KEEP_CALLBACK = 1;
209
210 if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
211 // This error typically occurs when the publisher has closed the input channel
212 // as part of removing a window or finishing an IME session, in which case
213 // the consumer will soon be disposed as well.
214 if (DEBUG_TRANSPORT_CONSUMER) {
215 LOG(INFO) << "The channel was hung up or an error occurred: " << mChannel->getName();
216 }
217 return REMOVE_CALLBACK;
218 }
219
220 int handledEvents = 0;
221 if (events & ALOOPER_EVENT_INPUT) {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000222 handleMessages(readAllMessages());
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800223 handledEvents |= ALOOPER_EVENT_INPUT;
224 }
225
226 if (events & ALOOPER_EVENT_OUTPUT) {
227 processOutboundEvents();
228 handledEvents |= ALOOPER_EVENT_OUTPUT;
229 }
230 if (handledEvents != events) {
231 LOG(FATAL) << "Mismatch: handledEvents=" << handledEvents << ", events=" << events;
232 }
233 return KEEP_CALLBACK;
234}
235
236void InputConsumerNoResampling::processOutboundEvents() {
237 while (!mOutboundQueue.empty()) {
238 const InputMessage& outboundMsg = mOutboundQueue.front();
239
240 const status_t result = mChannel->sendMessage(&outboundMsg);
241 if (result == OK) {
242 if (outboundMsg.header.type == InputMessage::Type::FINISHED) {
243 ATRACE_ASYNC_END("InputConsumer processing", /*cookie=*/outboundMsg.header.seq);
244 }
245 // Successful send. Erase the entry and keep trying to send more
246 mOutboundQueue.pop();
247 continue;
248 }
249
250 // Publisher is busy, try again later. Keep this entry (do not erase)
251 if (result == WOULD_BLOCK) {
252 setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
253 return; // try again later
254 }
255
256 // Some other error. Give up
257 LOG(FATAL) << "Failed to send outbound event on channel '" << mChannel->getName()
258 << "'. status=" << statusToString(result) << "(" << result << ")";
259 }
260
261 // The queue is now empty. Tell looper there's no more output to expect.
262 setFdEvents(ALOOPER_EVENT_INPUT);
263}
264
265void InputConsumerNoResampling::finishInputEvent(uint32_t seq, bool handled) {
266 ensureCalledOnLooperThread(__func__);
267 mOutboundQueue.push(createFinishedMessage(seq, handled, popConsumeTime(seq)));
268 // also produce finish events for all batches for this seq (if any)
269 const auto it = mBatchedSequenceNumbers.find(seq);
270 if (it != mBatchedSequenceNumbers.end()) {
271 for (uint32_t subSeq : it->second) {
272 mOutboundQueue.push(createFinishedMessage(subSeq, handled, popConsumeTime(subSeq)));
273 }
274 mBatchedSequenceNumbers.erase(it);
275 }
276 processOutboundEvents();
277}
278
279bool InputConsumerNoResampling::probablyHasInput() const {
280 // Ideally, this would only be allowed to run on the looper thread, and in production, it will.
281 // However, for testing, it's convenient to call this while the looper thread is blocked, so
282 // we do not call ensureCalledOnLooperThread here.
283 return (!mBatches.empty()) || mChannel->probablyHasInput();
284}
285
286void InputConsumerNoResampling::reportTimeline(int32_t inputEventId, nsecs_t gpuCompletedTime,
287 nsecs_t presentTime) {
288 ensureCalledOnLooperThread(__func__);
289 mOutboundQueue.push(createTimelineMessage(inputEventId, gpuCompletedTime, presentTime));
290 processOutboundEvents();
291}
292
293nsecs_t InputConsumerNoResampling::popConsumeTime(uint32_t seq) {
294 auto it = mConsumeTimes.find(seq);
295 // Consume time will be missing if either 'finishInputEvent' is called twice, or if it was
296 // called for the wrong (synthetic?) input event. Either way, it is a bug that should be fixed.
297 LOG_ALWAYS_FATAL_IF(it == mConsumeTimes.end(), "Could not find consume time for seq=%" PRIu32,
298 seq);
299 nsecs_t consumeTime = it->second;
300 mConsumeTimes.erase(it);
301 return consumeTime;
302}
303
304void InputConsumerNoResampling::setFdEvents(int events) {
305 if (mFdEvents != events) {
306 mFdEvents = events;
307 if (events != 0) {
308 mLooper->addFd(mChannel->getFd(), 0, events, mCallback, nullptr);
309 } else {
310 mLooper->removeFd(mChannel->getFd());
311 }
312 }
313}
314
315void InputConsumerNoResampling::handleMessages(std::vector<InputMessage>&& messages) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800316 for (const InputMessage& msg : messages) {
317 if (msg.header.type == InputMessage::Type::MOTION) {
318 const int32_t action = msg.body.motion.action;
319 const DeviceId deviceId = msg.body.motion.deviceId;
320 const int32_t source = msg.body.motion.source;
321 const bool batchableEvent = (action == AMOTION_EVENT_ACTION_MOVE ||
322 action == AMOTION_EVENT_ACTION_HOVER_MOVE) &&
323 (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER) ||
324 isFromSource(source, AINPUT_SOURCE_CLASS_JOYSTICK));
Paul Ramireze37f8342024-08-28 18:42:21 +0000325
326 const bool canResample = (mResamplerCreator != nullptr) &&
327 (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER));
328 if (canResample) {
329 if (action == AMOTION_EVENT_ACTION_DOWN) {
330 if (std::unique_ptr<Resampler> resampler = mResamplerCreator();
331 resampler != nullptr) {
332 const auto [_, inserted] =
333 mResamplers.insert(std::pair(deviceId, std::move(resampler)));
334 LOG_IF(WARNING, !inserted) << deviceId << "already exists in mResamplers";
335 }
336 }
337 }
338
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800339 if (batchableEvent) {
340 // add it to batch
341 mBatches[deviceId].emplace(msg);
342 } else {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000343 // consume all pending batches for this device immediately
344 consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/std::nullopt);
Paul Ramireze37f8342024-08-28 18:42:21 +0000345 if (canResample &&
346 (action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL)) {
347 LOG_IF(INFO, mResamplers.erase(deviceId) == 0)
348 << deviceId << "does not exist in mResamplers";
349 }
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800350 handleMessage(msg);
351 }
352 } else {
353 // Non-motion events shouldn't force the consumption of pending batched events
354 handleMessage(msg);
355 }
356 }
357 // At the end of this, if we still have pending batches, notify the receiver about it.
358
359 // We need to carefully notify the InputConsumerCallbacks about the pending batch. The receiver
360 // could choose to consume all events when notified about the batch. That means that the
361 // "mBatches" variable could change when 'InputConsumerCallbacks::onBatchedInputEventPending' is
362 // invoked. We also can't notify the InputConsumerCallbacks in a while loop until mBatches is
363 // empty, because the receiver could choose to not consume the batch immediately.
364 std::set<int32_t> pendingBatchSources;
365 for (const auto& [_, pendingMessages] : mBatches) {
366 // Assume that all messages for a given device has the same source.
367 pendingBatchSources.insert(pendingMessages.front().body.motion.source);
368 }
369 for (const int32_t source : pendingBatchSources) {
370 const bool sourceStillRemaining =
371 std::any_of(mBatches.begin(), mBatches.end(), [=](const auto& pair) {
372 return pair.second.front().body.motion.source == source;
373 });
374 if (sourceStillRemaining) {
375 mCallbacks.onBatchedInputEventPending(source);
376 }
377 }
378}
379
380std::vector<InputMessage> InputConsumerNoResampling::readAllMessages() {
381 std::vector<InputMessage> messages;
382 while (true) {
Paul Ramirez0c25e862024-06-18 21:33:33 +0000383 android::base::Result<InputMessage> result = mChannel->receiveMessage();
384 if (result.ok()) {
385 const InputMessage& msg = *result;
386 const auto [_, inserted] =
387 mConsumeTimes.emplace(msg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
388 LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
389 msg.header.seq);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800390
Paul Ramirez0c25e862024-06-18 21:33:33 +0000391 // Trace the event processing timeline - event was just read from the socket
392 // TODO(b/329777420): distinguish between multiple instances of InputConsumer
393 // in the same process.
394 ATRACE_ASYNC_BEGIN("InputConsumer processing", /*cookie=*/msg.header.seq);
395 messages.push_back(msg);
396 } else { // !result.ok()
397 switch (result.error().code()) {
398 case WOULD_BLOCK: {
399 return messages;
400 }
401 case DEAD_OBJECT: {
402 LOG(FATAL) << "Got a dead object for " << mChannel->getName();
403 break;
404 }
405 case BAD_VALUE: {
406 LOG(FATAL) << "Got a bad value for " << mChannel->getName();
407 break;
408 }
409 default: {
410 LOG(FATAL) << "Unexpected error: " << result.error().message();
411 break;
412 }
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800413 }
414 }
415 }
416}
417
418void InputConsumerNoResampling::handleMessage(const InputMessage& msg) const {
419 switch (msg.header.type) {
420 case InputMessage::Type::KEY: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700421 std::unique_ptr<KeyEvent> keyEvent = createKeyEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800422 mCallbacks.onKeyEvent(std::move(keyEvent), msg.header.seq);
423 break;
424 }
425
426 case InputMessage::Type::MOTION: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700427 std::unique_ptr<MotionEvent> motionEvent = createMotionEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800428 mCallbacks.onMotionEvent(std::move(motionEvent), msg.header.seq);
429 break;
430 }
431
432 case InputMessage::Type::FINISHED:
433 case InputMessage::Type::TIMELINE: {
Siarhei Vishniakou11d223b2024-03-26 21:52:38 +0000434 LOG(FATAL) << "Consumed a " << ftl::enum_string(msg.header.type)
435 << " message, which should never be seen by InputConsumer on "
436 << mChannel->getName();
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800437 break;
438 }
439
440 case InputMessage::Type::FOCUS: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700441 std::unique_ptr<FocusEvent> focusEvent = createFocusEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800442 mCallbacks.onFocusEvent(std::move(focusEvent), msg.header.seq);
443 break;
444 }
445
446 case InputMessage::Type::CAPTURE: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700447 std::unique_ptr<CaptureEvent> captureEvent = createCaptureEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800448 mCallbacks.onCaptureEvent(std::move(captureEvent), msg.header.seq);
449 break;
450 }
451
452 case InputMessage::Type::DRAG: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700453 std::unique_ptr<DragEvent> dragEvent = createDragEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800454 mCallbacks.onDragEvent(std::move(dragEvent), msg.header.seq);
455 break;
456 }
457
458 case InputMessage::Type::TOUCH_MODE: {
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700459 std::unique_ptr<TouchModeEvent> touchModeEvent = createTouchModeEvent(msg);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800460 mCallbacks.onTouchModeEvent(std::move(touchModeEvent), msg.header.seq);
461 break;
462 }
463 }
464}
465
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000466std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>>
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000467InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrameTime,
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000468 std::queue<InputMessage>& messages) {
469 std::unique_ptr<MotionEvent> motionEvent;
470 std::optional<uint32_t> firstSeqForBatch;
Paul Ramireze37f8342024-08-28 18:42:21 +0000471
472 LOG_IF(FATAL, messages.empty()) << "messages queue is empty!";
473 const DeviceId deviceId = messages.front().body.motion.deviceId;
474 const auto resampler = mResamplers.find(deviceId);
475 const nanoseconds resampleLatency = (resampler != mResamplers.cend())
476 ? resampler->second->getResampleLatency()
477 : nanoseconds{0};
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000478 const nanoseconds adjustedFrameTime = nanoseconds{requestedFrameTime} - resampleLatency;
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000479
480 while (!messages.empty() &&
481 (messages.front().body.motion.eventTime <= adjustedFrameTime.count())) {
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000482 if (motionEvent == nullptr) {
483 motionEvent = createMotionEvent(messages.front());
484 firstSeqForBatch = messages.front().header.seq;
485 const auto [_, inserted] = mBatchedSequenceNumbers.insert({*firstSeqForBatch, {}});
486 LOG_IF(FATAL, !inserted)
487 << "The sequence " << messages.front().header.seq << " was already present!";
488 } else {
489 addSample(*motionEvent, messages.front());
490 mBatchedSequenceNumbers[*firstSeqForBatch].push_back(messages.front().header.seq);
491 }
492 messages.pop();
493 }
Paul Ramireze37f8342024-08-28 18:42:21 +0000494
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000495 // Check if resampling should be performed.
Paul Ramireze37f8342024-08-28 18:42:21 +0000496 InputMessage* futureSample = nullptr;
497 if (!messages.empty()) {
498 futureSample = &messages.front();
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000499 }
Paul Ramireze37f8342024-08-28 18:42:21 +0000500 if ((motionEvent != nullptr) && (resampler != mResamplers.cend())) {
501 resampler->second->resampleMotionEvent(nanoseconds{requestedFrameTime}, *motionEvent,
502 futureSample);
503 }
504
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000505 return std::make_pair(std::move(motionEvent), firstSeqForBatch);
506}
507
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800508bool InputConsumerNoResampling::consumeBatchedInputEvents(
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000509 std::optional<DeviceId> deviceId, std::optional<nsecs_t> requestedFrameTime) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800510 ensureCalledOnLooperThread(__func__);
511 // When batching is not enabled, we want to consume all events. That's equivalent to having an
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000512 // infinite requestedFrameTime.
513 requestedFrameTime = requestedFrameTime.value_or(std::numeric_limits<nsecs_t>::max());
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800514 bool producedEvents = false;
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000515
516 for (auto deviceIdIter = (deviceId.has_value()) ? (mBatches.find(*deviceId))
517 : (mBatches.begin());
518 deviceIdIter != mBatches.cend(); ++deviceIdIter) {
519 std::queue<InputMessage>& messages = deviceIdIter->second;
520 auto [motion, firstSeqForBatch] = createBatchedMotionEvent(*requestedFrameTime, messages);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700521 if (motion != nullptr) {
522 LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value());
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800523 mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch);
524 producedEvents = true;
525 } else {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000526 // This is OK, it just means that the requestedFrameTime is too old (all events that we
527 // have pending are in the future of the requestedFrameTime). Maybe print a warning? If
528 // there are multiple devices active though, this might be normal and can just be
529 // ignored, unless none of them resulted in any consumption (in that case, this function
530 // would already return "false" so we could just leave it up to the caller).
531 }
532
533 if (deviceId.has_value()) {
534 // We already consumed events for this device. Break here to prevent iterating over the
535 // other devices.
536 break;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800537 }
538 }
539 std::erase_if(mBatches, [](const auto& pair) { return pair.second.empty(); });
540 return producedEvents;
541}
542
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000543bool InputConsumerNoResampling::consumeBatchedInputEvents(
544 std::optional<nsecs_t> requestedFrameTime) {
545 return consumeBatchedInputEvents(/*deviceId=*/std::nullopt, requestedFrameTime);
546}
547
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800548void InputConsumerNoResampling::ensureCalledOnLooperThread(const char* func) const {
549 sp<Looper> callingThreadLooper = Looper::getForThread();
Paul Ramirez87f1c012024-09-18 18:23:14 +0000550 if (callingThreadLooper != mLooper) {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800551 LOG(FATAL) << "The function " << func << " can only be called on the looper thread";
552 }
553}
554
555std::string InputConsumerNoResampling::dump() const {
556 ensureCalledOnLooperThread(__func__);
557 std::string out;
558 if (mOutboundQueue.empty()) {
559 out += "mOutboundQueue: <empty>\n";
560 } else {
561 out += "mOutboundQueue:\n";
562 // Make a copy of mOutboundQueue for printing destructively. Unfortunately std::queue
563 // doesn't provide a good way to iterate over the entire container.
564 std::queue<InputMessage> tmpQueue = mOutboundQueue;
565 while (!tmpQueue.empty()) {
566 out += std::string(" ") + outboundMessageToString(tmpQueue.front()) + "\n";
567 tmpQueue.pop();
568 }
569 }
570
571 if (mBatches.empty()) {
572 out += "mBatches: <empty>\n";
573 } else {
574 out += "mBatches:\n";
575 for (const auto& [deviceId, messages] : mBatches) {
576 out += " Device id ";
577 out += std::to_string(deviceId);
578 out += ":\n";
579 // Make a copy of mOutboundQueue for printing destructively. Unfortunately std::queue
580 // doesn't provide a good way to iterate over the entire container.
581 std::queue<InputMessage> tmpQueue = messages;
582 while (!tmpQueue.empty()) {
583 LOG_ALWAYS_FATAL_IF(tmpQueue.front().header.type != InputMessage::Type::MOTION);
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700584 std::unique_ptr<MotionEvent> motion = createMotionEvent(tmpQueue.front());
585 out += std::string(" ") + streamableToString(*motion) + "\n";
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800586 tmpQueue.pop();
587 }
588 }
589 }
590
591 return out;
592}
593
594} // namespace android