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

Commit 334929b5 authored by Tom Cherry's avatar Tom Cherry Committed by Gerrit Code Review
Browse files

Merge changes I7f00c5f0,Idc18f331,I1e7d3a88

* changes:
  init: use Result<T> for the parsing functions
  init: use Result<T> for builtin functions
  init: introduce Result<T> for return values and error handling
parents d467db9b 89bcc85e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -159,6 +159,7 @@ cc_test {
        "devices_test.cpp",
        "init_test.cpp",
        "property_service_test.cpp",
        "result_test.cpp",
        "service_test.cpp",
        "ueventd_test.cpp",
        "util_test.cpp",
+38 −48
Original line number Diff line number Diff line
@@ -31,14 +31,13 @@ namespace init {
Command::Command(BuiltinFunction f, const std::vector<std::string>& args, int line)
    : func_(f), args_(args), line_(line) {}

int Command::InvokeFunc() const {
Result<Success> Command::InvokeFunc() const {
    std::vector<std::string> expanded_args;
    expanded_args.resize(args_.size());
    expanded_args[0] = args_[0];
    for (std::size_t i = 1; i < args_.size(); ++i) {
        if (!expand_props(args_[i], &expanded_args[i])) {
            LOG(ERROR) << args_[0] << ": cannot expand '" << args_[i] << "'";
            return -EINVAL;
            return Error() << "cannot expand '" << args_[i] << "'";
        }
    }

@@ -54,19 +53,16 @@ Action::Action(bool oneshot, const std::string& filename, int line)

const KeywordMap<BuiltinFunction>* Action::function_map_ = nullptr;

bool Action::AddCommand(const std::vector<std::string>& args, int line, std::string* err) {
Result<Success> Action::AddCommand(const std::vector<std::string>& args, int line) {
    if (!function_map_) {
        *err = "no function map available";
        return false;
        return Error() << "no function map available";
    }

    auto function = function_map_->FindFunction(args, err);
    if (!function) {
        return false;
    }
    auto function = function_map_->FindFunction(args);
    if (!function) return Error() << function.error();

    AddCommand(function, args, line);
    return true;
    AddCommand(*function, args, line);
    return Success();
}

void Action::AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line) {
@@ -92,81 +88,74 @@ void Action::ExecuteAllCommands() const {

void Action::ExecuteCommand(const Command& command) const {
    android::base::Timer t;
    int result = command.InvokeFunc();

    auto result = command.InvokeFunc();
    auto duration = t.duration();

    // Any action longer than 50ms will be warned to user as slow operation
    if (duration > 50ms || android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
        std::string trigger_name = BuildTriggersString();
        std::string cmd_str = command.BuildCommandString();

        LOG(INFO) << "Command '" << cmd_str << "' action=" << trigger_name << " (" << filename_
                  << ":" << command.line() << ") returned " << result << " took "
                  << duration.count() << "ms.";
                  << ":" << command.line() << ") took " << duration.count() << "ms and "
                  << (result ? "succeeded" : "failed: " + result.error());
    }
}

bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) {
Result<Success> Action::ParsePropertyTrigger(const std::string& trigger) {
    const static std::string prop_str("property:");
    std::string prop_name(trigger.substr(prop_str.length()));
    size_t equal_pos = prop_name.find('=');
    if (equal_pos == std::string::npos) {
        *err = "property trigger found without matching '='";
        return false;
        return Error() << "property trigger found without matching '='";
    }

    std::string prop_value(prop_name.substr(equal_pos + 1));
    prop_name.erase(equal_pos);

    if (auto [it, inserted] = property_triggers_.emplace(prop_name, prop_value); !inserted) {
        *err = "multiple property triggers found for same property";
        return false;
        return Error() << "multiple property triggers found for same property";
    }
    return true;
    return Success();
}

bool Action::InitTriggers(const std::vector<std::string>& args, std::string* err) {
Result<Success> Action::InitTriggers(const std::vector<std::string>& args) {
    const static std::string prop_str("property:");
    for (std::size_t i = 0; i < args.size(); ++i) {
        if (args[i].empty()) {
            *err = "empty trigger is not valid";
            return false;
            return Error() << "empty trigger is not valid";
        }

        if (i % 2) {
            if (args[i] != "&&") {
                *err = "&& is the only symbol allowed to concatenate actions";
                return false;
                return Error() << "&& is the only symbol allowed to concatenate actions";
            } else {
                continue;
            }
        }

        if (!args[i].compare(0, prop_str.length(), prop_str)) {
            if (!ParsePropertyTrigger(args[i], err)) {
                return false;
            if (auto result = ParsePropertyTrigger(args[i]); !result) {
                return result;
            }
        } else {
            if (!event_trigger_.empty()) {
                *err = "multiple event triggers are not allowed";
                return false;
                return Error() << "multiple event triggers are not allowed";
            }

            event_trigger_ = args[i];
        }
    }

    return true;
    return Success();
}

bool Action::InitSingleTrigger(const std::string& trigger) {
Result<Success> Action::InitSingleTrigger(const std::string& trigger) {
    std::vector<std::string> name_vector{trigger};
    std::string err;
    bool ret = InitTriggers(name_vector, &err);
    if (!ret) {
        LOG(ERROR) << "InitSingleTrigger failed due to: " << err;
    if (auto result = InitTriggers(name_vector); !result) {
        return Error() << "InitTriggers() failed: " << result.error();
    }
    return ret;
    return Success();
}

// This function checks that all property triggers are satisfied, that is
@@ -264,7 +253,8 @@ void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string&
    auto action = std::make_unique<Action>(true, "<Builtin Action>", 0);
    std::vector<std::string> name_vector{name};

    if (!action->InitSingleTrigger(name)) {
    if (auto result = action->InitSingleTrigger(name); !result) {
        LOG(ERROR) << "Cannot queue BuiltinAction for " << name << ": " << result.error();
        return;
    }

@@ -333,25 +323,25 @@ void ActionManager::ClearQueue() {
    current_command_ = 0;
}

bool ActionParser::ParseSection(std::vector<std::string>&& args, const std::string& filename,
                                int line, std::string* err) {
Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args,
                                           const std::string& filename, int line) {
    std::vector<std::string> triggers(args.begin() + 1, args.end());
    if (triggers.size() < 1) {
        *err = "actions must have a trigger";
        return false;
        return Error() << "Actions must have a trigger";
    }

    auto action = std::make_unique<Action>(false, filename, line);
    if (!action->InitTriggers(triggers, err)) {
        return false;

    if (auto result = action->InitTriggers(triggers); !result) {
        return Error() << "InitTriggers() failed: " << result.error();
    }

    action_ = std::move(action);
    return true;
    return Success();
}

bool ActionParser::ParseLineSection(std::vector<std::string>&& args, int line, std::string* err) {
    return action_ ? action_->AddCommand(std::move(args), line, err) : false;
Result<Success> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
    return action_ ? action_->AddCommand(std::move(args), line) : Success();
}

void ActionParser::EndSection() {
+9 −8
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "builtins.h"
#include "keyword_map.h"
#include "parser.h"
#include "result.h"

namespace android {
namespace init {
@@ -34,7 +35,7 @@ class Command {
  public:
    Command(BuiltinFunction f, const std::vector<std::string>& args, int line);

    int InvokeFunc() const;
    Result<Success> InvokeFunc() const;
    std::string BuildCommandString() const;

    int line() const { return line_; }
@@ -53,10 +54,10 @@ class Action {
  public:
    explicit Action(bool oneshot, const std::string& filename, int line);

    bool AddCommand(const std::vector<std::string>& args, int line, std::string* err);
    Result<Success> AddCommand(const std::vector<std::string>& args, int line);
    void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line);
    bool InitTriggers(const std::vector<std::string>& args, std::string* err);
    bool InitSingleTrigger(const std::string& trigger);
    Result<Success> InitTriggers(const std::vector<std::string>& args);
    Result<Success> InitSingleTrigger(const std::string& trigger);
    std::size_t NumCommands() const;
    void ExecuteOneCommand(std::size_t command) const;
    void ExecuteAllCommands() const;
@@ -78,7 +79,7 @@ private:
    void ExecuteCommand(const Command& command) const;
    bool CheckPropertyTriggers(const std::string& name = "",
                               const std::string& value = "") const;
    bool ParsePropertyTrigger(const std::string& trigger, std::string* err);
    Result<Success> ParsePropertyTrigger(const std::string& trigger);

    std::map<std::string, std::string> property_triggers_;
    std::string event_trigger_;
@@ -120,9 +121,9 @@ class ActionParser : public SectionParser {
  public:
    ActionParser(ActionManager* action_manager)
        : action_manager_(action_manager), action_(nullptr) {}
    bool ParseSection(std::vector<std::string>&& args, const std::string& filename, int line,
                      std::string* err) override;
    bool ParseLineSection(std::vector<std::string>&& args, int line, std::string* err) override;
    Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
                                 int line) override;
    Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
    void EndSection() override;

  private:
+24 −24
Original line number Diff line number Diff line
@@ -163,20 +163,20 @@ static void bootchart_thread_main() {
  LOG(INFO) << "Bootcharting finished";
}

static int do_bootchart_start() {
static Result<Success> do_bootchart_start() {
    // We don't care about the content, but we do care that /data/bootchart/enabled actually exists.
    std::string start;
    if (!android::base::ReadFileToString("/data/bootchart/enabled", &start)) {
        LOG(VERBOSE) << "Not bootcharting";
    return 0;
        return Success();
    }

    g_bootcharting_thread = new std::thread(bootchart_thread_main);
  return 0;
    return Success();
}

static int do_bootchart_stop() {
  if (!g_bootcharting_thread) return 0;
static Result<Success> do_bootchart_stop() {
    if (!g_bootcharting_thread) return Success();

    // Tell the worker thread it's time to quit.
    {
@@ -188,10 +188,10 @@ static int do_bootchart_stop() {
    g_bootcharting_thread->join();
    delete g_bootcharting_thread;
    g_bootcharting_thread = nullptr;
  return 0;
    return Success();
}

int do_bootchart(const std::vector<std::string>& args) {
Result<Success> do_bootchart(const std::vector<std::string>& args) {
    if (args[1] == "start") return do_bootchart_start();
    return do_bootchart_stop();
}
+3 −1
Original line number Diff line number Diff line
@@ -20,10 +20,12 @@
#include <string>
#include <vector>

#include "result.h"

namespace android {
namespace init {

int do_bootchart(const std::vector<std::string>& args);
Result<Success> do_bootchart(const std::vector<std::string>& args);

}  // namespace init
}  // namespace android
Loading