HwBinder入门篇-Android10.0 HwBinder通信原理(一)

2023-11-17

[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析

[Android取经之路] 系列文章:

《系统启动篇》

Android系统架构
Android是怎么启动的
Android 10.0系统启动之init进程
Android10.0系统启动之Zygote进程
Android 10.0 系统启动之SystemServer进程
Android 10.0 系统服务之ActivityMnagerService
Android10.0系统启动之Launcher(桌面)启动流程
Android10.0应用进程创建过程以及Zygote的fork流程
Android 10.0 PackageManagerService(一)工作原理及启动流程
Android 10.0 PackageManagerService(二)权限扫描
Android 10.0 PackageManagerService(三)APK扫描
Android 10.0 PackageManagerService(四)APK安装流程
《日志系统篇》

Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现​
《Binder通信原理》:

Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
Android10.0 Binder通信原理(二)-Binder入门篇
Android10.0 Binder通信原理(三)-ServiceManager篇
Android10.0 Binder通信原理(四)-Native-C\C++实例分析
Android10.0 Binder通信原理(五)-Binder驱动分析
Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
Android10.0 Binder通信原理(七)-Framework binder示例
Android10.0 Binder通信原理(八)-Framework层分析
Android10.0 Binder通信原理(九)-AIDL Binder示例
Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
Android10.0 Binder通信原理(十一)-Binder总结

《HwBinder通信原理》

HwBinder入门篇-Android10.0 HwBinder通信原理(一)
 HIDL详解-Android10.0 HwBinder通信原理(二)
HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
HwServiceManager篇-Android10.0 HwBinder通信原理(五)
Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
《编译原理》

编译系统入门篇-Android10.0编译系统(一)
编译环境初始化-Android10.0编译系统(二)
make编译过程-Android10.0编译系统(三)
Image打包流程-Android10.0编译系统(四
Kati详解-Android10.0编译系统(五)
Blueprint简介-Android10.0编译系统(六)
Blueprint代码详细分析-Android10.0编译系统(七)
Android.bp 语法浅析-Android10.0编译系统(八)
Ninja简介-Android10.0编译系统(九)
Ninja提升编译速度的方法-Android10.0编译系统(十)
Android10.0编译系统(十一)

 在前面我们写了一个《Binder通信原理》的系列文章,这次准备来写一写HwBinder的系列文章。

    HAL binder是Android O(8.0)专门用于HAL(Hardware Abstract Layer)层(native)进程与其clients之间的通信机制(clients可以是native进程,也可以是Java Framework进程)。HAL binder替代了早先使用的socket通信,其kernel层实际是基于原有的binder驱动,但为了配合Client与Server之间的数据传输,需要使用特定的中间层HIDL来进行接口与数据的转换。那么,相对之前的HAL通信方式(socket),基于HIDL的HAL通信有什么优势?从系统架构的角度,HIDL为客户端与服务端提供了清晰的接口;从效率的角度,binder IPC实际在传输数据上只有一次拷贝,而socket实际传输需要两次数据拷贝。

 

1.概述
    在Android 8.0 之前,Binder机制比较简单,只有一个驱动设备"/dev/binder",一个守护进行"/system/bin/servicemanager",一个binder库"/system/lib64/libbinder.so".

    在Android 8.0开始,Android引入了Treble的机制,为了方便Android系统的快速移植、升级,提升系统稳定性,Binder机制被拓展成了

"/dev/binder", "/dev/hwbinder","/dev/vndbinder"。

    我们原先使用的"/dev/binder",成为框架进程的专有节点,这意味着供应商进程无法再访问此节点。供应商进程可以访问 /dev/hwbinder,但必须将其 AIDL 接口转为使用 HIDL。

对于想要继续在供应商进程之间使用 AIDL 接口的供应商,需要使用 /dev/vndbinder(而非 /dev/binder)。

    Android8.0及之后的Binder域如下图所示:

2.HwBinder 框架
 Binder和HwBinder的一些差异
 Binder          -> HwBinder
 BpProxy          -> BpHwBinder
 BBinder           -> BHwBinder
 JavaBBinder         -> JHwBinder
 BinderProxy.java     -> HwRemoteBinder.java
 Binder.java          -> HwBinder.java

 HwBinder架构如下图所示:

在Android 8.0之前,Android Framework与Android HAL是打包成一个system.img的,而且Framework与HAL之间是紧耦合的,HAL是一个个的.so库,库和framework位于同一个进程。

Android8.0之前 的系统框架当中framework与HAL之间的一般架构框架是:

 在上图的这种架构中,每次Android的Framework进行升级时,对应的HAL层都需要跟着升级,费时费力,这也Android最新版本推广较慢的原因。

    在Android 8.0及之后,Android觉得这也不行,每次出了新版本,但是用的人很少,得让大家快速使用新版本。于是Android引入了一个Treble的架构,把vendor的一些功能和库与system进行分离,OEM厂商设计的内容都放到vendor中去,Android原生的放到system中,这样Android只要升级System就能快速完成版本的升级,在这个场景下,Android Framework放在了System空间,厂商的HAL库放在了Vendor空间,两者之间使用hwbinder进行通信,通信的接口语言为HIDL。

    Android8.0及之后 的系统框架当中framework与HAL之间的一般架构框架是:

下图展示了Android 有Treble和没有Treble的升级方式:

 

3.Hwbinder 与Binder的区别
3.1 Binder
    在Android 8.0之前,这是我们最熟悉也一直使用的Binder。Java层继承Binder,Native C/C++层继承Bbbinder,然后通过servicemanager进程注册实名Binder,然后通过已经创建好的Binder接口传递匿名Binder对象,拿到BinderProxy或者BpBinder以后,就可以Binder通信了。

在Android 8.0后,这个Binder机制继续保留,/dev/binder 设备节点成为框架进程的专有节点,这意味着供应商进程无法再访问此节点。

    如果你是系统厂商,在system分区有进程,/dev/biner机制还是可以继续使用,但是你的进程在vendor分区,那只能使用/dev/hwbinder 或者/dev/vndbinder.

    Binder机制需要两个进程都同属于System分区

3.2 HwBinder
    hwbinder和 binder不同,hwbinder是一套全新的流程,有单独的驱动设备"/dev/hwbinder",独立的守护进程"hwservicemanager",独立的SDK-"libhwbinder"

HwBinder机制可以跨System和Vendor分区使用

4. 为什么要引入hwbinder
    Android 8.0中引入了Treble机制,Treble 项目通过将底层供应商实现从 Android 内核框架中剥离出来,使Android更新变得更简单。这种模块化的设计允许分别独立更新平台和供应商提供的组件。让更新变得更轻松、更快速,然而,Treble 加强模块化设计还有一个目的:提高安全性。

    Treble引入后,新增了一个vendor.img, 即原先的system分区,被拆分为了system分区和vendor分区,soc及供应商的功能实现都需要放到vendor分区,这样将system和vendor相关的镜像分开,便于能方便地更新和升级system,并且不依赖vendor等底层。

    在Android 8.0之前,HAL是一个个的.so库,通过dlopen来进行打开,库和framework位于同一个进程, 在此之前的Android 系统架构当中,Android Framework 与Android HAL是打包成一个system.img的,而且Framework 与HAL之间是紧耦合的,通过链接的方式使用相应的硬件相关so库。

Android 8.0之前的通信机制如下图所示:

所以每次Android framework的升级需要对应的Android HAL升级,这需要供应商花费很多的人力去升级相应的 Vendor HAL Implemetation,这也就是导致Android版本升级很缓慢,很多用户几年之后,Android都不能得到及时更新。

    在Android8.0及以后的版本中,Android设计了一套新的机制来隔离HAL层,引入了一个HIDL的语言来定义Framework和HAL之间的接口

    在Android 8.0以及以后的版本当中,Android 更新了新的框架设计在新的框架设计当中,引入了一套叫HIDL的语言来定义Freamework与HAL之间的接口,Android Framework会在system分区当中,而VendorHAL Implemetation会在一个新定义的分区(Vendor.img)当中,这样刷新的system.img 才不会影响到Vendor HAL Implemetation。

    在Android 8.0及之后,HAL库和framework不在同一个进程,他们之间使用hwbinder进行进程间通信。

    Android 8.0引入Treble后,各层的通信机制如下:

5.HwBinder的通信原理
 HwBinder 通信采用 C/S 架构,从组件视角来说,包含 Client、 Server、 HwServiceManager 以及 HwBinder 驱动,其中 HwServiceManager 用于管理系统中的各种服务。

HwBinder 在 framework 层进行了封装,通过 JNI 技术调用 Native(C/C++)层的 HwBinder 架构。

 HwBinder 在 Native 层以 ioctl 的方式与 Binder 驱动通讯。

 HwBinder通信原理图如下:

HwBinder通信流程如下:

首先服务端需要向HwServiceManager进行服务注册,HwServiceManager有一个全局的service列表mServiceMap,用来缓存所有服务的对象和name。

客户端与服务端通信,需要拿到服务端的对象,由于进程隔离,客户端拿到的其实是服务端的代理,也可以理解为引用。客户端通过HwServiceManager从mServiceMap中查找服务,HwServiceManager返回服务的代理。

拿到服务对象后,我们需要向服务发送请求,实现我们需要的功能。通过 BpHwBinder 将我们的请求参数发送给 内核,通过共享内存的方式使用内核方法 copy_from_user() 将我们的参数先拷贝到内核空间,这时我们的客户端进入等待状态。然后 Binder 驱动向服务端的 todo 队列里面插入一条事务,执行完之后把执行结果通过 copy_to_user() 将内核的结果拷贝到用户空间(这里只是执行了拷贝命令,并没有拷贝数据,binder只进行一次拷贝),唤醒等待的客户端并把结果响应回来,这样就完成了一次通讯。

 

    在这里其实会存在一个问题,Client和Server之间通信是称为进程间通信,使用了HwBinder机制,那么Server和HwServiceManager之间通信也叫进程间通信,Client和Server之间还会用到HwServiceManager,也就是说HwBinder进程间通信通过HwBinder进程间通信来完成,这就好比是 孵出鸡前提却是要找只鸡来孵蛋,这是怎么实现的呢?

    HwBinder的实现比较巧妙:预先创造一只鸡来孵蛋:HwServiceManager和其它进程同样采用HwBinder通信,HwServiceManager是Server端,有自己的HwBinder对象(实体),其它进程都是Client,需要通过这个HwBinder的引用来实现HwBinder的注册,查询和获取。

    HwServiceManager提供的HwBinder比较特殊,它没有名字也不需要注册,当一个进程使用BINDER_SET_CONTEXT_MGR_EXT命令将自己注册成HwServiceManager时HwBinder驱动会自动为它创建HwBinder实体(这就是那只预先造好的鸡)。

    其次这个HwBinder的引用在所有Client中都固定为0(handle=0)而无须通过其它手段获得。也就是说,一个Server若要向HwServiceManager注册自己HwBinder就需要通过0这个引用号和HwServiceManager的Binder通信。

    类比网络通信,0号引用就好比域名服务器的地址,你必须预先手工或动态配置好。要注意这里说的Client是相对HwServiceManager而言的,一个应用程序可能是个提供服务的Server,但对HwServiceManager来说它仍然是个Client。

    

/system/tools/hidl/

根据HAL接口 .hal来产生相应的Proxy(client端接口)以及stub(server端接口)

/system/libhidl

HIDL状态与HAL服务管理接口

/hardware/interfaces/

各个模块HAL层接口,每个模块都包含了一个Android.bp的脚步来生成对应的代理(Proxy)与存根对象(stub),如radio接口IRadio.hal,sensors接口ISensors.hal

android_os_HwBinder.java\cpp (JNI)

Java层HAL binder的JNI代码,负责将Java层的请求传递给相应的server进程

/dev/hwbinder

/kernel/msm-4.9/drivers/android/binder.c

/kernel/msm-4.9/drivers/android/binder_alloc.c

hwservicemanager

/system/hwservicemanager/hwservicemanager.rc

/system/hwservicemanager/ServiceManager.cpp

/system/hwservicemanager/HidlService.cpp

/system/hwservicemanager/HidlService.h

libhwbinder

/system/libhwbinder/Binder.cpp

/system/libhwbinder/BpHwBinder.cpp

/system/libhwbinder/IInterface.cpp

/system/libhwbinder/IPCThreadState.cpp

/system/libhwbinder/ProcessState.cpp

/system/libhwbinder/Parcel.cpp

/system/libhwbinder/include/hwbinder/Binder.h

/system/libhwbinder/include/hwbinder/BpHwBinder.h

/system/libhwbinder/include/hwbinder/IBinder.h

/system/libhwbinder/include/hwbinder/IInterface.h

/system/libhwbinder/include/hwbinder/IPCThreadState.h

/system/libhwbinder/include/hwbinder/ProcessState.h

/system/libhwbinder/include/hwbinder/Parcel.h

 

7.总结
  Android引入Treble机制后,扩展了一个vendor分区,为了能够快速的进行升级,做了隔离HAL层的机制,为了System/System、System/Vendor、Vendor/Vendor 之间进行不同的进程间通信,把原有的Binder机制拆分成了Binder、HwBinder、VndBinder。

Binder和VndBinder 共用一套libbinder、servicemanager的代码,使用AIDL接口,两者不能共存。

  HwBinder采用了单独的libhwbinder、hwservicemanager的代码,单独管理,使用HIDL接口。

  三者之间互不干扰,在方便系统升级的同时,又提升了系统的安全和稳定性。

 

参考:

《Android Treble Architecture: Part 3 - Changes for Treble[Binder & ServiceManager]》

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HwBinder入门篇-Android10.0 HwBinder通信原理(一) 的相关文章

  • PLSQL之动态SQL与异常

    1 动态 SQL 动态 SQL 是指在PL SQL程序执行时生成的 SQL 语句 编译程序对动态 SQL 不做处理 而是在程序运行时动态构造语句 对语句进行语法分析并执行 DDL 语句命令和会话控制语句不能在 PL SQL 中直接使用 但是

随机推荐

  • 微信公众号-测试号

    最近碰到了一个H5的公众号项目 需要openid来判断用户是否存在 视乎好多年都没碰这玩意了 完全忘记了 挨着看文档 一路各种坑 好不容易用测试号把本地测试环境调通了 环境不同可能使用的方法方式都不一样 微信测试号 需要微信扫码登陆 1 获
  • unity图片相似度识别

    public static SimilarPhoto Instance
  • 2022最新快捷键大全

    一 常用快捷键 ctrl c v 复制 粘贴 ctrl a 全选 ctrl s 保存 ctrl f 查找 ctrl z 撤销 ctrl x 剪切 win r 命令运行框 win d 隐藏 显示当前页面或者应用 win l 锁屏 alt Ta
  • json数组如何转换成string类型(超级好用)

    先上代码 下面解释 这个jar包地址之后更新的时候再给出来的 包的地址 JSONObject job ace text a 此时job里面的数据格式为 logid 2075 words result words acb words and
  • Using / for division outside of calc() is deprecated and will be removed in Dart Sass 2.0.0

    项目 taro3 vue3 描述 运行时警告 Deprecation Warning Using for division outside of calc is deprecated and will be removed in Dart
  • LeetCode 102. 二叉树的层序遍历BFS

    LeetCode 102 二叉树的层序遍历BFS 给你二叉树的根节点 root 返回其节点值的 层序遍历 即逐层地 从左到右访问所有节点 示例 1 输入 root 3 9 20 null null 15 7 输出 3 9 20 15 7 示
  • 机器学习:正则化

    正则化 引入正则化的目的是为了解决过拟合问题 左边的图中蓝色的线是目标函数 随机产生五个带噪声的点 我们理想的拟合曲线为红色的线 虽然有些许误差 但是整体拟合情况和目标函数接近 但是 事先不知道需要用二次曲线来拟合这些点 如果使用了更高次方
  • Vue2/Vue3 响应式原理

    Vue 2 x 版本与 Vue 3 x 版本的响应式实现有所不同 Vue 2 x 响应式基于 ES5 的 Object defineProperty 实现 Vue 3 x 响应式基于 ES6 的 Proxy 实现 Vue 2 响应式原理 V
  • Halcon与WPF联合编程

    环境 VS2017 halcon12 1 新建WPF应用程序完成后 解决方案资源管理器 引用处右键 添加引用如下两个dll 只引入第一个也可以 2 工具箱 空白处右键 选择项 只添加halcondotnet dll 文件位置同上 这样hal
  • 【TVM帮助文档学习】开始使用TVMC Python: TVM的高级API

    本文翻译自Getting Starting using TVMC Python a high level API for TVM tvm 0 9 dev0 documentation 首先我们需要准备好示例使用resnet模型 如果你还没有
  • [技术分享]Android平台实时音视频录像模块设计之道

    实现背景 录像有什么难的 无非就是数据过来 编码保存mp4而已 这可能是好多开发者在做录像模块的时候的思考输出 是的 确实不难 但是做好 或者和其他模块有非常好的逻辑配合 确实不容易 好多开发者希望聊聊录像模块 实际上录像这块 需求层面的东
  • 浏览器缓存机制及其分类

    聚沙成塔 每天进步一点点 专栏简介 强缓存 Cache Control 和 Expires 协商缓存 ETag 和 Last Modified 写在最后 专栏简介 前端入门之旅 探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦
  • 解决ros安装 使用roscore命令测试问题

    本人安装教程完成ROS的安装后 在进行测试如图1命令 出现 解决办法输入完命令1后要输入命令2才行 即可测试成功 测试成功的界面如下
  • caxa线切割怎样画链轮,收藏:Autocad实战教程-线切割画链轮

    Autocad实战教程 线切割画链轮 今天小编为各位朋友准备的内容是Autocad实战教程 线切割画链轮 希望能对各位朋友有所帮助 用AutoCAD绘制链轮首先要知道一些参数 d1为链条滚子直径 套铜直径 p为节距 链条两孔中心的距离也是链
  • c/c++开发时的VsCode插件

    Name Align Spaces Id OldStarchy align spaces Description Align operators without modifying the code 在不修改代码的情况下对齐操作符 Vers
  • 华为杯数学建模(准备)<2018 - 2022>

    前言 这里简单总结一些资料 为后期个人参赛做准备 其中的优秀案例皆以博客 链接的形式总结归纳 详细见对应原作者博客 基础知识 一些需要提前掌握的算法 1 时间序列算法 拟合插值算法 基础的图论算法 2 多元线性回归 3 整数规划 线性规划
  • 8. 让java性能提升的JIT深度解剖

    JVM性能调优 1 C1 C2与Graal编译器 1 1 C1编译器 1 2 C2编译器 1 3 分层编译 2 热点代码 3 热点探测 4 方法调用计数器 5 回边计数器 6 编译优化技术 6 1 方法内联 7 锁消除 8 栈上分配 9 逃
  • qt多文档

    http blog csdn net siren0203 article details 5661541 转载于 https www cnblogs com tiandsp p 7580571 html
  • 如何将照片中的文字转变成可编辑的文章(如何将书上的文字转变为可编辑的文字)

    在工作中 我常常在想 要是能把纸上有用的文字快速输入到电脑中 不用打字录入便可以大大提高工作效率该有多好呀 随着科技的发展 这个问题在不断的解决 例如 现在市场上的扫描仪就带有OCR软件 可以把扫描的文字转换到电脑中进行编辑 但是 对于我们
  • HwBinder入门篇-Android10.0 HwBinder通信原理(一)

    Android取经之路 的源码都基于Android Q 10 0 进行分析 Android取经之路 系列文章 系统启动篇 Android系统架构Android是怎么启动的Android 10 0系统启动之init进程Android10 0系