普通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.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()
來看看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為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
回到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<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,//線程函數是_threadLoop
this, name, priority, stack, &mThread);
}
//終于,在run函數中,創建線程了。從此
//主線程執行IPCThreadState::self()->joinThreadPool();新開的線程執行_threadLoop
//我們先看看_threadLoop
int 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了,但是好像是有兩個線程都執行了這個啊!這里有兩個消息循環?
//下面看看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<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驅動的交互,如有需求再開啟新的線程。
- 函數調用的流轉過程:通過一次次的流轉,每個部分都做了需要自己做的事,然后由一個最終的執行者去執行。