2

JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)

 1 year ago
source link: https://blog.csdn.net/yiranfeng/article/details/108038035
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 JAVA层HIDL服务的获取原理

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

文章首发微信公众号:IngresGe

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

欢迎关注我的公众号!

20200113052246361.jpg

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

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

《系统启动篇》

《日志系统篇》

《Binder通信原理》

  《HwBinder通信原理》

《编译原理》

上一节,我们学习了JAVA层 HIDL服务的注册获取原理,这一节我们来看看JAVA层HIDL服务的获取原理。

5. 获取服务

  JAVA层HIDL服务获取如下图所示:

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

5.1 获取服务调用栈

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

5.2 onClick()

5.3 getService()

这是一个JNI接口,参考上一节《JAVA层HIDL服务的注册原理》中的JNI的转换,在JNI层,进入JHwBinder_native_getService()

5.4 JHwBinder_native_getService

5.5 getRawServiceInternal()

getRawServiceInternal()步骤如下:

1.获取HwServiceManager的代理对象

2.获取IDemo 这个hidl服务的transport,来确认是绑定式服务,还是直通式服务

3.根据transport类型,调用不同的接口来获取服务对象 (我们设计的IDemo是绑定式hidl服务)

5.6 BpHwServiceManager::get()

_hidl_get流程如下:

1.准备两个Parcel结构-- _hidl_data,_hidl_reply

2.组装Parcel数据

3.写入RPC头信息"[email protected]::IServiceManager"

4.写入服务名称,如果没有配置的话,name为"default"

5.调用remote的transact,发送 1 /* get */的命令获取hidl服务

7.得到返回的reply数据

8.从reply中读取hidl binder的信息,转换成hidl service,发送出去

::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>> BpHwServiceManager::_hidl_get(::android::hardware::IInterface *_hidl_this, ::android::hardware::details::HidlInstrumentor *_hidl_this_instrumentor, const ::android::hardware::hidl_string& fqName, const ::android::hardware::hidl_string& name) {

根据如下调用栈所示,BpHwBinder::transact()最终会转到BnHwServiceManager::_hidl_get()

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

5.7 BnHwServiceManager::_hidl_get()

_hidl_get流程如下:

       1.获取hidl服务的fqName

       2.获取hidl服务的name

       3.根据hidl服务的fqName和name,从HwServiceManager的hidl service的map中拿到服务对象

       4.把reply信息写入Parcel

       5.把获取的hidl服务转成IBinder对象

       6.把转换后的IBinder对象,写入reply的Parcel数据中

       7.通过回调,把reply的Parcel数据给发给client

5.7.1 ServiceManager::get()

5.7.2 ServiceManager::lookup()

  主要是根据fqName和name从 HwServiceManager的服务map:mServiceMap 中找到对应的hidlservice

5.7.3 HidlService::getService()

返回hidlservice的mService成员

HwServiceManager中hidl服务的管理map:

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

5.8 toBinder()

  toBinder接口将IBase对象转换为binder对象,其实就是从BpHwBase中拿到其成员变量mRemote中的BpHwBinder对象

5.9 JHwRemoteBinder::NewObject()

  在JNI层将调用JHwRemoteBinder::NewObject()函数来创建一个Java层HwRemoteBinder对象,转换hidlservice,使之成为一个Java层HwRemoteBinder对象

5.10 asInterface(android.os.IHwBinder binder)

  通过服务查询得到HwRemoteBinder对象,这个只是传输层面的对象而已,需要转换为业务层面的对象,这个是由IXXX.asInterface函数完成

6. Client-Server接口调用

  JAVA层 Client和Server的对象转换如下图所示:

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

在[4] 和[5]节中,我们知道了服务注册registerService()和获取服务getService()的流程,接下来我们再看一看接口调用是如何进行的。

       上面调用的流程,其实和registerService()、getService()类似,都是组装Parcel数据,准备服务端的code,调用HwBinderProxy.transact()发送到服务端。

       但是和服务注册不同的是,在服务注册中,Native的HwServiceManager是Server端,服务实体是Client端。接口调用时,服务实体是Server端。

       服务端接收到CLient的请求后,根据下图的流程,最终流转到服务实体的onTransact()中,对解析出来的Parcel数据进行处理。

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

7.代码路径

我的微信公众号:IngresGe

20200113052246361.jpg

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK