新增HIDL服务
一、HIDL概述
HIDL 是用于指定 HAL 与其用户之间接口的一个接口描述语言,它允许将指定的类型与函数调用收集到接口和包中。更广泛地说,HIDL 是一个可以让那些独立编译的代码库之间进行通信的系统。 HIDL 实际上是用于进行进程间通信的。进程间的通信可以称为 Binder 化。对于必须连接到进程的库,也可以使用 passthough 模式。 HIDL 将指定的数据结构与方法签名组织到接口中,这些接口又会被收集到包中以供使用。
HIDL服务的诞生将system分区和vendor分区可以独立升级变成了可能。
在android在camera框架中,HIDL连接cameraserver和cameraprovider两个进程,直通式的HIDL可以让cameraserver进程访问cameraprovider中的相关库。
二、实现一个HIDL服务:
1、hardware/interfaces目录下创建lethe_hidl/1.0目录,并在此目录下创建一个Ilethe.hal文件
package android.hardware.lethe_hidl@1.0; // 类似于java中包的概念 interface Ilethe { // 添加一个addition_hidl函数,该函数有两个函数a和b,并返回total addition_hidl(uint32_t a, uint32_t b) generates (uint32_t total); };
使用Android提供的工具hidl-gen来生成HIDL框架,执行如下命令:
PACKAGE=android.hardware.lethe_hidl@1.0 LOC=hardware/interfaces/lethe_hidl/1.0/default/ hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
2、再在执行./hardware/interfaces/update-makefiles.sh这个命令,update-makefiles.sh这个脚本目的是为HIDL生成对应Android.bp文件。
3、接着我们还需要在default目录下增加一个空文件service.cpp,用作注册HIDL服务。
4、创建一个test文件夹,用作HIDL服务的测试。
5、需要将该HIDL服务注册到manifest.xml文件中,这样才能被framework所获取和识别到。在vendor/etc/vintf/manifest.xml进行修改push进去之后再重启即可生效。
<hal format="hidl"> <name>android.hardware.lethe_hidl</name> <transport>hwbinder</transport> <version>1.0</version> <interface> <name>Ilethe</name> <instance>default</instance> </interface> <fqname>@1.0::Ilethe/default</fqname> </hal>
在HIDL服务中,我们也可以调用到之前所写的lethe hal模块。
下面是具体代码和详细的解释说明:
1.0目录下的Android.bp:
// This file is autogenerated by hidl-gen -Landroidbp. hidl_interface { // hidl-gen生成的.bp文件 name: "android.hardware.lethe_hidl@1.0", // 名称,在default目录的Android.bp文件引用 root: "android.hardware", // 定义好的package root name vndk: { // vendor ndk enabled: true, }, srcs: [ // 源.hal文件 "Ilethe.hal", ], interfaces: [ // 编译过程中所依赖的接口名称 "android.hidl.base@1.0", ], gen_java: true, // 是否编译为java使用的接口 }
default目录下的Android.bp:
// FIXME: your file license if you have one cc_library_shared { // 编译生成native动态库 name: "android.hardware.lethe_hidl@1.0-impl", // 可执行程序名 relative_install_path: "hw", // 相对路径,和prop进行组合生成路径 proprietary: true, // 编译生成到vendor/lib(64) srcs: [ // 目标文件 "lethe.cpp", ], shared_libs: [ // 编译时依赖的动态库 "libhidlbase", "libhidltransport", "libutils", "android.hardware.lethe_hidl@1.0", "liblog", "libhardware", ], } cc_binary { // 生成bin name:"android.hardware.lethe_hidl@1.0-service", // 程序名 defaults: ["hidl_defaults"], // 引用默认模块名称 relative_install_path: "hw", vendor:true, // 是否放在vendor/etc目录下 srcs: [ "service.cpp", ], shared_libs: [ "libhidlbase", "libhidltransport", "libutils", "android.hardware.lethe_hidl@1.0", "libhardware", "liblog", ], }
lethe.h:
// FIXME: your file license if you have one #pragma once
#include <android/hardware/lethe_hidl/1.0/Ilethe.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
namespace android { namespace hardware { namespace lethe_hidl { namespace V1_0 { namespace 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 lethe : public Ilethe { // Methods from ::android::hardware::lethe_hidl::V1_0::Ilethe follow. Return<uint32_t> addition_hidl(uint32_t a, uint32_t b) override; // Methods from ::android::hidl::base::V1_0::IBase follow. }; // 采用直通式需要将该句的注释打开 // FIXME: most likely delete, this is only for passthrough implementations extern "C" Ilethe* HIDL_FETCH_Ilethe(const char* name); } // namespace implementation } // namespace V1_0 } // namespace lethe_hidl } // namespace hardware } // namespace android
lethe.cpp:
// FIXME: your file license if you have one #include "lethe.h" #include <log/log.h> #include <hardware/hardware.h> //#include "../../../../libhardware/include/hardware/hardware.h" #include "../../../../libhardware/include/hardware/lethe.h" namespace android { namespace hardware { namespace lethe_hidl { namespace V1_0 { namespace implementation { lethe_device_t* lethe_device = NULL; // Methods from ::android::hardware::lethe_hidl::V1_0::Ilethe follow. Return<uint32_t> lethe::addition_hidl(uint32_t a, uint32_t b) { // 返回给更上层使用的接口 // TODO implement uint32_t total = 0; ALOGE("lethe...hal addition_hidl..."); lethe_device->add(lethe_device,(int)a,(int)b,(int *)&total); // 调用lethe hal模块中的lethe_device->add函数 ALOGE("[lethe]======== add 5 + 3 = %d", total); return total; } // Methods from ::android::hidl::base::V1_0::IBase follow. Ilethe* HIDL_FETCH_Ilethe(const char* /* name */) { const lethe_module_t * module = NULL; ALOGE("lethe lethe_module_t"); // lethe_hidl服务注册成功就会在这里实现打印 int ret = hw_get_module(LETHE_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module); if (!ret) { ret = lethe_open_test((const struct hw_module_t*)module,&lethe_device); // 调用到lethe hal模块 } if (ret < 0) { ALOGD("lethe hidl get lethe hal service failed ......."); return NULL; } ALOGE("lethe hidl get lethe hal service success...."); return new lethe(); } // } // namespace implementation } // namespace V1_0 } // namespace lethe_hidl } // namespace hardware } // namespace android
service.cpp
#define LOG_TAG "android.hardware.lethe_hidl@1.0-service" #include <android/hardware/lethe_hidl/1.0/Ilethe.h> #include <hidl/LegacySupport.h> // Generated HIDL files using android::hardware::lethe_hidl::V1_0::Ilethe; // 参照camera的命名空间的用法,namespace implementation可以忽略 using android::hardware::defaultPassthroughServiceImplementation; // 直通式 int main() { // 注册hidl服务是,就是通过"HIDL_FETCH_"与"Ilethe"字符串得到的 return defaultPassthroughServiceImplementation<Ilethe>(); // ()中可以加线程池线程的个数等信息 }
test目录下的Android.bp:
cc_binary { name: "lethe_hidl_test", srcs: ["lethe_hidl_test.cpp"], shared_libs: [ "liblog", "android.hardware.lethe_hidl@1.0", "libhidlbase", "libhidltransport", "libhwbinder", "libutils", ], }
lethe_hidl_test.cpp
#include <android/hardware/lethe_hidl/1.0/Ilethe.h> #include <hidl/LegacySupport.h> #include <log/log.h> using android::sp; using android::hardware::lethe_hidl::V1_0::Ilethe; using android::hardware::Return; int main(){ android::sp<Ilethe> hw_device = Ilethe::getService(); // 获取HDIL服务 if (hw_device == nullptr) { ALOGD("lethe...failed to get lethe-hidl"); return -1; } ALOGD("lethe...success to get lethe-hidl...."); Return<uint32_t> total = hw_device->addition_hidl(3,4); // 调用HIDL函数 return 0; }