本文将详细介绍Android系统中如何往ServiceManager中添加服务,当然还是以MediaPlayerService服务为例子。
在前文已经说明了,Android系统中的所有Service对外提供服务时,都需要先注册到ServiceManager,由其进行统一的服务管理。这将导致在注册前,首先就需要和ServiceManager进行IPC通信,而ServiceManager也是一个服务,只不过这个服务比较特殊而已(服务代理的引用句柄为0)。
在注册前,需要和ServiceManager通信,所以首先需要获得ServiceManager的Binder代理才能与其进行通信。
路径:Main_mediaserver.cpp (av\media\mediaserver)
sp<IServiceManager> sm(defaultServiceManager());
这条语句用户获取ServiceManager服务的Binder代理,defaultServiceManager()接口最终返回一个指向IServiceManager的智能指针(自己灵活回收内存)。函数展开如下:
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
// 获取指向IServiceManager的智能指针
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
此函数中最为关键的一句就是如下:
gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
此函数主要调用了两个接口interface_cast<IServiceManager>()
、ProcessState::self()->getContextObject(NULL)
ProcessState::self()接口函数在Binder机制-ProcessState过程一文中有详细的介绍,这里不再展开讲述。其功能就是获取本进程中的唯一ProcessState对象,是一个单例模式的。
最终就是调用getContextObject(NULL)
接口,参数传入NULL,其实最终返回一个BpBinder(0)
对象,此函数体如下:
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
接着调用getStrongProxyForHandle(0)
接口函数,句柄0代表ServiceManager的Binder代理引用。
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// 如果当前没有一个binder代理,则需要创建一个,或者我们不能够获取一个弱引用binder的情况下
// 如果要了解更多详细信息,可以去看看关于getWeakProxyForHandle()接口的评论
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
b = new BpBinder(handle); //使用Binder代理句柄0去创建一个BpBinder,如果是BpHwBinder情况一样
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// 当自身没有一个,而另外一个server发送了一个handle的情况下,允许我们去添加一个远程代理的强引用
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
而lookupHandleLocked(handle)接口函数第一次一般返回一个值为空的handle_entry结构体,如下:
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();
if (N <= (size_t)handle) { // handle = 0, 如果在mHandleToObject中有数据,一般不会进入
handle_entry e;
e.binder = NULL; //就算进入也是创建一个值为空的的handle_entry
e.refs = NULL;
status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
if (err < NO_ERROR) return NULL;
}
return &mHandleToObject.editItemAt(handle); //从此Vector<handle_entry> mHandleToObject中获取 handle_entry
}
所以最终还是会调用 b = new BpBinder(handle);这一句去生成一个handle = 0的Binder的代理,也是ServiceManager的Binder代理,接着调用interface_cast<IServiceManager>()
把BpBinder(0)做为一个参数传入其中,最后转换成一个sp<IServiceManager>
并赋值给gDefaultServiceManager全局变量,这样可以直接和ServiceManager进行通信了。
// 是一个STL模板,INTERFACE为IServiceManager
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
参数obj = BpBinder(0),转换为:
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj); //调用了IServiceManager的asInterface接口
}
IServiceManager::asInterface(obj)接口函数是在
IMPLEMENT_META_INTERFACE(ServiceManager, “android.os.IServiceManager”);实现的。
::android::sp<IServiceManager> IServiceManager::asInterface(
const ::android::sp<::android::IBinder>& obj)
{
::android::sp<IServiceManager> intr;
if (obj != NULL){
intr = static_cast<IServiceManager*>(obj->queryLocalInterface(IServiceManager::descriptor).get());
if (intr == NULL) {
intr = new BpServiceManager(obj);
}
}
return intr;
}
前面说过obj=BpBinder(0),调用其queryLocalInterface( “android.os.IServiceManager”),最终调用到IBinder,如下:
sp<IInterface> IBinder::queryLocalInterface(const String16& /*descriptor*/)
{
return NULL;
}
返回NULL,则生成一个BpServiceManager(obj = BpBinder(0)),与ServiceManager通信的Binder代理创建成功后,回归本文的主题,向它添加service,即在函数:
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());
}
调用了ServiceManager的addService(String16("media.player"), new MediaPlayerService())
,这也是一个RPC过程。服务的名字为“media.player”,服务的实例为MediaPlayerService(),而MediaPlayerService的继承关系是继承BBinder的,在Binder机制概述一文中有详细框图介绍。
addService()
接口的函数体如下:
virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated)
{
Parcel data, reply;
// 写入ServiceManager的接口描述符"android.os.IServiceManager"
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name); //需要注册的服务的服务名
// 需要注意这个地方,在parcel数据结构中写入一个BBindr,也是Binder的响应实体,会进行扁平化处理的
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
remote()实际调用到BpRefBase的remote()接口,返回mRemote.
class BpRefBase : public virtual RefBase
{
protected:
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
}
mRemote实际是BpBinder(0),由构造函数传入的。
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{}
explicit BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{}
则调用的是BpBinder(0)->transact(ADD_SERVICE_TRANSACTION, data, &reply)
接口,展开的是:
status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
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::self()->transact()接口函数,这个接口及IPCThreadState::self()在我的另外一篇博文Binder机制-IPCThreadState过程中有详细的介绍过程,这里不做展开分析。