Service Manager)我们学习了Service Manager(服务管家)在Android Binder中的作用——服务(Service)注册,服务(Service)查询和获取等功能。
我们知道Service Manager既是服务的管理对象,又是一个系统级的服务server(通过向驱动发送设置命令,使自己成为服务管家),它用来管理系统服务,也用于向客户端体统服务。那么Service Manager的客户端(包括我们通常所说的其它系统服务和系统服务的客户端)如何同它进行通讯呢?客户端不可能凭空发送请求吧!那么在android系统中的binder肯定有实现客户端和服务端联系的机制。
本文我们一起学习服务(Service)在客户端中的代理机制,服务代理对象就是服务端和客户端的这个联络员。在详细介绍服务代理之前,让我们先来了解一下服务代理在应用中的模型。
(一)服务代理应用模型
下面是客户端(这里的客户端是泛指请求服务的一方,自然有时候也包括System Server,比如当System Server向Service Manager请求添加服务的时候)通过服务代理,向服务器端请求服务的模型:
(1)首先客户端向Service manager查找相应的Service。这在前一篇文中有比较详细的介绍,这里不做赘述。
(2)Android系统的binder机制将会为客户端进程中创建一个Service代理,这个创建过程是本文的重点,下面会详细介绍。
(3)客户端视角只有Service代理,他所有对Service的请求都发往Service代理,然后由Service代理把用户请求转发给Service本身。
(4)Service处理完成之后,把结果返回给Service代理,Service代理负责把处理结果返回给客户端。
注意客户端对Service代理的调用都是同步调用(调用挂起,直到调用返回为止),这样客户端视角来看调用远端Service的服务和调用本地的函数没有任何区别。这就是我之前说的Binder机制的一个特点—线程迁移,这使得一个线程就像进入另一个线程执行并待会执行结果。
(二)MediaService
要想说明白服务代理的创建过程,还真不是那么容易的,最好的办法就是参照android中的源码,一步步走下去,这里我们还是选择MediaService的应用为例吧(看过一些资料也是以MS为例介绍的)。
MediaService是android系统中的一个应用程序,和其他普通的应用程序没什么不同,源码如下:
framework\base\Media\MediaServer\Main_mediaserver.cpp
int main(int argc, char** argv)
{
sp proc(ProcessState::self());
sp sm = defaultServiceManager();
LOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
怎么样?看到这个文件的代码是不是很迷惑啊!那么多陌生的东东,怎么理解啊!那么多的难关,那么厚的面纱,看来,要想见到服务代理的创建,还得过五关斩六将啊!下面我们就来层层剥开她神秘的面纱。
在Android系统中任何进程,要想使用Binder机制,必须要创建一个ProcessState对象和IPCThreadState对象(不要急,这个对象我们将在后面介绍)。
我们知道,一个客户端进程可能有多个Service的服务,这样就会创建多个Service代理(BpBinder对象,当然上面还会有封装的),那么这个进程就需要一个东东来管理这些服务代理。ProcessState就是这么个东东,它的作用就是维护当前进程中所有Service代理。
ProcessState是一个singleton类型(关于这个类型,你可以查阅相关资料),一个进程只能创建一个他的对象。客户端进程中的ProcessState对象将会负责维护这些Service代理。那既然这样,Service代理是不是就是这个ProcessState创建的呢?呵呵,你猜对了,Service代理正是在这里被创建的,不过我可没打算现在就来分析服务代理的创建过程,你的一步一步脚踏实地地才能走向“光明”哦!
上面的main函数中的第一句是什么?不就是这个ProcessState嘛,这里我们暂且记住一点,她就是一个管理服务代理的对象就好。先来看看她的创建过程,那就看看她的构造函数,咦,怎会回事?这个构造函数是私有成员那!
private:
ProcessState();
嗯,你没有看错,它的确是被声明成私有成员了,那就意味着在类的外部无法直接通过其构造函数,生成自己的一个对象,所以上面Main函数里面用了另一个公有成员函数ProcessState::self(),来调用其构造函数,生成ProcessState对象:
sp ProcessState::self()
{
if (gProcess != NULL) return gProcess;//如果已经创建了,//则直接返回这个全局的ProcessState对象
AutoMutex _l(gProcessMutex);
//如果第一次创建,调用其构造函数
if (gProcess == NULL) gProcess = new ProcessState;
return gProcess;
}
还记得Main函数中的第一句:
sp proc(ProcessState::self());
不是说不能在外部直接调用其构造函数的吗?其实这也不是我们讨论的重点,不过既然说了,就解释一下吧。熟悉C++的朋友应该都知道,当你定义的类中,没有显示定义一个复制构造函数的话,系统会帮你添加一个默认的复制构造函数,上面的就是调用这个复制构造函数。
ProcessState::ProcessState()定义如下:
ProcessState::ProcessState()
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
……
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);//映射内存
……
}
这样就生成了一个ProcessState对象proc,用来管理本进程中所有的服务代理,当程序运行结束,proc会自动delete内部的内容,自动释放了先前分配的资源。
这里ProcessState对象打开了/dev/binder设备,并保留了文件描述符,那么打开设备文件,自然是要用它进行通讯了,不过在ProcessState中你还真的很难找到,使用这个文件描述符进行通讯的代码。那么它在什么地方使用呢?我们会在后面介绍IPCThreadState时候在有说明。
……
sp sm = defaultServiceManager();
这里生成了一个IserviceManager的对象sm,IserviceManager是什么?还记得上一篇文中的内容吧,serviceManager是服务管家,它负责系统服务的管理。你当然不会简单的认为有了serviceManager这个程序就万事OK了,这个守护进程做这么伟大的事,怎么可能孤军奋战,每一个成功的男人背后都有一个支持他的女人,这是谁说的,不记得了,呵呵!serviceManager也不例外,IserviceManager就提供了这样的一个机制,给了serviceManager管理服务的能力。
那么这个sm究竟什么呢?说的明白点,上面那行代码就是生成了一个服务代理啦!不要惊奇,MS进程就是通过这个代理对象sm和Service Manager通讯的,下面我们就来重点分析这个IserviceManager对象sm的创建过程。
Frameworks\base\libs\binder\IserviceManager.cpp
p defaultServiceManager()
{
if (gDefaultServiceManager != NULL)
return gDefaultServiceManager; //如果已经创建过,//直接返回
{
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast(ProcessState::self()->getContextObject(NULL)); //创建代理对象
}
}
return gDefaultServiceManager;
}
这个函数中调用了下面的语句:
gDefaultServiceManager = interface_cast(ProcessState::self()->getContextObject(NULL)); //创建代理对象
这是创建代理对象的地方,这句代码比较复杂一些,先来看看它的参数吧,ProcessState::self()我们现在已经很熟悉了,getContextObject()函数是干什么的:
sp ProcessState::getContextObject(const sp& caller)
{
if (supportsProcesses()) {
return getStrongProxyForHandle(0);
} else {
return getContextObject(String16("default"), caller);
}
}
这个getStrongProxyForHandle(int32_t handle)函数才是真正创建服务代理的地方,上面都是对其的封装罢了,看看这段代码:
sp ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
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函数去查看当前进程维护的Service代理对象的列表,该待创建Service代理对象是否已经在当前进程中创建,如果已经创建过了,则直接返回其引用就可以了。否则将会在Service代理对象的列表增加相应的位置,保存将要创建的代理对象。lookupHandleLocked的源码这里就不贴出来了,自己查阅吧!
如果Service代理对象已经创建过了,直接增加引用计数就行了。若没有创建过,则需要创建一个新的Service代理对象。下面是BpBinder的构造函数:
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
LOGV("Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle);
}
注意:上面创建服务代理对象时,传递的是handle,handle是一个表示符,用来标志不同的服务类型,这里的handle其实是0,上面已经有所说明,可以回头看看。Binder机制中,binder驱动每个服务维护一个服务句柄(这是Windows中的概念),上层创建服务代理对象时,传入一个唯一标志服务句柄handle,就可以获得这个特定服务句柄的代理对象。0号服务句柄就是Service Mananger服务的,这是著名句柄,众所周知的。
这里多少两句,我们刚才应该看到了,代码生产了一个BpBinder对象,并赋给了sp指针,说明BpBinder是Ibinder的一个继承类。Ibinder类是android系统对binder机制的一个抽象定义,其实就是一个抽象类,所有要实现binder机制的客户,服务端都要继承这个抽象类。 这时程序又返回到了这里:
gDefaultServiceManager = interface_cast(ProcessState::self()->getContextObject(NULL)); //创建代理对象
这个调用ProcessState::self()->getContextObject(NULL)返回的是sp类型,而gDefaultServiceManager是一个sp对象,这两者有嘛关系啊,为何能够转换呢?先不管这些,先来看看这个interface_cast如何定义的吧!
Framework\base\include\binder\Iiterface.h
template
inline sp interface_cast(const sp& obj)
{
return INTERFACE::asInterface(obj);
}
这是个模版类,C++特有的东东,刚才的我们看到的是用IserviceManager来对模版进行实例化的,那我们还原一下代码:
template
inline sp< IserviceManager > interface_cast(const sp& obj)
{
return IserviceManager::asInterface(obj);
}
那么这个IserviceManager::asInterface()在哪儿呢?我找遍源码也没发现它定义的地方,后来发现不是那么回事,要想理清这层关系还要从IserviceManager类说起,下面是它的定义:
Framework\base\include\binder\IserviceManager.h
class IServiceManager : public IInterface
{
public:
DECLARE_META_INTERFACE(ServiceManager);
……
virtual status_t addService( const String16& name,
const sp& service) = 0;
……
};
这个类继承了IIterface类,并出现一个貌似宏的东东DECLARE_META_INTERFACE(ServiceManager);这是什么玩意呢?不太喜欢这个东东,所以一开始看代码时就没太注意这东西,可后来才发现这是类型转换的关键所在,看看定义:
Framework\base\include\binder\Iiterface.h
#define DECLARE_META_INTERFACE(INTERFACE) \
static const String16 descriptor; \
static sp asInterface(const sp& obj); \
virtual const String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
这里可没有注释啊,那些“\”玩意都是控制换行连接的,这个定义一大堆的,都什么玩意,看的头痛,咱也不管它是什么,我们先来个顺藤摸瓜,既然上面IserviceManager类定义时,传递了一个ServiceManager参数,那就给他兑换出来看看得了,我把“\”去掉,就当是一个函数了,方便观察。
#define DECLARE_META_INTERFACE(serviceManager)
{
static const String16 descriptor;
static sp asInterface(const sp& obj);
virtual const String16& getInterfaceDescriptor() const;
IserviceManager();
virtual ~IserviceManager();
}
呵呵,这下就一目了然了吧,不就是声明了一个字符串描述符和一个返回描述符的接口函数,还有构造和析构函数嘛! 当然,这里出现了我们想要的东西asInterface()的定义,那这样我们上面的函数调用就有着落啦!嗯,现在是看看它定义的时候了!
既然它声明这么横空,那定义怎么着也得打扮一下吧!瞧瞧,在IserviceManager.cpp文件中有这么一句代码:
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
真是双胞胎啊,长的那么像,看看这个孪生胞弟:
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const String16 I##INTERFACE::descriptor(NAME); \
const String16& I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
sp I##INTERFACE::asInterface(const sp& obj) \
{ \
sp intr; \
if (obj != NULL) { \
intr = static_cast( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { }
还是看不下去了,先兑现先:
#define IMPLEMENT_META_INTERFACE(serviceManager, "android.os.IServiceManager")
const String16 IserviceManager::descriptor("android.os.IServiceManager");
const String16& IserviceManager::getInterfaceDescriptor() const {
return IserviceManager::descriptor;
}
sp IserviceManager::asInterface(const sp& obj)
{
sp intr;
if (obj != NULL) {
intr = static_cast(
obj->queryLocalInterface(IserviceManager::descriptor).get());
if (intr == NULL) {
intr = new BpserviceManager (obj);
}
}
return intr;
}
I##INTERFACE::IserviceManager () { }
I##INTERFACE::~IserviceManager () { }
这下终于清楚了,最后就是将一个BpServiceManager对象返回给sm,那么你也看出来了,BpServiceManager是IserviceManager的一个继承类,而这个对象sm就是MS进程获得的Service Manager服务的代理了,MS就可以通过sm这个代理对象发送添加服务等请求了。
代码走到这里,服务代理对象的生成过程就结束了,总之一句话,defaultServiceManager()函数返回了一个Service Manager的服务代理对象,提供给本进程的其他服务器端或客户端访问Service Manager的接口。
framework\base\Media\MediaServer\Main_mediaserver.cpp
int main(int argc, char** argv)
{
……
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
……
}
这四行代码就是android系统中,SM进程驱动的四个系统服务的初始化代码。每个服务都调用自己的instantiate()实例化函数,向Service Manager注册自己,以为之前做过Camera模块,比较熟悉点,呵呵,所以我们以CameraServce::instantiate()为例来说明服务器端实例化的过程:
Framework\base\camera\libcameraservice\cameraservice.cpp
void CameraService::instantiate() {
defaultServiceManager()->addService(
String16("media.camera"), new CameraService());
}
其实就是这么简单,首先创建一个自己的实例,然后调用defaultServiceManager()函数,获得Service Manager的服务代理对象,再通过这个代理对象调用添加服务函数,将自己注册到服务管理器,这个过程中的每一步,前面我们都已经分析过了,可以回头看看。其他的服务实例化过程和这个过程相同。
Void Main()
{
……
……
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
上面的代码已经说过了,这里就不列出来了,当MS执行到这里时,本进程完成了如下工作:
(1)创建了ProcessState对象,用来管理本进程中获取的服务代理对象。注意:每一个进程只能创建一个该对象。
(2) 获取了Service Manager的服务代理对象,可以通过这个对象和服务管家通讯了。
(3)实例化了一些服务,并向服务管家成功添加了这些服务。
既然服务端准备好了,就应该进入循环状态,以便接收来自客户端的请求,没错,那么,下面我们继续分析上面两句代码:
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
……
sp t = new PoolThread(isMain);
//创建线程池,然后跑起来
t->run(buf);
}
}
PoolThread继承自Thread,这里的PoolThread()构造函数,其实什么都没做,就连run()函数都没有重载,创建该对象后直接调用run()函数。真正的线程创建在其父类Thread的run()中被创建:
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
……
if (mCanCallJava) {
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
//这里创建了一个_threadLoop线程函数,这时候线程运行起来
} else {
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
……
}
int Thread::_threadLoop(void* user)
{
Thread* const self = static_cast(user);
do {
if (first) {
first = false;
self->mStatus = self->readyToRun();
……
} else {
result = self->threadLoop();//调用PoolThread的threadLoop()
}
……
} while(strong != 0);
return 0;
}
Framework\base\libs\binder\ProcessThread.cpp
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
到了这里,发现很奇怪啊,也是调用的IPCThreadState::joinThreadPool()函数,好吧,既然两句都是调用这个函数,而且这里都再次引入了一个不可忽视的对象IPCThreadState,下面先来了解一下什么是IPCThreadState,然后在分析这个joinThreadPoll()函数。
前面我们有提过,在ProcessState中打开了一个binder设备文件,并返回了一个文件描述符,在ProcessState中并没有使用这个文件描述符的地方,那么这个文件描述符到底被谁使用了呢?对,就是IPCThreadState对象。
IPCThreadState也是一个singleton的类型,一个进程中也只能有一个这样的对象。它在android的binder机制中扮演什么样的角色呢?到了这里,你也可能已经猜到了,IPCThreadState主要负责信息的传递,所有要到达binder驱动和驱动中出来的信息,都要由IPCThreadState来传递。IPCThreadState有一个传输函数transact():
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
……
if ((flags & TF_ONE_WAY) == 0) {
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
int32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
cmd = mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
……
}
return err;
}
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
……
do {
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
……
} while (err == -EINTR);
……
}
这里出现ioctl()函数了,这可是binder驱动的接口啊,下面就不再跟踪了,总之,上层的信息就是通过这个途径发送的binder驱动的。这样我们再来总结一下IPCThreadState对象的作用:
(1)维护当前进程中所有对/dev/binder的读写。换句话说当前进程通过binder机制进行跨进程调用都是通过IPCThreadState对象来完成的。
(2)IPCThreadState也可以理解成/dev/binder设备的封装,用户可以不直接通过ioctl来操作binder设备,都通过IPCThreadState对象来代理即可。
说了半天,这里还是通过mDriverFD文件描述符,向binder设备文件写入数据。可是这个mDriverFD不是ProcessState的东东吗,怎么在这里被引用了呢?看看ProcessSate类定义就知道了。
private:
friend class IPCThreadState;
哦,原来IPCThreadState是ProcessState的一个友元类,这样IPCThreadSate就可以名正言顺地使用mDriverFD了。好了,下面我们继续来分析joinThreadPool()函数吧!
void IPCThreadState::joinThreadPool(bool isMain)
{
androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
status_t result;
do {
int32_t cmd;
result = talkWithDriver();
result = executeCommand(cmd);
}
} while (result != -ECONNREFUSED && result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
看到了吧,这里是一个循环,循环调用talkWithDriver()从binder设备文件中读取信息,然后调用executeCommand()函数处理信息。这就是系统服务的循环体,不断重复地响应客户端的请求。
不管是客户端进程和Service进程都是需要用IPCThreadState来和binder设备通讯的。那么现在我们从客户端和服务器端分别来总结一下IPCThreadState对象的作用。
(1)如果是客户端进程,则通过服务代理BpBinder对象,调用transact函数,该函数作用就是把客户端的请求写入binder设备另一端的Service进程,详细的内容我们放在下一篇文章介绍。
(2)作为Service进程,当他完成初始化工作之后,他们需要进入循环状态等待客户端的请求,Service进程调用它的IPCThreadState对象的joinThreadPool方法,开始轮询binder设备,等待客户端请求的到来。
本文中我们通过MS程序,分析了Service Manager服务代理的创建过程,以及服务线程启动循环监听消息的过程,当然还有服务代理的概念,服务代理的管理对象ProcessState和消息传递对象IPCThreadState。
后面我们会从客户端请求服务端的服务的视角,来分析binder机制在android系统中的实际应用。