前言
安卓 启动链路里,SurfaceFlinger 一定先于 BootAnimation 工作起来,否则开机动画根本没有显示目标。因此,SurfaceFlinger 是 bootanimation 的前置依赖。
相关源码路径
bash
bootanimation frameworks/base/cmds/bootanimation/
surfaceflinger frameworks/native/services/surfaceflinger/
init system/core/init/
surfaceflinger启动
安卓内核起来后会启动第一个init进程。init进程会根据init.rc(system/core/rootdir/init.rc)配置启动surfaceflinger进程。
rc
# surfaceflinger.rc
service surfaceflinger /system/bin/surfaceflinger
class core animation
user system
group graphics drmrpc readproc
capabilities SYS_NICE
onrestart restart --only-if-running zygote
task_profiles HighPerformance
socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
surfaceflinger有一个单独的rc文件,定义了class core animation。
rc
# system/core/rootdir/init.rc
on boot
......
chown system system /sys/kernel/ipv4/tcp_rmem_max
chown root radio /proc/cmdline
chown root system /proc/bootconfig
# Define default initial receive window size in segments.
setprop net.tcp_def_init_rwnd 60
# Start standard binderized HAL daemons
class_start hal
# 这里,启动所有core类
class_start core
在 init.rc 的执行流程中,Android 不再倾向于逐个手动 start 服务,而是通过 class_start 命令来批量启动同一类别的服务。
- 当系统启动进入特定阶段(如
on boot)时,init.rc会执行class_start core。 - 因为 SurfaceFlinger 被标记为 core 类,
init进程会自动扫描所有加载的.rc文件,并启动所有属于该类的服务。
surfaceflinger进程便启动了,跟着就会跑进程的main()函数,即frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp。这个main_surfaceflinger.cpp就是第一个执行的文件,因为它包含了程序的入口点 main() 函数。
cpp
/* main_surfaceflinger.cpp */
int main(int, char**) {
sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger(); // 创建surfaceflinger服务
flinger->init(); // 初始化SurfaceFlinger
// 将SurfaceFlinger注册为系统服务
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
// run surface flinger in this thread
flinger->run();
return 0;
}
cpp
/* SurfaceFlinger.cpp */
void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) {
...
// 异步设置系统属性
// Avoid blocking the main thread on `init` to set properties.
mInitBootPropsFuture.callOnce([this] {
return std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this);
});
...
}
void SurfaceFlinger::initBootProperties() {
property_set("service.sf.present_timestamp", mHasReliablePresentFences ? "1" : "0");
if (base::GetBoolProperty("debug.sf.boot_animation"s, true)) {
// Reset and (if needed) start BootAnimation.
property_set("service.bootanim.exit", "0"); // 这个属性bootanimation进程里会周期检查,=1时就退出动画,这里=0表示要播放动画
property_set("service.bootanim.progress", "0");
property_set("ctl.start", "bootanim"); // 启动 开机动画
}
}
这样bootanim进程就会启动?凭什么设置了一个属性就启动了?
那么下面我们来看,/system/core/init/main.cpp ,在看init进程的main.cpp的main函数中:
cpp
/* system/core/init/main.cpp */
int main(int argc, char** argv) {
...
if (argc > 1) {
if (!strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
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); // 第二阶段则进一步加载系统配置并启动系统服务,SecondStageMain是在init.cpp中
}
}
return FirstStageMain(argc, argv);
}
cpp
/* system/core/init/init.cpp */
int SecondStageMain(int argc, char** argv) {
...
StartPropertyService(&property_fd); // 在property_service.cpp中定义,这里先执行
...
while (true) {
...
auto epoll_result = epoll.Wait(epoll_timeout); // 等待事件(被 WakeMainInitThread() 唤醒),这里等到后面才会用到
if (!epoll_result.ok()) {
LOG(ERROR) << epoll_result.error();
}
if (!IsShuttingDown()) {
HandleControlMessages();
SetUsbController();
}
}
return 0;
}
cpp
/* system/core/init/property_service.cpp */
void StartPropertyService(int* epoll_socket) {
InitPropertySet("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";
}
*epoll_socket = from_init_socket = sockets[0];
init_socket = sockets[1];
StartSendingMessages();
// 启动属性服务线程
StartThread(PROP_SERVICE_FOR_SYSTEM_NAME, 0660, AID_SYSTEM, property_service_for_system_thread,
true);
StartThread(PROP_SERVICE_NAME, 0666, 0, property_service_thread, false);
auto async_persist_writes =
android::base::GetBoolProperty("ro.property_service.async_persist_writes", false);
if (async_persist_writes) {
persist_write_thread = std::make_unique<PersistWriteThread>();
}
}
void StartThread(const char* name, int mode, int gid, std::thread& t, bool listen_init) {
int fd = -1;
if (auto result = CreateSocket(name, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
/*passcred=*/false, /*should_listen=*/false, mode, /*uid=*/0,
/*gid=*/gid, /*socketcon=*/{});
result.ok()) {
fd = *result;
} else {
LOG(FATAL) << "start_property_service socket creation failed: " << result.error();
}
listen(fd, 8);
// 创建新线程,运行 PropertyServiceThread 函数
auto new_thread = std::thread(PropertyServiceThread, fd, listen_init);
t.swap(new_thread);
}
static void PropertyServiceThread(int fd, bool listen_init) {
Epoll epoll; // 创建一个 epoll 实例,监听多个文件描述符(FD)的事件
if (auto result = epoll.Open(); !result.ok()) {
LOG(FATAL) << result.error();
}
// 将属性服务的 socket(fd)注册到 epoll,当有数据可读时,调用 handle_property_set_fd 处理。
if (auto result = epoll.RegisterHandler(fd, std::bind(handle_property_set_fd, fd));
!result.ok()) {
LOG(FATAL) << result.error();
}
...
}
static void handle_property_set_fd(int fd) {
switch (cmd) {
case PROP_MSG_SETPROP: {
...
const auto& cr = socket.cred();
std::string error;
// 这里的HandlePropertySetNoSocket,最后也会调用HandlePropertySet
auto result = HandlePropertySetNoSocket(prop_name, prop_value, source_context, cr, &error);
if (result != PROP_SUCCESS) {
LOG(ERROR) << "Unable to set property '" << prop_name << "' from uid:" << cr.uid
<< " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;
}
break;
}
case PROP_MSG_SETPROP2: {
...
// 这里的HandlePropertySet
auto result = HandlePropertySet(name, value, source_context, cr, &socket, &error);
if (!result) {
// Result will be sent after completion.
return;
}
if (*result != PROP_SUCCESS) {
LOG(ERROR) << "Unable to set property '" << name << "' from uid:" << cr.uid
<< " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;
}
socket.SendUint32(*result);
break;
}
default:
LOG(ERROR) << "sys_prop: invalid command " << cmd;
socket.SendUint32(PROP_ERROR_INVALID_CMD);
break;
}
}
在之前的SurfaceFlinger::initBootProperties中,传入的参数name=ctl.start,value=bootanim
cpp
/* system/core/init/property_service.cpp */
std::optional<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 (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) {
return {ret};
}
if (StartsWith(name, "ctl.")) {
// 这里,最终经过裁剪后,传入的是start和bootanim
return {SendControlMessage(name.c_str() + 4, value, cr.pid, socket, error)};
}
...
}
static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid,
SocketConnection* socket, std::string* error) {
...
bool queue_success = QueueControlMessage(msg, name, pid, fd); // 将消息加入队列
if (!queue_success && fd != -1) {
uint32_t response = PROP_ERROR_HANDLE_CONTROL_MESSAGE;
TEMP_FAILURE_RETRY(send(fd, &response, sizeof(response), 0));
close(fd);
}
return PROP_SUCCESS;
}
cpp
/* system/core/init/init.cpp */
bool QueueControlMessage(const std::string& message, const std::string& name, pid_t pid, int fd) {
auto lock = std::lock_guard{pending_control_messages_lock};
if (pending_control_messages.size() > 100) {
LOG(ERROR) << "Too many pending control messages, dropped '" << message << "' for '" << name
<< "' from pid: " << pid;
return false;
}
pending_control_messages.push({message, name, pid, fd});
WakeMainInitThread(); // 唤醒主线程!通知 init 主循环处理
return true;
}
在回到system/core/init/init.cpp的SecondStageMain主循环处理:
cpp
/* system/core/init/init.cpp */
int SecondStageMain(int argc, char** argv) {
while (true) {
...
auto epoll_result = epoll.Wait(epoll_timeout); // 等待事件(被 WakeMainInitThread() 唤醒)
if (!epoll_result.ok()) {
LOG(ERROR) << epoll_result.error();
}
if (!IsShuttingDown()) {
HandleControlMessages(); //这里,HandleControlMessages会调用HandleControlMessage
SetUsbController();
}
}
return 0;
}
static bool HandleControlMessage(std::string_view message, const std::string& name,
pid_t from_pid) {
const auto& map = GetControlMessageMap(); //这里,查表获取处理函数,GetControlMessageMap定义在下面
const auto it = map.find(action); // // action = "start"
if (it == map.end()) {
LOG(ERROR) << "Unknown control msg '" << message << "'";
return false;
}
const auto& function = it->second; // 对应启动服务的函数指针
// // 调用实际的 Start 函数
if (auto result = function(service); !result.ok()) {
LOG(ERROR) << "Control message: Could not ctl." << message << " for '" << name
<< "' from pid: " << from_pid << " (" << process_cmdline
<< "): " << result.error();
return false;
}
}
// 查表对应的处理函数
static const std::map<std::string, ControlMessageFunction, std::less<>>& GetControlMessageMap() {
// clang-format off
static const std::map<std::string, ControlMessageFunction, std::less<>> control_message_functions = {
...
{"start", DoControlStart}, // 我们是这个 start
{"stop", DoControlStop},
{"restart", DoControlRestart},
};
// clang-format on
return control_message_functions;
}
static Result<void> DoControlStart(Service* service) {
return service->Start(); //至此,就启动了bootanimation
}
其它
"挂载分区"含义
给物理存储分区分配一个 "可访问的目录路径";
安卓场景的具体例子
比如系统启动时 init.rc 里的这句配置:
bash
mount ext4 /dev/block/system /system ro wait
拆解就是:
ext4:分区的文件系统格式;/dev/block/system:物理存储分区的设备节点;/system:挂载点;ro:挂载为只读。
挂载前:/system 只是一个空目录,/dev/block/system 是一块无法访问的存储;
挂载后:访问 /system/bin/bootanimation 就等于直接读写 /dev/block/system 分区里的 bootanimation 文件。