2

HwServiceManager篇-Android10.0 HwBinder通信原理(五)

 5 months ago
source link: https://blog.csdn.net/yiranfeng/article/details/107922919
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

摘要:本节主要来讲解Android10.0 HwServiceManager的通信原理

阅读本文大约需要花费34分钟。

文章首发微信公众号:IngresGe

专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!

欢迎关注我的公众号!

20200113052246361.jpg

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

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

《系统启动篇》

《日志系统篇》

《Binder通信原理》

  《HwBinder通信原理》

《编译原理》

1.概述

    HwServiceManager是HAL服务管理中心,负责管理系统中的所有HAL服务,由init进程启动。

   HwServiceManager 的主要工作就是收集各个硬件服务,当有进程需要服务时由HwServiceManager 提供特定的硬件服务。

2.HwBinder架构

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lpcmFuZmVuZw==,size_16,color_FFFFFF,t_70

HwBinder通信原理:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lpcmFuZmVuZw==,size_16,color_FFFFFF,t_70

3.hwservicemanager的启动

    在init.rc中,当init进程启动后,会去启动servicemanager、hwservicemanager、vndservicemanager 三个binder的守护进程

20200810214748668.jpg

hwservicemanager.rc 文件如下:

4.HwServiceManager调用栈

    在分析源码之前,我们先来看下上下文的粗略调用关系,HwServiceManager的调用栈信息如下:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lpcmFuZmVuZw==,size_16,color_FFFFFF,t_70

5.源码分析

    下面我们正式进入HwServiceManager的源码分析。

    HwServiceManager时序图如下:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lpcmFuZmVuZw==,size_16,color_FFFFFF,t_70

5.1 main()

    HwServiceManager 启动时主要需要完成以下几件事情:

  • 将ServiceManager、TokenManager 注册到mServiceMap表中

  • 根据ServiceManager找到为Binder对象,得到的Binder对象为BnHwServiceManager,最终转换为本地的Binder对象-BHwBinder,为后续流程处理做准备

  • 初始化/dev/hwbinder驱动,为其分配一块虚拟内存用于IPC数据交换

  • 向hwbinder注册HAL服务管家(IPC上下文管理者)

  • 进入死循环,调用epoll_wait() 监听/dev/hwbinder是否有数据可读,如有则调用回调执行指令,根据client传入的code,从而调用get()\add()\addWithChain()\list() 等接口,来查询、注册hwbinder的hal服务

 接下来针对main()的整个流程做拆解分析。

5.2 ServiceManager::add()

  将ServiceManager、TokenManager 注册到mServiceMap表中

5.2.1 getBinderCallingContext()

  先获取当前binder线程的对象,再获取其调用的pid、sid 上下文信息

5.2.2 IPCThreadState::self()

  用来获取当前binder线程的对象,如果没有对象,就创建一个

5.2.3 IPCThreadState::IPCThreadState()

  用来做一些初值赋值,主要是获取ProcessState的对象,存入mProcess

5.2.4 ProcessState::self()

  这是一个单例的实现,在一个进程中,只会创建一次ProcessState对象

5.2.5 ProcessState::ProcessState()

  打开“/dev/hwbinder”,得到hwbinde句柄,赋给mDriverFD,后面该进程中就通过这个句柄和hwbinder驱动进行通信

  同时,申请一块(1M-8K)的虚拟内存空间,用来接收事务

5.2.6 open_driver()

  打开/dev/hwbinder驱动,比较binder比较协议版本是否相同,不同则跳出,同时设置最大的binder线程个数

5.2.7 ServiceManager::addImpl()

  获取当前binder调用的pid、sid 上下文信息后,开始注册ServiceManager自身,即把ServiceManager对象注册到mServiceMap中

  在过程中,要进行selinux检查,确认该进程有权限添加service后,再检查是否有重复注册,而且如果子类在父类上注册,则注销它,

  排除一切问题后,把需要注册的服务,注册到mServiceMap中,最后建立一个死亡连接,当服务挂掉时会接收到通知,做一些清理工作。

5.3 toBinder()

  根据ServiceManager找到对应的Binder对象,最终找到的Binder对象为BnHwServiceManager

转换一下:

  这里就有一个疑问getBnConstructorMap()获取的Binder对象,是从哪里来的呢?

  这里传入的description是IServiceManager的description,所以我们回到IServiceManager的实现中去,在ServiceManagerAll.cpp的开头有下面这么一段:

  __attribute__((constructor)) 不是标准C++,他是GCC的一种扩展属性函数。constructor属性使得函数在执行进入main()之前被自动调用。

  所以在HwServiceManager进程中,在serviec.cpp的main()函数执行之前会先执行__attribute__((constructor))中的内容,从这里可以看到__attribute__((constructor)) 中把 BnHwServiceManager 对象和BsServiceManager对象,分别插入了BnConstructorMap 和BsConstructorMap的map中,

  当main()启动后,其他函数调用getBnConstructorMap().get()时,就能获得BnHwServiceManager对象,所以我们这里的getOrCreateCachedBinder()最终获得的Binder对象就是BnHwServiceManager。

  BnHwServiceManager类继承关系如下图展示:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lpcmFuZmVuZw==,size_16,color_FFFFFF,t_70

5.4 ProcessState::becomeContextManager()

  让HwServiceManager成为整个系统中唯一的上下文管理器,其实也就是service管理器,这样我们就可以把HwServiceManager称之为守护进程。

5.5 HwBinderCallback::setupTo()

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lpcmFuZmVuZw==,size_16,color_FFFFFF,t_70

  setupTo()主要是把HwBinderCallback对象作为回调,加入到Lopper中,fd为之前打开的hwbinder句柄,ident:POLL_CALLBACK, events:EVENT_INPUT,调用epoll_ctl()来监听fd的变化,为后面回调处理做准备。

5.5.1 setupPolling()

  根据setupTo()的调用栈可知,setupTransportPolling最终会调到setupPolling(),主要用来配置一个hwbinder线程,往mOut写入一个code:BC_ENTER_LOOPER,用来后面和hwbinder进行通信,再把hwbinder的句柄赋值给fd

5.5.2 IPCThreadState::talkWithDriver()

  这里主要是把之前mOut的内容(code:BC_ENTER_LOOPER)写入hwbinder驱动,从binder驱动读入返回值,存入mIn

5.5.3 Looper::addFd()

  fd放入线程epoll中,epoll_wait等待时,当fd有数据接入,我们就可以处理相应的数据

5.6 ClientCallbackCallback::setupTo()

  把ClientCallbackCallback 加入Lopper,存入全局列表mRequests中,epoll监听fdTimer的变化

5.7 pollAll()

  HwServiceManager 会启动一个死循环来等待事件、分析时间,这个等待的入口就是pollAll(),先简略的看一下pollAll()的上下文关系。

  pollAll()的调用栈如下:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lpcmFuZmVuZw==,size_16,color_FFFFFF,t_70

 传入的timeoutMillis为-1

5.7.1 Looper::pollOnce()

  检查response是否有需要处理,最终调用pollInner()

5.7.2 Looper::pollInner()

  调用epoll_wait,等待epoll的消息,epoll_wait()类似于select()调用,监听EPOLL的事件发生,最大允许16个EPOLL事件上报,当有事件上报时,调用之前存入mRequests中的所有回调,例如HwBinderCallback 、ClientCallbackCallback 的handleEvent

我们这里以HwBinderCallback::handleEvent()为回调的handler处理为例进行分析。

5.7.3 HwBinderCallback::handleEvent()

  handleEvent调用栈:

20200810215704571.png

 最终会调用到IPCThreadState::handlePolledCommands()

5.7.4 IPCThreadState::handlePolledCommands()

  从hwbinder去除命令并执行命令,最后将mOut的数据写入hwbinder驱动

5.7.5 IPCThreadState::getAndExecuteCommand()

  从hwbinder取出cmd命令,然后执行这些命令

5.7.6 IPCThreadState::executeCommand()

  执行命令,hwbinder和hwservicemanager 通信的常用命令为 BR_TRANSACTION

5.7.7 BHwBinder::transact()

  根据传入的BR_TRANSACTION,最终调用到BnHwServiceManager的transact,但是由于BnHwServiceManager没有transact(),所以调用父类的transact(),即BHwBinder::transact

5.7.8 BnHwServiceManager::onTransact()

  最终会调用到这来处理其他进程发来的请求, 其实最后做事的是 ServiceManager对象,根据client传入的code,来执行不同的接口

  例如有进程向注册一个hidl的服务时,调用registerAsService()时,在Android10.0上最终是调用addWithChain()接口,这里的code是12,

  一个进程需要获取某个hidl服务时,需要调用get()接口,这里的code是1

    HwServiceManager作为HwBinder的守护进程,主要作用就是收集各个硬件服务,当有进程需要服务时由 HwServiceManager 提供特定的硬件服务。

7.代码路径:

我的微信公众号:IngresGe

20200113052246361.jpg

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK