Binder学习笔记-4——binder service实现框架

发布时间 2023-10-26 17:01:18作者: Hello-World3

一、一个HIDL binder服务的例子

1. 实现源码

/hardware/interfaces/graphics/composer/2.3/default/service.cpp

#include <binder/ProcessState.h>

int main() {
    android::ProcessState::initWithDriver("/dev/vndbinder");
    android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
    android::ProcessState::self()->startThreadPool();

    android::hardware::configureRpcThreadpool(4, true /* will join */);

    android::sp<IComposer> composer = HwcLoader::load();
    composer->registerAsService();

    android::hardware::joinRpcThreadpool();

    ALOGE("service is terminating");
    return 1;
}

可以看出包含的是哪个头文件,直接通过 ProcessState 进行使用的是 libs/binder 下的接口。
/system/libhwbinder/include/hwbinder/ProcessState.h
/frameworks/native/libs/binder/include/binder/ProcessState.h

通过 android::ProcessState:: 进行引用,是因为接口函数定义在 namespace android { 下。


2. 各函数调用路径

/system/libhidl/transport/HidlTransportSupport.cpp
//一套接口
/frameworks/native/libs/binder/ProcessState.cpp
/frameworks/native/libs/binder/IPCThreadState.cpp
//第二套接口
/system/libhwbinder/ProcessState.cpp
/system/libhwbinder/IPCThreadState.cpp

ProcessState::self() 返回一个每进程的单例模式的 ProcessState("/dev/vndbinder"或 "/dev/binder") 结构。


(1) initWithDriver

android::ProcessState::initWithDriver("/dev/vndbinder");
    new ProcessState(driver);
        open_driver(driver)
        mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);


(2) setThreadPoolMaxThreadCount

android::ProcessState::self()->setThreadPoolMaxThreadCount(4) //service.cpp
    ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) //ProcessState.cpp
        ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads)
        mMaxThreads = maxThreads;


(3) startThreadPool

android::ProcessState::self()->startThreadPool()
    ProcessState::startThreadPool() //ProcessState.cpp
        mThreadPoolStarted = true;
        spawnPooledThread(true) //ProcessState.cpp
            makeBinderThreadName() //ProcessState.cpp 构建binder线程名"Binder:PID_X"
                sp<Thread> t = new PoolThread(true); //只是将参数true赋值给PoolThread::mIsMain
                t->run(name.string());
                    PoolThread::threadLoop()
                        IPCThreadState::self()->joinThreadPool(mIsMain)
                            mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
                            do { //在这里循环处理
                                result = getAndExecuteCommand();
                                if(result == TIMED_OUT && !isMain)
                                    break;
                            } while (result != -ECONNREFUSED && result != -EBADF);
                            mOut.writeInt32(BC_EXIT_LOOPER); //下面是出错后的返回清理
                            talkWithDriver(false);

这就是将主线程变成一个binder线程了。


(4) configureRpcThreadpool

android::hardware::configureRpcThreadpool(4, true /* will join */); //这个是调用 namespace android{ namespace hardware ( 中定义的函数
    configureRpcThreadpool(size_t maxThreads, bool callerWillJoin) //HidlTransportSupport.cpp 此例 callerWillJoin=true
        configureBinderRpcThreadpool(maxThreads, callerWillJoin);
            ProcessState::self()->setThreadPoolConfiguration(maxThreads, callerWillJoin /*callerJoinsPool*/);
                ProcessState::setThreadPoolConfiguration(size_t maxThreads, bool callerJoinsPool) //libhwbinder//ProcessState.cpp
                    size_t threadsToAllocate = maxThreads;
                    if (callerJoinsPool) threadsToAllocate--; //若主线程加入,这4个中已经包含了加入的主线程 是不是只有hwbinder的会减去主线程的?
                    if (threadsToAllocate > 0) threadsToAllocate--; //【1】为啥又减去一个了呢?
                    ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &threadsToAllocate)

【1】位置是这么注释的:如果可以的话,在线程池启动时从用户空间生成一个线程。 这确保了线程池启动后始终有一个线程可用于启动更多线程。


(5) joinRpcThreadpool

android::hardware::joinRpcThreadpool(); 
    joinRpcThreadpool() //HidlTransportSupport.cpp
        joinBinderRpcThreadpool()
            IPCThreadState::self()->joinThreadPool()
                mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
                do { //在这里循环处理
                    result = getAndExecuteCommand();
                    if(result == TIMED_OUT && !isMain)
                        break;
                } while (result != -ECONNREFUSED && result != -EBADF);
                mOut.writeInt32(BC_EXIT_LOOPER); //下面是出错后的返回清理
                talkWithDriver(false);

TODO: 为啥会高重复两套操作呢? 一个是vnd的一个是hwbinder的?