在init启动的SecondStage,通过调用LoadBootScripts来解析启动脚本,也就是rc文件。下面来研究这个解析过程,之后再看看init如何处理事件并执行相关action的。
SecondStageMain
int SecondStageMain(int argc, char** argv) {
...
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
Action::set_function_map(&function_map); // 设置 Action 需要的函数映射表
...
InitializeSubcontext(); // 初始化Subcontext
ActionManager& am = ActionManager::GetInstance(); // 创建action管理器
ServiceList& sm = ServiceList::GetInstance(); // 创建服务管理列表
LoadBootScripts(am, sm); // 加载并解析启动脚本
...
}
InitializeSubcontext
创建subcontext进程,用于执行init交给其的一些任务(比如后面执行的某些Command),通过socket与init进行通信
/// @system/core/init/subcontext.cpp
void InitializeSubcontext() {
if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_P__) {
subcontext.reset( // 创建Subcontext, path_prefixes为"/vendor", "/odm"
new Subcontext(std::vector<std::string>{"/vendor", "/odm"}, kVendorContext));
}
}
/// @system/core/init/subcontext.h
Subcontext(std::vector<std::string> path_prefixes, std::string context, bool host = false)
: path_prefixes_(std::move(path_prefixes)), context_(std::move(context)), pid_(0) {
if (!host) { /// host默认为false
Fork(); // 创建subcontext进程
}
}
LoadBootScripts
加载并解析 init rc 脚本
/// @system/core/init/init.cpp
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
// 创建 Parser 对象
Parser parser = CreateParser(action_manager, service_list);
std::string bootscript = GetProperty("ro.boot.init_rc", "");//获取属性指定的rc
if (bootscript.empty()) { // 没有指定rc,解析默认位置
parser.ParseConfig("/system/etc/init/hw/init.rc"); // 首先解析 init.rc
if (!parser.ParseConfig("/system/etc/init")) { // 解析 /system/etc/init 目录
late_import_paths.emplace_back("/system/etc/init"); // 解析失败延时解析
}
// late_import is available only in Q and earlier release. As we don't
// have system_ext in those versions, skip late_import for system_ext.
parser.ParseConfig("/system_ext/etc/init"); // 解析 /system_ext/etc/init 目录
if (!parser.ParseConfig("/vendor/etc/init")) { // 解析 /vendor/etc/init 目录
late_import_paths.emplace_back("/vendor/etc/init");
}
if (!parser.ParseConfig("/odm/etc/init")) { // 解析 /odm/etc/init 目录
late_import_paths.emplace_back("/odm/etc/init");
}
if (!parser.ParseConfig("/product/etc/init")) { // 解析 /product/etc/init 目录
late_import_paths.emplace_back("/product/etc/init");
}
} else {
parser.ParseConfig(bootscript);
}
}
CreateParser
/// @system/core/init/init.cpp
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
Parser parser;
// 添加各部分解析器
// 创建ServiceParser 解析 service 服务,用于管理和启动native进程
parser.AddSectionParser("service", std::make_unique<ServiceParser>(
&service_list, GetSubcontext(), std::nullopt));
// 创建ActionParser 解析 on action , 定义的一些动作
parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, GetSubcontext()));
// ImportParser解析import, 导入其他rc
parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
return parser;
}
AddSectionParser按名称添加parser到集合
/// @system/core/init/parser.cpp
void Parser::AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser) {
section_parsers_[name] = std::move(parser); // 按名称存储对应的parser
}
// 集合按名字存储对应的 SectionParser
std::map<std::string, std::unique_ptr<SectionParser>> section_parsers_;
接下来看解析流程,通过调用Parser::ParseConfig函数来实现解析指定路径的rc文件或目录下的rc文件。
Parser::ParseConfig
/// @system/core/init/parser.cpp
bool Parser::ParseConfig(const std::string& path) {
if (is_dir(path.c_str())) { // 如果提供的目录
return ParseConfigDir(path); // 解析配置目录
}
return ParseConfigFile(path); // 解析配置文件
}
Parser::ParseConfigDir
执行解析配置目录操作,遍历目录调用ParseConfigFile解析每一个文件。忽略目录下的子目录,也就是不支持多层级目录。
/// @system/core/init/parser.cpp
bool Parser::ParseConfigDir(const std::string& path) {
LOG(INFO) << "Parsing directory " << path << "...";
std::unique_ptr<DIR, decltype(&closedir)> config_dir(opendir(path.c_str()), closedir);
if (!config_dir) {
PLOG(INFO) << "Could not import directory '" << path << "'";
return false;
}
dirent* current_file;
std::vector<std::string> files;
while ((current_file = readdir(config_dir.get()))) { // 读取目录下的内容
// Ignore directories and only process regular files.
if (current_file->d_type == DT_REG) { // 如果是文件则添加到待解析集合
std::string current_path =
android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name);
files.emplace_back(current_path);
}
}
// Sort first so we load files in a consistent order (bug 31996208)
std::sort(files.begin(), files.end());
for (const auto& file : files) { // 遍历集合,解析文件
if (!ParseConfigFile(file)) {
LOG(ERROR) << "could not import file '" << file << "'";
}
}
return true;
}
接下来看如何解析一个配置文件
Parser::ParseConfigFile
/// @system/core/init/parser.cpp
bool Parser::ParseConfigFile(const std::string& path) {
LOG(INFO) << "Parsing file " << path << "...";
android::base::Timer t;
// 读取文件内容到string,实现在system/core/init/util.cpp,调用 android::base::ReadFdToString
auto config_contents = ReadFile(path);
if (!config_contents.ok()) {
LOG(INFO) << "Unable to read config file '" << path << "': " << config_contents.error();
return false;
}
ParseData(path, &config_contents.value()); // 解析脚本内容
LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
return true;
}
Parser::ParseData
解析流程循环:
- 获取的下一个token来决定接下来的动作,比如EOF结尾或者某个关键字
- 遇到T_EOF则调用EndSection结束当前解析的ParseSection,退出循环
- 遇到T_NEWLINE换新行,则进行解析一行
- 如果获取的token是parser对应的关键字,比如on,则获取对应的parser进行解析,调用ParseSection
- 如果token不是关键字,且上一步有获取parser,则进行解析一行,调用ParseLineSection
- 遇到下一个关键字则调用EndSection结束当前解析的ParseSection,开启新的解析
- 如果解析到文本,则添加到args集合
void Parser::ParseData(const std::string& filename, std::string* data) {
data->push_back('\n'); // 添加一个换行
data->push_back('\0'); // 添加一个结束符
parse_state state;
state.line = 0;
state.ptr = data->data();
state.nexttoken = 0;
SectionParser* section_parser = nullptr;
int section_start_line = -1;
std::vector<std::string> args;
// If we encounter a bad section start, there is no valid parser object to parse the subsequent
// sections, so we must suppress errors until the next valid section is found.
bool bad_section_found = false;
auto end_section = [&] { // 结束section的回调
bad_section_found = false;
if (section_parser == nullptr) return;
if (auto result = section_parser->EndSection(); !result.ok()) {
parse_error_count_++;
LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error();
}
section_parser = nullptr;
section_start_line = -1;
};
for (;;) {
switch (next_token(&state)) { // 根据获取的下一个token来决定接下来的动作
case T_EOF: // 文件结束。
end_section();
for (const auto& [section_name, section_parser] : section_parsers_) {
section_parser->EndFile();
}
return;
case T_NEWLINE: { // 检测到换行,解析当前行
state.line++;
if (args.empty()) break;
// If we have a line matching a prefix we recognize, call its callback and unset any
// current section parsers. This is meant for /sys/ and /dev/ line entries for
// uevent.
auto line_callback = std::find_if(
line_callbacks_.begin(), line_callbacks_.end(),
[&args](const auto& c) { return android::base::StartsWith(args[0], c.first); });
if (line_callback != line_callbacks_.end()) { // 针对指定prefix的情况,比如 /dev/
end_section();
if (auto result = line_callback->second(std::move(args)); !result.ok()) {
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
}
} else if (section_parsers_.count(args[0])) { // 如果第一个值能够匹配到parser, 比如是 service
end_section(); // 结束之前。
section_parser = section_parsers_[args[0]].get();
section_start_line = state.line;
if (auto result = // 解析 section
section_parser->ParseSection(std::move(args), filename, state.line);
!result.ok()) {
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
section_parser = nullptr;
bad_section_found = true;
}
} else if (section_parser) { // 使用当前parser解析一行
if (auto result = section_parser->ParseLineSection(std::move(args), state.line);
!result.ok()) {
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
}
} else if (!bad_section_found) { // 没有任何匹配,则表示关键字错误
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line
<< ": Invalid section keyword found";
}
args.clear();
break;
}
case T_TEXT: // 是文本则添加到vector
args.emplace_back(state.text);
break;
}
}
}
next_token
该函数是用来解析token的,并获取有效的文本信息
/// @system/core/init/tokenizer.cpp
int next_token(struct parse_state *state)
{
char *x = state->ptr;
char *s;
if (state->nexttoken) {
int t = state->nexttoken;
state->nexttoken = 0;
return t;
}
for (;;) {
switch (*x) {
case 0: // 结尾
state->ptr = x;
return T_EOF;
case '\n': // 换行符
x++;
state->ptr = x;
return T_NEWLINE;
case ' ':
case '\t':
case '\r': // 跳过空白字符
x++;
continue;
case '#':
while (*x && (*x != '\n')) x++; // 跳过 # 注释行
if (*x == '\n') { // 换行
state->ptr = x+1;
return T_NEWLINE;
} else { // 结尾
state->ptr = x;
return T_EOF;
}
default: // 默认跳转到文本处理
goto text;
}
}
textdone:
state->ptr = x;
*s = 0;
return T_TEXT;
text:
state->text = s = x;
textresume:
for (;;) {
switch (*x) {
case 0: // 字符结束符
goto textdone;
case ' ':
case '\t':
case '\r': // 检测到空白符则返回
x++;
goto textdone;
case '\n': // 换行
state->nexttoken = T_NEWLINE;
x++;
goto textdone;
case '"': // 引号包裹内存
x++;
for (;;) {
switch (*x) {
case 0:
/* unterminated quoted thing */
state->ptr = x;
return T_EOF;
case '"':
x++;
goto textresume;
default:
*s++ = *x++; // 复制引号内容
}
}
break;
case '\\': // 下面处理其他转义字符
x++;
switch (*x) {
case 0:
goto textdone;
case 'n':
*s++ = '\n';
x++;
break;
case 'r':
*s++ = '\r';
x++;
break;
case 't':
*s++ = '\t';
x++;
break;
case '\\':
*s++ = '\\';
x++;
break;
case '\r':
/* \ <cr> <lf> -> line continuation */
if (x[1] != '\n') {
x++;
continue;
}
x++;
FALLTHROUGH_INTENDED;
case '\n':
/* \ <lf> -> line continuation */
state->line++;
x++;
/* eat any extra whitespace */
while((*x == ' ') || (*x == '\t')) x++;
continue;
default:
/* unknown escape -- just copy */
*s++ = *x++;
}
continue;
default:
*s++ = *x++;
}
}
return T_EOF;
}
接下来以解析on为例来分析,看关键字对应的是ActionParser
ActionParser::ParseSection
/// @system/core/init/action_parser.cpp
Result<void> ActionParser::ParseSection(std::vector<std::string>&& args,
const std::string& filename, int line) {
std::vector<std::string> triggers(args.begin() + 1, args.end()); // 除了on的其他参数
if (triggers.size() < 1) { // on 后面需要指定trigger
return Error() << "Actions must have a trigger";
}
Subcontext* action_subcontext = nullptr;
// 检查路径是否匹配path_prefixes_中的路径前缀 /vendor, /odm
if (subcontext_ && subcontext_->PathMatchesSubcontext(filename)) {
action_subcontext = subcontext_; // 前缀匹配会获取到 subcontext_
}
std::string event_trigger;
std::map<std::string, std::string> property_triggers;
if (auto result = // 解析 trigger
ParseTriggers(triggers, action_subcontext, &event_trigger, &property_triggers);
!result.ok()) {
return Error() << "ParseTriggers() failed: " << result.error();
}
// 创建该action对象,第一个参数false表示非oneshot,
auto action = std::make_unique<Action>(false, action_subcontext, filename, line, event_trigger,
property_triggers);
action_ = std::move(action); // 缓存此解析的action,后续解析line的时候会用到
return {};
}
ParseTriggers
以解析 on post-fs-data && property:ro.debuggable=1 为例分析,args 就是on 之后的内容。
Result<void> 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;
}
}
// property: 开头的是属性触发器
if (!args[i].compare(0, prop_str.length(), prop_str)) {
if (auto result = ParsePropertyTrigger(args[i], subcontext, property_triggers); // 解析属性触发器
!result.ok()) {
return result;
}
} else { // 否则是事件触发器,比如 post-fs-data
if (!event_trigger->empty()) { // 只能指定一个事件触发器
return Error() << "multiple event triggers are not allowed";
}
// 检查组成字符合法性,通常只能由 _ 、- 、数字或字母 组成
if (auto result = ValidateEventTrigger(args[i]); !result.ok()) {
return result;
}
*event_trigger = args[i]; // 保存事件触发器
}
}
return {};
}
ParsePropertyTrigger
Result<void> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext,
std::map<std::string, std::string>* property_triggers) {
const static std::string prop_str("property:"); // property:ro.debuggable=1
std::string prop_name(trigger.substr(prop_str.length()));// 去除前缀 ro.debuggable=1
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 trigger found: " << prop_name;
}
// 将属性名和值组成的触发器添加到 property_triggers
if (auto [it, inserted] = property_triggers->emplace(prop_name, prop_value); !inserted) {
return Error() << "multiple property triggers found for same property";
}
return {};
}
到此,已经创建了Action,并获取了事件触发器和属性触发器。接下来解析它的Command命令列表
ParseLineSection
/// @system/core/init/action_parser.cpp
Result<void> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
return action_ ? action_->AddCommand(std::move(args), line) : Result<void>{};// 通过Action解析Command
}
Action::AddCommand
/// @system/core/init/action.cpp
Result<void> Action::AddCommand(std::vector<std::string>&& args, int line) {
if (!function_map_) {
return Error() << "no function map available";
}
auto map_result = function_map_->Find(args); // 匹配函数表
if (!map_result.ok()) {
return Error() << map_result.error();
}
// 找到匹配的函数,将新创建的 Command 添加到commands_列表
commands_.emplace_back(map_result->function, map_result->run_in_subcontext, std::move(args),
line);
return {};
}
创建 Command
Command::Command(BuiltinFunction f, bool execute_in_subcontext, std::vector<std::string>&& args,
int line)
: func_(std::move(f)), // 函数
execute_in_subcontext_(execute_in_subcontext), // 是否在subcontext中执行
args_(std::move(args)), // 参数
line_(line) /* 命令在文件行号*/ {}
function_map_ 实际上是KeywordMap的实例,看看它的实现。
KeywordMap::Find
Result<Value> Find(const std::vector<std::string>& args) const {
if (args.empty()) return Error() << "Keyword needed, but not provided";
// 以 copy /proc/cmdline /dev/urandom 为例
auto& keyword = args[0]; // 取出关键字 copy
auto num_args = args.size() - 1; // 关键字copy 后的其他参数
auto result_it = map_.find(keyword); // 找到copy对应的 MapValue
if (result_it == map_.end()) {
return Errorf("Invalid keyword '{}'", keyword);
}
auto result = result_it->second; // MapValue
auto min_args = result.min_args;
auto max_args = result.max_args;
if (min_args == max_args && num_args != min_args) {// 检查参数的数量
return Errorf("{} requires {} argument{}", keyword, min_args,
(min_args > 1 || min_args == 0) ? "s" : "");
}
if (num_args < min_args || num_args > max_args) { // 检查是否缺参数,多参数
if (max_args == std::numeric_limits<decltype(max_args)>::max()) {
return Errorf("{} requires at least {} argument{}", keyword, min_args,
min_args > 1 ? "s" : "");
} else {
return Errorf("{} requires between {} and {} arguments", keyword, min_args,
max_args);
}
}
return result.value;
}
看一下KeywordMap的实现
// Value is the return value of Find(), which is typically either a single function or a struct with
// additional information.
template <typename Value>
class KeywordMap {
public:
struct MapValue {
size_t min_args;
size_t max_args;
Value value;
};
KeywordMap() {}
KeywordMap(std::initializer_list<std::pair<const std::string, MapValue>> init) : map_(init) {}
Result<Value> Find(const std::vector<std::string>& args) const { ... }
private:
std::map<std::string, MapValue> map_; // 函数名+MapValue组合
};
BuiltinFunctionMap
function_map_ 是一些内置函数映射表,通过GetBuiltinFunctionMap(),然后通过Action::set_function_map设置进来的。BuiltinFunctionMap 是KeywordMap的别名。
/// @system/core/init/builtins.h
using BuiltinFunction = std::function<Result<void>(const BuiltinArguments&)>;
struct BuiltinFunctionMapValue {
bool run_in_subcontext;
BuiltinFunction function;
};
using BuiltinFunctionMap = KeywordMap<BuiltinFunctionMapValue>;
/// 内置函数映射表,当Command执行 copy 时, 会调用 do_copy 函数
/// @system/core/init/builtins.cpp
// Builtin-function-map start
const BuiltinFunctionMap& GetBuiltinFunctionMap() {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
// clang-format off
static const BuiltinFunctionMap builtin_functions =
// 函数名, MapValue{ min_args,max_args,BuiltinFunctionMapValue{ run_in_subcontext, BuiltinFunction } }
{"bootchart", {1, 1, {false, do_bootchart}}},
{"chmod", {2, 2, {true, do_chmod}}},
{"chown", {2, 3, {true, do_chown}}},
{"class_reset", {1, 1, {false, do_class_reset}}},
{"class_reset_post_data", {1, 1, {false, do_class_reset_post_data}}},
{"class_restart", {1, 1, {false, do_class_restart}}},
{"class_start", {1, 1, {false, do_class_start}}},
{"class_start_post_data", {1, 1, {false, do_class_start_post_data}}},
{"class_stop", {1, 1, {false, do_class_stop}}},
{"copy", {2, 2, {true, do_copy}}},
{"copy_per_line", {2, 2, {true, do_copy_per_line}}},
{"domainname", {1, 1, {true, do_domainname}}},
{"enable", {1, 1, {false, do_enable}}},
{"exec", {1, kMax, {false, do_exec}}},
{"exec_background", {1, kMax, {false, do_exec_background}}},
{"exec_start", {1, 1, {false, do_exec_start}}},
{"export", {2, 2, {false, do_export}}},
{"hostname", {1, 1, {true, do_hostname}}},
{"ifup", {1, 1, {true, do_ifup}}},
{"init_user0", {0, 0, {false, do_init_user0}}},
{"insmod", {1, kMax, {true, do_insmod}}},
{"installkey", {1, 1, {false, do_installkey}}},
{"interface_restart", {1, 1, {false, do_interface_restart}}},
{"interface_start", {1, 1, {false, do_interface_start}}},
{"interface_stop", {1, 1, {false, do_interface_stop}}},
{"load_exports", {1, 1, {false, do_load_exports}}},
{"load_persist_props", {0, 0, {false, do_load_persist_props}}},
{"load_system_props", {0, 0, {false, do_load_system_props}}},
{"loglevel", {1, 1, {false, do_loglevel}}},
{"mark_post_data", {0, 0, {false, do_mark_post_data}}},
{"mkdir", {1, 6, {true, do_mkdir}}},
// TODO: Do mount operations in vendor_init.
// mount_all is currently too complex to run in vendor_init as it queues action triggers,
// imports rc scripts, etc. It should be simplified and run in vendor_init context.
// mount and umount are run in the same context as mount_all for symmetry.
{"mount_all", {0, kMax, {false, do_mount_all}}},
{"mount", {3, kMax, {false, do_mount}}},
{"perform_apex_config", {0, 0, {false, do_perform_apex_config}}},
{"umount", {1, 1, {false, do_umount}}},
{"umount_all", {0, 1, {false, do_umount_all}}},
{"update_linker_config", {0, 0, {false, do_update_linker_config}}},
{"readahead", {1, 2, {true, do_readahead}}},
{"remount_userdata", {0, 0, {false, do_remount_userdata}}},
{"restart", {1, 1, {false, do_restart}}},
{"restorecon", {1, kMax, {true, do_restorecon}}},
{"restorecon_recursive", {1, kMax, {true, do_restorecon_recursive}}},
{"rm", {1, 1, {true, do_rm}}},
{"rmdir", {1, 1, {true, do_rmdir}}},
{"setprop", {2, 2, {true, do_setprop}}},
{"setrlimit", {3, 3, {false, do_setrlimit}}},
{"start", {1, 1, {false, do_start}}},
{"stop", {1, 1, {false, do_stop}}},
{"swapon_all", {0, 1, {false, do_swapon_all}}},
{"enter_default_mount_ns", {0, 0, {false, do_enter_default_mount_ns}}},
{"symlink", {2, 2, {true, do_symlink}}},
{"sysclktz", {1, 1, {false, do_sysclktz}}},
{"trigger", {1, 1, {false, do_trigger}}},
{"verity_update_state", {0, 0, {false, do_verity_update_state}}},
{"wait", {1, 2, {true, do_wait}}},
{"wait_for_prop", {2, 2, {false, do_wait_for_prop}}},
{"write", {2, 2, {true, do_write}}},
};
// clang-format on
return builtin_functions;
}
// Builtin-function-map end
当解析完一个action,会执行EndSection函数
ActionParser::EndSection
Result<void> ActionParser::EndSection() {
if (action_ && action_->NumCommands() > 0) {
action_manager_->AddAction(std::move(action_)); // 将当前解析的action添加到集合
}
return {};
}
动作、内置动作和事件触发器
- 动作(Action)
通常是在rc中使用 on 声明的动作,action通常需要一些事件来触发 - 内置动作(Builtin Action)
只在代码里面调用QueueBuiltinAction的action,其他action在rc里使用 on 声明。 - 事件触发器(Trigger)
调用QueueEventTrigger插入事件触发器。这种触发器通常用一个字符串表示,会有一些action与之对应。
看下 Action 构造函数
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), // action所在文件和行号
line_(line) {}
action通常在事件发生时触发,事件都存放在event_queue_集合里
std::vector<std::unique_ptr<Action>> actions_; // action集合
std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_
GUARDED_BY(event_queue_lock_); // 事件队列
mutable std::mutex event_queue_lock_;
std::queue<const Action*> current_executing_actions_; // 正在出现的action队列
std::size_t current_command_; // 已执行的命令数量
ActionManager::QueueBuiltinAction
void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
auto lock = std::lock_guard{event_queue_lock_};
// 创建action,注意第一个参数为true 表示一次性的 oneshot
auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
std::map<std::string, std::string>{});
action->AddCommand(std::move(func), {name}, 0);// fun 添加到命令列表,执行action的命令时会被调用
event_queue_.emplace(action.get()); // 添加到事件队列
actions_.emplace_back(std::move(action)); // 添加到action队列
}
ActionManager::QueueEventTrigger
void ActionManager::QueueEventTrigger(const std::string& trigger) {
auto lock = std::lock_guard{event_queue_lock_};
event_queue_.emplace(trigger); // 添加到事件队列
}
QueueBuiltinAction和QueueEventTrigger只是将相关action和事件添加进队列,实际上没有真正去执行,而实际去执行是在其主循环里面触发的,通过 ActionManager#ExecuteOneCommand
ActionManager::ExecuteOneCommand
/// @system/core/init/action_manager.cpp
void ActionManager::ExecuteOneCommand() {
{
auto lock = std::lock_guard{event_queue_lock_};
// Loop through the event queue until we have an action to execute
while (current_executing_actions_.empty() && !event_queue_.empty()) { // 当前没有执行的action,但是有事件
for (const auto& action : actions_) { // 找到此事件对应要处理的action,可能对应多个
if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
event_queue_.front())) {
current_executing_actions_.emplace(action.get()); // 一个事件可以对应多个 action
}
}
event_queue_.pop();
}
}
if (current_executing_actions_.empty()) {
return;
}
// 返回 queue 中第一个元素的引用,而不是删除
auto action = current_executing_actions_.front();
if (current_command_ == 0) { // 处理此action的第一条命令时打印
std::string trigger_name = action->BuildTriggersString();
LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
<< ":" << action->line() << ")";
}
action->ExecuteOneCommand(current_command_); // 回调每个action匹配的命令
// 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_; // 每执行一次数量加1
if (current_command_ == action->NumCommands()) { // 如果此 action的命令全部执行完毕
current_executing_actions_.pop(); // 从正执行列表删除
current_command_ = 0;
if (action->oneshot()) { // 如果是一次性的 还有从action列表移除。 通常Builtin Action是一次性的
auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; };
actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser),
actions_.end());
}
}
}
Action::CheckEvent
检查event 与 action 是否匹配
bool Action::CheckEvent(const EventTrigger& event_trigger) const { // 检查事件触发器
return event_trigger == event_trigger_ && CheckPropertyTriggers();//触发器满足并且所有实现也匹配
}
bool Action::CheckEvent(const PropertyChange& property_change) const { // 检查属性变化事件
const auto& [name, value] = property_change;
return event_trigger_.empty() && CheckPropertyTriggers(name, value);
}
bool Action::CheckEvent(const BuiltinAction& builtin_action) const { // 检查内置action,其event和action是同一个对象
return this == builtin_action;
}
// 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.
//
// It takes an optional (name, value) pair, which if provided must
// be present in property_triggers_; it skips the check of the current
// property value for this pair.
bool Action::CheckPropertyTriggers(const std::string& name, const std::string& value) const {// 检查所有属性是否匹配
if (property_triggers_.empty()) { // 需要包含属性trigger -> property:aa.bb.cc=xxx
return true;
}
if (!name.empty()) { // 如果指定key,需要检查value是否满足指定触发值
auto it = property_triggers_.find(name);
if (it == property_triggers_.end()) {
return false;
}
const auto& trigger_value = it->second;
if (trigger_value != "*" && trigger_value != value) {
return false;
}
}
// 指定值满足 或 指定值为空。 判断所有非指定的属性键值要满足触发值
for (const auto& [trigger_name, trigger_value] : property_triggers_) {
if (trigger_name != name) { // 判断除了指定触发键之外的
std::string prop_value = android::base::GetProperty(trigger_name, "");
if (trigger_value == "*" && !prop_value.empty()) {
continue;
}
if (trigger_value != prop_value) return false;
}
}
return true;
}
Action::ExecuteOneCommand
执行一条Command
/// @system/core/init/action.cpp
void Action::ExecuteOneCommand(std::size_t command) const {
// We need a copy here since some Command execution may result in
// changing commands_ vector by importing .rc files through parser
Command cmd = commands_[command];
ExecuteCommand(cmd);
}
// 执行某一条命令
void Action::ExecuteCommand(const Command& command) const {
android::base::Timer t;
auto result = command.InvokeFunc(subcontext_); // 调用执行对应的命令
auto duration = t.duration();
// Any action longer than 50ms will be warned to user as slow operation
if (!result.has_value() || 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() << ") took " << duration.count() << "ms and "
<< (result.ok() ? "succeeded" : "failed: " + result.error().message());
}
}
Command::InvokeFunc
/// @system/core/init/action.cpp
Result<void> Command::InvokeFunc(Subcontext* subcontext) const {
if (subcontext) { // 指定了subcontext
if (execute_in_subcontext_) { // 如果指定在 subcontext 下执行
return subcontext->Execute(args_);
}
auto expanded_args = subcontext->ExpandArgs(args_);
if (!expanded_args.ok()) { // 膨胀处理失败,则结束处理
return expanded_args.error();
}
return RunBuiltinFunction(func_, *expanded_args, subcontext->context());
}
return RunBuiltinFunction(func_, args_, kInitContext);
}
- 当指定了不为空的subcontext,
- 若execute_in_subcontext_为true,则会直接调用subcontext->Execute
- 否则会先subcontext->ExpandArgs通过subcontext进程对args进行膨胀处理(主要是将 ${prop_name} 解析成对应的属性值),然后在调用RunBuiltinFunction
- 未指定subcontext则直接调用RunBuiltinFunction
RunBuiltinFunction
执行内置的函数
Result<void> RunBuiltinFunction(const BuiltinFunction& function,
const std::vector<std::string>& args, const std::string& context) {
auto builtin_arguments = BuiltinArguments(context);
builtin_arguments.args.resize(args.size());
builtin_arguments.args[0] = args[0];
for (std::size_t i = 1; i < args.size(); ++i) {
// ExpandProps函数将属性 ${prop_name} 解析成对应的属性值,在system/core/init/util.cpp 实现
auto expanded_arg = ExpandProps(args[i]);
if (!expanded_arg.ok()) {
return expanded_arg.error();
}
builtin_arguments.args[i] = std::move(*expanded_arg);
}
return function(builtin_arguments); // 调用对应的函数
}
比如对于如下Command,则会调用do_setprop去将vendor.qemu.timezone的属性值设置给persist.sys.timezone。
setprop persist.sys.timezone ${vendor.qemu.timezone}