Android 11 开机动画启动流程分析

首先看一下bootanim.rc文件

//frameworks\base\cmds\bootanimation
service bootanim /system/bin/bootanimation
    class core animation
    user graphics
    group graphics audio
    disabled  //代表不启动
    oneshot
    ioprio rt 0
    task_profiles MaxPerformance

disabled 表示 在init阶段,执行 start core 时,不启动bootanim服务。bootanim是在SurfarceFlinger进程中启动,在SurfaceFlinger进程的启动过程中,会调用SurfaceFlinger的init 方法

//frameworks\native\services\surfaceflinger\main_surfaceflinger.cpp

int main(int, char**) {
	//......
    // instantiate surfaceflinger
    sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();

    // initialize before clients can connect
    flinger->init();
    
    //......

//frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
void SurfaceFlinger::init() {
    //......
    mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable);

    if (mStartPropertySetThread->Start() != NO_ERROR) {
        ALOGE("Run StartPropertySetThread failed!");
    }

    ALOGV("Done initializing");
}

在init函数中,创建StartPropertySetThread线程并调用Start函数开启它。

//frameworks\native\services\surfaceflinger\StartPropertySetThread.h
class StartPropertySetThread : public Thread {
// Boot animation is triggered via calls to "property_set()" which can block
// if init's executing slow operation such as 'mount_all --late' (currently
// happening 1/10th with fsck)  concurrently. Running in a separate thread
// allows to pursue the SurfaceFlinger's init process without blocking.
// see b/34499826.
// Any property_set() will block during init stage so need to be offloaded
// to this thread. see b/63844978.
public:
    explicit StartPropertySetThread(bool timestampPropertyValue);
    status_t Start();
//frameworks\native\services\surfaceflinger\StartPropertySetThread.cpp
status_t StartPropertySetThread::Start() {
    return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
}

执行线程类的run函数,导致threadLoop函数被调用

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;
}

设置ctl.start 属性值为bootanim,怎么就能启动bootanim呢? 下面分析一下

在init进程启动的第二阶段过程,会开启属性服务

//system\core\init\init.cpp
int SecondStageMain(int argc, char** argv) {
    //......
    StartPropertyService(&property_fd);
    //......

使用epoll来监听是否有事件可供读入。对于epoll的操作,可以查看system/core/init/epoll.cpp文件

//system\core\init\property_service.cpp
static void PropertyServiceThread() {
    Epoll epoll;
    if (auto result = epoll.Open(); !result.ok()) {//创建监听的fd,
        LOG(FATAL) << result.error();
    }

    if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd);//调用 epoll_ctl,将fd加到检测列表,并且将property_set_fd和handle_property_set_fd存入链表,后面可以通过property_set_fd找到handle_property_set_fd函数
        !result.ok()) {
        LOG(FATAL) << result.error();
    }
    
	//......

    while (true) {
        auto pending_functions = epoll.Wait(std::nullopt);//等待事件,没有事件休眠,有事件时,根据fd找到对应的函数并返回
        if (!pending_functions.ok()) {
            LOG(ERROR) << pending_functions.error();
        } else {
            for (const auto& function : *pending_functions) {
                (*function)();//执行函数
            }
        }
    }
}

调用property_set(“ctl.start”, “bootanim”); 会导致epoll返回,调用handle_property_set_fd函数

//system\core\init\property_service.cpp
static void handle_property_set_fd() {
    //......

    switch (cmd) {
    case PROP_MSG_SETPROP: {
        char prop_name[PROP_NAME_MAX];
        char prop_value[PROP_VALUE_MAX];
		//接收数据
        //......
        uint32_t result =
                HandlePropertySet(prop_name, prop_value, source_context, cr, nullptr, &error);
        //......
      }

对于设置属性,继续调用HandlePropertySet函数

//system\core\init\property_service.cpp
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);
    }
    
    //......

对于ctl. 开头的属性名,调用SendControlMessage,注意,这里传入的socket为null

//system\core\init\property_service.cpp
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);
	
    //......
}

在QueueControlMessage 函数中,将消息放入队列,并唤醒init进程

//system\core\init\init.cpp
bool QueueControlMessage(const std::string& message, const std::string& name, pid_t pid, int fd) {
	//......
    pending_control_messages.push({message, name, pid, fd});
    WakeMainInitThread();
    return true;
}

//写fd
static void WakeMainInitThread() {
    uint64_t counter = 1;
    TEMP_FAILURE_RETRY(write(wake_main_thread_fd, &counter, sizeof(counter)));
}

init进程在启动的第二阶段,无事件时休眠,被唤醒后继续往下执行

//system\core\init\init.cpp
int SecondStageMain(int argc, char** argv) {
    while (true) {
        //......
        
        auto pending_functions = epoll.Wait(epoll_timeout);
        //......
        if (!IsShuttingDown()) {
            HandleControlMessages();
            SetUsbController();
        }
    
 //......   
}

在HandleControlMessages中,查找对应的函数,并执行

//system\core\init\init.cpp
static bool HandleControlMessage(std::string_view message, const std::string& name,
                                 pid_t from_pid) {
  	//......

    const auto& map = GetControlMessageMap();
    const auto it = map.find(action);//根据action,查找对应的函数
  
    const auto& function = it->second;

    if (auto result = function(service); !result.ok()) {//执行函数
        
        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 = {
        {"sigstop_on",        [](auto* service) { service->set_sigstop(true); return Result<void>{}; }},
        {"sigstop_off",       [](auto* service) { service->set_sigstop(false); return Result<void>{}; }},
        {"oneshot_on",        [](auto* service) { service->set_oneshot(true); return Result<void>{}; }},
        {"oneshot_off",       [](auto* service) { service->set_oneshot(false); return Result<void>{}; }},
        {"start",             DoControlStart},
        {"stop",              DoControlStop},
        {"restart",           DoControlRestart},
    };
    // clang-format on

    return control_message_functions;
}

对于start,调用 DoControlStart函数

//system\core\init\init.cpp
static Result<void> DoControlStart(Service* service) {
    return service->Start();
}

调用Start 最终fork一个子进程,并调用ExpandArgsAndExecv函数,执行/system/bin/bootanimation,开机动画就启动起来了

static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
    std::vector<std::string> expanded_args;
    std::vector<char*> c_strings;

    expanded_args.resize(args.size());
    c_strings.push_back(const_cast<char*>(args[0].data()));
    for (std::size_t i = 1; i < args.size(); ++i) {
        auto expanded_arg = ExpandProps(args[i]);
        if (!expanded_arg.ok()) {
            LOG(FATAL) << args[0] << ": cannot expand arguments': " << expanded_arg.error();
        }
        expanded_args[i] = *expanded_arg;
        c_strings.push_back(expanded_args[i].data());
    }
    c_strings.push_back(nullptr);

    if (sigstop) {
        kill(getpid(), SIGSTOP);
    }

    return execv(c_strings[0], c_strings.data()) == 0;//执行
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值