Android P Surfacelingeer启动bootanimation流程

1.surfaceflinger进程启动

init启动surfaceflinger.rc的过程可以参考 SurfaceFlinger启动流程分析

###xref: /frameworks/native/services/surfaceflinger/surfaceflinger.rc

service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    onrestart restart zygote
    writepid /dev/stune/foreground/tasks
    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

2.surfaceflinger main()函数

main()主要工作

1、SurfaceFlinger首先忽略了SIGPIPE信号,为什么要这么做呢?因为在SurfaceFlinger的Client-Server模型中,或者说IPC机制中,很可能会触发SIGPIPE信号,而这个信号的默认动作是终止进程,并不是我们想要的行为,所以主动对SIGPIPE信号进行处理。
2、接着,开启线程池,不过限制了线程的最大数量为4个,如果线程过多,可能会影响程序性能。
3、随后,创建SurfaceFlinger对象,在其构造函数中,主要是一些成员变量的初始化工作,同时还有一个高逼格的DDMS配置,即Dalvik Debug Monitor Service,是一个调试神器。如果配置了DDMS,就会dlopen libsurfaceflinger_ddmconnection.so,并dlsym其中的DdmConnection_start,最后建立SurfaceFlinger与DDMS的连接。
4、因为这里的SurfaceFlinger对象是一个StrongPointer,所以首先会走到RefBase的onFirstRef,这里就做了一件事情,MessageQueue初始化,保存SurfaceFlinger,并创建了消息队列所需的Looper和Handler。
5、SurfaceFlinger实例化后,设置进程优先级和事务处理策略。
6、然后,进入如下的SurfaceFlinger::init,主要是EGL配置、event线程启动、硬件composer初始化等,而且著名的VSync也在这里出现了。
7、在Android系统中有一个ServiceManager,专门用来管理所有的服务,而SurfaceFlinger不是由ServiceManager启动的,因此需要向ServiceManager注册SurfaceFlinger,同时还注册了GpuService。
8、最后通过SurfaceFlinger::run,进入消息循环,SurfaceFlinger启动成功,开始工作。

##/frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
int main(int, char**) {
    signal(SIGPIPE, SIG_IGN);  //ignore sigpipe信号

    hardware::configureRpcThreadpool(1 /* maxThreads */,
            false /* callerWillJoin */);

    // When SF is launched in its own process, limit the number of
    // binder threads to 4.
    ProcessState::self()->setThreadPoolMaxThreadCount(4);  //限制最大线程数为4

    // start the thread pool
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();

    // instantiate surfaceflinger
    sp<SurfaceFlinger> flinger = new SurfaceFlinger();  //定义为sp指针,执行onFirstRef

    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);


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

    // publish surface flinger
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);

    // publish GpuService
    sp<GpuService> gpuservice = new GpuService();
    sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);

    startDisplayService(); // dependency on SF getting registered above

    // run surface flinger in this thread
    flinger->run();   //运行

    return 0;
}

因为这里的SurfaceFlinger对象是一个StrongPointer,所以首先会走到RefBase的onFirstRef,这里就做了一件事情,MessageQueue初始化,保存SurfaceFlinger,并创建了消息队列所需的Looper和Handler。

void SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);
}
 
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
    mFlinger = flinger;
    mLooper = new Looper(true);
    mHandler = new Handler(*this);

3.surfaceflinger init()函数

void SurfaceFlinger::init() {
    ALOGI(  "SurfaceFlinger's main thread ready to run. "
            "Initializing graphics H/W...");

    Mutex::Autolock _l(mStateLock);   //持mutex lock

    // Inform native graphics APIs whether the present timestamp is supported:
    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");
}

init函数主要工作:
1.初始化OpenGL ES图形库。
2. 创建显示设备的抽象代表,负责和显示设备打交道。
3. 创建显示设备对象。
4. 启动EventThread。监听和处理SurfaceFlinger中的事件。
5.设置软件VSync信号周期。
6.初始化显示设备,调用initializeDisplays完成。
7.启动开机动画,mStartPropertySetThread,只是设置了两个属性,其中一个ctl.start是启动了bootanim进程。

4.通过ctl.start属性启动bootanim

###xref: /frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp
namespace android {

StartPropertySetThread::StartPropertySetThread(bool timestampPropertyValue):
        Thread(false), mTimestampPropertyValue(timestampPropertyValue) {}

status_t StartPropertySetThread::Start() {
    return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
}

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");   //Start BootAnimation
    // Exit immediately
    return false;
}

} // namespace android

5.init进程初始化时注册 property epoll

###xref: /system/core/init/init.cpp
int main(int argc, char** argv) {
    start_property_service();
}

###xref: /system/core/init/property_service.cpp
void start_property_service() {
    selinux_callback cb;
    cb.func_audit = SelinuxAuditCallback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    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);
    if (property_set_fd == -1) {
        PLOG(FATAL) << "start_property_service socket creation failed";
    }

    listen(property_set_fd, 8);

    register_epoll_handler(property_set_fd, handle_property_set_fd); //注册epoll
}

6.处理ctl.start属性变化

###xref: /system/core/init/property_service.cpp
static void handle_property_set_fd() {

    switch (cmd) {
    case PROP_MSG_SETPROP: {
        uint32_t result =
            HandlePropertySet(prop_name, prop_value, socket.source_context(), cr, &error);
        if (result != PROP_SUCCESS) {
            LOG(ERROR) << "Unable to set property '" << prop_name << "' to '" << prop_value
                       << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
                       << error;
        }

        break;
      }

    case PROP_MSG_SETPROP2: {

        uint32_t result = HandlePropertySet(name, value, socket.source_context(), cr, &error);
        if (result != PROP_SUCCESS) {
            LOG(ERROR) << "Unable to set property '" << name << "' to '" << value
                       << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
                       << error;
        }
        socket.SendUint32(result);
        break;
      }
    }
}

7.处理属性ctl.start变化

// 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, std::string* error) {

    if (StartsWith(name, "ctl.")) {   //property_set("ctl.start", "bootanim");
        if (!CheckControlPropertyPerms(name, value, source_context, cr)) {
            *error = StringPrintf("Invalid permissions to perform '%s' on '%s'", name.c_str() + 4,
                                  value.c_str());
            return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
        }

        HandleControlMessage(name.c_str() + 4, value, cr.pid);  //和android n名字一样
        return PROP_SUCCESS;
    }


    return PropertySet(name, value, error);
}

8.处理handlecontrolMessage

HandleControlMessage(name.c_str() + 4, value, cr.pid); 

从名字推断name.c_str() + 4 = ctl.start 也就是start,value = bootanim

### /system/core/init/init.cpp
void HandleControlMessage(const std::string& msg, const std::string& name, pid_t pid) {
    const auto& map = get_control_message_map(); 
    const auto it = map.find(msg);  //msg = start,it应该是{ControlTarget::SERVICE,   DoControlStart}

    const ControlMessageFunction& function = it->second;  //c++ it first是迭代器指向键值,it second是迭代器指向对应的值!

    if (function.target == ControlTarget::SERVICE) {  //if target = start
        //通过bootanim找到对应的service
        Service* svc = ServiceList::GetInstance().FindService(name); 
        if (svc == nullptr) {
            LOG(ERROR) << "No such service '" << name << "' for ctl." << msg;
            return;
        }
        //function.target  function.action  {ControlTarget::SERVICE,   DoControlStart}
        if (auto result = function.action(svc); !result) {
            LOG(ERROR) << "Could not ctl." << msg << " for service " << name << ": "
                       << result.error();
        }

        return;
    }

}

static const std::map<std::string, ControlMessageFunction>& get_control_message_map() {
    // clang-format off
    static const std::map<std::string, ControlMessageFunction> control_message_functions = {
        {"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;
}

9.bootanim start

###xref: /system/core/init/init.cpp
static Result<Success> DoControlStart(Service* service) {
    return service->Start();   //启动对应的service
}

static Result<Success> DoControlStop(Service* service) {
    service->Stop();
    return Success();
}

10.bootanition流程

可参照上一篇博客  Android O 开机动画流程以及制作(c片段和p片段)

猜你喜欢

转载自blog.csdn.net/wd229047557/article/details/81951712
今日推荐