本文内容需要用到我上一篇文章做的驱动,可以先看文章https://blog.csdn.net/ange_li/article/details/136759249
一、Hal 层的实现
1.Hal 层的实现一般放在 vendor 目录下,我们在 vendor 目录下创建如下的目录
aosp/vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0
接着在aosp/vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0 目录下创建Hal文件ILedControl.hal
//定义包名,最后跟一个版本号
package arpi.hardware.rbg_led_control_hidl@1.0;
//定义 hidl 服务对外提供的接口
interface ILedControl {
//开灯
openLed(uint32_t red,uint32_t blue,uint32_t green) generates (uint32_t result);
//读 hello 驱动
closeLed() generates (uint32_t result);
};
2. hal 文件生成 C++ 源文件
接着我们使用 hidl-gen 命令将我们写的 hal 文件转换为 C++ 文件:
source build/envsetup.sh
lunch rpi4-eng
PACKAGE=arpi.hardware.rbg_led_control_hidl@1.0
LOC=vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default
hidl-gen -o $LOC -Lc++-impl -rarpi.hardware:vendor/arpi/hardware/interfaces $PACKAGE
接着就会生成一些 C++ 代码:生成下图中的LedControl.h LedControl.cpp
接着修改 LedControl.cpp
// FIXME: your file license if you have one
#include "LedControl.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
namespace arpi::hardware::rbg_led_control_hidl::implementation {
// Methods from ::arpi::hardware::rbg_led_control_hidl::V1_0::ILedControl follow.
Return<uint32_t> LedControl::openLed(uint32_t red, uint32_t blue, uint32_t green) {
int fd = open("/dev/led_drv", O_RDWR);
if (fd == -1){
printf("can not open file /dev/led_drv\n");
return uint32_t { 0 };
}
char r[]="red";
char b[]="blue";
char g[]="green";
char cmd[14]="";
if(red==1){
strcat(cmd, r);
}
if(blue==1){
strcat(cmd, b);
}
if(green==1){
strcat(cmd, g);
}
::write(fd, cmd, strlen(cmd) +1);
close(fd);
return uint32_t {1};
}
Return<uint32_t> LedControl::closeLed() {
int fd = open("/dev/led_drv", O_RDWR);
if (fd == -1){
printf("can not open file /dev/led_drv\n");
return uint32_t { 0 };
}
char cmd[14]="";
::write(fd, cmd, strlen(cmd) +1);
close(fd);
return uint32_t {1};
}
// Methods from ::android::hidl::base::V1_0::IBase follow.
//ILedControl* HIDL_FETCH_ILedControl(const char* /* name */) {
//return new LedControl();
//}
//
} // namespace arpi::hardware::rbg_led_control_hidl::implementation
这里主要是对我们的协议进行实现,实现了对上一节实现的设备文件 /dev/led_drv
的读写。至此我们的 hidl 服务就定义好了
3. 服务端实现
接着我们需要写一个 Server 端来向 HwServiceManager 注册我们的服务。在vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default 目录下添加 service.cpp(参考上图)
#include <hidl/HidlTransportSupport.h>
#include <utils/Looper.h>
#include <utils/StrongPointer.h>
#include <log/log.h>
#include "LedControl.h"
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using arpi::hardware::rbg_led_control_hidl::V1_0::ILedControl;
using arpi::hardware::rbg_led_control_hidl::implementation::LedControl;
int main() {
ALOGD("hello-hidl is starting...");
configureRpcThreadpool(4, true /* callerWillJoin */);
android::sp<ILedControl> service = new LedControl();
android::status_t ret = service->registerAsService();
if (ret != android::NO_ERROR) {
}
joinRpcThreadpool();
return 0;
//Passthrough模式
//return defaultPassthroughServiceImplementation<IHello>(4);
}
我们的服务端需要在开机时启动,vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default 目录下创建arpi.hardware.rbg_led_control_hidl@1.0-service.rc 文件
service vendor_rbg_led_control_hidl_service /vendor/bin/hw/arpi.hardware.rbg_led_control_hidl@1.0-service
class hal
user system
group system
接着我们需要添加 VINTF 对象,对于注册到 hwservicemanager 的服务都需要添加一个 VINTF 对象。对于编码来说 VINTF 对象就是一个 xml 文件,vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default 目录下创建arpi.hardware.rbg_led_control_hidl@1.0-service.xml
<manifest version="1.0" type="device">
<hal format="hidl">
<name>arpi.hardware.rbg_led_control_hidl</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ILedControl</name>
<instance>default</instance>
</interface>
</hal>
</manifest>
4 生成 Android.bp
hidl-gen -o $LOC -Landroidbp-impl -rarpi.hardware:vendor/arpi/hardware/interfaces $PACKAGE
该命令会在vendor/arpi/hardware/interfaces/rbg_led_control_hidl/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 '-<hardware identifier>' etc to distinguish it.
name: "arpi.hardware.rbg_led_control_hidl@1.0-impl",
relative_install_path: "hw",
// FIXME: this should be 'vendor: true' for modules that will eventually be
// on AOSP.
proprietary: true,
srcs: [
"LedControl.cpp",
],
shared_libs: [
"libhidlbase",
"libhidltransport",
"libutils",
"arpi.hardware.rbg_led_control_hidl@1.0",
"liblog",
],
}
cc_binary {
name: "arpi.hardware.rbg_led_control_hidl@1.0-service",
init_rc: ["arpi.hardware.rbg_led_control_hidl@1.0-service.rc"],
vintf_fragments: ["arpi.hardware.rbg_led_control_hidl@1.0-service.xml"],
defaults: ["hidl_defaults"],
relative_install_path: "hw",
vendor: true,
srcs: ["service.cpp", "LedControl.cpp"],
shared_libs: [
"arpi.hardware.rbg_led_control_hidl@1.0",
"libhardware",
"libhidlbase",
"libhidltransport",
"libutils",
"liblog",
],
}
生成的库里面有一个依赖 arpi.hardware.rbg_led_control_hidl@1.0
,接着我们来生成这个库对应的 Android.bp:
在vendor/arpi/hardware/interfaces/下创建update-makefiles.sh
#!/bin/bash
source $ANDROID_BUILD_TOP/system/tools/hidl/update-makefiles-helper.sh
do_makefiles_update \
"arpi.hardware:vendor/arpi/hardware/interfaces"
接着执行:
./vendor/arpi/hardware/interfaces/update-makefiles.sh
结果生成文件aosp/vendor/arpi/hardware/interfaces/rbg_led_control_hidl/Android.bp
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
name: "arpi.hardware.rbg_led_control_hidl@1.0",
root: "arpi.hardware",
system_ext_specific: true,
srcs: [
"ILedControl.hal",
],
interfaces: [
"android.hidl.base@1.0",
],
gen_java: true,
}
这个过程会生成一些so 库。
随后在aosp/vendor/arpi/hardware/interfaces下创建Android.bp (告诉编译系统包名与路径的映射关系)
hidl_package_root {
name: "arpi.hardware",
path: "vendor/arpi/hardware/interfaces",
}
接着创建aosp/vendor/arpi/hardware/interfaces/current.txt
ecf0cea3adff3da5319d360d2e86c3a4b336aa64e798f1fc4eb3dc2abbd6905f arpi.hardware.rbg_led_control_hidl@1.0::ILedControl
再执行一遍 update-makefiles.sh,这个时候就会发现提示 hash 值不正确了,同时会给出正确的 hash 值,我们把正确的 hash 值替换到 current.txt 即可。
5 test客户端编写
vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default 目录下创建test文件夹
Android.bp
cc_binary {
name: "rbg_led_control_hidl_test",
srcs: ["rbg_led_control_hidl_test.cpp"],
vendor: true,
shared_libs: [
"liblog",
"arpi.hardware.rbg_led_control_hidl@1.0",
"libhidlbase",
"libhidltransport",
"libhwbinder",
"libutils",
],
}
#include <arpi/hardware/rbg_led_control_hidl/1.0/ILedControl.h>
#include <hidl/LegacySupport.h>
#define LOG_TAG "rbg_led_control_hidl"
#include <log/log.h>
using android::sp;
using arpi::hardware::rbg_led_control_hidl::V1_0::ILedControl;
using android::hardware::Return;
using android::hardware::hidl_string;
int main(){
android::sp<ILedControl> hw_device = ILedControl::getService();
if (hw_device == nullptr) {
ALOGD("failed to get rbg_led_control_hidl");
return -1;
}
ALOGD("success to rbg_led_control_hidl....");
hw_device->openLed(1,0,0);
return 0;
}
上面测试代码可以点亮led 红灯
6 selinux 配置
在aosp/device/arpi/rpi4/sepolicy 目录下
device.te 中添加如下内容:
type led_drv_t, dev_type;
hwservice.te:
type rbg_led_control_hidl_hwservice, hwservice_manager_type;
rbg_led_control_hidl.te:
# type rbg_led_control_hidl, domain;
type rbg_led_control_hidl, domain;
type rbg_led_control_hidl_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(rbg_led_control_hidl);
add_hwservice(rbg_led_control_hidl, rbg_led_control_hidl_hwservice)
hwbinder_use(rbg_led_control_hidl)
allow rbg_led_control_hidl hidl_base_hwservice:hwservice_manager { add };
allow rbg_led_control_hidl led_drv_t:chr_file { open read write };
binder_call(rbg_led_control_hidl,hwservicemanager)
get_prop(rbg_led_control_hidl,hwservicemanager_prop)
hwservice_contexts:
arpi.hardware.rbg_led_control_hidl::ILedControl u:object_r:rbg_led_control_hidl_hwservice:s0
rbg_led_control_hidl_test.te:
type rbg_led_control_hidl_test, domain;
type rbg_led_control_hidl_test_exec, exec_type, vendor_file_type, file_type;
domain_auto_trans(shell, rbg_led_control_hidl_test_exec, rbg_led_control_hidl_test);
get_prop(rbg_led_control_hidl_test, hwservicemanager_prop);
allow rbg_led_control_hidl_test rbg_led_control_hidl_hwservice:hwservice_manager find;
hwbinder_use(rbg_led_control_hidl_test);
file_contexts:
/dev/led_drv u:object_r:led_drv_t:s0
/vendor/bin/hw/arpi\.hardware\.rbg_led_control_hidl@1\.0-service u:object_r:rbg_led_control_hidl_exec:s0
7 编译执行
接着在aosp/device/arpi/rpi4/rpi4.mk 加入程序
PRODUCT_PACKAGES += \
arpi.hardware.rbg_led_control_hidl@1.0-service \
rbg_led_control_hidl_test \
arpi.hardware.rbg_led_control_hidl@1.0-impl \
source build/envsetup.sh
lunch rpi4-eng
make ramdisk systemimage vendorimage
最后测试(点亮led):
rbg_led_control_hidl_test &