Merge changes Iea2d97fb,I08fa3905,Idd5b923e
* changes: Move all Action parsing into ActionParser Move ActionManager to its own file Move ActionParser to its own file
This commit is contained in:
commit
e1ae2ff9e4
|
@ -93,6 +93,8 @@ cc_library_static {
|
|||
defaults: ["init_defaults"],
|
||||
srcs: [
|
||||
"action.cpp",
|
||||
"action_manager.cpp",
|
||||
"action_parser.cpp",
|
||||
"bootchart.cpp",
|
||||
"builtins.cpp",
|
||||
"capabilities.cpp",
|
||||
|
|
229
init/action.cpp
229
init/action.cpp
|
@ -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.
|
||||
|
@ -281,142 +207,5 @@ void Action::DumpState() const {
|
|||
}
|
||||
}
|
||||
|
||||
ActionManager::ActionManager() : current_command_(0) {
|
||||
}
|
||||
|
||||
ActionManager& ActionManager::GetInstance() {
|
||||
static ActionManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ActionManager::AddAction(std::unique_ptr<Action> action) {
|
||||
actions_.emplace_back(std::move(action));
|
||||
}
|
||||
|
||||
void ActionManager::QueueEventTrigger(const std::string& trigger) {
|
||||
event_queue_.emplace(trigger);
|
||||
}
|
||||
|
||||
void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
|
||||
event_queue_.emplace(std::make_pair(name, value));
|
||||
}
|
||||
|
||||
void ActionManager::QueueAllPropertyActions() {
|
||||
QueuePropertyChange("", "");
|
||||
}
|
||||
|
||||
void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
|
||||
auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0);
|
||||
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());
|
||||
actions_.emplace_back(std::move(action));
|
||||
}
|
||||
|
||||
void ActionManager::ExecuteOneCommand() {
|
||||
// Loop through the event queue until we have an action to execute
|
||||
while (current_executing_actions_.empty() && !event_queue_.empty()) {
|
||||
for (const auto& action : actions_) {
|
||||
if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
|
||||
event_queue_.front())) {
|
||||
current_executing_actions_.emplace(action.get());
|
||||
}
|
||||
}
|
||||
event_queue_.pop();
|
||||
}
|
||||
|
||||
if (current_executing_actions_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto action = current_executing_actions_.front();
|
||||
|
||||
if (current_command_ == 0) {
|
||||
std::string trigger_name = action->BuildTriggersString();
|
||||
LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
|
||||
<< ":" << action->line() << ")";
|
||||
}
|
||||
|
||||
action->ExecuteOneCommand(current_command_);
|
||||
|
||||
// If this was the last command in the current action, then remove
|
||||
// the action from the executing list.
|
||||
// If this action was oneshot, then also remove it from actions_.
|
||||
++current_command_;
|
||||
if (current_command_ == action->NumCommands()) {
|
||||
current_executing_actions_.pop();
|
||||
current_command_ = 0;
|
||||
if (action->oneshot()) {
|
||||
auto eraser = [&action] (std::unique_ptr<Action>& a) {
|
||||
return a.get() == action;
|
||||
};
|
||||
actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ActionManager::HasMoreCommands() const {
|
||||
return !current_executing_actions_.empty() || !event_queue_.empty();
|
||||
}
|
||||
|
||||
void ActionManager::DumpState() const {
|
||||
for (const auto& a : actions_) {
|
||||
a->DumpState();
|
||||
}
|
||||
}
|
||||
|
||||
void ActionManager::ClearQueue() {
|
||||
// We are shutting down so don't claim the oneshot builtin actions back
|
||||
current_executing_actions_ = {};
|
||||
event_queue_ = {};
|
||||
current_command_ = 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
return Error() << "Actions must have a trigger";
|
||||
}
|
||||
|
||||
Subcontext* action_subcontext = nullptr;
|
||||
if (subcontexts_) {
|
||||
for (auto& subcontext : *subcontexts_) {
|
||||
if (StartsWith(filename, subcontext.path_prefix())) {
|
||||
action_subcontext = &subcontext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto action = std::make_unique<Action>(false, action_subcontext, filename, line);
|
||||
|
||||
if (auto result = action->InitTriggers(triggers); !result) {
|
||||
return Error() << "InitTriggers() failed: " << result.error();
|
||||
}
|
||||
|
||||
action_ = std::move(action);
|
||||
return Success();
|
||||
}
|
||||
|
||||
Result<Success> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
|
||||
return action_ ? action_->AddCommand(std::move(args), line) : Success();
|
||||
}
|
||||
|
||||
Result<Success> ActionParser::EndSection() {
|
||||
if (action_ && action_->NumCommands() > 0) {
|
||||
action_manager_->AddAction(std::move(action_));
|
||||
}
|
||||
|
||||
return Success();
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "builtins.h"
|
||||
#include "keyword_map.h"
|
||||
#include "parser.h"
|
||||
#include "result.h"
|
||||
#include "subcontext.h"
|
||||
|
||||
|
@ -58,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;
|
||||
|
@ -84,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_;
|
||||
|
@ -96,48 +94,6 @@ class Action {
|
|||
static const KeywordFunctionMap* function_map_;
|
||||
};
|
||||
|
||||
class ActionManager {
|
||||
public:
|
||||
static ActionManager& GetInstance();
|
||||
|
||||
// Exposed for testing
|
||||
ActionManager();
|
||||
|
||||
void AddAction(std::unique_ptr<Action> action);
|
||||
void QueueEventTrigger(const std::string& trigger);
|
||||
void QueuePropertyChange(const std::string& name, const std::string& value);
|
||||
void QueueAllPropertyActions();
|
||||
void QueueBuiltinAction(BuiltinFunction func, const std::string& name);
|
||||
void ExecuteOneCommand();
|
||||
bool HasMoreCommands() const;
|
||||
void DumpState() const;
|
||||
void ClearQueue();
|
||||
|
||||
private:
|
||||
ActionManager(ActionManager const&) = delete;
|
||||
void operator=(ActionManager const&) = delete;
|
||||
|
||||
std::vector<std::unique_ptr<Action>> actions_;
|
||||
std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_;
|
||||
std::queue<const Action*> current_executing_actions_;
|
||||
std::size_t current_command_;
|
||||
};
|
||||
|
||||
class ActionParser : public SectionParser {
|
||||
public:
|
||||
ActionParser(ActionManager* action_manager, std::vector<Subcontext>* subcontexts)
|
||||
: action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {}
|
||||
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;
|
||||
Result<Success> EndSection() override;
|
||||
|
||||
private:
|
||||
ActionManager* action_manager_;
|
||||
std::vector<Subcontext>* subcontexts_;
|
||||
std::unique_ptr<Action> action_;
|
||||
};
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "action_manager.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
ActionManager::ActionManager() : current_command_(0) {}
|
||||
|
||||
ActionManager& ActionManager::GetInstance() {
|
||||
static ActionManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ActionManager::AddAction(std::unique_ptr<Action> action) {
|
||||
actions_.emplace_back(std::move(action));
|
||||
}
|
||||
|
||||
void ActionManager::QueueEventTrigger(const std::string& trigger) {
|
||||
event_queue_.emplace(trigger);
|
||||
}
|
||||
|
||||
void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
|
||||
event_queue_.emplace(std::make_pair(name, value));
|
||||
}
|
||||
|
||||
void ActionManager::QueueAllPropertyActions() {
|
||||
QueuePropertyChange("", "");
|
||||
}
|
||||
|
||||
void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
|
||||
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};
|
||||
|
||||
action->AddCommand(func, name_vector, 0);
|
||||
|
||||
event_queue_.emplace(action.get());
|
||||
actions_.emplace_back(std::move(action));
|
||||
}
|
||||
|
||||
void ActionManager::ExecuteOneCommand() {
|
||||
// Loop through the event queue until we have an action to execute
|
||||
while (current_executing_actions_.empty() && !event_queue_.empty()) {
|
||||
for (const auto& action : actions_) {
|
||||
if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
|
||||
event_queue_.front())) {
|
||||
current_executing_actions_.emplace(action.get());
|
||||
}
|
||||
}
|
||||
event_queue_.pop();
|
||||
}
|
||||
|
||||
if (current_executing_actions_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto action = current_executing_actions_.front();
|
||||
|
||||
if (current_command_ == 0) {
|
||||
std::string trigger_name = action->BuildTriggersString();
|
||||
LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
|
||||
<< ":" << action->line() << ")";
|
||||
}
|
||||
|
||||
action->ExecuteOneCommand(current_command_);
|
||||
|
||||
// If this was the last command in the current action, then remove
|
||||
// the action from the executing list.
|
||||
// If this action was oneshot, then also remove it from actions_.
|
||||
++current_command_;
|
||||
if (current_command_ == action->NumCommands()) {
|
||||
current_executing_actions_.pop();
|
||||
current_command_ = 0;
|
||||
if (action->oneshot()) {
|
||||
auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; };
|
||||
actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ActionManager::HasMoreCommands() const {
|
||||
return !current_executing_actions_.empty() || !event_queue_.empty();
|
||||
}
|
||||
|
||||
void ActionManager::DumpState() const {
|
||||
for (const auto& a : actions_) {
|
||||
a->DumpState();
|
||||
}
|
||||
}
|
||||
|
||||
void ActionManager::ClearQueue() {
|
||||
// We are shutting down so don't claim the oneshot builtin actions back
|
||||
current_executing_actions_ = {};
|
||||
event_queue_ = {};
|
||||
current_command_ = 0;
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _INIT_ACTION_MANAGER_H
|
||||
#define _INIT_ACTION_MANAGER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "action.h"
|
||||
#include "builtins.h"
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
class ActionManager {
|
||||
public:
|
||||
static ActionManager& GetInstance();
|
||||
|
||||
// Exposed for testing
|
||||
ActionManager();
|
||||
|
||||
void AddAction(std::unique_ptr<Action> action);
|
||||
void QueueEventTrigger(const std::string& trigger);
|
||||
void QueuePropertyChange(const std::string& name, const std::string& value);
|
||||
void QueueAllPropertyActions();
|
||||
void QueueBuiltinAction(BuiltinFunction func, const std::string& name);
|
||||
void ExecuteOneCommand();
|
||||
bool HasMoreCommands() const;
|
||||
void DumpState() const;
|
||||
void ClearQueue();
|
||||
|
||||
private:
|
||||
ActionManager(ActionManager const&) = delete;
|
||||
void operator=(ActionManager const&) = delete;
|
||||
|
||||
std::vector<std::unique_ptr<Action>> actions_;
|
||||
std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_;
|
||||
std::queue<const Action*> current_executing_actions_;
|
||||
std::size_t current_command_;
|
||||
};
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
||||
#endif
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#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());
|
||||
if (triggers.size() < 1) {
|
||||
return Error() << "Actions must have a trigger";
|
||||
}
|
||||
|
||||
Subcontext* action_subcontext = nullptr;
|
||||
if (subcontexts_) {
|
||||
for (auto& subcontext : *subcontexts_) {
|
||||
if (StartsWith(filename, subcontext.path_prefix())) {
|
||||
action_subcontext = &subcontext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string event_trigger;
|
||||
std::map<std::string, std::string> property_triggers;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
Result<Success> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
|
||||
return action_ ? action_->AddCommand(std::move(args), line) : Success();
|
||||
}
|
||||
|
||||
Result<Success> ActionParser::EndSection() {
|
||||
if (action_ && action_->NumCommands() > 0) {
|
||||
action_manager_->AddAction(std::move(action_));
|
||||
}
|
||||
|
||||
return Success();
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _INIT_ACTION_PARSER_H
|
||||
#define _INIT_ACTION_PARSER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "action.h"
|
||||
#include "action_manager.h"
|
||||
#include "parser.h"
|
||||
#include "subcontext.h"
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
class ActionParser : public SectionParser {
|
||||
public:
|
||||
ActionParser(ActionManager* action_manager, std::vector<Subcontext>* subcontexts)
|
||||
: action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {}
|
||||
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;
|
||||
Result<Success> EndSection() override;
|
||||
|
||||
private:
|
||||
ActionManager* action_manager_;
|
||||
std::vector<Subcontext>* subcontexts_;
|
||||
std::unique_ptr<Action> action_;
|
||||
};
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
||||
#endif
|
|
@ -58,7 +58,7 @@
|
|||
#include <selinux/selinux.h>
|
||||
#include <system/thread_defs.h>
|
||||
|
||||
#include "action.h"
|
||||
#include "action_manager.h"
|
||||
#include "bootchart.h"
|
||||
#include "init.h"
|
||||
#include "parser.h"
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "action_parser.h"
|
||||
#include "import_parser.h"
|
||||
#include "init_first_stage.h"
|
||||
#include "keychords.h"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "action.h"
|
||||
#include "action_manager.h"
|
||||
#include "parser.h"
|
||||
#include "service.h"
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include "action.h"
|
||||
#include "action_manager.h"
|
||||
#include "action_parser.h"
|
||||
#include "builtins.h"
|
||||
#include "import_parser.h"
|
||||
#include "keyword_map.h"
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <private/android_filesystem_config.h>
|
||||
#include <selinux/selinux.h>
|
||||
|
||||
#include "action_manager.h"
|
||||
#include "capabilities.h"
|
||||
#include "init.h"
|
||||
#include "property_service.h"
|
||||
|
|
|
@ -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…
Reference in New Issue