diff options
| -rw-r--r-- | services/inputflinger/EventHub.cpp | 85 | ||||
| -rw-r--r-- | services/inputflinger/InputReader.cpp | 6 | ||||
| -rw-r--r-- | services/inputflinger/include/EventHub.h | 13 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputReader_test.cpp | 4 |
4 files changed, 97 insertions, 11 deletions
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp index b2d2f14bf3..18c3ded880 100644 --- a/services/inputflinger/EventHub.cpp +++ b/services/inputflinger/EventHub.cpp @@ -220,7 +220,6 @@ bool EventHub::Device::hasValidFd() { // --- EventHub --- -const int EventHub::EPOLL_SIZE_HINT; const int EventHub::EPOLL_MAX_EVENTS; EventHub::EventHub(void) : @@ -762,13 +761,27 @@ EventHub::Device* EventHub::getDeviceByPathLocked(const char* devicePath) const return nullptr; } +/** + * The file descriptor could be either input device, or a video device (associated with a + * specific input device). Check both cases here, and return the device that this event + * belongs to. Caller can compare the fd's once more to determine event type. + * Looks through all input devices, and only attached video devices. Unattached video + * devices are ignored. + */ EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const { for (size_t i = 0; i < mDevices.size(); i++) { Device* device = mDevices.valueAt(i); if (device->fd == fd) { + // This is an input device event + return device; + } + if (device->videoDevice && device->videoDevice->getFd() == fd) { + // This is a video device event return device; } } + // We do not check mUnattachedVideoDevices here because they should not participate in epoll, + // and therefore should never be looked up by fd. return nullptr; } @@ -874,12 +887,33 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz } Device* device = getDeviceByFdLocked(eventItem.data.fd); - if (device == nullptr) { - ALOGW("Received unexpected epoll event 0x%08x for unknown device fd %d.", + if (!device) { + ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.", eventItem.events, eventItem.data.fd); + ALOG_ASSERT(!DEBUG); continue; } - + if (device->videoDevice && eventItem.data.fd == device->videoDevice->getFd()) { + if (eventItem.events & EPOLLIN) { + size_t numFrames = device->videoDevice->readAndQueueFrames(); + if (numFrames == 0) { + ALOGE("Received epoll event for video device %s, but could not read frame", + device->videoDevice->getName().c_str()); + } + } else if (eventItem.events & EPOLLHUP) { + // TODO(b/121395353) - consider adding EPOLLRDHUP + ALOGI("Removing video device %s due to epoll hang-up event.", + device->videoDevice->getName().c_str()); + unregisterVideoDeviceFromEpollLocked(*device->videoDevice); + device->videoDevice = nullptr; + } else { + ALOGW("Received unexpected epoll event 0x%08x for device %s.", + eventItem.events, device->videoDevice->getName().c_str()); + ALOG_ASSERT(!DEBUG); + } + continue; + } + // This must be an input event if (eventItem.events & EPOLLIN) { int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity); @@ -994,6 +1028,16 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz return event - buffer; } +std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) { + AutoMutex _l(mLock); + + Device* device = getDeviceLocked(deviceId); + if (!device || !device->videoDevice) { + return {}; + } + return device->videoDevice->consumeFrames(); +} + void EventHub::wake() { ALOGV("wake() called"); @@ -1044,6 +1088,7 @@ static const int32_t GAMEPAD_KEYCODES[] = { }; status_t EventHub::registerFdForEpoll(int fd) { + // TODO(b/121395353) - consider adding EPOLLRDHUP struct epoll_event eventItem = {}; eventItem.events = EPOLLIN | EPOLLWAKEUP; eventItem.data.fd = fd; @@ -1072,10 +1117,21 @@ status_t EventHub::registerDeviceForEpollLocked(Device* device) { status_t result = registerFdForEpoll(device->fd); if (result != OK) { ALOGE("Could not add input device fd to epoll for device %" PRId32, device->id); + return result; + } + if (device->videoDevice) { + registerVideoDeviceForEpollLocked(*device->videoDevice); } return result; } +void EventHub::registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice) { + status_t result = registerFdForEpoll(videoDevice.getFd()); + if (result != OK) { + ALOGE("Could not add video device %s to epoll", videoDevice.getName().c_str()); + } +} + status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) { if (device->hasValidFd()) { status_t result = unregisterFdFromEpoll(device->fd); @@ -1084,10 +1140,23 @@ status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) { return result; } } + if (device->videoDevice) { + unregisterVideoDeviceFromEpollLocked(*device->videoDevice); + } return OK; } -status_t EventHub::openDeviceLocked(const char *devicePath) { +void EventHub::unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice) { + if (videoDevice.hasValidFd()) { + status_t result = unregisterFdFromEpoll(videoDevice.getFd()); + if (result != OK) { + ALOGW("Could not remove video device fd from epoll for device: %s", + videoDevice.getName().c_str()); + } + } +} + +status_t EventHub::openDeviceLocked(const char* devicePath) { char buffer[80]; ALOGV("Opening device: %s", devicePath); @@ -1345,6 +1414,7 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { } // Find a matching video device by comparing device names + // This should be done before registerDeviceForEpollLocked, so that both fds are added to epoll for (std::unique_ptr<TouchVideoDevice>& videoDevice : mUnattachedVideoDevices) { if (device->identifier.name == videoDevice->getName()) { device->videoDevice = std::move(videoDevice); @@ -1422,6 +1492,9 @@ void EventHub::openVideoDeviceLocked(const std::string& devicePath) { Device* device = mDevices.valueAt(i); if (videoDevice->getName() == device->identifier.name) { device->videoDevice = std::move(videoDevice); + if (device->enabled) { + registerVideoDeviceForEpollLocked(*device->videoDevice); + } return; } } @@ -1632,6 +1705,7 @@ void EventHub::closeVideoDeviceByPathLocked(const std::string& devicePath) { for (size_t i = 0; i < mDevices.size(); i++) { Device* device = mDevices.valueAt(i); if (device->videoDevice && device->videoDevice->getPath() == devicePath) { + unregisterVideoDeviceFromEpollLocked(*device->videoDevice); device->videoDevice = nullptr; return; } @@ -1662,6 +1736,7 @@ void EventHub::closeDeviceLocked(Device* device) { unregisterDeviceFromEpollLocked(device); if (device->videoDevice) { + // This must be done after the video device is removed from epoll mUnattachedVideoDevices.push_back(std::move(device->videoDevice)); } diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index 73fcb1124d..3d5f1d92d5 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -6483,11 +6483,13 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 } } - NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), + const int32_t deviceId = getDeviceId(); + std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId); + NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId, source, mViewport.displayId, policyFlags, action, actionButton, flags, metaState, buttonState, edgeFlags, deviceTimestamp, pointerCount, pointerProperties, pointerCoords, - xPrecision, yPrecision, downTime, /* videoFrames */ {}); + xPrecision, yPrecision, downTime, std::move(frames)); getListener()->notifyMotion(&args); } diff --git a/services/inputflinger/include/EventHub.h b/services/inputflinger/include/EventHub.h index ae70169a09..295aca8955 100644 --- a/services/inputflinger/include/EventHub.h +++ b/services/inputflinger/include/EventHub.h @@ -211,6 +211,7 @@ public: * Returns the number of events obtained, or 0 if the timeout expired. */ virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0; + virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0; /* * Query current input state. @@ -303,6 +304,7 @@ public: const int32_t* keyCodes, uint8_t* outFlags) const; virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize); + virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId); virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const; virtual bool hasLed(int32_t deviceId, int32_t led) const; @@ -381,7 +383,7 @@ private: } }; - status_t openDeviceLocked(const char *devicePath); + status_t openDeviceLocked(const char* devicePath); void openVideoDeviceLocked(const std::string& devicePath); void createVirtualKeyboardLocked(); void addDeviceLocked(Device* device); @@ -400,7 +402,9 @@ private: status_t registerFdForEpoll(int fd); status_t unregisterFdFromEpoll(int fd); status_t registerDeviceForEpollLocked(Device* device); + void registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice); status_t unregisterDeviceFromEpollLocked(Device* device); + void unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice); status_t scanDirLocked(const char *dirname); status_t scanVideoDirLocked(const std::string& dirname); @@ -410,6 +414,10 @@ private: Device* getDeviceByDescriptorLocked(const std::string& descriptor) const; Device* getDeviceLocked(int32_t deviceId) const; Device* getDeviceByPathLocked(const char* devicePath) const; + /** + * Look through all available fd's (both for input devices and for video devices), + * and return the device pointer. + */ Device* getDeviceByFdLocked(int fd) const; bool hasKeycodeLocked(Device* device, int keycode) const; @@ -470,9 +478,6 @@ private: int mInputWd; int mVideoWd; - // Epoll FD list size hint. - static const int EPOLL_SIZE_HINT = 8; - // Maximum number of signalled FDs to handle at a time. static const int EPOLL_MAX_EVENTS = 16; diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index b5d209092a..d39d8dc852 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -692,6 +692,10 @@ private: return 1; } + virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) { + return {}; + } + virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const { Device* device = getDevice(deviceId); if (device) { |