1// 2// Copyright 2010 The Android Open Source Project 3// 4// Provides a shared memory transport for input events. 5// 6#define LOG_TAG "InputTransport" 7 8//#define LOG_NDEBUG 0 9 10// Log debug messages about channel signalling (send signal, receive signal) 11#define DEBUG_CHANNEL_SIGNALS 0 12 13// Log debug messages whenever InputChannel objects are created/destroyed 14#define DEBUG_CHANNEL_LIFECYCLE 0 15 16// Log debug messages about transport actions (initialize, reset, publish, ...) 17#define DEBUG_TRANSPORT_ACTIONS 0 18 19 20#include <cutils/ashmem.h> 21#include <cutils/log.h> 22#include <errno.h> 23#include <fcntl.h> 24#include <sys/mman.h> 25#include <ui/InputTransport.h> 26#include <unistd.h> 27 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, 73 sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) { 74 status_t result; 75 76 int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE); 77 if (serverAshmemFd < 0) { 78 result = -errno; 79 LOGE("channel '%s' ~ Could not create shared memory region. errno=%d", 80 name.string(), errno); 81 } else { 82 result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE); 83 if (result < 0) { 84 LOGE("channel '%s' ~ Error %d trying to set protection of ashmem fd %d.", 85 name.string(), result, serverAshmemFd); 86 } else { 87 // Dup the file descriptor because the server and client input channel objects that 88 // are returned may have different lifetimes but they share the same shared memory region. 89 int clientAshmemFd; 90 clientAshmemFd = dup(serverAshmemFd); 91 if (clientAshmemFd < 0) { 92 result = -errno; 93 LOGE("channel '%s' ~ Could not dup() shared memory region fd. errno=%d", 94 name.string(), errno); 95 } else { 96 int forward[2]; 97 if (pipe(forward)) { 98 result = -errno; 99 LOGE("channel '%s' ~ Could not create forward pipe. errno=%d", 100 name.string(), errno); 101 } else { 102 int reverse[2]; 103 if (pipe(reverse)) { 104 result = -errno; 105 LOGE("channel '%s' ~ Could not create reverse pipe. errno=%d", 106 name.string(), errno); 107 } else { 108 String8 serverChannelName = name; 109 serverChannelName.append(" (server)"); 110 outServerChannel = new InputChannel(serverChannelName, 111 serverAshmemFd, reverse[0], forward[1]); 112 113 String8 clientChannelName = name; 114 clientChannelName.append(" (client)"); 115 outClientChannel = new InputChannel(clientChannelName, 116 clientAshmemFd, forward[0], reverse[1]); 117 return OK; 118 } 119 ::close(forward[0]); 120 ::close(forward[1]); 121 } 122 ::close(clientAshmemFd); 123 } 124 } 125 ::close(serverAshmemFd); 126 } 127 128 outServerChannel.clear(); 129 outClientChannel.clear(); 130 return result; 131} 132 133status_t InputChannel::sendSignal(char signal) { 134 ssize_t nWrite; 135 do { 136 nWrite = ::write(mSendPipeFd, & signal, 1); 137 } while (nWrite == -1 && errno == EINTR); 138 139 if (nWrite == 1) { 140#if DEBUG_CHANNEL_SIGNALS 141 LOGD("channel '%s' ~ sent signal '%c'", mName.string(), signal); 142#endif 143 return OK; 144 } 145 146#if DEBUG_CHANNEL_SIGNALS 147 LOGD("channel '%s' ~ error sending signal '%c', errno=%d", mName.string(), signal, errno); 148#endif 149 return -errno; 150} 151 152status_t InputChannel::receiveSignal(char* outSignal) { 153 ssize_t nRead; 154 do { 155 nRead = ::read(mReceivePipeFd, outSignal, 1); 156 } while (nRead == -1 && errno == EINTR); 157 158 if (nRead == 1) { 159#if DEBUG_CHANNEL_SIGNALS 160 LOGD("channel '%s' ~ received signal '%c'", mName.string(), *outSignal); 161#endif 162 return OK; 163 } 164 165 if (nRead == 0) { // check for EOF 166#if DEBUG_CHANNEL_SIGNALS 167 LOGD("channel '%s' ~ receive signal failed because peer was closed", mName.string()); 168#endif 169 return DEAD_OBJECT; 170 } 171 172 if (errno == EAGAIN) { 173#if DEBUG_CHANNEL_SIGNALS 174 LOGD("channel '%s' ~ receive signal failed because no signal available", mName.string()); 175#endif 176 return WOULD_BLOCK; 177 } 178 179#if DEBUG_CHANNEL_SIGNALS 180 LOGD("channel '%s' ~ receive signal failed, errno=%d", mName.string(), errno); 181#endif 182 return -errno; 183} 184 185 186// --- InputPublisher --- 187 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, 280 int32_t source) { 281 if (mPinned) { 282 LOGE("channel '%s' publisher ~ Attempted to publish a new event but publisher has " 283 "not yet been reset.", mChannel->getName().string()); 284 return INVALID_OPERATION; 285 } 286 287 // Pin the region. 288 // We do not check for ASHMEM_NOT_PURGED because we don't care about the previous 289 // contents of the buffer so it does not matter whether it was purged in the meantime. 290 int ashmemFd = mChannel->getAshmemFd(); 291 int result = ashmem_pin_region(ashmemFd, 0, 0); 292 if (result < 0) { 293 LOGE("channel '%s' publisher ~ Error %d pinning ashmem fd %d.", 294 mChannel->getName().string(), result, ashmemFd); 295 return UNKNOWN_ERROR; 296 } 297 298 mPinned = true; 299 300 result = sem_init(& mSharedMessage->semaphore, 1, 1); 301 if (result < 0) { 302 LOGE("channel '%s' publisher ~ Error %d in sem_init.", 303 mChannel->getName().string(), errno); 304 return UNKNOWN_ERROR; 305 } 306 307 mSemaphoreInitialized = true; 308 309 mSharedMessage->consumed = false; 310 mSharedMessage->type = type; 311 mSharedMessage->deviceId = deviceId; 312 mSharedMessage->source = source; 313 return OK; 314} 315 316status_t InputPublisher::publishKeyEvent( 317 int32_t deviceId, 318 int32_t source, 319 int32_t action, 320 int32_t flags, 321 int32_t keyCode, 322 int32_t scanCode, 323 int32_t metaState, 324 int32_t repeatCount, 325 nsecs_t downTime, 326 nsecs_t eventTime) { 327#if DEBUG_TRANSPORT_ACTIONS 328 LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=0x%x, " 329 "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d," 330 "downTime=%lld, eventTime=%lld", 331 mChannel->getName().string(), 332 deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount, 333 downTime, eventTime); 334#endif 335 336 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_KEY, deviceId, source); 337 if (result < 0) { 338 return result; 339 } 340 341 mSharedMessage->key.action = action; 342 mSharedMessage->key.flags = flags; 343 mSharedMessage->key.keyCode = keyCode; 344 mSharedMessage->key.scanCode = scanCode; 345 mSharedMessage->key.metaState = metaState; 346 mSharedMessage->key.repeatCount = repeatCount; 347 mSharedMessage->key.downTime = downTime; 348 mSharedMessage->key.eventTime = eventTime; 349 return OK; 350} 351 352status_t InputPublisher::publishMotionEvent( 353 int32_t deviceId, 354 int32_t source, 355 int32_t action, 356 int32_t flags, 357 int32_t edgeFlags, 358 int32_t metaState, 359 float xOffset, 360 float yOffset, 361 float xPrecision, 362 float yPrecision, 363 nsecs_t downTime, 364 nsecs_t eventTime, 365 size_t pointerCount, 366 const int32_t* pointerIds, 367 const PointerCoords* pointerCoords) { 368#if DEBUG_TRANSPORT_ACTIONS 369 LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, " 370 "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, xOffset=%f, yOffset=%f, " 371 "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, " 372 "pointerCount=%d", 373 mChannel->getName().string(), 374 deviceId, source, action, flags, edgeFlags, metaState, xOffset, yOffset, 375 xPrecision, yPrecision, downTime, eventTime, pointerCount); 376#endif 377 378 if (pointerCount > MAX_POINTERS || pointerCount < 1) { 379 LOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.", 380 mChannel->getName().string(), pointerCount); 381 return BAD_VALUE; 382 } 383 384 status_t result = publishInputEvent(AINPUT_EVENT_TYPE_MOTION, deviceId, source); 385 if (result < 0) { 386 return result; 387 } 388 389 mSharedMessage->motion.action = action; 390 mSharedMessage->motion.flags = flags; 391 mSharedMessage->motion.edgeFlags = edgeFlags; 392 mSharedMessage->motion.metaState = metaState; 393 mSharedMessage->motion.xOffset = xOffset; 394 mSharedMessage->motion.yOffset = yOffset; 395 mSharedMessage->motion.xPrecision = xPrecision; 396 mSharedMessage->motion.yPrecision = yPrecision; 397 mSharedMessage->motion.downTime = downTime; 398 mSharedMessage->motion.pointerCount = pointerCount; 399 400 mSharedMessage->motion.sampleCount = 1; 401 mSharedMessage->motion.sampleData[0].eventTime = eventTime; 402 403 for (size_t i = 0; i < pointerCount; i++) { 404 mSharedMessage->motion.pointerIds[i] = pointerIds[i]; 405 mSharedMessage->motion.sampleData[0].coords[i] = pointerCoords[i]; 406 } 407 408 // Cache essential information about the motion event to ensure that a malicious consumer 409 // cannot confuse the publisher by modifying the contents of the shared memory buffer while 410 // it is being updated. 411 if (action == AMOTION_EVENT_ACTION_MOVE) { 412 mMotionEventPointerCount = pointerCount; 413 mMotionEventSampleDataStride = InputMessage::sampleDataStride(pointerCount); 414 mMotionEventSampleDataTail = InputMessage::sampleDataPtrIncrement( 415 mSharedMessage->motion.sampleData, mMotionEventSampleDataStride); 416 } else { 417 mMotionEventSampleDataTail = NULL; 418 } 419 return OK; 420} 421 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 " 432 "AMOTION_EVENT_ACTION_MOVE event.", mChannel->getName().string()); 433 return INVALID_OPERATION; 434 } 435 436 InputMessage::SampleData* newTail = InputMessage::sampleDataPtrIncrement( 437 mMotionEventSampleDataTail, mMotionEventSampleDataStride); 438 size_t newBytesUsed = reinterpret_cast<char*>(newTail) - 439 reinterpret_cast<char*>(mSharedMessage); 440 441 if (newBytesUsed > mAshmemSize) { 442#if DEBUG_TRANSPORT_ACTIONS 443 LOGD("channel '%s' publisher ~ Cannot append motion sample because the shared memory " 444 "buffer is full. Buffer size: %d bytes, pointers: %d, samples: %d", 445 mChannel->getName().string(), 446 mAshmemSize, mMotionEventPointerCount, mSharedMessage->motion.sampleCount); 447#endif 448 return NO_MEMORY; 449 } 450 451 int result; 452 if (mWasDispatched) { 453 result = sem_trywait(& mSharedMessage->semaphore); 454 if (result < 0) { 455 if (errno == EAGAIN) { 456 // Only possible source of contention is the consumer having consumed (or being in the 457 // process of consuming) the message and left the semaphore count at 0. 458#if DEBUG_TRANSPORT_ACTIONS 459 LOGD("channel '%s' publisher ~ Cannot append motion sample because the message has " 460 "already been consumed.", mChannel->getName().string()); 461#endif 462 return FAILED_TRANSACTION; 463 } else { 464 LOGE("channel '%s' publisher ~ Error %d in sem_trywait.", 465 mChannel->getName().string(), errno); 466 return UNKNOWN_ERROR; 467 } 468 } 469 } 470 471 mMotionEventSampleDataTail->eventTime = eventTime; 472 for (size_t i = 0; i < mMotionEventPointerCount; i++) { 473 mMotionEventSampleDataTail->coords[i] = pointerCoords[i]; 474 } 475 mMotionEventSampleDataTail = newTail; 476 477 mSharedMessage->motion.sampleCount += 1; 478 479 if (mWasDispatched) { 480 result = sem_post(& mSharedMessage->semaphore); 481 if (result < 0) { 482 LOGE("channel '%s' publisher ~ Error %d in sem_post.", 483 mChannel->getName().string(), errno); 484 return UNKNOWN_ERROR; 485 } 486 } 487 return OK; 488} 489 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 558status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent** outEvent) { 559#if DEBUG_TRANSPORT_ACTIONS 560 LOGD("channel '%s' consumer ~ consume", 561 mChannel->getName().string()); 562#endif 563 564 *outEvent = NULL; 565 566 int ashmemFd = mChannel->getAshmemFd(); 567 int result = ashmem_pin_region(ashmemFd, 0, 0); 568 if (result != ASHMEM_NOT_PURGED) { 569 if (result == ASHMEM_WAS_PURGED) { 570 LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d because it was purged " 571 "which probably indicates that the publisher and consumer are out of sync.", 572 mChannel->getName().string(), result, ashmemFd); 573 return INVALID_OPERATION; 574 } 575 576 LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d.", 577 mChannel->getName().string(), result, ashmemFd); 578 return UNKNOWN_ERROR; 579 } 580 581 if (mSharedMessage->consumed) { 582 LOGE("channel '%s' consumer ~ The current message has already been consumed.", 583 mChannel->getName().string()); 584 return INVALID_OPERATION; 585 } 586 587 // Acquire but *never release* the semaphore. Contention on the semaphore is used to signal 588 // to the publisher that the message has been consumed (or is in the process of being 589 // consumed). Eventually the publisher will reinitialize the semaphore for the next message. 590 result = sem_wait(& mSharedMessage->semaphore); 591 if (result < 0) { 592 LOGE("channel '%s' consumer ~ Error %d in sem_wait.", 593 mChannel->getName().string(), errno); 594 return UNKNOWN_ERROR; 595 } 596 597 mSharedMessage->consumed = true; 598 599 switch (mSharedMessage->type) { 600 case AINPUT_EVENT_TYPE_KEY: { 601 KeyEvent* keyEvent = factory->createKeyEvent(); 602 if (! keyEvent) return NO_MEMORY; 603 604 populateKeyEvent(keyEvent); 605 606 *outEvent = keyEvent; 607 break; 608 } 609 610 case AINPUT_EVENT_TYPE_MOTION: { 611 MotionEvent* motionEvent = factory->createMotionEvent(); 612 if (! motionEvent) return NO_MEMORY; 613 614 populateMotionEvent(motionEvent); 615 616 *outEvent = motionEvent; 617 break; 618 } 619 620 default: 621 LOGE("channel '%s' consumer ~ Received message of unknown type %d", 622 mChannel->getName().string(), mSharedMessage->type); 623 return UNKNOWN_ERROR; 624 } 625 626 return OK; 627} 628 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, 660 mSharedMessage->source, 661 mSharedMessage->key.action, 662 mSharedMessage->key.flags, 663 mSharedMessage->key.keyCode, 664 mSharedMessage->key.scanCode, 665 mSharedMessage->key.metaState, 666 mSharedMessage->key.repeatCount, 667 mSharedMessage->key.downTime, 668 mSharedMessage->key.eventTime); 669} 670 671void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const { 672 motionEvent->initialize( 673 mSharedMessage->deviceId, 674 mSharedMessage->source, 675 mSharedMessage->motion.action, 676 mSharedMessage->motion.flags, 677 mSharedMessage->motion.edgeFlags, 678 mSharedMessage->motion.metaState, 679 mSharedMessage->motion.xOffset, 680 mSharedMessage->motion.yOffset, 681 mSharedMessage->motion.xPrecision, 682 mSharedMessage->motion.yPrecision, 683 mSharedMessage->motion.downTime, 684 mSharedMessage->motion.sampleData[0].eventTime, 685 mSharedMessage->motion.pointerCount, 686 mSharedMessage->motion.pointerIds, 687 mSharedMessage->motion.sampleData[0].coords); 688 689 size_t sampleCount = mSharedMessage->motion.sampleCount; 690 if (sampleCount > 1) { 691 InputMessage::SampleData* sampleData = mSharedMessage->motion.sampleData; 692 size_t sampleDataStride = InputMessage::sampleDataStride( 693 mSharedMessage->motion.pointerCount); 694 695 while (--sampleCount > 0) { 696 sampleData = InputMessage::sampleDataPtrIncrement(sampleData, sampleDataStride); 697 motionEvent->addSample(sampleData->eventTime, sampleData->coords); 698 } 699 } 700} 701 702} // namespace android 703