Binder Framework通信我之见解
来源:互联网 发布:蚕丝被淘宝买什么牌子 编辑:程序博客网 时间:2024/05/29 17:18
1.Binder Native 层家族
Binder类在Native层有两个重要的子类BBinder 和BpBinder,其中BBinder代表通信的服务端,BpBinder代表通信的客户端。
这幅类关系图中BnInterface继承了BBinder对象表示服务端的binder,BpInterfce 继承BpRefBase 对象,通过mRemote 持有BpBinder对象表示客户端的binder对象,INTERFACE表示具体的业务类接口,通常该业务类接口还需实现IInterface中的函数,BnInterface<INTERFACE>这个模板类,实际是表示了继承BBinder和INTERFACE。类的详细定义如下:
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
BpInterface<INTERFACE>也是模板类,实际与BnInterface<INTERFACE>定义类似,该类表示继承BpRefBase和INTERFACE两个类,详细定义如下:
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
如下将介绍Native的相关服务对binder 通信进行分析。
1.1 IServiceManager类图分析
Native层很多服务也运用了Binder通信,如下通过ServiceManager在Native的通信过程,去了解Binder的通信原理。
在讲解Binder通信前,首先理解IServiceManager家族的类关系图,如下:
IServiceManager相当于Binder关系图中提到的INTERFACE模板,实现了IInterface中定义的接口函数。这里BnInterface<IServiceManager>除了继承了BBinder外,相当于还实现了IServiceManager接口,同理BpInterface<IServiceManager>除了继承BpRefBase外,也还实现了IServiceManager接口。BnServiceManager就是继承BnInterface<IServiceManager>,这样即具有了服务端通信的BBinder对象,又实现了IServiceManager的接口函数。BpServiceManager则是通过BpRefBase持有的mRemote(BpBinder类型)对象与服务端通信,并通过实现IServiceManager接口,完成通信的业务。
1.2 IServiceManager客户端通信代理获取
Native层的IServiceManager 的客户端对象是如何获取的?在IServiceManager中存在defaultServiceManager接口,让native程序获取IServiceManager客户端的业务对象,该对象是单实例的,实际这个对象是BpServiceManager类型的。
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
实例化该对象时,程序首先调用了ProcessState::self()->getContextObject(NULL)得到一个BpBinder对象,这里不详细说明,可跟踪代码了解,另外interface_cast实际上是IInterface类中定义的模板方法,而IServiceManager是继承了IInterface类的,模板方法的定义如下:
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
INTERFACE是IServiceManager,所以该方法的实际调用是IServiceManager::asInterface(obj);
asInterface是在IInterface定义的模板: DECLARE_META_INTERFACE(INTERFACE),由于继承关系(IServiceManager继承了IInterface)相当于IServiceManager定义了DECLARE_META_INTERFACE(ServiceManager)
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
IMPLEMENT_META_INTERFACE也是在IInterface定义的模板,它表示DECLARE_META_INTERFACE(INTERFACE)的实现,IServiceManager继承的实现如下:
IMPLEMENT_META_INTERFACE(ServiceManager,"android.os.IServiceManager");
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<I##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
#define CHECK_INTERFACE(interface, data, reply) \
if (!data.checkInterface(this)) { return PERMISSION_DENIED; } \
通过模板定义的接口实现,最终返回客户端的业务对象Bp##INTERFACE(obj)即BpServiceManager对象。
1.3 IServiceManager客户端通信过程分析
根据获取到的业务对象,由于业务对象已经具备binder通信的客户端,所以可通过该业务对象进行添加新服务、查询服务等操作。这里介绍addService的实现,该过程时序图所示。 defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService());上面的defaultServiceManager()表示BpServiceManager。IPCThreadState::transact函数中传入的flags需要做关注,这里它加入了标志TF_ACCEPT_FDS,并判断是否有TF_ONE_WAY,因为传入的值默认为0,所以这里不会携带TF_ONE_WAY.这两个特殊的宏实际定义在了./include/uapi/linux/android/binder.h。
enum transaction_flags {
//异步通信或者没返回值则使用该标志
TF_ONE_WAY = 0x01, /*this is a one-way call: async, no return */
//允许通过binder文件描述符返回,这里似乎都要加入该标志
TF_ACCEPT_FDS = 0x10, /*allow replies with file descriptors */
};
所以这个IPCThreadState::transact是同步的函数,即必须要服务端返回数据,才算完成通信。
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{……….
flags |= TF_ACCEPT_FDS;
if (err == NO_ERROR) {
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
…………
}
BpServiceManager的业务函数addService的整体过程比较简单,就是将需要发送的数据打包成Parcel对象后,由BpBinder对象传递给IPCThreadState(一个与线程相关的状态对象),IPCThreadState将检查数据的完整正确性,并将数据转化成binder_transaction_data类型的数据,最终将数据写道mOut(相当于该线程对象与binder的通信缓存)变量中,在上层这就完成了一次数据的传输,当然之后的事情需要驱动完成。
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
binder_transaction_data tr;
tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
………….
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
…………….
mOut.writeInt32(cmd);//先写命令BC_TRANSACTION
mOut.write(&tr, sizeof(tr));//后写数据,数据类型binder_transaction_data
return NO_ERROR;
}
发送完数据后,需要等待服务端的返回信息,这个过程由IPCThreadState的waitForResponse函数完成。waitForResponse通过talkWithDriver与设备通信,获取信息返回的状态,并根据信息的类型做出不同的处理。这样就完成了一次Binder通信处理。
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
int32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;//1.与驱动通信
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = mIn.readInt32();//驱动会将服务端回复的信息,写到mIn中,回复的消息类型需要根据驱动的实现确定,这里不深究。
//…..….
switch (cmd) {//第一次读取的是信息的类型,客户端根据不同的信息做不同的处理
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
case BR_DEAD_REPLY:
err = DEAD_OBJECT;
goto finish;//……….
default://如果上面没有找到信息类型,则交由executeCommand函数处理
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
//……………..
return err;
}
1.4 IMediaPlayerService服务端接收信息处理
virtual sp<IMediaRecorder> createMediaRecorder()
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
remote()->transact(CREATE_MEDIA_RECORDER, data, &reply);
return interface_cast<IMediaRecorder>(reply.readStrongBinder());
}
由于IServiceManager通信并不涉及BnxxxService封装的通信,而是直接在服务端读写Binder设备,进行消息处理的。所以这里将分析BnMediaPlayService的通信原理,进一步了解Binder通信在服务封装的机制。假设此时服务端MediaPlayerService启动,那必然会开启线程通过talkWithDriver()函数与Binder设备通信。如果此时收到客户端的请求,比如客户端通过BpMediaPlayerService调用createMediaRecorder业务函数,经过binder设备通信,服务端进行调用talkWithDriver获取到信息的类型,IPCThreadState::waitForResponse就会根据不同的返回类型,做不同的处理。而这里最终是在IPCThreadState的executeCommand函数中做处理的:
case BR_TRANSACTION:{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
………….
if (tr.target.ptr) {//这里调用BBinder 的transact 函数,最终会调用到子类的onTransact 函数,而实现该方法的子类为BnMediaPlayerService
sp<BBinder> b((BBinder*)tr.cookie);
error = b->transact(tr.code, buffer, &reply, tr.flags);
} else {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
mCallingPid = origPid;
mCallingUid = origUid;
mStrictModePolicy = origStrictModePolicy;
mLastTransactionBinderFlags = origTransactionBinderFlags;
}
break;
看一下BBinder::transact函数,最终会调用onTransact函数,BnMediaPlayerService则重新实现了该函数
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
……….
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
……….
}
status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
…………
switch (code) {
case CREATE_MEDIA_RECORDER: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
//这里就会调用服务端的createMediaRecorder函数,这个函数由BnMediaPlayerService子类MediaPlayerService实现
sp<IMediaRecorder> recorder = createMediaRecorder();
reply->writeStrongBinder(recorder->asBinder());
return NO_ERROR;
…………
}
这样就完成从客户端到服务端的通信。
2.Binder Java 层家族
Java层Binder系统是Native层Binder系统的一个镜像,其最终也是借助Native层Binder系统完成通信的。Java层的Binder系统通过JNI的调用,在Java世界初创的时期完成与Native层映射。
Java Binder通过上面jni的调用完成了几个重要全局静态变量的初始化,分别是gBinderOffsets、gBinderInternalOffsets、gBinderProxyOffsets.实际这些变量就是提前获取了一些JNI层的使用信息,如类的成员变量和函数等。如下是这些成员结构体的类解析:
int_register_android_os_Binder代码的作用是获取的java层相关信息保存在结构体bindernative_offsets_t类型的变量中mClass:表示android/os/Binder这个类的实例mExecTransact:表示java层Binder的execTransact方法mObject:java层的成员变量,用于保存native层Binder的相关信息(JavaBBinderHolder)int_register_android_os_BinderInternal则是获取java层的相关信息保存到结构体binderinternal_offsets_t中mClass:表示com/android/internal/os/BinderInternal这个类的实例mForceGc:表示java层BinderInternal的forceBinderGc方法int_register_android_os_BinderProxy中除了获取BinderProxy的相关信息,还获取了其他调用类的信息,这里只解释BinderProxy的信息mClass:表示android/os/BinderProxy这个类的实例mConstructor : 表示BinderProxy的构造方法mSendDeathNotice:表示BinderProxy的sendDeathNotice静态方法mObject:表示BinderProxy的成员变量mObject,用于保存native BpBinder对象mSelf:表示java/lang/ref/WeakReference对象,表示对象的引用信息。mOrgue:表示java层的成员变量mOrgu
2.1 ServiceManager 类图分析
上面是ServiceManager家族的关系图ServiceManager实际是个封装类,其客户端的通信最终实现是通过ServiceManagerNative. asInterface接口返回的类ServiceManagerProxy实现,ServiceManagerNative实际是服务端通信的空实现,因为servicemanager的服务端并没有用Binder封装,而是直接通过操作Binder设备进行通信。
2.2 ServiceManager 客户端通信实现
之前提到ServiceManagerProxy作为客户端通信的代码,需要从ServiceManagerNative. asInterface接口中返回。
private static IServiceManager getIServiceManager() {
…….. sServiceManager=ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
用户如果要添加java层服务,则需ServiceManager的addService 接口完成,其实际首先调用了ServiceManagerNative.asInterface(如下代码)接口获取servicemanager在java层的代理ServiceManagerProxy对象,然后调用了ServiceManagerProxy的addService方法。如下:
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service, false);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
要看如何添加服务的,需要先了解ServiceManagerProxy是如何初始化的,它是在ServiceManagerNative.asInterface(BinderInternal.getContextObject());完成的初始化。
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
ProcessState::self()->getContextObject(NULL)返回的是BpBinder对象。javaObjectForIBinder这个函数是通过Native对象创建一个Java对象。
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{//val实际是一个BpBinder对象
//……………
//通过调用java层的BinderProxy的构造方法,新建一个BinderProxy对象。
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {//完成native与java层的映射关系。
LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
// The proxy holds a reference to the native object.
//下面就是将BpBinder保存到java层的BinderProxy的mObject中
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
// The native object needs to hold a weak reference back to the
// proxy, so we can retrieve the same proxy if it is still active.
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
// Also remember the death recipients registered on this proxy
sp<DeathRecipientList> drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
// Note that a new object reference has been created.
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;//将创建的对象返回
}
即javaObjectForIBinder返回的是一个BinderProxy 对象,所以得到的是ServiceManagerNative.asInterface(BinderProxy bp),即ServiceManagerProxy构造函数传入的是BinderProxy,保存在mRemote对象中。这就完成了ServiceManagerProxy的初始化。
当调用addService接口时,即利用了mRemote将数据往外传递
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
mRemote为BinderProxy,可看到transact是调用transactNative jni函数完成通信。
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
return transactNative(code, data, reply, flags);
}
transactNative对应的jni函数是android_os_BinderProxy_transact,实现如下:
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
//………..
//这里可以看到,将之前保存在java层的Native BpBinder获取到。
IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
//……………..
//最终调用native层的对象完成通信
//printf("Transact from Java code to %p sending: ", target); data->print();
status_t err = target->transact(code, *data, reply, flags);
//if (reply) printf("Transact from Java code to %p received: ", target); reply->print();
//……….
return JNI_FALSE;
}
可得出的结论,Java层的Binder架构最终还是要借助Natvie的Binder架构进行通信。
2.3 ActivityManagerNative服务端接收信息处理
ActivityManagerNative代码服务端的通信实现,ActivityManagerProxy则代码客户端的通信实现。ActivityManagerService则表示服务端的业务的实现。
这分析通信之前,需要了解java层的Binder对象是如何与Natvie层的BBinder进行关联的。
在新建一个ActivityManagerService服务时,即调用newActivityManagerService(context);时,由于继承关系,所以会调用Binder对象的构造方法。
/**
* Default constructor initializes the object.
*/
public Binder() {
init();
……….
}
Binder的构造方法存在一个jni函数,该方法有init,它的实现如下:
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder();
if (jbh == NULL) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
return;
}
ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
jbh->incStrong((void*)android_os_Binder_init);
//这里将jbh保存到Binder的mObject对象中。
env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
通过该构造函数调用后,Binder的成员变量mObject指向了 JavaBBinderHolder对象,对JavaBBinderHolder进行剖析,可以看出java层的Binder对象如何与Native层的BBinder对象关联起来的:
JavaBBinderHolder提供了一个接口sp<JavaBBinder>get(JNIEnv* env, jobject obj)可返回JavaBBinder对象,进而得到BBinder对象。如果此时客户端通信发送信息到ActivityManagerNative代表的服务端,则服务端应该怎么处理呢?在android_util_Binder.cpp中会调用如下函数处理。virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
//…………………这里的mObject表示ActivityManagerService
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
jthrowable excep = env->ExceptionOccurred();
//………………….
}
会调用execTransact函数,该函数在Binder中实现,最终该函数是调用子类的onTransact函数。onTransact由ActivityManagerNative实现,而onTransact没一种情况的处理即业务函数,则由ActivityManagerService实现。通过这样就可以完成业务函数的处理了。
3.Binder与Aidl的实现
3.1 IPackageManager.aidl的实现关系图
IPackageManager.aidl在经过aidl的工具处理后,会生成如下的类。这些类最终都会与Binder系统关联上,可以这样说aidl是将实现了业务通信架构。IPackageManager.Stub代表了服务端通信端的实现,IPackageManager.Stub.Proxy则为客户端的通信实现。可进一步看到android对这个通信系统的实现是PackageManagerService通过继承IPackageManager.Stub完成业务函数的实现。而ApplicationPackageManager通过持有IPackageManager.Stub.Proxy对象封装客户端通信的接口。
所以aidl实际就是将业务函数与Binder系统完成关联。
- Binder Framework通信我之见解
- extjs 我之见解
- 我之见解字符串
- android之binder通信
- Web 3.0 我之见解
- linux之我的见解
- PHP缓存之我见解
- NSfileManager 之我的见解
- android IPC 之Binder通信
- Android之Binder通信原理
- Android IPC通信之Binder通信
- Android FrameWork 之Binder机制初识
- Android Framework学习(九)之Binder概述
- 【Android--Binder】关于通信机制之Binder机制(上)
- 我的注入方法之个人见解!
- 关于 API MFC .net 我之见解
- 关于 API MFC .net 我之见解
- c++虚函数表之我见解
- easyui datagrid如何解析 一个对象的子对象的多个属性
- JDK-Eclipse-Android_SDK-ADT详细图文安装教程(5)
- poj 3254 Corn Fields(状态压缩dp)
- MyEclipse2014配置Tomcat开发JavaWeb程序JSP以及Servlet
- Android5.1系统启动过程中启动有线网卡并为其分配静态IP地址
- Binder Framework通信我之见解
- 第二章 一切都是对象
- Session和Cookie区别
- ubuntu定时任务管理crontab
- LeetCode Range Sum Query 2D - Immutable
- JavaScript语言精粹学习笔记(2)——对象
- 欢迎使用CSDN-markdown编辑器
- Java之异常处理
- Linux Advance--设备特殊文件