本文主要是介绍Android IPC机制4-ServiceManager的addService与getService实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
普通client或者server在获得servicemanger的proxy对象后,肯定就要使用了。对于server来说,主要是调用addService,向serivceManager注册。而client则是通过serivcemanager查询所需server的信息,然后得到server的proxy对象。
注册服务-addService
以Native层的服务mediaservice为例,我们先来分析下server是如何向SerivceManager注册的吧
先来看入口 main_mediaserver.cpp
的main函数中的与ServiceManager相关的代码:
int main(int argc __unused, char** argv)
{...//获得ProcessState实例对象sp<ProcessState> proc(ProcessState::self()); //获取ServiceManager实例对象 【既BpServiceManager】sp<IServiceManager> sm = defaultServiceManager(); AudioFlinger::instantiate(); //多媒体服务 MediaPlayerService::instantiate(); ResourceManagerService::instantiate(); CameraService::instantiate(); AudioPolicyService::instantiate(); SoundTriggerHwService::instantiate(); RadioService::instantiate(); registerExtensions();//创建Binder线程,并加入线程池ProcessState::self()->startThreadPool(); //当前线程加入到线程池 IPCThreadState::self()->joinThreadPool(); }
proc(ProcessState::self())
首先调用的函数是ProcessState::self(),获得ProcessState对象,ProcessState位置在framework\base\libs\binder\ProcessState.cpp
,在上一篇文章里有过讲述。其内部有Binder驱动的一些配置,每个进程只有一个。
获取到ProcessState对象后赋值给了proc变量,程序运行完,proc会自动delete内部的内容,所以就自动释放了先前分配的资源。
MediaPlayerService:instantiate
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<IBinder>& service,bool allowIsolated)
{Parcel data, reply; //Parcel是数据通信包data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); //先把Interface名字写进去,也就是什么android.os.IServiceManagerdata.writeString16(name); // name为 "media.player"data.writeStrongBinder(service); // MediaPlayerService对象data.writeInt32(allowIsolated ? 1 : 0); // allowIsolated= falsestatus_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()
来看看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::self
看到这个形式就知道肯定是单例模式了,确实也是这样
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为falseif (pthread_key_create(&gTLS, threadDestructor) != 0) { //创建线程的TLSpthread_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
回到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=0tr.code = code; // ADD_SERVICE_TRANSACTIONtr.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是命令的缓冲区,也是一个ParcelmOut.writeInt32(cmd); //cmd = BC_TRANSACTIONmOut.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<Thread> 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,//线程函数是_threadLoopthis, name, priority, stack, &mThread);}//终于,在run函数中,创建线程了。从此//主线程执行IPCThreadState::self()->joinThreadPool();新开的线程执行_threadLoop//我们先看看_threadLoopint Thread::_threadLoop(void* user){Thread* const self = static_cast<Thread*>(user);sp<Thread> strong(self->mHoldSelf);wp<Thread> 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了,但是好像是有两个线程都执行了这个啊!这里有两个消息循环?//下面看看executeCommandstatus_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<BBinder> 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<IMediaPlayer> 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线程个数。
获取服务-getService
再来看看client如何通过servicemanager获得server的bpbinder的。
getService
首先来看看IServiceManager
的getService函数:
virtual sp<IBinder> getService(const String16& name) const{unsigned n;for (n = 0; n < 5; n++){sp<IBinder> svc = checkService(name);if (svc != NULL) return svc;sleep(1);}return NULL;}
核心是checkService(name),进入代码看看
virtual sp<IBinder> 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通信的核心有以下几个:
- IPCProcessState和IPCThreadState这两个类,他们分别记录了进程和线程中IPC通信需要的相关要素。这两个类都是单例模式,IPCThreadState是最终通信的执行者。
- BpBinder:通过handl=0可以直接与ServiceManager的实体Binder通信
- Server端会在主线程和一个工作线程开始消息循环,来处理和binder驱动的交互,如有需求再开启新的线程。
- 函数调用的流转过程:通过一次次的流转,每个部分都做了需要自己做的事,然后由一个最终的执行者去执行。
文章里很多部分都来自与gityuan 和innost,在此表示感谢!
这篇关于Android IPC机制4-ServiceManager的addService与getService实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!