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
28namespace android {
29
30// Must be at least sizeof(InputMessage) + sufficient space for pointer data
31static 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.
35static 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.
39static const char INPUT_SIGNAL_FINISHED = 'f';
40
41
42// --- InputChannel ---
43
44InputChannel::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
61InputChannel::~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
72status_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
133status_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
152status_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
188InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
189        mChannel(channel), mSharedMessage(NULL),
190        mPinned(false), mSemaphoreInitialized(false), mWasDispatched(false),
191        mMotionEventSampleDataTail(NULL) {
192}
193
194InputPublisher::~InputPublisher() {
195    reset();
196
197    if (mSharedMessage) {
198        munmap(mSharedMessage, mAshmemSize);
199    }
200}
201
202status_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
231status_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
277status_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
316status_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
352status_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
422status_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
490status_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
500status_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
521InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
522        mChannel(channel), mSharedMessage(NULL) {
523}
524
525InputConsumer::~InputConsumer() {
526    if (mSharedMessage) {
527        munmap(mSharedMessage, mAshmemSize);
528    }
529}
530
531status_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
558status_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
629status_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
638status_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
657void 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
671void 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