系统启动动画

开机的时候没有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
喜欢就支持一下吧
点赞0 分享