一、HIDL简单介绍

HIDL是Android8.0新出的一个技能,以service和client的方式实现hal接口,目的是想使Android系统和BSP解绑,使系统升级更加方便。HIDL的使用方法一般是先提供.hal文件,然后使用hidl-gen工具生成 框架源文件和Android.bp编译工具文件,之后填充生成的源文件和定制Android.bp编译文件。

二、修改源HIDL文件添加hal接口

以Qucomm蓝牙模块额外提供BT MAC地址访问接口为例进行机介绍

[ubuntu @fm]$ tree
.
├── 1.0
│ ├── Android.bp
│ ├── Android.mk
│ ├── hidl-gen.sh
│ ├── IFmHciCallbacks.hal
│ ├── IFmHci.hal
│ └── types.hal
└── Android.bp

1.修改提供.hal文件

# cat vendor/qcom/proprietaryinterfaces/fm/1.0/IFmHci.hal
package vendor.qti.hardware.fm@1.0;
interface IFmHci {
sendHciCommand(HciPacket command);
+ getBluetoothMacAddress() generates (MacRet mret); //添加这个接口,MacRet (void)类型
}; # cat vendor/qcom/proprietaryinterfaces/fm/1.0/types.hal
package vendor.qti.hardware.fm@1.0;
struct MacRet { //添加这个结构体
uint8_t mac0; //写成数组测试不行,hidl不自持吧。
uint8_t mac1;
uint8_t mac2;
uint8_t mac3;
uint8_t mac4;
uint8_t mac5;
int8_t ret;
};

2.重新生成1.0目录下的Android.bp和Android.mk
这两个文件是hidl-gen根据hal文件自动生成的,用户不要去改。因为hal文件变了,因此需要重新生成。

# rm 1.0/Android.mk
# rm 1.0/Android.bp
# hidl-gen -Landroidbp -r vendor.qti.hardware:vendor/qcom/proprietary/interfaces -r android.hidl:system/libhidl/transport vendor.qti.hardware.fm@1.0
# hidl-gen -Lmakefile -r vendor.qti.hardware:vendor/qcom/proprietary/interfaces -r android.hidl:system/libhidl/transport vendor.qti.hardware.fm@1.0 //一般情况下只需要重新生成Android.bp就可以了。

3.生成hal文件中新添加函数的C++代码实现框架
可以根据hal文件生成cpp文件,然后从新生成的cpp文件中拷贝出getBluetoothMacAddress的cpp实现框架,然后将其拷贝到原cpp文件中。注意,需要在指定在一个临时的目录中生成C++实现框架文件,以免将已经存在原来的C++文件覆盖掉。
# hidl-gen -o tmp_dir -Lc++-impl -r vendor.qti.hardware:vendor/qcom/proprietary/interfaces -r android.hidl:system/libhidl/transport vendor.qti.hardware.fm@1.0
此时会在tmp_dir中生成FmHci.cpp文件和FmHci.h文件,拷贝这两个文件中getBluetoothMacAddress()到原来的C++实现文件的对应位置

# cat FmHci.h
struct FmHci : public IFmHci {
...
Return<void> getBluetoothMacAddress(getBluetoothMacAddress_cb _hidl_cb) override; //拷贝过来
...
}; # cat FmHci.cpp
Return<void> FmHci::getBluetoothMacAddress(getBluetoothMacAddress_cb _hidl_cb) { //参数是个回调函数
bool ret;
MacRet mret; //这里不需要加struct ret = BluetoothAddress::GetLocalAddress((uint8_t *)&mret);
if (ret == true) {
mret.ret = true;
} else {
memset(&mret, , sizeof(mret));
mret.ret = false;
}
_hidl_cb(mret); //给回调函数传参,回调的函数来自client return Void();
}

4.收尾工作
(1)使用using导入使用的元素
FmHci.h中:
using android::hardware::bluetooth::V1_0::implementation::BluetoothAddress; //导入FmHci.cpp文件中使用到的BluetoothAddress::GetLocalAddress()所在的类。
(2)添加头文件搜索路径
在Android.mk中:

LOCAL_C_INCLUDES += vendor/qcom/proprietary/qmi-framework/inc
LOCAL_C_INCLUDES += vendor/qcom/proprietary/qmi/inc
LOCAL_C_INCLUDES += vendor/qcom/proprietary/bt/hci_qcomm_init

若此时能编译成功,则Service端添加的这个hal接口就添加好了。

5.编写测试程序进行验证
一般测试程序放在/external/tools目录下,也可以放在hal实现目录下的vts目录下
(1)编写测试cpp文件

//[ubuntu @btaddr_test]$ cat btaddr_client.cpp
#include <stdio.h>
#include <android/hardware/btaddr/1.0/IBtaddr.h>
#include <android/hardware/btaddr/1.0/types.h> using ::android::hardware::btaddr::V1_0::IBtaddr;
using ::android::hardware::btaddr::V1_0::MacRet;
using namespace std; MacRet g_mret; IBtaddr::getBluetoothMacAddress_cb get_mac_addr(android::hardware::btaddr::V1_0::MacRet mret)
{
g_mret = mret; return nullptr;
} int main()
{
android::sp<IBtaddr> service = IBtaddr::getService();
if (service == nullptr){
printf("SFL: Failed to get service\n");
return -;
}
service->getBluetoothMacAddress(get_mac_addr); printf("MAC=0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", g_mret.mac0, g_mret.mac1, g_mret.mac2, g_mret.mac3, g_mret.mac4, g_mret.mac5); return ;
}

(2)编写Android.bp

//[ubuntu @btaddr_test]$ cat Android.bp
cc_binary {
name: "btaddr_test",
vendor: true,
srcs: ["btaddr_client.cpp"],
cflags: ["-Wall"],
shared_libs: [
"liblog",
"libutils",
"libhidltransport",
"android.hardware.btaddr@1.0",
"libhidlbase",
"libbase",
],
}

(3)将测试程序btaddr_test安装到文件系统
在device/qcom/common/base.mk中添加
XX_TEST_APPS += demo_client  //XX_TEST_APPS环境变量里面的所有可执行程序都会被编译进文件系统

然后就可以重新烧录验证了。

三、独立实现HIDL文件

1.实现.hal文件

/media/ubuntu/work/g6pa_mount/G6PA_NEW/LINUX/android/hardware/interfaces/btaddr
[hardware/interfaces/btaddr: @btaddr]$ tree
.
├── 1.0
├── IBtaddr.hal
└── types.hal //# cat 1.0/IBtaddr.hal
package android.hardware.btaddr@1.0; interface IBtaddr {
getBluetoothMacAddress() generates (MacRet mret);
}; //# cat 1.0/types.hal
package android.hardware.btaddr@1.0; struct MacRet {
uint8_t mac0;
uint8_t mac1;
uint8_t mac2;
uint8_t mac3;
uint8_t mac4;
uint8_t mac5;
int8_t ret;
};

2.由hal文件生成C++实现文件

# hidl-gen -o hardware/interfaces/btaddr/1.0/default -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.btaddr@1.0
会在1./default下生成Btaddr.cpp 和Btaddr.h # hidl-gen -o hardware/interfaces/btaddr/1.0/default -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.btaddr@1.0
会在1./default下生成Android.bp # ./hardware/interfaces/update-makefiles.sh
会在btaddr下生成Android.bp .0下生成Android.bp和Android.mk 此时:
[ubuntu @btaddr]$ tree
.
├── 1.0
│ ├── Android.bp
│ ├── Android.mk
│ ├── default
│ │ ├── Android.bp
│ │ ├── Btaddr.cpp
│ │ └── Btaddr.h
│ ├── IBtaddr.hal
│ └── types.hal
└── Android.bp

3.实现生成C++文件

//[ubuntu @btaddr]$ cat 1.0/default/Btaddr.cpp
#define LOG_TAG "android.hardware.btaddr@1.0-impl" #include <string.h>
#include <errno.h> #include "Btaddr.h" namespace android {
namespace hardware {
namespace btaddr {
namespace V1_0 {
namespace implementation { // Methods from IBtaddr follow.
Return<void> Btaddr::getBluetoothMacAddress(getBluetoothMacAddress_cb _hidl_cb) {
MacRet mret;
mret.ret = ;
mret.mac0 = 0x11;
mret.mac1 = 0x22;
mret.mac2 = 0x33;
mret.mac3 = 0x44;
mret.mac4 = 0x55;
mret.mac5 = 0x66; _hidl_cb(mret); return Void();
} // Methods from ::android::hidl::base::V1_0::IBase follow. IBtaddr* HIDL_FETCH_IBtaddr(const char* /* name */) {
return new Btaddr();
} } // namespace implementation
} // namespace V1_0
} // namespace btaddr
} // namespace hardware
} // namespace android
//[ubuntu @btaddr]$ cat 1.0/default/Btaddr.h
#ifndef ANDROID_HARDWARE_BTADDR_V1_0_BTADDR_H
#define ANDROID_HARDWARE_BTADDR_V1_0_BTADDR_H #include <android/hardware/btaddr/1.0/IBtaddr.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h> namespace android {
namespace hardware {
namespace btaddr {
namespace V1_0 {
namespace 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; using ::android::hardware::btaddr::V1_0::IBtaddr;
using ::android::hardware::btaddr::V1_0::MacRet; struct Btaddr : public IBtaddr {
// Methods from IBtaddr follow.
Return<void> getBluetoothMacAddress(getBluetoothMacAddress_cb _hidl_cb) override; // Methods from ::android::hidl::base::V1_0::IBase follow. }; // FIXME: most likely delete, this is only for passthrough implementations
// extern "C" IBtaddr* HIDL_FETCH_IBtaddr(const char* name); } // namespace implementation
} // namespace V1_0
} // namespace btaddr
} // namespace hardware
} // namespace android #endif // ANDROID_HARDWARE_BTADDR_V1_0_BTADDR_H

4.添加service.cpp和启动此service的android.hardware.btaddr@1.0-service.rc文件

//[ubuntu @btaddr]# cat 1.0/default/service.cpp
[ubuntu @btaddr]$ cat 1.0/default/service.cpp
#define LOG_TAG "android.hardware.btaddr@1.0-service" #include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include <android/hardware/btaddr/1.0/IBtaddr.h>
#include <hidl/LegacySupport.h> #include "Btaddr.h" using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::btaddr::V1_0::implementation::Btaddr; int main()
{
configureRpcThreadpool(, true); Btaddr addr;
auto status = addr.registerAsService();
CHECK_EQ(status, android::OK) << "Failed to register btaddr HAL implementation"; joinRpcThreadpool(); return ;
} [ubuntu @btaddr]# cat 1.0/default/android.hardware.btaddr@1.0-service.rc
service btaddr-hal-- /vendor/bin/hw/android.hardware.btaddr@1.0-service
class core
user root
group root

5.修改编译service的Android.bp

[ubuntu @btaddr]# cat 1.0/default/Android.bp
cc_binary {
name: "android.hardware.btaddr@1.0-service",
vendor: true,
relative_install_path: "hw",
init_rc: ["android.hardware.btaddr@1.0-service.rc"],
srcs: [
"Btaddr.cpp",
"service.cpp",
],
cflags: [
"-Wall",
],
shared_libs: [
"libhidlbase",
"libhidltransport",
"libutils",
"android.hardware.btaddr@1.0",
"liblog",
"libutils",
"libbase",
],
}

在btaddr下mm,若能build过,Service端就实现好了

6.将编译出的service可执行程序编译进文件系统
在/device/$(Vender)/$(Product)/$(Product).mk中添加: PRODUCT_PACKAGES += android.hardware.btaddr@1.0-service

7.将这个hwservice注册到系统(这样getService()才能找到它) 在/device/$(Vender)/$(Product)/manifest.xml中添加:

<hal format="hidl">
<name>android.hardware.btaddr</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IBtaddr</name>
<instance>default</instance>
</interface>
</hal>

8.添加selinux权限
在device/qcom/sepolicy/common/hwservice_contexts中添加:

android.hardware.btaddr::IBtaddr     u:object_r:hal_btaddr_hwservice:s0
android.hardware.btaddr::MacRet u:object_r:hal_btaddr_hwservice:s0

在device/qcom/sepolicy/common/hwservice.te中添加:

type hal_btaddr_hwservice, hwservice_manager_type;

在device/qcom/sepolicy/msm8996/file_contexts中添加:

/(vendor|system/vendor)/bin/hw/android.hardware.btaddr@1.0-service    u:object_r:hal_btaddr_default_exec:s0

添加文件:device/qcom/sepolicy/msm8996/hal_btaddr_default.te

# cat device/qcom/sepolicy/msm8996/hal_btaddr_default.te 

type hal_btaddr_default, domain;
type hal_btaddr_default_exec, exec_type, vendor_file_type, file_type; allow hal_btaddr_default sysfs:file rw_file_perms;
allow hal_btaddr_default hwservicemanager_prop:file r_file_perms;
allow hal_btaddr_default hwservicemanager:binder { transfer call }; allow hal_btaddr_default hal_btaddr_hwservice:binder call;
allow hal_btaddr_default hal_btaddr_hwservice:hwservice_manager { add find }; allow hal_btaddr_default hidl_base_hwservice:hwservice_manager add; init_daemon_domain(hal_btaddr_default)

在/device/qcom/sepolicy/msm8996/hwservicemanager.te中添加:

allow hwservicemanager hal_btaddr_default:process getattr;
allow hwservicemanager hal_btaddr_default:binder { transfer call };
allow hwservicemanager hal_btaddr_default:file r_file_perms;
allow hwservicemanager hal_btaddr_default:dir search;

重新编译系统进行验证。

HIDL学习笔记的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  4. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  5. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  6. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  7. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记

    今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...

随机推荐

  1. 阿里云服务器创建swap分区

    阿里云服务器使用了4核8G内存配置,但最近由于jenkins构建时执行gradle打包安卓应用,导致即时的内存严重不足,线上应用长时间无法访问. 执行free命令才发现,swap分区一直是没有创建的. ...

  2. 读书笔记 C# 接口中的索引器之浅析

    在C#中,可以在类.结构或接口中用this关键字声明索引器,在索引器内部用get或set访问器访问类中集合的某项值.因此可以将索引器看作是类的属性一样去定义.索引器常用定义格式如下: public i ...

  3. S2 深入.NET和C#编程 笔试测试错题积累

    ---恢复内容开始--- <深入.NET平台和C#编程>内部测试题-笔试试卷错题积累 1: 1) 以下关于序列化和反序列化的描述错误的是( C). a) 序列化是将对象的状态存储到特定存储 ...

  4. Lookaside

    频繁申请和回收内存,会导致在内存上产生大量的内存碎片,从而导致最终无法申请内存.DDK提供了Lookaside结构来解决这个问题.可以将Lookaside结构想象成一个内存容器.在初始的时候,它先向W ...

  5. Problem C: 平面上的点——Point类 (III)

    Description 在数学上,平面直角坐标系上的点用X轴和Y轴上的两个坐标值唯一确定.现在我们封装一个“Point类”来实现平面上的点的操作. 根据“append.cc”,完成Point类的构造方 ...

  6. jaxb 组装及解析xml

    参考 http://blog.csdn.net/yanan_seachange/article/details/7325708 a.添加依赖 b.建立绑定关系 c.测试 a.添加依赖 <depe ...

  7. Linux平台搭建-----C语言

    下面内容是新手上路,各位高手路过勿喷!因为我第一次发布,可能页面设置或者其他做的不好,还请见谅~该文章只是作为我学习C语言的笔记以及记录学习进程的. 零基础学习C语言---搭建Linux平台开发环境 ...

  8. 20165326 java第七周学习笔记

    第七周学习笔记 MySQL(数据管理系统)学习 知识点总结: 不能通过关闭MySQL数据库服务器所占用的命令行窗口来关闭MySQL数据库. 如果MySQL服务器和MySQL管理工具驻留在同一台计算机上 ...

  9. hph 缓存机制

    bufferbuffer是一个内存地址空间,Linux系统默认大小一般为4096(4kb),即一个内存页.主要用于存储速度不同步的设备或者优先级不同的设备之间传办理数据的区域.通过buffer,可以使 ...

  10. OSPF路由协议(一)

    实验要求:使用OSPF协议,使各个PC之间能够相互通信 拓扑如下: 配置如下: R1enableconfigure terminal interface f0/0ip address 192.168. ...