IBinder体系中得到一个服务的过程分析:
ServiceManager是管理所有服务(如音频,相机)的一个进程,它的handle是0
一、总的来说:得到一个service很简单,分成两步,
1,得到一个默认的serviceManager;
2,然后使用serviceManger->getService(service名称)得到具体的service
二、详细分析
参照网上一些资料(感谢石头),我们也以得到AudioFlinger服务为例,详细的讲述整个过程。
1,AudioSystem.cpp中有个函数const sp<IAudioFlinger>& AudioSystem:: get_audio_flinger(),顾名思义,该函数的功能是得到AudioFlinger服务
2,查看该函数的实现,首先我们看到了一个函数调用:
sp<IServiceManager> sm = defaultServiceManager();
该函数就是我们所说的第一步---得到一个默认的serviceManager;
defaultServiceManager()的实现如下:
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL)
return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
}
return gDefaultServiceManager;
}
重点分析gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
A.ProcessState::self()得到一个ProcessState的实例,在它的构造函数中通过mmap将/dev/binder文件映射到了一段内存,并将这段内存的地址保存下来,这段内存就是IBinder中进行数据客户端和服务端读写数据的地方
B.ProcessState::self()->getContextObject(NULL)); 通过getStrongProxyForHandle返回一个BpBinder对象
C.根据上面描述,该语句实际上就是interface_cast<IServiceManager>(BpBinder)
D.在此,我们有必要关注一下interface_cast,通过代码跟踪:看到它的实现
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
通过模板替换就是:
inline sp< IServiceManager > interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);
}
看来在asInterface是IServiceManager的一个成员函数,我们打开IServiceManager.cpp/h文件,我们并没有发现该函数,那它到底在哪儿呢,仔细观察IServiceManager.cpp,发现里面有个
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
在IServiceManager.h里面发现了
DECLARE_META_INTERFACE(ServiceManager);
通过跟踪这两个宏发现DECLARE_META_INTERFACE声明了一个变量和两个函数,代码如下:
#define DECLARE_META_INTERFACE(INTERFACE) \
static const String16 descriptor; \
static sp<I##INTERFACE> asInterface(const sp<IBinder>& obj); \
virtual String16 getInterfaceDescriptor() const; \
IMPLEMENT_META_INTERFACE这个宏是对上面声明的实现
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const String16 I##INTERFACE::descriptor(NAME); \
String16 I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj) \
{ \
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; \
} \
interface_cast<IServiceManager>实际上返回了一个BpServiceManager,在创建一个BpServiceManager时,有些细节还是需要注意:
BpServiceManager(const sp<IBinder>& impl): BpInterface<IServiceManager>(impl){}
BpInterface<IServiceManager>(impl)中的impl实际就是一个BpBinder,它调用了BpInterface的构造函数,然后调用了BpRefBase(remote),从而把一个BpBinder赋值给了mRemote,这个变量会在后面传输的时候用到
3,AudioSystem.cpp文件中紧接着就执行了 binder = sm->getService(String16("media.audio_flinger")); //参数是服务名称
我们知道了sm就是一个BpServiceManager,可以在BpServiceManager类中看到getService的实现,它调用了checkService,checkService先将数据打包成Parcel格式,然后调用remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);进行传输,remote()是BpServiceManager父类BpRefBase的一个成员函数,作用是返回mRemote(在上面讲过它就是一个BpBinder),那么我们就去BpBinder.cpp中去寻找transact的实现,代码如下:
status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
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是专门负责进程间通讯的,包括进程间的数据传输,查看IPCThreadState::self()->transact(mHandle, code, data, reply, flags)的实现,提取两行和我们相关的代码
………………..
Err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
……………………….
err = waitForResponse(reply);
writeTransactionData的作用是把数据写到类型为Parcel的mOut容器中去,方便ServiceManager读取
waitForResponse等待ServiceManager找到具体的服务,并把结果传回来
查看status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)的实现,里面调用了函数talkWithDriver(),该函数通过ioctl将mOut中的数据写到Binder driver中去,同时等待将返回的数据写入mIn。此时,数据的发送就算完成。
再来看看ServiceManager是怎么读取该数据的,在Service_manager.c中,调用了binder_loop(bs, svcmgr_handler),binder_loop其实就是一直在等待数据的到来,到来就就从驱动中读取数据,然后调用binder_parser解析,在binder_parser中
case BR_TRANSACTION:
…………………..
res = func(bs, txn, &msg, &reply);//这里的func就是svcmgr_handler
binder_send_reply(bs, &reply, txn->data, res); //将结果返回到Binder driver中
svcmgr_handler在getService的情况下,就是从服务链表中根据名称找到对应的服务的节点,然后转化成binder_object的格式后返回回去
waitForResponse中将返回结果写到reply中,然后从reply中就结果返回给调用者