在Linux中,进程间通信机制主要有D-BUS和OpenBinder两种,在Android中,通过IBinder对OpenBinder进行了封装,IBinder通信机制是一个轻量级的远程过程调用机制,用于进程内和进程间的高性能的通信。IBinder传递的数据被封装在android.os.Parcel中。需要注意的是,android.os.Parcel并非一种通用的序列化机制,而是专为IBinder设计的。D-BUS通信机制由于Blue-Z协议栈的需求在Android局部进行了使用。
在Android中,远程过程调用被封住到IBinder类中。在底层的实现上和处理器间的远程过程调用类似,如图1-1所示为IBinder通信的类图。

图1-1 IBinder通信
IBinder:: transact()是IBinder接口中一个比较重要的方法,其原型如下:
virtual status_t transact( uint32_t code, //请求的ID号
const Parcel& data, //请求的参数
Parcel* reply, //返回的结果
uint32_t flags=0)=0; //标识符
对开发者而言,Android目前只提供了FLAG_ONEWAY一种标识符,表示调用者在发出请求后,立即返回,不必等待被调用者返回结果。在Binder驱动中,目前提供了4种标识符:
TF_ONE_WAY //调用者立即范围,异步调用
TF_ROOT_OBJECT //数据为组件的根对象
TF_STATUS_CODE //数据为一个32bit的状态码
TF_ACCEPT_FDS //允许以文件标识符的方式响应
如果IBinder指向的是一个客户端代理,那么IBinder:: transact()方法只是把请求发送给服务器。服务端的IBinder:: transact()方法则提供实际的服务。
在客户端,BpBinder类是远程IBinder对象在本地进程的一个代理,其transact()方法实现为:
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
//一旦一个binder被销毁,将无法再被激活
if (mAlive) {
status_t status=IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status==DEAD_OBJECT) mAlive=0;
return status;
}
return DEAD_OBJECT;
}
其中IPCThreadState:: transact()会把请求经内核模块发送给服务器端,服务器端处理完请求之后,沿原路将处理结果返给调用进程。这里的请求是同步操作,它会等待直到结果返回为止。
在BpBinder之上进行简单封装,我们可以得到与服务对象相同的接口,调用者无须关心调用的对象是远程的还是本地的。此类实现在Android的多个场景获得了应用。与BpBinder类似的接口为BpRefBase,而BBinder则是一个本地对象。
在各种原生服务的实现上,通常会继承BpRefBase的BpInterface接口来实现远程代理,继承Bbinder的BnInterface接口来实现本地对象。
为了使C代码也能调用Java实现的服务,android_os_Binder_init里的JavaBBinder对Java 里的Binder对象进行包装。下面是JavaBBinder:: onTransact()方法的实现:
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags=0)
{
JNIEnv* env=javavm_to_jnienv(mVM); //转换Java
LOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
jboolean res=env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, (int32_t)&data, (int32_t)reply, flags);
jthrowable excep=env->ExceptionOccurred();
if (excep) {
report_exception(env, excep,
"*** Uncaught remote exception! "
"(Exceptions are not yet supported across processes.)");
res=JNI_FALSE;
//清除JNI的本地记数因子
env->DeleteLocalRef(excep);
}
return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}
JavaBBinder的实现位于android_util_Binder.cpp文件中。
IBinder不提供广播消息,但通过ActivityManagerService服务可以实现广播,触发广播需要调用 ActivityManagerProxy::broadcastIntent()方法,接收广播消息需要首先实现接口BroadcastReceiver,然后调用 ActivityManagerProxy::registerReceiver()方法进行注册。