Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eca25076 authored by Mark Salyzyn's avatar Mark Salyzyn
Browse files

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
parent e82401e5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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",
+23 −1
Original line number Diff line number Diff line
@@ -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<Success> {
            KeychordInit(&epoll);
            for (const auto& svc : ServiceList::GetInstance()) {
                svc->set_keychord_id(GetKeychordId(svc->keycodes()));
            }
            KeychordInit(&epoll, HandleKeychord);
            return Success();
        },
        "KeychordInit");
+15 −39
Original line number Diff line number Diff line
@@ -33,10 +33,6 @@
#include <vector>

#include <android-base/logging.h>
#include <android-base/properties.h>

#include "init.h"
#include "service.h"

namespace android {
namespace init {
@@ -45,6 +41,7 @@ namespace {

int keychords_count;
Epoll* epoll;
std::function<void(int)> handle_keychord;

struct KeychordEntry {
    const std::vector<int> keycodes;
@@ -124,25 +121,6 @@ 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", "");
    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<uintptr_t>(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;
    }
}  // namespace

int GetKeychordId(const std::vector<int>& keycodes) {
    if (keycodes.empty()) return 0;
    ++keychords_count;
    keychord_entries.emplace_back(KeychordEntry(svc->keycodes(), keychords_count));
    svc->set_keychord_id(keychords_count);
    keychord_entries.emplace_back(KeychordEntry(keycodes, keychords_count));
    return keychords_count;
}

}  // namespace

void KeychordInit(Epoll* init_epoll) {
void KeychordInit(Epoll* init_epoll, std::function<void(int)> handler) {
    epoll = init_epoll;
    for (const auto& service : ServiceList::GetInstance()) {
        AddServiceKeycodes(service.get());
    }
    handle_keychord = handler;
    if (keychords_count) GeteventOpenDevice();
}

+5 −1
Original line number Diff line number Diff line
@@ -17,12 +17,16 @@
#ifndef _INIT_KEYCHORDS_H_
#define _INIT_KEYCHORDS_H_

#include <functional>
#include <vector>

#include "epoll.h"

namespace android {
namespace init {

void KeychordInit(Epoll* init_epoll);
void KeychordInit(Epoll* init_epoll, std::function<void(int)> handler);
int GetKeychordId(const std::vector<int>& keycodes);

}  // namespace init
}  // namespace android
+6 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <fcntl.h>
#include <inttypes.h>
#include <linux/input.h>
#include <linux/securebits.h>
#include <sched.h>
#include <sys/mount.h>
@@ -544,10 +545,13 @@ Result<Success> Service::ParseIoprio(const std::vector<std::string>& args) {
Result<Success> Service::ParseKeycodes(const std::vector<std::string>& 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();