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