Loading init/action.cpp +9 −83 Original line number Diff line number Diff line Loading @@ -21,11 +21,9 @@ #include <android-base/properties.h> #include <android-base/strings.h> #include "stable_properties.h" #include "util.h" using android::base::Join; using android::base::StartsWith; namespace android { namespace init { Loading Loading @@ -70,8 +68,15 @@ std::string Command::BuildCommandString() const { return Join(args_, ' '); } Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line) : oneshot_(oneshot), subcontext_(subcontext), filename_(filename), line_(line) {} Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line, const std::string& event_trigger, const std::map<std::string, std::string>& property_triggers) : property_triggers_(property_triggers), event_trigger_(event_trigger), oneshot_(oneshot), subcontext_(subcontext), filename_(filename), line_(line) {} const KeywordFunctionMap* Action::function_map_ = nullptr; Loading Loading @@ -135,85 +140,6 @@ void Action::ExecuteCommand(const Command& command) const { } } static bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) { static bool enabled = android::base::GetBoolProperty("ro.actionable_compatible_property.enabled", false); if (subcontext == nullptr || !enabled) { return true; } if (kExportedActionableProperties.count(prop_name) == 1) { return true; } for (const auto& prefix : kPartnerPrefixes) { if (android::base::StartsWith(prop_name, prefix)) { return true; } } return false; } 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) { return Error() << "property trigger found without matching '='"; } std::string prop_value(prop_name.substr(equal_pos + 1)); prop_name.erase(equal_pos); if (!IsActionableProperty(subcontext_, prop_name)) { return Error() << "unexported property tigger found: " << prop_name; } if (auto [it, inserted] = property_triggers_.emplace(prop_name, prop_value); !inserted) { return Error() << "multiple property triggers found for same property"; } return Success(); } 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()) { return Error() << "empty trigger is not valid"; } if (i % 2) { if (args[i] != "&&") { return Error() << "&& is the only symbol allowed to concatenate actions"; } else { continue; } } if (!args[i].compare(0, prop_str.length(), prop_str)) { if (auto result = ParsePropertyTrigger(args[i]); !result) { return result; } } else { if (!event_trigger_.empty()) { return Error() << "multiple event triggers are not allowed"; } event_trigger_ = args[i]; } } return Success(); } Result<Success> Action::InitSingleTrigger(const std::string& trigger) { std::vector<std::string> name_vector{trigger}; if (auto result = InitTriggers(name_vector); !result) { return Error() << "InitTriggers() failed: " << result.error(); } return Success(); } // This function checks that all property triggers are satisfied, that is // for each (name, value) in property_triggers_, check that the current // value of the property 'name' == value. Loading init/action.h +3 −4 Original line number Diff line number Diff line Loading @@ -57,12 +57,12 @@ using BuiltinAction = class Action*; class Action { public: Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line); Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line, const std::string& event_trigger, const std::map<std::string, std::string>& property_triggers); Result<Success> AddCommand(const std::vector<std::string>& args, int line); void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line); 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 @@ -83,7 +83,6 @@ class Action { void ExecuteCommand(const Command& command) const; bool CheckPropertyTriggers(const std::string& name = "", const std::string& value = "") const; Result<Success> ParsePropertyTrigger(const std::string& trigger); std::map<std::string, std::string> property_triggers_; std::string event_trigger_; Loading init/action_manager.cpp +2 −6 Original line number Diff line number Diff line Loading @@ -45,14 +45,10 @@ void ActionManager::QueueAllPropertyActions() { } void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) { auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0); auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name, std::map<std::string, std::string>{}); std::vector<std::string> name_vector{name}; if (auto result = action->InitSingleTrigger(name); !result) { LOG(ERROR) << "Cannot queue BuiltinAction for " << name << ": " << result.error(); return; } action->AddCommand(func, name_vector, 0); event_queue_.emplace(action.get()); Loading init/action_parser.cpp +90 −3 Original line number Diff line number Diff line Loading @@ -16,13 +16,95 @@ #include "action_parser.h" #include <android-base/properties.h> #include <android-base/strings.h> #include "stable_properties.h" using android::base::GetBoolProperty; using android::base::StartsWith; namespace android { namespace init { namespace { bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) { static bool enabled = GetBoolProperty("ro.actionable_compatible_property.enabled", false); if (subcontext == nullptr || !enabled) { return true; } if (kExportedActionableProperties.count(prop_name) == 1) { return true; } for (const auto& prefix : kPartnerPrefixes) { if (android::base::StartsWith(prop_name, prefix)) { return true; } } return false; } Result<Success> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext, std::map<std::string, std::string>* property_triggers) { 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) { return Error() << "property trigger found without matching '='"; } std::string prop_value(prop_name.substr(equal_pos + 1)); prop_name.erase(equal_pos); if (!IsActionableProperty(subcontext, prop_name)) { return Error() << "unexported property tigger found: " << prop_name; } if (auto [it, inserted] = property_triggers->emplace(prop_name, prop_value); !inserted) { return Error() << "multiple property triggers found for same property"; } return Success(); } Result<Success> ParseTriggers(const std::vector<std::string>& args, Subcontext* subcontext, std::string* event_trigger, std::map<std::string, std::string>* property_triggers) { const static std::string prop_str("property:"); for (std::size_t i = 0; i < args.size(); ++i) { if (args[i].empty()) { return Error() << "empty trigger is not valid"; } if (i % 2) { if (args[i] != "&&") { return Error() << "&& is the only symbol allowed to concatenate actions"; } else { continue; } } if (!args[i].compare(0, prop_str.length(), prop_str)) { if (auto result = ParsePropertyTrigger(args[i], subcontext, property_triggers); !result) { return result; } } else { if (!event_trigger->empty()) { return Error() << "multiple event triggers are not allowed"; } *event_trigger = args[i]; } } return Success(); } } // namespace 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()); Loading @@ -40,12 +122,17 @@ Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args, } } auto action = std::make_unique<Action>(false, action_subcontext, filename, line); std::string event_trigger; std::map<std::string, std::string> property_triggers; if (auto result = action->InitTriggers(triggers); !result) { return Error() << "InitTriggers() failed: " << result.error(); if (auto result = ParseTriggers(triggers, action_subcontext, &event_trigger, &property_triggers); !result) { return Error() << "ParseTriggers() failed: " << result.error(); } auto action = std::make_unique<Action>(false, action_subcontext, filename, line, event_trigger, property_triggers); action_ = std::move(action); return Success(); } Loading init/service.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -189,7 +189,8 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid, capabilities_(capabilities), namespace_flags_(namespace_flags), seclabel_(seclabel), onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0), onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0, "onrestart", {}), keychord_id_(0), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), Loading @@ -199,9 +200,7 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid, soft_limit_in_bytes_(-1), limit_in_bytes_(-1), start_order_(0), args_(args) { onrestart_.InitSingleTrigger("onrestart"); } args_(args) {} void Service::NotifyStateChange(const std::string& new_state) const { if ((flags_ & SVC_TEMPORARY) != 0) { Loading Loading
init/action.cpp +9 −83 Original line number Diff line number Diff line Loading @@ -21,11 +21,9 @@ #include <android-base/properties.h> #include <android-base/strings.h> #include "stable_properties.h" #include "util.h" using android::base::Join; using android::base::StartsWith; namespace android { namespace init { Loading Loading @@ -70,8 +68,15 @@ std::string Command::BuildCommandString() const { return Join(args_, ' '); } Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line) : oneshot_(oneshot), subcontext_(subcontext), filename_(filename), line_(line) {} Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line, const std::string& event_trigger, const std::map<std::string, std::string>& property_triggers) : property_triggers_(property_triggers), event_trigger_(event_trigger), oneshot_(oneshot), subcontext_(subcontext), filename_(filename), line_(line) {} const KeywordFunctionMap* Action::function_map_ = nullptr; Loading Loading @@ -135,85 +140,6 @@ void Action::ExecuteCommand(const Command& command) const { } } static bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) { static bool enabled = android::base::GetBoolProperty("ro.actionable_compatible_property.enabled", false); if (subcontext == nullptr || !enabled) { return true; } if (kExportedActionableProperties.count(prop_name) == 1) { return true; } for (const auto& prefix : kPartnerPrefixes) { if (android::base::StartsWith(prop_name, prefix)) { return true; } } return false; } 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) { return Error() << "property trigger found without matching '='"; } std::string prop_value(prop_name.substr(equal_pos + 1)); prop_name.erase(equal_pos); if (!IsActionableProperty(subcontext_, prop_name)) { return Error() << "unexported property tigger found: " << prop_name; } if (auto [it, inserted] = property_triggers_.emplace(prop_name, prop_value); !inserted) { return Error() << "multiple property triggers found for same property"; } return Success(); } 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()) { return Error() << "empty trigger is not valid"; } if (i % 2) { if (args[i] != "&&") { return Error() << "&& is the only symbol allowed to concatenate actions"; } else { continue; } } if (!args[i].compare(0, prop_str.length(), prop_str)) { if (auto result = ParsePropertyTrigger(args[i]); !result) { return result; } } else { if (!event_trigger_.empty()) { return Error() << "multiple event triggers are not allowed"; } event_trigger_ = args[i]; } } return Success(); } Result<Success> Action::InitSingleTrigger(const std::string& trigger) { std::vector<std::string> name_vector{trigger}; if (auto result = InitTriggers(name_vector); !result) { return Error() << "InitTriggers() failed: " << result.error(); } return Success(); } // This function checks that all property triggers are satisfied, that is // for each (name, value) in property_triggers_, check that the current // value of the property 'name' == value. Loading
init/action.h +3 −4 Original line number Diff line number Diff line Loading @@ -57,12 +57,12 @@ using BuiltinAction = class Action*; class Action { public: Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line); Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line, const std::string& event_trigger, const std::map<std::string, std::string>& property_triggers); Result<Success> AddCommand(const std::vector<std::string>& args, int line); void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line); 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 @@ -83,7 +83,6 @@ class Action { void ExecuteCommand(const Command& command) const; bool CheckPropertyTriggers(const std::string& name = "", const std::string& value = "") const; Result<Success> ParsePropertyTrigger(const std::string& trigger); std::map<std::string, std::string> property_triggers_; std::string event_trigger_; Loading
init/action_manager.cpp +2 −6 Original line number Diff line number Diff line Loading @@ -45,14 +45,10 @@ void ActionManager::QueueAllPropertyActions() { } void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) { auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0); auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name, std::map<std::string, std::string>{}); std::vector<std::string> name_vector{name}; if (auto result = action->InitSingleTrigger(name); !result) { LOG(ERROR) << "Cannot queue BuiltinAction for " << name << ": " << result.error(); return; } action->AddCommand(func, name_vector, 0); event_queue_.emplace(action.get()); Loading
init/action_parser.cpp +90 −3 Original line number Diff line number Diff line Loading @@ -16,13 +16,95 @@ #include "action_parser.h" #include <android-base/properties.h> #include <android-base/strings.h> #include "stable_properties.h" using android::base::GetBoolProperty; using android::base::StartsWith; namespace android { namespace init { namespace { bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) { static bool enabled = GetBoolProperty("ro.actionable_compatible_property.enabled", false); if (subcontext == nullptr || !enabled) { return true; } if (kExportedActionableProperties.count(prop_name) == 1) { return true; } for (const auto& prefix : kPartnerPrefixes) { if (android::base::StartsWith(prop_name, prefix)) { return true; } } return false; } Result<Success> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext, std::map<std::string, std::string>* property_triggers) { 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) { return Error() << "property trigger found without matching '='"; } std::string prop_value(prop_name.substr(equal_pos + 1)); prop_name.erase(equal_pos); if (!IsActionableProperty(subcontext, prop_name)) { return Error() << "unexported property tigger found: " << prop_name; } if (auto [it, inserted] = property_triggers->emplace(prop_name, prop_value); !inserted) { return Error() << "multiple property triggers found for same property"; } return Success(); } Result<Success> ParseTriggers(const std::vector<std::string>& args, Subcontext* subcontext, std::string* event_trigger, std::map<std::string, std::string>* property_triggers) { const static std::string prop_str("property:"); for (std::size_t i = 0; i < args.size(); ++i) { if (args[i].empty()) { return Error() << "empty trigger is not valid"; } if (i % 2) { if (args[i] != "&&") { return Error() << "&& is the only symbol allowed to concatenate actions"; } else { continue; } } if (!args[i].compare(0, prop_str.length(), prop_str)) { if (auto result = ParsePropertyTrigger(args[i], subcontext, property_triggers); !result) { return result; } } else { if (!event_trigger->empty()) { return Error() << "multiple event triggers are not allowed"; } *event_trigger = args[i]; } } return Success(); } } // namespace 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()); Loading @@ -40,12 +122,17 @@ Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args, } } auto action = std::make_unique<Action>(false, action_subcontext, filename, line); std::string event_trigger; std::map<std::string, std::string> property_triggers; if (auto result = action->InitTriggers(triggers); !result) { return Error() << "InitTriggers() failed: " << result.error(); if (auto result = ParseTriggers(triggers, action_subcontext, &event_trigger, &property_triggers); !result) { return Error() << "ParseTriggers() failed: " << result.error(); } auto action = std::make_unique<Action>(false, action_subcontext, filename, line, event_trigger, property_triggers); action_ = std::move(action); return Success(); } Loading
init/service.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -189,7 +189,8 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid, capabilities_(capabilities), namespace_flags_(namespace_flags), seclabel_(seclabel), onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0), onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0, "onrestart", {}), keychord_id_(0), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), Loading @@ -199,9 +200,7 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid, soft_limit_in_bytes_(-1), limit_in_bytes_(-1), start_order_(0), args_(args) { onrestart_.InitSingleTrigger("onrestart"); } args_(args) {} void Service::NotifyStateChange(const std::string& new_state) const { if ((flags_ & SVC_TEMPORARY) != 0) { Loading