HwBinder流程分析

    HwBinder与普通Binder是一样的,区别是前者是专门给硬件使用,后者是给一般的应用程序使用,为了不影响现有的binder,单独增加硬件的HwBinder来实现硬件相关进程的通信。

HwBinder也是有四部分组成:hwservermanager、server、client,driver,其中Driver部分与普通Binder是一样的,《Android图形显示系统》对Binder的原理进行过详细的介绍,这里主要介绍HwBinder与Binder不一样的地方。

服务管理进程

    首先是服务管理进程由HwServiceManager服务,主要流程如下:

/* system/hwservicemanager/service.cpp */

int main() {

    ServiceManager *manager = new ServiceManager();

    if (!manager->add(serviceName, manager)) {}

    TokenManager *tokenManager = new TokenManager();

    if (!manager->add(serviceName, tokenManager)) {}

sp<BnHwServiceManager> service = new BnHwServiceManager(manager);

IPCThreadState::self()->setTheContextObject(service);

ProcessState::self()->becomeContextManager(nullptr, nullptr);

    joinRpcThreadpool();

}

  HwServiceManager与ServiceManager不一样的地方是hwservicemanager有Binder节点,并把Binder节点通过setTheContextObject传给了驱动,并且使用IPCThreadState把主线程加入到线程池来循环处理请求。意味着HwServiceManager是支持并发访问的,可以同时处理多个请求,

服务进程

    Server的开发比较简单,service.cpp的实现比较简单,如下所示。

int main() {

    return defaultPassthroughServiceImplementation<IDemo>();

}

   defaultPassthroughServiceImplementation的实现流程如下。

/* system\libhidl\transport\include\hidl\LegacySupport.h*/

template<class Interface>

__attribute__((warn_unused_result))

status_t defaultPassthroughServiceImplementation(size_t maxThreads = 1) {

    return defaultPassthroughServiceImplementation<Interface>("default", maxThreads);

}

template<class Interface>

__attribute__((warn_unused_result))

status_t defaultPassthroughServiceImplementation(std::string name,

                                            size_t maxThreads = 1) {

    configureRpcThreadpool(maxThreads, true);

    status_t result = registerPassthroughServiceImplementation<Interface>(name);

    joinRpcThreadpool(); 

    return UNKNOWN_ERROR;

}

template<class Interface>

__attribute__((warn_unused_result))

status_t registerPassthroughServiceImplementation(

        std::string name = "default") {

    sp<Interface> service = Interface::getService(name, true /* getStub */);

    status_t status = service->registerAsService(name);

    return status;

}

    最后调registerPassthroughServiceImplementation来注册服务,把Interface替换成IDemo得到以下。

__attribute__((warn_unused_result))

status_t registerPassthroughServiceImplementation(

        std::string name = "default") {

    sp<IDemo> service = IDemo::getService(name, true /* getStub */);

    status_t status = service->registerAsService(name);

    return status;

}

    调用的是IDemo的接口getService得到IDemo节点,通过registerAsServie来添加到服务管理HwServiceManager。

IDemo::getService在DemoAll.cpp实现,该文件是自动生成的,路径如下

out/soong/.intermediates/hardware/interfaces/demo/1.0/android.hardware.demo@1.0_genc++/gen/android/hardware/demo/1.0/DemoAll.cpp 

::android::sp<IDemo> IDemo::getService(const std::string &serviceName, const bool getStub) {

return ::android::hardware::details::getServiceInternal<BpHwDemo>(

serviceName, true, getStub);

}

getService主要通过getServiceInternal来实现,继续往下:

system\libhidl\transport\include\hidl\HidlTransportSupport.h

template <typename BpType, typename IType = typename BpType::Pure,

          typename = std::enable_if_t<std::is_same<i_tag,

typename IType::_hidl_tag>::value>,

          typename = std::enable_if_t<std::is_same<bphw_tag,

typename BpType::_hidl_tag>::value>>

sp<IType> getServiceInternal(const std::string& instance, bool retry, bool getStub) {

    using ::android::hidl::base::V1_0::IBase;

    sp<IBase> base = getRawServiceInternal(IType::descriptor, instance, retry, getStub);

    if (base->isRemote()) {

        // getRawServiceInternal guarantees we get the proper class

        return sp<IType>(new BpType(toBinder<IBase>(base)));

    }

    return IType::castFrom(base);

}

system\libhidl\transport\ServiceManagement.cpp

sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,

                                                  const std::string& instance,

                                                  bool retry,  bool getStub) {

    const sp<IServiceManager> pm = getPassthroughServiceManager();

    sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);

    return base;

}

sp<IServiceManager1_0> getPassthroughServiceManager() {

    return getPassthroughServiceManager1_1();

}

sp<IServiceManager1_1> getPassthroughServiceManager1_1() {

    static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());

    return manager;

}

struct PassthroughServiceManager : IServiceManager1_1 {

    static void openLibs(

        const std::string& fqName,

        const std::function<bool /* continue */ (void* /* handle */, const std::string& /* lib */,

                                                 const std::string& /* sym */)>& eachLib) {

        const std::string sym = "HIDL_FETCH_" + ifaceName;/

    }

    Return<sp<IBase>> get(const hidl_string& fqName,

                          const hidl_string& name) override {

        sp<IBase> ret = nullptr;

        openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {

            IBase* (*generator)(const char* name);

            *(void **)(&generator) = dlsym(handle, sym.c_str());

           ret = (*generator)(name.c_str());

           using ::android::hardware::details::getDescriptor;

           std::string actualFqName = getDescriptor(ret.get());

           registerReference(actualFqName, name);

        });

        return ret;

    }

}

最终通过遍历so加载得到符号HIDL_FETCH_IDemo,并调用得到Demo的对象,在Demo.h已经定义 extern "C" IDemo* HIDL_FETCH_IDemo(const char* name);  在函数前加extern “C”才能使用dlsym 加载到该方法的地址。

下一步Server通过registerAsService把Binder注册到ServiceManager的流程,实现还是在DemoAll.cpp里。

out/soong/.intermediates/hardware/interfaces/demo/1.0/android.hardware.demo@1.0_genc++/gen/android/hardware/demo/1.0/DemoAll.cpp

::android::status_t IDemo::registerAsService(const std::string &serviceName) {

    const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm

            = ::android::hardware::defaultServiceManager();

    ::android::hardware::Return<bool> ret = sm->add(serviceName.c_str(), this);

}

这里也是通过defaultServiceManager找到ServiceManager的索引对象,然后调add接口来添加Demo的对象。

system/hwservicemanager/ServieManager.cpp

Return<bool> ServiceManager::add(const hidl_string& name, const sp<IBase>& service) {

    auto ret = service->interfaceChain([&](const auto &interfaceChain) {

        for(size_t i = 0; i < interfaceChain.size(); i++) {

            const std::string fqName = interfaceChain[i];

            PackageInterfaceMap &ifaceMap = mServiceMap[fqName];

            HidlService *hidlService = ifaceMap.lookup(name);

            if (hidlService == nullptr) {

                ifaceMap.insertService(

                    std::make_unique<HidlService>(fqName, name, service, pid));

            } else {

                hidlService->setService(service, pid);

            }

            ifaceMap.sendPackageRegistrationNotification(fqName, name);

        }

    });

}

在HwServiceManager注册Binder的时候,也是需要name的,不过是通过interfaceChain来获取Demo Binder对象的name。最后把结果保存到ifaceMap里,这里跟ServiceManager只保存Binder的handle也是不一样的。

Server注册服务后,Client进程可以查找到Server的binder对象,并调用相关的接口来向Server请求服务了

客户进程

接下来是客户进程的流程,

int main()

{

    android::sp<IDemo> service = IDemo::getService();

    service->sayHello("HIDL !!!", [&](hidl_string result) {

                printf("get from server %s\n", result.c_str()); });

    return 0;

}

Client进程主要先调IDemo::getService来得到binder对象,并调其方法sayHello,把请求发给Server。

Client进程也通过getService获取Demo索引对象,跟Server进程获取到的Demo节点对象是不太一样的。

out/soong/.intermediates/hardware/interfaces/demo/1.0/android.hardware.demo@1.0_genc++_headers/gen/android/hardware/demo/1.0/IDemo.h

struct IDemo : public ::android::hidl::base::V1_0::IBase {

    static ::android::sp<IDemo> getService(const std::string &serviceName="default", bool getStub=false);

}

    Server进程的registerPassthroughServiceImplementation也使用过getService,只不过getStub为true,这里使用默认参数为false,主要是getRawServiceInternal有区别。

system\libhidl\transport\ServiceManagement.cpp

sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,

                                                             const std::string& instance,

                                                             bool retry, bool getStub) {

    const sp<IServiceManager1_1> sm = defaultServiceManager1_1();

    for (int tries = 0; !getStub && (vintfHwbinder || vintfLegacy); tries++) {

        Return<sp<IBase>> ret = sm->get(descriptor, instance);

        sp<IBase> base = ret;

        return base;

    }

}

getStub为false,会从ServiceManager来查找服务。

system/hwservicemanager/ServieManager.cpp

Return<sp<IBase>> ServiceManager::get(const hidl_string& hidlFqName,

                                      const hidl_string& hidlName) {

    const std::string fqName = hidlFqName;

    const std::string name = hidlName;

    auto ifaceIt = mServiceMap.find(fqName);

    const PackageInterfaceMap &ifaceMap = ifaceIt->second;

    const HidlService *hidlService = ifaceMap.lookup(name);

    sp<IBase> service = hidlService->getService();

    return service;

}

Client进程是从HwManager查询回来的索引对象。原理跟普通的binder一样。只不过这里封装的比普通的Binder要复杂。

上面结合一个简单的例子介绍了HIDL的用法,并解析了相关的代码,HIDL基于hwbinder进行进程间通信。

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值