diff --git a/init/Android.bp b/init/Android.bp index 63f3fca50..a3083c121 100644 --- a/init/Android.bp +++ b/init/Android.bp @@ -232,6 +232,8 @@ cc_binary { "action_parser.cpp", "capabilities.cpp", "descriptors.cpp", + "epoll.cpp", + "keychords.cpp", "import_parser.cpp", "host_init_parser.cpp", "host_init_stubs.cpp", diff --git a/init/init.cpp b/init/init.cpp index fd9a90cd7..43242b2dc 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -553,6 +553,25 @@ static void InstallSignalFdHandler(Epoll* epoll) { } } +void HandleKeychord(int id) { + // Only handle keychords if adb is enabled. + std::string adb_enabled = android::base::GetProperty("init.svc.adbd", ""); + if (adb_enabled == "running") { + Service* svc = ServiceList::GetInstance().FindService(id, &Service::keychord_id); + if (svc) { + LOG(INFO) << "Starting service '" << svc->name() << "' from keychord " << id; + if (auto result = svc->Start(); !result) { + LOG(ERROR) << "Could not start service '" << svc->name() << "' from keychord " << id + << ": " << result.error(); + } + } else { + LOG(ERROR) << "Service for keychord " << id << " not found"; + } + } else { + LOG(WARNING) << "Not starting service for keychord " << id << " because ADB is disabled"; + } +} + int main(int argc, char** argv) { if (!strcmp(basename(argv[0]), "ueventd")) { return ueventd_main(argc, argv); @@ -732,7 +751,10 @@ int main(int argc, char** argv) { am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict"); am.QueueBuiltinAction( [&epoll](const BuiltinArguments& args) -> Result { - KeychordInit(&epoll); + for (const auto& svc : ServiceList::GetInstance()) { + svc->set_keychord_id(GetKeychordId(svc->keycodes())); + } + KeychordInit(&epoll, HandleKeychord); return Success(); }, "KeychordInit"); diff --git a/init/keychords.cpp b/init/keychords.cpp index 418cdeb22..1a8f2aea3 100644 --- a/init/keychords.cpp +++ b/init/keychords.cpp @@ -33,10 +33,6 @@ #include #include -#include - -#include "init.h" -#include "service.h" namespace android { namespace init { @@ -45,6 +41,7 @@ namespace { int keychords_count; Epoll* epoll; +std::function handle_keychord; struct KeychordEntry { const std::vector keycodes; @@ -124,25 +121,6 @@ constexpr char kDevicePath[] = "/dev/input"; std::map keychord_registration; -void HandleKeychord(int id) { - // Only handle keychords if adb is enabled. - std::string adb_enabled = android::base::GetProperty("init.svc.adbd", ""); - if (adb_enabled == "running") { - Service* svc = ServiceList::GetInstance().FindService(id, &Service::keychord_id); - if (svc) { - LOG(INFO) << "Starting service '" << svc->name() << "' from keychord " << id; - if (auto result = svc->Start(); !result) { - LOG(ERROR) << "Could not start service '" << svc->name() << "' from keychord " << id - << ": " << result.error(); - } - } else { - LOG(ERROR) << "Service for keychord " << id << " not found"; - } - } else { - LOG(WARNING) << "Not starting service for keychord " << id << " because ADB is disabled"; - } -} - void KeychordLambdaCheck() { for (auto& e : keychord_entries) { bool found = true; @@ -156,7 +134,7 @@ void KeychordLambdaCheck() { if (!found) continue; if (e.notified) continue; e.notified = true; - HandleKeychord(e.id); + handle_keychord(e.id); } } @@ -169,12 +147,12 @@ void KeychordLambdaHandler(int fd) { } bool KeychordGeteventEnable(int fd) { - static bool EviocsmaskSupported = true; - // Make sure it is an event channel, should pass this ioctl call int version; if (::ioctl(fd, EVIOCGVERSION, &version)) return false; +#ifdef EVIOCSMASK + static auto EviocsmaskSupported = true; if (EviocsmaskSupported) { KeychordMask mask(EV_KEY); mask.SetBit(EV_KEY); @@ -187,6 +165,7 @@ bool KeychordGeteventEnable(int fd) { EviocsmaskSupported = false; } } +#endif KeychordMask mask; for (auto& e : keychord_entries) { @@ -202,6 +181,7 @@ bool KeychordGeteventEnable(int fd) { if (res == -1) return false; if (!(available & mask)) return false; +#ifdef EVIOCSMASK if (EviocsmaskSupported) { input_mask msg = {}; msg.type = EV_KEY; @@ -209,6 +189,7 @@ bool KeychordGeteventEnable(int fd) { msg.codes_ptr = reinterpret_cast(mask.data()); ::ioctl(fd, EVIOCSMASK, &msg); } +#endif KeychordMask set(mask.size()); res = ::ioctl(fd, EVIOCGKEY(res), set.data()); @@ -299,23 +280,18 @@ void GeteventOpenDevice() { if (inotify_fd >= 0) epoll->RegisterHandler(inotify_fd, InotifyHandler); } -void AddServiceKeycodes(Service* svc) { - if (svc->keycodes().empty()) return; - for (auto& code : svc->keycodes()) { - if ((code < 0) || (code >= KEY_MAX)) return; - } - ++keychords_count; - keychord_entries.emplace_back(KeychordEntry(svc->keycodes(), keychords_count)); - svc->set_keychord_id(keychords_count); -} - } // namespace -void KeychordInit(Epoll* init_epoll) { +int GetKeychordId(const std::vector& keycodes) { + if (keycodes.empty()) return 0; + ++keychords_count; + keychord_entries.emplace_back(KeychordEntry(keycodes, keychords_count)); + return keychords_count; +} + +void KeychordInit(Epoll* init_epoll, std::function handler) { epoll = init_epoll; - for (const auto& service : ServiceList::GetInstance()) { - AddServiceKeycodes(service.get()); - } + handle_keychord = handler; if (keychords_count) GeteventOpenDevice(); } diff --git a/init/keychords.h b/init/keychords.h index f3aecbb56..f273c8c2e 100644 --- a/init/keychords.h +++ b/init/keychords.h @@ -17,12 +17,16 @@ #ifndef _INIT_KEYCHORDS_H_ #define _INIT_KEYCHORDS_H_ +#include +#include + #include "epoll.h" namespace android { namespace init { -void KeychordInit(Epoll* init_epoll); +void KeychordInit(Epoll* init_epoll, std::function handler); +int GetKeychordId(const std::vector& keycodes); } // namespace init } // namespace android diff --git a/init/service.cpp b/init/service.cpp index 0e08d9bba..5778a93b0 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -544,10 +545,13 @@ Result Service::ParseIoprio(const std::vector& args) { Result Service::ParseKeycodes(const std::vector& args) { for (std::size_t i = 1; i < args.size(); i++) { int code; - if (ParseInt(args[i], &code)) { + if (ParseInt(args[i], &code, 0, KEY_MAX)) { + for (auto& key : keycodes_) { + if (key == code) return Error() << "duplicate keycode: " << args[i]; + } keycodes_.emplace_back(code); } else { - LOG(WARNING) << "ignoring invalid keycode: " << args[i]; + return Error() << "invalid keycode: " << args[i]; } } return Success();