1 //
2 // Copyright 2010 The Android Open Source Project
3 //
4 // Provides a shared memory transport for input events.
5 //
6 #define LOG_TAG "InputTransport"
7
8 //#define LOG_NDEBUG 0
9
10 // Log debug messages about channel messages (send message, receive message)
11 #define DEBUG_CHANNEL_MESSAGES 0
12
13 // Log debug messages whenever InputChannel objects are created/destroyed
14 #define DEBUG_CHANNEL_LIFECYCLE 0
15
16 // Log debug messages about transport actions
17 #define DEBUG_TRANSPORT_ACTIONS 0
18
19 // Log debug messages about touch event resampling
20 #define DEBUG_RESAMPLING 0
21
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <math.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <unistd.h>
29
30 #include <cutils/log.h>
31 #include <cutils/properties.h>
32 #include <input/InputTransport.h>
33
34
35 namespace android {
36
37 // Socket buffer size. The default is typically about 128KB, which is much larger than
38 // we really need. So we make it smaller. It just needs to be big enough to hold
39 // a few dozen large multi-finger motion events in the case where an application gets
40 // behind processing touches.
41 static const size_t SOCKET_BUFFER_SIZE = 32 * 1024;
42
43 // Nanoseconds per milliseconds.
44 static const nsecs_t NANOS_PER_MS = 1000000;
45
46 // Latency added during resampling. A few milliseconds doesn't hurt much but
47 // reduces the impact of mispredicted touch positions.
48 static const nsecs_t RESAMPLE_LATENCY = 5 * NANOS_PER_MS;
49
50 // Minimum time difference between consecutive samples before attempting to resample.
51 static const nsecs_t RESAMPLE_MIN_DELTA = 2 * NANOS_PER_MS;
52
53 // Maximum time to predict forward from the last known state, to avoid predicting too
54 // far into the future. This time is further bounded by 50% of the last time delta.
55 static const nsecs_t RESAMPLE_MAX_PREDICTION = 8 * NANOS_PER_MS;
56
57 template<typename T>
min(const T & a,const T & b)58 inline static T min(const T& a, const T& b) {
59 return a < b ? a : b;
60 }
61
lerp(float a,float b,float alpha)62 inline static float lerp(float a, float b, float alpha) {
63 return a + alpha * (b - a);
64 }
65
66 // --- InputMessage ---
67
isValid(size_t actualSize) const68 bool InputMessage::isValid(size_t actualSize) const {
69 if (size() == actualSize) {
70 switch (header.type) {
71 case TYPE_KEY:
72 return true;
73 case TYPE_MOTION:
74 return body.motion.pointerCount > 0
75 && body.motion.pointerCount <= MAX_POINTERS;
76 case TYPE_FINISHED:
77 return true;
78 }
79 }
80 return false;
81 }
82
size() const83 size_t InputMessage::size() const {
84 switch (header.type) {
85 case TYPE_KEY:
86 return sizeof(Header) + body.key.size();
87 case TYPE_MOTION:
88 return sizeof(Header) + body.motion.size();
89 case TYPE_FINISHED:
90 return sizeof(Header) + body.finished.size();
91 }
92 return sizeof(Header);
93 }
94
95
96 // --- InputChannel ---
97
InputChannel(const String8 & name,int fd)98 InputChannel::InputChannel(const String8& name, int fd) :
99 mName(name), mFd(fd) {
100 #if DEBUG_CHANNEL_LIFECYCLE
101 ALOGD("Input channel constructed: name='%s', fd=%d",
102 mName.string(), fd);
103 #endif
104
105 int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
106 LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket "
107 "non-blocking. errno=%d", mName.string(), errno);
108 }
109
~InputChannel()110 InputChannel::~InputChannel() {
111 #if DEBUG_CHANNEL_LIFECYCLE
112 ALOGD("Input channel destroyed: name='%s', fd=%d",
113 mName.string(), mFd);
114 #endif
115
116 ::close(mFd);
117 }
118
openInputChannelPair(const String8 & name,sp<InputChannel> & outServerChannel,sp<InputChannel> & outClientChannel)119 status_t InputChannel::openInputChannelPair(const String8& name,
120 sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
121 int sockets[2];
122 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
123 status_t result = -errno;
124 ALOGE("channel '%s' ~ Could not create socket pair. errno=%d",
125 name.string(), errno);
126 outServerChannel.clear();
127 outClientChannel.clear();
128 return result;
129 }
130
131 int bufferSize = SOCKET_BUFFER_SIZE;
132 setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
133 setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
134 setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
135 setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
136
137 String8 serverChannelName = name;
138 serverChannelName.append(" (server)");
139 outServerChannel = new InputChannel(serverChannelName, sockets[0]);
140
141 String8 clientChannelName = name;
142 clientChannelName.append(" (client)");
143 outClientChannel = new InputChannel(clientChannelName, sockets[1]);
144 return OK;
145 }
146
sendMessage(const InputMessage * msg)147 status_t InputChannel::sendMessage(const InputMessage* msg) {
148 size_t msgLength = msg->size();
149 ssize_t nWrite;
150 do {
151 nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
152 } while (nWrite == -1 && errno == EINTR);
153
154 if (nWrite < 0) {
155 int error = errno;
156 #if DEBUG_CHANNEL_MESSAGES
157 ALOGD("channel '%s' ~ error sending message of type %d, errno=%d", mName.string(),
158 msg->header.type, error);
159 #endif
160 if (error == EAGAIN || error == EWOULDBLOCK) {
161 return WOULD_BLOCK;
162 }
163 if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {
164 return DEAD_OBJECT;
165 }
166 return -error;
167 }
168
169 if (size_t(nWrite) != msgLength) {
170 #if DEBUG_CHANNEL_MESSAGES
171 ALOGD("channel '%s' ~ error sending message type %d, send was incomplete",
172 mName.string(), msg->header.type);
173 #endif
174 return DEAD_OBJECT;
175 }
176
177 #if DEBUG_CHANNEL_MESSAGES
178 ALOGD("channel '%s' ~ sent message of type %d", mName.string(), msg->header.type);
179 #endif
180 return OK;
181 }
182
receiveMessage(InputMessage * msg)183 status_t InputChannel::receiveMessage(InputMessage* msg) {
184 ssize_t nRead;
185 do {
186 nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
187 } while (nRead == -1 && errno == EINTR);
188
189 if (nRead < 0) {
190 int error = errno;
191 #if DEBUG_CHANNEL_MESSAGES
192 ALOGD("channel '%s' ~ receive message failed, errno=%d", mName.string(), errno);
193 #endif
194 if (error == EAGAIN || error == EWOULDBLOCK) {
195 return WOULD_BLOCK;
196 }
197 if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) {
198 return DEAD_OBJECT;
199 }
200 return -error;
201 }
202
203 if (nRead == 0) { // check for EOF
204 #if DEBUG_CHANNEL_MESSAGES
205 ALOGD("channel '%s' ~ receive message failed because peer was closed", mName.string());
206 #endif
207 return DEAD_OBJECT;
208 }
209
210 if (!msg->isValid(nRead)) {
211 #if DEBUG_CHANNEL_MESSAGES
212 ALOGD("channel '%s' ~ received invalid message", mName.string());
213 #endif
214 return BAD_VALUE;
215 }
216
217 #if DEBUG_CHANNEL_MESSAGES
218 ALOGD("channel '%s' ~ received message of type %d", mName.string(), msg->header.type);
219 #endif
220 return OK;
221 }
222
dup() const223 sp<InputChannel> InputChannel::dup() const {
224 int fd = ::dup(getFd());
225 return fd >= 0 ? new InputChannel(getName(), fd) : NULL;
226 }
227
228
229 // --- InputPublisher ---
230
InputPublisher(const sp<InputChannel> & channel)231 InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
232 mChannel(channel) {
233 }
234
~InputPublisher()235 InputPublisher::~InputPublisher() {
236 }
237
publishKeyEvent(uint32_t seq,int32_t deviceId,int32_t source,int32_t action,int32_t flags,int32_t keyCode,int32_t scanCode,int32_t metaState,int32_t repeatCount,nsecs_t downTime,nsecs_t eventTime)238 status_t InputPublisher::publishKeyEvent(
239 uint32_t seq,
240 int32_t deviceId,
241 int32_t source,
242 int32_t action,
243 int32_t flags,
244 int32_t keyCode,
245 int32_t scanCode,
246 int32_t metaState,
247 int32_t repeatCount,
248 nsecs_t downTime,
249 nsecs_t eventTime) {
250 #if DEBUG_TRANSPORT_ACTIONS
251 ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x, "
252 "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
253 "downTime=%lld, eventTime=%lld",
254 mChannel->getName().string(), seq,
255 deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
256 downTime, eventTime);
257 #endif
258
259 if (!seq) {
260 ALOGE("Attempted to publish a key event with sequence number 0.");
261 return BAD_VALUE;
262 }
263
264 InputMessage msg;
265 msg.header.type = InputMessage::TYPE_KEY;
266 msg.body.key.seq = seq;
267 msg.body.key.deviceId = deviceId;
268 msg.body.key.source = source;
269 msg.body.key.action = action;
270 msg.body.key.flags = flags;
271 msg.body.key.keyCode = keyCode;
272 msg.body.key.scanCode = scanCode;
273 msg.body.key.metaState = metaState;
274 msg.body.key.repeatCount = repeatCount;
275 msg.body.key.downTime = downTime;
276 msg.body.key.eventTime = eventTime;
277 return mChannel->sendMessage(&msg);
278 }
279
publishMotionEvent(uint32_t seq,int32_t deviceId,int32_t source,int32_t action,int32_t flags,int32_t edgeFlags,int32_t metaState,int32_t buttonState,float xOffset,float yOffset,float xPrecision,float yPrecision,nsecs_t downTime,nsecs_t eventTime,size_t pointerCount,const PointerProperties * pointerProperties,const PointerCoords * pointerCoords)280 status_t InputPublisher::publishMotionEvent(
281 uint32_t seq,
282 int32_t deviceId,
283 int32_t source,
284 int32_t action,
285 int32_t flags,
286 int32_t edgeFlags,
287 int32_t metaState,
288 int32_t buttonState,
289 float xOffset,
290 float yOffset,
291 float xPrecision,
292 float yPrecision,
293 nsecs_t downTime,
294 nsecs_t eventTime,
295 size_t pointerCount,
296 const PointerProperties* pointerProperties,
297 const PointerCoords* pointerCoords) {
298 #if DEBUG_TRANSPORT_ACTIONS
299 ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
300 "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
301 "xOffset=%f, yOffset=%f, "
302 "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
303 "pointerCount=%d",
304 mChannel->getName().string(), seq,
305 deviceId, source, action, flags, edgeFlags, metaState, buttonState,
306 xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
307 #endif
308
309 if (!seq) {
310 ALOGE("Attempted to publish a motion event with sequence number 0.");
311 return BAD_VALUE;
312 }
313
314 if (pointerCount > MAX_POINTERS || pointerCount < 1) {
315 ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.",
316 mChannel->getName().string(), pointerCount);
317 return BAD_VALUE;
318 }
319
320 InputMessage msg;
321 msg.header.type = InputMessage::TYPE_MOTION;
322 msg.body.motion.seq = seq;
323 msg.body.motion.deviceId = deviceId;
324 msg.body.motion.source = source;
325 msg.body.motion.action = action;
326 msg.body.motion.flags = flags;
327 msg.body.motion.edgeFlags = edgeFlags;
328 msg.body.motion.metaState = metaState;
329 msg.body.motion.buttonState = buttonState;
330 msg.body.motion.xOffset = xOffset;
331 msg.body.motion.yOffset = yOffset;
332 msg.body.motion.xPrecision = xPrecision;
333 msg.body.motion.yPrecision = yPrecision;
334 msg.body.motion.downTime = downTime;
335 msg.body.motion.eventTime = eventTime;
336 msg.body.motion.pointerCount = pointerCount;
337 for (size_t i = 0; i < pointerCount; i++) {
338 msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]);
339 msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);
340 }
341 return mChannel->sendMessage(&msg);
342 }
343
receiveFinishedSignal(uint32_t * outSeq,bool * outHandled)344 status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) {
345 #if DEBUG_TRANSPORT_ACTIONS
346 ALOGD("channel '%s' publisher ~ receiveFinishedSignal",
347 mChannel->getName().string());
348 #endif
349
350 InputMessage msg;
351 status_t result = mChannel->receiveMessage(&msg);
352 if (result) {
353 *outSeq = 0;
354 *outHandled = false;
355 return result;
356 }
357 if (msg.header.type != InputMessage::TYPE_FINISHED) {
358 ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer",
359 mChannel->getName().string(), msg.header.type);
360 return UNKNOWN_ERROR;
361 }
362 *outSeq = msg.body.finished.seq;
363 *outHandled = msg.body.finished.handled;
364 return OK;
365 }
366
367 // --- InputConsumer ---
368
InputConsumer(const sp<InputChannel> & channel)369 InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
370 mResampleTouch(isTouchResamplingEnabled()),
371 mChannel(channel), mMsgDeferred(false) {
372 }
373
~InputConsumer()374 InputConsumer::~InputConsumer() {
375 }
376
isTouchResamplingEnabled()377 bool InputConsumer::isTouchResamplingEnabled() {
378 char value[PROPERTY_VALUE_MAX];
379 int length = property_get("ro.input.noresample", value, NULL);
380 if (length > 0) {
381 if (!strcmp("1", value)) {
382 return false;
383 }
384 if (strcmp("0", value)) {
385 ALOGD("Unrecognized property value for 'ro.input.noresample'. "
386 "Use '1' or '0'.");
387 }
388 }
389 return true;
390 }
391
consume(InputEventFactoryInterface * factory,bool consumeBatches,nsecs_t frameTime,uint32_t * outSeq,InputEvent ** outEvent)392 status_t InputConsumer::consume(InputEventFactoryInterface* factory,
393 bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
394 #if DEBUG_TRANSPORT_ACTIONS
395 ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%lld",
396 mChannel->getName().string(), consumeBatches ? "true" : "false", frameTime);
397 #endif
398
399 *outSeq = 0;
400 *outEvent = NULL;
401
402 // Fetch the next input message.
403 // Loop until an event can be returned or no additional events are received.
404 while (!*outEvent) {
405 if (mMsgDeferred) {
406 // mMsg contains a valid input message from the previous call to consume
407 // that has not yet been processed.
408 mMsgDeferred = false;
409 } else {
410 // Receive a fresh message.
411 status_t result = mChannel->receiveMessage(&mMsg);
412 if (result) {
413 // Consume the next batched event unless batches are being held for later.
414 if (consumeBatches || result != WOULD_BLOCK) {
415 result = consumeBatch(factory, frameTime, outSeq, outEvent);
416 if (*outEvent) {
417 #if DEBUG_TRANSPORT_ACTIONS
418 ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
419 mChannel->getName().string(), *outSeq);
420 #endif
421 break;
422 }
423 }
424 return result;
425 }
426 }
427
428 switch (mMsg.header.type) {
429 case InputMessage::TYPE_KEY: {
430 KeyEvent* keyEvent = factory->createKeyEvent();
431 if (!keyEvent) return NO_MEMORY;
432
433 initializeKeyEvent(keyEvent, &mMsg);
434 *outSeq = mMsg.body.key.seq;
435 *outEvent = keyEvent;
436 #if DEBUG_TRANSPORT_ACTIONS
437 ALOGD("channel '%s' consumer ~ consumed key event, seq=%u",
438 mChannel->getName().string(), *outSeq);
439 #endif
440 break;
441 }
442
443 case AINPUT_EVENT_TYPE_MOTION: {
444 ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source);
445 if (batchIndex >= 0) {
446 Batch& batch = mBatches.editItemAt(batchIndex);
447 if (canAddSample(batch, &mMsg)) {
448 batch.samples.push(mMsg);
449 #if DEBUG_TRANSPORT_ACTIONS
450 ALOGD("channel '%s' consumer ~ appended to batch event",
451 mChannel->getName().string());
452 #endif
453 break;
454 } else {
455 // We cannot append to the batch in progress, so we need to consume
456 // the previous batch right now and defer the new message until later.
457 mMsgDeferred = true;
458 status_t result = consumeSamples(factory,
459 batch, batch.samples.size(), outSeq, outEvent);
460 mBatches.removeAt(batchIndex);
461 if (result) {
462 return result;
463 }
464 #if DEBUG_TRANSPORT_ACTIONS
465 ALOGD("channel '%s' consumer ~ consumed batch event and "
466 "deferred current event, seq=%u",
467 mChannel->getName().string(), *outSeq);
468 #endif
469 break;
470 }
471 }
472
473 // Start a new batch if needed.
474 if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE
475 || mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
476 mBatches.push();
477 Batch& batch = mBatches.editTop();
478 batch.samples.push(mMsg);
479 #if DEBUG_TRANSPORT_ACTIONS
480 ALOGD("channel '%s' consumer ~ started batch event",
481 mChannel->getName().string());
482 #endif
483 break;
484 }
485
486 MotionEvent* motionEvent = factory->createMotionEvent();
487 if (! motionEvent) return NO_MEMORY;
488
489 updateTouchState(&mMsg);
490 initializeMotionEvent(motionEvent, &mMsg);
491 *outSeq = mMsg.body.motion.seq;
492 *outEvent = motionEvent;
493 #if DEBUG_TRANSPORT_ACTIONS
494 ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u",
495 mChannel->getName().string(), *outSeq);
496 #endif
497 break;
498 }
499
500 default:
501 ALOGE("channel '%s' consumer ~ Received unexpected message of type %d",
502 mChannel->getName().string(), mMsg.header.type);
503 return UNKNOWN_ERROR;
504 }
505 }
506 return OK;
507 }
508
consumeBatch(InputEventFactoryInterface * factory,nsecs_t frameTime,uint32_t * outSeq,InputEvent ** outEvent)509 status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
510 nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
511 status_t result;
512 for (size_t i = mBatches.size(); i-- > 0; ) {
513 Batch& batch = mBatches.editItemAt(i);
514 if (frameTime < 0) {
515 result = consumeSamples(factory, batch, batch.samples.size(),
516 outSeq, outEvent);
517 mBatches.removeAt(i);
518 return result;
519 }
520
521 nsecs_t sampleTime = frameTime;
522 if (mResampleTouch) {
523 sampleTime -= RESAMPLE_LATENCY;
524 }
525 ssize_t split = findSampleNoLaterThan(batch, sampleTime);
526 if (split < 0) {
527 continue;
528 }
529
530 result = consumeSamples(factory, batch, split + 1, outSeq, outEvent);
531 const InputMessage* next;
532 if (batch.samples.isEmpty()) {
533 mBatches.removeAt(i);
534 next = NULL;
535 } else {
536 next = &batch.samples.itemAt(0);
537 }
538 if (!result && mResampleTouch) {
539 resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next);
540 }
541 return result;
542 }
543
544 return WOULD_BLOCK;
545 }
546
consumeSamples(InputEventFactoryInterface * factory,Batch & batch,size_t count,uint32_t * outSeq,InputEvent ** outEvent)547 status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory,
548 Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent) {
549 MotionEvent* motionEvent = factory->createMotionEvent();
550 if (! motionEvent) return NO_MEMORY;
551
552 uint32_t chain = 0;
553 for (size_t i = 0; i < count; i++) {
554 InputMessage& msg = batch.samples.editItemAt(i);
555 updateTouchState(&msg);
556 if (i) {
557 SeqChain seqChain;
558 seqChain.seq = msg.body.motion.seq;
559 seqChain.chain = chain;
560 mSeqChains.push(seqChain);
561 addSample(motionEvent, &msg);
562 } else {
563 initializeMotionEvent(motionEvent, &msg);
564 }
565 chain = msg.body.motion.seq;
566 }
567 batch.samples.removeItemsAt(0, count);
568
569 *outSeq = chain;
570 *outEvent = motionEvent;
571 return OK;
572 }
573
updateTouchState(InputMessage * msg)574 void InputConsumer::updateTouchState(InputMessage* msg) {
575 if (!mResampleTouch ||
576 !(msg->body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
577 return;
578 }
579
580 int32_t deviceId = msg->body.motion.deviceId;
581 int32_t source = msg->body.motion.source;
582 nsecs_t eventTime = msg->body.motion.eventTime;
583
584 // Update the touch state history to incorporate the new input message.
585 // If the message is in the past relative to the most recently produced resampled
586 // touch, then use the resampled time and coordinates instead.
587 switch (msg->body.motion.action & AMOTION_EVENT_ACTION_MASK) {
588 case AMOTION_EVENT_ACTION_DOWN: {
589 ssize_t index = findTouchState(deviceId, source);
590 if (index < 0) {
591 mTouchStates.push();
592 index = mTouchStates.size() - 1;
593 }
594 TouchState& touchState = mTouchStates.editItemAt(index);
595 touchState.initialize(deviceId, source);
596 touchState.addHistory(msg);
597 break;
598 }
599
600 case AMOTION_EVENT_ACTION_MOVE: {
601 ssize_t index = findTouchState(deviceId, source);
602 if (index >= 0) {
603 TouchState& touchState = mTouchStates.editItemAt(index);
604 touchState.addHistory(msg);
605 if (eventTime < touchState.lastResample.eventTime) {
606 rewriteMessage(touchState, msg);
607 } else {
608 touchState.lastResample.idBits.clear();
609 }
610 }
611 break;
612 }
613
614 case AMOTION_EVENT_ACTION_POINTER_DOWN: {
615 ssize_t index = findTouchState(deviceId, source);
616 if (index >= 0) {
617 TouchState& touchState = mTouchStates.editItemAt(index);
618 touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
619 rewriteMessage(touchState, msg);
620 }
621 break;
622 }
623
624 case AMOTION_EVENT_ACTION_POINTER_UP: {
625 ssize_t index = findTouchState(deviceId, source);
626 if (index >= 0) {
627 TouchState& touchState = mTouchStates.editItemAt(index);
628 rewriteMessage(touchState, msg);
629 touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
630 }
631 break;
632 }
633
634 case AMOTION_EVENT_ACTION_SCROLL: {
635 ssize_t index = findTouchState(deviceId, source);
636 if (index >= 0) {
637 const TouchState& touchState = mTouchStates.itemAt(index);
638 rewriteMessage(touchState, msg);
639 }
640 break;
641 }
642
643 case AMOTION_EVENT_ACTION_UP:
644 case AMOTION_EVENT_ACTION_CANCEL: {
645 ssize_t index = findTouchState(deviceId, source);
646 if (index >= 0) {
647 const TouchState& touchState = mTouchStates.itemAt(index);
648 rewriteMessage(touchState, msg);
649 mTouchStates.removeAt(index);
650 }
651 break;
652 }
653 }
654 }
655
rewriteMessage(const TouchState & state,InputMessage * msg)656 void InputConsumer::rewriteMessage(const TouchState& state, InputMessage* msg) {
657 for (size_t i = 0; i < msg->body.motion.pointerCount; i++) {
658 uint32_t id = msg->body.motion.pointers[i].properties.id;
659 if (state.lastResample.idBits.hasBit(id)) {
660 PointerCoords& msgCoords = msg->body.motion.pointers[i].coords;
661 const PointerCoords& resampleCoords = state.lastResample.getPointerById(id);
662 #if DEBUG_RESAMPLING
663 ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
664 resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
665 resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_Y),
666 msgCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
667 msgCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
668 #endif
669 msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
670 msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
671 }
672 }
673 }
674
resampleTouchState(nsecs_t sampleTime,MotionEvent * event,const InputMessage * next)675 void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
676 const InputMessage* next) {
677 if (!mResampleTouch
678 || !(event->getSource() & AINPUT_SOURCE_CLASS_POINTER)
679 || event->getAction() != AMOTION_EVENT_ACTION_MOVE) {
680 return;
681 }
682
683 ssize_t index = findTouchState(event->getDeviceId(), event->getSource());
684 if (index < 0) {
685 #if DEBUG_RESAMPLING
686 ALOGD("Not resampled, no touch state for device.");
687 #endif
688 return;
689 }
690
691 TouchState& touchState = mTouchStates.editItemAt(index);
692 if (touchState.historySize < 1) {
693 #if DEBUG_RESAMPLING
694 ALOGD("Not resampled, no history for device.");
695 #endif
696 return;
697 }
698
699 // Ensure that the current sample has all of the pointers that need to be reported.
700 const History* current = touchState.getHistory(0);
701 size_t pointerCount = event->getPointerCount();
702 for (size_t i = 0; i < pointerCount; i++) {
703 uint32_t id = event->getPointerId(i);
704 if (!current->idBits.hasBit(id)) {
705 #if DEBUG_RESAMPLING
706 ALOGD("Not resampled, missing id %d", id);
707 #endif
708 return;
709 }
710 }
711
712 // Find the data to use for resampling.
713 const History* other;
714 History future;
715 float alpha;
716 if (next) {
717 // Interpolate between current sample and future sample.
718 // So current->eventTime <= sampleTime <= future.eventTime.
719 future.initializeFrom(next);
720 other = &future;
721 nsecs_t delta = future.eventTime - current->eventTime;
722 if (delta < RESAMPLE_MIN_DELTA) {
723 #if DEBUG_RESAMPLING
724 ALOGD("Not resampled, delta time is %lld ns.", delta);
725 #endif
726 return;
727 }
728 alpha = float(sampleTime - current->eventTime) / delta;
729 } else if (touchState.historySize >= 2) {
730 // Extrapolate future sample using current sample and past sample.
731 // So other->eventTime <= current->eventTime <= sampleTime.
732 other = touchState.getHistory(1);
733 nsecs_t delta = current->eventTime - other->eventTime;
734 if (delta < RESAMPLE_MIN_DELTA) {
735 #if DEBUG_RESAMPLING
736 ALOGD("Not resampled, delta time is %lld ns.", delta);
737 #endif
738 return;
739 }
740 nsecs_t maxPredict = current->eventTime + min(delta / 2, RESAMPLE_MAX_PREDICTION);
741 if (sampleTime > maxPredict) {
742 #if DEBUG_RESAMPLING
743 ALOGD("Sample time is too far in the future, adjusting prediction "
744 "from %lld to %lld ns.",
745 sampleTime - current->eventTime, maxPredict - current->eventTime);
746 #endif
747 sampleTime = maxPredict;
748 }
749 alpha = float(current->eventTime - sampleTime) / delta;
750 } else {
751 #if DEBUG_RESAMPLING
752 ALOGD("Not resampled, insufficient data.");
753 #endif
754 return;
755 }
756
757 // Resample touch coordinates.
758 touchState.lastResample.eventTime = sampleTime;
759 touchState.lastResample.idBits.clear();
760 for (size_t i = 0; i < pointerCount; i++) {
761 uint32_t id = event->getPointerId(i);
762 touchState.lastResample.idToIndex[id] = i;
763 touchState.lastResample.idBits.markBit(id);
764 PointerCoords& resampledCoords = touchState.lastResample.pointers[i];
765 const PointerCoords& currentCoords = current->getPointerById(id);
766 if (other->idBits.hasBit(id)
767 && shouldResampleTool(event->getToolType(i))) {
768 const PointerCoords& otherCoords = other->getPointerById(id);
769 resampledCoords.copyFrom(currentCoords);
770 resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
771 lerp(currentCoords.getX(), otherCoords.getX(), alpha));
772 resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
773 lerp(currentCoords.getY(), otherCoords.getY(), alpha));
774 #if DEBUG_RESAMPLING
775 ALOGD("[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
776 "other (%0.3f, %0.3f), alpha %0.3f",
777 id, resampledCoords.getX(), resampledCoords.getY(),
778 currentCoords.getX(), currentCoords.getY(),
779 otherCoords.getX(), otherCoords.getY(),
780 alpha);
781 #endif
782 } else {
783 resampledCoords.copyFrom(currentCoords);
784 #if DEBUG_RESAMPLING
785 ALOGD("[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f)",
786 id, resampledCoords.getX(), resampledCoords.getY(),
787 currentCoords.getX(), currentCoords.getY());
788 #endif
789 }
790 }
791
792 event->addSample(sampleTime, touchState.lastResample.pointers);
793 }
794
shouldResampleTool(int32_t toolType)795 bool InputConsumer::shouldResampleTool(int32_t toolType) {
796 return toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
797 || toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
798 }
799
sendFinishedSignal(uint32_t seq,bool handled)800 status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
801 #if DEBUG_TRANSPORT_ACTIONS
802 ALOGD("channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s",
803 mChannel->getName().string(), seq, handled ? "true" : "false");
804 #endif
805
806 if (!seq) {
807 ALOGE("Attempted to send a finished signal with sequence number 0.");
808 return BAD_VALUE;
809 }
810
811 // Send finished signals for the batch sequence chain first.
812 size_t seqChainCount = mSeqChains.size();
813 if (seqChainCount) {
814 uint32_t currentSeq = seq;
815 uint32_t chainSeqs[seqChainCount];
816 size_t chainIndex = 0;
817 for (size_t i = seqChainCount; i-- > 0; ) {
818 const SeqChain& seqChain = mSeqChains.itemAt(i);
819 if (seqChain.seq == currentSeq) {
820 currentSeq = seqChain.chain;
821 chainSeqs[chainIndex++] = currentSeq;
822 mSeqChains.removeAt(i);
823 }
824 }
825 status_t status = OK;
826 while (!status && chainIndex-- > 0) {
827 status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
828 }
829 if (status) {
830 // An error occurred so at least one signal was not sent, reconstruct the chain.
831 do {
832 SeqChain seqChain;
833 seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
834 seqChain.chain = chainSeqs[chainIndex];
835 mSeqChains.push(seqChain);
836 } while (chainIndex-- > 0);
837 return status;
838 }
839 }
840
841 // Send finished signal for the last message in the batch.
842 return sendUnchainedFinishedSignal(seq, handled);
843 }
844
sendUnchainedFinishedSignal(uint32_t seq,bool handled)845 status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
846 InputMessage msg;
847 msg.header.type = InputMessage::TYPE_FINISHED;
848 msg.body.finished.seq = seq;
849 msg.body.finished.handled = handled;
850 return mChannel->sendMessage(&msg);
851 }
852
hasDeferredEvent() const853 bool InputConsumer::hasDeferredEvent() const {
854 return mMsgDeferred;
855 }
856
hasPendingBatch() const857 bool InputConsumer::hasPendingBatch() const {
858 return !mBatches.isEmpty();
859 }
860
findBatch(int32_t deviceId,int32_t source) const861 ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const {
862 for (size_t i = 0; i < mBatches.size(); i++) {
863 const Batch& batch = mBatches.itemAt(i);
864 const InputMessage& head = batch.samples.itemAt(0);
865 if (head.body.motion.deviceId == deviceId && head.body.motion.source == source) {
866 return i;
867 }
868 }
869 return -1;
870 }
871
findTouchState(int32_t deviceId,int32_t source) const872 ssize_t InputConsumer::findTouchState(int32_t deviceId, int32_t source) const {
873 for (size_t i = 0; i < mTouchStates.size(); i++) {
874 const TouchState& touchState = mTouchStates.itemAt(i);
875 if (touchState.deviceId == deviceId && touchState.source == source) {
876 return i;
877 }
878 }
879 return -1;
880 }
881
initializeKeyEvent(KeyEvent * event,const InputMessage * msg)882 void InputConsumer::initializeKeyEvent(KeyEvent* event, const InputMessage* msg) {
883 event->initialize(
884 msg->body.key.deviceId,
885 msg->body.key.source,
886 msg->body.key.action,
887 msg->body.key.flags,
888 msg->body.key.keyCode,
889 msg->body.key.scanCode,
890 msg->body.key.metaState,
891 msg->body.key.repeatCount,
892 msg->body.key.downTime,
893 msg->body.key.eventTime);
894 }
895
initializeMotionEvent(MotionEvent * event,const InputMessage * msg)896 void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage* msg) {
897 size_t pointerCount = msg->body.motion.pointerCount;
898 PointerProperties pointerProperties[pointerCount];
899 PointerCoords pointerCoords[pointerCount];
900 for (size_t i = 0; i < pointerCount; i++) {
901 pointerProperties[i].copyFrom(msg->body.motion.pointers[i].properties);
902 pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords);
903 }
904
905 event->initialize(
906 msg->body.motion.deviceId,
907 msg->body.motion.source,
908 msg->body.motion.action,
909 msg->body.motion.flags,
910 msg->body.motion.edgeFlags,
911 msg->body.motion.metaState,
912 msg->body.motion.buttonState,
913 msg->body.motion.xOffset,
914 msg->body.motion.yOffset,
915 msg->body.motion.xPrecision,
916 msg->body.motion.yPrecision,
917 msg->body.motion.downTime,
918 msg->body.motion.eventTime,
919 pointerCount,
920 pointerProperties,
921 pointerCoords);
922 }
923
addSample(MotionEvent * event,const InputMessage * msg)924 void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) {
925 size_t pointerCount = msg->body.motion.pointerCount;
926 PointerCoords pointerCoords[pointerCount];
927 for (size_t i = 0; i < pointerCount; i++) {
928 pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords);
929 }
930
931 event->setMetaState(event->getMetaState() | msg->body.motion.metaState);
932 event->addSample(msg->body.motion.eventTime, pointerCoords);
933 }
934
canAddSample(const Batch & batch,const InputMessage * msg)935 bool InputConsumer::canAddSample(const Batch& batch, const InputMessage *msg) {
936 const InputMessage& head = batch.samples.itemAt(0);
937 size_t pointerCount = msg->body.motion.pointerCount;
938 if (head.body.motion.pointerCount != pointerCount
939 || head.body.motion.action != msg->body.motion.action) {
940 return false;
941 }
942 for (size_t i = 0; i < pointerCount; i++) {
943 if (head.body.motion.pointers[i].properties
944 != msg->body.motion.pointers[i].properties) {
945 return false;
946 }
947 }
948 return true;
949 }
950
findSampleNoLaterThan(const Batch & batch,nsecs_t time)951 ssize_t InputConsumer::findSampleNoLaterThan(const Batch& batch, nsecs_t time) {
952 size_t numSamples = batch.samples.size();
953 size_t index = 0;
954 while (index < numSamples
955 && batch.samples.itemAt(index).body.motion.eventTime <= time) {
956 index += 1;
957 }
958 return ssize_t(index) - 1;
959 }
960
961 } // namespace android
962