Move all Action parsing into ActionParser
Bug: 36970783 Test: Build Change-Id: Iea2d97fb45c3e88bc83fb72d6fa67049be42cfa9
This commit is contained in:
parent
7fd3bc27ec
commit
9cbf57048c
5 changed files with 107 additions and 100 deletions
|
|
@ -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 {
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
@ -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…
Add table
Reference in a new issue