blob: 00716d74bf8592717d697d6761c0bd015ed81c8d [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
Jeff Brown4e91a182011-04-07 11:38:09 -070030#define ROUND_UP(value, boundary) (((value) + (boundary) - 1) & ~((boundary) - 1))
31#define MIN_HISTORY_DEPTH 20
32
Jeff Brown46b9ac02010-04-22 18:58:52 -070033// Must be at least sizeof(InputMessage) + sufficient space for pointer data
Jeff Brown4e91a182011-04-07 11:38:09 -070034static const int DEFAULT_MESSAGE_BUFFER_SIZE = ROUND_UP(
35 sizeof(InputMessage) + MIN_HISTORY_DEPTH
36 * (sizeof(InputMessage::SampleData) + MAX_POINTERS * sizeof(PointerCoords)),
37 4096);
Jeff Brown46b9ac02010-04-22 18:58:52 -070038
39// Signal sent by the producer to the consumer to inform it that a new message is
40// available to be consumed in the shared memory buffer.
41static const char INPUT_SIGNAL_DISPATCH = 'D';
42
43// Signal sent by the consumer to the producer to inform it that it has finished
Jeff Brown3915bb82010-11-05 15:02:16 -070044// consuming the most recent message and it handled it.
45static const char INPUT_SIGNAL_FINISHED_HANDLED = 'f';
46
47// Signal sent by the consumer to the producer to inform it that it has finished
48// consuming the most recent message but it did not handle it.
49static const char INPUT_SIGNAL_FINISHED_UNHANDLED = 'u';
Jeff Brown46b9ac02010-04-22 18:58:52 -070050
51
52// --- InputChannel ---
53
54InputChannel::InputChannel(const String8& name, int32_t ashmemFd, int32_t receivePipeFd,
55 int32_t sendPipeFd) :
56 mName(name), mAshmemFd(ashmemFd), mReceivePipeFd(receivePipeFd), mSendPipeFd(sendPipeFd) {
57#if DEBUG_CHANNEL_LIFECYCLE
Steve Block5baa3a62011-12-20 16:23:08 +000058 ALOGD("Input channel constructed: name='%s', ashmemFd=%d, receivePipeFd=%d, sendPipeFd=%d",
Jeff Brown46b9ac02010-04-22 18:58:52 -070059 mName.string(), ashmemFd, receivePipeFd, sendPipeFd);
60#endif
61
62 int result = fcntl(mReceivePipeFd, F_SETFL, O_NONBLOCK);
63 LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make receive pipe "
64 "non-blocking. errno=%d", mName.string(), errno);
65
66 result = fcntl(mSendPipeFd, F_SETFL, O_NONBLOCK);
67 LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make send pipe "
68 "non-blocking. errno=%d", mName.string(), errno);
69}
70
71InputChannel::~InputChannel() {
72#if DEBUG_CHANNEL_LIFECYCLE
Steve Block5baa3a62011-12-20 16:23:08 +000073 ALOGD("Input channel destroyed: name='%s', ashmemFd=%d, receivePipeFd=%d, sendPipeFd=%d",
Jeff Brown46b9ac02010-04-22 18:58:52 -070074 mName.string(), mAshmemFd, mReceivePipeFd, mSendPipeFd);
75#endif
76
77 ::close(mAshmemFd);
78 ::close(mReceivePipeFd);
79 ::close(mSendPipeFd);
80}
81
82status_t InputChannel::openInputChannelPair(const String8& name,
Jeff Brown5c225b12010-06-16 01:53:36 -070083 sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
Jeff Brown46b9ac02010-04-22 18:58:52 -070084 status_t result;
85
Jeff Brownf7537bc2011-07-13 22:18:46 -070086 String8 ashmemName("InputChannel ");
87 ashmemName.append(name);
88 int serverAshmemFd = ashmem_create_region(ashmemName.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
Jeff Brown46b9ac02010-04-22 18:58:52 -070089 if (serverAshmemFd < 0) {
90 result = -errno;
91 LOGE("channel '%s' ~ Could not create shared memory region. errno=%d",
92 name.string(), errno);
93 } else {
94 result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE);
95 if (result < 0) {
96 LOGE("channel '%s' ~ Error %d trying to set protection of ashmem fd %d.",
97 name.string(), result, serverAshmemFd);
98 } else {
99 // Dup the file descriptor because the server and client input channel objects that
100 // are returned may have different lifetimes but they share the same shared memory region.
101 int clientAshmemFd;
102 clientAshmemFd = dup(serverAshmemFd);
103 if (clientAshmemFd < 0) {
104 result = -errno;
105 LOGE("channel '%s' ~ Could not dup() shared memory region fd. errno=%d",
106 name.string(), errno);
107 } else {
108 int forward[2];
109 if (pipe(forward)) {
110 result = -errno;
111 LOGE("channel '%s' ~ Could not create forward pipe. errno=%d",
112 name.string(), errno);
113 } else {
114 int reverse[2];
115 if (pipe(reverse)) {
116 result = -errno;
117 LOGE("channel '%s' ~ Could not create reverse pipe. errno=%d",
118 name.string(), errno);
119 } else {
120 String8 serverChannelName = name;
121 serverChannelName.append(" (server)");
Jeff Brown5c225b12010-06-16 01:53:36 -0700122 outServerChannel = new InputChannel(serverChannelName,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700123 serverAshmemFd, reverse[0], forward[1]);
124
125 String8 clientChannelName = name;
126 clientChannelName.append(" (client)");
Jeff Brown5c225b12010-06-16 01:53:36 -0700127 outClientChannel = new InputChannel(clientChannelName,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700128 clientAshmemFd, forward[0], reverse[1]);
129 return OK;
130 }
131 ::close(forward[0]);
132 ::close(forward[1]);
133 }
134 ::close(clientAshmemFd);
135 }
136 }
137 ::close(serverAshmemFd);
138 }
139
Jeff Brown5c225b12010-06-16 01:53:36 -0700140 outServerChannel.clear();
141 outClientChannel.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700142 return result;
143}
144
145status_t InputChannel::sendSignal(char signal) {
Jeff Brown7dae0e42010-09-16 17:04:52 -0700146 ssize_t nWrite;
147 do {
148 nWrite = ::write(mSendPipeFd, & signal, 1);
149 } while (nWrite == -1 && errno == EINTR);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700150
151 if (nWrite == 1) {
152#if DEBUG_CHANNEL_SIGNALS
Steve Block5baa3a62011-12-20 16:23:08 +0000153 ALOGD("channel '%s' ~ sent signal '%c'", mName.string(), signal);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700154#endif
155 return OK;
156 }
157
158#if DEBUG_CHANNEL_SIGNALS
Steve Block5baa3a62011-12-20 16:23:08 +0000159 ALOGD("channel '%s' ~ error sending signal '%c', errno=%d", mName.string(), signal, errno);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700160#endif
161 return -errno;
162}
163
164status_t InputChannel::receiveSignal(char* outSignal) {
Jeff Brown7dae0e42010-09-16 17:04:52 -0700165 ssize_t nRead;
166 do {
167 nRead = ::read(mReceivePipeFd, outSignal, 1);
168 } while (nRead == -1 && errno == EINTR);
169
Jeff Brown46b9ac02010-04-22 18:58:52 -0700170 if (nRead == 1) {
171#if DEBUG_CHANNEL_SIGNALS
Steve Block5baa3a62011-12-20 16:23:08 +0000172 ALOGD("channel '%s' ~ received signal '%c'", mName.string(), *outSignal);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700173#endif
174 return OK;
175 }
176
Jeff Brown5c225b12010-06-16 01:53:36 -0700177 if (nRead == 0) { // check for EOF
178#if DEBUG_CHANNEL_SIGNALS
Steve Block5baa3a62011-12-20 16:23:08 +0000179 ALOGD("channel '%s' ~ receive signal failed because peer was closed", mName.string());
Jeff Brown5c225b12010-06-16 01:53:36 -0700180#endif
181 return DEAD_OBJECT;
182 }
183
Jeff Brown46b9ac02010-04-22 18:58:52 -0700184 if (errno == EAGAIN) {
185#if DEBUG_CHANNEL_SIGNALS
Steve Block5baa3a62011-12-20 16:23:08 +0000186 ALOGD("channel '%s' ~ receive signal failed because no signal available", mName.string());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700187#endif
188 return WOULD_BLOCK;
189 }
190
191#if DEBUG_CHANNEL_SIGNALS
Steve Block5baa3a62011-12-20 16:23:08 +0000192 ALOGD("channel '%s' ~ receive signal failed, errno=%d", mName.string(), errno);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700193#endif
194 return -errno;
195}
196
197
198// --- InputPublisher ---
199
200InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
201 mChannel(channel), mSharedMessage(NULL),
202 mPinned(false), mSemaphoreInitialized(false), mWasDispatched(false),
203 mMotionEventSampleDataTail(NULL) {
204}
205
206InputPublisher::~InputPublisher() {
207 reset();
208
209 if (mSharedMessage) {
210 munmap(mSharedMessage, mAshmemSize);
211 }
212}
213
214status_t InputPublisher::initialize() {
215#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000216 ALOGD("channel '%s' publisher ~ initialize",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700217 mChannel->getName().string());
218#endif
219
220 int ashmemFd = mChannel->getAshmemFd();
221 int result = ashmem_get_size_region(ashmemFd);
222 if (result < 0) {
223 LOGE("channel '%s' publisher ~ Error %d getting size of ashmem fd %d.",
224 mChannel->getName().string(), result, ashmemFd);
225 return UNKNOWN_ERROR;
226 }
227 mAshmemSize = (size_t) result;
228
229 mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
230 PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
231 if (! mSharedMessage) {
232 LOGE("channel '%s' publisher ~ mmap failed on ashmem fd %d.",
233 mChannel->getName().string(), ashmemFd);
234 return NO_MEMORY;
235 }
236
237 mPinned = true;
238 mSharedMessage->consumed = false;
239
240 return reset();
241}
242
243status_t InputPublisher::reset() {
244#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000245 ALOGD("channel '%s' publisher ~ reset",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700246 mChannel->getName().string());
247#endif
248
249 if (mPinned) {
250 // Destroy the semaphore since we are about to unpin the memory region that contains it.
251 int result;
252 if (mSemaphoreInitialized) {
253 if (mSharedMessage->consumed) {
254 result = sem_post(& mSharedMessage->semaphore);
255 if (result < 0) {
256 LOGE("channel '%s' publisher ~ Error %d in sem_post.",
257 mChannel->getName().string(), errno);
258 return UNKNOWN_ERROR;
259 }
260 }
261
262 result = sem_destroy(& mSharedMessage->semaphore);
263 if (result < 0) {
264 LOGE("channel '%s' publisher ~ Error %d in sem_destroy.",
265 mChannel->getName().string(), errno);
266 return UNKNOWN_ERROR;
267 }
268
269 mSemaphoreInitialized = false;
270 }
271
272 // Unpin the region since we no longer care about its contents.
273 int ashmemFd = mChannel->getAshmemFd();
274 result = ashmem_unpin_region(ashmemFd, 0, 0);
275 if (result < 0) {
276 LOGE("channel '%s' publisher ~ Error %d unpinning ashmem fd %d.",
277 mChannel->getName().string(), result, ashmemFd);
278 return UNKNOWN_ERROR;
279 }
280
281 mPinned = false;
282 }
283
284 mMotionEventSampleDataTail = NULL;
285 mWasDispatched = false;
286 return OK;
287}
288
289status_t InputPublisher::publishInputEvent(
290 int32_t type,
291 int32_t deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700292 int32_t source) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700293 if (mPinned) {
294 LOGE("channel '%s' publisher ~ Attempted to publish a new event but publisher has "
295 "not yet been reset.", mChannel->getName().string());
296 return INVALID_OPERATION;
297 }
298
299 // Pin the region.
300 // We do not check for ASHMEM_NOT_PURGED because we don't care about the previous
301 // contents of the buffer so it does not matter whether it was purged in the meantime.
302 int ashmemFd = mChannel->getAshmemFd();
303 int result = ashmem_pin_region(ashmemFd, 0, 0);
304 if (result < 0) {
305 LOGE("channel '%s' publisher ~ Error %d pinning ashmem fd %d.",
306 mChannel->getName().string(), result, ashmemFd);
307 return UNKNOWN_ERROR;
308 }
309
310 mPinned = true;
311
312 result = sem_init(& mSharedMessage->semaphore, 1, 1);
313 if (result < 0) {
314 LOGE("channel '%s' publisher ~ Error %d in sem_init.",
315 mChannel->getName().string(), errno);
316 return UNKNOWN_ERROR;
317 }
318
319 mSemaphoreInitialized = true;
320
321 mSharedMessage->consumed = false;
322 mSharedMessage->type = type;
323 mSharedMessage->deviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700324 mSharedMessage->source = source;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700325 return OK;
326}
327
328status_t InputPublisher::publishKeyEvent(
329 int32_t deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700330 int32_t source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700331 int32_t action,
332 int32_t flags,
333 int32_t keyCode,
334 int32_t scanCode,
335 int32_t metaState,
336 int32_t repeatCount,
337 nsecs_t downTime,
338 nsecs_t eventTime) {
339#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000340 ALOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=0x%x, "
Jeff Brown85a31762010-09-01 17:01:00 -0700341 "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
Jeff Brown46b9ac02010-04-22 18:58:52 -0700342 "downTime=%lld, eventTime=%lld",
343 mChannel->getName().string(),
Jeff Brownc5ed5912010-07-14 18:48:53 -0700344 deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700345 downTime, eventTime);
346#endif
347
Jeff Brownc5ed5912010-07-14 18:48:53 -0700348 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_KEY, deviceId, source);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700349 if (result < 0) {
350 return result;
351 }
352
353 mSharedMessage->key.action = action;
354 mSharedMessage->key.flags = flags;
355 mSharedMessage->key.keyCode = keyCode;
356 mSharedMessage->key.scanCode = scanCode;
357 mSharedMessage->key.metaState = metaState;
358 mSharedMessage->key.repeatCount = repeatCount;
359 mSharedMessage->key.downTime = downTime;
360 mSharedMessage->key.eventTime = eventTime;
361 return OK;
362}
363
364status_t InputPublisher::publishMotionEvent(
365 int32_t deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700366 int32_t source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700367 int32_t action,
Jeff Brown85a31762010-09-01 17:01:00 -0700368 int32_t flags,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700369 int32_t edgeFlags,
370 int32_t metaState,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700371 int32_t buttonState,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700372 float xOffset,
373 float yOffset,
374 float xPrecision,
375 float yPrecision,
376 nsecs_t downTime,
377 nsecs_t eventTime,
378 size_t pointerCount,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700379 const PointerProperties* pointerProperties,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700380 const PointerCoords* pointerCoords) {
381#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000382 ALOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700383 "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
384 "xOffset=%f, yOffset=%f, "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700385 "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
386 "pointerCount=%d",
387 mChannel->getName().string(),
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700388 deviceId, source, action, flags, edgeFlags, metaState, buttonState,
389 xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700390#endif
391
392 if (pointerCount > MAX_POINTERS || pointerCount < 1) {
393 LOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.",
394 mChannel->getName().string(), pointerCount);
395 return BAD_VALUE;
396 }
397
Jeff Brownc5ed5912010-07-14 18:48:53 -0700398 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_MOTION, deviceId, source);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700399 if (result < 0) {
400 return result;
401 }
402
403 mSharedMessage->motion.action = action;
Jeff Brown85a31762010-09-01 17:01:00 -0700404 mSharedMessage->motion.flags = flags;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700405 mSharedMessage->motion.edgeFlags = edgeFlags;
406 mSharedMessage->motion.metaState = metaState;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700407 mSharedMessage->motion.buttonState = buttonState;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700408 mSharedMessage->motion.xOffset = xOffset;
409 mSharedMessage->motion.yOffset = yOffset;
410 mSharedMessage->motion.xPrecision = xPrecision;
411 mSharedMessage->motion.yPrecision = yPrecision;
412 mSharedMessage->motion.downTime = downTime;
413 mSharedMessage->motion.pointerCount = pointerCount;
414
415 mSharedMessage->motion.sampleCount = 1;
416 mSharedMessage->motion.sampleData[0].eventTime = eventTime;
417
418 for (size_t i = 0; i < pointerCount; i++) {
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700419 mSharedMessage->motion.pointerProperties[i].copyFrom(pointerProperties[i]);
Jeff Brownace13b12011-03-09 17:39:48 -0800420 mSharedMessage->motion.sampleData[0].coords[i].copyFrom(pointerCoords[i]);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700421 }
422
423 // Cache essential information about the motion event to ensure that a malicious consumer
424 // cannot confuse the publisher by modifying the contents of the shared memory buffer while
425 // it is being updated.
Jeff Browncc0c1592011-02-19 05:07:28 -0800426 if (action == AMOTION_EVENT_ACTION_MOVE
427 || action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700428 mMotionEventPointerCount = pointerCount;
429 mMotionEventSampleDataStride = InputMessage::sampleDataStride(pointerCount);
430 mMotionEventSampleDataTail = InputMessage::sampleDataPtrIncrement(
431 mSharedMessage->motion.sampleData, mMotionEventSampleDataStride);
432 } else {
433 mMotionEventSampleDataTail = NULL;
434 }
435 return OK;
436}
437
438status_t InputPublisher::appendMotionSample(
439 nsecs_t eventTime,
440 const PointerCoords* pointerCoords) {
441#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000442 ALOGD("channel '%s' publisher ~ appendMotionSample: eventTime=%lld",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700443 mChannel->getName().string(), eventTime);
444#endif
445
446 if (! mPinned || ! mMotionEventSampleDataTail) {
447 LOGE("channel '%s' publisher ~ Cannot append motion sample because there is no current "
Jeff Brown81346812011-06-28 20:08:48 -0700448 "AMOTION_EVENT_ACTION_MOVE or AMOTION_EVENT_ACTION_HOVER_MOVE event.",
449 mChannel->getName().string());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700450 return INVALID_OPERATION;
451 }
452
453 InputMessage::SampleData* newTail = InputMessage::sampleDataPtrIncrement(
454 mMotionEventSampleDataTail, mMotionEventSampleDataStride);
455 size_t newBytesUsed = reinterpret_cast<char*>(newTail) -
456 reinterpret_cast<char*>(mSharedMessage);
457
458 if (newBytesUsed > mAshmemSize) {
Jeff Brown349703e2010-06-22 01:27:15 -0700459#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000460 ALOGD("channel '%s' publisher ~ Cannot append motion sample because the shared memory "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700461 "buffer is full. Buffer size: %d bytes, pointers: %d, samples: %d",
462 mChannel->getName().string(),
463 mAshmemSize, mMotionEventPointerCount, mSharedMessage->motion.sampleCount);
Jeff Brown349703e2010-06-22 01:27:15 -0700464#endif
Jeff Brown46b9ac02010-04-22 18:58:52 -0700465 return NO_MEMORY;
466 }
467
468 int result;
469 if (mWasDispatched) {
470 result = sem_trywait(& mSharedMessage->semaphore);
471 if (result < 0) {
472 if (errno == EAGAIN) {
473 // Only possible source of contention is the consumer having consumed (or being in the
474 // process of consuming) the message and left the semaphore count at 0.
Jeff Brown349703e2010-06-22 01:27:15 -0700475#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000476 ALOGD("channel '%s' publisher ~ Cannot append motion sample because the message has "
Jeff Brown46b9ac02010-04-22 18:58:52 -0700477 "already been consumed.", mChannel->getName().string());
Jeff Brown349703e2010-06-22 01:27:15 -0700478#endif
Jeff Brown46b9ac02010-04-22 18:58:52 -0700479 return FAILED_TRANSACTION;
480 } else {
481 LOGE("channel '%s' publisher ~ Error %d in sem_trywait.",
482 mChannel->getName().string(), errno);
483 return UNKNOWN_ERROR;
484 }
485 }
486 }
487
488 mMotionEventSampleDataTail->eventTime = eventTime;
489 for (size_t i = 0; i < mMotionEventPointerCount; i++) {
Jeff Brownace13b12011-03-09 17:39:48 -0800490 mMotionEventSampleDataTail->coords[i].copyFrom(pointerCoords[i]);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700491 }
492 mMotionEventSampleDataTail = newTail;
493
494 mSharedMessage->motion.sampleCount += 1;
495
496 if (mWasDispatched) {
497 result = sem_post(& mSharedMessage->semaphore);
498 if (result < 0) {
499 LOGE("channel '%s' publisher ~ Error %d in sem_post.",
500 mChannel->getName().string(), errno);
501 return UNKNOWN_ERROR;
502 }
503 }
504 return OK;
505}
506
507status_t InputPublisher::sendDispatchSignal() {
508#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000509 ALOGD("channel '%s' publisher ~ sendDispatchSignal",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700510 mChannel->getName().string());
511#endif
512
513 mWasDispatched = true;
514 return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
515}
516
Jeff Brown49ed71d2010-12-06 17:13:33 -0800517status_t InputPublisher::receiveFinishedSignal(bool* outHandled) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700518#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000519 ALOGD("channel '%s' publisher ~ receiveFinishedSignal",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700520 mChannel->getName().string());
521#endif
522
523 char signal;
524 status_t result = mChannel->receiveSignal(& signal);
525 if (result) {
Jeff Brown49ed71d2010-12-06 17:13:33 -0800526 *outHandled = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700527 return result;
528 }
Jeff Brown3915bb82010-11-05 15:02:16 -0700529 if (signal == INPUT_SIGNAL_FINISHED_HANDLED) {
Jeff Brown49ed71d2010-12-06 17:13:33 -0800530 *outHandled = true;
Jeff Brown3915bb82010-11-05 15:02:16 -0700531 } else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) {
Jeff Brown49ed71d2010-12-06 17:13:33 -0800532 *outHandled = false;
Jeff Brown3915bb82010-11-05 15:02:16 -0700533 } else {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700534 LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
535 mChannel->getName().string(), signal);
536 return UNKNOWN_ERROR;
537 }
538 return OK;
539}
540
541// --- InputConsumer ---
542
543InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
544 mChannel(channel), mSharedMessage(NULL) {
545}
546
547InputConsumer::~InputConsumer() {
548 if (mSharedMessage) {
549 munmap(mSharedMessage, mAshmemSize);
550 }
551}
552
553status_t InputConsumer::initialize() {
554#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000555 ALOGD("channel '%s' consumer ~ initialize",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700556 mChannel->getName().string());
557#endif
558
559 int ashmemFd = mChannel->getAshmemFd();
560 int result = ashmem_get_size_region(ashmemFd);
561 if (result < 0) {
562 LOGE("channel '%s' consumer ~ Error %d getting size of ashmem fd %d.",
563 mChannel->getName().string(), result, ashmemFd);
564 return UNKNOWN_ERROR;
565 }
566
567 mAshmemSize = (size_t) result;
568
569 mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
570 PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
571 if (! mSharedMessage) {
572 LOGE("channel '%s' consumer ~ mmap failed on ashmem fd %d.",
573 mChannel->getName().string(), ashmemFd);
574 return NO_MEMORY;
575 }
576
577 return OK;
578}
579
Jeff Brown5c225b12010-06-16 01:53:36 -0700580status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent** outEvent) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700581#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000582 ALOGD("channel '%s' consumer ~ consume",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700583 mChannel->getName().string());
584#endif
585
Jeff Brown5c225b12010-06-16 01:53:36 -0700586 *outEvent = NULL;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700587
588 int ashmemFd = mChannel->getAshmemFd();
589 int result = ashmem_pin_region(ashmemFd, 0, 0);
590 if (result != ASHMEM_NOT_PURGED) {
591 if (result == ASHMEM_WAS_PURGED) {
592 LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d because it was purged "
593 "which probably indicates that the publisher and consumer are out of sync.",
594 mChannel->getName().string(), result, ashmemFd);
595 return INVALID_OPERATION;
596 }
597
598 LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d.",
599 mChannel->getName().string(), result, ashmemFd);
600 return UNKNOWN_ERROR;
601 }
602
603 if (mSharedMessage->consumed) {
604 LOGE("channel '%s' consumer ~ The current message has already been consumed.",
605 mChannel->getName().string());
606 return INVALID_OPERATION;
607 }
608
609 // Acquire but *never release* the semaphore. Contention on the semaphore is used to signal
610 // to the publisher that the message has been consumed (or is in the process of being
611 // consumed). Eventually the publisher will reinitialize the semaphore for the next message.
612 result = sem_wait(& mSharedMessage->semaphore);
613 if (result < 0) {
614 LOGE("channel '%s' consumer ~ Error %d in sem_wait.",
615 mChannel->getName().string(), errno);
616 return UNKNOWN_ERROR;
617 }
618
619 mSharedMessage->consumed = true;
620
621 switch (mSharedMessage->type) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700622 case AINPUT_EVENT_TYPE_KEY: {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700623 KeyEvent* keyEvent = factory->createKeyEvent();
624 if (! keyEvent) return NO_MEMORY;
625
626 populateKeyEvent(keyEvent);
627
Jeff Brown5c225b12010-06-16 01:53:36 -0700628 *outEvent = keyEvent;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700629 break;
630 }
631
Jeff Brownc5ed5912010-07-14 18:48:53 -0700632 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700633 MotionEvent* motionEvent = factory->createMotionEvent();
634 if (! motionEvent) return NO_MEMORY;
635
636 populateMotionEvent(motionEvent);
637
Jeff Brown5c225b12010-06-16 01:53:36 -0700638 *outEvent = motionEvent;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700639 break;
640 }
641
642 default:
643 LOGE("channel '%s' consumer ~ Received message of unknown type %d",
644 mChannel->getName().string(), mSharedMessage->type);
645 return UNKNOWN_ERROR;
646 }
647
648 return OK;
649}
650
Jeff Brown3915bb82010-11-05 15:02:16 -0700651status_t InputConsumer::sendFinishedSignal(bool handled) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700652#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000653 ALOGD("channel '%s' consumer ~ sendFinishedSignal: handled=%d",
Jeff Brown3915bb82010-11-05 15:02:16 -0700654 mChannel->getName().string(), handled);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700655#endif
656
Jeff Brown3915bb82010-11-05 15:02:16 -0700657 return mChannel->sendSignal(handled
658 ? INPUT_SIGNAL_FINISHED_HANDLED
659 : INPUT_SIGNAL_FINISHED_UNHANDLED);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700660}
661
662status_t InputConsumer::receiveDispatchSignal() {
663#if DEBUG_TRANSPORT_ACTIONS
Steve Block5baa3a62011-12-20 16:23:08 +0000664 ALOGD("channel '%s' consumer ~ receiveDispatchSignal",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700665 mChannel->getName().string());
666#endif
667
668 char signal;
669 status_t result = mChannel->receiveSignal(& signal);
670 if (result) {
671 return result;
672 }
673 if (signal != INPUT_SIGNAL_DISPATCH) {
674 LOGE("channel '%s' consumer ~ Received unexpected signal '%c' from publisher",
675 mChannel->getName().string(), signal);
676 return UNKNOWN_ERROR;
677 }
678 return OK;
679}
680
681void InputConsumer::populateKeyEvent(KeyEvent* keyEvent) const {
682 keyEvent->initialize(
683 mSharedMessage->deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700684 mSharedMessage->source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700685 mSharedMessage->key.action,
686 mSharedMessage->key.flags,
687 mSharedMessage->key.keyCode,
688 mSharedMessage->key.scanCode,
689 mSharedMessage->key.metaState,
690 mSharedMessage->key.repeatCount,
691 mSharedMessage->key.downTime,
692 mSharedMessage->key.eventTime);
693}
694
695void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
696 motionEvent->initialize(
697 mSharedMessage->deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700698 mSharedMessage->source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700699 mSharedMessage->motion.action,
Jeff Brown85a31762010-09-01 17:01:00 -0700700 mSharedMessage->motion.flags,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700701 mSharedMessage->motion.edgeFlags,
702 mSharedMessage->motion.metaState,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700703 mSharedMessage->motion.buttonState,
Jeff Brown5c225b12010-06-16 01:53:36 -0700704 mSharedMessage->motion.xOffset,
705 mSharedMessage->motion.yOffset,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700706 mSharedMessage->motion.xPrecision,
707 mSharedMessage->motion.yPrecision,
708 mSharedMessage->motion.downTime,
709 mSharedMessage->motion.sampleData[0].eventTime,
710 mSharedMessage->motion.pointerCount,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700711 mSharedMessage->motion.pointerProperties,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700712 mSharedMessage->motion.sampleData[0].coords);
713
714 size_t sampleCount = mSharedMessage->motion.sampleCount;
715 if (sampleCount > 1) {
716 InputMessage::SampleData* sampleData = mSharedMessage->motion.sampleData;
717 size_t sampleDataStride = InputMessage::sampleDataStride(
718 mSharedMessage->motion.pointerCount);
719
720 while (--sampleCount > 0) {
721 sampleData = InputMessage::sampleDataPtrIncrement(sampleData, sampleDataStride);
722 motionEvent->addSample(sampleData->eventTime, sampleData->coords);
723 }
724 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700725}
726
727} // namespace android