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

Commit 6f5333a4 authored by Steven Moreland's avatar Steven Moreland
Browse files

Allow a service to override another.

For instance, on vendor.img:
service foo /vendor/bin/nfc
    ...

And then on odm.img:
service foo /odm/bin/super-nfc
    override

Allows a service on ODM to override a HAL on vendor.

Bug: 69050941
Test: boot, init_tests
Change-Id: I4e908fb66e89fc6e021799fe1fa6603d3072d62a
parent 5e1bea30
Loading
Loading
Loading
Loading
+34 −6
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@
#include "import_parser.h"
#include "import_parser.h"
#include "keyword_map.h"
#include "keyword_map.h"
#include "parser.h"
#include "parser.h"
#include "service.h"
#include "test_function_map.h"
#include "test_function_map.h"
#include "util.h"
#include "util.h"


@@ -34,12 +35,13 @@ namespace init {
using ActionManagerCommand = std::function<void(ActionManager&)>;
using ActionManagerCommand = std::function<void(ActionManager&)>;


void TestInit(const std::string& init_script_file, const TestFunctionMap& test_function_map,
void TestInit(const std::string& init_script_file, const TestFunctionMap& test_function_map,
              const std::vector<ActionManagerCommand>& commands) {
              const std::vector<ActionManagerCommand>& commands, ServiceList* service_list) {
    ActionManager am;
    ActionManager am;


    Action::set_function_map(&test_function_map);
    Action::set_function_map(&test_function_map);


    Parser parser;
    Parser parser;
    parser.AddSectionParser("service", std::make_unique<ServiceParser>(service_list, nullptr));
    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
    parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
    parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));


@@ -55,11 +57,11 @@ void TestInit(const std::string& init_script_file, const TestFunctionMap& test_f
}
}


void TestInitText(const std::string& init_script, const TestFunctionMap& test_function_map,
void TestInitText(const std::string& init_script, const TestFunctionMap& test_function_map,
                  const std::vector<ActionManagerCommand>& commands) {
                  const std::vector<ActionManagerCommand>& commands, ServiceList* service_list) {
    TemporaryFile tf;
    TemporaryFile tf;
    ASSERT_TRUE(tf.fd != -1);
    ASSERT_TRUE(tf.fd != -1);
    ASSERT_TRUE(android::base::WriteStringToFd(init_script, tf.fd));
    ASSERT_TRUE(android::base::WriteStringToFd(init_script, tf.fd));
    TestInit(tf.path, test_function_map, commands);
    TestInit(tf.path, test_function_map, commands, service_list);
}
}


TEST(init, SimpleEventTrigger) {
TEST(init, SimpleEventTrigger) {
@@ -76,7 +78,8 @@ pass_test
    ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
    ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
    std::vector<ActionManagerCommand> commands{trigger_boot};
    std::vector<ActionManagerCommand> commands{trigger_boot};


    TestInitText(init_script, test_function_map, commands);
    ServiceList service_list;
    TestInitText(init_script, test_function_map, commands, &service_list);


    EXPECT_TRUE(expect_true);
    EXPECT_TRUE(expect_true);
}
}
@@ -104,7 +107,30 @@ execute_third
    ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
    ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
    std::vector<ActionManagerCommand> commands{trigger_boot};
    std::vector<ActionManagerCommand> commands{trigger_boot};


    TestInitText(init_script, test_function_map, commands);
    ServiceList service_list;
    TestInitText(init_script, test_function_map, commands, &service_list);
}

TEST(init, OverrideService) {
    std::string init_script = R"init(
service A something
    class first

service A something
    class second
    override

)init";

    ServiceList service_list;
    TestInitText(init_script, TestFunctionMap(), {}, &service_list);
    ASSERT_EQ(1, std::distance(service_list.begin(), service_list.end()));

    auto service = service_list.begin()->get();
    ASSERT_NE(nullptr, service);
    EXPECT_EQ(std::set<std::string>({"second"}), service->classnames());
    EXPECT_EQ("A", service->name());
    EXPECT_TRUE(service->is_override());
}
}


TEST(init, EventTriggerOrderMultipleFiles) {
TEST(init, EventTriggerOrderMultipleFiles) {
@@ -162,7 +188,9 @@ TEST(init, EventTriggerOrderMultipleFiles) {
    ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
    ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
    std::vector<ActionManagerCommand> commands{trigger_boot};
    std::vector<ActionManagerCommand> commands{trigger_boot};


    TestInit(start.path, test_function_map, commands);
    ServiceList service_list;

    TestInit(start.path, test_function_map, commands, &service_list);


    EXPECT_EQ(6, num_executed);
    EXPECT_EQ(6, num_executed);
}
}
+13 −1
Original line number Original line Diff line number Diff line
@@ -530,6 +530,11 @@ Result<Success> Service::ParseOomScoreAdjust(const std::vector<std::string>& arg
    return Success();
    return Success();
}
}


Result<Success> Service::ParseOverride(const std::vector<std::string>& args) {
    override_ = true;
    return Success();
}

Result<Success> Service::ParseMemcgSwappiness(const std::vector<std::string>& args) {
Result<Success> Service::ParseMemcgSwappiness(const std::vector<std::string>& args) {
    if (!ParseInt(args[1], &swappiness_, 0)) {
    if (!ParseInt(args[1], &swappiness_, 0)) {
        return Error() << "swappiness value must be equal or greater than 0";
        return Error() << "swappiness value must be equal or greater than 0";
@@ -671,6 +676,7 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
        {"keycodes",    {1,     kMax, &Service::ParseKeycodes}},
        {"keycodes",    {1,     kMax, &Service::ParseKeycodes}},
        {"oneshot",     {0,     0,    &Service::ParseOneshot}},
        {"oneshot",     {0,     0,    &Service::ParseOneshot}},
        {"onrestart",   {1,     kMax, &Service::ParseOnrestart}},
        {"onrestart",   {1,     kMax, &Service::ParseOnrestart}},
        {"override",    {0,     0,    &Service::ParseOverride}},
        {"oom_score_adjust",
        {"oom_score_adjust",
                        {1,     1,    &Service::ParseOomScoreAdjust}},
                        {1,     1,    &Service::ParseOomScoreAdjust}},
        {"memcg.swappiness",
        {"memcg.swappiness",
@@ -1134,7 +1140,13 @@ Result<Success> ServiceParser::EndSection() {
    if (service_) {
    if (service_) {
        Service* old_service = service_list_->FindService(service_->name());
        Service* old_service = service_list_->FindService(service_->name());
        if (old_service) {
        if (old_service) {
            return Error() << "ignored duplicate definition of service '" << service_->name() << "'";
            if (!service_->is_override()) {
                return Error() << "ignored duplicate definition of service '" << service_->name()
                               << "'";
            }

            service_list_->RemoveService(*old_service);
            old_service = nullptr;
        }
        }


        service_list_->AddService(std::move(service_));
        service_list_->AddService(std::move(service_));
+4 −0
Original line number Original line Diff line number Diff line
@@ -111,6 +111,7 @@ class Service {
    const std::set<std::string>& interfaces() const { return interfaces_; }
    const std::set<std::string>& interfaces() const { return interfaces_; }
    int priority() const { return priority_; }
    int priority() const { return priority_; }
    int oom_score_adjust() const { return oom_score_adjust_; }
    int oom_score_adjust() const { return oom_score_adjust_; }
    bool is_override() const { return override_; }
    bool process_cgroup_empty() const { return process_cgroup_empty_; }
    bool process_cgroup_empty() const { return process_cgroup_empty_; }
    unsigned long start_order() const { return start_order_; }
    unsigned long start_order() const { return start_order_; }
    const std::vector<std::string>& args() const { return args_; }
    const std::vector<std::string>& args() const { return args_; }
@@ -139,6 +140,7 @@ class Service {
    Result<Success> ParseOneshot(const std::vector<std::string>& args);
    Result<Success> ParseOneshot(const std::vector<std::string>& args);
    Result<Success> ParseOnrestart(const std::vector<std::string>& args);
    Result<Success> ParseOnrestart(const std::vector<std::string>& args);
    Result<Success> ParseOomScoreAdjust(const std::vector<std::string>& args);
    Result<Success> ParseOomScoreAdjust(const std::vector<std::string>& args);
    Result<Success> ParseOverride(const std::vector<std::string>& args);
    Result<Success> ParseMemcgLimitInBytes(const std::vector<std::string>& args);
    Result<Success> ParseMemcgLimitInBytes(const std::vector<std::string>& args);
    Result<Success> ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args);
    Result<Success> ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args);
    Result<Success> ParseMemcgSwappiness(const std::vector<std::string>& args);
    Result<Success> ParseMemcgSwappiness(const std::vector<std::string>& args);
@@ -201,6 +203,8 @@ class Service {


    bool process_cgroup_empty_ = false;
    bool process_cgroup_empty_ = false;


    bool override_ = false;

    unsigned long start_order_;
    unsigned long start_order_;


    std::vector<std::pair<int, rlimit>> rlimits_;
    std::vector<std::pair<int, rlimit>> rlimits_;