文档章节

android的Binder通信机制java层浅谈-android学习之旅(88)

fengsehng
 fengsehng
发布于 2016/11/09 09:07
字数 2029
阅读 8
收藏 0

1.Service Manager的Java代理对象

在Java层中,Service Manager的代理对象类型为ServiceManagerProxy。它继承并且实现了IServiceManager接口,其中四个成员函数和一个变量如下:
getService、checkService:获取Java服务代理对象
addService:注册Java服务
listService:获取已经注册的java服务表mRemote:类型为Ibinder,指向了一个BinderProxy对象。这个对象用来描述Java服务代理对象,内部的成员变量mObject,指向c++层中的一个Binder代理对象。Java服务代理和c++层中的服务代理由此联系起来。
在Java层中,Service Manager的代理对象由Service Manager类创建。
其成员函数getIServiceManager,作用就是用来获取Service Manager的Java远程接口了,而这个函数又是通过ServiceManagerNative类的成员方法asInterface来获取Service Manager的Java远程接口的。
这里写图片描述
从上面代码可看出在调用asInterface函数之前,首先要通过getContextObject函数来获得一个BinderProxy对象。
getContextObject是一个JNI方法:
这里写图片描述
第3行调用函数获得一个句柄为NULL的Binder代理对象。第4行使用函数javaObjectForIBinde为这个对象创建一个Java服务代理对象(BinderProxy)。
第3行调用函数获得一个句柄为NULL的Binder代理对象。第4行使用函数

javaObjectForIBinde为这个对象创建一个Java服务代理对象(BinderProxy)。

这里写图片描述
这里传进来的参数是一个BpBinder的指针,而BpBinder::checkSubclass继承于父类IBinder::checkSubclass,它什么也不做就返回false。于是直接向下执行:

会创建一个Java层的BinderProxy对象

这里写图片描述
17行中,由于这个BpBinder对象是第一创建,它里面什么对象也没有,因此,这里返回的object为NULL。继续执行

最后的代码如下:

这里写图片描述

小结:整个的过程就是在Java层,我们拥有了一个Service Manager远程接口ServiceManagerProxy,而这个ServiceManagerProxy对象在JNI层有一个句柄值为0的BpBinder对象与之通过gBinderProxyOffsets关联起来。这样获取Service Manager的Java远程接口的过程就完成了。

2Java服务接口的定义

在实现Java服务之前,必须要定义这个Java服务接口。在Android中通过AIDL语言来定义Java服务接口。
首先,以一个硬件访问服务为例,其aidl文件如下:
setVal设置变量
getVal获取变量
文件编译后会生成一个IFregService.java文件
这里写图片描述

IFregService.java文件展开如下:

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

总结:aidl文件编译之后,就是根据IFregService接口的定义生成相应的Stub和Proxy类,即实现这个FregService的Server必须继承于这里的IFregService.Stub类,而这个FregService的远程接口就是这里的IFregService.Stub.Proxy对象获得的IFregService接口。

3Java服务接口的启动

Java服务和binder服务一样,同样需要将自己注册到Service Manager中,但是由于system和Android进程启动的时候都会在内部启动一个线程池,所以运行在里面的Java服务启动时,只需要注册服务,不需要添加线程池。
服务FregService是从IFregService.Stub类继承来的,是一个实现了IFregService接口的Java服务

定义如下

这里写图片描述
第8行首先创建一个服务FregService,然后接着调用ServiceManager类的静态成员函数addService来注册。
首先分析创建过程:new FregService
由于硬件访问服务FregService继承了IFregService.Stub类,这个类继承了Binder类,因此最终创建服务时会调用Binder类的构造函数。
构造函数调用了成员函数init来执行初始化工作,init是一个JNI方法。
这里写图片描述

小结:注册Java服务时,并不是真的将Java服务注册到Service Manager中,而是将它对应的一个类型为JavaBBinder的本地对象注册到Service Manager中。当这个JavaBBinder类型的本地对象收到来自client进程的进程间通信请求时,他就需要将这个请求发送给Java服务来处理。

4Java服务代理对象的获取

ava服务在注册到Service Manager之后,Android应用程序就可以通过它来获取一个Java服务的代理对象,通过代理对象,就可以使用相应的Java服务了。
因此,客户端想要使用服务,首先要获取Java服务的代理对象,下面分析流程:

客户端中代码如下:

这里写图片描述
在第7行①通过ServiceManager类的静态函数getService获取名称为”freg”的Java服务代理对象;②使用IFregService.Stub类的函数asInterface将其转化为实现了服务接口的代理对象。

小结:经过两个函数的封装,getService函数相当于下面语句这就是我们想要获得的Java服务代理对象了。再获取了Java代理对象后,就可以调用服务了。Binder机制在提供Java接口时使用了JNI方法封装c++接口,使用AIDL语言来完成服务的定义,使用全局数据结构将Java服务接口中的各种对象和对应在c++层中的各个对象关联起来,从而使Android应用可以通过Java语言使用Binder进程间通信。

5实例

Service代码如下:

这里写图片描述

客户端的activity代码如下:

这里写图片描述

aidl文件代码如下:

这里写图片描述

aidl对应的java文件内容为:

这里写图片描述
这里写图片描述
这里写图片描述

运行截图

这里写图片描述

普通服务 和系统服务是有些区别的:

①服务启动和注册:系统服务是需要更改Android源码,将服务添加至systemserver中,并且随开机启动;此次实例是将服务编译好之后把相应的包存放在客户端功能内,当做一个数据文件来访问的。
②调用:调用系统服务客户端需要一个service manager的代理对象,靠它寻找服务的代理对象,并且完成服务;而此实例则是在客户端内使用包含了这个服务的包以及相应的接口,是对系统服务调用的一个简化。

Binder机制在java层和C++层的实现的相同点和不同点?

相同点:①这两层的Binder机制结构是相同的。Java层的Binder机制实际上是对c++层次进行了一个封装,使用JNI方法,使得Java代码可以调用c++层中相应的函数。
②仅从使用方式来看两个层是相同的。都是 首先需要一个Service Manager,随后定义相关的服务,之后把服务注册到Service Manager中;客户端在使用服务时,首先获得Service Manager的代理对象,之后从中找到相关的服务代理对象,在从这个服务代理对象中找到相关服务函数,调用函数完成Binder通信功能。
不同点:①数据结构:Java层想使用Binder机制就必须使用JNI方法调用C++层中的相应的对象,因此在Java层和c++层中要记录相对应的对象的地址,把两者关联起来,在Java层中就可以完成c++层中的功能
②服务的定义:c++层运行在系统底层,因此服务的定义可以直接写在头文件中,随系统运行。但是Java服务需要使用AIDL语言来定义,才能时Java服务接口有Binder通信能力。
③服务的启动:c++层的服务需要由服务端自己分配Binder线程池,而Java层的服务随着system启动,不需要自己分配。
④服务的调用:c++层:首先获得service manager的代理对象,通过它获得一个服务的代理对象,通过服务代理对象完成通信。
Java:首先获得Java层的service manager的代理对象,再通过JNI方法获得c++层中Binder代理对象,将他封装成Java服务的代理对象,返回给调用者,在使用函数的时候通过JNI方法使用c++层的Binder机制,通过Binder机制寻找Java层中相对应的服务。

本文转载自:http://blog.csdn.net/lpjishu/article/details/49942919

fengsehng
粉丝 4
博文 284
码字总数 214494
作品 0
朝阳
程序员
私信 提问
Android 源码分析之旅1--系统架构与分析方法、工具

《Android 源码分析之旅》目录 apefwkall.png 《Android 源码分析之旅》的全部目录将作如下安排: 第1章节——本篇文章,将介绍一些基本的概念、方法、工具。 第2章节——着重介绍Binder IP...

猴亮屏
2017/10/19
49
0
android6.0源码分析之Camera API2.0简介

前面几篇主要分析的是android Camera API1.0的架构以及初始化流程,而google在android5.0(Lollipop)开始对Camera的架构进行了调整,为了适应HAL3,新添加实现了CameraDeviceClient,而Camer...

天王盖地虎626
05/21
24
0
浅谈Android FrameWork框架和它在android的四层架构起到的作用

这里写一些关于Android Framework比较重要的知识点,这些东西对于之后理解和研究Android Framework有很大好处,就是让我们脑子里先有一个大概的模型,以及认识一点之后经常会碰见的角色。 首...

天王盖地虎626
06/06
9
0
Android系统的Binder机制之三——服务代理对象(2)

文《Android系统的Binder机制之二——服务代理对象(1)》我们学习了进程的C/C++层面的服务代理对象BpBinder,和Binder底层处理方式。本文我们将深入分析一下在进程的Java层面服务代理对象的...

垂盆草
2012/08/04
314
0
Android应用开发以及设计思想深度剖析(3)

特别声明:本系列文章LiAnLab.org著作权所有,转载请注明出处。作者系LiAnLab.org资深Android技术顾问吴赫老师。 我们接下来从安全性,性能,功能,可移植性的角度分别分析Android系统为应用...

21cnbao
2012/09/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何递归计算目录中的所有代码行?

我们有一个PHP应用程序,并希望计算特定目录及其子目录下的所有代码行。 我们不需要忽略评论,因为我们只是想弄清楚。 wc -l *.php 该命令在给定目录中运行良好,但忽略子目录。 我当时认为...

技术盛宴
31分钟前
3
0
使用 try-with-resources 优雅关闭资源

我们知道,在 Java 编程过程中,如果打开了外部资源(文件、数据库连接、网络连接等、redis),我们必须在这些外部资源使用完毕后,手动关闭它们。 因为外部资源不由 JVM 管理,无法享用 JVM ...

七弦桐
37分钟前
4
0
04.深入浅出索引(上)

简单来说,索引的出现就是为了提高数据查询效率,就像书的目录一样。 索引的常见模型 索引实现的方式有很多种,所以这里就引入了索引模型的概念,可以用于提高读写效率的数据结构很多,比较常...

scgaopan
41分钟前
5
0
Redis哨兵、复制、集群的设计原理,以及区别

谈到Redis服务器的高可用,如何保证备份的机器是原始服务器的完整备份呢?这时候就需要哨兵和复制。 **哨兵(Sentinel):**可以管理多个Redis服务器,它提供了监控,提醒以及自动的故障转移的...

Java阿七
50分钟前
5
0
浅析laravel路由执行原理

目前很多文章已经对Laravel的执行原理做了详细介绍,这里只是为了个人做一下简单记录 首先看入口 index.php 关键的执行函数就是 handle方法 ,但是前面的几个预处理函数,包括了整合框架的大...

冻结not
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部