Android开发

[024]binder,hwbinder,vndbinder之间

2020-02-12  本文已影响0人  王小二的技术栈

1 前言

先复制一段来自于android官方文档的文字
https://source.android.google.cn/devices/architecture/hidl/binder-ipc

一直以来,供应商进程都使用 Binder 进程间通信 (IPC) 技术进行通信。在 Android 8 中,/dev/binder 设备节点成为框架进程的专有节点,这意味着供应商进程无法再访问此节点。供应商进程可以访问 /dev/hwbinder,但必须将其 AIDL 接口转为使用 HIDL。对于想要继续在供应商进程之间使用 AIDL 接口的供应商,Android 会按以下方式支持 Binder IPC。

Android 8 支持供供应商服务使用的新 Binder 域,访问此域需要使用 /dev/vndbinder(而非 /dev/binder)。添加 /dev/vndbinder 后,Android 现在拥有以下 3 个 IPC 域:

2 举个例子

看了上面一段文字之后,可能很多人还是比较懵逼,我来举一个例子:

假如手机中有如下3类进程

a.应用进程:

Camera APP
手电筒 APP

b.框架进程:

System Server进程

c.供应商进程:

Camera HAL进程
Light HAL进程

这些进程之间需要使用Binder机制跨进程通信,Android提供了三个Binder设备节点dev/binder,dev/hwbinder,dev/vndbinder,也就是Android系统同时提供了三个独立运行的Binder通信模块,Android团队规定每类进程使用的这三个Binder通信模块的规则如下图:


3 三种Binder介绍以及之间的联系

3.1 dev/binder

这个是我们最熟悉的Binder,App开发中,ActivityManagerService用的都是这个,Java继承Binder,C++中继承Bbbinder,然后通过servicemanager进程注册实名Binder,然后通过已经创建好的Binder接口传递匿名Binder对象,拿到BinderProxy或者BpBinder以后,就可以Binder通信了。

3.2 dev/vndbinder

其实dev/vndbinde和dev/binder使用方式基本一样而且是共用一套Binder SDK,也是Java继承Binder,C++中继承Bbbinder,但是通过vndservicemanager进程注册实名Binder,然后通过已经创建好的Binder接口传递匿名Binder对象,拿到BinderProxy或者BpBinder以后,就可以Binder通信了。如何在使用同一套Binder SDK的代码,最后访问的设备节点变成dev/vndbinder,servicemanager变成vndservicemanager。

其实和简单,只要在你这个进程初始化的时候执行下面这个代码

ProcessState::initWithDriver("/dev/vndbinder");
dev/binder和dev/vndbinder无法在一个进程中同时使用

细心的读者肯定发现上面的图中三类进程的任意一个进程无法同时使用dev/binder和dev/vndbinder,这一点不单是android官方约定,也是目前android binder sdk的限制,因为两者都是共用Binder SDK,所以只能指定一个设备节点,要么dev/binder,要么dev/vndbinder

3.3 dev/hwbinder

那么dev/hwbinder是如何解决与dev/binder或dev/vndbinder之间的共存问题?有人肯定想到了,很简单,我们把所有Binder SDK复制一套新的Hw Binder SDK,改名成dev/hwbinder,HwBinder,HwBbinder,hwservicemanager,HwProcessState,这样子不就可以和dev/binder或dev/vndbinder共存了嘛?其实android团队就会类似这样子干的。

但是他们想hwbinder是为了规范hal层,毕竟hal层是操作硬件的,所以他们不应该提供这么自由,这么麻烦的接口定义。
他们的目标有两个:
1.不能那么自由,强制所有供应商按照android官方定义的hal接口来实现
2.不能增加供应商开发人员的学习成本,学习一套复杂的Hw Binder SDK
为了达成上述的两个目标,android团队想出了HIDL这个方案。

4 HIDL是什么

具体HIDL做了什么,我不细讲了,简单描述一下:
假如Android官方定义了一个ILight.hal的HAL层接口

Interface ILight {
    void turnOn();
    void turnOff();
}

通过编译会自动生成如下两个类LightServer和LightClient的java对象和c++对象。

供应商只需要简单的继承LightServer,并实现turnOn和turnOff的抽象方法,就可以完成Light接口的实现,以及Light服务注册到hwservicemanager的代码。

需要使用ILight接口的进程,只需要调用sp<ILight> lightClient= ILight::tryGetService(这个方法是自动生成的,不是我们声明的)就可以完成从hwservicemanager获得Light服务的Proxy对象,调用lightClient的turnOn和turnOff接口就可以完成ILight的Binder接口调用。

HIDL与AIDL的区别

看了上面的文字描述,应该明白了HIDL比AIDL做的事情更多:
AIDL在Server端串联Interface和Binder或者Bbbinder,在Client端串联Interface和BinderProxy或者Bpbinder
HIDL则是串联Interface->Hw Binder SDK->dev/hwbinder

5 总结

为什么Android团队要大费周章搞出那么多Binder,我觉得有以下几个原因:

1.可以发现App不可能直接跨过FWK调用HAL层接口,FWK和HAL之间的接口也是安卓官方限定的,这样子App的代码和FWK的代码可以快速的移植到一个新的平台,这就是安卓的Project Treble计划,把硬件HAL和安卓FWK,APP层剥离开,配合上mainline计划,以后Android系统工程师能改的东西越来越少。

2.估计这个是Android团队绞尽脑汁想出来的KPI,我猜的。

上一篇下一篇

猜你喜欢

热点阅读