logo资料库

HIDL接口实现.pdf

第1页 / 共9页
第2页 / 共9页
第3页 / 共9页
第4页 / 共9页
第5页 / 共9页
第6页 / 共9页
第7页 / 共9页
第8页 / 共9页
资料共9页,剩余部分请下载后查看
HIDL 接口实现 1.背景 HIDL 的目标是,可以在无需重新构建 HAL 的情况下替换框架。HAL 将由供应商或 SOC 制造商构建,并放置在设备的/vendor 分区中,这样一来,就可以在其自己的分区中通过 OTA 替换框架,而无需重新编译 HAL。 2.操作实例 以实例着手,在 MTK 平台,用 HIDL 实现调用 linux 内核驱动,并测试。 功能: a. 在 linux 驱动层实现 helloworld 驱动,功能打印”hello world!”。 b. 设计 HIDL 调用内核中 helloworld 驱动,并提供接口。 c.测试程序调用 HIDL 接口,观察是否有打印“hello world!” d. 实现 HIDL 与驱动层的数据交互,HIDL 往内核写入数据并读取。 3.流程 HIDL 接口文件定义 有关 HIDL 接口与软件包规则,详见接口和软件包。 进入代码 HAL 层,自定义软件包。先以 attempt 命名这个例子。 创建 attempt HIDL 目录: mkdir -p hardware/interfaces/attempt/1.0/default 接着创建 Iattempt.hal。 hardware/interfaces/attempt/1.0/IAttempt.hal 意义: 定义一个 Iattempt.hal 接口文件,简单添加一个 helloWorld 接口,传入 string,返回 string, 在之后会实现这个接口。 生成 HAL 相关文件 使用 hidl-gen 工具 hidl-gen 代码路径为:system/tools/hidl (1) 安装 hidl-gen: dx@jacob-All-Series:~/project/AndroidQ$lunch dx@jacob-All-Series:~/project/AndroidQ$make hidl-gen 编译后路径存在: out/host/linux-x86/bin/hidl-gen
(2) 使用 hidl-gen 生成根据.hal 文件生成 HIDL 格式接口 $ LOC= hardware/interfaces/attempt/1.0/default $ PACKAGE=android.hardware.attempt@1.0 /* 生成 hardware/interfaces/attempt/1.0/default/(Attempt.h Attempt.cpp) */ $ hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE /* 生成 hardware/interfaces/attempt/1.0/Android.bp */ $ hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE //注: hardware/interfaces/attempt/1.0/default/ 自定义的 hidl 路径 android.hardware.attempt@1.0 自定义的 package 包名,与.hal 代码一致 (3) update-makefile.sh 更新 Makefile, 自动生成 hardware/interfaces/attempt/Android.dp $ ./hardware/interfaces/update-makefiles.sh (4) 添加如下文件用于注册 HIDL 服务 $ touch hardware/interfaces/attempt/1.0/default/android.hardware.attempt@ 1.0-service.rc $ touch hardware/interfaces/attempt/1.0/default/service.cpp (5) 查看一下目录结构 自此 hal 层目录结构搭建完成。 总结一下:
首先是写了一个 IAttempt.hal 并定义需要的接口函数,然后通过 hdil-gen 和 update-makefiles.sh 生成 HIDL 接口文件。最后创建用于注册接口文件的 service.cpp,**rc 文 件。 android.hardware.attempt@1.0-service.rc Attempt.cpp Attempt.h Android.bp service.cpp 用于注册 HIDL 服务 提供服务接口 编译文件 实现 HIDL 接口(共享端服务) 选择使用 Passthrouugh 模式 打开注释 hardware/interfaces/attempt/1.0/default/Attempt.h extern "C" IAttempt* HIDL_FETCH_IAttempt(const char* name); hardware/interfaces/attempt/1.0/default // Methods from ::android::hidl::base::V1_0::IBase follow. IAttempt* HIDL_FETCH_IAttempt(const char* /* name */) { return new Attempt(); } 实现 hardware/interfaces/attempt/1.0/default/service.cpp 实现 hardware/interfaces/attempt/1.0/default/android.hardware.attempt@1.0-service.rc 修改 hardware/interfaces/attempt/1.0/default/Android.bp 添加如下代码,将 service.cpp 文件加载为入口文件,开机启动服务
编译 mmm ./hardware/interfaces/attempt/1.0/ 将自定义的 attempt 服务开机自启(不确定这一步是否多余) /device/mediatek/mt6739/device.mk 然后全编 发现报错:error: VNDK library list has been changed. 解决方法:将 out/target/product/k39tv1_bsp_512/obj/PACKAGING/vndk_intermediates/libs.txt 比对到 build/make/target/product/gsi/29.txt 和 build/make/target/product/gsi/current.txt(以 out 目录下的为准,网上也有比对到 28.txt,视工程报错 log 定,也可以都同步一下) 重新编译即可解决。 4.客户端测试 实例一个 HIDL(C++)客户端 hardware/interfaces/attempt/1.0/test/attempt_client.cpp
hardware/interfaces/attempt/1.0/test/Android.bp 编译 mmm ./hardware/interfaces/attempt/1.0/test 生成路径: out/target/product/k39tv1_bsp_512/vendor/bin/hw/attempt_client 执行 将可执行文件 push 到 vendor/bin/hw/ 查看 attempt 服务是否运行 ps –A | grep attempt
执行客户端程序 ./vendor/bin/hw/attempt_client 成功!!!!(如遇 HIDL 服务没有开机启动,详见问题 2) 5.HIDL 与内核驱动交互 上述只是成功实现 HIDL 接口的建立以及与上层的交互,本段主要介绍上层通过 HIDL 与 kernel 驱动层的数据交互。 首先创建一个自定义的 kernel 驱动,并注册到内核中,我这里自定义一个 helloworld.c 的驱动,注册一个/dev/hello_world 设备,cat /proc/devices 可见 然后在 HIDL 接口实现对驱动的访问,即使用 open、read、write 函数访问到内核 hello_world.c 驱动。主要 HIDL 接口、kernel 驱动 hello_world.c 与 HIDL 测试文件主要代码如 下:
hardware/interfaces/attempt/1.0/default/Attempt.cpp(HIDL 接口文件) kernel-4.14/drivers/misc/mediatek/dx_driver/hello_world/hello_world.c(内核驱动文件)
hardware/interfaces/attempt/1.0/test/attempt_client.cpp(HIDL 测试文件) (其中一些 log,主要为测试使用,不必在意) 主要功能:HIDL 先将 write_val 值写入内核驱动,内核驱动将接收到的数据赋值给 global_char。 然后 HIDL 从内核驱动读取 global_char 并赋值给 read_val,最后将 read_val 返回给上层。上层 测试文件则负责打印 HIDL 接口上传的数据。 在实际测试时,发现 read_val 的值为空,由于 HIDL 接口 log 无法吐出(不知什么原因), 所以排查起来比较麻烦。期间写了一个可执行 C 文件调用驱动设备,才发现是因为驱动节点 open 失败,然后联想到可能是因为驱动节点的权限问题。在查询/dev/hellow_world 权限后, 看到其权限为 crw------- 。果然!因此需要更改一下/dev/hello_world 权限 system/core/rootdir/ueventd.rc 全编之后,adb 进入/vendor/bin/hw 执行./attempt_client 发现打印出 I can do it ,即 HIDL 能够将数据写入内核,且可以读取出来。大功告成! 6.问题点 这里列举一下我遇到的且排查起来比较费时的问题: 问题 1. 需要把 attempt_client push 到机器中执行,但是机器在 adb remount 失败,导致不能 push 文件。 这里将机器默认开启 root 权限: device/mediateksample/k39tv1_bsp_512/system.prop #root ro.secure=0 问题 2. 运行测试程序时出现卡死 (用的另一个 HIDL 测试)
分享到:
收藏