一个进程要想提供Binder服务,必须要调用
ProcessState::self()->startThreadPool();
IPCThreadState::self->joinThreadPool();这两个方法,然后整个进程就进入一个Binder loop循环了。
ProcessState负责打开Binder设备节点,做mmap内存映射,,IPCThreadState是负责跟Binder驱动做命令交互的,重点看下IPCThreadState::self->joinThreadPool();方法,
void IPCThreadState::joinThreadPool(boolisMain){
//告知Binder驱动,进入Binder主循环。
mOut.writeInt32(isMain? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
do{
//now get the next command to be processed, waiting if necessary
result= getAndExecuteCommand();
} while (result!= -ECONNREFUSED && result != -EBADF);
//告知Binder驱动退出Binder循环。
mOut.writeInt32(BC_EXIT_LOOPER);
//参数false,表明不在从Binder驱动读数据。
talkWithDriver(false);
}
status_t IPCThreadState::getAndExecuteCommand(){
// talkWithDriver的参数默认值是true,这个函数对数据的处理既包括读,也包括写。
result= talkWithDriver();
//执行cmd。
result= executeCommand(cmd);
}
这样的Binderloop框架在所有需要Binder服务的进程中,基本是一致的。如果同一个进程中,有多个基于AIDL的BinderServer时,IPCThreadState是单实例,该怎么来区分他们呢,Binder client发送的请求通过Binder驱动到达Binder server端,那么IPCThreadState是如何把Binder驱动的消息准确投递给对应的BinderServer的?
我们看executeCommand是怎么执行的。
status_t IPCThreadState::executeCommand(int32_t cmd){
switch((uint32_t)cmd) {
// BR_TRANSACTION,Binder驱动向Server端发送请求数据,接收的是请求,
//BC_TRANSACTION,client向Binder驱动发送请求数据,发送的是请求,
//BR_REPLY ,Binder驱动向Client端发送回复数据,接收的是应答,
//BC_REPLY ,Server向Binder驱动发送回复数据,发送的是应答,
//这是Binder机制中client与server端交互最关键的几个命令。
case BR_TRANSACTION:{
binder_transaction_data tr;
//读取业务请求
result= mIn.read(&tr, sizeof(tr));
//分情况,调用transact处理请求
if(tr.target.ptr) {
error= reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply,tr.flags);
}else{
error =the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
}
}
}
如果tr.target.ptr不为null,把tr.cookie转换成BBinder,最后调用BBinder->transact来处理请求。所以BBinder是server 跟 IPCThreadState沟通的桥梁。
基于AIDL的server都会生成一个stub内部类,这个stub继承于android.os.Binder,我们看Binder.java的构造函数。
public Binder() {
//这是native函数,对应实现在android_util_Binder.cpp中,这个cpp类中包含了很多java
//类中的native函数实现。
init();
}
static void android_os_Binder_init(JNIEnv*env, jobject obj){
//这里虽然没有直接看到BBinder,但是从JavaBBinderHolder进去,看到他有一个JavaBBinder
//类型的弱指针:wp<JavaBBinder>mBinder;而JavaBBinder继承自BBinder,
JavaBBinderHolder* jbh = new JavaBBinderHolder();
//把JavaBBinderHolder的指针值保存到Binder的mObject变量中。
env->SetLongField(obj,gBinderOffsets.mObject, (jlong)jbh);
}
在一个基于AIDL的server创建时,是想要生成BBinder的,但是在创建JavaBBinderHolder对象时并没有生成JavaBBinder对象,那什么时候创建的JavaBBinder对象呢?
当一个BinderServer创建后,会把他注册到ServiceManager中,这时会调用addService方法,实际是通过ServiceManagerProxy调用的addService,它是Servicemanager的代理类,这个类在ServiceManagerNative.java中,
public void addService(String name, IBinder service, boolean allowIsolated){
//这里的Parcel是Parcel.java
Parcel data = Parcel.obtain();
//service是一个Ibinder,把这个service写入到parcel中,parcel是进程间传递数据的一个载体,利用parcel把Binder对象写入,读取时就能得到原始的Binder对象。
data.writeStrongBinder(service);
//这里是跨进程的开始。
mRemote.transact(ADD_SERVICE_TRANSACTION,data, reply, 0);
}
接着看Parcel.java中writeStrongBinder的实现:
public final void writeStrongBinder(IBinder val) {
//只是调用了native层的实现。
nativeWriteStrongBinder(mNativePtr,val);
}
进入到JNI中的实现android_os_Parcel.cpp,
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr,jobject object){
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
//这里的参数object就是那个Java层的Ibinder对象,
conststatus_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
}
通过ibinderForJavaObject对这个IBinder进行转化,
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj){
if(env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder*jbh = (JavaBBinderHolder*)
env->GetLongField(obj,gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
}
前面在Binder的构造函数中,我们把JavaBBinderHolder的指针值保存到gBinderOffsets的mObject变量中,这里通过gBinderOffsets.mObject把它取出来,并转成JavaBBinderHolder,接着调用它的get方法。
class JavaBBinderHolder : public RefBase{
sp<JavaBBinder>get(JNIEnv* env, jobject obj){
sp<JavaBBinder>b = mBinder.promote();
//第一次调用,会New一个JavaBBinder,实际就是一个BBinder。
if(b == NULL) {
b= new JavaBBinder(env, obj);
mBinder= b;
}
}
}
接下来就是Parcel.cpp中的方法writeStrongBinder,把JavaBBinder这样一个强指针写入到parcel中。
status_t Parcel::writeStrongBinder(constsp<IBinder>& val){
return flatten_binder(ProcessState::self(), val, this);
}
这里又把val转成了弱指针,wp<IBinder>& binder,wp是一个模板类,在构造一个wp对象时,给其成员m_ptr赋值,
wp<T>::wp(T* other) : m_ptr(other){
if(other) m_refs = other->createWeak(this);
}
所以这里的m_ptr实际就是BBinder对象。
status_t flatten_binder(constsp<ProcessState>& /*proc*/,
const wp<IBinder>& binder, Parcel* out){
//这里的cookie记录的就是BBinder对象。
obj.cookie= reinterpret_cast<uintptr_t>(binder.unsafe_get());
//把这个obj写入到parcel空间的相应位置,这样就把一个Binder对象填充到了Parcel中。
finish_flatten_binder(real,obj, out);
}
以上addService的操作都还在client端,后面就会通过mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);进而通过ioctl与Binder驱动通信,把请求(数据)发送到servicemanager的服务端。
在Binder驱动中,只有有用户带一个Binder对象经过他,就会被记录下来,进而把这一Binder对象相关的binder_node节点加入到当前proc的nodes树中,也就是说当前proc的所有Binder对象在驱动中都有记录。
相关代码就是Binder.c的binder_transaction函数,
Kernel/drivers/staging/android/Binder.c
static void binder_transaction(structbinder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply){
switch(fp->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER:
struct binder_node *node = binder_get_node(proc, fp->binder);
node= binder_new_node(proc, fp->binder, fp->cookie);
ref= binder_get_ref_for_node(target_proc, node);
}
}
这样就知道BBinder是怎么来的了。
使用AIDL来描述的server,经过工具转化后生成的java文件中,有两个重要的嵌套类,一个是stub,还有一个是Proxy,其中I***.Stub是服务端要继承的类,I***.Stub.Proxy是相应的client,这是java层的Binder服务格式。
native层的Binder服务都是手写的,以IGraphicBufferProducer.cpp为例,其中的Bp***,相当于AIDL中的I***.stub.Proxy,而Bn××××相当于AIDL中的I***.Stub,
相应的服务端要继承Bn××××这个类。
做个小结:
1)在请求的数据包中binder_transaction_data类性的数据tr,其中的tr.target.ptr通常不会为null,也就是target中指定了目标对象,具体是其中tr.cookie,这是个BBinder类型的。
2)这个BBinder的来源,在一个AIDL的server被创建时,确切的说是在其被添加到serviceManager时,会去生成一个BBinder,具体是由stub的父类android.os.binder的构造过程中实现的,在addService的过程中,肯定是经过Binder驱动的,在Binder驱动的设计中,只要有人带着Binder对象路过他,就会被记录下,存到当前proc的nodes树中,这也是后面client发送的数据可以携带BBinder的来源。
3)BBinder的transact函数,会调用onTransact函数,onTransact函数的重点是调用java层的Binder对象的某个接口,把client的请求传过去,所以服务端都会重写这个onTransact函数,这样就把client的请求传到了Binder(java)了。基于aidl的server,其中的onTransact通常什么都没做,只是调用了super.onTransact函数,这是因为aidl的stub类也重写了onTransact方法,做好了无缝调转,基于aidl的server只要实现业务处理接口就可以,这也是aidl的server编写方便的一个原因。