blob: 83d955682ad6f009289fd298d43fa2b8043b8e52 [file] [log] [blame]
Jeff Brown46b9ac02010-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 Brown5c225b12010-06-16 01:53:36 -070011#define DEBUG_CHANNEL_SIGNALS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070012
13// Log debug messages whenever InputChannel objects are created/destroyed
Jeff Brown5c225b12010-06-16 01:53:36 -070014#define DEBUG_CHANNEL_LIFECYCLE 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070015
16// Log debug messages about transport actions (initialize, reset, publish, ...)
Jeff Brown5c225b12010-06-16 01:53:36 -070017#define DEBUG_TRANSPORT_ACTIONS 0
Jeff Brown46b9ac02010-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
Jeff Brown3915bb82010-11-05 15:02:16 -070038// consuming the most recent message and it handled it.
39static const char INPUT_SIGNAL_FINISHED_HANDLED = 'f';
40
41// Signal sent by the consumer to the producer to inform it that it has finished
42// consuming the most recent message but it did not handle it.
43static const char INPUT_SIGNAL_FINISHED_UNHANDLED = 'u';
Jeff Brown46b9ac02010-04-22 18:58:52 -070044
45
46// --- InputChannel ---
47
48InputChannel::InputChannel(const String8& name, int32_t ashmemFd, int32_t receivePipeFd,
49 int32_t sendPipeFd) :
50 mName(name), mAshmemFd(ashmemFd), mReceivePipeFd(receivePipeFd), mSendPipeFd(sendPipeFd) {
51#if DEBUG_CHANNEL_LIFECYCLE
52 LOGD("Input channel constructed: name='%s', ashmemFd=%d, receivePipeFd=%d, sendPipeFd=%d",
53 mName.string(), ashmemFd, receivePipeFd, sendPipeFd);
54#endif
55
56 int result = fcntl(mReceivePipeFd, F_SETFL, O_NONBLOCK);
57 LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make receive pipe "
58 "non-blocking. errno=%d", mName.string(), errno);
59
60 result = fcntl(mSendPipeFd, F_SETFL, O_NONBLOCK);
61 LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make send pipe "
62 "non-blocking. errno=%d", mName.string(), errno);
63}
64
65InputChannel::~InputChannel() {
66#if DEBUG_CHANNEL_LIFECYCLE
67 LOGD("Input channel destroyed: name='%s', ashmemFd=%d, receivePipeFd=%d, sendPipeFd=%d",
68 mName.string(), mAshmemFd, mReceivePipeFd, mSendPipeFd);
69#endif
70
71 ::close(mAshmemFd);
72 ::close(mReceivePipeFd);
73 ::close(mSendPipeFd);
74}
75
76status_t InputChannel::openInputChannelPair(const String8& name,
Jeff Brown5c225b12010-06-16 01:53:36 -070077 sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
Jeff Brown46b9ac02010-04-22 18:58:52 -070078 status_t result;
79
80 int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
81 if (serverAshmemFd < 0) {
82 result = -errno;
83 LOGE("channel '%s' ~ Could not create shared memory region. errno=%d",
84 name.string(), errno);
85 } else {
86 result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE);
87 if (result < 0) {
88 LOGE("channel '%s' ~ Error %d trying to set protection of ashmem fd %d.",
89 name.string(), result, serverAshmemFd);
90 } else {
91 // Dup the file descriptor because the server and client input channel objects that
92 // are returned may have different lifetimes but they share the same shared memory region.
93 int clientAshmemFd;
94 clientAshmemFd = dup(serverAshmemFd);
95 if (clientAshmemFd < 0) {
96 result = -errno;
97 LOGE("channel '%s' ~ Could not dup() shared memory region fd. errno=%d",
98 name.string(), errno);
99 } else {
100 int forward[2];
101 if (pipe(forward)) {
102 result = -errno;
103 LOGE("channel '%s' ~ Could not create forward pipe. errno=%d",
104 name.string(), errno);
105 } else {
106 int reverse[2];
107 if (pipe(reverse)) {
108 result = -errno;
109 LOGE("channel '%s' ~ Could not create reverse pipe. errno=%d",
110 name.string(), errno);
111 } else {
112 String8 serverChannelName = name;
113 serverChannelName.append(" (server)");
Jeff Brown5c225b12010-06-16 01:53:36 -0700114 outServerChannel = new InputChannel(serverChannelName,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700115 serverAshmemFd, reverse[0], forward[1]);
116
117 String8 clientChannelName = name;
118 clientChannelName.append(" (client)");
Jeff Brown5c225b12010-06-16 01:53:36 -0700119 outClientChannel = new InputChannel(clientChannelName,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700120 clientAshmemFd, forward[0], reverse[1]);
121 return OK;
122 }
123 ::close(forward[0]);
124 ::close(forward[1]);
125 }
126 ::close(clientAshmemFd);
127 }
128 }
129 ::close(serverAshmemFd);
130 }
131
Jeff Brown5c225b12010-06-16 01:53:36 -0700132 outServerChannel.clear();
133 outClientChannel.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700134 return result;
135}
136
137status_t InputChannel::sendSignal(char signal) {
Jeff Brown7dae0e42010-09-16 17:04:52 -0700138 ssize_t nWrite;
139 do {
140 nWrite = ::write(mSendPipeFd, & signal, 1);
141 } while (nWrite == -1 && errno == EINTR);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700142
143 if (nWrite == 1) {
144#if DEBUG_CHANNEL_SIGNALS
145 LOGD("channel '%s' ~ sent signal '%c'", mName.string(), signal);
146#endif
147 return OK;
148 }
149
150#if DEBUG_CHANNEL_SIGNALS
151 LOGD("channel '%s' ~ error sending signal '%c', errno=%d", mName.string(), signal, errno);
152#endif
153 return -errno;
154}
155
156status_t InputChannel::receiveSignal(char* outSignal) {
Jeff Brown7dae0e42010-09-16 17:04:52 -0700157 ssize_t nRead;
158 do {
159 nRead = ::read(mReceivePipeFd, outSignal, 1);
160 } while (nRead == -1 && errno == EINTR);
161
Jeff Brown46b9ac02010-04-22 18:58:52 -0700162 if (nRead == 1) {
163#if DEBUG_CHANNEL_SIGNALS
164 LOGD("channel '%s' ~ received signal '%c'", mName.string(), *outSignal);
165#endif
166 return OK;
167 }
168
Jeff Brown5c225b12010-06-16 01:53:36 -0700169 if (nRead == 0) { // check for EOF
170#if DEBUG_CHANNEL_SIGNALS
171 LOGD("channel '%s' ~ receive signal failed because peer was closed", mName.string());
172#endif
173 return DEAD_OBJECT;
174 }
175
Jeff Brown46b9ac02010-04-22 18:58:52 -0700176 if (errno == EAGAIN) {
177#if DEBUG_CHANNEL_SIGNALS
178 LOGD("channel '%s' ~ receive signal failed because no signal available", mName.string());
179#endif
180 return WOULD_BLOCK;
181 }
182
183#if DEBUG_CHANNEL_SIGNALS
184 LOGD("channel '%s' ~ receive signal failed, errno=%d", mName.string(), errno);
185#endif
186 return -errno;
187}
188
189
190// --- InputPublisher ---
191
192InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
193 mChannel(channel), mSharedMessage(NULL),
194 mPinned(false), mSemaphoreInitialized(false), mWasDispatched(false),
195 mMotionEventSampleDataTail(NULL) {
196}
197
198InputPublisher::~InputPublisher() {
199 reset();
200
201 if (mSharedMessage) {
202 munmap(mSharedMessage, mAshmemSize);
203 }
204}
205
206status_t InputPublisher::initialize() {
207#if DEBUG_TRANSPORT_ACTIONS
208 LOGD("channel '%s' publisher ~ initialize",
209 mChannel->getName().string());
210#endif
211
212 int ashmemFd = mChannel->getAshmemFd();
213 int result = ashmem_get_size_region(ashmemFd);
214 if (result < 0) {
215 LOGE("channel '%s' publisher ~ Error %d getting size of ashmem fd %d.",
216 mChannel->getName().string(), result, ashmemFd);
217 return UNKNOWN_ERROR;
218 }
219 mAshmemSize = (size_t) result;
220
221 mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
222 PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
223 if (! mSharedMessage) {
224 LOGE("channel '%s' publisher ~ mmap failed on ashmem fd %d.",
225 mChannel->getName().string(), ashmemFd);
226 return NO_MEMORY;
227 }
228
229 mPinned = true;
230 mSharedMessage->consumed = false;
231
232 return reset();
233}
234
235status_t InputPublisher::reset() {
236#if DEBUG_TRANSPORT_ACTIONS
237 LOGD("channel '%s' publisher ~ reset",
238 mChannel->getName().string());
239#endif
240
241 if (mPinned) {
242 // Destroy the semaphore since we are about to unpin the memory region that contains it.
243 int result;
244 if (mSemaphoreInitialized) {
245 if (mSharedMessage->consumed) {
246 result = sem_post(& mSharedMessage->semaphore);
247 if (result < 0) {
248 LOGE("channel '%s' publisher ~ Error %d in sem_post.",
249 mChannel->getName().string(), errno);
250 return UNKNOWN_ERROR;
251 }
252 }
253
254 result = sem_destroy(& mSharedMessage->semaphore);
255 if (result < 0) {
256 LOGE("channel '%s' publisher ~ Error %d in sem_destroy.",
257 mChannel->getName().string(), errno);
258 return UNKNOWN_ERROR;
259 }
260
261 mSemaphoreInitialized = false;
262 }
263
264 // Unpin the region since we no longer care about its contents.
265 int ashmemFd = mChannel->getAshmemFd();
266 result = ashmem_unpin_region(ashmemFd, 0, 0);
267 if (result < 0) {
268 LOGE("channel '%s' publisher ~ Error %d unpinning ashmem fd %d.",
269 mChannel->getName().string(), result, ashmemFd);
270 return UNKNOWN_ERROR;
271 }
272
273 mPinned = false;
274 }
275
276 mMotionEventSampleDataTail = NULL;
277 mWasDispatched = false;
278 return OK;
279}
280
281status_t InputPublisher::publishInputEvent(
282 int32_t type,
283 int32_t deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700284 int32_t source) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700285 if (mPinned) {
286 LOGE("channel '%s' publisher ~ Attempted to publish a new event but publisher has "
287 "not yet been reset.", mChannel->getName().string());
288 return INVALID_OPERATION;
289 }
290
291 // Pin the region.
292 // We do not check for ASHMEM_NOT_PURGED because we don't care about the previous
293 // contents of the buffer so it does not matter whether it was purged in the meantime.
294 int ashmemFd = mChannel->getAshmemFd();
295 int result = ashmem_pin_region(ashmemFd, 0, 0);
296 if (result < 0) {
297 LOGE("channel '%s' publisher ~ Error %d pinning ashmem fd %d.",
298 mChannel->getName().string(), result, ashmemFd);
299 return UNKNOWN_ERROR;
300 }
301
302 mPinned = true;
303
304 result = sem_init(& mSharedMessage->semaphore, 1, 1);
305 if (result < 0) {
306 LOGE("channel '%s' publisher ~ Error %d in sem_init.",
307 mChannel->getName().string(), errno);
308 return UNKNOWN_ERROR;
309 }
310
311 mSemaphoreInitialized = true;
312
313 mSharedMessage->consumed = false;
314 mSharedMessage->type = type;
315 mSharedMessage->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700316 mSharedMessage->source = source;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700317 return OK;
318}
319
320status_t InputPublisher::publishKeyEvent(
321 int32_t deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700322 int32_t source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700323 int32_t action,
324 int32_t flags,
325 int32_t keyCode,
326 int32_t scanCode,
327 int32_t metaState,
328 int32_t repeatCount,
329 nsecs_t downTime,
330 nsecs_t eventTime) {
331#if DEBUG_TRANSPORT_ACTIONS
Jeff Brown85a31762010-09-01 17:01:00 -0700332 LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=0x%x, "
333 "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
Jeff Brown46b9ac02010-04-22 18:58:52 -0700334 "downTime=%lld, eventTime=%lld",
335 mChannel->getName().string(),
Jeff Brownc5ed5912010-07-14 18:48:53 -0700336 deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700337 downTime, eventTime);
338#endif
339
Jeff Brownc5ed5912010-07-14 18:48:53 -0700340 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_KEY, deviceId, source);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700341 if (result < 0) {
342 return result;
343 }
344
345 mSharedMessage->key.action = action;
346 mSharedMessage->key.flags = flags;
347 mSharedMessage->key.keyCode = keyCode;
348 mSharedMessage->key.scanCode = scanCode;
349 mSharedMessage->key.metaState = metaState;
350 mSharedMessage->key.repeatCount = repeatCount;
351 mSharedMessage->key.downTime = downTime;
352 mSharedMessage->key.eventTime = eventTime;
353 return OK;
354}
355
356status_t InputPublisher::publishMotionEvent(
357 int32_t deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700358 int32_t source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700359 int32_t action,
Jeff Brown85a31762010-09-01 17:01:00 -0700360 int32_t flags,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700361 int32_t edgeFlags,
362 int32_t metaState,
363 float xOffset,
364 float yOffset,
365 float xPrecision,
366 float yPrecision,
367 nsecs_t downTime,
368 nsecs_t eventTime,
369 size_t pointerCount,
370 const int32_t* pointerIds,
371 const PointerCoords* pointerCoords) {
372#if DEBUG_TRANSPORT_ACTIONS
Jeff Brown85a31762010-09-01 17:01:00 -0700373 LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
374 "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, xOffset=%f, yOffset=%f, "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700375 "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
376 "pointerCount=%d",
377 mChannel->getName().string(),
Jeff Brown85a31762010-09-01 17:01:00 -0700378 deviceId, source, action, flags, edgeFlags, metaState, xOffset, yOffset,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700379 xPrecision, yPrecision, downTime, eventTime, pointerCount);
380#endif
381
382 if (pointerCount > MAX_POINTERS || pointerCount < 1) {
383 LOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.",
384 mChannel->getName().string(), pointerCount);
385 return BAD_VALUE;
386 }
387
Jeff Brownc5ed5912010-07-14 18:48:53 -0700388 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_MOTION, deviceId, source);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700389 if (result < 0) {
390 return result;
391 }
392
393 mSharedMessage->motion.action = action;
Jeff Brown85a31762010-09-01 17:01:00 -0700394 mSharedMessage->motion.flags = flags;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700395 mSharedMessage->motion.edgeFlags = edgeFlags;
396 mSharedMessage->motion.metaState = metaState;
397 mSharedMessage->motion.xOffset = xOffset;
398 mSharedMessage->motion.yOffset = yOffset;
399 mSharedMessage->motion.xPrecision = xPrecision;
400 mSharedMessage->motion.yPrecision = yPrecision;
401 mSharedMessage->motion.downTime = downTime;
402 mSharedMessage->motion.pointerCount = pointerCount;
403
404 mSharedMessage->motion.sampleCount = 1;
405 mSharedMessage->motion.sampleData[0].eventTime = eventTime;
406
407 for (size_t i = 0; i < pointerCount; i++) {
408 mSharedMessage->motion.pointerIds[i] = pointerIds[i];
409 mSharedMessage->motion.sampleData[0].coords[i] = pointerCoords[i];
410 }
411
412 // Cache essential information about the motion event to ensure that a malicious consumer
413 // cannot confuse the publisher by modifying the contents of the shared memory buffer while
414 // it is being updated.
Jeff Brownc5ed5912010-07-14 18:48:53 -0700415 if (action == AMOTION_EVENT_ACTION_MOVE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700416 mMotionEventPointerCount = pointerCount;
417 mMotionEventSampleDataStride = InputMessage::sampleDataStride(pointerCount);
418 mMotionEventSampleDataTail = InputMessage::sampleDataPtrIncrement(
419 mSharedMessage->motion.sampleData, mMotionEventSampleDataStride);
420 } else {
421 mMotionEventSampleDataTail = NULL;
422 }
423 return OK;
424}
425
426status_t InputPublisher::appendMotionSample(
427 nsecs_t eventTime,
428 const PointerCoords* pointerCoords) {
429#if DEBUG_TRANSPORT_ACTIONS
430 LOGD("channel '%s' publisher ~ appendMotionSample: eventTime=%lld",
431 mChannel->getName().string(), eventTime);
432#endif
433
434 if (! mPinned || ! mMotionEventSampleDataTail) {
435 LOGE("channel '%s' publisher ~ Cannot append motion sample because there is no current "
Jeff Brownc5ed5912010-07-14 18:48:53 -0700436 "AMOTION_EVENT_ACTION_MOVE event.", mChannel->getName().string());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700437 return INVALID_OPERATION;
438 }
439
440 InputMessage::SampleData* newTail = InputMessage::sampleDataPtrIncrement(
441 mMotionEventSampleDataTail, mMotionEventSampleDataStride);
442 size_t newBytesUsed = reinterpret_cast<char*>(newTail) -
443 reinterpret_cast<char*>(mSharedMessage);
444
445 if (newBytesUsed > mAshmemSize) {
Jeff Brown349703e2010-06-22 01:27:15 -0700446#if DEBUG_TRANSPORT_ACTIONS
Jeff Brown46b9ac02010-04-22 18:58:52 -0700447 LOGD("channel '%s' publisher ~ Cannot append motion sample because the shared memory "
448 "buffer is full. Buffer size: %d bytes, pointers: %d, samples: %d",
449 mChannel->getName().string(),
450 mAshmemSize, mMotionEventPointerCount, mSharedMessage->motion.sampleCount);
Jeff Brown349703e2010-06-22 01:27:15 -0700451#endif
Jeff Brown46b9ac02010-04-22 18:58:52 -0700452 return NO_MEMORY;
453 }
454
455 int result;
456 if (mWasDispatched) {
457 result = sem_trywait(& mSharedMessage->semaphore);
458 if (result < 0) {
459 if (errno == EAGAIN) {
460 // Only possible source of contention is the consumer having consumed (or being in the
461 // process of consuming) the message and left the semaphore count at 0.
Jeff Brown349703e2010-06-22 01:27:15 -0700462#if DEBUG_TRANSPORT_ACTIONS
Jeff Brown46b9ac02010-04-22 18:58:52 -0700463 LOGD("channel '%s' publisher ~ Cannot append motion sample because the message has "
464 "already been consumed.", mChannel->getName().string());
Jeff Brown349703e2010-06-22 01:27:15 -0700465#endif
Jeff Brown46b9ac02010-04-22 18:58:52 -0700466 return FAILED_TRANSACTION;
467 } else {
468 LOGE("channel '%s' publisher ~ Error %d in sem_trywait.",
469 mChannel->getName().string(), errno);
470 return UNKNOWN_ERROR;
471 }
472 }
473 }
474
475 mMotionEventSampleDataTail->eventTime = eventTime;
476 for (size_t i = 0; i < mMotionEventPointerCount; i++) {
477 mMotionEventSampleDataTail->coords[i] = pointerCoords[i];
478 }
479 mMotionEventSampleDataTail = newTail;
480
481 mSharedMessage->motion.sampleCount += 1;
482
483 if (mWasDispatched) {
484 result = sem_post(& mSharedMessage->semaphore);
485 if (result < 0) {
486 LOGE("channel '%s' publisher ~ Error %d in sem_post.",
487 mChannel->getName().string(), errno);
488 return UNKNOWN_ERROR;
489 }
490 }
491 return OK;
492}
493
494status_t InputPublisher::sendDispatchSignal() {
495#if DEBUG_TRANSPORT_ACTIONS
496 LOGD("channel '%s' publisher ~ sendDispatchSignal",
497 mChannel->getName().string());
498#endif
499
500 mWasDispatched = true;
501 return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
502}
503
Jeff Brown49ed71d2010-12-06 17:13:33 -0800504status_t InputPublisher::receiveFinishedSignal(bool* outHandled) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700505#if DEBUG_TRANSPORT_ACTIONS
506 LOGD("channel '%s' publisher ~ receiveFinishedSignal",
507 mChannel->getName().string());
508#endif
509
510 char signal;
511 status_t result = mChannel->receiveSignal(& signal);
512 if (result) {
Jeff Brown49ed71d2010-12-06 17:13:33 -0800513 *outHandled = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700514 return result;
515 }
Jeff Brown3915bb82010-11-05 15:02:16 -0700516 if (signal == INPUT_SIGNAL_FINISHED_HANDLED) {
Jeff Brown49ed71d2010-12-06 17:13:33 -0800517 *outHandled = true;
Jeff Brown3915bb82010-11-05 15:02:16 -0700518 } else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) {
Jeff Brown49ed71d2010-12-06 17:13:33 -0800519 *outHandled = false;
Jeff Brown3915bb82010-11-05 15:02:16 -0700520 } else {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700521 LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
522 mChannel->getName().string(), signal);
523 return UNKNOWN_ERROR;
524 }
525 return OK;
526}
527
528// --- InputConsumer ---
529
530InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
531 mChannel(channel), mSharedMessage(NULL) {
532}
533
534InputConsumer::~InputConsumer() {
535 if (mSharedMessage) {
536 munmap(mSharedMessage, mAshmemSize);
537 }
538}
539
540status_t InputConsumer::initialize() {
541#if DEBUG_TRANSPORT_ACTIONS
542 LOGD("channel '%s' consumer ~ initialize",
543 mChannel->getName().string());
544#endif
545
546 int ashmemFd = mChannel->getAshmemFd();
547 int result = ashmem_get_size_region(ashmemFd);
548 if (result < 0) {
549 LOGE("channel '%s' consumer ~ Error %d getting size of ashmem fd %d.",
550 mChannel->getName().string(), result, ashmemFd);
551 return UNKNOWN_ERROR;
552 }
553
554 mAshmemSize = (size_t) result;
555
556 mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
557 PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
558 if (! mSharedMessage) {
559 LOGE("channel '%s' consumer ~ mmap failed on ashmem fd %d.",
560 mChannel->getName().string(), ashmemFd);
561 return NO_MEMORY;
562 }
563
564 return OK;
565}
566
Jeff Brown5c225b12010-06-16 01:53:36 -0700567status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent** outEvent) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700568#if DEBUG_TRANSPORT_ACTIONS
569 LOGD("channel '%s' consumer ~ consume",
570 mChannel->getName().string());
571#endif
572
Jeff Brown5c225b12010-06-16 01:53:36 -0700573 *outEvent = NULL;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700574
575 int ashmemFd = mChannel->getAshmemFd();
576 int result = ashmem_pin_region(ashmemFd, 0, 0);
577 if (result != ASHMEM_NOT_PURGED) {
578 if (result == ASHMEM_WAS_PURGED) {
579 LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d because it was purged "
580 "which probably indicates that the publisher and consumer are out of sync.",
581 mChannel->getName().string(), result, ashmemFd);
582 return INVALID_OPERATION;
583 }
584
585 LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d.",
586 mChannel->getName().string(), result, ashmemFd);
587 return UNKNOWN_ERROR;
588 }
589
590 if (mSharedMessage->consumed) {
591 LOGE("channel '%s' consumer ~ The current message has already been consumed.",
592 mChannel->getName().string());
593 return INVALID_OPERATION;
594 }
595
596 // Acquire but *never release* the semaphore. Contention on the semaphore is used to signal
597 // to the publisher that the message has been consumed (or is in the process of being
598 // consumed). Eventually the publisher will reinitialize the semaphore for the next message.
599 result = sem_wait(& mSharedMessage->semaphore);
600 if (result < 0) {
601 LOGE("channel '%s' consumer ~ Error %d in sem_wait.",
602 mChannel->getName().string(), errno);
603 return UNKNOWN_ERROR;
604 }
605
606 mSharedMessage->consumed = true;
607
608 switch (mSharedMessage->type) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700609 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700610 KeyEvent* keyEvent = factory->createKeyEvent();
611 if (! keyEvent) return NO_MEMORY;
612
613 populateKeyEvent(keyEvent);
614
Jeff Brown5c225b12010-06-16 01:53:36 -0700615 *outEvent = keyEvent;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700616 break;
617 }
618
Jeff Brownc5ed5912010-07-14 18:48:53 -0700619 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700620 MotionEvent* motionEvent = factory->createMotionEvent();
621 if (! motionEvent) return NO_MEMORY;
622
623 populateMotionEvent(motionEvent);
624
Jeff Brown5c225b12010-06-16 01:53:36 -0700625 *outEvent = motionEvent;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700626 break;
627 }
628
629 default:
630 LOGE("channel '%s' consumer ~ Received message of unknown type %d",
631 mChannel->getName().string(), mSharedMessage->type);
632 return UNKNOWN_ERROR;
633 }
634
635 return OK;
636}
637
Jeff Brown3915bb82010-11-05 15:02:16 -0700638status_t InputConsumer::sendFinishedSignal(bool handled) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700639#if DEBUG_TRANSPORT_ACTIONS
Jeff Brown3915bb82010-11-05 15:02:16 -0700640 LOGD("channel '%s' consumer ~ sendFinishedSignal: handled=%d",
641 mChannel->getName().string(), handled);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700642#endif
643
Jeff Brown3915bb82010-11-05 15:02:16 -0700644 return mChannel->sendSignal(handled
645 ? INPUT_SIGNAL_FINISHED_HANDLED
646 : INPUT_SIGNAL_FINISHED_UNHANDLED);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700647}
648
649status_t InputConsumer::receiveDispatchSignal() {
650#if DEBUG_TRANSPORT_ACTIONS
651 LOGD("channel '%s' consumer ~ receiveDispatchSignal",
652 mChannel->getName().string());
653#endif
654
655 char signal;
656 status_t result = mChannel->receiveSignal(& signal);
657 if (result) {
658 return result;
659 }
660 if (signal != INPUT_SIGNAL_DISPATCH) {
661 LOGE("channel '%s' consumer ~ Received unexpected signal '%c' from publisher",
662 mChannel->getName().string(), signal);
663 return UNKNOWN_ERROR;
664 }
665 return OK;
666}
667
668void InputConsumer::populateKeyEvent(KeyEvent* keyEvent) const {
669 keyEvent->initialize(
670 mSharedMessage->deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700671 mSharedMessage->source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700672 mSharedMessage->key.action,
673 mSharedMessage->key.flags,
674 mSharedMessage->key.keyCode,
675 mSharedMessage->key.scanCode,
676 mSharedMessage->key.metaState,
677 mSharedMessage->key.repeatCount,
678 mSharedMessage->key.downTime,
679 mSharedMessage->key.eventTime);
680}
681
682void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
683 motionEvent->initialize(
684 mSharedMessage->deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700685 mSharedMessage->source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700686 mSharedMessage->motion.action,
Jeff Brown85a31762010-09-01 17:01:00 -0700687 mSharedMessage->motion.flags,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700688 mSharedMessage->motion.edgeFlags,
689 mSharedMessage->motion.metaState,
Jeff Brown5c225b12010-06-16 01:53:36 -0700690 mSharedMessage->motion.xOffset,
691 mSharedMessage->motion.yOffset,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700692 mSharedMessage->motion.xPrecision,
693 mSharedMessage->motion.yPrecision,
694 mSharedMessage->motion.downTime,
695 mSharedMessage->motion.sampleData[0].eventTime,
696 mSharedMessage->motion.pointerCount,
697 mSharedMessage->motion.pointerIds,
698 mSharedMessage->motion.sampleData[0].coords);
699
700 size_t sampleCount = mSharedMessage->motion.sampleCount;
701 if (sampleCount > 1) {
702 InputMessage::SampleData* sampleData = mSharedMessage->motion.sampleData;
703 size_t sampleDataStride = InputMessage::sampleDataStride(
704 mSharedMessage->motion.pointerCount);
705
706 while (--sampleCount > 0) {
707 sampleData = InputMessage::sampleDataPtrIncrement(sampleData, sampleDataStride);
708 motionEvent->addSample(sampleData->eventTime, sampleData->coords);
709 }
710 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700711}
712
713} // namespace android