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