开机的时候没有Activity为什么可以播放开机动画呢?注意Android系统中存在几个开机动画,这里不去聊Linux开机动画,我们只聊Android渲染系统中的开机动画,也就是我们打开手机时候的那个动画。
正文
解析init.rc service的原理
service bootanim /system/bin/bootanimation
class core animation
user graphics
group graphics audio
disabled
oneshot
writepid /dev/stune/top-app/tasks
复制代码
开机就启动进程,那肯定就要从rc里面找。负责开机动画的进程是bootanimation。上面是他的rc文件。值得注意的是,设置了disable标志位。
我们翻翻看在init进程,是怎么解析service的。在Android9.0中实际上会把service,action,import等都会进行字符串解析额,最后分散在三个链表等待执行。
const Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
// clang-format off
static const Map option_parsers = {
{"capabilities",
{1, kMax, &Service::ParseCapabilities}},
{"class", {1, kMax, &Service::ParseClass}},
{"console", {0, 1, &Service::ParseConsole}},
{"critical", {0, 0, &Service::ParseCritical}},
{"disabled", {0, 0, &Service::ParseDisabled}},
{"enter_namespace",
{2, 2, &Service::ParseEnterNamespace}},
{"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}},
{"interface", {2, 2, &Service::ParseInterface}},
{"ioprio", {2, 2, &Service::ParseIoprio}},
{"priority", {1, 1, &Service::ParsePriority}},
{"keycodes", {1, kMax, &Service::ParseKeycodes}},
{"oneshot", {0, 0, &Service::ParseOneshot}},
{"onrestart", {1, kMax, &Service::ParseOnrestart}},
{"override", {0, 0, &Service::ParseOverride}},
{"oom_score_adjust",
{1, 1, &Service::ParseOomScoreAdjust}},
{"memcg.swappiness",
{1, 1, &Service::ParseMemcgSwappiness}},
{"memcg.soft_limit_in_bytes",
{1, 1, &Service::ParseMemcgSoftLimitInBytes}},
{"memcg.limit_in_bytes",
{1, 1, &Service::ParseMemcgLimitInBytes}},
{"namespace", {1, 2, &Service::ParseNamespace}},
{"rlimit", {3, 3, &Service::ParseProcessRlimit}},
{"seclabel", {1, 1, &Service::ParseSeclabel}},
{"setenv", {2, 2, &Service::ParseSetenv}},
{"shutdown", {1, 1, &Service::ParseShutdown}},
{"socket", {3, 6, &Service::ParseSocket}},
{"file", {2, 2, &Service::ParseFile}},
{"user", {1, 1, &Service::ParseUser}},
{"writepid", {1, kMax, &Service::ParseWritepid}},
};
// clang-format on
return option_parsers;
}
复制代码
在这个map中写好了每一个命令对应的解析方法指针。我们直接看看disable做了什么:
Result<Success> Service::ParseDisabled(const std::vector<std::string>& args) {
flags_ |= SVC_DISABLED;
flags_ |= SVC_RC_DISABLED;
return Success();
}
复制代码
很简单就是设置了DISABLED的flag。
当解析完毕将会尝试着执行解析好的service的命令。
Result<Success> Service::Start() {
bool disabled = (flags_ & (SVC_DISABLED | SVC_RESET));
flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
if (flags_ & SVC_RUNNING) {
if ((flags_ & SVC_ONESHOT) && disabled) {
flags_ |= SVC_RESTART;
}
// It is not an error to try to start a service that is already running.
return Success();
}
bool needs_console = (flags_ & SVC_CONSOLE);
if (needs_console) {
if (console_.empty()) {
console_ = default_console;
}
int console_fd = open(console_.c_str(), O_RDWR | O_CLOEXEC);
if (console_fd < 0) {
flags_ |= SVC_DISABLED;
return ErrnoError() << "Couldn't open console '" << console_ << "'";
}
close(console_fd);
}
...
pid_t pid = -1;
if (namespace_flags_) {
pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
} else {
pid = fork();
}
if (pid == 0) {
...
}
if (pid < 0) {
pid_ = 0;
return ErrnoError() << "Failed to fork";
}
...
return Success();
}
复制代码
能看到如果没有disable,reset这些标志位阻碍,将会通过fork系统生成一个新的进程。但是这里disable了,因此不会走下来,而是会把解析结果保存起来。保存在ServiceList对象中的services_ vector集合。
作者:yjy239
链接:www.jianshu.com/p/a79de4a6d…
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
作者:yjy239
链接:www.jianshu.com/p/a79de4a6d…
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
作者:yjy239
链接:www.jianshu.com/p/a79de4a6d…
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END