1、环境准备
首先准备一份Android源码。
#源码中编译生成hidl-gen
make hidl-gen
下面是hidl-gen的语法:
usage: hidl-gen [-p
Process FQNAME, PACKAGE(.SUBPACKAGE)*@[0-9]+.[0-9]+(::TYPE)?, to create output.
-h: Prints this menu.
-L
check : Parses the interface to see if valid but doesn't write any files.
c++ : (internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.
c++-headers : (internal) Generates C++ headers for interface files for talking to HIDL interfaces.
c++-sources : (internal) Generates C++ sources for interface files for talking to HIDL interfaces.
export-header : Generates a header file from @export enumerations to help maintain legacy code.
c++-impl : Generates boilerplate implementation of a hidl interface in C++ (for convenience).
c++-impl-headers: c++-impl but headers only.
c++-impl-sources: c++-impl but sources only.
c++-adapter : Takes a x.(y+n) interface and mocks an x.y interface.
c++-adapter-headers: c++-adapter but helper headers only.
c++-adapter-sources: c++-adapter but helper sources only.
c++-adapter-main: c++-adapter but the adapter binary source only.
java : (internal) Generates Java library for talking to HIDL interfaces in Java.
java-constants : (internal) Like export-header but for Java (always created by -Lmakefile if @export exists).
vts : (internal) Generates vts proto files for use in vtsd.
makefile : (removed) Used to generate makefiles for -Ljava and -Ljava-constants.
androidbp : (internal) Generates Soong bp files for -Lc++-headers, -Lc++-sources, -Ljava, -Ljava-constants, and -Lc++-adapter.
androidbp-impl : Generates boilerplate bp files for implementation created with -Lc++-impl.
hash : Prints hashes of interface in `current.txt` format to standard out.
function-count : Prints the total number of functions added by the package or interface.
dependencies : Prints all depended types.
-O
-o
2、创建hidl
在vendor/qcom/proprietary/interfaces下创建howie目录,在howie下创建1.0目录,在1.0目录下创建接口IHowie.hal,包名设置为自定义vendor.oem.hardware.howie的创建目录default。
package [email protected];
interface IHowie{
helloWorld(string name) generates (string result);
};
这时候,目录结构为:
howie/
└── 1.0
├── default
└── IHowie.hal
在1.0下写一个hidl-gen.sh脚本
# -o
运行后,目录结构为:
.
└── 1.0
├── Android.bp
├── default
│ ├── Android.bp
│ ├── Howie.cpp
│ └── Howie.h
├── hidl-gen.sh
└── IHowie.hal
2 directories, 6 files
1.0目录下的Android.bp
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
name: "[email protected]",
root: "vendor.qcom.hardware",
system_ext_specific: true,
srcs: [
"IHowie.hal",
],
interfaces: [
"[email protected]",
],
gen_java: true,
}
我们稍作修改
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
name: "[email protected]",
root: "vendor.qcom.hardware.howie",
required: ["manifest_vendor.qcom.hardware.howie.xml"],
//vendor: true,
srcs: [
"IHowie.hal",
],
interfaces: [
"[email protected]",
],
gen_java: true,
}
1.0/default目录下的Android.bp
// FIXME: your file license if you have one
cc_library_shared {
// FIXME: this should only be -impl for a passthrough hal.
// In most cases, to convert this to a binderized implementation, you should:
// - change '-impl' to '-service' here and make it a cc_binary instead of a
// cc_library_shared.
// - add a *.rc file for this module.
// - delete HIDL_FETCH_I* functions.
// - call configureRpcThreadpool and registerAsService on the instance.
// You may also want to append '-impl/-service' with a specific identifier like
// '-vendor' or '-
name: "[email protected]",
relative_install_path: "hw",
// FIXME: this should be 'vendor: true' for modules that will eventually be
// on AOSP.
proprietary: true,
srcs: [
"Howie.cpp",
],
shared_libs: [
"libhidlbase",
"libutils",
"[email protected]",
],
}
稍作修改
cc_library_shared {
// FIXME: this should only be -impl for a passthrough hal.
// In most cases, to convert this to a binderized implementation, you should:
// - change '-impl' to '-service' here and make it a cc_binary instead of a
// cc_library_shared.
// - add a *.rc file for this module.
// - delete HIDL_FETCH_I* functions.
// - call configureRpcThreadpool and registerAsService on the instance.
// You may also want to append '-impl/-service' with a specific identifier like
// '-vendor' or '-
name: "[email protected]",
//relative_install_path: "hw",
// FIXME: this should be 'vendor: true' for modules that will eventually be
// on AOSP.
vendor: true,
srcs: [
"Howie.cpp",
],
shared_libs: [
"libhidlbase",
"libutils",
"[email protected]",
],
}
Howie.h
// FIXME: your file license if you have one
#pragma once
#include
#include
#include
namespace vendor::qcom::hardware::howie::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 Howie : public V1_0::IHowie {
// Methods from ::vendor::qcom::hardware::howie::V1_0::IHowie follow.
Return
// Methods from ::android::hidl::base::V1_0::IBase follow.
};
// FIXME: most likely delete, this is only for passthrough implementations
// extern "C" IHowie* HIDL_FETCH_IHowie(const char* name);
} // namespace vendor::qcom::hardware::howie::implementation
Howie.cpp
// FIXME: your file license if you have one
#include "Howie.h"
namespace vendor::qcom::hardware::howie::implementation {
// Methods from ::vendor::qcom::hardware::howie::V1_0::IHowie follow.
Return
// TODO implement
return Void();
}
// Methods from ::android::hidl::base::V1_0::IBase follow.
//IHowie* HIDL_FETCH_IHowie(const char* /* name */) {
//return new Howie();
//}
//
} // namespace vendor::qcom::hardware::howie::implementation
如上面的注释所说,如果将下面的几行注释去掉,hidl将采用直通式通信方式。
// extern "C" IHowie* HIDL_FETCH_IHowie(const char* name);
//IHowie* HIDL_FETCH_IHowie(const char* /* name */) {
//return new Howie();
//}
下面,润色一下Howie.cpp
// FIXME: your file license if you have one
#include "Howie.h"
namespace vendor::qcom::hardware::howie::implementation {
// Methods from ::vendor::qcom::hardware::howie::V1_0::IHowie follow.
Return
char buf[128];
::memset(buf, 0, 128);
::snprintf(buf, 128, "Hello World, %s", name.c_str());
hidl_string result(buf);
_hidl_cb(result);
return Void();
}
// Methods from ::android::hidl::base::V1_0::IBase follow.
//IHowie* HIDL_FETCH_IHowie(const char* /* name */) {
//return new Howie();
//}
//
} // namespace vendor::qcom::hardware::howie::implementation
我希望hidl接口和实现都编译到vendor分区,因此需要做出一点改动:
[email protected]的root修改为"vendor.qcom.hardware.howie";
将1.0/Android.bp的"system_ext_specific: true,"改成"vendor: true,";
将1.0/default/Android.bp的"proprietary: true,"改成"vendor: true,",后面碰到编译问题,这一行可以注释掉;
[email protected]移除relative_install_path: "hw",因为会碰到找不到该动态库的问题;
除此以外,在howie目录下新增Android.bp
subdirs = [
"1.0",
]
hidl_package_root {
name: "vendor.qcom.hardware.howie",
path: "vendor/qcom/proprietary/interface/howie",
}
3、构建service
为了能调用到先前创建的hidl接口,我们在default下面再创建一个service.cpp,通过直通式注册服务。
#define LOG_TAG "[email protected]"
#include
#include
using vendor::qcom::hardware::howie::V1_0::IHowie;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
return defaultPassthroughServiceImplementation
}
绑定式写法:
#define LOG_TAG "[email protected]"
#include
#include "android/log.h"
#include
#include
#include
#include
#include
#include "Howie.h"
using vendor::qcom::hardware::howie::V1_0::IHowie;
using vendor::qcom::hardware::howie::implementation::Howie;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;
using android::status_t;
using android::OK;
int main() {
configureRpcThreadpool(10, true);
sp
status_t status = howie->registerAsService();
LOG_ALWAYS_FATAL_IF(status != OK, "Could not register IHowie");
// other interface registration comes here
joinRpcThreadpool();
return 0;
}
同时在default目录下创建rc文件——[email protected],用于启动[email protected]。
service howie_service /vendor/bin/hw/[email protected]
class hal
user system
group system
由于新增了两个文件,想要将这两个文件也编进系统,需要再次编辑1.0/default下的Android.bp,如下为新增的:
//新增如下
cc_binary {
name: "[email protected]",
defaults: ["hidl_defaults"],
vendor: true,
relative_install_path: "hw",
srcs: ["service.cpp"],
init_rc: ["[email protected]"],
shared_libs: [
"libhidlbase",
"libhidltransport",
"libutils",
"liblog",
"[email protected]",
"[email protected]",
],
}
4、设备清单和框架清单
为了能为server被client访问到,在howie目录下新增目录vintf,在vintf目录下新增设备清单manifest_vendor.qcom.hardware.howie.xml和框架清单vendor_framework_compatibility_matrix.xml。
将两个清单文件加入编译,新增vendor_framework_compatibility_matrix.mk
DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE += \
vendor/qcom/proprietary/interface/howie/vintf/vendor_framework_compatibility_matrix.xml
新增Android.bp
prebuilt_etc_xml {
name: "manifest_vendor.qcom.hardware.howie.xml",
src: "manifest_vendor.qcom.hardware.howie.xml",
vendor: true,
installable: true,
sub_dir: "vintf/manifest",
}
同时,为了vintf下新增的vendor_framework_compatibility_matrix.mk被编译到,在howie目录下新增Android.mk
LOCAL_PATH := $(call my-dir)
include $(call all-makefiles-under,$(LOCAL_PATH))
将vintf也加入到howie下的Android.bp
subdirs = [
"1.0",
"vintf",
]
5、新增测试client
在1.0目录下新增test目录,在test下面新增如下文件:
HowieTest.cpp
#include
#include
#include
#include
#include
#include
using ::android::hardware::hidl_string;
using ::android::sp;
using vendor::qcom::hardware::howie::V1_0::IHowie;
int main(){
android::sp
if (service == nullptr){
printf("Failed to get service\n");
return -1;
}
service->helloWorld("Howie", [&](hidl_string result){
printf("%s\n", result.c_str());
});
return 0;
}
Android.bp
cc_binary {
name: "howie_client",
defaults: ["hidl_defaults"],
vendor: true,
relative_install_path: "hw",
srcs: ["HowieTest.cpp"],
shared_libs: [
"liblog",
"libhardware",
"libhidlbase",
"libhidltransport",
"libutils",
"[email protected]",
],
}
重新修改目录howie下的Android.bp,将test加入其中。
subdirs = [
"1.0",
"vintf",
"test",
]
6、编译
mmm vendor/qcom/proprietary/interfaces/howie
按照之前的编译规则,我们可以在以下的路径中找到编译产物,out/target/product/${PRODUCT}/下,找到这些产物后,push到手机对应目录下即可:
/vendor/lib64/[email protected]
/vendor/lib64/[email protected]
/vendor/bin/hw/[email protected]
/vendor/etc/init/[email protected]
/vendor/etc/vintf/manifest/manifest_vendor.qcom.hardware.howie.xml
产物vendor_framework_compatibility_matrix.xml没找到,需要将手机中的/vendor/etc/vintf/compatibility_matrix.xml手动pull出来,然后添加以下内容,并push手机中原文件位置处。
7、运行测试
上述文件全部push后重启手机。重启后,在终端模拟器中做如下操作:
#获取root权限
adb root
#运行service
adb shell
cd vendor/bin/hw
另起一个终端模拟器
adb shell
cd vendor/bin/hw
./howie_client
这时候,终端模拟器会打印信息:
Hello World, Howie
8、添加HIDL接口的hash值
上述添加hidl接口后,会报VTS问题,这时候需要添加hidl接口的hash值
通过修改hidl-gen.sh,注意,这里需要将之前的生成C++文件和bp文件的语句注释掉,否则前面写的内容就全部没了。
# -o
然后运行脚本,就会在vendor/qcom/proprietary/interfaces/howie下看到current.txt文件了
9c2be150b345854b44ea713cbd64ea64e45932f78ff30770e736286100df5777 [email protected]::IHowie
9、资源链接
androidhidlhowie.zip-Android文档类资源-CSDN下载
参考文章:
[1] HIDL最全编译流程_Gunder的博客-CSDN博客_hidl编译
[2] https://www.jianshu.com/p/fd73ab98e423
[3] https://www.jianshu.com/p/ca6823b897b5
[4] Android P HIDL服务绑定模式与直通模式的分析 (原创) - five.li - 博客园
[5] 添加HIDL接口hash值(解VTS问题)_JoggingPig的博客-CSDN博客
原文链接:https://blog.csdn.net/hihan_5/article/details/118550429