blob: f9fa420ea9e54b8dcd731380aac2f787f05524c8 [file] [log] [blame]
Jeff Brown5912f952013-07-01 19:10:31 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// Provides a shared memory transport for input events.
5//
6#define LOG_TAG "InputTransport"
Zimd8402b62023-06-02 11:56:26 +01007#define ATRACE_TAG ATRACE_TAG_INPUT
Jeff Brown5912f952013-07-01 19:10:31 -07008
Jeff Brown5912f952013-07-01 19:10:31 -07009#include <errno.h>
10#include <fcntl.h>
Michael Wrightd0a4a622014-06-09 19:03:32 -070011#include <inttypes.h>
Jeff Brown5912f952013-07-01 19:10:31 -070012#include <math.h>
Egor Paskoa0d32af2023-12-14 17:45:41 +010013#include <poll.h>
Jeff Brown5912f952013-07-01 19:10:31 -070014#include <sys/socket.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070015#include <sys/types.h>
Jeff Brown5912f952013-07-01 19:10:31 -070016#include <unistd.h>
17
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070018#include <android-base/logging.h>
Prabir Pradhanb2bd83c2023-02-23 02:34:40 +000019#include <android-base/properties.h>
Michael Wright3dd60e22019-03-27 22:06:44 +000020#include <android-base/stringprintf.h>
21#include <binder/Parcel.h>
Jeff Brown5912f952013-07-01 19:10:31 -070022#include <cutils/properties.h>
Dominik Laskowski75788452021-02-09 18:51:25 -080023#include <ftl/enum.h>
Mark Salyzyn7823e122016-09-29 08:08:05 -070024#include <log/log.h>
Michael Wright3dd60e22019-03-27 22:06:44 +000025#include <utils/Trace.h>
Mark Salyzyn7823e122016-09-29 08:08:05 -070026
Siarhei Vishniakou96818962023-08-23 10:19:02 -070027#include <com_android_input_flags.h>
Jeff Brown5912f952013-07-01 19:10:31 -070028#include <input/InputTransport.h>
Prabir Pradhana37bad12023-08-18 15:55:32 +000029#include <input/TraceTools.h>
Jeff Brown5912f952013-07-01 19:10:31 -070030
Siarhei Vishniakou96818962023-08-23 10:19:02 -070031namespace input_flags = com::android::input::flags;
32
Siarhei Vishniakou9dbf6372024-03-06 16:08:01 -080033namespace android {
34
Prabir Pradhan60dd97a2023-02-23 02:23:02 +000035namespace {
36
37/**
38 * Log debug messages about channel messages (send message, receive message).
39 * Enable this via "adb shell setprop log.tag.InputTransportMessages DEBUG"
40 * (requires restart)
41 */
42const bool DEBUG_CHANNEL_MESSAGES =
43 __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Messages", ANDROID_LOG_INFO);
44
45/**
46 * Log debug messages whenever InputChannel objects are created/destroyed.
47 * Enable this via "adb shell setprop log.tag.InputTransportLifecycle DEBUG"
48 * (requires restart)
49 */
50const bool DEBUG_CHANNEL_LIFECYCLE =
51 __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Lifecycle", ANDROID_LOG_INFO);
52
53/**
54 * Log debug messages relating to the consumer end of the transport channel.
55 * Enable this via "adb shell setprop log.tag.InputTransportConsumer DEBUG" (requires restart)
56 */
57
58const bool DEBUG_TRANSPORT_CONSUMER =
59 __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Consumer", ANDROID_LOG_INFO);
60
Prabir Pradhanb2bd83c2023-02-23 02:34:40 +000061const bool IS_DEBUGGABLE_BUILD =
62#if defined(__ANDROID__)
63 android::base::GetBoolProperty("ro.debuggable", false);
64#else
65 true;
66#endif
67
Prabir Pradhan60dd97a2023-02-23 02:23:02 +000068/**
69 * Log debug messages relating to the producer end of the transport channel.
Prabir Pradhanb2bd83c2023-02-23 02:34:40 +000070 * Enable this via "adb shell setprop log.tag.InputTransportPublisher DEBUG".
71 * This requires a restart on non-debuggable (e.g. user) builds, but should take effect immediately
72 * on debuggable builds (e.g. userdebug).
Prabir Pradhan60dd97a2023-02-23 02:23:02 +000073 */
Prabir Pradhanb2bd83c2023-02-23 02:34:40 +000074bool debugTransportPublisher() {
75 if (!IS_DEBUGGABLE_BUILD) {
76 static const bool DEBUG_TRANSPORT_PUBLISHER =
77 __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Publisher", ANDROID_LOG_INFO);
78 return DEBUG_TRANSPORT_PUBLISHER;
79 }
80 return __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Publisher", ANDROID_LOG_INFO);
81}
Prabir Pradhan60dd97a2023-02-23 02:23:02 +000082
83/**
84 * Log debug messages about touch event resampling.
Harry Cutts6c658cc2023-08-02 14:40:40 +000085 *
86 * Enable this via "adb shell setprop log.tag.InputTransportResampling DEBUG".
87 * This requires a restart on non-debuggable (e.g. user) builds, but should take effect immediately
88 * on debuggable builds (e.g. userdebug).
Prabir Pradhan60dd97a2023-02-23 02:23:02 +000089 */
Harry Cutts6c658cc2023-08-02 14:40:40 +000090bool debugResampling() {
91 if (!IS_DEBUGGABLE_BUILD) {
92 static const bool DEBUG_TRANSPORT_RESAMPLING =
93 __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Resampling",
94 ANDROID_LOG_INFO);
95 return DEBUG_TRANSPORT_RESAMPLING;
96 }
97 return __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Resampling", ANDROID_LOG_INFO);
98}
Prabir Pradhan60dd97a2023-02-23 02:23:02 +000099
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800100android::base::unique_fd dupChannelFd(int fd) {
101 android::base::unique_fd newFd(::dup(fd));
102 if (!newFd.ok()) {
103 ALOGE("Could not duplicate fd %i : %s", fd, strerror(errno));
104 const bool hitFdLimit = errno == EMFILE || errno == ENFILE;
105 // If this process is out of file descriptors, then throwing that might end up exploding
106 // on the other side of a binder call, which isn't really helpful.
107 // Better to just crash here and hope that the FD leak is slow.
108 // Other failures could be client errors, so we still propagate those back to the caller.
109 LOG_ALWAYS_FATAL_IF(hitFdLimit, "Too many open files, could not duplicate input channel");
110 return {};
111 }
112 return newFd;
113}
114
Siarhei Vishniakou9dbf6372024-03-06 16:08:01 -0800115void initializeKeyEvent(KeyEvent& event, const InputMessage& msg) {
116 event.initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
117 msg.body.key.displayId, msg.body.key.hmac, msg.body.key.action,
118 msg.body.key.flags, msg.body.key.keyCode, msg.body.key.scanCode,
119 msg.body.key.metaState, msg.body.key.repeatCount, msg.body.key.downTime,
120 msg.body.key.eventTime);
121}
122
123void initializeFocusEvent(FocusEvent& event, const InputMessage& msg) {
124 event.initialize(msg.body.focus.eventId, msg.body.focus.hasFocus);
125}
126
127void initializeCaptureEvent(CaptureEvent& event, const InputMessage& msg) {
128 event.initialize(msg.body.capture.eventId, msg.body.capture.pointerCaptureEnabled);
129}
130
131void initializeDragEvent(DragEvent& event, const InputMessage& msg) {
132 event.initialize(msg.body.drag.eventId, msg.body.drag.x, msg.body.drag.y,
133 msg.body.drag.isExiting);
134}
135
136void initializeMotionEvent(MotionEvent& event, const InputMessage& msg) {
137 uint32_t pointerCount = msg.body.motion.pointerCount;
138 PointerProperties pointerProperties[pointerCount];
139 PointerCoords pointerCoords[pointerCount];
140 for (uint32_t i = 0; i < pointerCount; i++) {
141 pointerProperties[i] = msg.body.motion.pointers[i].properties;
142 pointerCoords[i] = msg.body.motion.pointers[i].coords;
143 }
144
145 ui::Transform transform;
146 transform.set({msg.body.motion.dsdx, msg.body.motion.dtdx, msg.body.motion.tx,
147 msg.body.motion.dtdy, msg.body.motion.dsdy, msg.body.motion.ty, 0, 0, 1});
148 ui::Transform displayTransform;
149 displayTransform.set({msg.body.motion.dsdxRaw, msg.body.motion.dtdxRaw, msg.body.motion.txRaw,
150 msg.body.motion.dtdyRaw, msg.body.motion.dsdyRaw, msg.body.motion.tyRaw,
151 0, 0, 1});
152 event.initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
153 msg.body.motion.displayId, msg.body.motion.hmac, msg.body.motion.action,
154 msg.body.motion.actionButton, msg.body.motion.flags, msg.body.motion.edgeFlags,
155 msg.body.motion.metaState, msg.body.motion.buttonState,
156 msg.body.motion.classification, transform, msg.body.motion.xPrecision,
157 msg.body.motion.yPrecision, msg.body.motion.xCursorPosition,
158 msg.body.motion.yCursorPosition, displayTransform, msg.body.motion.downTime,
159 msg.body.motion.eventTime, pointerCount, pointerProperties, pointerCoords);
160}
161
162void addSample(MotionEvent& event, const InputMessage& msg) {
163 uint32_t pointerCount = msg.body.motion.pointerCount;
164 PointerCoords pointerCoords[pointerCount];
165 for (uint32_t i = 0; i < pointerCount; i++) {
166 pointerCoords[i] = msg.body.motion.pointers[i].coords;
167 }
168
169 event.setMetaState(event.getMetaState() | msg.body.motion.metaState);
170 event.addSample(msg.body.motion.eventTime, pointerCoords);
171}
172
173void initializeTouchModeEvent(TouchModeEvent& event, const InputMessage& msg) {
174 event.initialize(msg.body.touchMode.eventId, msg.body.touchMode.isInTouchMode);
175}
176
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000177} // namespace
178
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -0700179using android::base::Result;
Michael Wright3dd60e22019-03-27 22:06:44 +0000180using android::base::StringPrintf;
181
Jeff Brown5912f952013-07-01 19:10:31 -0700182// Socket buffer size. The default is typically about 128KB, which is much larger than
183// we really need. So we make it smaller. It just needs to be big enough to hold
184// a few dozen large multi-finger motion events in the case where an application gets
185// behind processing touches.
186static const size_t SOCKET_BUFFER_SIZE = 32 * 1024;
187
188// Nanoseconds per milliseconds.
189static const nsecs_t NANOS_PER_MS = 1000000;
190
191// Latency added during resampling. A few milliseconds doesn't hurt much but
192// reduces the impact of mispredicted touch positions.
Siarhei Vishniakou0ced3cc2017-11-21 15:33:17 -0800193const std::chrono::duration RESAMPLE_LATENCY = 5ms;
Jeff Brown5912f952013-07-01 19:10:31 -0700194
195// Minimum time difference between consecutive samples before attempting to resample.
196static const nsecs_t RESAMPLE_MIN_DELTA = 2 * NANOS_PER_MS;
197
Andrew de los Reyesde18f6c2015-10-01 15:57:25 -0700198// Maximum time difference between consecutive samples before attempting to resample
199// by extrapolation.
200static const nsecs_t RESAMPLE_MAX_DELTA = 20 * NANOS_PER_MS;
201
Jeff Brown5912f952013-07-01 19:10:31 -0700202// Maximum time to predict forward from the last known state, to avoid predicting too
203// far into the future. This time is further bounded by 50% of the last time delta.
204static const nsecs_t RESAMPLE_MAX_PREDICTION = 8 * NANOS_PER_MS;
205
Siarhei Vishniakoub5433e92019-02-21 09:27:39 -0600206/**
207 * System property for enabling / disabling touch resampling.
208 * Resampling extrapolates / interpolates the reported touch event coordinates to better
209 * align them to the VSYNC signal, thus resulting in smoother scrolling performance.
210 * Resampling is not needed (and should be disabled) on hardware that already
211 * has touch events triggered by VSYNC.
212 * Set to "1" to enable resampling (default).
213 * Set to "0" to disable resampling.
214 * Resampling is enabled by default.
215 */
216static const char* PROPERTY_RESAMPLING_ENABLED = "ro.input.resampling";
217
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -0800218/**
219 * Crash if the events that are getting sent to the InputPublisher are inconsistent.
220 * Enable this via "adb shell setprop log.tag.InputTransportVerifyEvents DEBUG"
221 */
222static bool verifyEvents() {
Siarhei Vishniakou96818962023-08-23 10:19:02 -0700223 return input_flags::enable_outbound_event_verification() ||
224 __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "VerifyEvents", ANDROID_LOG_INFO);
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -0800225}
226
Jeff Brown5912f952013-07-01 19:10:31 -0700227template<typename T>
228inline static T min(const T& a, const T& b) {
229 return a < b ? a : b;
230}
231
232inline static float lerp(float a, float b, float alpha) {
233 return a + alpha * (b - a);
234}
235
Siarhei Vishniakou128eab12019-05-23 10:25:59 +0800236inline static bool isPointerEvent(int32_t source) {
237 return (source & AINPUT_SOURCE_CLASS_POINTER) == AINPUT_SOURCE_CLASS_POINTER;
238}
239
Siarhei Vishniakou3b37f9a2019-11-23 13:42:41 -0800240inline static const char* toString(bool value) {
241 return value ? "true" : "false";
242}
243
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700244static bool shouldResampleTool(ToolType toolType) {
245 return toolType == ToolType::FINGER || toolType == ToolType::UNKNOWN;
246}
247
Jeff Brown5912f952013-07-01 19:10:31 -0700248// --- InputMessage ---
249
250bool InputMessage::isValid(size_t actualSize) const {
Siarhei Vishniakoudbdb6732021-04-26 19:40:26 +0000251 if (size() != actualSize) {
252 ALOGE("Received message of incorrect size %zu (expected %zu)", actualSize, size());
253 return false;
254 }
255
256 switch (header.type) {
257 case Type::KEY:
258 return true;
259 case Type::MOTION: {
260 const bool valid =
261 body.motion.pointerCount > 0 && body.motion.pointerCount <= MAX_POINTERS;
262 if (!valid) {
263 ALOGE("Received invalid MOTION: pointerCount = %" PRIu32, body.motion.pointerCount);
264 }
265 return valid;
266 }
267 case Type::FINISHED:
268 case Type::FOCUS:
269 case Type::CAPTURE:
270 case Type::DRAG:
Antonio Kantek7cdf8ef2021-07-13 18:04:53 -0700271 case Type::TOUCH_MODE:
Siarhei Vishniakoudbdb6732021-04-26 19:40:26 +0000272 return true;
273 case Type::TIMELINE: {
274 const nsecs_t gpuCompletedTime =
275 body.timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME];
276 const nsecs_t presentTime =
277 body.timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME];
278 const bool valid = presentTime > gpuCompletedTime;
279 if (!valid) {
280 ALOGE("Received invalid TIMELINE: gpuCompletedTime = %" PRId64
281 " presentTime = %" PRId64,
282 gpuCompletedTime, presentTime);
283 }
284 return valid;
Jeff Brown5912f952013-07-01 19:10:31 -0700285 }
286 }
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000287 ALOGE("Invalid message type: %s", ftl::enum_string(header.type).c_str());
Jeff Brown5912f952013-07-01 19:10:31 -0700288 return false;
289}
290
291size_t InputMessage::size() const {
292 switch (header.type) {
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700293 case Type::KEY:
294 return sizeof(Header) + body.key.size();
295 case Type::MOTION:
296 return sizeof(Header) + body.motion.size();
297 case Type::FINISHED:
298 return sizeof(Header) + body.finished.size();
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800299 case Type::FOCUS:
300 return sizeof(Header) + body.focus.size();
Prabir Pradhan3f37b7b2020-11-10 16:50:18 -0800301 case Type::CAPTURE:
302 return sizeof(Header) + body.capture.size();
arthurhung7632c332020-12-30 16:58:01 +0800303 case Type::DRAG:
304 return sizeof(Header) + body.drag.size();
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000305 case Type::TIMELINE:
306 return sizeof(Header) + body.timeline.size();
Antonio Kantek7cdf8ef2021-07-13 18:04:53 -0700307 case Type::TOUCH_MODE:
308 return sizeof(Header) + body.touchMode.size();
Jeff Brown5912f952013-07-01 19:10:31 -0700309 }
310 return sizeof(Header);
311}
312
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800313/**
314 * There could be non-zero bytes in-between InputMessage fields. Force-initialize the entire
315 * memory to zero, then only copy the valid bytes on a per-field basis.
316 */
317void InputMessage::getSanitizedCopy(InputMessage* msg) const {
318 memset(msg, 0, sizeof(*msg));
319
320 // Write the header
321 msg->header.type = header.type;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -0500322 msg->header.seq = header.seq;
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800323
324 // Write the body
325 switch(header.type) {
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700326 case InputMessage::Type::KEY: {
Garfield Tan1c7bc862020-01-28 13:24:04 -0800327 // int32_t eventId
328 msg->body.key.eventId = body.key.eventId;
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800329 // nsecs_t eventTime
330 msg->body.key.eventTime = body.key.eventTime;
331 // int32_t deviceId
332 msg->body.key.deviceId = body.key.deviceId;
333 // int32_t source
334 msg->body.key.source = body.key.source;
335 // int32_t displayId
336 msg->body.key.displayId = body.key.displayId;
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600337 // std::array<uint8_t, 32> hmac
338 msg->body.key.hmac = body.key.hmac;
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800339 // int32_t action
340 msg->body.key.action = body.key.action;
341 // int32_t flags
342 msg->body.key.flags = body.key.flags;
343 // int32_t keyCode
344 msg->body.key.keyCode = body.key.keyCode;
345 // int32_t scanCode
346 msg->body.key.scanCode = body.key.scanCode;
347 // int32_t metaState
348 msg->body.key.metaState = body.key.metaState;
349 // int32_t repeatCount
350 msg->body.key.repeatCount = body.key.repeatCount;
351 // nsecs_t downTime
352 msg->body.key.downTime = body.key.downTime;
353 break;
354 }
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700355 case InputMessage::Type::MOTION: {
Garfield Tan1c7bc862020-01-28 13:24:04 -0800356 // int32_t eventId
357 msg->body.motion.eventId = body.motion.eventId;
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700358 // uint32_t pointerCount
359 msg->body.motion.pointerCount = body.motion.pointerCount;
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800360 // nsecs_t eventTime
361 msg->body.motion.eventTime = body.motion.eventTime;
362 // int32_t deviceId
363 msg->body.motion.deviceId = body.motion.deviceId;
364 // int32_t source
365 msg->body.motion.source = body.motion.source;
366 // int32_t displayId
367 msg->body.motion.displayId = body.motion.displayId;
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600368 // std::array<uint8_t, 32> hmac
369 msg->body.motion.hmac = body.motion.hmac;
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800370 // int32_t action
371 msg->body.motion.action = body.motion.action;
372 // int32_t actionButton
373 msg->body.motion.actionButton = body.motion.actionButton;
374 // int32_t flags
375 msg->body.motion.flags = body.motion.flags;
376 // int32_t metaState
377 msg->body.motion.metaState = body.motion.metaState;
378 // int32_t buttonState
379 msg->body.motion.buttonState = body.motion.buttonState;
Siarhei Vishniakou16a2e302019-01-14 19:21:45 -0800380 // MotionClassification classification
381 msg->body.motion.classification = body.motion.classification;
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800382 // int32_t edgeFlags
383 msg->body.motion.edgeFlags = body.motion.edgeFlags;
384 // nsecs_t downTime
385 msg->body.motion.downTime = body.motion.downTime;
chaviw9eaa22c2020-07-01 16:21:27 -0700386
387 msg->body.motion.dsdx = body.motion.dsdx;
388 msg->body.motion.dtdx = body.motion.dtdx;
389 msg->body.motion.dtdy = body.motion.dtdy;
390 msg->body.motion.dsdy = body.motion.dsdy;
391 msg->body.motion.tx = body.motion.tx;
392 msg->body.motion.ty = body.motion.ty;
393
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800394 // float xPrecision
395 msg->body.motion.xPrecision = body.motion.xPrecision;
396 // float yPrecision
397 msg->body.motion.yPrecision = body.motion.yPrecision;
Garfield Tan00f511d2019-06-12 16:55:40 -0700398 // float xCursorPosition
399 msg->body.motion.xCursorPosition = body.motion.xCursorPosition;
400 // float yCursorPosition
401 msg->body.motion.yCursorPosition = body.motion.yCursorPosition;
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700402
403 msg->body.motion.dsdxRaw = body.motion.dsdxRaw;
404 msg->body.motion.dtdxRaw = body.motion.dtdxRaw;
405 msg->body.motion.dtdyRaw = body.motion.dtdyRaw;
406 msg->body.motion.dsdyRaw = body.motion.dsdyRaw;
407 msg->body.motion.txRaw = body.motion.txRaw;
408 msg->body.motion.tyRaw = body.motion.tyRaw;
409
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800410 //struct Pointer pointers[MAX_POINTERS]
411 for (size_t i = 0; i < body.motion.pointerCount; i++) {
412 // PointerProperties properties
413 msg->body.motion.pointers[i].properties.id = body.motion.pointers[i].properties.id;
414 msg->body.motion.pointers[i].properties.toolType =
415 body.motion.pointers[i].properties.toolType,
416 // PointerCoords coords
417 msg->body.motion.pointers[i].coords.bits = body.motion.pointers[i].coords.bits;
418 const uint32_t count = BitSet64::count(body.motion.pointers[i].coords.bits);
419 memcpy(&msg->body.motion.pointers[i].coords.values[0],
420 &body.motion.pointers[i].coords.values[0],
421 count * (sizeof(body.motion.pointers[i].coords.values[0])));
Philip Quinnafb31282022-12-20 18:17:55 -0800422 msg->body.motion.pointers[i].coords.isResampled =
423 body.motion.pointers[i].coords.isResampled;
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800424 }
425 break;
426 }
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700427 case InputMessage::Type::FINISHED: {
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800428 msg->body.finished.handled = body.finished.handled;
Siarhei Vishniakou3531ae72021-02-02 12:12:27 -1000429 msg->body.finished.consumeTime = body.finished.consumeTime;
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800430 break;
431 }
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800432 case InputMessage::Type::FOCUS: {
Garfield Tan1c7bc862020-01-28 13:24:04 -0800433 msg->body.focus.eventId = body.focus.eventId;
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800434 msg->body.focus.hasFocus = body.focus.hasFocus;
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800435 break;
436 }
Prabir Pradhan3f37b7b2020-11-10 16:50:18 -0800437 case InputMessage::Type::CAPTURE: {
438 msg->body.capture.eventId = body.capture.eventId;
439 msg->body.capture.pointerCaptureEnabled = body.capture.pointerCaptureEnabled;
440 break;
441 }
arthurhung7632c332020-12-30 16:58:01 +0800442 case InputMessage::Type::DRAG: {
443 msg->body.drag.eventId = body.drag.eventId;
444 msg->body.drag.x = body.drag.x;
445 msg->body.drag.y = body.drag.y;
446 msg->body.drag.isExiting = body.drag.isExiting;
447 break;
448 }
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000449 case InputMessage::Type::TIMELINE: {
450 msg->body.timeline.eventId = body.timeline.eventId;
451 msg->body.timeline.graphicsTimeline = body.timeline.graphicsTimeline;
452 break;
453 }
Antonio Kantek7cdf8ef2021-07-13 18:04:53 -0700454 case InputMessage::Type::TOUCH_MODE: {
455 msg->body.touchMode.eventId = body.touchMode.eventId;
456 msg->body.touchMode.isInTouchMode = body.touchMode.isInTouchMode;
457 }
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800458 }
459}
Jeff Brown5912f952013-07-01 19:10:31 -0700460
461// --- InputChannel ---
462
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500463std::unique_ptr<InputChannel> InputChannel::create(const std::string& name,
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500464 android::base::unique_fd fd, sp<IBinder> token) {
Josh Gao2ccbe3a2019-08-09 14:35:36 -0700465 const int result = fcntl(fd, F_SETFL, O_NONBLOCK);
466 if (result != 0) {
467 LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(),
468 strerror(errno));
469 return nullptr;
470 }
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500471 // using 'new' to access a non-public constructor
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500472 return std::unique_ptr<InputChannel>(new InputChannel(name, std::move(fd), token));
Josh Gao2ccbe3a2019-08-09 14:35:36 -0700473}
474
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800475std::unique_ptr<InputChannel> InputChannel::create(
476 android::os::InputChannelCore&& parceledChannel) {
477 return InputChannel::create(parceledChannel.name, parceledChannel.fd.release(),
478 parceledChannel.token);
479}
480
481InputChannel::InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token) {
482 this->name = std::move(name);
483 this->fd.reset(std::move(fd));
484 this->token = std::move(token);
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000485 ALOGD_IF(DEBUG_CHANNEL_LIFECYCLE, "Input channel constructed: name='%s', fd=%d",
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800486 getName().c_str(), getFd());
Jeff Brown5912f952013-07-01 19:10:31 -0700487}
488
489InputChannel::~InputChannel() {
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000490 ALOGD_IF(DEBUG_CHANNEL_LIFECYCLE, "Input channel destroyed: name='%s', fd=%d",
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800491 getName().c_str(), getFd());
Robert Carr3720ed02018-08-08 16:08:27 -0700492}
493
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800494status_t InputChannel::openInputChannelPair(const std::string& name,
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500495 std::unique_ptr<InputChannel>& outServerChannel,
496 std::unique_ptr<InputChannel>& outClientChannel) {
Jeff Brown5912f952013-07-01 19:10:31 -0700497 int sockets[2];
498 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
499 status_t result = -errno;
Siarhei Vishniakou09b02ac2021-04-14 22:24:04 +0000500 ALOGE("channel '%s' ~ Could not create socket pair. errno=%s(%d)", name.c_str(),
501 strerror(errno), errno);
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500502 outServerChannel.reset();
503 outClientChannel.reset();
Jeff Brown5912f952013-07-01 19:10:31 -0700504 return result;
505 }
506
507 int bufferSize = SOCKET_BUFFER_SIZE;
508 setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
509 setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
510 setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
511 setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
512
Siarhei Vishniakou4c155eb2023-06-30 11:47:12 -0700513 sp<IBinder> token = sp<BBinder>::make();
Siarhei Vishniakou26d3cfb2019-10-15 17:02:32 -0700514
Josh Gao2ccbe3a2019-08-09 14:35:36 -0700515 std::string serverChannelName = name + " (server)";
516 android::base::unique_fd serverFd(sockets[0]);
Siarhei Vishniakou26d3cfb2019-10-15 17:02:32 -0700517 outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);
Jeff Brown5912f952013-07-01 19:10:31 -0700518
Josh Gao2ccbe3a2019-08-09 14:35:36 -0700519 std::string clientChannelName = name + " (client)";
520 android::base::unique_fd clientFd(sockets[1]);
Siarhei Vishniakou26d3cfb2019-10-15 17:02:32 -0700521 outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
Jeff Brown5912f952013-07-01 19:10:31 -0700522 return OK;
523}
524
525status_t InputChannel::sendMessage(const InputMessage* msg) {
Prabir Pradhan2dac8b82023-09-06 01:11:51 +0000526 ATRACE_NAME_IF(ATRACE_ENABLED(),
527 StringPrintf("sendMessage(inputChannel=%s, seq=0x%" PRIx32 ", type=0x%" PRIx32
528 ")",
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800529 name.c_str(), msg->header.seq, msg->header.type));
Siarhei Vishniakou1f7c0e42018-11-16 22:18:53 -0800530 const size_t msgLength = msg->size();
531 InputMessage cleanMsg;
532 msg->getSanitizedCopy(&cleanMsg);
Jeff Brown5912f952013-07-01 19:10:31 -0700533 ssize_t nWrite;
534 do {
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800535 nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
Jeff Brown5912f952013-07-01 19:10:31 -0700536 } while (nWrite == -1 && errno == EINTR);
537
538 if (nWrite < 0) {
539 int error = errno;
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000540 ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ error sending message of type %s, %s",
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800541 name.c_str(), ftl::enum_string(msg->header.type).c_str(), strerror(error));
Jeff Brown5912f952013-07-01 19:10:31 -0700542 if (error == EAGAIN || error == EWOULDBLOCK) {
543 return WOULD_BLOCK;
544 }
545 if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {
546 return DEAD_OBJECT;
547 }
548 return -error;
549 }
550
551 if (size_t(nWrite) != msgLength) {
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000552 ALOGD_IF(DEBUG_CHANNEL_MESSAGES,
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800553 "channel '%s' ~ error sending message type %s, send was incomplete", name.c_str(),
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000554 ftl::enum_string(msg->header.type).c_str());
Jeff Brown5912f952013-07-01 19:10:31 -0700555 return DEAD_OBJECT;
556 }
557
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800558 ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ sent message of type %s", name.c_str(),
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000559 ftl::enum_string(msg->header.type).c_str());
Zimd8402b62023-06-02 11:56:26 +0100560
Jeff Brown5912f952013-07-01 19:10:31 -0700561 return OK;
562}
563
564status_t InputChannel::receiveMessage(InputMessage* msg) {
565 ssize_t nRead;
566 do {
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800567 nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT);
Jeff Brown5912f952013-07-01 19:10:31 -0700568 } while (nRead == -1 && errno == EINTR);
569
570 if (nRead < 0) {
571 int error = errno;
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000572 ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ receive message failed, errno=%d",
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800573 name.c_str(), errno);
Jeff Brown5912f952013-07-01 19:10:31 -0700574 if (error == EAGAIN || error == EWOULDBLOCK) {
575 return WOULD_BLOCK;
576 }
577 if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) {
578 return DEAD_OBJECT;
579 }
580 return -error;
581 }
582
583 if (nRead == 0) { // check for EOF
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000584 ALOGD_IF(DEBUG_CHANNEL_MESSAGES,
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800585 "channel '%s' ~ receive message failed because peer was closed", name.c_str());
Jeff Brown5912f952013-07-01 19:10:31 -0700586 return DEAD_OBJECT;
587 }
588
589 if (!msg->isValid(nRead)) {
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800590 ALOGE("channel '%s' ~ received invalid message of size %zd", name.c_str(), nRead);
Jeff Brown5912f952013-07-01 19:10:31 -0700591 return BAD_VALUE;
592 }
593
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800594 ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ received message of type %s", name.c_str(),
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000595 ftl::enum_string(msg->header.type).c_str());
Zimd8402b62023-06-02 11:56:26 +0100596 if (ATRACE_ENABLED()) {
Prabir Pradhana37bad12023-08-18 15:55:32 +0000597 // Add an additional trace point to include data about the received message.
Zimd8402b62023-06-02 11:56:26 +0100598 std::string message = StringPrintf("receiveMessage(inputChannel=%s, seq=0x%" PRIx32
599 ", type=0x%" PRIx32 ")",
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800600 name.c_str(), msg->header.seq, msg->header.type);
Zimd8402b62023-06-02 11:56:26 +0100601 ATRACE_NAME(message.c_str());
602 }
Jeff Brown5912f952013-07-01 19:10:31 -0700603 return OK;
604}
605
Egor Paskoa0d32af2023-12-14 17:45:41 +0100606bool InputChannel::probablyHasInput() const {
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800607 struct pollfd pfds = {.fd = fd.get(), .events = POLLIN};
Egor Paskoa0d32af2023-12-14 17:45:41 +0100608 if (::poll(&pfds, /*nfds=*/1, /*timeout=*/0) <= 0) {
Egor Pasko5a67a562024-01-16 16:46:45 +0100609 // This can be a false negative because EINTR and ENOMEM are not handled. The latter should
610 // be extremely rare. The EINTR is also unlikely because it happens only when the signal
611 // arrives while the syscall is executed, and the syscall is quick. Hitting EINTR too often
Egor Paskoa0d32af2023-12-14 17:45:41 +0100612 // would be a sign of having too many signals, which is a bigger performance problem. A
Egor Pasko5a67a562024-01-16 16:46:45 +0100613 // common tradition is to repeat the syscall on each EINTR, but it is not necessary here.
Egor Paskoa0d32af2023-12-14 17:45:41 +0100614 // In other words, the missing one liner is replaced by a multiline explanation.
615 return false;
616 }
617 // From poll(2): The bits returned in |revents| can include any of those specified in |events|,
618 // or one of the values POLLERR, POLLHUP, or POLLNVAL.
619 return (pfds.revents & POLLIN) != 0;
620}
621
Egor Pasko5a67a562024-01-16 16:46:45 +0100622void InputChannel::waitForMessage(std::chrono::milliseconds timeout) const {
623 if (timeout < 0ms) {
624 LOG(FATAL) << "Timeout cannot be negative, received " << timeout.count();
625 }
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800626 struct pollfd pfds = {.fd = fd.get(), .events = POLLIN};
Egor Pasko5a67a562024-01-16 16:46:45 +0100627 int ret;
628 std::chrono::time_point<std::chrono::steady_clock> stopTime =
629 std::chrono::steady_clock::now() + timeout;
630 std::chrono::milliseconds remaining = timeout;
631 do {
632 ret = ::poll(&pfds, /*nfds=*/1, /*timeout=*/remaining.count());
633 remaining = std::chrono::duration_cast<std::chrono::milliseconds>(
634 stopTime - std::chrono::steady_clock::now());
635 } while (ret == -1 && errno == EINTR && remaining > 0ms);
636}
637
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500638std::unique_ptr<InputChannel> InputChannel::dup() const {
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800639 base::unique_fd newFd(dupChannelFd(fd.get()));
Chris Ye0783e992020-06-02 21:34:49 -0700640 return InputChannel::create(getName(), std::move(newFd), getConnectionToken());
Jeff Brown5912f952013-07-01 19:10:31 -0700641}
642
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800643void InputChannel::copyTo(android::os::InputChannelCore& outChannel) const {
644 outChannel.name = getName();
645 outChannel.fd.reset(dupChannelFd(fd.get()));
646 outChannel.token = getConnectionToken();
Robert Carr3720ed02018-08-08 16:08:27 -0700647}
648
Siarhei Vishniakou7b9f4f52024-02-02 13:07:16 -0800649void InputChannel::moveChannel(std::unique_ptr<InputChannel> from,
650 android::os::InputChannelCore& outChannel) {
651 outChannel.name = from->getName();
652 outChannel.fd = android::os::ParcelFileDescriptor(std::move(from->fd));
653 outChannel.token = from->getConnectionToken();
654}
655
Siarhei Vishniakou26d3cfb2019-10-15 17:02:32 -0700656sp<IBinder> InputChannel::getConnectionToken() const {
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800657 return token;
Garfield Tan15601662020-09-22 15:32:38 -0700658}
659
Jeff Brown5912f952013-07-01 19:10:31 -0700660// --- InputPublisher ---
661
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -0800662InputPublisher::InputPublisher(const std::shared_ptr<InputChannel>& channel)
Siarhei Vishniakou7b9f4f52024-02-02 13:07:16 -0800663 : mChannel(channel), mInputVerifier(mChannel->getName()) {}
Jeff Brown5912f952013-07-01 19:10:31 -0700664
665InputPublisher::~InputPublisher() {
666}
667
Garfield Tan1c7bc862020-01-28 13:24:04 -0800668status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId,
669 int32_t source, int32_t displayId,
670 std::array<uint8_t, 32> hmac, int32_t action,
671 int32_t flags, int32_t keyCode, int32_t scanCode,
672 int32_t metaState, int32_t repeatCount, nsecs_t downTime,
673 nsecs_t eventTime) {
Prabir Pradhan2dac8b82023-09-06 01:11:51 +0000674 ATRACE_NAME_IF(ATRACE_ENABLED(),
675 StringPrintf("publishKeyEvent(inputChannel=%s, action=%s, keyCode=%s)",
676 mChannel->getName().c_str(), KeyEvent::actionToString(action),
677 KeyEvent::getLabel(keyCode)));
Prabir Pradhanb2bd83c2023-02-23 02:34:40 +0000678 ALOGD_IF(debugTransportPublisher(),
Prabir Pradhan96282b02023-02-24 22:36:17 +0000679 "channel '%s' publisher ~ %s: seq=%u, id=%d, deviceId=%d, source=%s, "
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000680 "action=%s, flags=0x%x, keyCode=%s, scanCode=%d, metaState=0x%x, repeatCount=%d,"
681 "downTime=%" PRId64 ", eventTime=%" PRId64,
Prabir Pradhan96282b02023-02-24 22:36:17 +0000682 mChannel->getName().c_str(), __func__, seq, eventId, deviceId,
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000683 inputEventSourceToString(source).c_str(), KeyEvent::actionToString(action), flags,
684 KeyEvent::getLabel(keyCode), scanCode, metaState, repeatCount, downTime, eventTime);
Jeff Brown5912f952013-07-01 19:10:31 -0700685
686 if (!seq) {
687 ALOGE("Attempted to publish a key event with sequence number 0.");
688 return BAD_VALUE;
689 }
690
691 InputMessage msg;
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700692 msg.header.type = InputMessage::Type::KEY;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -0500693 msg.header.seq = seq;
Garfield Tan1c7bc862020-01-28 13:24:04 -0800694 msg.body.key.eventId = eventId;
Jeff Brown5912f952013-07-01 19:10:31 -0700695 msg.body.key.deviceId = deviceId;
696 msg.body.key.source = source;
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100697 msg.body.key.displayId = displayId;
Edgar Arriagac6ae4bb2020-04-16 18:46:48 -0700698 msg.body.key.hmac = std::move(hmac);
Jeff Brown5912f952013-07-01 19:10:31 -0700699 msg.body.key.action = action;
700 msg.body.key.flags = flags;
701 msg.body.key.keyCode = keyCode;
702 msg.body.key.scanCode = scanCode;
703 msg.body.key.metaState = metaState;
704 msg.body.key.repeatCount = repeatCount;
705 msg.body.key.downTime = downTime;
706 msg.body.key.eventTime = eventTime;
707 return mChannel->sendMessage(&msg);
708}
709
710status_t InputPublisher::publishMotionEvent(
Garfield Tan1c7bc862020-01-28 13:24:04 -0800711 uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, int32_t displayId,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600712 std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton, int32_t flags,
713 int32_t edgeFlags, int32_t metaState, int32_t buttonState,
chaviw9eaa22c2020-07-01 16:21:27 -0700714 MotionClassification classification, const ui::Transform& transform, float xPrecision,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700715 float yPrecision, float xCursorPosition, float yCursorPosition,
716 const ui::Transform& rawTransform, nsecs_t downTime, nsecs_t eventTime,
Evan Rosky09576692021-07-01 12:22:09 -0700717 uint32_t pointerCount, const PointerProperties* pointerProperties,
718 const PointerCoords* pointerCoords) {
Prabir Pradhan2dac8b82023-09-06 01:11:51 +0000719 ATRACE_NAME_IF(ATRACE_ENABLED(),
720 StringPrintf("publishMotionEvent(inputChannel=%s, action=%s)",
721 mChannel->getName().c_str(),
722 MotionEvent::actionToString(action).c_str()));
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -0800723 if (verifyEvents()) {
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -0700724 Result<void> result =
Siarhei Vishniakou2d151ac2023-09-19 13:30:24 -0700725 mInputVerifier.processMovement(deviceId, source, action, pointerCount,
726 pointerProperties, pointerCoords, flags);
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -0700727 if (!result.ok()) {
728 LOG(FATAL) << "Bad stream: " << result.error();
729 }
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -0800730 }
Prabir Pradhanb2bd83c2023-02-23 02:34:40 +0000731 if (debugTransportPublisher()) {
chaviw9eaa22c2020-07-01 16:21:27 -0700732 std::string transformString;
chaviw85b44202020-07-24 11:46:21 -0700733 transform.dump(transformString, "transform", " ");
Prabir Pradhan96282b02023-02-24 22:36:17 +0000734 ALOGD("channel '%s' publisher ~ %s: seq=%u, id=%d, deviceId=%d, source=%s, "
Siarhei Vishniakou3b37f9a2019-11-23 13:42:41 -0800735 "displayId=%" PRId32 ", "
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000736 "action=%s, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
chaviw9eaa22c2020-07-01 16:21:27 -0700737 "metaState=0x%x, buttonState=0x%x, classification=%s,"
Siarhei Vishniakou3b37f9a2019-11-23 13:42:41 -0800738 "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", "
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -0700739 "pointerCount=%" PRIu32 "\n%s",
Prabir Pradhan96282b02023-02-24 22:36:17 +0000740 mChannel->getName().c_str(), __func__, seq, eventId, deviceId,
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000741 inputEventSourceToString(source).c_str(), displayId,
742 MotionEvent::actionToString(action).c_str(), actionButton, flags, edgeFlags,
743 metaState, buttonState, motionClassificationToString(classification), xPrecision,
744 yPrecision, downTime, eventTime, pointerCount, transformString.c_str());
Siarhei Vishniakou3b37f9a2019-11-23 13:42:41 -0800745 }
Jeff Brown5912f952013-07-01 19:10:31 -0700746
747 if (!seq) {
748 ALOGE("Attempted to publish a motion event with sequence number 0.");
749 return BAD_VALUE;
750 }
751
752 if (pointerCount > MAX_POINTERS || pointerCount < 1) {
Michael Wright63ff3a82014-06-10 13:03:17 -0700753 ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %" PRIu32 ".",
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800754 mChannel->getName().c_str(), pointerCount);
Jeff Brown5912f952013-07-01 19:10:31 -0700755 return BAD_VALUE;
756 }
757
758 InputMessage msg;
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700759 msg.header.type = InputMessage::Type::MOTION;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -0500760 msg.header.seq = seq;
Garfield Tan1c7bc862020-01-28 13:24:04 -0800761 msg.body.motion.eventId = eventId;
Jeff Brown5912f952013-07-01 19:10:31 -0700762 msg.body.motion.deviceId = deviceId;
763 msg.body.motion.source = source;
Tarandeep Singh58641502017-07-31 10:51:54 -0700764 msg.body.motion.displayId = displayId;
Edgar Arriagac6ae4bb2020-04-16 18:46:48 -0700765 msg.body.motion.hmac = std::move(hmac);
Jeff Brown5912f952013-07-01 19:10:31 -0700766 msg.body.motion.action = action;
Michael Wright7b159c92015-05-14 14:48:03 +0100767 msg.body.motion.actionButton = actionButton;
Jeff Brown5912f952013-07-01 19:10:31 -0700768 msg.body.motion.flags = flags;
769 msg.body.motion.edgeFlags = edgeFlags;
770 msg.body.motion.metaState = metaState;
771 msg.body.motion.buttonState = buttonState;
Siarhei Vishniakou16a2e302019-01-14 19:21:45 -0800772 msg.body.motion.classification = classification;
chaviw9eaa22c2020-07-01 16:21:27 -0700773 msg.body.motion.dsdx = transform.dsdx();
774 msg.body.motion.dtdx = transform.dtdx();
775 msg.body.motion.dtdy = transform.dtdy();
776 msg.body.motion.dsdy = transform.dsdy();
777 msg.body.motion.tx = transform.tx();
778 msg.body.motion.ty = transform.ty();
Jeff Brown5912f952013-07-01 19:10:31 -0700779 msg.body.motion.xPrecision = xPrecision;
780 msg.body.motion.yPrecision = yPrecision;
Garfield Tan00f511d2019-06-12 16:55:40 -0700781 msg.body.motion.xCursorPosition = xCursorPosition;
782 msg.body.motion.yCursorPosition = yCursorPosition;
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700783 msg.body.motion.dsdxRaw = rawTransform.dsdx();
784 msg.body.motion.dtdxRaw = rawTransform.dtdx();
785 msg.body.motion.dtdyRaw = rawTransform.dtdy();
786 msg.body.motion.dsdyRaw = rawTransform.dsdy();
787 msg.body.motion.txRaw = rawTransform.tx();
788 msg.body.motion.tyRaw = rawTransform.ty();
Jeff Brown5912f952013-07-01 19:10:31 -0700789 msg.body.motion.downTime = downTime;
790 msg.body.motion.eventTime = eventTime;
791 msg.body.motion.pointerCount = pointerCount;
Narayan Kamathbc6001b2014-05-02 17:53:33 +0100792 for (uint32_t i = 0; i < pointerCount; i++) {
Siarhei Vishniakou73e6d372023-07-06 18:07:21 -0700793 msg.body.motion.pointers[i].properties = pointerProperties[i];
794 msg.body.motion.pointers[i].coords = pointerCoords[i];
Jeff Brown5912f952013-07-01 19:10:31 -0700795 }
Atif Niyaz3d3fa522019-07-25 11:12:39 -0700796
Jeff Brown5912f952013-07-01 19:10:31 -0700797 return mChannel->sendMessage(&msg);
798}
799
Antonio Kantek3cfec7b2021-11-05 18:26:17 -0700800status_t InputPublisher::publishFocusEvent(uint32_t seq, int32_t eventId, bool hasFocus) {
Prabir Pradhan2dac8b82023-09-06 01:11:51 +0000801 ATRACE_NAME_IF(ATRACE_ENABLED(),
802 StringPrintf("publishFocusEvent(inputChannel=%s, hasFocus=%s)",
803 mChannel->getName().c_str(), toString(hasFocus)));
Prabir Pradhan96282b02023-02-24 22:36:17 +0000804 ALOGD_IF(debugTransportPublisher(), "channel '%s' publisher ~ %s: seq=%u, id=%d, hasFocus=%s",
805 mChannel->getName().c_str(), __func__, seq, eventId, toString(hasFocus));
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800806
807 InputMessage msg;
808 msg.header.type = InputMessage::Type::FOCUS;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -0500809 msg.header.seq = seq;
Garfield Tan1c7bc862020-01-28 13:24:04 -0800810 msg.body.focus.eventId = eventId;
Siarhei Vishniakou38b7f7f2021-03-05 01:57:08 +0000811 msg.body.focus.hasFocus = hasFocus;
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800812 return mChannel->sendMessage(&msg);
813}
814
Prabir Pradhan3f37b7b2020-11-10 16:50:18 -0800815status_t InputPublisher::publishCaptureEvent(uint32_t seq, int32_t eventId,
816 bool pointerCaptureEnabled) {
Prabir Pradhan2dac8b82023-09-06 01:11:51 +0000817 ATRACE_NAME_IF(ATRACE_ENABLED(),
818 StringPrintf("publishCaptureEvent(inputChannel=%s, pointerCaptureEnabled=%s)",
819 mChannel->getName().c_str(), toString(pointerCaptureEnabled)));
Prabir Pradhanb2bd83c2023-02-23 02:34:40 +0000820 ALOGD_IF(debugTransportPublisher(),
Prabir Pradhan96282b02023-02-24 22:36:17 +0000821 "channel '%s' publisher ~ %s: seq=%u, id=%d, pointerCaptureEnabled=%s",
822 mChannel->getName().c_str(), __func__, seq, eventId, toString(pointerCaptureEnabled));
Prabir Pradhan3f37b7b2020-11-10 16:50:18 -0800823
824 InputMessage msg;
825 msg.header.type = InputMessage::Type::CAPTURE;
826 msg.header.seq = seq;
827 msg.body.capture.eventId = eventId;
Siarhei Vishniakou38b7f7f2021-03-05 01:57:08 +0000828 msg.body.capture.pointerCaptureEnabled = pointerCaptureEnabled;
Prabir Pradhan3f37b7b2020-11-10 16:50:18 -0800829 return mChannel->sendMessage(&msg);
830}
831
arthurhung7632c332020-12-30 16:58:01 +0800832status_t InputPublisher::publishDragEvent(uint32_t seq, int32_t eventId, float x, float y,
833 bool isExiting) {
Prabir Pradhan2dac8b82023-09-06 01:11:51 +0000834 ATRACE_NAME_IF(ATRACE_ENABLED(),
835 StringPrintf("publishDragEvent(inputChannel=%s, x=%f, y=%f, isExiting=%s)",
836 mChannel->getName().c_str(), x, y, toString(isExiting)));
Prabir Pradhanb2bd83c2023-02-23 02:34:40 +0000837 ALOGD_IF(debugTransportPublisher(),
Prabir Pradhan96282b02023-02-24 22:36:17 +0000838 "channel '%s' publisher ~ %s: seq=%u, id=%d, x=%f, y=%f, isExiting=%s",
839 mChannel->getName().c_str(), __func__, seq, eventId, x, y, toString(isExiting));
arthurhung7632c332020-12-30 16:58:01 +0800840
841 InputMessage msg;
842 msg.header.type = InputMessage::Type::DRAG;
843 msg.header.seq = seq;
844 msg.body.drag.eventId = eventId;
845 msg.body.drag.isExiting = isExiting;
846 msg.body.drag.x = x;
847 msg.body.drag.y = y;
848 return mChannel->sendMessage(&msg);
849}
850
Antonio Kantek7cdf8ef2021-07-13 18:04:53 -0700851status_t InputPublisher::publishTouchModeEvent(uint32_t seq, int32_t eventId, bool isInTouchMode) {
Prabir Pradhan2dac8b82023-09-06 01:11:51 +0000852 ATRACE_NAME_IF(ATRACE_ENABLED(),
853 StringPrintf("publishTouchModeEvent(inputChannel=%s, isInTouchMode=%s)",
854 mChannel->getName().c_str(), toString(isInTouchMode)));
Prabir Pradhan96282b02023-02-24 22:36:17 +0000855 ALOGD_IF(debugTransportPublisher(),
856 "channel '%s' publisher ~ %s: seq=%u, id=%d, isInTouchMode=%s",
857 mChannel->getName().c_str(), __func__, seq, eventId, toString(isInTouchMode));
Antonio Kantek7cdf8ef2021-07-13 18:04:53 -0700858
859 InputMessage msg;
860 msg.header.type = InputMessage::Type::TOUCH_MODE;
861 msg.header.seq = seq;
862 msg.body.touchMode.eventId = eventId;
863 msg.body.touchMode.isInTouchMode = isInTouchMode;
864 return mChannel->sendMessage(&msg);
865}
866
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000867android::base::Result<InputPublisher::ConsumerResponse> InputPublisher::receiveConsumerResponse() {
Jeff Brown5912f952013-07-01 19:10:31 -0700868 InputMessage msg;
869 status_t result = mChannel->receiveMessage(&msg);
870 if (result) {
Siarhei Vishniakou69112652023-08-24 08:34:18 -0700871 if (debugTransportPublisher() && result != WOULD_BLOCK) {
872 LOG(INFO) << "channel '" << mChannel->getName() << "' publisher ~ " << __func__ << ": "
873 << strerror(result);
874 }
Siarhei Vishniakoueedd0fc2021-03-12 09:50:36 +0000875 return android::base::Error(result);
Jeff Brown5912f952013-07-01 19:10:31 -0700876 }
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000877 if (msg.header.type == InputMessage::Type::FINISHED) {
Prabir Pradhan96282b02023-02-24 22:36:17 +0000878 ALOGD_IF(debugTransportPublisher(),
879 "channel '%s' publisher ~ %s: finished: seq=%u, handled=%s",
880 mChannel->getName().c_str(), __func__, msg.header.seq,
881 toString(msg.body.finished.handled));
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000882 return Finished{
883 .seq = msg.header.seq,
884 .handled = msg.body.finished.handled,
885 .consumeTime = msg.body.finished.consumeTime,
886 };
Jeff Brown5912f952013-07-01 19:10:31 -0700887 }
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000888
889 if (msg.header.type == InputMessage::Type::TIMELINE) {
Prabir Pradhan96282b02023-02-24 22:36:17 +0000890 ALOGD_IF(debugTransportPublisher(), "channel '%s' publisher ~ %s: timeline: id=%d",
891 mChannel->getName().c_str(), __func__, msg.body.timeline.eventId);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000892 return Timeline{
893 .inputEventId = msg.body.timeline.eventId,
894 .graphicsTimeline = msg.body.timeline.graphicsTimeline,
895 };
896 }
897
898 ALOGE("channel '%s' publisher ~ Received unexpected %s message from consumer",
Dominik Laskowski75788452021-02-09 18:51:25 -0800899 mChannel->getName().c_str(), ftl::enum_string(msg.header.type).c_str());
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000900 return android::base::Error(UNKNOWN_ERROR);
Jeff Brown5912f952013-07-01 19:10:31 -0700901}
902
903// --- InputConsumer ---
904
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500905InputConsumer::InputConsumer(const std::shared_ptr<InputChannel>& channel)
Siarhei Vishniakou0ced3cc2017-11-21 15:33:17 -0800906 : InputConsumer(channel, isTouchResamplingEnabled()) {}
907
908InputConsumer::InputConsumer(const std::shared_ptr<InputChannel>& channel,
909 bool enableTouchResampling)
910 : mResampleTouch(enableTouchResampling), mChannel(channel), mMsgDeferred(false) {}
Jeff Brown5912f952013-07-01 19:10:31 -0700911
912InputConsumer::~InputConsumer() {
913}
914
915bool InputConsumer::isTouchResamplingEnabled() {
Siarhei Vishniakoub5433e92019-02-21 09:27:39 -0600916 return property_get_bool(PROPERTY_RESAMPLING_ENABLED, true);
Jeff Brown5912f952013-07-01 19:10:31 -0700917}
918
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800919status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consumeBatches,
920 nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000921 ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
922 "channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64,
923 mChannel->getName().c_str(), toString(consumeBatches), frameTime);
Jeff Brown5912f952013-07-01 19:10:31 -0700924
925 *outSeq = 0;
Yi Kong5bed83b2018-07-17 12:53:47 -0700926 *outEvent = nullptr;
Jeff Brown5912f952013-07-01 19:10:31 -0700927
928 // Fetch the next input message.
929 // Loop until an event can be returned or no additional events are received.
930 while (!*outEvent) {
931 if (mMsgDeferred) {
932 // mMsg contains a valid input message from the previous call to consume
933 // that has not yet been processed.
934 mMsgDeferred = false;
935 } else {
936 // Receive a fresh message.
937 status_t result = mChannel->receiveMessage(&mMsg);
Siarhei Vishniakou3531ae72021-02-02 12:12:27 -1000938 if (result == OK) {
Siarhei Vishniakou0ced3cc2017-11-21 15:33:17 -0800939 const auto [_, inserted] =
940 mConsumeTimes.emplace(mMsg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
941 LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
942 mMsg.header.seq);
Siarhei Vishniakouca42e0d2024-01-12 12:10:32 -0800943
944 // Trace the event processing timeline - event was just read from the socket
945 ATRACE_ASYNC_BEGIN("InputConsumer processing", /*cookie=*/mMsg.header.seq);
Siarhei Vishniakou3531ae72021-02-02 12:12:27 -1000946 }
Jeff Brown5912f952013-07-01 19:10:31 -0700947 if (result) {
948 // Consume the next batched event unless batches are being held for later.
949 if (consumeBatches || result != WOULD_BLOCK) {
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800950 result = consumeBatch(factory, frameTime, outSeq, outEvent);
Jeff Brown5912f952013-07-01 19:10:31 -0700951 if (*outEvent) {
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000952 ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
953 "channel '%s' consumer ~ consumed batch event, seq=%u",
954 mChannel->getName().c_str(), *outSeq);
Jeff Brown5912f952013-07-01 19:10:31 -0700955 break;
956 }
957 }
958 return result;
959 }
960 }
961
962 switch (mMsg.header.type) {
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700963 case InputMessage::Type::KEY: {
964 KeyEvent* keyEvent = factory->createKeyEvent();
965 if (!keyEvent) return NO_MEMORY;
Jeff Brown5912f952013-07-01 19:10:31 -0700966
Siarhei Vishniakou9dbf6372024-03-06 16:08:01 -0800967 initializeKeyEvent(*keyEvent, mMsg);
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -0500968 *outSeq = mMsg.header.seq;
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700969 *outEvent = keyEvent;
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000970 ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
971 "channel '%s' consumer ~ consumed key event, seq=%u",
972 mChannel->getName().c_str(), *outSeq);
973 break;
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700974 }
Jeff Brown5912f952013-07-01 19:10:31 -0700975
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700976 case InputMessage::Type::MOTION: {
977 ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source);
978 if (batchIndex >= 0) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -0500979 Batch& batch = mBatches[batchIndex];
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700980 if (canAddSample(batch, &mMsg)) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -0500981 batch.samples.push_back(mMsg);
Prabir Pradhan60dd97a2023-02-23 02:23:02 +0000982 ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
983 "channel '%s' consumer ~ appended to batch event",
984 mChannel->getName().c_str());
985 break;
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700986 } else if (isPointerEvent(mMsg.body.motion.source) &&
987 mMsg.body.motion.action == AMOTION_EVENT_ACTION_CANCEL) {
988 // No need to process events that we are going to cancel anyways
989 const size_t count = batch.samples.size();
990 for (size_t i = 0; i < count; i++) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -0500991 const InputMessage& msg = batch.samples[i];
992 sendFinishedSignal(msg.header.seq, false);
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700993 }
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -0500994 batch.samples.erase(batch.samples.begin(), batch.samples.begin() + count);
995 mBatches.erase(mBatches.begin() + batchIndex);
Siarhei Vishniakou52402772019-10-22 09:32:30 -0700996 } else {
997 // We cannot append to the batch in progress, so we need to consume
998 // the previous batch right now and defer the new message until later.
999 mMsgDeferred = true;
1000 status_t result = consumeSamples(factory, batch, batch.samples.size(),
1001 outSeq, outEvent);
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001002 mBatches.erase(mBatches.begin() + batchIndex);
Siarhei Vishniakou52402772019-10-22 09:32:30 -07001003 if (result) {
1004 return result;
1005 }
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001006 ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
1007 "channel '%s' consumer ~ consumed batch event and "
1008 "deferred current event, seq=%u",
1009 mChannel->getName().c_str(), *outSeq);
1010 break;
Siarhei Vishniakou52402772019-10-22 09:32:30 -07001011 }
Jeff Brown5912f952013-07-01 19:10:31 -07001012 }
Jeff Brown5912f952013-07-01 19:10:31 -07001013
Siarhei Vishniakou3b37f9a2019-11-23 13:42:41 -08001014 // Start a new batch if needed.
1015 if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE ||
1016 mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001017 Batch batch;
1018 batch.samples.push_back(mMsg);
1019 mBatches.push_back(batch);
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001020 ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
1021 "channel '%s' consumer ~ started batch event",
1022 mChannel->getName().c_str());
Siarhei Vishniakou3b37f9a2019-11-23 13:42:41 -08001023 break;
1024 }
Jeff Brown5912f952013-07-01 19:10:31 -07001025
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -08001026 MotionEvent* motionEvent = factory->createMotionEvent();
1027 if (!motionEvent) return NO_MEMORY;
Jeff Brown5912f952013-07-01 19:10:31 -07001028
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -08001029 updateTouchState(mMsg);
Siarhei Vishniakou9dbf6372024-03-06 16:08:01 -08001030 initializeMotionEvent(*motionEvent, mMsg);
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001031 *outSeq = mMsg.header.seq;
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -08001032 *outEvent = motionEvent;
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08001033
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001034 ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
1035 "channel '%s' consumer ~ consumed motion event, seq=%u",
1036 mChannel->getName().c_str(), *outSeq);
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -08001037 break;
Siarhei Vishniakou52402772019-10-22 09:32:30 -07001038 }
Jeff Brown5912f952013-07-01 19:10:31 -07001039
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001040 case InputMessage::Type::FINISHED:
1041 case InputMessage::Type::TIMELINE: {
Siarhei Vishniakou7766c032021-03-02 20:32:20 +00001042 LOG_ALWAYS_FATAL("Consumed a %s message, which should never be seen by "
1043 "InputConsumer!",
Dominik Laskowski75788452021-02-09 18:51:25 -08001044 ftl::enum_string(mMsg.header.type).c_str());
Siarhei Vishniakou3b37f9a2019-11-23 13:42:41 -08001045 break;
1046 }
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -08001047
1048 case InputMessage::Type::FOCUS: {
1049 FocusEvent* focusEvent = factory->createFocusEvent();
1050 if (!focusEvent) return NO_MEMORY;
1051
Siarhei Vishniakou9dbf6372024-03-06 16:08:01 -08001052 initializeFocusEvent(*focusEvent, mMsg);
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001053 *outSeq = mMsg.header.seq;
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -08001054 *outEvent = focusEvent;
1055 break;
1056 }
Prabir Pradhan3f37b7b2020-11-10 16:50:18 -08001057
1058 case InputMessage::Type::CAPTURE: {
1059 CaptureEvent* captureEvent = factory->createCaptureEvent();
1060 if (!captureEvent) return NO_MEMORY;
1061
Siarhei Vishniakou9dbf6372024-03-06 16:08:01 -08001062 initializeCaptureEvent(*captureEvent, mMsg);
Prabir Pradhan3f37b7b2020-11-10 16:50:18 -08001063 *outSeq = mMsg.header.seq;
1064 *outEvent = captureEvent;
1065 break;
1066 }
arthurhung7632c332020-12-30 16:58:01 +08001067
1068 case InputMessage::Type::DRAG: {
1069 DragEvent* dragEvent = factory->createDragEvent();
1070 if (!dragEvent) return NO_MEMORY;
1071
Siarhei Vishniakou9dbf6372024-03-06 16:08:01 -08001072 initializeDragEvent(*dragEvent, mMsg);
arthurhung7632c332020-12-30 16:58:01 +08001073 *outSeq = mMsg.header.seq;
1074 *outEvent = dragEvent;
1075 break;
1076 }
Antonio Kantek7cdf8ef2021-07-13 18:04:53 -07001077
1078 case InputMessage::Type::TOUCH_MODE: {
1079 TouchModeEvent* touchModeEvent = factory->createTouchModeEvent();
1080 if (!touchModeEvent) return NO_MEMORY;
1081
Siarhei Vishniakou9dbf6372024-03-06 16:08:01 -08001082 initializeTouchModeEvent(*touchModeEvent, mMsg);
Antonio Kantek7cdf8ef2021-07-13 18:04:53 -07001083 *outSeq = mMsg.header.seq;
1084 *outEvent = touchModeEvent;
1085 break;
1086 }
Jeff Brown5912f952013-07-01 19:10:31 -07001087 }
1088 }
1089 return OK;
1090}
1091
1092status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08001093 nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
Jeff Brown5912f952013-07-01 19:10:31 -07001094 status_t result;
Dan Austin1faef802015-09-22 14:28:07 -07001095 for (size_t i = mBatches.size(); i > 0; ) {
1096 i--;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001097 Batch& batch = mBatches[i];
Michael Wright32232172013-10-21 12:05:22 -07001098 if (frameTime < 0) {
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08001099 result = consumeSamples(factory, batch, batch.samples.size(), outSeq, outEvent);
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001100 mBatches.erase(mBatches.begin() + i);
Jeff Brown5912f952013-07-01 19:10:31 -07001101 return result;
1102 }
1103
Michael Wright32232172013-10-21 12:05:22 -07001104 nsecs_t sampleTime = frameTime;
1105 if (mResampleTouch) {
Siarhei Vishniakou0ced3cc2017-11-21 15:33:17 -08001106 sampleTime -= std::chrono::nanoseconds(RESAMPLE_LATENCY).count();
Michael Wright32232172013-10-21 12:05:22 -07001107 }
Jeff Brown5912f952013-07-01 19:10:31 -07001108 ssize_t split = findSampleNoLaterThan(batch, sampleTime);
1109 if (split < 0) {
1110 continue;
1111 }
1112
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08001113 result = consumeSamples(factory, batch, split + 1, outSeq, outEvent);
Jeff Brown5912f952013-07-01 19:10:31 -07001114 const InputMessage* next;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001115 if (batch.samples.empty()) {
1116 mBatches.erase(mBatches.begin() + i);
Yi Kong5bed83b2018-07-17 12:53:47 -07001117 next = nullptr;
Jeff Brown5912f952013-07-01 19:10:31 -07001118 } else {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001119 next = &batch.samples[0];
Jeff Brown5912f952013-07-01 19:10:31 -07001120 }
Michael Wright32232172013-10-21 12:05:22 -07001121 if (!result && mResampleTouch) {
Jeff Brown5912f952013-07-01 19:10:31 -07001122 resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next);
1123 }
1124 return result;
1125 }
1126
1127 return WOULD_BLOCK;
1128}
1129
1130status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08001131 Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent) {
Jeff Brown5912f952013-07-01 19:10:31 -07001132 MotionEvent* motionEvent = factory->createMotionEvent();
1133 if (! motionEvent) return NO_MEMORY;
1134
1135 uint32_t chain = 0;
1136 for (size_t i = 0; i < count; i++) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001137 InputMessage& msg = batch.samples[i];
Siarhei Vishniakou0aeec072017-06-12 15:01:41 +01001138 updateTouchState(msg);
Jeff Brown5912f952013-07-01 19:10:31 -07001139 if (i) {
1140 SeqChain seqChain;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001141 seqChain.seq = msg.header.seq;
Jeff Brown5912f952013-07-01 19:10:31 -07001142 seqChain.chain = chain;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001143 mSeqChains.push_back(seqChain);
Siarhei Vishniakou9dbf6372024-03-06 16:08:01 -08001144 addSample(*motionEvent, msg);
Jeff Brown5912f952013-07-01 19:10:31 -07001145 } else {
Siarhei Vishniakou9dbf6372024-03-06 16:08:01 -08001146 initializeMotionEvent(*motionEvent, msg);
Jeff Brown5912f952013-07-01 19:10:31 -07001147 }
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001148 chain = msg.header.seq;
Jeff Brown5912f952013-07-01 19:10:31 -07001149 }
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001150 batch.samples.erase(batch.samples.begin(), batch.samples.begin() + count);
Jeff Brown5912f952013-07-01 19:10:31 -07001151
1152 *outSeq = chain;
1153 *outEvent = motionEvent;
1154 return OK;
1155}
1156
Siarhei Vishniakou0aeec072017-06-12 15:01:41 +01001157void InputConsumer::updateTouchState(InputMessage& msg) {
Siarhei Vishniakou128eab12019-05-23 10:25:59 +08001158 if (!mResampleTouch || !isPointerEvent(msg.body.motion.source)) {
Jeff Brown5912f952013-07-01 19:10:31 -07001159 return;
1160 }
1161
Siarhei Vishniakou0aeec072017-06-12 15:01:41 +01001162 int32_t deviceId = msg.body.motion.deviceId;
1163 int32_t source = msg.body.motion.source;
Jeff Brown5912f952013-07-01 19:10:31 -07001164
1165 // Update the touch state history to incorporate the new input message.
1166 // If the message is in the past relative to the most recently produced resampled
1167 // touch, then use the resampled time and coordinates instead.
Siarhei Vishniakou0aeec072017-06-12 15:01:41 +01001168 switch (msg.body.motion.action & AMOTION_EVENT_ACTION_MASK) {
Jeff Brown5912f952013-07-01 19:10:31 -07001169 case AMOTION_EVENT_ACTION_DOWN: {
1170 ssize_t index = findTouchState(deviceId, source);
1171 if (index < 0) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001172 mTouchStates.push_back({});
Jeff Brown5912f952013-07-01 19:10:31 -07001173 index = mTouchStates.size() - 1;
1174 }
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001175 TouchState& touchState = mTouchStates[index];
Jeff Brown5912f952013-07-01 19:10:31 -07001176 touchState.initialize(deviceId, source);
1177 touchState.addHistory(msg);
1178 break;
1179 }
1180
1181 case AMOTION_EVENT_ACTION_MOVE: {
1182 ssize_t index = findTouchState(deviceId, source);
1183 if (index >= 0) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001184 TouchState& touchState = mTouchStates[index];
Jeff Brown5912f952013-07-01 19:10:31 -07001185 touchState.addHistory(msg);
Siarhei Vishniakou56c9ae12017-11-06 21:16:47 -08001186 rewriteMessage(touchState, msg);
Jeff Brown5912f952013-07-01 19:10:31 -07001187 }
1188 break;
1189 }
1190
1191 case AMOTION_EVENT_ACTION_POINTER_DOWN: {
1192 ssize_t index = findTouchState(deviceId, source);
1193 if (index >= 0) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001194 TouchState& touchState = mTouchStates[index];
Siarhei Vishniakou0aeec072017-06-12 15:01:41 +01001195 touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
Jeff Brown5912f952013-07-01 19:10:31 -07001196 rewriteMessage(touchState, msg);
1197 }
1198 break;
1199 }
1200
1201 case AMOTION_EVENT_ACTION_POINTER_UP: {
1202 ssize_t index = findTouchState(deviceId, source);
1203 if (index >= 0) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001204 TouchState& touchState = mTouchStates[index];
Jeff Brown5912f952013-07-01 19:10:31 -07001205 rewriteMessage(touchState, msg);
Siarhei Vishniakou0aeec072017-06-12 15:01:41 +01001206 touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
Jeff Brown5912f952013-07-01 19:10:31 -07001207 }
1208 break;
1209 }
1210
1211 case AMOTION_EVENT_ACTION_SCROLL: {
1212 ssize_t index = findTouchState(deviceId, source);
1213 if (index >= 0) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001214 TouchState& touchState = mTouchStates[index];
Jeff Brown5912f952013-07-01 19:10:31 -07001215 rewriteMessage(touchState, msg);
1216 }
1217 break;
1218 }
1219
1220 case AMOTION_EVENT_ACTION_UP:
1221 case AMOTION_EVENT_ACTION_CANCEL: {
1222 ssize_t index = findTouchState(deviceId, source);
1223 if (index >= 0) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001224 TouchState& touchState = mTouchStates[index];
Jeff Brown5912f952013-07-01 19:10:31 -07001225 rewriteMessage(touchState, msg);
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001226 mTouchStates.erase(mTouchStates.begin() + index);
Jeff Brown5912f952013-07-01 19:10:31 -07001227 }
1228 break;
1229 }
1230 }
1231}
1232
Siarhei Vishniakou56c9ae12017-11-06 21:16:47 -08001233/**
1234 * Replace the coordinates in msg with the coordinates in lastResample, if necessary.
1235 *
1236 * If lastResample is no longer valid for a specific pointer (i.e. the lastResample time
1237 * is in the past relative to msg and the past two events do not contain identical coordinates),
1238 * then invalidate the lastResample data for that pointer.
1239 * If the two past events have identical coordinates, then lastResample data for that pointer will
1240 * remain valid, and will be used to replace these coordinates. Thus, if a certain coordinate x0 is
1241 * resampled to the new value x1, then x1 will always be used to replace x0 until some new value
1242 * not equal to x0 is received.
1243 */
1244void InputConsumer::rewriteMessage(TouchState& state, InputMessage& msg) {
Siarhei Vishniakou0aeec072017-06-12 15:01:41 +01001245 nsecs_t eventTime = msg.body.motion.eventTime;
1246 for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
1247 uint32_t id = msg.body.motion.pointers[i].properties.id;
Jeff Brown5912f952013-07-01 19:10:31 -07001248 if (state.lastResample.idBits.hasBit(id)) {
Siarhei Vishniakou0aeec072017-06-12 15:01:41 +01001249 if (eventTime < state.lastResample.eventTime ||
1250 state.recentCoordinatesAreIdentical(id)) {
Siarhei Vishniakou56c9ae12017-11-06 21:16:47 -08001251 PointerCoords& msgCoords = msg.body.motion.pointers[i].coords;
1252 const PointerCoords& resampleCoords = state.lastResample.getPointerById(id);
Harry Cutts6c658cc2023-08-02 14:40:40 +00001253 ALOGD_IF(debugResampling(), "[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001254 resampleCoords.getX(), resampleCoords.getY(), msgCoords.getX(),
1255 msgCoords.getY());
Siarhei Vishniakou56c9ae12017-11-06 21:16:47 -08001256 msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
1257 msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
Philip Quinnafb31282022-12-20 18:17:55 -08001258 msgCoords.isResampled = true;
Siarhei Vishniakou56c9ae12017-11-06 21:16:47 -08001259 } else {
1260 state.lastResample.idBits.clearBit(id);
Siarhei Vishniakou0aeec072017-06-12 15:01:41 +01001261 }
Jeff Brown5912f952013-07-01 19:10:31 -07001262 }
1263 }
1264}
1265
1266void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
1267 const InputMessage* next) {
1268 if (!mResampleTouch
Siarhei Vishniakou128eab12019-05-23 10:25:59 +08001269 || !(isPointerEvent(event->getSource()))
Jeff Brown5912f952013-07-01 19:10:31 -07001270 || event->getAction() != AMOTION_EVENT_ACTION_MOVE) {
1271 return;
1272 }
1273
1274 ssize_t index = findTouchState(event->getDeviceId(), event->getSource());
1275 if (index < 0) {
Harry Cutts6c658cc2023-08-02 14:40:40 +00001276 ALOGD_IF(debugResampling(), "Not resampled, no touch state for device.");
Jeff Brown5912f952013-07-01 19:10:31 -07001277 return;
1278 }
1279
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001280 TouchState& touchState = mTouchStates[index];
Jeff Brown5912f952013-07-01 19:10:31 -07001281 if (touchState.historySize < 1) {
Harry Cutts6c658cc2023-08-02 14:40:40 +00001282 ALOGD_IF(debugResampling(), "Not resampled, no history for device.");
Jeff Brown5912f952013-07-01 19:10:31 -07001283 return;
1284 }
1285
1286 // Ensure that the current sample has all of the pointers that need to be reported.
1287 const History* current = touchState.getHistory(0);
1288 size_t pointerCount = event->getPointerCount();
1289 for (size_t i = 0; i < pointerCount; i++) {
1290 uint32_t id = event->getPointerId(i);
1291 if (!current->idBits.hasBit(id)) {
Harry Cutts6c658cc2023-08-02 14:40:40 +00001292 ALOGD_IF(debugResampling(), "Not resampled, missing id %d", id);
Jeff Brown5912f952013-07-01 19:10:31 -07001293 return;
1294 }
1295 }
1296
1297 // Find the data to use for resampling.
1298 const History* other;
1299 History future;
1300 float alpha;
1301 if (next) {
1302 // Interpolate between current sample and future sample.
1303 // So current->eventTime <= sampleTime <= future.eventTime.
Siarhei Vishniakou0aeec072017-06-12 15:01:41 +01001304 future.initializeFrom(*next);
Jeff Brown5912f952013-07-01 19:10:31 -07001305 other = &future;
1306 nsecs_t delta = future.eventTime - current->eventTime;
1307 if (delta < RESAMPLE_MIN_DELTA) {
Harry Cutts6c658cc2023-08-02 14:40:40 +00001308 ALOGD_IF(debugResampling(), "Not resampled, delta time is too small: %" PRId64 " ns.",
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001309 delta);
Jeff Brown5912f952013-07-01 19:10:31 -07001310 return;
1311 }
1312 alpha = float(sampleTime - current->eventTime) / delta;
1313 } else if (touchState.historySize >= 2) {
1314 // Extrapolate future sample using current sample and past sample.
1315 // So other->eventTime <= current->eventTime <= sampleTime.
1316 other = touchState.getHistory(1);
1317 nsecs_t delta = current->eventTime - other->eventTime;
1318 if (delta < RESAMPLE_MIN_DELTA) {
Harry Cutts6c658cc2023-08-02 14:40:40 +00001319 ALOGD_IF(debugResampling(), "Not resampled, delta time is too small: %" PRId64 " ns.",
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001320 delta);
Andrew de los Reyesde18f6c2015-10-01 15:57:25 -07001321 return;
1322 } else if (delta > RESAMPLE_MAX_DELTA) {
Harry Cutts6c658cc2023-08-02 14:40:40 +00001323 ALOGD_IF(debugResampling(), "Not resampled, delta time is too large: %" PRId64 " ns.",
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001324 delta);
Jeff Brown5912f952013-07-01 19:10:31 -07001325 return;
1326 }
1327 nsecs_t maxPredict = current->eventTime + min(delta / 2, RESAMPLE_MAX_PREDICTION);
1328 if (sampleTime > maxPredict) {
Harry Cutts6c658cc2023-08-02 14:40:40 +00001329 ALOGD_IF(debugResampling(),
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001330 "Sample time is too far in the future, adjusting prediction "
1331 "from %" PRId64 " to %" PRId64 " ns.",
1332 sampleTime - current->eventTime, maxPredict - current->eventTime);
Jeff Brown5912f952013-07-01 19:10:31 -07001333 sampleTime = maxPredict;
1334 }
1335 alpha = float(current->eventTime - sampleTime) / delta;
1336 } else {
Harry Cutts6c658cc2023-08-02 14:40:40 +00001337 ALOGD_IF(debugResampling(), "Not resampled, insufficient data.");
Jeff Brown5912f952013-07-01 19:10:31 -07001338 return;
1339 }
1340
Siarhei Vishniakou0ced3cc2017-11-21 15:33:17 -08001341 if (current->eventTime == sampleTime) {
1342 // Prevents having 2 events with identical times and coordinates.
1343 return;
1344 }
1345
Jeff Brown5912f952013-07-01 19:10:31 -07001346 // Resample touch coordinates.
Siarhei Vishniakou56c9ae12017-11-06 21:16:47 -08001347 History oldLastResample;
1348 oldLastResample.initializeFrom(touchState.lastResample);
Jeff Brown5912f952013-07-01 19:10:31 -07001349 touchState.lastResample.eventTime = sampleTime;
1350 touchState.lastResample.idBits.clear();
1351 for (size_t i = 0; i < pointerCount; i++) {
1352 uint32_t id = event->getPointerId(i);
1353 touchState.lastResample.idToIndex[id] = i;
1354 touchState.lastResample.idBits.markBit(id);
Siarhei Vishniakou56c9ae12017-11-06 21:16:47 -08001355 if (oldLastResample.hasPointerId(id) && touchState.recentCoordinatesAreIdentical(id)) {
1356 // We maintain the previously resampled value for this pointer (stored in
1357 // oldLastResample) when the coordinates for this pointer haven't changed since then.
1358 // This way we don't introduce artificial jitter when pointers haven't actually moved.
Philip Quinnafb31282022-12-20 18:17:55 -08001359 // The isResampled flag isn't cleared as the values don't reflect what the device is
1360 // actually reporting.
Siarhei Vishniakou56c9ae12017-11-06 21:16:47 -08001361
1362 // We know here that the coordinates for the pointer haven't changed because we
1363 // would've cleared the resampled bit in rewriteMessage if they had. We can't modify
1364 // lastResample in place becasue the mapping from pointer ID to index may have changed.
Siarhei Vishniakou73e6d372023-07-06 18:07:21 -07001365 touchState.lastResample.pointers[i] = oldLastResample.getPointerById(id);
Siarhei Vishniakou56c9ae12017-11-06 21:16:47 -08001366 continue;
1367 }
1368
Jeff Brown5912f952013-07-01 19:10:31 -07001369 PointerCoords& resampledCoords = touchState.lastResample.pointers[i];
1370 const PointerCoords& currentCoords = current->getPointerById(id);
Siarhei Vishniakou73e6d372023-07-06 18:07:21 -07001371 resampledCoords = currentCoords;
Philip Quinn4e955a22023-09-26 12:09:40 -07001372 resampledCoords.isResampled = true;
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001373 if (other->idBits.hasBit(id) && shouldResampleTool(event->getToolType(i))) {
Jeff Brown5912f952013-07-01 19:10:31 -07001374 const PointerCoords& otherCoords = other->getPointerById(id);
Jeff Brown5912f952013-07-01 19:10:31 -07001375 resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001376 lerp(currentCoords.getX(), otherCoords.getX(), alpha));
Jeff Brown5912f952013-07-01 19:10:31 -07001377 resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001378 lerp(currentCoords.getY(), otherCoords.getY(), alpha));
Harry Cutts6c658cc2023-08-02 14:40:40 +00001379 ALOGD_IF(debugResampling(),
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001380 "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
1381 "other (%0.3f, %0.3f), alpha %0.3f",
1382 id, resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
1383 currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha);
Jeff Brown5912f952013-07-01 19:10:31 -07001384 } else {
Harry Cutts6c658cc2023-08-02 14:40:40 +00001385 ALOGD_IF(debugResampling(), "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f)", id,
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001386 resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
1387 currentCoords.getY());
Jeff Brown5912f952013-07-01 19:10:31 -07001388 }
1389 }
1390
1391 event->addSample(sampleTime, touchState.lastResample.pointers);
1392}
1393
Jeff Brown5912f952013-07-01 19:10:31 -07001394status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001395 ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
1396 "channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s",
1397 mChannel->getName().c_str(), seq, toString(handled));
Jeff Brown5912f952013-07-01 19:10:31 -07001398
1399 if (!seq) {
1400 ALOGE("Attempted to send a finished signal with sequence number 0.");
1401 return BAD_VALUE;
1402 }
1403
1404 // Send finished signals for the batch sequence chain first.
1405 size_t seqChainCount = mSeqChains.size();
1406 if (seqChainCount) {
1407 uint32_t currentSeq = seq;
1408 uint32_t chainSeqs[seqChainCount];
1409 size_t chainIndex = 0;
Dan Austin1faef802015-09-22 14:28:07 -07001410 for (size_t i = seqChainCount; i > 0; ) {
1411 i--;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001412 const SeqChain& seqChain = mSeqChains[i];
Jeff Brown5912f952013-07-01 19:10:31 -07001413 if (seqChain.seq == currentSeq) {
1414 currentSeq = seqChain.chain;
1415 chainSeqs[chainIndex++] = currentSeq;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001416 mSeqChains.erase(mSeqChains.begin() + i);
Jeff Brown5912f952013-07-01 19:10:31 -07001417 }
1418 }
1419 status_t status = OK;
Dan Austin1faef802015-09-22 14:28:07 -07001420 while (!status && chainIndex > 0) {
1421 chainIndex--;
Jeff Brown5912f952013-07-01 19:10:31 -07001422 status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
1423 }
1424 if (status) {
1425 // An error occurred so at least one signal was not sent, reconstruct the chain.
gaoshang9090d4f2017-05-17 14:36:46 +08001426 for (;;) {
Jeff Brown5912f952013-07-01 19:10:31 -07001427 SeqChain seqChain;
1428 seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
1429 seqChain.chain = chainSeqs[chainIndex];
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001430 mSeqChains.push_back(seqChain);
gaoshang9090d4f2017-05-17 14:36:46 +08001431 if (!chainIndex) break;
1432 chainIndex--;
1433 }
Jeff Brown5912f952013-07-01 19:10:31 -07001434 return status;
1435 }
1436 }
1437
1438 // Send finished signal for the last message in the batch.
1439 return sendUnchainedFinishedSignal(seq, handled);
1440}
1441
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001442status_t InputConsumer::sendTimeline(int32_t inputEventId,
1443 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline) {
Prabir Pradhan60dd97a2023-02-23 02:23:02 +00001444 ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
1445 "channel '%s' consumer ~ sendTimeline: inputEventId=%" PRId32
1446 ", gpuCompletedTime=%" PRId64 ", presentTime=%" PRId64,
1447 mChannel->getName().c_str(), inputEventId,
1448 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME],
1449 graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001450
1451 InputMessage msg;
1452 msg.header.type = InputMessage::Type::TIMELINE;
1453 msg.header.seq = 0;
1454 msg.body.timeline.eventId = inputEventId;
1455 msg.body.timeline.graphicsTimeline = std::move(graphicsTimeline);
1456 return mChannel->sendMessage(&msg);
1457}
1458
Siarhei Vishniakou3531ae72021-02-02 12:12:27 -10001459nsecs_t InputConsumer::getConsumeTime(uint32_t seq) const {
1460 auto it = mConsumeTimes.find(seq);
1461 // Consume time will be missing if either 'finishInputEvent' is called twice, or if it was
1462 // called for the wrong (synthetic?) input event. Either way, it is a bug that should be fixed.
1463 LOG_ALWAYS_FATAL_IF(it == mConsumeTimes.end(), "Could not find consume time for seq=%" PRIu32,
1464 seq);
1465 return it->second;
1466}
1467
1468void InputConsumer::popConsumeTime(uint32_t seq) {
1469 mConsumeTimes.erase(seq);
1470}
1471
Jeff Brown5912f952013-07-01 19:10:31 -07001472status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
1473 InputMessage msg;
Siarhei Vishniakou52402772019-10-22 09:32:30 -07001474 msg.header.type = InputMessage::Type::FINISHED;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001475 msg.header.seq = seq;
Siarhei Vishniakou38b7f7f2021-03-05 01:57:08 +00001476 msg.body.finished.handled = handled;
Siarhei Vishniakou3531ae72021-02-02 12:12:27 -10001477 msg.body.finished.consumeTime = getConsumeTime(seq);
1478 status_t result = mChannel->sendMessage(&msg);
1479 if (result == OK) {
1480 // Remove the consume time if the socket write succeeded. We will not need to ack this
1481 // message anymore. If the socket write did not succeed, we will try again and will still
1482 // need consume time.
1483 popConsumeTime(seq);
Siarhei Vishniakouca42e0d2024-01-12 12:10:32 -08001484
1485 // Trace the event processing timeline - event was just finished
1486 ATRACE_ASYNC_END("InputConsumer processing", /*cookie=*/seq);
Siarhei Vishniakou3531ae72021-02-02 12:12:27 -10001487 }
1488 return result;
Jeff Brown5912f952013-07-01 19:10:31 -07001489}
1490
Jeff Brown5912f952013-07-01 19:10:31 -07001491bool InputConsumer::hasPendingBatch() const {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001492 return !mBatches.empty();
Jeff Brown5912f952013-07-01 19:10:31 -07001493}
1494
Arthur Hungc7812be2020-02-27 22:40:27 +08001495int32_t InputConsumer::getPendingBatchSource() const {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001496 if (mBatches.empty()) {
Arthur Hungc7812be2020-02-27 22:40:27 +08001497 return AINPUT_SOURCE_CLASS_NONE;
1498 }
1499
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001500 const Batch& batch = mBatches[0];
1501 const InputMessage& head = batch.samples[0];
Arthur Hungc7812be2020-02-27 22:40:27 +08001502 return head.body.motion.source;
1503}
1504
Egor Paskoa0d32af2023-12-14 17:45:41 +01001505bool InputConsumer::probablyHasInput() const {
1506 return hasPendingBatch() || mChannel->probablyHasInput();
1507}
1508
Jeff Brown5912f952013-07-01 19:10:31 -07001509ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const {
1510 for (size_t i = 0; i < mBatches.size(); i++) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001511 const Batch& batch = mBatches[i];
1512 const InputMessage& head = batch.samples[0];
Jeff Brown5912f952013-07-01 19:10:31 -07001513 if (head.body.motion.deviceId == deviceId && head.body.motion.source == source) {
1514 return i;
1515 }
1516 }
1517 return -1;
1518}
1519
1520ssize_t InputConsumer::findTouchState(int32_t deviceId, int32_t source) const {
1521 for (size_t i = 0; i < mTouchStates.size(); i++) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001522 const TouchState& touchState = mTouchStates[i];
Jeff Brown5912f952013-07-01 19:10:31 -07001523 if (touchState.deviceId == deviceId && touchState.source == source) {
1524 return i;
1525 }
1526 }
1527 return -1;
1528}
1529
Jeff Brown5912f952013-07-01 19:10:31 -07001530bool InputConsumer::canAddSample(const Batch& batch, const InputMessage *msg) {
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001531 const InputMessage& head = batch.samples[0];
Narayan Kamathbc6001b2014-05-02 17:53:33 +01001532 uint32_t pointerCount = msg->body.motion.pointerCount;
Jeff Brown5912f952013-07-01 19:10:31 -07001533 if (head.body.motion.pointerCount != pointerCount
1534 || head.body.motion.action != msg->body.motion.action) {
1535 return false;
1536 }
1537 for (size_t i = 0; i < pointerCount; i++) {
1538 if (head.body.motion.pointers[i].properties
1539 != msg->body.motion.pointers[i].properties) {
1540 return false;
1541 }
1542 }
1543 return true;
1544}
1545
1546ssize_t InputConsumer::findSampleNoLaterThan(const Batch& batch, nsecs_t time) {
1547 size_t numSamples = batch.samples.size();
1548 size_t index = 0;
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001549 while (index < numSamples && batch.samples[index].body.motion.eventTime <= time) {
Jeff Brown5912f952013-07-01 19:10:31 -07001550 index += 1;
1551 }
1552 return ssize_t(index) - 1;
1553}
1554
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001555std::string InputConsumer::dump() const {
1556 std::string out;
1557 out = out + "mResampleTouch = " + toString(mResampleTouch) + "\n";
1558 out = out + "mChannel = " + mChannel->getName() + "\n";
1559 out = out + "mMsgDeferred: " + toString(mMsgDeferred) + "\n";
1560 if (mMsgDeferred) {
Dominik Laskowski75788452021-02-09 18:51:25 -08001561 out = out + "mMsg : " + ftl::enum_string(mMsg.header.type) + "\n";
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001562 }
1563 out += "Batches:\n";
1564 for (const Batch& batch : mBatches) {
1565 out += " Batch:\n";
1566 for (const InputMessage& msg : batch.samples) {
1567 out += android::base::StringPrintf(" Message %" PRIu32 ": %s ", msg.header.seq,
Dominik Laskowski75788452021-02-09 18:51:25 -08001568 ftl::enum_string(msg.header.type).c_str());
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001569 switch (msg.header.type) {
1570 case InputMessage::Type::KEY: {
1571 out += android::base::StringPrintf("action=%s keycode=%" PRId32,
1572 KeyEvent::actionToString(
1573 msg.body.key.action),
1574 msg.body.key.keyCode);
1575 break;
1576 }
1577 case InputMessage::Type::MOTION: {
1578 out = out + "action=" + MotionEvent::actionToString(msg.body.motion.action);
1579 for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
1580 const float x = msg.body.motion.pointers[i].coords.getX();
1581 const float y = msg.body.motion.pointers[i].coords.getY();
1582 out += android::base::StringPrintf("\n Pointer %" PRIu32
1583 " : x=%.1f y=%.1f",
1584 i, x, y);
1585 }
1586 break;
1587 }
1588 case InputMessage::Type::FINISHED: {
Siarhei Vishniakou3531ae72021-02-02 12:12:27 -10001589 out += android::base::StringPrintf("handled=%s, consumeTime=%" PRId64,
1590 toString(msg.body.finished.handled),
1591 msg.body.finished.consumeTime);
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001592 break;
1593 }
1594 case InputMessage::Type::FOCUS: {
Antonio Kantek3cfec7b2021-11-05 18:26:17 -07001595 out += android::base::StringPrintf("hasFocus=%s",
1596 toString(msg.body.focus.hasFocus));
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001597 break;
1598 }
Prabir Pradhan3f37b7b2020-11-10 16:50:18 -08001599 case InputMessage::Type::CAPTURE: {
1600 out += android::base::StringPrintf("hasCapture=%s",
1601 toString(msg.body.capture
1602 .pointerCaptureEnabled));
1603 break;
1604 }
arthurhung7632c332020-12-30 16:58:01 +08001605 case InputMessage::Type::DRAG: {
1606 out += android::base::StringPrintf("x=%.1f y=%.1f, isExiting=%s",
1607 msg.body.drag.x, msg.body.drag.y,
1608 toString(msg.body.drag.isExiting));
1609 break;
1610 }
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001611 case InputMessage::Type::TIMELINE: {
1612 const nsecs_t gpuCompletedTime =
1613 msg.body.timeline
1614 .graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME];
1615 const nsecs_t presentTime =
1616 msg.body.timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME];
1617 out += android::base::StringPrintf("inputEventId=%" PRId32
1618 ", gpuCompletedTime=%" PRId64
1619 ", presentTime=%" PRId64,
1620 msg.body.timeline.eventId, gpuCompletedTime,
1621 presentTime);
1622 break;
1623 }
Antonio Kantek7cdf8ef2021-07-13 18:04:53 -07001624 case InputMessage::Type::TOUCH_MODE: {
1625 out += android::base::StringPrintf("isInTouchMode=%s",
1626 toString(msg.body.touchMode.isInTouchMode));
1627 break;
1628 }
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001629 }
1630 out += "\n";
1631 }
1632 }
1633 if (mBatches.empty()) {
1634 out += " <empty>\n";
1635 }
1636 out += "mSeqChains:\n";
1637 for (const SeqChain& chain : mSeqChains) {
1638 out += android::base::StringPrintf(" chain: seq = %" PRIu32 " chain=%" PRIu32, chain.seq,
1639 chain.chain);
1640 }
1641 if (mSeqChains.empty()) {
1642 out += " <empty>\n";
1643 }
Siarhei Vishniakou3531ae72021-02-02 12:12:27 -10001644 out += "mConsumeTimes:\n";
1645 for (const auto& [seq, consumeTime] : mConsumeTimes) {
1646 out += android::base::StringPrintf(" seq = %" PRIu32 " consumeTime = %" PRId64, seq,
1647 consumeTime);
1648 }
1649 if (mConsumeTimes.empty()) {
1650 out += " <empty>\n";
1651 }
Siarhei Vishniakoua64c1592020-06-22 12:02:29 -05001652 return out;
1653}
1654
Jeff Brown5912f952013-07-01 19:10:31 -07001655} // namespace android