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 signalling (send signal, receive signal)
11 #define DEBUG_CHANNEL_SIGNALS 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 (initialize, reset, publish, ...)
17 #define DEBUG_TRANSPORT_ACTIONS 0
18
19
20 #include <cutils/ashmem.h>
21 #include <cutils/log.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25 #include <ui/InputTransport.h>
26 #include <unistd.h>
27
28 namespace android {
29
30 #define ROUND_UP(value, boundary) (((value) + (boundary) - 1) & ~((boundary) - 1))
31 #define MIN_HISTORY_DEPTH 20
32
33 // Must be at least sizeof(InputMessage) + sufficient space for pointer data
34 static const int DEFAULT_MESSAGE_BUFFER_SIZE = ROUND_UP(
35 sizeof(InputMessage) + MIN_HISTORY_DEPTH
36 * (sizeof(InputMessage::SampleData) + MAX_POINTERS * sizeof(PointerCoords)),
37 4096);
38
39 // Signal sent by the producer to the consumer to inform it that a new message is
40 // available to be consumed in the shared memory buffer.
41 static const char INPUT_SIGNAL_DISPATCH = 'D';
42
43 // Signal sent by the consumer to the producer to inform it that it has finished
44 // consuming the most recent message and it handled it.
45 static const char INPUT_SIGNAL_FINISHED_HANDLED = 'f';
46
47 // Signal sent by the consumer to the producer to inform it that it has finished
48 // consuming the most recent message but it did not handle it.
49 static const char INPUT_SIGNAL_FINISHED_UNHANDLED = 'u';
50
51
52 // --- InputChannel ---
53
InputChannel(const String8 & name,int32_t ashmemFd,int32_t receivePipeFd,int32_t sendPipeFd)54 InputChannel::InputChannel(const String8& name, int32_t ashmemFd, int32_t receivePipeFd,
55 int32_t sendPipeFd) :
56 mName(name), mAshmemFd(ashmemFd), mReceivePipeFd(receivePipeFd), mSendPipeFd(sendPipeFd) {
57 #if DEBUG_CHANNEL_LIFECYCLE
58 LOGD("Input channel constructed: name='%s', ashmemFd=%d, receivePipeFd=%d, sendPipeFd=%d",
59 mName.string(), ashmemFd, receivePipeFd, sendPipeFd);
60 #endif
61
62 int result = fcntl(mReceivePipeFd, F_SETFL, O_NONBLOCK);
63 LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make receive pipe "
64 "non-blocking. errno=%d", mName.string(), errno);
65
66 result = fcntl(mSendPipeFd, F_SETFL, O_NONBLOCK);
67 LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make send pipe "
68 "non-blocking. errno=%d", mName.string(), errno);
69 }
70
~InputChannel()71 InputChannel::~InputChannel() {
72 #if DEBUG_CHANNEL_LIFECYCLE
73 LOGD("Input channel destroyed: name='%s', ashmemFd=%d, receivePipeFd=%d, sendPipeFd=%d",
74 mName.string(), mAshmemFd, mReceivePipeFd, mSendPipeFd);
75 #endif
76
77 ::close(mAshmemFd);
78 ::close(mReceivePipeFd);
79 ::close(mSendPipeFd);
80 }
81
openInputChannelPair(const String8 & name,sp<InputChannel> & outServerChannel,sp<InputChannel> & outClientChannel)82 status_t InputChannel::openInputChannelPair(const String8& name,
83 sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
84 status_t result;
85
86 String8 ashmemName("InputChannel ");
87 ashmemName.append(name);
88 int serverAshmemFd = ashmem_create_region(ashmemName.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
89 if (serverAshmemFd < 0) {
90 result = -errno;
91 LOGE("channel '%s' ~ Could not create shared memory region. errno=%d",
92 name.string(), errno);
93 } else {
94 result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE);
95 if (result < 0) {
96 LOGE("channel '%s' ~ Error %d trying to set protection of ashmem fd %d.",
97 name.string(), result, serverAshmemFd);
98 } else {
99 // Dup the file descriptor because the server and client input channel objects that
100 // are returned may have different lifetimes but they share the same shared memory region.
101 int clientAshmemFd;
102 clientAshmemFd = dup(serverAshmemFd);
103 if (clientAshmemFd < 0) {
104 result = -errno;
105 LOGE("channel '%s' ~ Could not dup() shared memory region fd. errno=%d",
106 name.string(), errno);
107 } else {
108 int forward[2];
109 if (pipe(forward)) {
110 result = -errno;
111 LOGE("channel '%s' ~ Could not create forward pipe. errno=%d",
112 name.string(), errno);
113 } else {
114 int reverse[2];
115 if (pipe(reverse)) {
116 result = -errno;
117 LOGE("channel '%s' ~ Could not create reverse pipe. errno=%d",
118 name.string(), errno);
119 } else {
120 String8 serverChannelName = name;
121 serverChannelName.append(" (server)");
122 outServerChannel = new InputChannel(serverChannelName,
123 serverAshmemFd, reverse[0], forward[1]);
124
125 String8 clientChannelName = name;
126 clientChannelName.append(" (client)");
127 outClientChannel = new InputChannel(clientChannelName,
128 clientAshmemFd, forward[0], reverse[1]);
129 return OK;
130 }
131 ::close(forward[0]);
132 ::close(forward[1]);
133 }
134 ::close(clientAshmemFd);
135 }
136 }
137 ::close(serverAshmemFd);
138 }
139
140 outServerChannel.clear();
141 outClientChannel.clear();
142 return result;
143 }
144
sendSignal(char signal)145 status_t InputChannel::sendSignal(char signal) {
146 ssize_t nWrite;
147 do {
148 nWrite = ::write(mSendPipeFd, & signal, 1);
149 } while (nWrite == -1 && errno == EINTR);
150
151 if (nWrite == 1) {
152 #if DEBUG_CHANNEL_SIGNALS
153 LOGD("channel '%s' ~ sent signal '%c'", mName.string(), signal);
154 #endif
155 return OK;
156 }
157
158 #if DEBUG_CHANNEL_SIGNALS
159 LOGD("channel '%s' ~ error sending signal '%c', errno=%d", mName.string(), signal, errno);
160 #endif
161 return -errno;
162 }
163
receiveSignal(char * outSignal)164 status_t InputChannel::receiveSignal(char* outSignal) {
165 ssize_t nRead;
166 do {
167 nRead = ::read(mReceivePipeFd, outSignal, 1);
168 } while (nRead == -1 && errno == EINTR);
169
170 if (nRead == 1) {
171 #if DEBUG_CHANNEL_SIGNALS
172 LOGD("channel '%s' ~ received signal '%c'", mName.string(), *outSignal);
173 #endif
174 return OK;
175 }
176
177 if (nRead == 0) { // check for EOF
178 #if DEBUG_CHANNEL_SIGNALS
179 LOGD("channel '%s' ~ receive signal failed because peer was closed", mName.string());
180 #endif
181 return DEAD_OBJECT;
182 }
183
184 if (errno == EAGAIN) {
185 #if DEBUG_CHANNEL_SIGNALS
186 LOGD("channel '%s' ~ receive signal failed because no signal available", mName.string());
187 #endif
188 return WOULD_BLOCK;
189 }
190
191 #if DEBUG_CHANNEL_SIGNALS
192 LOGD("channel '%s' ~ receive signal failed, errno=%d", mName.string(), errno);
193 #endif
194 return -errno;
195 }
196
197
198 // --- InputPublisher ---
199
InputPublisher(const sp<InputChannel> & channel)200 InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
201 mChannel(channel), mSharedMessage(NULL),
202 mPinned(false), mSemaphoreInitialized(false), mWasDispatched(false),
203 mMotionEventSampleDataTail(NULL) {
204 }
205
~InputPublisher()206 InputPublisher::~InputPublisher() {
207 reset();
208
209 if (mSharedMessage) {
210 munmap(mSharedMessage, mAshmemSize);
211 }
212 }
213
initialize()214 status_t InputPublisher::initialize() {
215 #if DEBUG_TRANSPORT_ACTIONS
216 LOGD("channel '%s' publisher ~ initialize",
217 mChannel->getName().string());
218 #endif
219
220 int ashmemFd = mChannel->getAshmemFd();
221 int result = ashmem_get_size_region(ashmemFd);
222 if (result < 0) {
223 LOGE("channel '%s' publisher ~ Error %d getting size of ashmem fd %d.",
224 mChannel->getName().string(), result, ashmemFd);
225 return UNKNOWN_ERROR;
226 }
227 mAshmemSize = (size_t) result;
228
229 mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
230 PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
231 if (! mSharedMessage) {
232 LOGE("channel '%s' publisher ~ mmap failed on ashmem fd %d.",
233 mChannel->getName().string(), ashmemFd);
234 return NO_MEMORY;
235 }
236
237 mPinned = true;
238 mSharedMessage->consumed = false;
239
240 return reset();
241 }
242
reset()243 status_t InputPublisher::reset() {
244 #if DEBUG_TRANSPORT_ACTIONS
245 LOGD("channel '%s' publisher ~ reset",
246 mChannel->getName().string());
247 #endif
248
249 if (mPinned) {
250 // Destroy the semaphore since we are about to unpin the memory region that contains it.
251 int result;
252 if (mSemaphoreInitialized) {
253 if (mSharedMessage->consumed) {
254 result = sem_post(& mSharedMessage->semaphore);
255 if (result < 0) {
256 LOGE("channel '%s' publisher ~ Error %d in sem_post.",
257 mChannel->getName().string(), errno);
258 return UNKNOWN_ERROR;
259 }
260 }
261
262 result = sem_destroy(& mSharedMessage->semaphore);
263 if (result < 0) {
264 LOGE("channel '%s' publisher ~ Error %d in sem_destroy.",
265 mChannel->getName().string(), errno);
266 return UNKNOWN_ERROR;
267 }
268
269 mSemaphoreInitialized = false;
270 }
271
272 // Unpin the region since we no longer care about its contents.
273 int ashmemFd = mChannel->getAshmemFd();
274 result = ashmem_unpin_region(ashmemFd, 0, 0);
275 if (result < 0) {
276 LOGE("channel '%s' publisher ~ Error %d unpinning ashmem fd %d.",
277 mChannel->getName().string(), result, ashmemFd);
278 return UNKNOWN_ERROR;
279 }
280
281 mPinned = false;
282 }
283
284 mMotionEventSampleDataTail = NULL;
285 mWasDispatched = false;
286 return OK;
287 }
288
publishInputEvent(int32_t type,int32_t deviceId,int32_t source)289 status_t InputPublisher::publishInputEvent(
290 int32_t type,
291 int32_t deviceId,
292 int32_t source) {
293 if (mPinned) {
294 LOGE("channel '%s' publisher ~ Attempted to publish a new event but publisher has "
295 "not yet been reset.", mChannel->getName().string());
296 return INVALID_OPERATION;
297 }
298
299 // Pin the region.
300 // We do not check for ASHMEM_NOT_PURGED because we don't care about the previous
301 // contents of the buffer so it does not matter whether it was purged in the meantime.
302 int ashmemFd = mChannel->getAshmemFd();
303 int result = ashmem_pin_region(ashmemFd, 0, 0);
304 if (result < 0) {
305 LOGE("channel '%s' publisher ~ Error %d pinning ashmem fd %d.",
306 mChannel->getName().string(), result, ashmemFd);
307 return UNKNOWN_ERROR;
308 }
309
310 mPinned = true;
311
312 result = sem_init(& mSharedMessage->semaphore, 1, 1);
313 if (result < 0) {
314 LOGE("channel '%s' publisher ~ Error %d in sem_init.",
315 mChannel->getName().string(), errno);
316 return UNKNOWN_ERROR;
317 }
318
319 mSemaphoreInitialized = true;
320
321 mSharedMessage->consumed = false;
322 mSharedMessage->type = type;
323 mSharedMessage->deviceId = deviceId;
324 mSharedMessage->source = source;
325 return OK;
326 }
327
publishKeyEvent(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)328 status_t InputPublisher::publishKeyEvent(
329 int32_t deviceId,
330 int32_t source,
331 int32_t action,
332 int32_t flags,
333 int32_t keyCode,
334 int32_t scanCode,
335 int32_t metaState,
336 int32_t repeatCount,
337 nsecs_t downTime,
338 nsecs_t eventTime) {
339 #if DEBUG_TRANSPORT_ACTIONS
340 LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=0x%x, "
341 "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
342 "downTime=%lld, eventTime=%lld",
343 mChannel->getName().string(),
344 deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
345 downTime, eventTime);
346 #endif
347
348 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_KEY, deviceId, source);
349 if (result < 0) {
350 return result;
351 }
352
353 mSharedMessage->key.action = action;
354 mSharedMessage->key.flags = flags;
355 mSharedMessage->key.keyCode = keyCode;
356 mSharedMessage->key.scanCode = scanCode;
357 mSharedMessage->key.metaState = metaState;
358 mSharedMessage->key.repeatCount = repeatCount;
359 mSharedMessage->key.downTime = downTime;
360 mSharedMessage->key.eventTime = eventTime;
361 return OK;
362 }
363
publishMotionEvent(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)364 status_t InputPublisher::publishMotionEvent(
365 int32_t deviceId,
366 int32_t source,
367 int32_t action,
368 int32_t flags,
369 int32_t edgeFlags,
370 int32_t metaState,
371 int32_t buttonState,
372 float xOffset,
373 float yOffset,
374 float xPrecision,
375 float yPrecision,
376 nsecs_t downTime,
377 nsecs_t eventTime,
378 size_t pointerCount,
379 const PointerProperties* pointerProperties,
380 const PointerCoords* pointerCoords) {
381 #if DEBUG_TRANSPORT_ACTIONS
382 LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
383 "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
384 "xOffset=%f, yOffset=%f, "
385 "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
386 "pointerCount=%d",
387 mChannel->getName().string(),
388 deviceId, source, action, flags, edgeFlags, metaState, buttonState,
389 xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
390 #endif
391
392 if (pointerCount > MAX_POINTERS || pointerCount < 1) {
393 LOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.",
394 mChannel->getName().string(), pointerCount);
395 return BAD_VALUE;
396 }
397
398 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_MOTION, deviceId, source);
399 if (result < 0) {
400 return result;
401 }
402
403 mSharedMessage->motion.action = action;
404 mSharedMessage->motion.flags = flags;
405 mSharedMessage->motion.edgeFlags = edgeFlags;
406 mSharedMessage->motion.metaState = metaState;
407 mSharedMessage->motion.buttonState = buttonState;
408 mSharedMessage->motion.xOffset = xOffset;
409 mSharedMessage->motion.yOffset = yOffset;
410 mSharedMessage->motion.xPrecision = xPrecision;
411 mSharedMessage->motion.yPrecision = yPrecision;
412 mSharedMessage->motion.downTime = downTime;
413 mSharedMessage->motion.pointerCount = pointerCount;
414
415 mSharedMessage->motion.sampleCount = 1;
416 mSharedMessage->motion.sampleData[0].eventTime = eventTime;
417
418 for (size_t i = 0; i < pointerCount; i++) {
419 mSharedMessage->motion.pointerProperties[i].copyFrom(pointerProperties[i]);
420 mSharedMessage->motion.sampleData[0].coords[i].copyFrom(pointerCoords[i]);
421 }
422
423 // Cache essential information about the motion event to ensure that a malicious consumer
424 // cannot confuse the publisher by modifying the contents of the shared memory buffer while
425 // it is being updated.
426 if (action == AMOTION_EVENT_ACTION_MOVE
427 || action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
428 mMotionEventPointerCount = pointerCount;
429 mMotionEventSampleDataStride = InputMessage::sampleDataStride(pointerCount);
430 mMotionEventSampleDataTail = InputMessage::sampleDataPtrIncrement(
431 mSharedMessage->motion.sampleData, mMotionEventSampleDataStride);
432 } else {
433 mMotionEventSampleDataTail = NULL;
434 }
435 return OK;
436 }
437
appendMotionSample(nsecs_t eventTime,const PointerCoords * pointerCoords)438 status_t InputPublisher::appendMotionSample(
439 nsecs_t eventTime,
440 const PointerCoords* pointerCoords) {
441 #if DEBUG_TRANSPORT_ACTIONS
442 LOGD("channel '%s' publisher ~ appendMotionSample: eventTime=%lld",
443 mChannel->getName().string(), eventTime);
444 #endif
445
446 if (! mPinned || ! mMotionEventSampleDataTail) {
447 LOGE("channel '%s' publisher ~ Cannot append motion sample because there is no current "
448 "AMOTION_EVENT_ACTION_MOVE or AMOTION_EVENT_ACTION_HOVER_MOVE event.",
449 mChannel->getName().string());
450 return INVALID_OPERATION;
451 }
452
453 InputMessage::SampleData* newTail = InputMessage::sampleDataPtrIncrement(
454 mMotionEventSampleDataTail, mMotionEventSampleDataStride);
455 size_t newBytesUsed = reinterpret_cast<char*>(newTail) -
456 reinterpret_cast<char*>(mSharedMessage);
457
458 if (newBytesUsed > mAshmemSize) {
459 #if DEBUG_TRANSPORT_ACTIONS
460 LOGD("channel '%s' publisher ~ Cannot append motion sample because the shared memory "
461 "buffer is full. Buffer size: %d bytes, pointers: %d, samples: %d",
462 mChannel->getName().string(),
463 mAshmemSize, mMotionEventPointerCount, mSharedMessage->motion.sampleCount);
464 #endif
465 return NO_MEMORY;
466 }
467
468 int result;
469 if (mWasDispatched) {
470 result = sem_trywait(& mSharedMessage->semaphore);
471 if (result < 0) {
472 if (errno == EAGAIN) {
473 // Only possible source of contention is the consumer having consumed (or being in the
474 // process of consuming) the message and left the semaphore count at 0.
475 #if DEBUG_TRANSPORT_ACTIONS
476 LOGD("channel '%s' publisher ~ Cannot append motion sample because the message has "
477 "already been consumed.", mChannel->getName().string());
478 #endif
479 return FAILED_TRANSACTION;
480 } else {
481 LOGE("channel '%s' publisher ~ Error %d in sem_trywait.",
482 mChannel->getName().string(), errno);
483 return UNKNOWN_ERROR;
484 }
485 }
486 }
487
488 mMotionEventSampleDataTail->eventTime = eventTime;
489 for (size_t i = 0; i < mMotionEventPointerCount; i++) {
490 mMotionEventSampleDataTail->coords[i].copyFrom(pointerCoords[i]);
491 }
492 mMotionEventSampleDataTail = newTail;
493
494 mSharedMessage->motion.sampleCount += 1;
495
496 if (mWasDispatched) {
497 result = sem_post(& mSharedMessage->semaphore);
498 if (result < 0) {
499 LOGE("channel '%s' publisher ~ Error %d in sem_post.",
500 mChannel->getName().string(), errno);
501 return UNKNOWN_ERROR;
502 }
503 }
504 return OK;
505 }
506
sendDispatchSignal()507 status_t InputPublisher::sendDispatchSignal() {
508 #if DEBUG_TRANSPORT_ACTIONS
509 LOGD("channel '%s' publisher ~ sendDispatchSignal",
510 mChannel->getName().string());
511 #endif
512
513 mWasDispatched = true;
514 return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
515 }
516
receiveFinishedSignal(bool * outHandled)517 status_t InputPublisher::receiveFinishedSignal(bool* outHandled) {
518 #if DEBUG_TRANSPORT_ACTIONS
519 LOGD("channel '%s' publisher ~ receiveFinishedSignal",
520 mChannel->getName().string());
521 #endif
522
523 char signal;
524 status_t result = mChannel->receiveSignal(& signal);
525 if (result) {
526 *outHandled = false;
527 return result;
528 }
529 if (signal == INPUT_SIGNAL_FINISHED_HANDLED) {
530 *outHandled = true;
531 } else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) {
532 *outHandled = false;
533 } else {
534 LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
535 mChannel->getName().string(), signal);
536 return UNKNOWN_ERROR;
537 }
538 return OK;
539 }
540
541 // --- InputConsumer ---
542
InputConsumer(const sp<InputChannel> & channel)543 InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
544 mChannel(channel), mSharedMessage(NULL) {
545 }
546
~InputConsumer()547 InputConsumer::~InputConsumer() {
548 if (mSharedMessage) {
549 munmap(mSharedMessage, mAshmemSize);
550 }
551 }
552
initialize()553 status_t InputConsumer::initialize() {
554 #if DEBUG_TRANSPORT_ACTIONS
555 LOGD("channel '%s' consumer ~ initialize",
556 mChannel->getName().string());
557 #endif
558
559 int ashmemFd = mChannel->getAshmemFd();
560 int result = ashmem_get_size_region(ashmemFd);
561 if (result < 0) {
562 LOGE("channel '%s' consumer ~ Error %d getting size of ashmem fd %d.",
563 mChannel->getName().string(), result, ashmemFd);
564 return UNKNOWN_ERROR;
565 }
566
567 mAshmemSize = (size_t) result;
568
569 mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
570 PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
571 if (! mSharedMessage) {
572 LOGE("channel '%s' consumer ~ mmap failed on ashmem fd %d.",
573 mChannel->getName().string(), ashmemFd);
574 return NO_MEMORY;
575 }
576
577 return OK;
578 }
579
consume(InputEventFactoryInterface * factory,InputEvent ** outEvent)580 status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent** outEvent) {
581 #if DEBUG_TRANSPORT_ACTIONS
582 LOGD("channel '%s' consumer ~ consume",
583 mChannel->getName().string());
584 #endif
585
586 *outEvent = NULL;
587
588 int ashmemFd = mChannel->getAshmemFd();
589 int result = ashmem_pin_region(ashmemFd, 0, 0);
590 if (result != ASHMEM_NOT_PURGED) {
591 if (result == ASHMEM_WAS_PURGED) {
592 LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d because it was purged "
593 "which probably indicates that the publisher and consumer are out of sync.",
594 mChannel->getName().string(), result, ashmemFd);
595 return INVALID_OPERATION;
596 }
597
598 LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d.",
599 mChannel->getName().string(), result, ashmemFd);
600 return UNKNOWN_ERROR;
601 }
602
603 if (mSharedMessage->consumed) {
604 LOGE("channel '%s' consumer ~ The current message has already been consumed.",
605 mChannel->getName().string());
606 return INVALID_OPERATION;
607 }
608
609 // Acquire but *never release* the semaphore. Contention on the semaphore is used to signal
610 // to the publisher that the message has been consumed (or is in the process of being
611 // consumed). Eventually the publisher will reinitialize the semaphore for the next message.
612 result = sem_wait(& mSharedMessage->semaphore);
613 if (result < 0) {
614 LOGE("channel '%s' consumer ~ Error %d in sem_wait.",
615 mChannel->getName().string(), errno);
616 return UNKNOWN_ERROR;
617 }
618
619 mSharedMessage->consumed = true;
620
621 switch (mSharedMessage->type) {
622 case AINPUT_EVENT_TYPE_KEY: {
623 KeyEvent* keyEvent = factory->createKeyEvent();
624 if (! keyEvent) return NO_MEMORY;
625
626 populateKeyEvent(keyEvent);
627
628 *outEvent = keyEvent;
629 break;
630 }
631
632 case AINPUT_EVENT_TYPE_MOTION: {
633 MotionEvent* motionEvent = factory->createMotionEvent();
634 if (! motionEvent) return NO_MEMORY;
635
636 populateMotionEvent(motionEvent);
637
638 *outEvent = motionEvent;
639 break;
640 }
641
642 default:
643 LOGE("channel '%s' consumer ~ Received message of unknown type %d",
644 mChannel->getName().string(), mSharedMessage->type);
645 return UNKNOWN_ERROR;
646 }
647
648 return OK;
649 }
650
sendFinishedSignal(bool handled)651 status_t InputConsumer::sendFinishedSignal(bool handled) {
652 #if DEBUG_TRANSPORT_ACTIONS
653 LOGD("channel '%s' consumer ~ sendFinishedSignal: handled=%d",
654 mChannel->getName().string(), handled);
655 #endif
656
657 return mChannel->sendSignal(handled
658 ? INPUT_SIGNAL_FINISHED_HANDLED
659 : INPUT_SIGNAL_FINISHED_UNHANDLED);
660 }
661
receiveDispatchSignal()662 status_t InputConsumer::receiveDispatchSignal() {
663 #if DEBUG_TRANSPORT_ACTIONS
664 LOGD("channel '%s' consumer ~ receiveDispatchSignal",
665 mChannel->getName().string());
666 #endif
667
668 char signal;
669 status_t result = mChannel->receiveSignal(& signal);
670 if (result) {
671 return result;
672 }
673 if (signal != INPUT_SIGNAL_DISPATCH) {
674 LOGE("channel '%s' consumer ~ Received unexpected signal '%c' from publisher",
675 mChannel->getName().string(), signal);
676 return UNKNOWN_ERROR;
677 }
678 return OK;
679 }
680
populateKeyEvent(KeyEvent * keyEvent) const681 void InputConsumer::populateKeyEvent(KeyEvent* keyEvent) const {
682 keyEvent->initialize(
683 mSharedMessage->deviceId,
684 mSharedMessage->source,
685 mSharedMessage->key.action,
686 mSharedMessage->key.flags,
687 mSharedMessage->key.keyCode,
688 mSharedMessage->key.scanCode,
689 mSharedMessage->key.metaState,
690 mSharedMessage->key.repeatCount,
691 mSharedMessage->key.downTime,
692 mSharedMessage->key.eventTime);
693 }
694
populateMotionEvent(MotionEvent * motionEvent) const695 void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
696 motionEvent->initialize(
697 mSharedMessage->deviceId,
698 mSharedMessage->source,
699 mSharedMessage->motion.action,
700 mSharedMessage->motion.flags,
701 mSharedMessage->motion.edgeFlags,
702 mSharedMessage->motion.metaState,
703 mSharedMessage->motion.buttonState,
704 mSharedMessage->motion.xOffset,
705 mSharedMessage->motion.yOffset,
706 mSharedMessage->motion.xPrecision,
707 mSharedMessage->motion.yPrecision,
708 mSharedMessage->motion.downTime,
709 mSharedMessage->motion.sampleData[0].eventTime,
710 mSharedMessage->motion.pointerCount,
711 mSharedMessage->motion.pointerProperties,
712 mSharedMessage->motion.sampleData[0].coords);
713
714 size_t sampleCount = mSharedMessage->motion.sampleCount;
715 if (sampleCount > 1) {
716 InputMessage::SampleData* sampleData = mSharedMessage->motion.sampleData;
717 size_t sampleDataStride = InputMessage::sampleDataStride(
718 mSharedMessage->motion.pointerCount);
719
720 while (--sampleCount > 0) {
721 sampleData = InputMessage::sampleDataPtrIncrement(sampleData, sampleDataStride);
722 motionEvent->addSample(sampleData->eventTime, sampleData->coords);
723 }
724 }
725 }
726
727 } // namespace android
728