blob: 2c6346ebeeb767689c46c20ab11bf3b6fc785e50 [file] [log] [blame]
Jeff Browne839a582010-04-22 18:58:52 -07001//
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)
Jeff Brownf4a4ec22010-06-16 01:53:36 -070011#define DEBUG_CHANNEL_SIGNALS 0
Jeff Browne839a582010-04-22 18:58:52 -070012
13// Log debug messages whenever InputChannel objects are created/destroyed
Jeff Brownf4a4ec22010-06-16 01:53:36 -070014#define DEBUG_CHANNEL_LIFECYCLE 0
Jeff Browne839a582010-04-22 18:58:52 -070015
16// Log debug messages about transport actions (initialize, reset, publish, ...)
Jeff Brownf4a4ec22010-06-16 01:53:36 -070017#define DEBUG_TRANSPORT_ACTIONS 0
Jeff Browne839a582010-04-22 18:58:52 -070018
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,
Jeff Brownf4a4ec22010-06-16 01:53:36 -070073 sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
Jeff Browne839a582010-04-22 18:58:52 -070074 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)");
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700110 outServerChannel = new InputChannel(serverChannelName,
Jeff Browne839a582010-04-22 18:58:52 -0700111 serverAshmemFd, reverse[0], forward[1]);
112
113 String8 clientChannelName = name;
114 clientChannelName.append(" (client)");
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700115 outClientChannel = new InputChannel(clientChannelName,
Jeff Browne839a582010-04-22 18:58:52 -0700116 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
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700128 outServerChannel.clear();
129 outClientChannel.clear();
Jeff Browne839a582010-04-22 18:58:52 -0700130 return result;
131}
132
133status_t InputChannel::sendSignal(char signal) {
Jeff Brownf67f2992010-09-16 17:04:52 -0700134 ssize_t nWrite;
135 do {
136 nWrite = ::write(mSendPipeFd, & signal, 1);
137 } while (nWrite == -1 && errno == EINTR);
Jeff Browne839a582010-04-22 18:58:52 -0700138
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) {
Jeff Brownf67f2992010-09-16 17:04:52 -0700153 ssize_t nRead;
154 do {
155 nRead = ::read(mReceivePipeFd, outSignal, 1);
156 } while (nRead == -1 && errno == EINTR);
157
Jeff Browne839a582010-04-22 18:58:52 -0700158 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
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700165 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
Jeff Browne839a582010-04-22 18:58:52 -0700172 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,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700280 int32_t source) {
Jeff Browne839a582010-04-22 18:58:52 -0700281 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;
Jeff Brown5c1ed842010-07-14 18:48:53 -0700312 mSharedMessage->source = source;
Jeff Browne839a582010-04-22 18:58:52 -0700313 return OK;
314}
315
316status_t InputPublisher::publishKeyEvent(
317 int32_t deviceId,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700318 int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -0700319 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
Jeff Brownaf30ff62010-09-01 17:01:00 -0700328 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,"
Jeff Browne839a582010-04-22 18:58:52 -0700330 "downTime=%lld, eventTime=%lld",
331 mChannel->getName().string(),
Jeff Brown5c1ed842010-07-14 18:48:53 -0700332 deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
Jeff Browne839a582010-04-22 18:58:52 -0700333 downTime, eventTime);
334#endif
335
Jeff Brown5c1ed842010-07-14 18:48:53 -0700336 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_KEY, deviceId, source);
Jeff Browne839a582010-04-22 18:58:52 -0700337 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,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700354 int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -0700355 int32_t action,
Jeff Brownaf30ff62010-09-01 17:01:00 -0700356 int32_t flags,
Jeff Browne839a582010-04-22 18:58:52 -0700357 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
Jeff Brownaf30ff62010-09-01 17:01:00 -0700369 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, "
Jeff Browne839a582010-04-22 18:58:52 -0700371 "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
372 "pointerCount=%d",
373 mChannel->getName().string(),
Jeff Brownaf30ff62010-09-01 17:01:00 -0700374 deviceId, source, action, flags, edgeFlags, metaState, xOffset, yOffset,
Jeff Browne839a582010-04-22 18:58:52 -0700375 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
Jeff Brown5c1ed842010-07-14 18:48:53 -0700384 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_MOTION, deviceId, source);
Jeff Browne839a582010-04-22 18:58:52 -0700385 if (result < 0) {
386 return result;
387 }
388
389 mSharedMessage->motion.action = action;
Jeff Brownaf30ff62010-09-01 17:01:00 -0700390 mSharedMessage->motion.flags = flags;
Jeff Browne839a582010-04-22 18:58:52 -0700391 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.
Jeff Brown5c1ed842010-07-14 18:48:53 -0700411 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -0700412 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 "
Jeff Brown5c1ed842010-07-14 18:48:53 -0700432 "AMOTION_EVENT_ACTION_MOVE event.", mChannel->getName().string());
Jeff Browne839a582010-04-22 18:58:52 -0700433 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) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700442#if DEBUG_TRANSPORT_ACTIONS
Jeff Browne839a582010-04-22 18:58:52 -0700443 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);
Jeff Brown50de30a2010-06-22 01:27:15 -0700447#endif
Jeff Browne839a582010-04-22 18:58:52 -0700448 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.
Jeff Brown50de30a2010-06-22 01:27:15 -0700458#if DEBUG_TRANSPORT_ACTIONS
Jeff Browne839a582010-04-22 18:58:52 -0700459 LOGD("channel '%s' publisher ~ Cannot append motion sample because the message has "
460 "already been consumed.", mChannel->getName().string());
Jeff Brown50de30a2010-06-22 01:27:15 -0700461#endif
Jeff Browne839a582010-04-22 18:58:52 -0700462 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
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700558status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent** outEvent) {
Jeff Browne839a582010-04-22 18:58:52 -0700559#if DEBUG_TRANSPORT_ACTIONS
560 LOGD("channel '%s' consumer ~ consume",
561 mChannel->getName().string());
562#endif
563
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700564 *outEvent = NULL;
Jeff Browne839a582010-04-22 18:58:52 -0700565
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) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700600 case AINPUT_EVENT_TYPE_KEY: {
Jeff Browne839a582010-04-22 18:58:52 -0700601 KeyEvent* keyEvent = factory->createKeyEvent();
602 if (! keyEvent) return NO_MEMORY;
603
604 populateKeyEvent(keyEvent);
605
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700606 *outEvent = keyEvent;
Jeff Browne839a582010-04-22 18:58:52 -0700607 break;
608 }
609
Jeff Brown5c1ed842010-07-14 18:48:53 -0700610 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Browne839a582010-04-22 18:58:52 -0700611 MotionEvent* motionEvent = factory->createMotionEvent();
612 if (! motionEvent) return NO_MEMORY;
613
614 populateMotionEvent(motionEvent);
615
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700616 *outEvent = motionEvent;
Jeff Browne839a582010-04-22 18:58:52 -0700617 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,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700660 mSharedMessage->source,
Jeff Browne839a582010-04-22 18:58:52 -0700661 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,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700674 mSharedMessage->source,
Jeff Browne839a582010-04-22 18:58:52 -0700675 mSharedMessage->motion.action,
Jeff Brownaf30ff62010-09-01 17:01:00 -0700676 mSharedMessage->motion.flags,
Jeff Browne839a582010-04-22 18:58:52 -0700677 mSharedMessage->motion.edgeFlags,
678 mSharedMessage->motion.metaState,
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700679 mSharedMessage->motion.xOffset,
680 mSharedMessage->motion.yOffset,
Jeff Browne839a582010-04-22 18:58:52 -0700681 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 }
Jeff Browne839a582010-04-22 18:58:52 -0700700}
701
702} // namespace android