这篇文章是对IBinder对象在进程间传递的形式(一)这篇文章的补充,首先还是把service启动过程的流程图贴上来
Android中主要通过2种方法来获得service IBinder:
1. 通过ServiceManager.getService(String Descriptor)来获得Service Manager管理的service的IBinder。
2. Client获得Application Service的IBinder,如下图描述的binder service流程。
不管哪种方法,均涉及到IBinder在不同进程间的传递,因为不论是Application Service 还是 System Service,它们在注册时均会涉及到第三方进程,如Application Service注册在Acitivity Manager中(system_server进程),System Service注册在Service Manager中(servicemanager进程)。
从Service Manager中获得IBinder涉及到service和servicemanager进程以及client和servicemanager进程之间的IBinder传递;
获得Application Service的IBinder,更是涉及到ApplicationService和system_server进程以及client和system_server进程之间的IBinder传递,如上图所示。
研究这个主题的意义在于,虽然从表面上看,在用到IBinder时,我们在应用中使用的是同一个接口,但是它的实质是怎么样的?是一套什么样的机制保证在同进程间client调用的是service的实体,而在不同进程间则是调用的service的proxy。
关于Binder的传递过程,首先需要了解一个service的类图关系。下图为JNI以上的类图。涉及到JNI和JAVA层的Binder对应关系。JNI层以下的Binder不涉及到这个文章的主题。
IISERVICEInterface表示aidl文件生成的或者用户自定义的当前service的接口文件,SERVICE表示当前service的实现。IISERVICEInterface.Proxy表示当前service的代理。
在JNI层,JavaBBinder继承自BBinder,是Binder的实体,它是在BBinder的基础上添加了成员变量jobjectmObject,该成员变量指向JAVA的SERVICE对象。这么做的好处就是在同进程间传递时,接收方能够直接向JAVA层返回SERVICE对象。
JavaBBinderHolder类,可以说是JavaBBinder类的一个容器,当JAVA层的SERVICE对象被创建时,就会相应的创建一个JavaBBinderHolder实例(android_os_Binder_init@android_util_Binder.cpp),但是只有SERVICE对象被IPC传递时,JavaBBinderHolder对象才会创建一个JavaBBinder实例(JavaBBinderHolder::get(env)@
android_util_Binder.cpp)。
1.IBinder在IPC通信中的发送过程
IBinder在IPC通信中,android通过Parcel类的成员函数writeStrongBinder()写入IBinder,在向Parcel写入IBinder时,首先会判断JAVA层IBinder的类型并转化为native的IBinder类型,下面介绍它的的2种类型。
android_os_Parcel_writeStrongBinder()@android_util_Binder.cpp
parcel->writeStrongBinder(ibinderForJavaObject(env, object));@ android_util_Binder.cpp
1.1IBinder是以JavaBBinder的形式传递的,即是一个ServiceIBinder的reference。如上图中的第一个return语句。
这种较常见,作为传输介质的IBinder所处的service和发送方在同一进程中。
Service处在Process A中,ProcessA为IBinder发送方。
1.2 IBinder是以BpBinder的形式传递的,即是一个ServiceIBinder的Proxy。如Service bind图中的第二个return语句。
Service 处在Process C中,Process A为IBinder发送方。
这种情况比较典型的就是bindservice时会用到,如图中最后一步中AMS通知client bind成功时,传递给client的就是一个service IBinder的Proxy。作为传输介质的IBinder所处的service和发送方在不同的进程中。
Kernel中,Binder Module会根据IPC通信双方是否处于同一个进程中,来设置binder object type值,下图code描述。
当IBinder的发送方和Service在同一进程的话,那么传递给内核的binder_object的type为BINDER_TYPE_BINDER,由于IBinder发送到内核均是在进程间传递的,所以Binder Module driver会将type改为BINDER_TYPE_HANDLE.
当IBinder的发送方和Service不在同一进程的话,那么传递给内核的binder_object的type就为BINDER_TYPE_HANDLE,并且这种情况接收方和Service可能处在同一个进程中,因此当这种情况发生时,需要将其改为BINDER_TYPE_BINDER。这一点在下面会介绍。
IBinder发送的流程:
1.IBinder在IPC通信中的接收过程
首先查看一下Parcel的unflatten_binder@Parcel.cpp(readStrongBinder()方法会调用到):
2.1 当从BinderModule中读出的binder_object的type为BINDER_TYPE_BINDER,说明接收方收到的Service是同进程的,那么此时直接将保存在cookie中的Service的实体传递给JNI层。
此时,JNI层收到的Service实体为一个JavaBBinder对象,由上面的类图可以知道,JavaBBinder对象中包含着JAVA层SERVICE对象的引用。
2.2 当从Binder Module中读出的binder_object的type为BINDER_TYPE_HANDLER,说明接收方收到的Service不是同进程的,那么会创建或者引用已有
的一个BpBinder对象给JNI层。
Service 处在Process C中,Process B为IBinder接收方。
2.2.1如何创建BpBinder对象
通过调用ProcessState的方法getStrongProxyForHandle(),来创建或者引用已有的一个BpBinder对象。
A.首先,检查当前所要创建的BpBinder是否已经在Vector mHandleToObject中存在,每个进程中均会维护这么一个Vector,保存当前进程获得的所有BpBinder对象。没有分析出这么做的原因,可能为了资源的重复利用,避免每次使用完都得回收的问题。
B.如果没有查找到BpBinder对象,创建一个新的BpBinder对象,并会向mHandleToObject保存这个对象。
由于每个Service均会对应一个唯一的handle,因此可以通过这个handle来标示BpBinder对象。
2.2.2 JNI层的特殊处理
javaObjectForIBinder@android_util_Binder.cpp
①首先,在BpBinder对象中查找是否保存相关的BinderProxy的对象,如果有,向JAVA层返回这个对象;
②如果没有,创建一个BinderProxy对象;
③将新创建的BinderProxy对象,attach到BpBinder对象中。
结合下面的关系图,我们得出这样的逻辑关系:
a.每个进程中会保存多个当前进程调用过的BpBinder对象;
b. 每个BpBinder对象都会保存与之对应的JAVA层的BinderProxy。
将创建的BinderProxyattach到BpBinder的意义在于:通过这种方式,JAVA应用层频繁获取同一service的IBinder时,获取的是同一个BinderProxy。
分享到:
相关推荐
android中IPC机制的IBinder简单使用,简要说明下IBinder中两个重要方法
详细介绍android开发中的重点难点部分binder的工作机制
IPC android 分析 关于android IBinder源码分析,大家可以看看,也可以提出质疑
Android 中Parcel 的使用,他是一个存储基本数据类型和引用数据类型的容器,在andorid 中通过IBinder来绑定数据在进程间传递数据。 Parcel parcel = Parcel.obtain();// 获取一个Parcel 对象 下面就可以对其进行...
Android安卓AIDL进程间通信Service简单例子,分为客户端和服务端代码,一看就会,一看就懂,核心还是IBinder.
Android IBinder
android根据不同任务创建不同进程,并通过AIDL进行进程间通信
This doc tells you that how the IBinder IPC at Google Android framework works, using 1 ezxample code....
第三阶段,实例操作,不使用半自动的AIDL工具,纯手动利用Binder实现一把进程间通信。 相信这一套军体拳下来,应该能薛伟地掌握Binder的相关原理。 P.S. 本文code部分使用了伪代码,包含但不限于kotlin、java和汉字...
通过AIDL 实现Client求1+2的和,服务端实现具体的做法,并通过Ibinder来获取服务端的ADIL对象来操作。
对用户程序来说,我们也要创建server,或者Service用于进程间通信,这里有一个 ActivityManagerService管理JAVA应用层所有的service创建与连接(connect),disconnect,所有的 Activity也是通过这个service来启动,加载...
android 13.Android的IBinder接口及其安全性机制
如果你需要在不同进程间通信,你可以在Service中使用Messenger来实现进程中通信。 如果使用这种方式,Service中需要定义一个Handler对象(负责对客户端发送过来的Message进行响应)。 Messenger可以共享给client一个...
1、如果我们要访问service的属性和方法,那么在activity肯定是以bindservice的方法实现的,而在service中的onbind方法也是必须要实现的,onbind返回的Ibinder对象在activity的serviceconnection中得到使用。...
一个扩展的IBinder类实现通信的简单例子
实现服务的onCreate(),重写onbind()方法,销毁onDestroy()方法如果 Activity 绑定,Activity 就可以取到 IBinder 对象,可以直接调用对象的方法,相同应用内部不同组件绑定,可以使用内部类以及Binder对象来...
只需要简单易懂的Messenger,它也称为信使,通过它可以在不同进程中传递message对象,在message中放入我们需要传递的数据你就可以实现跨进程通讯和传递数据。废话不多说,直接上代码。 首先是服务端: public ...
文件中是对Service的测试,对于绑定时的IBinder对象,有两种实现形式,也就对应有两种测试方式
Binder其实也不是Android提出来的一套新的进程间通信机制,它是基于OpenBinder来实现的。Binder是一种进程间通信机制,它是一种类似于COM和CORBA分布式组件架构,是提供远程过程调用(RPC)功能。 什么是Binder ...
E04_HAL觀點_ServiceManager和IBinder扮演的角色_android