Android HIDL学习 - 注册回调(整理2)

本文详细介绍了在Android O及以上版本中,如何利用HIDL(Hardware Interface Definition Language)实现跨进程间的回调机制,包括创建接口、定义回调、实现服务端逻辑及客户端测试程序的全过程。

概述

上一节我们学会了如何创建HIDL的server端和client端,对于那些没玩过Android O或者以上的BSP开发者而言,可以吹上一阵子牛逼了,毕竟比人家多了一个技能,面试的时候也可以装一下了_

OK,我们还知道了在Android O或者以上的Android版本上创建一个HAL模块的一般流程是如何的,我们这一节来看一个比较简单的东西,也是每个模块基本必不可少的一个玩意儿,那就是回调函数。

注册回调

怎么个回事呢,我们来举一个栗子:
在这里插入图片描述
很多现有的 HAL 实现会与异步硬件通信,这意味着它们需要以异步方式通知客户端已发生的新事件。HIDL 接口可以用作异步回调,因为 HIDL 接口函数可以将 HIDL 接口对象用作参数。
我们把HAL独立为一个单独的进程,client也是一个单独的进程,那么对于一般的模块而言,都是需要从底层(HAL以及以下)获取数据,比如sensor,需要获取sensor数据,Camera,需要获取camera的raw、yuv等数据流,那么对于软件设计而言,如果是同步的话,很简单,我们通过getXXX()函数来获取即可,但是如果是异步的,比如底层的实现是中端的机制,你不知道他什么时候会出来数据,那么这个时候通常的,我们会通过callback来实现异步的回调。

看下面的图就比较清楚了:
在这里插入图片描述官方关于回调的介绍请参考

实例

我们这一节就来实现简单的回调机制。
这个例子很简单,写一个简单的HAL模块,就跟之前的差不多,然后我们在.hal文件里面加入一个setCallback函数,传入一个callback指针,当我们HAL的server端起来的时候会起一个线程,每隔1秒钟时间调用一下传入的这个回调函数,实现回调的机制,OK,废话不多说,上代码。

1. 创建接口目录

首先,和上一篇naruto一样先创建文件目录,即定义接口的位置。
我们现在将该接口定义到vendor厂商目录中,如下:

mkdir -p vendor/mediatek/proprietary/hardware/interfaces/hello/1.0/default

2. 定义HIDL接口

其次,开始定义HIDL 能够访问到的接口IHello.hal

// The file path: vendor/mediatek/proprietary/hardware/interfaces/hello/1.0/IHello.hal
// 定义我们的包名
package vendor.mediatek.hardware.hello@1.0;  
// 导入回调接口
import IHelloCallback;

interface IHello {
   
   
    // 初始化服务端实例行为
    init();
    // 释放服务端
    release();
    // 用于客户端向服务端注册回调函数
    setCallback(IHelloCallback callback);
};

定义了三个接口

  • init:做一些初始化的动作
  • release:做一些释放的动作
  • setCallback:让client端设置一个callback方法到server端

下面来看看这个callback里面都定义了些啥,我们要为这个callback定义一个接口IHelloCallback.hal

package vendor.mediatek.hardware.hello@1.0;

interface IHelloCallback {
   
   
    oneway onNotify(HalEvent event);
};

这个接口里面有一个回调方法,可以让server传一个HalEvent的结构体到client端,这个结构体也是自定义的,在types.hal,可以定义自己喜欢的类型,这里只是定义了一个简单的int成员变量通过这个onNotify传递给客户端。

package vendor.mediatek.hardware.hello@1.0;

struct HalEvent {
   
   
   int32_t value;
};

3. 生成hal代码框架

OK,HIDL的接口定义好之后,我们来使用一条牛逼的指令为我们生产代码框架:

# 自动生成impl实例文件
hidl-gen -o vendor/mediatek/proprietary/hardware/interfaces/hello/1.0/default -Lc++-impl -rvendor.mediatek.hardware:vendor/mediatek/proprietary/hardware/interfaces -randroid.hidl:system/libhidl/transport vendor.mediatek.hardware.hello@1.0
# 自动生成编译控制文件Android.bp - 只有mk可以不生成
hidl-gen  -Landroidbp -rvendor.mediatek.hardware:vendor/mediatek/proprietary/hardware/interfaces -randroid.hidl:system/libhidl/transport vendor.mediatek.hardware.hello@1.0
# 自动生成编译控制文件Android.mk - 只有bp可以不生成
hidl-gen  -Lmakefile -rvendor.mediatek.hardware:vendor/mediatek/proprietary/hardware/interfaces -randroid.hidl:system/libhidl/transport vendor.mediatek.hardware.hello@1.0
# 增加顶层Android.bp编译控制内容 - 这个文件通过hidl-gen无法自动生成,需要其他脚本才可以自动生成,在这里我们只能手动编写增加这个文件
// The file path: vendor/mediatek/proprietary/hardware/interfaces/hello/Android.bp
// This is an autogenerated file, do not edit.
subdirs = [
    "1.0",
    "1.0/default",
]

以上是通过hidl-gen手动运行该命令自动生成的上述文件。执行起来还是很麻烦,在这里只是让大家知道hidl-gen是如何输入命令执行的。在真正开发过程中Google已经给我们提供了一个自动生成的脚本,就像前一篇所使用的update-makefiles.sh全部都给搞定,这样就不怕有些文件无法通过hidl-gen自动生成比如上面的Android.bp还需要手动编写或者某些文件遗漏等等细节问题。

# 上述那些文件,通过这个脚本将全部搞定,一步撸到底 很爽
./vendor/mediatek/proprietary/hardware/interfaces/update-makefiles.sh

现在的文件目录如下:

.
├── 1.0
│   ├── Android.bp	# 自动生成update-makefiles.sh或者手动执行hidl-gen命令
│   ├── Android.mk  # 自动生成update-makefiles.sh或者手动执行hidl-gen命令
│   ├── default
│   │   ├── Android.bp #自动生成update-makefiles.sh或者手动执行hidl-gen命令
│   │   ├── HelloCallback.cpp #自动生成update-makefiles.sh或者手动执行hidl-gen命令
│   │   ├── HelloCallback.h #自动生成update-makefiles.sh或者手动执行hidl-gen命令
│   │   ├── Hello.cpp #自动生成update-makefiles.sh或者手动执行hidl-gen命令
│   │   ├── Hello.h #自动生成update-makefiles.sh或者手动执行hidl-gen命令
│   │   ├── service.cpp #手动增加编辑 - 服务端注册启动入口
│   │   └── vendor.mediatek.hardware.hello@1.0-service.rc #用于开机自启动行为
│   ├── IHelloCallback.hal  # 手动定义回调接口
│   ├── IHello.hal 	# 手动定义接口
│   └── types.hal # 自定义数据类型
└── Android.bp  # 自动生成update-makefiles.sh或手动增加编辑

4. 编写服务端注册入口

在vendor分区,要起一个service来handle这个HIDL 接口,这个我们在上一节中有详细讲到,贴一下代码:

#include <vendor/mediatek/hardware/hello/1.0/IHello.h>
#include <hidl/LegacySupport.h>

using vendor::mediatek::hardware::hello::V1_0::IHello;
using android::hardware::defaultPassthroughServiceImplementation;

int main()
{
   
   
    return defaultPassthroughServiceImplementation<IHello>();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值