From eca25076343945f901c7f631aad5e915c14c1a56 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Wed, 16 May 2018 15:10:24 -0700 Subject: [PATCH] init: refactor keychord for testing Move things around so that keychords.cpp is independent of service and init and can be individually tested with few dependencies. Permits also rolling out the keychords as a class in a future commit. Improve parser checking. Test: init_tests Bug: 64114943 Change-Id: I82570bc6269ed478db784ec38a8bc916da2be2be --- init/Android.bp | 2 ++ init/init.cpp | 24 +++++++++++++++++++- init/keychords.cpp | 56 +++++++++++++--------------------------------- init/keychords.h | 6 ++++- init/service.cpp | 8 +++++-- 5 files changed, 52 insertions(+), 44 deletions(-) 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();