Add video device to epoll in EventHub
The video device is already being watched, and we now need to start
actually reading the video frames. This is done similarly to the input
devices. The video device fd is added to epoll. Whenever an epoll
detects new data, the frames will be added to video device's internal
queue. In the subsequent commits we will consume these frames and report
them to the InputClassifier HAL.
Note here that registering for epoll is a bit complex. It is important
to only have the video device in epoll if the input device is in epoll.
There are several situations possible here:
1) Video device is found during directory traversal of /dev
2) Video device is found through inotify
3) Video device is added after matching input device
4) Video device is added before matching input device
5) Video device is added while input device is disabled
6) As long as input device is enabled, and has a video device, the video
device should be part of epoll. That means input device.enable() should
add the video device to epoll.
Therefore, the decision here was made to registerVideoDevice inside
registerDevice (=registerInputDevice), which should account for most
cases. For the other corner cases, handle adding video device to epoll
separately.
Test: video device is being read, because InputClassifier receives video
frames and classifies them.
Bug: 111480215
Change-Id: I340b44a9b17182444b8a3308e3ab322ae1ad444c
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index b2d2f14..aa241a0 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -220,7 +220,6 @@
// --- EventHub ---
-const int EventHub::EPOLL_SIZE_HINT;
const int EventHub::EPOLL_MAX_EVENTS;
EventHub::EventHub(void) :
@@ -762,13 +761,27 @@
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 @@
}
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);
@@ -1044,6 +1078,7 @@
};
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 +1107,21 @@
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 +1130,23 @@
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 +1404,7 @@
}
// 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 +1482,9 @@
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 +1695,7 @@
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 +1726,7 @@
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/include/EventHub.h b/services/inputflinger/include/EventHub.h
index ae70169..dd64132 100644
--- a/services/inputflinger/include/EventHub.h
+++ b/services/inputflinger/include/EventHub.h
@@ -381,7 +381,7 @@
}
};
- 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 +400,9 @@
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 +412,10 @@
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 +476,6 @@
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;