前面两节中介绍了Binder机制中的
ServiceManager和
Binder驱动,在这一节中,我们来介绍Native中的Binder通讯。
1、需要启动一个media的service,路径在/system/bin/mediaserver
2、该服务的入口函数为main
3、该服务运行在media的用户名下
4、该服务属于以下组:audio camera inet等
这些信息中,我们只关心service的名字(mediaserver)和入口函数(main),那么这个服务的入口函数究竟在那个文件里面呢?
我们打开mediaserver模块,在模块的Android.mk文件中找到了这个Service的加载信息:
1、 通过open_driver打开binder驱动,并把binder设备句柄传给mDriverFD
2、 通过mmap()将一块内核地址映射到用户空间,作为buffer传输数据。
这样一来,getStrongProxyForHandle()所返回的result就相当于我们刚刚new出来的BpBinder对象:
由此我们知道,通过:
首先,他表示一个函数,这个函数名就叫interface_cast,参数必须是const类型的IBinder指针。
其次,既然是“模版”,就说明他只提供了一个框架(或者一种形式),可以适应多种环境调用。
具体来说就是, 这个函数名叫interface_cast,调用这个函数必须传递进来一个IBinder的指针,但是他的返回值可以是不固定的,是根据传递进来的INTERFACE而定的。同时,返回值的具体值就是INTERFACE::asInterface(obj)。
结合上面的代码来说,下面的语句:
1、调用名叫interface_cast函数模版;
2、模版参数为IServiceManager;
3、函数参数为BpBinder(0);
4、返回值赋值给了gDefaultServiceManager。
这样一来,这个函数模版就相当于:
为了更好的理解过程,我们挑选Native中的MediaServer进行分析。
一、MediaServer加载过程
Android启动过程中会去执行init.rc脚本,在这个脚本中将会启动一些关键的系统服务,其中之一就是MediaServer: @init.rc(google-code\system\core\rootdir\init.rc)
service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc
ioprio rt 4
这个脚本包含了几个重要信息:
1、需要启动一个media的service,路径在/system/bin/mediaserver
2、该服务的入口函数为main
3、该服务运行在media的用户名下
4、该服务属于以下组:audio camera inet等
这些信息中,我们只关心service的名字(mediaserver)和入口函数(main),那么这个服务的入口函数究竟在那个文件里面呢?
我们打开mediaserver模块,在模块的Android.mk文件中找到了这个Service的加载信息:
@Android.mk(google-code\frameworks\av\media\mediaserver\)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= main_mediaserver.cpp
LOCAL_MODULE:= mediaserver
在这个脚本中,将main_mediaserver.cpp加载为mediaserver模块,因此,main_mediaserver.cpp文件就是我们要找的入口文件,而这个文件中的main函数就是我们要找的入口函数:
@main_mediaserver.cpp
int main(int argc, char** argv) {
sp<ProcessState> proc(ProcessState::self());
//得到ServiceManager
sp<IServiceManager> sm = defaultServiceManager();
//三个Service自身的初始化
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
下面我们就来详细看一下整个Service启动的流程。
二、ProcessState的初始化
我们先来分析main中的第一步,也就是ProcessState::self()的过程。 @ProcessState.cpp(google-code\frameworks\native\libs\binder\)
sp<ProcessState> ProcessState::self() {
if (gProcess != NULL) return gProcess;
AutoMutex _l(gProcessMutex);
if (gProcess == NULL) gProcess = new ProcessState;
return gProcess;
}
这里我们看到,
ProcessState是一个单例模式,所有的进程共享同一个ProcessState对象。如果初始化过了(gProcess!=NULL),就直接返回给客户端使用即可,没有的话需要创建ProcessState对象。这里我们假设当前没有被初始化过,那么就会调用他的构造函数:
ProcessState::ProcessState()
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
//映射内存
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
close(mDriverFD);
mDriverFD = -1;
}
}
}
在他的初始化过程中,主要完成了两个重要步骤:
1、 通过open_driver打开binder驱动,并把binder设备句柄传给mDriverFD
2、 通过mmap()将一块内核地址映射到用户空间,作为buffer传输数据。
由此,就完成了ProcessState的初始化工作。
三、得到ServiceManager代理对象的过程
main函数的下一个动作就是要得到ServiceManager的对象: sp<IServiceManager> sm = defaultServiceManager();
那么是如何得到ServiceManager对象呢?得到的对象就是ServiceManager本身吗?我们从代码中找答案。
@IServiceManager.cpp(google-code\frameworks\native\libs\binder\)
sp<IServiceManager> defaultServiceManager() {
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
//得到ServiceManager
gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL));
}
return gDefaultServiceManager;
}
这里我们发现,defaultServiceManager()也是单例模式,就是说,如果其他Service已经申请到了ServiceManager,其他Service就可以直接使用,这里我们假设是第一次申请,那么就要通过下面方法申请:
gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL));
这个步骤稍微复杂,我们拆开分析:
ProcessState::self()->getContextObject(NULL)
interface_cast<IServiceManager>()
上面第一步可以得到ServiceManager的BpBinder对象,第二步把得到的BpBinder对象转换为IServiceManager对象,下面我们逐步分析这两个过程。
3.1、得到ServiceManager的BpBinder对象
ProcessState::self()->getContextObject(NULL)
在第二节中我们介绍过,ProcessState::self()的过程就是完成ProcessState的初始化,然后返回ProcessState对象,因此,上面的代码相当于:
ProcessState->getContextObject(NULL);
我们来看这个过程:
@ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller) {
return getStrongProxyForHandle(0);
}
继续看getStrongProxyForHandle(),记住,传递下去的参数为0:
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) {
sp<IBinder> result;
//从数组中查找handle_entry,不存在的话就创建一个
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
//new一个BpBinder返回给调用者
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
在这一步中,要先通过lookupHandleLocked()去查找当前handle的handle_entry对象,如果没有找到的话就会创建一个handle_entry,用于后续的Service使用,而且新建的handle_entry的binder变量为空,当前我们假设得到的就是新建的handle_entry对象,那么由于其e->binder为空,因此将会new一个BpBinder的对象作为其binder变量。
这样一来,getStrongProxyForHandle()所返回的result就相当于我们刚刚new出来的BpBinder对象:
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) {
return new BpBinder(handle);
}
也就是说,
我们通过getStrongProxyForHandle()得到的就是BpBinder对象,不仅如此,而且我们得到的是
handle为0的BpBinder对象。
由此我们知道,通过:
ProcessState::self()->getContextObject(NULL)
我们得到的是BpBinder(0)的对象。
下面我们来看如何将这个对象转换为ServiceManager对象。
3.2、得到ServiceManager的BpServiceManager对象
经过3.1的分析,我们可以将第三节中的: gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL));
转换为:
gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));
下面我们来分析interface_cast是如何将BpBinder对象进行转换的。
3.2.1、函数模版转换
我们先来看一下这个函数模版: @IInterface.h(google-code\frameworks\native\include\binder\)
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
这里要补充一下函数模版的知识。上面这个函数组成了一个标准的函数模版功能。
首先,他表示一个函数,这个函数名就叫interface_cast,参数必须是const类型的IBinder指针。
其次,既然是“模版”,就说明他只提供了一个框架(或者一种形式),可以适应多种环境调用。
具体来说就是, 这个函数名叫interface_cast,调用这个函数必须传递进来一个IBinder的指针,但是他的返回值可以是不固定的,是根据传递进来的INTERFACE而定的。同时,返回值的具体值就是INTERFACE::asInterface(obj)。
结合上面的代码来说,下面的语句:
gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));
其实包含了4个信息:
1、调用名叫interface_cast函数模版;
2、模版参数为IServiceManager;
3、函数参数为BpBinder(0);
4、返回值赋值给了gDefaultServiceManager。
这样一来,这个函数模版就相当于:
sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);
}
这里要求asInterface的参数obj是IBinder,而我们前面分析过我们得到的BpBinder对象就是IBinder类型的ServiceManager。因此,当初的:
gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));
将会等价于:
gDefaultServiceManager = IServiceManager::asInterface(BpBinder(0));
下面我们来看IServiceManager的asInterface()函数。
3.2.2、IServiceManager的asInterface函数
在IServiceManager.cpp中我们并没有找到asInterface函数,但是在IServiceManager.h中却找到了一个宏控: @IServiceManager.h
class IServiceManager : public IInterface {
DECLARE_META_INTERFACE(ServiceManager);
};
我们查看这个宏控的定义:
@IInterface.h(google-code\frameworks\native\include\binder\)
#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();
这是一个宏定义可以看出,其中的asInterface()函数被宏定义为了:
static android::sp<I##INTERFACE> asInterface(const android::sp<android::IBinder>& obj);
替换掉INTERFACE可以得到:
static android::sp<IServiceManager> asInterface(const android::sp<android::IBinder>& obj);
也就是说,这段宏声明了asInterface函数,但是asInterface的定义呢?
#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