blob: c46d6f4724a208b23285f6f83796439be32bfad2 [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
Jeff Brown4e394b12011-04-07 11:38:09 -070030#define ROUND_UP(value, boundary) (((value) + (boundary) - 1) & ~((boundary) - 1))
31#define MIN_HISTORY_DEPTH 20
32
Jeff Browne839a582010-04-22 18:58:52 -070033// Must be at least sizeof(InputMessage) + sufficient space for pointer data
Jeff Brown4e394b12011-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 Browne839a582010-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 Brown81499912010-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 Browne839a582010-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
58 LOGD("Input channel constructed: name='%s', ashmemFd=%d, receivePipeFd=%d, sendPipeFd=%d",
59 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
73 LOGD("Input channel destroyed: name='%s', ashmemFd=%d, receivePipeFd=%d, sendPipeFd=%d",
74 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 Brownf4a4ec22010-06-16 01:53:36 -070083 sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
Jeff Browne839a582010-04-22 18:58:52 -070084 status_t result;
85
86 int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
87 if (serverAshmemFd < 0) {
88 result = -errno;
89 LOGE("channel '%s' ~ Could not create shared memory region. errno=%d",
90 name.string(), errno);
91 } else {
92 result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE);
93 if (result < 0) {
94 LOGE("channel '%s' ~ Error %d trying to set protection of ashmem fd %d.",
95 name.string(), result, serverAshmemFd);
96 } else {
97 // Dup the file descriptor because the server and client input channel objects that
98 // are returned may have different lifetimes but they share the same shared memory region.
99 int clientAshmemFd;
100 clientAshmemFd = dup(serverAshmemFd);
101 if (clientAshmemFd < 0) {
102 result = -errno;
103 LOGE("channel '%s' ~ Could not dup() shared memory region fd. errno=%d",
104 name.string(), errno);
105 } else {
106 int forward[2];
107 if (pipe(forward)) {
108 result = -errno;
109 LOGE("channel '%s' ~ Could not create forward pipe. errno=%d",
110 name.string(), errno);
111 } else {
112 int reverse[2];
113 if (pipe(reverse)) {
114 result = -errno;
115 LOGE("channel '%s' ~ Could not create reverse pipe. errno=%d",
116 name.string(), errno);
117 } else {
118 String8 serverChannelName = name;
119 serverChannelName.append(" (server)");
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700120 outServerChannel = new InputChannel(serverChannelName,
Jeff Browne839a582010-04-22 18:58:52 -0700121 serverAshmemFd, reverse[0], forward[1]);
122
123 String8 clientChannelName = name;
124 clientChannelName.append(" (client)");
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700125 outClientChannel = new InputChannel(clientChannelName,
Jeff Browne839a582010-04-22 18:58:52 -0700126 clientAshmemFd, forward[0], reverse[1]);
127 return OK;
128 }
129 ::close(forward[0]);
130 ::close(forward[1]);
131 }
132 ::close(clientAshmemFd);
133 }
134 }
135 ::close(serverAshmemFd);
136 }
137
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700138 outServerChannel.clear();
139 outClientChannel.clear();
Jeff Browne839a582010-04-22 18:58:52 -0700140 return result;
141}
142
143status_t InputChannel::sendSignal(char signal) {
Jeff Brownf67f2992010-09-16 17:04:52 -0700144 ssize_t nWrite;
145 do {
146 nWrite = ::write(mSendPipeFd, & signal, 1);
147 } while (nWrite == -1 && errno == EINTR);
Jeff Browne839a582010-04-22 18:58:52 -0700148
149 if (nWrite == 1) {
150#if DEBUG_CHANNEL_SIGNALS
151 LOGD("channel '%s' ~ sent signal '%c'", mName.string(), signal);
152#endif
153 return OK;
154 }
155
156#if DEBUG_CHANNEL_SIGNALS
157 LOGD("channel '%s' ~ error sending signal '%c', errno=%d", mName.string(), signal, errno);
158#endif
159 return -errno;
160}
161
162status_t InputChannel::receiveSignal(char* outSignal) {
Jeff Brownf67f2992010-09-16 17:04:52 -0700163 ssize_t nRead;
164 do {
165 nRead = ::read(mReceivePipeFd, outSignal, 1);
166 } while (nRead == -1 && errno == EINTR);
167
Jeff Browne839a582010-04-22 18:58:52 -0700168 if (nRead == 1) {
169#if DEBUG_CHANNEL_SIGNALS
170 LOGD("channel '%s' ~ received signal '%c'", mName.string(), *outSignal);
171#endif
172 return OK;
173 }
174
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700175 if (nRead == 0) { // check for EOF
176#if DEBUG_CHANNEL_SIGNALS
177 LOGD("channel '%s' ~ receive signal failed because peer was closed", mName.string());
178#endif
179 return DEAD_OBJECT;
180 }
181
Jeff Browne839a582010-04-22 18:58:52 -0700182 if (errno == EAGAIN) {
183#if DEBUG_CHANNEL_SIGNALS
184 LOGD("channel '%s' ~ receive signal failed because no signal available", mName.string());
185#endif
186 return WOULD_BLOCK;
187 }
188
189#if DEBUG_CHANNEL_SIGNALS
190 LOGD("channel '%s' ~ receive signal failed, errno=%d", mName.string(), errno);
191#endif
192 return -errno;
193}
194
195
196// --- InputPublisher ---
197
198InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
199 mChannel(channel), mSharedMessage(NULL),
200 mPinned(false), mSemaphoreInitialized(false), mWasDispatched(false),
201 mMotionEventSampleDataTail(NULL) {
202}
203
204InputPublisher::~InputPublisher() {
205 reset();
206
207 if (mSharedMessage) {
208 munmap(mSharedMessage, mAshmemSize);
209 }
210}
211
212status_t InputPublisher::initialize() {
213#if DEBUG_TRANSPORT_ACTIONS
214 LOGD("channel '%s' publisher ~ initialize",
215 mChannel->getName().string());
216#endif
217
218 int ashmemFd = mChannel->getAshmemFd();
219 int result = ashmem_get_size_region(ashmemFd);
220 if (result < 0) {
221 LOGE("channel '%s' publisher ~ Error %d getting size of ashmem fd %d.",
222 mChannel->getName().string(), result, ashmemFd);
223 return UNKNOWN_ERROR;
224 }
225 mAshmemSize = (size_t) result;
226
227 mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
228 PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
229 if (! mSharedMessage) {
230 LOGE("channel '%s' publisher ~ mmap failed on ashmem fd %d.",
231 mChannel->getName().string(), ashmemFd);
232 return NO_MEMORY;
233 }
234
235 mPinned = true;
236 mSharedMessage->consumed = false;
237
238 return reset();
239}
240
241status_t InputPublisher::reset() {
242#if DEBUG_TRANSPORT_ACTIONS
243 LOGD("channel '%s' publisher ~ reset",
244 mChannel->getName().string());
245#endif
246
247 if (mPinned) {
248 // Destroy the semaphore since we are about to unpin the memory region that contains it.
249 int result;
250 if (mSemaphoreInitialized) {
251 if (mSharedMessage->consumed) {
252 result = sem_post(& mSharedMessage->semaphore);
253 if (result < 0) {
254 LOGE("channel '%s' publisher ~ Error %d in sem_post.",
255 mChannel->getName().string(), errno);
256 return UNKNOWN_ERROR;
257 }
258 }
259
260 result = sem_destroy(& mSharedMessage->semaphore);
261 if (result < 0) {
262 LOGE("channel '%s' publisher ~ Error %d in sem_destroy.",
263 mChannel->getName().string(), errno);
264 return UNKNOWN_ERROR;
265 }
266
267 mSemaphoreInitialized = false;
268 }
269
270 // Unpin the region since we no longer care about its contents.
271 int ashmemFd = mChannel->getAshmemFd();
272 result = ashmem_unpin_region(ashmemFd, 0, 0);
273 if (result < 0) {
274 LOGE("channel '%s' publisher ~ Error %d unpinning ashmem fd %d.",
275 mChannel->getName().string(), result, ashmemFd);
276 return UNKNOWN_ERROR;
277 }
278
279 mPinned = false;
280 }
281
282 mMotionEventSampleDataTail = NULL;
283 mWasDispatched = false;
284 return OK;
285}
286
287status_t InputPublisher::publishInputEvent(
288 int32_t type,
289 int32_t deviceId,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700290 int32_t source) {
Jeff Browne839a582010-04-22 18:58:52 -0700291 if (mPinned) {
292 LOGE("channel '%s' publisher ~ Attempted to publish a new event but publisher has "
293 "not yet been reset.", mChannel->getName().string());
294 return INVALID_OPERATION;
295 }
296
297 // Pin the region.
298 // We do not check for ASHMEM_NOT_PURGED because we don't care about the previous
299 // contents of the buffer so it does not matter whether it was purged in the meantime.
300 int ashmemFd = mChannel->getAshmemFd();
301 int result = ashmem_pin_region(ashmemFd, 0, 0);
302 if (result < 0) {
303 LOGE("channel '%s' publisher ~ Error %d pinning ashmem fd %d.",
304 mChannel->getName().string(), result, ashmemFd);
305 return UNKNOWN_ERROR;
306 }
307
308 mPinned = true;
309
310 result = sem_init(& mSharedMessage->semaphore, 1, 1);
311 if (result < 0) {
312 LOGE("channel '%s' publisher ~ Error %d in sem_init.",
313 mChannel->getName().string(), errno);
314 return UNKNOWN_ERROR;
315 }
316
317 mSemaphoreInitialized = true;
318
319 mSharedMessage->consumed = false;
320 mSharedMessage->type = type;
321 mSharedMessage->deviceId = deviceId;
Jeff Brown5c1ed842010-07-14 18:48:53 -0700322 mSharedMessage->source = source;
Jeff Browne839a582010-04-22 18:58:52 -0700323 return OK;
324}
325
326status_t InputPublisher::publishKeyEvent(
327 int32_t deviceId,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700328 int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -0700329 int32_t action,
330 int32_t flags,
331 int32_t keyCode,
332 int32_t scanCode,
333 int32_t metaState,
334 int32_t repeatCount,
335 nsecs_t downTime,
336 nsecs_t eventTime) {
337#if DEBUG_TRANSPORT_ACTIONS
Jeff Brownaf30ff62010-09-01 17:01:00 -0700338 LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=0x%x, "
339 "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
Jeff Browne839a582010-04-22 18:58:52 -0700340 "downTime=%lld, eventTime=%lld",
341 mChannel->getName().string(),
Jeff Brown5c1ed842010-07-14 18:48:53 -0700342 deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
Jeff Browne839a582010-04-22 18:58:52 -0700343 downTime, eventTime);
344#endif
345
Jeff Brown5c1ed842010-07-14 18:48:53 -0700346 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_KEY, deviceId, source);
Jeff Browne839a582010-04-22 18:58:52 -0700347 if (result < 0) {
348 return result;
349 }
350
351 mSharedMessage->key.action = action;
352 mSharedMessage->key.flags = flags;
353 mSharedMessage->key.keyCode = keyCode;
354 mSharedMessage->key.scanCode = scanCode;
355 mSharedMessage->key.metaState = metaState;
356 mSharedMessage->key.repeatCount = repeatCount;
357 mSharedMessage->key.downTime = downTime;
358 mSharedMessage->key.eventTime = eventTime;
359 return OK;
360}
361
362status_t InputPublisher::publishMotionEvent(
363 int32_t deviceId,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700364 int32_t source,
Jeff Browne839a582010-04-22 18:58:52 -0700365 int32_t action,
Jeff Brownaf30ff62010-09-01 17:01:00 -0700366 int32_t flags,
Jeff Browne839a582010-04-22 18:58:52 -0700367 int32_t edgeFlags,
368 int32_t metaState,
Jeff Browne959ed22011-05-06 18:20:01 -0700369 int32_t buttonState,
Jeff Browne839a582010-04-22 18:58:52 -0700370 float xOffset,
371 float yOffset,
372 float xPrecision,
373 float yPrecision,
374 nsecs_t downTime,
375 nsecs_t eventTime,
376 size_t pointerCount,
Jeff Browne959ed22011-05-06 18:20:01 -0700377 const PointerProperties* pointerProperties,
Jeff Browne839a582010-04-22 18:58:52 -0700378 const PointerCoords* pointerCoords) {
379#if DEBUG_TRANSPORT_ACTIONS
Jeff Brownaf30ff62010-09-01 17:01:00 -0700380 LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
Jeff Browne959ed22011-05-06 18:20:01 -0700381 "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
382 "xOffset=%f, yOffset=%f, "
Jeff Browne839a582010-04-22 18:58:52 -0700383 "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
384 "pointerCount=%d",
385 mChannel->getName().string(),
Jeff Browne959ed22011-05-06 18:20:01 -0700386 deviceId, source, action, flags, edgeFlags, metaState, buttonState,
387 xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
Jeff Browne839a582010-04-22 18:58:52 -0700388#endif
389
390 if (pointerCount > MAX_POINTERS || pointerCount < 1) {
391 LOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.",
392 mChannel->getName().string(), pointerCount);
393 return BAD_VALUE;
394 }
395
Jeff Brown5c1ed842010-07-14 18:48:53 -0700396 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_MOTION, deviceId, source);
Jeff Browne839a582010-04-22 18:58:52 -0700397 if (result < 0) {
398 return result;
399 }
400
401 mSharedMessage->motion.action = action;
Jeff Brownaf30ff62010-09-01 17:01:00 -0700402 mSharedMessage->motion.flags = flags;
Jeff Browne839a582010-04-22 18:58:52 -0700403 mSharedMessage->motion.edgeFlags = edgeFlags;
404 mSharedMessage->motion.metaState = metaState;
Jeff Browne959ed22011-05-06 18:20:01 -0700405 mSharedMessage->motion.buttonState = buttonState;
Jeff Browne839a582010-04-22 18:58:52 -0700406 mSharedMessage->motion.xOffset = xOffset;
407 mSharedMessage->motion.yOffset = yOffset;
408 mSharedMessage->motion.xPrecision = xPrecision;
409 mSharedMessage->motion.yPrecision = yPrecision;
410 mSharedMessage->motion.downTime = downTime;
411 mSharedMessage->motion.pointerCount = pointerCount;
412
413 mSharedMessage->motion.sampleCount = 1;
414 mSharedMessage->motion.sampleData[0].eventTime = eventTime;
415
416 for (size_t i = 0; i < pointerCount; i++) {
Jeff Browne959ed22011-05-06 18:20:01 -0700417 mSharedMessage->motion.pointerProperties[i].copyFrom(pointerProperties[i]);
Jeff Brownfa773aa2011-03-09 17:39:48 -0800418 mSharedMessage->motion.sampleData[0].coords[i].copyFrom(pointerCoords[i]);
Jeff Browne839a582010-04-22 18:58:52 -0700419 }
420
421 // Cache essential information about the motion event to ensure that a malicious consumer
422 // cannot confuse the publisher by modifying the contents of the shared memory buffer while
423 // it is being updated.
Jeff Brown25943a82011-02-19 05:07:28 -0800424 if (action == AMOTION_EVENT_ACTION_MOVE
425 || action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
Jeff Browne839a582010-04-22 18:58:52 -0700426 mMotionEventPointerCount = pointerCount;
427 mMotionEventSampleDataStride = InputMessage::sampleDataStride(pointerCount);
428 mMotionEventSampleDataTail = InputMessage::sampleDataPtrIncrement(
429 mSharedMessage->motion.sampleData, mMotionEventSampleDataStride);
430 } else {
431 mMotionEventSampleDataTail = NULL;
432 }
433 return OK;
434}
435
436status_t InputPublisher::appendMotionSample(
437 nsecs_t eventTime,
438 const PointerCoords* pointerCoords) {
439#if DEBUG_TRANSPORT_ACTIONS
440 LOGD("channel '%s' publisher ~ appendMotionSample: eventTime=%lld",
441 mChannel->getName().string(), eventTime);
442#endif
443
444 if (! mPinned || ! mMotionEventSampleDataTail) {
445 LOGE("channel '%s' publisher ~ Cannot append motion sample because there is no current "
Jeff Brown78320802011-06-28 20:08:48 -0700446 "AMOTION_EVENT_ACTION_MOVE or AMOTION_EVENT_ACTION_HOVER_MOVE event.",
447 mChannel->getName().string());
Jeff Browne839a582010-04-22 18:58:52 -0700448 return INVALID_OPERATION;
449 }
450
451 InputMessage::SampleData* newTail = InputMessage::sampleDataPtrIncrement(
452 mMotionEventSampleDataTail, mMotionEventSampleDataStride);
453 size_t newBytesUsed = reinterpret_cast<char*>(newTail) -
454 reinterpret_cast<char*>(mSharedMessage);
455
456 if (newBytesUsed > mAshmemSize) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700457#if DEBUG_TRANSPORT_ACTIONS
Jeff Browne839a582010-04-22 18:58:52 -0700458 LOGD("channel '%s' publisher ~ Cannot append motion sample because the shared memory "
459 "buffer is full. Buffer size: %d bytes, pointers: %d, samples: %d",
460 mChannel->getName().string(),
461 mAshmemSize, mMotionEventPointerCount, mSharedMessage->motion.sampleCount);
Jeff Brown50de30a2010-06-22 01:27:15 -0700462#endif
Jeff Browne839a582010-04-22 18:58:52 -0700463 return NO_MEMORY;
464 }
465
466 int result;
467 if (mWasDispatched) {
468 result = sem_trywait(& mSharedMessage->semaphore);
469 if (result < 0) {
470 if (errno == EAGAIN) {
471 // Only possible source of contention is the consumer having consumed (or being in the
472 // process of consuming) the message and left the semaphore count at 0.
Jeff Brown50de30a2010-06-22 01:27:15 -0700473#if DEBUG_TRANSPORT_ACTIONS
Jeff Browne839a582010-04-22 18:58:52 -0700474 LOGD("channel '%s' publisher ~ Cannot append motion sample because the message has "
475 "already been consumed.", mChannel->getName().string());
Jeff Brown50de30a2010-06-22 01:27:15 -0700476#endif
Jeff Browne839a582010-04-22 18:58:52 -0700477 return FAILED_TRANSACTION;
478 } else {
479 LOGE("channel '%s' publisher ~ Error %d in sem_trywait.",
480 mChannel->getName().string(), errno);
481 return UNKNOWN_ERROR;
482 }
483 }
484 }
485
486 mMotionEventSampleDataTail->eventTime = eventTime;
487 for (size_t i = 0; i < mMotionEventPointerCount; i++) {
Jeff Brownfa773aa2011-03-09 17:39:48 -0800488 mMotionEventSampleDataTail->coords[i].copyFrom(pointerCoords[i]);
Jeff Browne839a582010-04-22 18:58:52 -0700489 }
490 mMotionEventSampleDataTail = newTail;
491
492 mSharedMessage->motion.sampleCount += 1;
493
494 if (mWasDispatched) {
495 result = sem_post(& mSharedMessage->semaphore);
496 if (result < 0) {
497 LOGE("channel '%s' publisher ~ Error %d in sem_post.",
498 mChannel->getName().string(), errno);
499 return UNKNOWN_ERROR;
500 }
501 }
502 return OK;
503}
504
505status_t InputPublisher::sendDispatchSignal() {
506#if DEBUG_TRANSPORT_ACTIONS
507 LOGD("channel '%s' publisher ~ sendDispatchSignal",
508 mChannel->getName().string());
509#endif
510
511 mWasDispatched = true;
512 return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
513}
514
Jeff Brown02d85b52010-12-06 17:13:33 -0800515status_t InputPublisher::receiveFinishedSignal(bool* outHandled) {
Jeff Browne839a582010-04-22 18:58:52 -0700516#if DEBUG_TRANSPORT_ACTIONS
517 LOGD("channel '%s' publisher ~ receiveFinishedSignal",
518 mChannel->getName().string());
519#endif
520
521 char signal;
522 status_t result = mChannel->receiveSignal(& signal);
523 if (result) {
Jeff Brown02d85b52010-12-06 17:13:33 -0800524 *outHandled = false;
Jeff Browne839a582010-04-22 18:58:52 -0700525 return result;
526 }
Jeff Brown81499912010-11-05 15:02:16 -0700527 if (signal == INPUT_SIGNAL_FINISHED_HANDLED) {
Jeff Brown02d85b52010-12-06 17:13:33 -0800528 *outHandled = true;
Jeff Brown81499912010-11-05 15:02:16 -0700529 } else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) {
Jeff Brown02d85b52010-12-06 17:13:33 -0800530 *outHandled = false;
Jeff Brown81499912010-11-05 15:02:16 -0700531 } else {
Jeff Browne839a582010-04-22 18:58:52 -0700532 LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
533 mChannel->getName().string(), signal);
534 return UNKNOWN_ERROR;
535 }
536 return OK;
537}
538
539// --- InputConsumer ---
540
541InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
542 mChannel(channel), mSharedMessage(NULL) {
543}
544
545InputConsumer::~InputConsumer() {
546 if (mSharedMessage) {
547 munmap(mSharedMessage, mAshmemSize);
548 }
549}
550
551status_t InputConsumer::initialize() {
552#if DEBUG_TRANSPORT_ACTIONS
553 LOGD("channel '%s' consumer ~ initialize",
554 mChannel->getName().string());
555#endif
556
557 int ashmemFd = mChannel->getAshmemFd();
558 int result = ashmem_get_size_region(ashmemFd);
559 if (result < 0) {
560 LOGE("channel '%s' consumer ~ Error %d getting size of ashmem fd %d.",
561 mChannel->getName().string(), result, ashmemFd);
562 return UNKNOWN_ERROR;
563 }
564
565 mAshmemSize = (size_t) result;
566
567 mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
568 PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
569 if (! mSharedMessage) {
570 LOGE("channel '%s' consumer ~ mmap failed on ashmem fd %d.",
571 mChannel->getName().string(), ashmemFd);
572 return NO_MEMORY;
573 }
574
575 return OK;
576}
577
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700578status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent** outEvent) {
Jeff Browne839a582010-04-22 18:58:52 -0700579#if DEBUG_TRANSPORT_ACTIONS
580 LOGD("channel '%s' consumer ~ consume",
581 mChannel->getName().string());
582#endif
583
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700584 *outEvent = NULL;
Jeff Browne839a582010-04-22 18:58:52 -0700585
586 int ashmemFd = mChannel->getAshmemFd();
587 int result = ashmem_pin_region(ashmemFd, 0, 0);
588 if (result != ASHMEM_NOT_PURGED) {
589 if (result == ASHMEM_WAS_PURGED) {
590 LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d because it was purged "
591 "which probably indicates that the publisher and consumer are out of sync.",
592 mChannel->getName().string(), result, ashmemFd);
593 return INVALID_OPERATION;
594 }
595
596 LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d.",
597 mChannel->getName().string(), result, ashmemFd);
598 return UNKNOWN_ERROR;
599 }
600
601 if (mSharedMessage->consumed) {
602 LOGE("channel '%s' consumer ~ The current message has already been consumed.",
603 mChannel->getName().string());
604 return INVALID_OPERATION;
605 }
606
607 // Acquire but *never release* the semaphore. Contention on the semaphore is used to signal
608 // to the publisher that the message has been consumed (or is in the process of being
609 // consumed). Eventually the publisher will reinitialize the semaphore for the next message.
610 result = sem_wait(& mSharedMessage->semaphore);
611 if (result < 0) {
612 LOGE("channel '%s' consumer ~ Error %d in sem_wait.",
613 mChannel->getName().string(), errno);
614 return UNKNOWN_ERROR;
615 }
616
617 mSharedMessage->consumed = true;
618
619 switch (mSharedMessage->type) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700620 case AINPUT_EVENT_TYPE_KEY: {
Jeff Browne839a582010-04-22 18:58:52 -0700621 KeyEvent* keyEvent = factory->createKeyEvent();
622 if (! keyEvent) return NO_MEMORY;
623
624 populateKeyEvent(keyEvent);
625
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700626 *outEvent = keyEvent;
Jeff Browne839a582010-04-22 18:58:52 -0700627 break;
628 }
629
Jeff Brown5c1ed842010-07-14 18:48:53 -0700630 case AINPUT_EVENT_TYPE_MOTION: {
Jeff Browne839a582010-04-22 18:58:52 -0700631 MotionEvent* motionEvent = factory->createMotionEvent();
632 if (! motionEvent) return NO_MEMORY;
633
634 populateMotionEvent(motionEvent);
635
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700636 *outEvent = motionEvent;
Jeff Browne839a582010-04-22 18:58:52 -0700637 break;
638 }
639
640 default:
641 LOGE("channel '%s' consumer ~ Received message of unknown type %d",
642 mChannel->getName().string(), mSharedMessage->type);
643 return UNKNOWN_ERROR;
644 }
645
646 return OK;
647}
648
Jeff Brown81499912010-11-05 15:02:16 -0700649status_t InputConsumer::sendFinishedSignal(bool handled) {
Jeff Browne839a582010-04-22 18:58:52 -0700650#if DEBUG_TRANSPORT_ACTIONS
Jeff Brown81499912010-11-05 15:02:16 -0700651 LOGD("channel '%s' consumer ~ sendFinishedSignal: handled=%d",
652 mChannel->getName().string(), handled);
Jeff Browne839a582010-04-22 18:58:52 -0700653#endif
654
Jeff Brown81499912010-11-05 15:02:16 -0700655 return mChannel->sendSignal(handled
656 ? INPUT_SIGNAL_FINISHED_HANDLED
657 : INPUT_SIGNAL_FINISHED_UNHANDLED);
Jeff Browne839a582010-04-22 18:58:52 -0700658}
659
660status_t InputConsumer::receiveDispatchSignal() {
661#if DEBUG_TRANSPORT_ACTIONS
662 LOGD("channel '%s' consumer ~ receiveDispatchSignal",
663 mChannel->getName().string());
664#endif
665
666 char signal;
667 status_t result = mChannel->receiveSignal(& signal);
668 if (result) {
669 return result;
670 }
671 if (signal != INPUT_SIGNAL_DISPATCH) {
672 LOGE("channel '%s' consumer ~ Received unexpected signal '%c' from publisher",
673 mChannel->getName().string(), signal);
674 return UNKNOWN_ERROR;
675 }
676 return OK;
677}
678
679void InputConsumer::populateKeyEvent(KeyEvent* keyEvent) const {
680 keyEvent->initialize(
681 mSharedMessage->deviceId,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700682 mSharedMessage->source,
Jeff Browne839a582010-04-22 18:58:52 -0700683 mSharedMessage->key.action,
684 mSharedMessage->key.flags,
685 mSharedMessage->key.keyCode,
686 mSharedMessage->key.scanCode,
687 mSharedMessage->key.metaState,
688 mSharedMessage->key.repeatCount,
689 mSharedMessage->key.downTime,
690 mSharedMessage->key.eventTime);
691}
692
693void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
694 motionEvent->initialize(
695 mSharedMessage->deviceId,
Jeff Brown5c1ed842010-07-14 18:48:53 -0700696 mSharedMessage->source,
Jeff Browne839a582010-04-22 18:58:52 -0700697 mSharedMessage->motion.action,
Jeff Brownaf30ff62010-09-01 17:01:00 -0700698 mSharedMessage->motion.flags,
Jeff Browne839a582010-04-22 18:58:52 -0700699 mSharedMessage->motion.edgeFlags,
700 mSharedMessage->motion.metaState,
Jeff Browne959ed22011-05-06 18:20:01 -0700701 mSharedMessage->motion.buttonState,
Jeff Brownf4a4ec22010-06-16 01:53:36 -0700702 mSharedMessage->motion.xOffset,
703 mSharedMessage->motion.yOffset,
Jeff Browne839a582010-04-22 18:58:52 -0700704 mSharedMessage->motion.xPrecision,
705 mSharedMessage->motion.yPrecision,
706 mSharedMessage->motion.downTime,
707 mSharedMessage->motion.sampleData[0].eventTime,
708 mSharedMessage->motion.pointerCount,
Jeff Browne959ed22011-05-06 18:20:01 -0700709 mSharedMessage->motion.pointerProperties,
Jeff Browne839a582010-04-22 18:58:52 -0700710 mSharedMessage->motion.sampleData[0].coords);
711
712 size_t sampleCount = mSharedMessage->motion.sampleCount;
713 if (sampleCount > 1) {
714 InputMessage::SampleData* sampleData = mSharedMessage->motion.sampleData;
715 size_t sampleDataStride = InputMessage::sampleDataStride(
716 mSharedMessage->motion.pointerCount);
717
718 while (--sampleCount > 0) {
719 sampleData = InputMessage::sampleDataPtrIncrement(sampleData, sampleDataStride);
720 motionEvent->addSample(sampleData->eventTime, sampleData->coords);
721 }
722 }
Jeff Browne839a582010-04-22 18:58:52 -0700723}
724
725} // namespace android