Loading init/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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", Loading init/action.cpp +38 −48 Original line number Diff line number Diff line Loading @@ -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] << "'"; } } Loading @@ -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) { Loading @@ -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 Loading Loading @@ -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; } Loading Loading @@ -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() { Loading init/action.h +9 −8 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "builtins.h" #include "keyword_map.h" #include "parser.h" #include "result.h" namespace android { namespace init { Loading @@ -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_; } Loading @@ -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; Loading @@ -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_; Loading Loading @@ -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: Loading init/bootchart.cpp +24 −24 Original line number Diff line number Diff line Loading @@ -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. { Loading @@ -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(); } Loading init/bootchart.h +3 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
init/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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", Loading
init/action.cpp +38 −48 Original line number Diff line number Diff line Loading @@ -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] << "'"; } } Loading @@ -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) { Loading @@ -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 Loading Loading @@ -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; } Loading Loading @@ -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() { Loading
init/action.h +9 −8 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "builtins.h" #include "keyword_map.h" #include "parser.h" #include "result.h" namespace android { namespace init { Loading @@ -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_; } Loading @@ -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; Loading @@ -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_; Loading Loading @@ -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: Loading
init/bootchart.cpp +24 −24 Original line number Diff line number Diff line Loading @@ -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. { Loading @@ -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(); } Loading
init/bootchart.h +3 −1 Original line number Diff line number Diff line Loading @@ -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