普通client或者server在获得servicemanger的proxy对象后,肯定就要使用了。对于server来说,主要是调用addService,向serivceManager注册。而client则是通过serivcemanager查询所需server的信息,然后得到server的proxy对象。
以Native层的服务mediaservice为例,我们先来分析下server是如何向SerivceManager注册的吧
先来看入口 main_mediaserver.cpp
的main函数中的与ServiceManager相关的代码:
int main(int argc __unused, char** argv)
{
...
//获得ProcessState实例对象
sp proc(ProcessState::self());
//获取ServiceManager实例对象 【既BpServiceManager】
sp sm = defaultServiceManager();
AudioFlinger::instantiate();
//多媒体服务
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
SoundTriggerHwService::instantiate();
RadioService::instantiate();
registerExtensions();
//创建Binder线程,并加入线程池
ProcessState::self()->startThreadPool();
//当前线程加入到线程池
IPCThreadState::self()->joinThreadPool();
}
首先调用的函数是ProcessState::self(),获得ProcessState对象,ProcessState位置在framework\base\libs\binder\ProcessState.cpp
,在上一篇文章里有过讲述。其内部有Binder驱动的一些配置,每个进程只有一个。
获取到ProcessState对象后赋值给了proc变量,程序运行完,proc会自动delete内部的内容,所以就自动释放了先前分配的资源。
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
MediaPlayerService的初始化其实就是调用defaultServiceManager的addserivce方法向servicemanager注册,而上一篇已经讲过了defaultServiceManager,此处不在赘述。defaultServiceManager最终得到的是BpServiceManager。
下面来看看BpServiceManager的addService方法:
virtual status_t addService(const String16& name, const sp& service,
bool allowIsolated)
{
Parcel data, reply; //Parcel是数据通信包
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); //先把Interface名字写进去,也就是什么android.os.IServiceManager
data.writeString16(name); // name为 "media.player"
data.writeStrongBinder(service); // MediaPlayerService对象
data.writeInt32(allowIsolated ? 1 : 0); // allowIsolated= false
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); //
return err == NO_ERROR ? reply.readExceptionCode() :
}
上面函数的核心就是status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
,而remote()
就是创建bpservicemanager时的bpbinder(handle=0)
来看看BpBinder的Transact函数:
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;
}
可以发现,transact函数还不是在这个执行的,而是调用的IPCThreadState的transact.
看到这个形式就知道肯定是单例模式了,确实也是这样
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
return new IPCThreadState; //初始IPCThreadState
}
if (gShutdown) return NULL;
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) { //首次进入gHaveTLS为false
if (pthread_key_create(&gTLS, threadDestructor) != 0) { //创建线程的TLS
pthread_mutex_unlock(&gTLSMutex);
return NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mMyThreadId(gettid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
TLS是指Thread local storage(线程本地储存空间),每个线程都拥有自己的TLS,并且是私有空间,线程之间不会共享,,和java中的ThreadLocal是差不多的概念。通过pthread_getspecific/pthread_setspecific函数可以获取/设置这些空间中的内容。从线程本地存储空间中获得保存在其中的IPCThreadState对象。
IPCThreadState的构造函数中则是对所属进程,现成id,优先级等做了一些设置。需要注意的是mIn
和mOut
,后面会用到。
回到IPCThreadState::transact这个方法,看看是怎么实现的。
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err = data.errorCheck(); //数据错误检查
flags |= TF_ACCEPT_FDS;
....
if (err == NO_ERROR) {
//调用writeTransactionData 发送数据
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) { //flgs=0进入该分支
if (reply) {
//等待响应
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
//不需要响应消息的binder则进入该分支
err = waitForResponse(NULL, NULL);
}
return err;
}
上面代码的核心就是writeTransactionData 发送数据,waitForResponse等待响应,来看看这两个函数
writeTransactionData:
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
binder_transaction_data tr;
tr.target.ptr = 0;
tr.target.handle = handle; // handle=0
tr.code = code; // ADD_SERVICE_TRANSACTION
tr.flags = binderFlags; // 0
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
tr.flags |= TF_STATUS_CODE;
*statusBuffer = err;
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
tr.offsets_size = 0;
tr.data.ptr.offsets = 0;
} else {
return (mLastError = err);
}
//上面把命令数据封装成binder_transaction_data,然后
//写到mOut中,mOut是命令的缓冲区,也是一个Parcel
mOut.writeInt32(cmd); //cmd = BC_TRANSACTION
mOut.write(&tr, sizeof(tr)); //写入binder_transaction_data数据
return NO_ERROR;
}
其中handle的值用来标识目的端,注册服务过程的目的端为service manager,此处handle=0所对应的是binder_context_mgr_node对象,正是service manager所对应的binder实体对象。binder_transaction_data结构体
是binder驱动通信的数据结构,该过程最终是把Binder请求码BC_TRANSACTION和binder_transaction_data结构体写入到mOut。
再来看看waitForResponse函数
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();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
//这里开始操作mIn了,看来talkWithDriver中
//把mOut发出去,然后从driver中读到数据放到mIn中了。
cmd = mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
case BR_DEAD_REPLY:
err = DEAD_OBJECT;
goto finish;
case BR_FAILED_REPLY:
err = FAILED_TRANSACTION;
goto finish;
case BR_ACQUIRE_RESULT:
{
const int32_t result = mIn.readInt32();
if (!acquireResult) continue;
*acquireResult = result ? NO_ERROR : INVALID_OPERATION;
}
goto finish;
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
if (err != NO_ERROR) goto finish;
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
continue;
}
}
goto finish;
default:
err = executeCommand(cmd); //
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
上面代码的细节就不深究了,到这里,我们发送addService的流程就彻底走完了。
其实就是BpServiceManager发送了一个addService命令到BnServiceManager,然后收到回复。
回到开始的mediaservice的main函数,在将MediaPlayerService、CameraService、SoundTriggerHwService等服务都初始化后,就会走到下面的语句:
ProcessState::self()->startThreadPool();
//当前线程加入到线程池
IPCThreadState::self()->joinThreadPool();
进入两个函数内部看看
...
看看startThreadPool吧
void ProcessState::startThreadPool()
{
...
spawnPooledThread(true);
}
void ProcessState::spawnPooledThread(bool isMain)
{
sp t = new PoolThread(isMain);isMain是TRUE
//创建线程池,然后run起来,和java的Threadf非常像
t->run(buf);
}
//PoolThread从Thread类中派生,那么此时会产生一个线程吗?看看PoolThread和Thread的构造吧
PoolThread::PoolThread(bool isMain)
: mIsMain(isMain)
{
}
//再来看看父类
Thread::Thread(bool canCallJava)//canCallJava默认值是true
: mCanCallJava(canCallJava),
mThread(thread_id_t(-1)),
mLock("Thread::mLock"),
mStatus(NO_ERROR),
mExitPending(false), mRunning(false)
{
}
//喔,这个时候还没有创建线程呢。然后调用PoolThread::run,实际调用了基类的run。
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
bool res;
if (mCanCallJava) {
res = createThreadEtc(_threadLoop,//线程函数是_threadLoop
this, name, priority, stack, &mThread);
}
//终于,在run函数中,创建线程了。从此
//主线程执行IPCThreadState::self()->joinThreadPool();新开的线程执行_threadLoop
//我们先看看_threadLoop
int Thread::_threadLoop(void* user)
{
Thread* const self = static_cast(user);
sp strong(self->mHoldSelf);
wp weak(strong);
self->mHoldSelf.clear();
do {
...
if (result && !self->mExitPending) {
result = self->threadLoop();哇塞,调用自己的threadLoop
}
}
//我们是PoolThread对象,所以调用PoolThread的threadLoop函数
virtual bool PoolThread ::threadLoop()
{
//mIsMain为true。
//而且注意,这是一个新的线程,所以必然会创建一个
//新的IPCThreadState对象(记得线程本地存储吗?TLS),然后
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
//主线程和工作线程都调用了joinThreadPool,看看这个干嘛了!
void IPCThreadState::joinThreadPool(bool isMain)
{
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
int32_t cmd;
result = talkWithDriver();
result = executeCommand(cmd);
}
} while (result != -ECONNREFUSED && result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
//看到没?有loop了,但是好像是有两个线程都执行了这个啊!这里有两个消息循环?
//下面看看executeCommand
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
//来了一个命令,解析成BR_TRANSACTION,然后读取后续的信息
Parcel reply;
if (tr.target.ptr) {
//这里用的是BBinder。(因为自己是做server端)
sp b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, 0);
}
//让我们看看BBinder的transact函数干嘛了
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
//就是调用自己的onTransact函数嘛
err = onTransact(code, data, reply, flags);
return err;
}
BnMediaPlayerService从BBinder派生,所以会调用到它的onTransact函数
终于水落石出了,让我们看看BnMediaPlayerServcice的onTransact函数。
status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// BnMediaPlayerService从BBinder和IMediaPlayerService派生,所有IMediaPlayerService
//看到下面的switch没?所有IMediaPlayerService提供的函数都通过命令类型来区分
//
switch(code) {
case CREATE_URL: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
create是一个虚函数,由MediaPlayerService来实现!!
sp player = create(
pid, client, url, numHeaders > 0 ? &headers : NULL);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
其实,到这里,我们就明白了。BnXXX的onTransact函数收取命令,然后派发到派生类的函数,由他们完成实际的工作。
说明:
这里有点特殊,startThreadPool和joinThreadPool完后确实有两个线程,主线程和工作线程,而且都在做消息循环。
过程分析:
MediaPlayerService进程获得bpservicemanager,通过bpservicemanager对象的bpbinder成员(handl=0)中转到IPCThreadState执行transact
IPCThreadState调用writeTransactionData函数向mout缓冲区写入数据,然后调用waitForResponse等待响应。
mediaservice开启一个工作线程,和主线程一起开始做消息循环,不断的与binder驱动通信,故后续更加需求Binder驱动会增加binder线程个数。
再来看看client如何通过servicemanager获得server的bpbinder的。
首先来看看IServiceManager
的getService函数:
virtual sp getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp svc = checkService(name);
if (svc != NULL) return svc;
sleep(1);
}
return NULL;
}
核心是checkService(name),进入代码看看
virtual sp checkService( const String16& name) const
{
Parcel data, reply;
//写入RPC头
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
//写入服务名
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
,这句和之前addService的非常类似,肯定又是通过bpservicemanager最终流转到IPCThreadState
的transact,只是传递的参数有所不同罢了。 这里就不再讲了。
本片文章说是讲ServiceManager的addService
和getService
,其实主要还是在分析transact这个函数的执行流转过程,上面有些代码细节我也没有完全弄懂,但我觉得也够了。简单的说ServiceMnager通信的核心有以下几个:
文章里很多部分都来自与gityuan 和innost,在此表示感谢!