Merge "init: Add inotify for /dev/input/"

am: 7ea8047185

Change-Id: Ib1d5308f1964f8a7ea1bab260dae7e1e8dc11317
This commit is contained in:
Mark Salyzyn 2018-05-10 12:55:56 -07:00 committed by android-build-merger
commit 205cf8aefb
1 changed files with 68 additions and 10 deletions

View File

@ -20,12 +20,14 @@
#include <fcntl.h>
#include <linux/input.h>
#include <sys/cdefs.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <algorithm>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <vector>
@ -118,6 +120,8 @@ KeychordMask keychord_current;
constexpr char kDevicePath[] = "/dev/input";
std::map<std::string, int> keychord_registration;
void HandleKeychord(int id) {
// Only handle keychords if adb is enabled.
std::string adb_enabled = android::base::GetProperty("init.svc.adbd", "");
@ -215,6 +219,7 @@ bool KeychordGeteventEnable(int fd) {
}
void GeteventOpenDevice(const std::string& device) {
if (keychord_registration.count(device)) return;
auto fd = TEMP_FAILURE_RETRY(::open(device.c_str(), O_RDWR | O_CLOEXEC));
if (fd == -1) {
PLOG(ERROR) << "Can not open " << device;
@ -222,21 +227,74 @@ void GeteventOpenDevice(const std::string& device) {
}
if (!KeychordGeteventEnable(fd)) {
::close(fd);
} else {
keychord_registration.emplace(device, fd);
}
}
void GeteventCloseDevice(const std::string& device) {
auto it = keychord_registration.find(device);
if (it == keychord_registration.end()) return;
auto fd = (*it).second;
unregister_epoll_handler(fd);
keychord_registration.erase(it);
::close(fd);
}
int inotify_fd = -1;
void InotifyHandler() {
unsigned char buf[512];
auto res = TEMP_FAILURE_RETRY(::read(inotify_fd, buf, sizeof(buf)));
if (res < 0) {
PLOG(WARNING) << "could not get event";
return;
}
auto event_buf = buf;
while (static_cast<size_t>(res) >= sizeof(inotify_event)) {
auto event = reinterpret_cast<inotify_event*>(event_buf);
auto event_size = sizeof(inotify_event) + event->len;
if (static_cast<size_t>(res) < event_size) break;
if (event->len) {
std::string devname(kDevicePath);
devname += '/';
devname += event->name;
if (event->mask & IN_CREATE) {
GeteventOpenDevice(devname);
} else {
GeteventCloseDevice(devname);
}
}
res -= event_size;
event_buf += event_size;
}
}
void GeteventOpenDevice() {
std::unique_ptr<DIR, decltype(&closedir)> device(opendir(kDevicePath), closedir);
if (!device) return;
dirent* entry;
while ((entry = readdir(device.get()))) {
if (entry->d_name[0] == '.') continue;
std::string devname(kDevicePath);
devname += '/';
devname += entry->d_name;
GeteventOpenDevice(devname);
inotify_fd = ::inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
if (inotify_fd < 0) {
PLOG(WARNING) << "Could not instantiate inotify for " << kDevicePath;
} else if (::inotify_add_watch(inotify_fd, kDevicePath, IN_DELETE | IN_CREATE) < 0) {
PLOG(WARNING) << "Could not add watch for " << kDevicePath;
::close(inotify_fd);
inotify_fd = -1;
}
std::unique_ptr<DIR, decltype(&closedir)> device(opendir(kDevicePath), closedir);
if (device) {
dirent* entry;
while ((entry = readdir(device.get()))) {
if (entry->d_name[0] == '.') continue;
std::string devname(kDevicePath);
devname += '/';
devname += entry->d_name;
GeteventOpenDevice(devname);
}
}
if (inotify_fd >= 0) register_epoll_handler(inotify_fd, InotifyHandler);
}
void AddServiceKeycodes(Service* svc) {