揭秘开机动画BootAnimation启动全过程(全网最直白、最详细讲解,没有之一)
我们知道,android中的所有界面的显示都是需要surfaceflinger进程的绘制和渲染,所以BootAnimation进程肯定是在SurfaceFlinger之后启动的,我们先看一下surfaceflinger进程的代码。执行了class_start core后,会触发到system/core/init/buildtins.cpp中的do_class_start方法的执行,在 handle
首先来看一下BootAnimation的.rc文件 bootanim.rc,从class core animation可知,该进程是属于core和animation两大类的进程,但注意到,bootanim.rc和surfaceflinger.rc相比较,bootanim.rc多了一个disabled,我们知道,当init进程去执行init.rc的时候,执行到on boot块中的class_start core 语句的时候,就会启动core类的进程,其实,更准确来讲,是启动所有非disabled 的core类进程,所以即使执行了class_start core,也不会启动BootAnimation进程。
//bootanim.rc
service bootanim /system/bin/bootanimation
class core animation
user graphics
group graphics audio
disabled
oneshot
writepid /dev/stune/top-app/tasks
执行了class_start core后,会触发到system/core/init/buildtins.cpp中的do_class_start方法的执行,
从StartIfNotDisabled可知,该方法会启动所有非disabled 相关的进程,所以也就不会启动BootAnimation进程。
// builtins.cpp
static int do_class_start(const std::vector<std::string>& args) {
/* Starting a class does not start services
* which are explicitly disabled. They must
* be started individually.
*/
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
return 0;
}
那BootAnimation进程是在哪里启动的呢?
我们知道,android中的所有界面的显示都是需要surfaceflinger进程的绘制和渲染,所以BootAnimation进程肯定是在SurfaceFlinger之后启动的,我们先看一下surfaceflinger进程的代码
//main_sufaceflinger.cpp
int main(int, char**) {
........省略
flinger->init();
........省略
flinger->run();
return 0;
}
// SurfaceFlinger.cpp
void SurfaceFlinger::init() {
......省略
//这里会创建一个线程
if (getHwComposer().hasCapability(
HWC2::Capability::PresentFenceIsNotReliable)) {
mStartPropertySetThread = new StartPropertySetThread(false);
} else {
mStartPropertySetThread = new StartPropertySetThread(true);
}
//启动线程
if (mStartPropertySetThread->Start() != NO_ERROR) {
ALOGE("Run StartPropertySetThread failed!");
}
ALOGV("Done initializing");
}
当调用mStartPropertySetThread->Start() 之后会启动这个线程,启动线程之后,就会触发threadLoop()方法执行,执行了property_set("ctl.start", "bootanim") 这条语句就会去启动BootAnimation了
// StartPropertySetThread.cpp
//threadLoop()相当于java线程类中runable(),当调用StartPropertySetThread的时候就会触发该方法执行
bool StartPropertySetThread::threadLoop() {
// Set property service.sf.present_timestamp, consumer need check its readiness
property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
// Clear BootAnimation exit flag
property_set("service.bootanim.exit", "0");
// Start BootAnimation if not started
property_set("ctl.start", "bootanim");
// Exit immediately
return false;
}
问题1:为什么执行了property_set("ctl.start", "bootanim")语句,设置了属性之后,就会启动BootAnimation了呢?
回答:在init.cpp的main方法中,会调用start_property_service() 来创建一个socket来进行跨进程通信,当我们在surfaceflinger进程中设置了property_set("ctl.start", "bootanim")之后,就会触发init进程中的handle_property_set_fd方法的执行
//property_service.cpp
void start_property_service() {
property_set("ro.property_service.version", "2");
property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
false, 0666, 0, 0, nullptr, sehandle);
if (property_set_fd == -1) {
PLOG(ERROR) << "start_property_service socket creation failed";
exit(1);
}
listen(property_set_fd, 8);
register_epoll_handler(property_set_fd, handle_property_set_fd);
}
在 handle_property_set_fd方法中,会执行handle_property_set方法
//property.service.cpp
//最终会执行了handle_property_set方法
static void handle_property_set_fd() {
.......省略
switch (cmd) {
case PROP_MSG_SETPROP: {
.....省略
handle_property_set(socket, prop_value, prop_value, true);
break;
}
case PROP_MSG_SETPROP2: {
.....省略
handle_property_set(socket, name, value, false);
break;
}
default:
LOG(ERROR) << "sys_prop: invalid command " << cmd;
socket.SendUint32(PROP_ERROR_INVALID_CMD);
break;
}
}
//property_service.cpp
/*
* 通过StartsWith(name, "ctl.")判断是否以ctr.l开头,而启动BootAnimation的时候,设置了属性
* property_set("ctl.start", "bootanim"),刚好是ctl.开头,所以进入了if判断逻辑,执行
* handle_control_message方法
*/
static void handle_property_set(SocketConnection& socket,
const std::string& name,
const std::string& value,
bool legacy_protocol) {
......省略
if (android::base::StartsWith(name, "ctl.")) {
if (check_control_mac_perms(value.c_str(), source_ctx, &cr)) {
//property_set("ctl.start", "bootanim"),刚好是ctl.开头,所以执行到这里
handle_control_message(name.c_str() + 4, value.c_str());
} else {
.....省略
}
} else {
.....省略
}
freecon(source_ctx);
}
在handle_control_message中,执行了 svc->Start()之后,会fork出进程,然后调用ExpandArgsAndExecve方法启动BootAnimation进程
// init.cpp
void handle_control_message(const std::string& msg, const std::string& name) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(name);
if (svc == nullptr) {
LOG(ERROR) << "no such service '" << name << "'";
return;
}
if (msg == "start") {
//执行这里,将会启动进程
svc->Start();
} else if (msg == "stop") {
svc->Stop();
} else if (msg == "restart") {
svc->Restart();
} else {
}
}
至此,BootAnimation启动完成,总的来说,BootAnimation是还是由init进程fork出来的
更多推荐



所有评论(0)