ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Android Framework实战视频--init进程的bootanimation启动源码分析(补充Android 10部分的BootAnimation的启动源码分析)

2022-05-08 13:04:36  阅读:225  来源: 互联网

标签:control return 启动 源码 fd Android property message


课程答疑和新课信息:QQ交流群:422901085进行课程讨论
FrameWork入门课视频链接:https://edu.csdn.net/course/detail/30298
FrameWork实战课1视频链接:https://edu.csdn.net/course/detail/30275
FrameWork跨进程通信视频链接:https://edu.csdn.net/course/detail/35911
专题博客系列:
Android 8.1 zygote 启动过程源码
Android Framework实战视频–Zygote的fork进程篇
Android Framework实战视频–SystemServer启动篇
Android Framework实战视频–SystemServer启动FallbackHome篇
Android Framework实战视频–FallbackHome进程启动及Activity启动篇
Android Framework实战视频–FallbackHome结束启动Launcher篇
Android Framework实战视频–BootAnimation的启动源码分析(Android8.1)

Android Framework实战视频–init进程的bootanimation启动源码分析(补充Android 10部分的BootAnimation的启动源码分析)

Android Framework实战视频–BootAnimation的启动源码分析(补充Android 10部分的差异)
提示:针对有的同学可能代码较新这里基于Android 10源码对init部分进行分析
针对Android init进程启动property service的启动部分流程如下:
init进程的入口main函数已经不在init.cpp而是在main.cpp
路径如下:
system/core/init/main.cpp

int main(int argc, char** argv) {

if __has_feature(address_sanitizer)

__asan_set_error_report_callback(AsanReportCallback);

endif

if (!strcmp(basename(argv[0]), "ueventd")) {
    return ueventd_main(argc, argv);
}

if (argc > 1) {
    if (!strcmp(argv[1], "subcontext")) {
        android::base::InitLogging(argv, &android::base::KernelLogger);
        const BuiltinFunctionMap function_map;

        return SubcontextMain(argc, argv, &function_map);
    }

    if (!strcmp(argv[1], "selinux_setup")) {
        return SetupSelinux(argv);
    }

    if (!strcmp(argv[1], "second_stage")) {
        return SecondStageMain(argc, argv);//这里是关键,二阶段启动
    }
}

return FirstStageMain(argc, argv);

}

这里主要看的是二阶段启动方法SecondStageMain,该方法又是回到init.cpp

int SecondStageMain(int argc, char** argv) {
//省略
StartPropertyService(&property_fd);
if (auto result = epoll.RegisterHandler(property_fd, HandlePropertyFd); !result) { //监听fd的事件
LOG(FATAL) << "Could not register epoll handler for property fd: " << result.error();
}
//省略
return 0;
}

这里又看一个熟悉的方法StartPropertyService,而且传递进去了一个property_fd地址,然后对property_fd进行监听,该方法如下:

void StartPropertyService(int* epoll_socket) {
property_set("ro.property_service.version", "2");

int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 0) {//特别注意这里双工通信
    PLOG(FATAL) << "Failed to socketpair() between property_service and init";
}
//特别注意这里双工通信,可以实现0端写入1端读取,1端写入0端读取
*epoll_socket = sockets[0];//把fd传递给了指针
init_socket = sockets[1];

property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,false, 0666, 0, 0, nullptr);//创建PROP_SERVICE_NAME 的socket进行通信
if (property_set_fd == -1) {
    PLOG(FATAL) << "start_property_service socket creation failed";
}

listen(property_set_fd, 8);

std::thread{PropertyServiceThread}.detach();//启动线程监听数据

property_set = [](const std::string& key, const std::string& value) -> uint32_t {
    android::base::SetProperty(key, value);
    return 0;
};

}

这里其实和8.1差不多,主要创建socket,监听socket绑定和接收数据(特别注意这里双工通信,可以实现0端写入1端读取,1端写入0端读取),而且接收数据和对数据处理是在PropertyServiceThread方法中实现:

static void PropertyServiceThread() {
Epoll epoll;
if (auto result = epoll.Open(); !result) {
LOG(FATAL) << result.error();
}

if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd); !result) {
    LOG(FATAL) << result.error();
}

if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result) {
    LOG(FATAL) << result.error();
}

while (true) {
    if (auto result = epoll.Wait(std::nullopt); !result) {
        LOG(ERROR) << result.error();
    }
}

}

这里主要使用了epoll来监听各个fd的变化,这里我们主要关心是epoll.RegisterHandler(property_set_fd, handle_property_set_fd); !result),这个property_set_fd才是我们关心的fd,有数据变化这里会触发handle_property_set_fd方法:

static void handle_property_set_fd() {
//省略
switch (cmd) {
case PROP_MSG_SETPROP: {
//省略
uint32_t result =HandlePropertySet(prop_name, prop_value, source_context, cr, nullptr, &error);
//省略
break;
}

case PROP_MSG_SETPROP2: {
  //省略
    uint32_t result = HandlePropertySet(name, value, source_context, cr, &socket, &error);
    //省略
default:
  //省略
    break;
}

}

这里最后其实最后调用到了HandlePropertySet:

// This returns one of the enum of PROP_SUCCESS or PROP_ERROR.
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
const std::string& source_context, const ucred& cr,
SocketConnection
socket, std::string* error) {
//省略
if (StartsWith(name, "ctl.")) {//开机动画就是符合这个
return SendControlMessage(name.c_str() + 4, value, cr.pid, socket, error);
}
//省略

return PropertySet(name, value, error);

}

代码可以看出开机动画就是符合这个“ctrl.”情况接下来执行SendControlMessage:

static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid,SocketConnection* socket, std::string* error) {
//省略
if (auto result = SendMessage(init_socket, property_msg); !result) {
// We've already released the fd above, so if we fail to send the message to init, we need
// to manually free it here.
if (fd != -1) {
close(fd);
}
*error = "Failed to send control message: " + result.error_string();
return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
}

return PROP_SUCCESS;

}

这里其实就是调用SendMessage来发一个消息,但是这里大家注意发给了init_socket这个fd(就是前面说过的0端写入1端读取),那接下来在就会在init.cpp的HandlePropertyFd收到消息,故来分析方法:

static void HandlePropertyFd() {
auto message = ReadMessage(property_fd);
//省略
switch (property_message.msg_case()) {
case PropertyMessage::kControlMessage: {
auto& control_message = property_message.control_message();
//这里是关键,又会调用HandleControlMessage启动及判断是否成功
bool success = HandleControlMessage(control_message.msg(), control_message.name(),
control_message.pid());

        uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
        if (control_message.has_fd()) {
            int fd = control_message.fd();
            TEMP_FAILURE_RETRY(send(fd, &response, sizeof(response), 0));
            close(fd);
        }
        break;
    }
    case PropertyMessage::kChangedMessage: {
        auto& changed_message = property_message.changed_message();
        property_changed(changed_message.name(), changed_message.value());
        break;
    }
    default:
        LOG(ERROR) << "Unknown message type from property service: "
                   << property_message.msg_case();
}

}

这里最后又调用到HandleControlMessage:

bool HandleControlMessage(const std::string& msg, const std::string& name, pid_t pid) {
//获取一个control msg的map
const auto& map = get_control_message_map();
const auto it = map.find(msg);
//省略
const ControlMessageFunction& function = it->second;//得到对应function

Service* svc = nullptr;

switch (function.target) {
    case ControlTarget::SERVICE:
        svc = ServiceList::GetInstance().FindService(name);//寻找出对于service
        break;
    case ControlTarget::INTERFACE:
        svc = ServiceList::GetInstance().FindInterface(name);
        break;
    default:
        LOG(ERROR) << "Invalid function target from static map key '" << msg << "': "
                   << static_cast<std::underlying_type<ControlTarget>::type>(function.target);
        return false;
}

if (svc == nullptr) {
    LOG(ERROR) << "Could not find '" << name << "' for ctl." << msg;
    return false;
}

if (auto result = function.action(svc); !result) {//获取service后,会调用function进行执行
    LOG(ERROR) << "Could not ctl." << msg << " for '" << name << "': " << result.error();
    return false;
}
return true;

}

其实就是根据control msg获取对应的function,然后执行方法,那具体执行什么方法呢?
这里的get_control_message_map如下:

static const std::map<std::string, ControlMessageFunction>& get_control_message_map() {
// clang-format off
static const std::map<std::string, ControlMessageFunction> control_message_functions = {
{"sigstop_on", {ControlTarget::SERVICE,
[](auto* service) { service->set_sigstop(true); return Success(); }}},
{"sigstop_off", {ControlTarget::SERVICE,
[](auto* service) { service->set_sigstop(false); return Success(); }}},
{"start", {ControlTarget::SERVICE, DoControlStart}},
{"stop", {ControlTarget::SERVICE, DoControlStop}},
{"restart", {ControlTarget::SERVICE, DoControlRestart}},
{"interface_start", {ControlTarget::INTERFACE, DoControlStart}},
{"interface_stop", {ControlTarget::INTERFACE, DoControlStop}},
{"interface_restart", {ControlTarget::INTERFACE, DoControlRestart}},
};
// clang-format on

return control_message_functions;

}

所以这里我们bootanimation(“ctrl.start”)明显属于start,所以匹配的方法为DoControlStart:

static Result DoControlStart(Service* service) {
return service->Start();
}

看到service->Start();后就知道和以前8.1一模一样了,都是service启动,不再进行分析,看对于视频或者blog既可以
————————————————
版权声明:本文为CSDN博主「learnframework」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/learnframework/article/details/116719986

标签:control,return,启动,源码,fd,Android,property,message
来源: https://www.cnblogs.com/qianlima-android/p/16245150.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有