当前位置:   article > 正文

Android P HIDL服务绑定模式与直通模式的分析_defaultpassthroughserviceimplementation

defaultpassthroughserviceimplementation

 从Android 8.0之后,Android 引入Treble机制,主要是为了解决目前Android 版本之间升级麻烦的问题,将OEM适配的部分vendor与google 对android 大框架升级的部分system部分做了分离,一旦适配了一个版本的vendor信息之后,之后的版本再进行升级时,直接升级system即可,这个就不会给OEM厂商升级带来太大的工作量,直接升级最新功能,可以解决目前市面上Android版本过来凌乱的问题。

  首先Treble机制在Vendor分区中有两种模式,一个编译成so库,供System分区的进程和应用直接加载调用,两者在同一个进程中,这种叫直通式 HAL(passthrough)模式, 另外一种是直接编译成一个daemon可运行的服务,然后System分区的进程通过HwBinder的IPC通信方式来调用,两者在二个独立的进程中,这种称为绑定式HAL(Binderized )模式。

HIDL 初始化
Passthrough

  1. extern "C" IMapper* HIDL_FETCH_IMapper(const char* name){
  2.   return CrallocLoader::load();
  3. }
  4. class GrallocLoader : public V2.0::passthrough::GrallocLoader {
  5. public:
  6. static IMapper* load(){
  7. const hw_module_t* module = loadModule();
  8. auto hal = createHal(module);
  9. return createMapper(std::move(hal));
  10. }
  11.     static const hw_module_t loadModule(){
  12.       const hw_module_t* module;
  13.       int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
  14.       return module;
  15. }
  16.     
  17.     static std::unique_prt<hal::MapperHal> createHal(const hw_module_t* module){
  18.       auto hal = std::make_unique<GrallocHal>();
  19.       return hal->initWithModule(module) ? std::move(hal) : nullptr;
  20.     }
  21. }

直通模式与 绑定模式最大的区别就是直通模式没有一个独立运行的服务进程,而绑定模式是作为一个独立运行的服务相当于Deamon进程在运行。直通模式是将android 8.0之前的版本的module 封装起来,供System以上的服务进行调用, 上层直接调用 HIDL_FETCH_XXX 来调用此接口的。

Binderized 
绑定式可以用两种方式来绑定服务,第一种通过defaultPassthroughServiceImplementation 的调用来注册服务,另外一种是直接调用RegisterAsService来注册服务。

1. defaultPassthroughServiceImplementation 

  1. int main{
  2.   return defaultPassthroughServiceImplementation<IDemo>(4);
  3. //4表示与/dev/hwbinder通信的最大的线程数
  4. }

这个函数的功能是创建默认的IDemo直通服务的实现方式。

  1. status_t defaultPassthroughServiceImplementation(size_t maxThreads = 1){
  2. configureRpcThreadpool(maxThreads, true);
  3. status_t result = registerPassthroughServiceImplementation<IDemo>("default");
  4.      joinRpcThreadpool();
  5.     return UNKOWN_ERROR;
  6. }
  7. status_t registerPassthroughServiceImplementation(String name = "default"){
  8. // Interface 传递进来的是 IComposer
  9. // 1. 获取 IComposer 接口类对象
  10.   sp<IDemo> service = Interface::getService(name, true);
  11.   ....
  12. // 2. 将 IComposer 服务注册到 hwservicemanager 中
  13.   status_t status = service->registerAsService(name);
  14.   return status;
  15. }

将IDemo 实例化一个对象出来, 然后将其与“default”为名称注册到一个服务上。
那我们来看RegisterAsService,这个函数是使用hidl的工具生成的,如下所示:

  1. out/soong/.intermediates/hardware/interfaces/demo/1.0/android.hardware.demo@1.0_genc++/gen/android/hardware/demo/1.0/DemoAll.cpp
  2. ::android::status_t IDemo::registerAsService(const std::string &serviceName){
  3.   ::android::hardware::details::onRegistration("android.hardware.demo@1.0", "IDemo", serviceName);
  4.   const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm = ::android::hardware::defaultServiceManager();
  5. ::android::hardware::Return<bool> ret = sm->add(serviceName.c_str(), this);
  6.   return ret.isOk() && ret ? ::android::OK :: android::UNKNOWN_ERROR;
  7. }

 这里就是将IDemo这个实例 通过IServicemanager的add 接口,添加到服务列表中, 到目前前止,就将defaultPassthroughServiceImplementation 的服务注册过程完成了。

2. RegisterAsService 

  1. int main(){
  2. configureRpcThreadpool(4, true);
  3. Demo mDemo = new Demo();
  4. mDemo.registerAsService();
  5. joinRpcThreadpool();
  6. return 1;
  7. }

这里核心的也是registerAsService(), 此函数之前已经分析过了,就不重复解释了,就是注册一个服务到Service列表中。 

 HIDL的调用
上面已经说明了直通模式与绑定模式的初始化,现在我们来介绍下如何调用直通模式和绑定模式,两者调用的函数有没有什么区别呢? 答案是两者使用的调用接口是一样的,都是通过getService 来调用的。

IMapper mMapper = mapper::V2_0::IMapper::getService()

同样getService 也是HIDL的工具生成的函数执行的:

  1. out/soong/.intermediates/hardware/interfaces/graphics/mapper/2.1/android.hardware.graphics.mapper@2.1_genc++/gen/android/hardware/graphics/mapper/2.1/MapperAll.cpp
  2. ::android::sp<IMapper> IMapper::getService(const std::string &serviceName, const bool getStub){
  3.   return ::android::hardware::details::getServiceInternal<BpHwMapper>(serviceName, true, getStub);
  4. }
  5. sp<IType> getServiceInternal(const std::string & instance, bool retry, bool getStub){
  6. sp<IBase> base = getRawServiceInternal(IType::descriptor, inst/ance, retyr, getStub);
  7. .....
  8. }
  9. sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
  10. const std::string& instance,
  11. bool retry, bool getStub) {
  12. const sp<IServiceManager1_1> sm = defaultServiceManager1_1();
  13. ....
  14. //绑定模式
  15. const bool vintfHwbinder = (transport == Transport::HWBINDER);
  16. //直通模式
  17. const bool vintfPassthru = (transport == Transport::PASSTHROUGH);
  18. ......
  19. //绑定模式
  20. for (int tries = 0; !getStub && (vintfHwbinder || vintfLegacy); tries++) {
  21. Return<sp<IBase>> ret = sm->get(descriptor, instance);
  22. }
  23. //直通模式
  24. if (getStub || vintfPassthru || vintfLegacy) {
  25. const sp<IServiceManager> pm = getPassthroughServiceManager();
  26. sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);
  27. }
  28. ....

这里分成了二条路,绑定模式就直接通过IServiceManager->get的方法去获取,是不是觉得很熟悉,就和AIDL一个套路,通过BpBinder 和 BnBinder 直接对Binder驱动的操作来完成数据交换,但AIDL的binder驱动是/dev/binder, HIDL的hwbinder驱动是/dev/hwbinder,具体的我们就不去详细分析了。关于直通模式,先通过getPassthroughServiceManager ,获取IServiceManager的句柄,然后再get得到对应的服务。

  1. sp<IServiceManager1_0> getPassthroughServiceManager() {
  2. return getPassthroughServiceManager1_1();
  3. }
  4. sp<IServiceManager1_1> getPassthroughServiceManager1_1() {
  5. static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
  6. return manager;
  7. }

这里相当于直接new了一个PassthroughServiceManager(), 之后再调用get 方法:

  1. Return<sp<IBase>> get(const hidl_string& fqName,
  2. const hidl_string& name) override {
  3. sp<IBase> ret = nullptr;
  4. openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
  5. IBase* (*generator)(const char* name);
  6. //这里就会调用 到sym 也就是HIDL_FETCH_XXX ,然后通过dlsym 去链接调用了。
  7. *(void **)(&generator) = dlsym(handle, sym.c_str());
  8. ret = (*generator)(name.c_str());
  9. });
  10. return ret;
  11. }
  12. static void openLibs(
  13. const std::string& fqName,
  14. const std::function<bool /* continue */ (void* /* handle */, const std::string& /* lib */,
  15. const std::string& /* sym */)>& eachLib) {
  16. std::string packageAndVersion = fqName.substr(0, idx);
  17. std::string ifaceName = fqName.substr(idx + strlen("::"));
  18. const std::string prefix = packageAndVersion + "-impl";
  19.      //HIDL_FETCH_XXX 出现了,就是passthrough模式下需要被调用的方法。
  20. const std::string sym = "HIDL_FETCH_" + ifaceName;
  21. .....
  22. std::vector<std::string> paths = {HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR,
  23. halLibPathVndkSp, HAL_LIBRARY_PATH_SYSTEM};
  24. ....
  25. for (const std::string& path : paths) {
  26. std::vector<std::string> libs = search(path, prefix, ".so");
  27. for (const std::string &lib : libs) {
  28.           //路径最后组装成/system 或者/vendor 下面的供调用的xxxxx-impl.so
  29. const std::string fullPath = path + lib;
  30. if (path == HAL_LIBRARY_PATH_SYSTEM) {
  31. //这里就供dlopen了。
  32. handle = dlopen(fullPath.c_str(), dlMode);
  33. } else {
  34. handle = android_load_sphal_library(fullPath.c_str(), dlMode);
  35. }
  36. .....
  37. }
  38. }

到这里就可以看到HIDL_FETCH_XXX的调用过程了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/667226
推荐阅读
相关标签
  

闽ICP备14008679号