使用hidl-gen直接生成ICustomHardware接口的实现类CustomHardware.cpp,命令如下
flagstaff@flagstaff-pc:~/aosp_r.lns$ hidl-gen -L c++-impl -o test/flagstaffTest/hardware/interfaces/custom_hardware/1.0/default -r flagstaff.hardware:test/flagstaffTest/hardware/interfaces flagstaff.hardware.custom_hardware@1.0
成功执行后,目录结构如下
flagstaff@flagstaff-pc:~/aosp_r.lns/test/flagstaffTest/hardware/interfaces/custom_hardware/1.0$ tree . ├── Android.bp ├── default │ ├── CustomHardware.cpp │ └── CustomHardware.h └── ICustomHardware.hal1.2 CustomHardware.h
使用hidl-gen确实为我们省略了不少的工作量。
#pragma once #include#include #include #include namespace flagstaff::hardware::custom_hardware::implementation { using ::android::hardware::hidl_array; using ::android::hardware::hidl_memory; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::sp; struct CustomHardware : public V1_0::ICustomHardware { private: const std::string mName; public: CustomHardware(const std::string& name); Return enableHardware(bool data) override; const std::string& getName(); }; }
命名空间:
CustomHardware的命名空间为如下,该命名空间由ICustomHardware.hal中的package转化而来,规则很简单,就是将packge中的.用::来替换,对于实现类后跟implementation。
//file:ICustomHardware.hal package flagstaff.hardware.custom_hardware@1.0; //CustomHardware.h namespace flagstaff::hardware::custom_hardware::implementation
HIDL中的后端大都是cpp来写的,这里实在没看懂为什么HIDL中喜欢用package加点的方式。
类定义:
下面是CustomHardware的类继承关系图,顶层的父类为Refbase,可见CustomHardware是支持强弱指针的。
返回值–Return
Return实际上是一个模板类,方便调用者捕获远程调用状态的。并且如果Client本次远程调用失败且不调用Return.isOk检查的话,HIDL框架则会强制kill掉当前进程。其定义如下
//file:systemlibhidlbaseincludehidlStatus.h class Status final { public: ... bool isOk() const { return mException == EX_NONE; } }; class return_status { private: Status mStatus {}; public: bool isOk() const { mCheckedStatus = true; return mStatus.isOk(); } }; templateclass Return : public details::return_status { ... };
因为Return重载了符号,所以使用时直接当作原类型即可,如此处为boolean类型。
1.3 CustomHardware.cpp测试用,所以在方法enableHardware中打印值来验证是否调用成功即可,代码如下
#include "CustomHardware.h" #include namespace flagstaff::hardware::custom_hardware::implementation { CustomHardware::CustomHardware(const std::string& name):mName(name) { } const std::string& CustomHardware::getName(){ return mName; } ReturnCustomHardware::enableHardware(bool data) { LOG(ERROR)<<"[service]"< mName用于验证单接口多实例功能,此处可以直接忽略。可见最终接口enableHardware被调用时会打印入参和被调用的实例名称。
2.HIDL实例的注册前面提过,远程调用模型就是C/S模型,对于调用者也就是Client端,其也可是一个常驻的后台服务也可以是单次调用命令。但是实现端其必须是一个常驻后台的server,下面则是HIDL server的一种写法。
#include#include #include #include using flagstaff::hardware::custom_hardware::implementation::CustomHardware; using flagstaff::hardware::custom_hardware::V1_0::ICustomHardware; int main(int , char** ) { ::android::hardware::configureRpcThreadpool(5, true); android::sp instance = new CustomHardware("default"); if (instance->registerAsService() != ::android::OK) { LOG(ERROR)<<"Failed to register ICustomHardware default instance"; return -1; } android::sp instance1 = new CustomHardware("custom"); if (instance->registerAsService("custom") != ::android::OK) { LOG(ERROR)<<"Failed to register ICustomHardware custome instance"; return -1; } LOG(INFO)<<"The instance of CustomHardware is registered to hwmanager in success."; ::android::hardware::joinRpcThreadpool(); return 1; // joinRpcThreadpool shouldn't exit } configureRpcThreadpool
用于设置server的线程池数量,每一次client端调用,Server都会对应一个线程去处理client的调用请求。如果client的请求数量小于等于此处设置的5,那么这5次调用实际上就是并行的,即使此处的接口没有设置oneway关键字,所以实现接口的时候要考虑并发。
本次的server则是为ICustomHardware接口注册了两个实例,并且其命名分别为default/custom,其中registerAsService无入参的时候默认为defalut,其代码如下//file:outsoong.intermediatestestflagstaffTesthardwareinterfacescustom_hardware1.0flagstaff.hardware.custom_hardware@1.0_genc++_headersgenflagstaffhardwarecustom_hardware1.0ICustomHardware.h namespace flagstaff { namespace hardware { namespace custom_hardware { namespace V1_0 { struct ICustomHardware : public ::android::hidl::base::V1_0::Ibase { ... __attribute__ ((warn_unused_result))::android::status_t registerAsService(const std::string &serviceName="default"); ... };joinRpcThreadpool
3.Android.bp
该函数实际上等同于thread->join(),并且binder线程是在死循环中轮询client是否发送消息过来的,所以并不会返回,正常情况下server也就不会退出。Android团队推荐使用Android.bp来编写编译规则,因此此处也使用Android.bp。
cc_binary { name: "flagstaff.hardware.custom_hardware@1.0-service", defaults: ["hidl_defaults"], vendor: true, relative_install_path: "hw", srcs: [ "service.cpp", "src/*.cpp", ], init_rc: ["flagstaff.hardware.custom_hardware@1.0-service.rc"], local_include_dirs: [ "include", ], shared_libs: [ "libbinder", "libhidlbase", "libbase", "libutils", "libcutils", "liblog", "flagstaff.hardware.custom_hardware@1.0", ], cppflags:[ "-Wno-unused-parameter", "-DLOG_TAG="flagstaff.hardware.custom_hardware"", ], vintf_fragments: ["flagstaff.hardware.custom_hardware@1.0.xml"], }对于其中关键字的解释AOSP自带的文档已经解释的很详细了,所以就不赘诉了,注意只有编译后才会生成。
flagstaff@flagstaff-pc:~/aosp_r.lns/out/soong/docs$ ls cc.html cc.html额外说明下,如果熟悉Android.mk的写法,想学习Android.bp的写法,可以使用AOSP自带的工具androidmk来将Android.mk转化为Android.bp来对比学习,下面是其简略使用说明
flagstaff@flagstaff-pc:~/aosp_r.lns$ androidmk usage: androidmk [flags]androidmk parses as an Android.mk file and attempts to output an analogous Android.bp file (to standard out) 另外如果有问题,欢迎留言或者email(836190520@qq.com)我,技术升级在于交流~~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)