Android 14之HIDL转AIDL通信
Android 14之HIDL转AIDL通信
- 1、interface接口
- 1.1 接口变更
- 1.2 生成hidl2aidl工具
- 1.3 执行hidl2aidl指令
- 1.4 修改aidl的Android.bp文件
- 1.5 创建路径
- 1.6 拷贝生成的aidl到1和current
- 1.7 更新与冻结版本
- 1.8 编译模块接口
- 2、服务端代码适配hal代码修改
- 2.1 修改Android.bp的hidl依赖
- 2.2 修改头文件依赖
- 2.3 修改服务启动的rc脚本
- 2.4 修改接口函数,返回值Return<>拆分
- 2.5 aidl 服务实现
1、interface接口
1.1 接口变更
google原生的::ndk::ScopedAStatus 已经支持status返回了,hal接口理论上不需要再自定义status。所以需要删除掉目前我们HIDL文件里面里所有使用到status的接口。
注意:需要用到的返回值不需要删除,要保留,只需要删除无用的status即可。
例子1:
gwm_subscribe(IDiagCallback callback, vec<uint16_t> didList) generates (GWM_StatusCode status);
修改为:
gwm_subscribe(IDiagCallback callback, vec<uint16_t> didList) ;
并删掉enum GWM_StatusCode 枚举(GWM_StatusCode不需要使用的话)
例子2:
gwm_registerCallback(ISwumCallback callback) generates (bool status);
修改为:
bool gwm_registerCallback(ISwumCallback callback);
例子3:
gwm_setCallback(IInformationCallback callback) generates (GWM_StatusCode status, int32_t clientid);
修改为:
int gwm_setCallback(in IInformationCallback callback);
后续的例子以ILog.hal为例:
修改前:
sendToServer(String data) generates(boolean result) ;
void setCallback(ILogCallback callback);
修改后:
boolean sendToServer(in String data);
void setCallback(in vendor.mediatek.hardware.log.ILogCallback callback);
1.2 生成hidl2aidl工具
注意:需要先执行source和lunch命令
m hidl2aidl -j128
1.3 执行hidl2aidl指令
hidl2aidl -o 要生成的aidl的路径 -r 转换的hidl的路径 hidl_interface name
这里用的命令是:
hidl2aidl -o vendor/mediatek/proprietary/hardware/interfaces/log/aidl -r vendor/mediatek/proprietary/hardware/interfaces/log vendor.mediatek.hardware.log@1.0
hidl_interface name一般是hidl同级目录下Android.bp文件里面定义的。
1、如果有报错,按照提示修改即可。
2、VehicleHAL/wifi/sensor等原生接口除外,如VehicleHAL为原生接口,需要根据原生接口适配aidl 服务器
3、当执行完上述的hidl2aidl指令后,会在-o 对应目录下生成aidl文件,和一些translate文件,以及Android.bp。
1.4 修改aidl的Android.bp文件
删除translate文件。
会生成如下截图红框所示文件:
文件结构:
Android.bp:
aidl_interface {name: "vendor.mediatek.hardware.log",system_ext_specific: true,vendor_available: true,host_supported: true,frozen: true,srcs: ["vendor/mediatek/hardware/log/*.aidl"],stability: "vintf",backend: {cpp: {// FIXME should this be disabled?// prefer NDK backend which can be used anywhere// If you disable this, you also need to delete the C++// translate code.enabled: true, },java: {sdk_version: "system_current",enabled: true, },},versions_with_info: [{version: "1",imports: [],},],
}
backend: 服务的后端,AIDL支持四种后端,分别是C++/JAVA/NDK/RUST, 我们要使用NDK(谷歌推荐),CPP和JAVA后端,加上enabled: true。
vendor_available配置参考vndk介绍文档
ILog.aidl:
package vendor.mediatek.hardware.log;import vendor.mediatek.hardware.log.ILogCallback;@VintfStability
interface ILog {// Adding return type to method instead of out param boolean success since there is only one return value.boolean sendToServer(in String data);void setCallback(in ILogCallback callback);}
ILogCallback.aidl:
// FIXME: license file, or use the -l option to generate the files with the header.package vendor.mediatek.hardware.log;@VintfStability
interface ILogCallback {// Adding return type to method instead of out param boolean success since there is only one return value.boolean callbackToClient(in String data);}
1.5 创建路径
mkdir -p aidl_api/vendor.mediatek.hardware.log
cd aidl_api/vendor.mediatek.hardware.log
mkdir 1
mkdir current
1.6 拷贝生成的aidl到1和current
我自己本地尝试不拷贝直接进行下一步:更新和冻结版本会遇到问题,提示文件夹1下面没有文件。如果可以用1.7更新api和冻结api直接生成的请跳过这一步。
1.7 更新与冻结版本
先生成hash文件
croot && system/tools/aidl/build/hash_gen.sh vendor/mediatek/proprietary/hardware/interfaces/log/aidl/aidl_api/vendor.mediatek.hardware.log/1 latest-version vendor/mediatek/proprietary/hardware/interfaces/log/aidl/aidl_api/vendor.mediatek.hardware.log/1/.hash
//更新api:
m vendor.mediatek.hardware.log-update-api
//执行后生成current的api
//冻结api:
m vendor.mediatek.hardware.log-freeze-api
//执行后生成初始版本号为1的api,并且生成.hash文件,并将frozen改为true
如果提示version:这个错误,需要在Android.bp添加:
versions_with_info: [
{
version: "1",
imports: [],
},
],
错误提示:
vendor/mediatek/proprietary/hardware/interfaces/log/aidl/Android.bp:3:1: module “vendor.mediatek.hardware.log_interface”: versions: must be set (need to be frozen) because: “this is a release branch - freeze it or set ‘owners:’”
1.8 编译模块接口
先将interface编译通过:
mmm vendor/mediatek/proprietary/hardware/interfaces/log/aidl
有错解错
会编译生成jar包,还有ndk相关文件
2、服务端代码适配hal代码修改
2.1 修改Android.bp的hidl依赖
去掉hidl依赖库
“libhidlbase”,
“libhidltransport”,
添加binder依赖库:
“libbinder_ndk”,
“libbinder”,
去掉hidl接口模块:
vendor.mediatek.hardware.log@1.0
添加aidl接口模块:
“vendor.mediatek.hardware.lbs-V1-ndk”,
2.2 修改头文件依赖
HIDL的特点是,服务端和客户端都引用相同的接口文件即可,由编译时工具自动进行展开。这里需要将HIDL的引用该为AIDL的。
将vendor/mediatek/hardware/log/2.0/ILog.h
改为aidl/vendor/mediatek/hardware/log/BnILog.h //BinderNative
在路径gen\include\aidl\vendor\mediatek\hardware\log路径下生成的头文件。
2.3 修改服务启动的rc脚本
service mtk_lbs_service.rc:
service mtk_lbs_service /vendor/bin/mtk_lbs_serviceclass haluser systemgroup system gps radio inet
2.4 修改接口函数,返回值Return<>拆分
AIDL不再使用Return<>模板函数,直接将其拆分为状态和值,状态由 ::ndk::ScopedAStatus返回,非void的值由输出参数返回。
之前实现的hidl接口返回类型为Return的需要改成**::ndk::ScopedAStatus**,返回值也需要同步修改为ScopedAStatus::ok()
例子:
virtual ::android::hardware::Return<bool> gwm_registerCallback(
const ::android::sp<::vendor::gwm::hardware::swum::V2_0::ISwumCallback>& callback)
override;
修改为:
virtual ::ndk::ScopedAStatus gwm_registerCallback(
const ::android::sp<::vendor.gwm.hardware.swum::ISwumCallback>& callback,bool* _aidl_return) override;
状态拆分成了::ndk::ScopedAStatus作为返回值,HIDL的GWM_StatusCode 返回值放到了输出参数中,使用指针的形式返回。
注意:
1、::ndk::ScopedAStatus 依然可以使用isOk的方法。类似于下面这种用法,在aidl仍然适用。具体作用就不在这里详细讲了,后面有机会更新下。
auto ret = mCallback->LocationInfoStructOnChange(locationStruct);
if (!ret.isOk()) {
ALOGI("%s has error", func);
}
除了拆分其实也可以直接去参考BnILog.h文件,最后头文件的声明为:
virtual ScopedAStatus setCallback(const std::shared_ptr<ILbsCallback>& callback) override;
virtual ScopedAStatus sendToServer(const std::vector<uint8_t>& data, bool* result) override;
cpp文件的实现为:
ScopedAStatus AgpsDebugInterfaceLbsService::setCallback(const std::shared_ptr<ILbsCallback>& callback) {if (callback == nullptr) {LOGE("[%s][%s] AgpsDebugInterfaceLbsService setCallback is null !!!", g_ver, mName);return ScopedAStatus::ok();;}BaseLbsService::setCallback(callback);if(mLocalFd != -1) {LOGE("[%s][%s] DebugInterface::setCallback() mLocalFd is not -1", g_ver, mName);return ScopedAStatus::ok();}if (connectToAgpsd3()) {mIsExit = false;};return ScopedAStatus::ok();
}ScopedAStatus AgpsDebugInterfaceLbsService::sendToServer(const std::vector<uint8_t>& data,bool* result) {char buff[MAX_BUFFER_SIZE] = {0};int read_len = 0;LOGD("[%s][%s] DebugInterface::sendToServer() size=[%d]", g_ver, mName, (int)data.size());if (data.size() == 0 || data.size() > MAX_BUFFER_SIZE) {LOGE("[%s][%s] DebugInterface::sendToServer() data size check fail !", g_ver, mName);*result = false;return ScopedAStatus::ok();}covertVector2Array(data, buff);read_len = mtk_socket_write(mLocalFd, buff, (int)data.size());if (read_len <= 0 ) {LOGE("[%s][%s] DebugInterface mtk_socket_write() failed, len=%d", g_ver, mName, read_len);}// we don't care the error happens in this scenarioUNUSED(read_len);mIsExit = true;*result = true;return ScopedAStatus::ok();
}
注意:在aidl中所有的指针类型都会定义为智能指针std_sharedptr,之前hidl定义的强指针sp需要修改为智能指针。
2.5 aidl 服务实现
模板大概是:
hidl hal:
auto service = std::make_unique<Diag>(); //创建对象
configureRpcThreadpool(4, true /* callerWillJoin */); //配置线程池
ALOGD("Diag HAL service starting");
status_t status = service->registerAsService(); //注册服务
if (status != OK) {ALOGE("Unable to register Diag HAL service (%d)", status); return 1;
}ALOGI("Register DiagHAL Service successfully");
joinRpcThreadpool(); //加入线程池
aidl hal:
android::ProcessState::initWithDriver("/dev/vndbinder"); //使用vndbinder设备节点
ABinderProcess_setThreadPoolMaxThreadCount(1); // vnbinder的线程池独立,需要单独配置
ABinderProcess_startThreadPool(); //手动启动线程池
// registering
std::shared_ptr<Diag> service = ::ndk::SharedRefBase::make<Diag>(); //创建对象
const std::string desc = Diag::descriptor + "/default"s;binder_exception_t err = AServiceManager_addService(service>asBinder().get(), desc.c_str()); //注册服务
CHECK_EQ(err, STATUS_OK);
ABinderProcess_joinThreadPool();
//加入线程池
最终实现:
#define LOG_TAG "mtk_lbs_service"#include <android/binder_process.h>
#include <log/log.h>#include "mtk_lbs_service.h"//namespace aidl::vendor::mediatek::hardware::lbs {
//extern int mtk_lbs_main();
//}int main() { Register AIDL servicebinder_exception_t err = AServiceManager_addService(service->asBinder().get(), "vendor.mediatek.hardware.log.ILog/lbs");if (err != EX_NONE) {ALOGE("failed to register vendor.mediatek.hardware.log.ILog service, exception: %d", err);return 1;}ABinderProcess_setThreadPoolMaxThreadCount(20);ABinderProcess_startThreadPool();//aidl::vendor::mediatek::hardware::lbs::mtk_lbs_main();ABinderProcess_joinThreadPool();return EXIT_FAILURE; // should not reach
}
然后就是编译hal模块,编译遇到什么问题改什么。
相关文章:

Android 14之HIDL转AIDL通信
Android 14之HIDL转AIDL通信 1、interface接口1.1 接口变更1.2 生成hidl2aidl工具1.3 执行hidl2aidl指令1.4 修改aidl的Android.bp文件1.5 创建路径1.6 拷贝生成的aidl到1和current1.7 更新与冻结版本1.8 编译模块接口 2、服务端代码适配hal代码修改2.1 修改Android.bp的hidl依…...

【R库包安装】R库包安装总结:conda、CRAN等
【R库包安装】R studio 安装rgdal库/BPST库 R studio 安装rgdal库解决方法 R studio 安装BPST库(github)解决方法方法1:使用devtools安装方法2:下载安装包直接在Rstudio中安装 参考 基础 R 库包的安装可参见另一博客-【R库包安装】…...

学习PMC要不要去培训班?
在当今快速变化的商业环境中,PMC作为供应链管理的核心环节之一,其重要性日益凸显。PMC不仅关乎产品的物料计划、采购、库存控制及物流协调,还直接影响到企业的生产效率、成本控制以及市场竞争力。面对这一专业领域的学习需求,许多…...
前端 用js封装部分数据结构
文章目录 Stack队列链表Setset 用来数组去重set用来取两个数组的并集set用来取两个数组的交集set用来取两个数组的差集 字典 Stack 栈,先进后出,后进先出。用数组来进行模拟,通过push存入,通过pop取出。 class Stack {// 带#表示…...
cocoscreator-doc-TS:目录
cocoscreator-doc-TS-脚本开发-访问节点和组件-CSDN博客 cocoscreator-doc-TS-常用节点和组件接口-CSDN博客 cocoscreator-doc-TS-脚本开发-创建和销毁节点-CSDN博客 cocoscreator-doc-TS-脚本开发-加载和切换场景-CSDN博客 cocoscreator-doc-TS-脚本开发-获取和设置资源-CS…...

理解Java集合的基本用法—Collection:List、Set 和 Queue,Map
本博文部分参考 博客 ,强烈推荐这篇博客,写得超级全面!!! 图片来源 Java 集合框架 主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合(单列…...
IOC容器实现分层解耦
文章开始之前,先引入软件开发的两个名词:耦合和内聚。耦合是指:衡量软件中各个层(三层架构)/各个模块的依赖关联程度;内聚是指:软件中各个功能模块内部的功能联系。三层架构中Controller、Servi…...
Flutter 共性元素动画
在 Flutter 中,共性元素动画(Shared Element Transitions)用于在页面导航或组件切换时创建视觉上更流畅和连贯的动画效果。这种动画可以使用户感受到两个界面之间的“物理联系”,比如图片从缩略图到全屏的扩大效果。 前置知识点整…...

K8s内存溢出问题剖析:排查与解决方案
文章目录 一、背景二、排查方案:1. 可能是数据量超出了限制的大小,检查数据目录大小2. 查看是否是内存溢出2.1 排查数据量(查看数据目录大小是否超过limit限制)2.2 查看pod详情发现问题 三、解决过程 一、背景 做redis压测过程中…...

乌班图单机(不访问外网)部署docker和服务的方法
面向对象:Ubuntu不能访问外网的机子,部署mysql、redis、jdk8、minio 过程: 1、安装docker(照着图去这里找对应的下载下来https://download.docker.com/linux/static/stable/),将7个docker官网下载的文件下载下来后,传上去服务器随便一个文件夹或者常用的opt或者/usr/lo…...

使用 pycharm 新建使用 conda 虚拟 python 环境的工程
1. conda 常见命令复习: conda env list // 查看 conda 环境列表 conda activate xxxenv // 进入指定 conda 环境2. 环境展示: 2.1. 我的物理环境的 Python 版本为 3.10.9: 2.2. 我的 conda 虚拟环境 env_yolov9_python_3_8 中的 pyth…...
Docker的save和export命令的区别,load和import的区别 笔记241124
Docker的save和export命令的区别,load和import的区别 解说1: Docker的save和export命令,以及load和import命令,在功能和使用场景上存在显著的区别。以下是对这两组命令的详细对比和解释: Docker save和export命令的区别 使用方式和目的&am…...

通俗理解人工智能、机器学习和深度学习的关系
最近几年人工智能成为极其热门的概念和话题,可以说彻底出圈了。但人工智能的概念在1955年就提出来了,可以说非常古老。我在上小学的时候《科学》课本上就有人工智能的概念介绍,至今还有印象,但那些年AI正处于“寒冬”,…...

使用 pycharm 新建不使用 python 虚拟环境( venv、conda )的工程
有时候我们发现一个好玩的 demo,想赶快在电脑上 pip install 一下跑起来,发现因为 python 的 venv、conda 环境还挺费劲的,因为随着时间的发展,之前记得很清楚的 venv、conda 的用法,不经常使用,半天跑不起…...
【大数据学习 | Spark-SQL】SparkSQL读写数据
我们使用sparksql进行编程,编程的过程我们需要创建dataframe对象,这个对象的创建方式我们是先创建RDD然后再转换rdd变成为DataFrame对象。 但是sparksql给大家提供了多种便捷读取数据的方式。 //原始读取数据方式 sc.textFile().toRDD sqlSc.createDat…...

AI赋能公共服务转型升级 | 第十届中国行业互联网大会暨腾讯云TVP行业大使三周年庆典公共服务专场圆满举办!
引言 党的二十大报告把“基本公共服务实现均等化”作为 2035 年我国发展的总体目标之一,强调要“健全基本公共服务体系,提高公共服务水平”。AI 作为新质生产力的核心驱动力之一,正在公共服务领域发挥着越来越重要的作用。 2024 年 10 月 2…...
关于按天切割Tomcat的catalina.out日志文件的配置
1、catalina.out 是 Tomcat 的标准输出和标准错误日志,通常输出到 Tomcat 安装目录下的 logs 文件夹中。这个日志文件会记录 Tomcat 启动、停止以及运行过程中产生的所有日志信息。 2、在Apache Tomcat中,日志文件catalina.out默认情况下不会自动按天切割…...

【人工智能】深入解析GPT、BERT与Transformer模型|从原理到应用的完整教程
在当今人工智能迅猛发展的时代,自然语言处理(NLP)领域涌现出许多强大的模型,其中GPT、BERT与Transformer无疑是最受关注的三大巨头。这些模型不仅在学术界引起了广泛讨论,也在工业界得到了广泛应用。那么,G…...

彻底理解如何保证ElasticSearch和数据库数据一致性问题
一.业务场景举例 需求: 一个卖房业务,双十一前一天,维护楼盘的运营人员突然接到合作开发商的通知,需要上线一批热门的楼盘列表,上传完成后,C端小程序支持按楼盘的名称、户型、面积等产品属性全模糊搜索热门…...

2024-2025热门留学趋势
在信息爆炸的时代,留学已成为许多人规划未来、拓宽视野的重要途径。随着全球教育格局的不断变化,留学领域也涌现出一系列新热点和趋势。本文将为您解读2024年最热门的留学话题,并提供实用的准备策略,助您在留学之路上一帆风顺。 热…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...