camera启动之---HwServiceManager进程启动过程(1)

序言


安卓机器开机会先加载kernel驱动,上层是先启动CameraProvider加载camerahal。
之后cameraservice会获取cameraprovider。应用调用的时候camera2 api会获取cameraservice,然后通过cameraprovider访问hal,hal最终访问到驱动。
后续文章会说明
cameraprovider启动hal
hal3加载过程
cameraserver如何连接cameraprovider
为了介绍CameraProvider启动过程,有必要简单说下HwServiceManager进程,因为CameraProvider会注册到HwServiceManager中,是各个硬件进程服务的管理器。
HwServiceManager 进程由 init 进程启动脚本hwservicemanager.rc
目录在system/hwservicemanager/hwservicemanager.rc
我们直接看服务main函数,在system/hwservicemanager/service.cpp

int main() {
    configureRpcThreadpool(1, true /* callerWillJoin */);//1

    sp<ServiceManager> manager = new ServiceManager();
    setRequestingSid(manager, true);

    if (!manager->add(serviceName, manager)) {//2
        ALOGE("Failed to register hwservicemanager with itself.");
    }

    TokenManager *tokenManager = new TokenManager();

    if (!manager->add(serviceName, tokenManager)) {
        ALOGE("Failed to register ITokenManager with hwservicemanager.");
    }

    // Tell IPCThreadState we're the service manager
    sp<BnHwServiceManager> service = new BnHwServiceManager(manager);//3
    IPCThreadState::self()->setTheContextObject(service);
    // Then tell the kernel
    ProcessState::self()->becomeContextManager(nullptr, nullptr);

    int rc = property_set("hwservicemanager.ready", "true");
    if (rc) {
        ALOGE("Failed to set \"hwservicemanager.ready\" (error %d). "\
              "HAL services will not start!\n", rc);
    }

    ALOGI("hwservicemanager is ready now.");
    joinRpcThreadpool();

    return 0;
}

1

/system/libhidl/transport/HidlTransportSupport.cpp
configureRpcThreadpool()-(直接调用)> configureBinderRpcThreadpool-(直接调用)>
/system/libhidl/transport/HidlBinderSupport.cpp
ProcessState::self()->setThreadPoolConfiguration
函数实现在
/system/libhwbinder/ProcessState.cpp

status_t ProcessState::setThreadPoolConfiguration(size_t maxThreads, bool callerJoinsPool) {
…….
size_t kernelMaxThreads = maxThreads - 1;
//告诉kernel最多能创建几个线程,这个是配置线程池
    if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &kernelMaxThreads) != -1) {
        AutoMutex _l(mLock);
        mMaxThreads = maxThreads;
        mSpawnThreadOnStart = !callerJoinsPool;
    } else {……. }
    return result;
}

实际上是向驱动层ioctl,mDriverFD是打开节点,可以接下来看
ProcessState::self()调用gProcess = new ProcessState(DEFAULT_BINDER_VM_SIZE);
DEFAULT_BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)

ProcessState::ProcessState(size_t mmap_size)
: mDriverFD(open_driver())
……
 , mMmapSize(mmap_size)
{
    if (mDriverFD >= 0) {
    // mmap the binder, providing a chunk of virtual address space to receive transactions.
//这个进程的Binder内核内存上限就是BINDER_VM_SIZE
        mVMStart = mmap(0, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
   ……

static int open_driver()
{
    int fd = open("/dev/hwbinder", O_RDWR | O_CLOEXEC);

所以通过打开/dev/hwbinder节点,mmap一段虚拟内存,建立私有映射,用于binder通信接收数据。
更多的可能需要到底层去看下这个节点相关创建以及ioctl的用法

2

system/hwservicemanager/ServiceManager.cpp
manager->add(serviceName, manager)
这个类没有看到构造函数,
static std::string serviceName = “default”;
自己是manager同样也是server,所以将自己加入管理器

Return<bool> ServiceManager::add(const hidl_string& name, const sp<IBase>& service) {
……
        for(size_t i = 0; i < interfaceChain.size(); i++) {
            const std::string fqName = interfaceChain[i];

            PackageInterfaceMap &ifaceMap = mServiceMap[fqName];
            HidlService *hidlService = ifaceMap.lookup(name);
	//将服务插入ifaceMap
            if (hidlService == nullptr) {
                ifaceMap.insertService(
                    std::make_unique<HidlService>(fqName, name, service, callingContext.pid));
            } 

如果ifaceMap找不到要添加名字的服务,将当前服务插入ifaceMap
manager->add(serviceName, tokenManager)

后面再加入一个tokenManager。

3

out/soong/.intermediates/system/libhidl/transport/manager/1.1/android.hidl.manager@1.1_genc++/gen/android/hidl/manager/1.1/ServiceManagerAll.cpp

BnHwServiceManager::BnHwServiceManager(const ::android::sp<IServiceManager> &_hidl_impl)
        : ::android::hidl::base::V1_0::BnHwBase(_hidl_impl, "android.hidl.manager@1.1", "IServiceManager") { 
            _hidl_mImpl = _hidl_impl;
            auto prio = ::android::hardware::details::gServicePrioMap.get(_hidl_impl, {SCHED_NORMAL, 0});
            mSchedPolicy = prio.sched_policy;
            mSchedPriority = prio.prio;
            setRequestingSid(::android::hardware::details::gServiceSidMap.get(_hidl_impl, false));
}

创建一个BnHwServiceManager对象,_hidl_mImpl保存的是ServiceManager实例。
system\libhwbinder\ IPCThreadState.cpp

void IPCThreadState::setTheContextObject(sp<BHwBinder> obj)
{
    mContextObject = obj;//赋值变量
}

4

ProcessState::self()->becomeContextManager(nullptr, nullptr);
主要调用result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
将本进程设置为binder系统的管理进程,只有servicemanager进程才会使用这个命令且只能调用一次。
看资料设置下去会生成节点,成为servicemanager在binder驱动的实体,现在不去关心,有机会看驱动在了解

5

/system/libhidl/transport/HidlTransportSupport.cpp
joinRpcThreadpool-(直接调用)-> joinBinderRpcThreadpool-(直接调用)-> IPCThreadState::self()->joinThreadPool()
进入到/system/libhwbinder/IPCThreadState.cpp
这个整体是个循环,用于接收消息,处理消息

void IPCThreadState::joinThreadPool(bool isMain)
{
……
    do {
        processPendingDerefs();//mPendingWeakDerefs和mPendingStrongDerefs中的指针引用减一
        // now get the next command to be processed, waiting if necessary
        result = getAndExecuteCommand();
	……
    } while (result != -ECONNREFUSED && result != -EBADF);

后面调用情况

status_t IPCThreadState::getAndExecuteCommand()
{…
    result = talkWithDriver();
……
result = executeCommand(cmd);
status_t IPCThreadState::talkWithDriver(bool doReceive)
{……
    // Return immediately if there is nothing to do. 不需要读写,直接返回
    if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
    do {..
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
status_t IPCThreadState::executeCommand(int32_t cmd)
{
……
    case BR_TRANSACTION:
        {
        ……
        error = mContextObject->transact(tr.code, buffer, &reply, tr.flags, reply_callback);

用binder驱动进行读写,读出来之后,执行executeCommand,判断命令执行对应的函数。
case BR_TRANSACTION 是比较重要的case,接收驱动的回应。
mContextObject->transact(tr.code, buffer, &reply, tr.flags, reply_callback);
mContextObject 就是我们前面设置的 BnHwServiceManager ,调用父类函数binder.cpp

status_t BHwBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags, TransactCallback callback)
{    switch (code) {
        default:
            /* BnHwServiceManager 实现了 onTransact() */
            err = onTransact(code, data, reply, flags,
 [&](auto &replyParcel) {
                        replyParcel.setDataPosition(0);

ServiceManagerAll.cpp
::android::status_t BnHwServiceManager::onTransact 实现这个函数
So,管理服务线程就这样创建,进入循环 写入和度读取。

总结:
创建过程
1)首先打开“/dev/hwbinder”设备文件,映射内存
2)利用BINDER_SET_CONTEXT_MGR命令,让自己成为管理者 ServiceManager。维护service列表
3)进入一个无限循环,等待Client的请求到来。
通信过程
1) 整个进程间通信的大部分工作都是通过 open(), mmap()和 ioctl()等文件操作,在内核空间与用户空间中操作,来实现的
2) Binder驱动在内核空间中创建了一个Binder节点,隶属于Server们的进程,并分配一个句柄,给ServiceManager维护
3) Client通信,只要发送服务名字和数据包,发送给binder驱动,然后将包丢给ServiceManager,ServiceManager寻找服务返回句柄,返回给client。然后client就可以通过句柄通信。

关于这部分我也只是简单看了下,并没有深入,如果只学习camera部分可以当做黑盒,其实这就是服务的管理器,也是个服务,服务的本质就是响应客户端(比如cmaera provider)请求。要提供服务,就要循环接收请求,处理请求,应答客服端。这个hidl和aidl,本质都是一样的,通过底层节点传输数据,一边Transact,另一边onTransact ,实现进程间的通信。

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页