0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Android Q打通应用层到HAL层(HIDL服务实现)

哆啦安全 来源:CSDN-DJLZPP 2023-02-21 10:28 次阅读

AndroidQ 打通应用层到HAL层—(HAL模块实现)这篇文章中我们已经实现了自己的HAL,本篇我们实现一个HIDL服务,通过这个服务来调用HAL模块的函数

什么是HIDL

HIDL 全称为HAL interface definition language(发音为“hide-l”)是用于指定 HAL 和其用户之间的接口的一种接口描述语言 (IDL),Android O开始引入了HIDL这个概念。

HIDL和应用层AIDL差不多,AIDL常用于连接App和Framework,HIDL则是用来连接Framework和HAL,AIDL使用Binder通信,HIDL则使用HwBinder通信,他们都是通过Binder驱动完成通信,只不过两个Binder域不一样

为什么需要HIDL

目前Android系统生态是几乎每年google都会出一个Android大版本,而普通手机用户一部手机一般要用两三年,所以你会发现尽管Android系统已经升级到了10,马上11出来了,然后还是有很多用户依然使用的是Android 5,6,7等版本。

对普通用户来说如果不更换手机就很难跟上Android版本,这是因为OEM厂商在同一设备上进行系统升级需要花费时间金钱成本很高,导致他们不愿意升级,成本高的原因是Android O之前Android Framework的升级需要OEM将HAL也进行对应升级,Framework和HAL是一起被编译成system.img,它们存在高耦合

针对这种情况google在Android O中引入了Treble计划,Treble的目的就是解耦Framework和HAL,就是通过HIDL来实现,Framework不再直接调用HAL,而是通过HIDL来间接使用HAL模块,每个HAL模块都可以对应一个HIDL服务,Framework层通过HwBinder创建HIDL服务。

通过HIDL服务来获取HAL相关模块继而打开HAL下的设备,而最终HAL也从system.img中分离,被编进一个单独的分区vendor.img,从而简化了Android系统升级的影响与难度。

HIDL的使用

HIDL可以分为:HIDL C++(C++实现)、HIDL Java(Java 实现),并且还主要分为直通式和绑定式,本篇文章使用的C++和直通式的HIDL,HIDL用起来非常简单,AOSP的hardware/interfaces/目录下有很多的HIDL,我们仿照其他HIDL创建自己的HIDL目录:hardware/interfaces/hello_hidl/1.0

并在此目录下创建一个IHello.hal文件:

packageandroid.hardware.hello_hidl@1.0;

interfaceIHello{

addition_hidl(uint32_ta,uint32_tb)generates(uint32_ttotal);

};

这个文件定义了一个addition_hidl函数,这个函数用来调用HAL的加法函数

然后就可以使用Android提供的工具hidl-gen来生成HIDL框架,执行如下命令:

PACKAGE=android.hardware.hello_hidl@1.0
LOC=hardware/interfaces/hello_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

执行命令成功之后我们会发现hardware/interfaces/hello_hidl/1.0下多了一个default目录,进入default目录,里面有三个文件Android.bp,Hello.cpp,Hello.h

d6405992-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述
之后再在执行./hardware/interfaces/update-makefiles.sh这个命令,update-makefiles.sh这个脚本目的是为HIDL生成对应Android.bp文件

最后目录结构为:

d64e1ec4-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述

接着我们还需要在default目录下增加一个空文件service.cpp,用作注册HIDL服务,我们采用直通式的HIDL,所以service.cpp的内容为:

#include
#include
//GeneratedHIDLfiles
usingandroid::IHello;
usingandroid::defaultPassthroughServiceImplementation;

intmain(){
returndefaultPassthroughServiceImplementation();
}

defaultPassthroughServiceImplementation函数最终会向HwServiceManager注册HIDL服务

接着我们来看看之前生成的文件,首先看Hello.h

//FIXME:yourfilelicenseifyouhaveone

#pragmaonce

#include
#include
#include

namespaceandroid{
namespacehardware{
namespacehello_hidl{
namespaceV1_0{
namespaceimplementation{
using::hidl_array;
using::hidl_memory;
using::hidl_string;
using::hidl_vec;
using::Return;
using::Void;
using::sp;

structHello:publicIHello{
//Methodsfrom::IHellofollow.
Returnaddition_hidl(uint32_ta,uint32_tb)override;

//Methodsfrom::IBasefollow.

};

//FIXME:mostlikelydelete,thisisonlyforpassthroughimplementations
//去掉注释
extern"C"IHello*HIDL_FETCH_IHello(constchar*name);

}//namespaceimplementation
}//namespaceV1_0
}//namespacehello_hidl
}//namespacehardware
}//namespaceandroid

系统自动生成了Hello结构体(当然也可以自己改为class),继承IHello接口,addition_hidl函数就需要在Hello.cpp中去实现了,因为我们采用直通式HIDL,所以需要将// extern “C” IHello* HIDL_FETCH_IHello(const char* name);的注释去掉

接着来看看Hello.cpp:

//FIXME:yourfilelicenseifyouhaveone

#include"Hello.h"
#include
namespaceandroid{
namespacehardware{
namespacehello_hidl{
namespaceV1_0{
namespaceimplementation{

//Methodsfrom::IHellofollow.
ReturnHello::addition_hidl(uint32_ta,uint32_tb){
//TODOimplement
ALOGE("hello_hidlserviceisinitsuccess....a:%d,b:%d",a,b);
returnuint32_t{};
}
//Methodsfrom::IBasefollow.

IHello*HIDL_FETCH_IHello(constchar*/*name*/){
returnnewHello();
}
}//namespaceimplementation
}//namespaceV1_0
}//namespacehello_hidl
}//namespacehardware
}//namespaceandroid

同样需要去掉HIDL_FETCH_IHello函数的注释,采用直通式HIDL时,通过前面service.cpp中的defaultPassthroughServiceImplementation函数注册HIDL服务时,内部原理就是通过“HIDL_FETCH_”字串拼接defaultPassthroughServiceImplementation传递的IHello,找到HIDL_FETCH_IHello函数并获取IHello对象,我们可以看到HIDL_FETCH_IHello初始代码就是创建了一个Hello对象

在接着看default目录下的Android.bp:

cc_library_shared{
name:"android.hardware.hello_hidl@1.0-impl",
relative_install_path:"hw",
proprietary:true,
srcs:[
"Hello.cpp",
],
shared_libs:[
"libhidlbase",
"libhidltransport",
"libutils",
"android.hardware.hello_hidl@1.0",
"liblog",
"libutils",
],
}

这个Android.bp会将Hello这个HIDL服务编译成一个android.hardware.hello_hidl@1.0-impl.so,它还依赖一个android.hardware.hello_hidl@1.0.so,这个so哪来的呢?

再接着看1.0目录下的Android.bp:

//Thisfileisautogeneratedbyhidl-gen-Landroidbp.
hidl_interface{
name:"android.hardware.hello_hidl@1.0",
root:"android.hardware",
vndk:{
enabled:true,
},
srcs:[
"IHello.hal",
],
interfaces:[
"android.hidl.base@1.0",
],
gen_java:true,
}

这个Android.bp会将hardware/interfaces/hello_hidl/1.0这个HIDL编译成一个android.hardware.hello_hidl@1.0.so,到这里我们发现service.cpp没有用到,所以我们还需要修改default目录下的Android.bp:

//FIXME:yourfilelicenseifyouhaveone

cc_library_shared{
name:"android.hardware.hello_hidl@1.0-impl",
relative_install_path:"hw",
proprietary:true,
srcs:[
"Hello.cpp",
],
shared_libs:[
"libhidlbase",
"libhidltransport",
"libutils",
"liblog",
"libhardware",
"android.hardware.hello_hidl@1.0",
"liblog",
"libutils",
],
}
cc_binary{
name:"android.hardware.hello_hidl@1.0-service",
defaults:["hidl_defaults"],
relative_install_path:"hw",
vendor:true,
srcs:["service.cpp"],
shared_libs:[
"android.hardware.hello_hidl@1.0",
"libhardware",
"libhidlbase",
"libhidltransport",
"libutils",
"liblog",
],

}

新增加对service.cpp的编译,我们将service.cpp编译成一个二进制可执行文件android.hardware.hello_hidl@1.0-service.so,用来启动HIDL服务,好了,最终我们这个HIDL会编译出来如下三个so:
android.hardware.hello_hidl@1.0-impl.so
android.hardware.hello_hidl@1.0.so
android.hardware.hello_hidl@1.0-service.so

还有一点需要注意的是,这个HIDL想要被Framework获取使用还需要在manifest.xml中注册,
manifest.xml在手机vendor/etc/vintf/manifest.xml下,我们将这个文件pull出来然后添加如下代码:


android.hardware.hello_hidl
hwbinder
1.0

IHello
default

@1.0::IHello/default

然后在Hello.cpp中添加一行log,之后进行编译

IHello*HIDL_FETCH_IHello(constchar*/*name*/){

ALOGE("hello_hidlserviceisinitsuccess....");

returnnewHello();
}

执行mmm hardware/interfaces/hello_hidl/1.0/

d6674dae-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述
编译成功后我们将生成的三个so分别push到手机vendor/lib64/hw/,vendor/lib64/,vendor/bin/hw/目录下

adb push vendor/lib64/hw/android.hardware.hello_hidl@1.0-impl.so vendor/lib64/hw/

adb push system/lib64/android.hardware.hello_hidl@1.0.so vendor/lib64/

adb push vendor/bin/hw/android.hardware.hello_hidl@1.0-service vendor/bin/hw/

接着我们到手机vendor/bin/hw/目录下去执行android.hardware.hello_hidl@1.0-service这个二进制可执行文件,这个文件就会执行service.cpp的代码,调用defaultPassthroughServiceImplementation注册我们的HIDL服务

d697d01e-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述

再看看log输出:

d6b2d814-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述
在执行android.hardware.hello_hidl@1.0-service时就会输入这句log,代表我们这个HIDL服务已经实现,其实通常的HIDL服务都是通过rc文件来开机启动的,我这里为了方便演示就没有写

再执行adb shell ps -A|grep -i --color "hello_hidl"命令看下这个服务状态
我们发现HIDL服务启动之后就会一直在后台,这个其实和AMS,WMS这种服务是类似的,启动之后在后台会等待client端访问

d6c5c294-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述

HIDL这个服务已经能够正常启动了,接着写一个测试程序看能否获取这个服务,并且调用该服务的函数,我在Hello.cpp的addition_hidl函数中添加了一句log:

ReturnHello::addition_hidl(uint32_ta,uint32_tb){
//TODOimplement
ALOGD("dongjiao...Hello::addition_hidla=%d,b=%d",a,b);
returnuint32_t{};
}

测试程序写在hardware/interfaces/hello_hidl/1.0/default目录下:

d6e1b706-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述
Hello_hidl_test.cpp:

#include
#include
#include

usingandroid::sp;
usingandroid::IHello;
usingandroid::Return;
intmain(){
android::sphw_device=IHello::getService();
if(hw_device==nullptr){
ALOGD("dongjiao...failedtogethello-hidl");
return-1;
}
ALOGD("dongjiao...successtogethello-hidl....");
Returntotal=hw_device->addition_hidl(3,4);
return0;
}

测试程序代码也比较简单,获取IHello的服务,然后调用addition_hidl函数

看一下Android.bp:

cc_binary{
name:"Hello_hidl_test",
srcs:["Hello_hidl_test.cpp"],
shared_libs:[
"liblog",
"android.hardware.hello_hidl@1.0",
"libhidlbase",
"libhidltransport",
"libhwbinder",
"libutils",
],
}

我们再编译这个测试程序,它会被编译成一个可执行二进制文件Hello_hidl_test
编译命令:
mmm hardware/interfaces/hello_hidl/1.0/default/test/

d708152c-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述
编译成功了,将这个可执行文件push到手机/system/bin/目录下

在执行Hello_hidl_test之前别忘了把HIDL服务启动起来

d74177ae-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述
接着执行Hello_hidl_test
d75700f6-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述
然后看log输出
d7747096-b06c-11ed-bfe3-dac502259ad0.png在这里插入图片描述
可以看到成功了,成功获取到了HIDL服务并且调用了该服务的addition_hidl函数,将我们的参数传递了过去,实际开发中就可以在获取HIDL服务时打开HAL模块,然后可以直接调用HAL的函数。 上一篇文章其实也写了测试程序测自定义的HAL模块,我们只需要将上一篇文章中的测试程序中的代码copy到HIDL初始化代码中就能够调用HAL的那个加法函数了,具体就不测试了。

到这里HIDL服务已经成功实现并且能够正常使用,HIDL这个框架用起来还是比较简单的,大部分代码都是通过工具生成的。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Android
    +关注

    关注

    12

    文章

    3935

    浏览量

    127373
  • 函数
    +关注

    关注

    3

    文章

    4329

    浏览量

    62588
  • C++
    C++
    +关注

    关注

    22

    文章

    2108

    浏览量

    73636
  • 应用层
    +关注

    关注

    0

    文章

    46

    浏览量

    11501
  • HAL
    HAL
    +关注

    关注

    2

    文章

    70

    浏览量

    12611

原文标题:Android Q打通应用层到HAL层(HIDL服务实现)

文章出处:【微信号:哆啦安全,微信公众号:哆啦安全】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    关于应用层协议定义

    运输给应用进程提供了端端的通信服务,但不同的网络进程之间,还需要有不同的通信规则,因此运输之上还需要有应用层
    发表于 08-25 10:49 1596次阅读

    PCM2707C是否支持Android系统?PCM2707C Android应用层怎么写?

    有如下两个问题,帮忙看看,谢谢! 1,PCM2707C是否支持Android系统 2,PCM2707C Android应用层怎么写?如何获取USB上的音频数据。
    发表于 10-30 07:46

    鸿蒙Hi3516 纯手工打造从应用层驱动示例

    本帖最后由 PCB00023915 于 2020-11-6 09:56 编辑 鸿蒙Hi3516 纯手工打造从应用层驱动示例鸿蒙的应用和驱动构建涉及的文件较多,能够重新编译的
    发表于 11-06 09:56

    请问如何从Android应用层APP对u盘进行读写操作?

    开发板:i.MX6Q系统:Android6.0Linux4.1.15从Android应用层APP对u盘进行读写操作,没有权限。怎么解决。。。求教。。。
    发表于 01-11 06:06

    RK3326 Android系统Hal是怎样去添加服务

    RK3326 Android系统Hal是怎样去添加服务的?有哪些流程?
    发表于 02-17 06:31

    RK3288 android7.1.2 HAL添加I2C Service怎么实现

    RK3288 android7.1.2 HAL添加I2CService怎么实现
    发表于 03-02 09:11

    【学习打卡】OpenHarmony的应用层说明

    通过应用层实现控制与其他设备的通信。它是一种抽象服务,并且它将应用程序的其余部分与传输过程相屏蔽。应用层位于所有
    发表于 07-14 08:44

    计算机网络应用层

    掌握TCP/IP 的应用层的主要应用及工作原理,包括DNS 服务、 HTTP 服务、 FTP 服务和E-mail 服务;理解OSI
    发表于 08-05 17:46 292次下载

    Zigbee应用层规范

    本内容介绍了Zigbee应用层规范
    发表于 05-24 11:37 85次下载
    Zigbee<b class='flag-5'>应用层</b>规范

    局域网通信原理传输应用层

    局域网通信原理传输应用层(烽火通信网络机顶盒hg680-j刷机)-该文档为局域网通信原理传输应用层讲解资料,讲解的还不错,感兴趣的可以下载看看…………………………
    发表于 07-30 08:29 15次下载
    局域网通信原理传输<b class='flag-5'>层</b>和<b class='flag-5'>应用层</b>

    认知无线电MAC应用层仿真软件

    认知无线电MAC应用层仿真软件(澳莱特电源技术有限公司)-该文档为认知无线电MAC应用层仿真软件总结文档,是一份很不错的参考资料,具有较高参考价值,感兴趣的可以下载看看…………
    发表于 09-15 11:40 11次下载
    认知无线电MAC<b class='flag-5'>层</b>与<b class='flag-5'>应用层</b>仿真软件

    Android硬件通讯之HIDL介绍

    HIDL的全称是HAL interface definition language(硬件抽象接口定义语言),是AndroidFramework 与
    的头像 发表于 03-08 15:52 5233次阅读

    应用层知多少?(总结在末尾)

    为什么需要应用层运输给应用进程提供了端端的通信服务,但不同的网络进程之间,还需要有不同的通信规则,因此运输之上还需要有
    的头像 发表于 08-26 11:16 1380次阅读
    <b class='flag-5'>应用层</b>知多少?(总结在末尾)

    物联网的技术架构及应用层是什么?

    物联网的技术架构包括感知、网络、平台应用层应用层是物联网的顶层,它的主要功能是将感知
    的头像 发表于 07-15 08:56 3726次阅读

    Linux应用层控制外设的两种不同的方式

    众所周知,linux下一切皆文件,那么应用层如何控制硬件,同样是通过 文件I/O的方式来实现的,那么应用层控制硬件通常有两种方式。
    的头像 发表于 10-05 19:03 488次阅读
    Linux<b class='flag-5'>应用层</b>控制外设的两种不同的方式