介紹
Binder是什么?它可以叫作:IPC、RPC、線程遷移、遠程對象訪問,本文中理解它為遠程對象訪問更貼切些,簡而言之就是一個進程能訪問另一個進程中的對象,調用該對象的方法,就好像對象在自己的進程中一樣,這種訪問是同步的訪問,當然Binder也能實現異步的通信。
Binder基於C/S架構:
Binder分為Java和C++兩套實現,分別用於Java應用和Native應用開發,Java Binder實際上也是基於C++ Binder的一個封裝,因此本文只分析C++ Binder。
服務分為2種:Native Service、Android Service。
Native Service:是在系統init階段通過init.rc腳本建立的服務,完全在C++空間完成的服務。
Androids service:是系統二階段(init2)初始化時建立的服務,是指在JVM空間完成的服務,雖然也要使用Navite上的框架,但是服務主體存在於Android空間,所有的Androids service都運行在一個進程中:systemsever進程。
實現原理
Binder本質上說就是一種數據傳輸方式,當通過服務代理調用服務對象的方法時,服務代理把參數序列化進行傳輸,服務對象反序列化取出參數,然后調用服務對象的方法。
進程間的通信是通過Android專門為Linux增加的一個設備(/dev/binder)來實現的。
本質上是使用了共享內存來進行通信,但該共享內存和我們平常理解會有一點不一樣。
我們平常使用的共享內存是兩個進程之間,即點到點的,如果有N個進程要兩兩通信而又不相互干擾,那么就必須有N*N個共享內存。Binder使用的共享內存是進程與binder設備之間,即binder做為一個中間者進行傳遞,類似會議電視的MCU。
使用了共享內存,在驅動中還是會有一次拷貝的,進程A向進程B傳遞數據時,數據會被驅動從進程A中拷貝到binder和進程B之間的共享內存中,然后進程B就可以直接讀了。
通信過程:
所有要進行通信的進程都得打開/dev/binder設備
binder設備驅動會為每個進程分配一個數據結構binder_proc,每進程中的每個用到了binder通信的線程分配數據結構binder_thread。
binder設備驅動會為服務進程中的每個服務對象分配數據結構binder_node,它隸屬於服務進程的binder_proc,是服務端相關的,binder_node中記錄了服務對象在服務進程中的地址;會為客戶進程中引用的每個服務分配binder_ref,是客戶端相關的,binder_ref會指向客戶進程引用的服務對象的binder_node。
binder設備驅動為客戶進程引用的每個服務都會維護一個handle,它存在於binder_ref中(binder_ref.desc),它就像進程打開某個文件產生的文件描述符一樣,進程每引用一個服務,就會分配一個最小未使用的整數作為handle。handle是客戶進程相關的,多個進程引用同一個服務得到的handle並不是一樣的。
當服務進程向ServiceManager注冊服務時,會帶上服務的名稱字符串,驅動會為服務進程中的服務對象增加一個binder_node,歸屬於服務進程的binder_proc。
當把注冊服務的請求發給ServiceManager時,ServiceManager也是服務對象的一個引用者,驅動會為ServiceManager增加一個binder_ref,指向服務對象的binder_node。驅動把binder_ref.desc(ServiceManager)作為handle返回給ServiceManager,ServiceManager保存此handle和服務名稱字符串。
當客戶進程向ServiceManager獲取服務時,ServiceManager根據服務名稱字符串找到服務對象在ServiceManager進程中的handle。在ServiceManager的應答的過程中,驅動根據此handle在ServiceManager進程的binder_proc找到對應的binder_ref,並根據它找到服務對象的binder_node。然后,驅動會為客戶進程增加一個binder_ref,指向服務對象的binder_node,最后把binder_ref.desc(客戶進程)作為handle返回給客戶進程。
客戶進程使用得到的handle向服務進程發起請求,驅動會在根據此handle在客戶進程的binder_proc查找對應的binder_ref,並找到它指向的binder_node,並找到binder_node所屬的binder_proc,最終驅動把請求放入服務進程的接收隊列中。
服務進程收到請求后,從binder_node中找到服務對象的地址,然后調用該服務對象。所以,對於服務對象,在客戶進程中表現出來的是handle,在服務進程中表現出來的是地址,驅動會對它們進行映射。
Binder框架
概覽
框架的層次結構:
說明:
Bn代表服務端,Bp代表代理
ProcessState、IPCThreadState是進程、線程相關,是對Binder驅動的封裝
Binder核心庫又是對ProcessState、IPCThreadState的封裝
C++ Binder框架是對Binder核心庫和服務接口的封裝
類關系圖:
`
說明:綠色部分是用戶編寫應用程序需要實現的
IPCThreadState、ProcessState、Binder關系圖:
對於Binder核心庫:
IBinder:是一個接口,被BpBinder、Bbinder繼承
BpBinder:客戶端,內部有一個成員mHandle記錄了遠程服務對象的handle
BpRefBase:客戶端,內部有一個成員指向BpBinder,采用的是Bridge設計模式,實際是是通過BpBinder來完成通信
Bbinder:服務端
對於C++ Binder框架:
Iinterface:主要是定義了asBinder()、純虛函數onAsBinder(),asBinder()直接調用onAsBinder(),onAsBinder()分別在BnInterface、BpInterface中進行了實現,用於獲取BnInterface、BpBinder的地址,即IInterface的作用是通過接口獲取對應的Binder對象的本地地址/代理BpBinder的地址。
BpInterface<XXX>:是一個接口,一個模板類,是一個粘合類,即繼承BpInterface<XXX>便等同於同時繼承IXXX和BpRefBase。
BnInterface<XXX>:是一個接口,一個模板類,是一個粘合類
對於用戶實現:
IXXX:是一個接口類,繼承IInterface,定義服務的方法,即純虛函數method_1()等,不能被實例化
BpXXX:是一個實現類,實現了IXXX中的純虛函數,因為不是接口類,這個實現類不需要在接口中體現(即不需要在接口的頭文件中體現,如:IMediaPlayer.h),它封裝了IXXX的操作和BpBinder的操作;
BnXXX:仍是一個接口類,未實現IXXX中的純虛函數,不能被實例化,需要一個真正工作的類來繼承、實現它,這個類才是真正執行具體功能的類。BnXXX僅實現了虛函數onTransact()(在BBinder::transact()被調用)。
XXX:實現BnXXX,會有一個XXX::instantiate()函數來注冊服務。
Binder驅動
源代碼:
kernel\drivers\staging\android\binder.h
kernel\drivers\staging\android\binder.c
參見下文驅動源代碼的分析
Binder Adapter
源代碼:
frameworks\base\include\binder\IPCThreadState.h
frameworks\base\include\binder\ProcessState.h
frameworks\base\libs\binder\IPCThreadState.cpp
frameworks\base\libs\binder\ProcessState.cpp
ProcessState
一個進程只有一個ProcessState對象,主要用於打開/dev/binder,設置設備支持的最大線程數,進行內存映射,把binder設備文件的句柄保存在mDriverFD以供IPCThreadState使用。維護進程中所有的Service代理(BpBinder對象)和其對應的handle(Binder驅動為每個Service維護一個handle,對handle的操作封裝在ProcessState中維護的BpBinder對象中)
ProcessState是singleton模式,使用靜態成員函數ProcessState::self()來構造。
構造函數:
ProcessState::ProcessState() { mDriverFD(open_driver()) //打開binder設備 open("/dev/binder", O_RDWR); ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); //最大線程數設為15,保存在binder_proc.max_threads mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); //內存映射,只讀,用於接收transactions } |
ProcessState::getStrongProxyForHandle()
作用:為Service的handle創建BpBinder對象。主要在Parcel::readStrongBinder()、ProcessState::getContextObject()中調用。
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { sp<IBinder> result;
AutoMutex _l(mLock); //互斥鎖,在ProcessState::expungeHandle()也有調用
// 查詢Service代理對象列表,如果未代理對象未創建,將在列表中增加相應位置,以保存下面將要創建的代理對象 handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) { // 1、BpBinder對象在創建時設置了RefBase標志:OBJECT_LIFETIME_WEAK。並且重寫了RefBase的虛方法:onFirstRef()、onLastStrongRef()。 // 2、創建的BpBinder對象在該函數中,只是記錄它的地址和它的引用記錄的地址,未記錄下它的強引用/弱引用 // 3、調用attemptIncWeak()是安全的,假設BpBinder對象因為弱引用計數減為0而調用BpBinder析構函數(參見:RefBase::weakref_type::decWeak()),該析構函數中要調用ProcessState::expungeHandle(),而expungeHandle()要獲取本函數中相同的互斥鎖mLock,然后把e->binder置為NULL。所以,如果下面的代碼e->binder不為NULL,expungeHandle()也無法執行把它置成NULL,析構函數也就無法完成,對象的空間也不會釋放,e->refs指向的空間就是有效的。但此時對象的引用計數可能為0,這樣調用attemptIncWeak()會失敗,當析構函數完成后,對象的空間會被釋放,所以就要重新創建一個對象。 IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { //如果弱引用計數為0,則attemptIncWeak()返回失敗 b = new BpBinder(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); // e->refs是e->binder的引用記錄的地址 result = b; } else { // This little bit of nastyness is to allow us to add a primary // reference to the remote proxy when this team doesn't have one // but another team is sending the handle to us. result.force_set(b); //調用的是 RefBase::forceIncStrong(),其中會調用BpBinder重寫的onFirstRef() e->refs->decWeak(this); //抵消上面的e->refs->attemptIncWeak()的增加 } }
return result; } |
ProcessState::startThreadPool()
只啟動一次,它直接調用ProcessState::spawnPooledThread(true),創建PoolThread對象並調用PoolThread::run()(實際上就創建了一個線程,沒看到線程池的概念),PoolThread繼承自Thread,實際上調用的是Thread::run(),其中創建線程函數_threadLoop(),其中調用PoolThread::threadLoop(),其中調用IPCThreadState::self()->joinThreadPool(mIsMain);,此處mIsMain==true,即表示進入looper
IPCThreadState
每個線程都有一個IPCThreadState對象,它有一個成員變量mProcess指向它所屬的ProcessState對象,它主要負責Binder數據讀寫和命令處理,客戶端調用transact(),服務端調用joinThreadPool()。
IPCThreadState是singleton模式,使用靜態成員函數IPCThreadState::self()來構造。
構造函數:
IPCThreadState::IPCThreadState() { mProcess(ProcessState::self()) mMyThreadId(androidGetTid()) //調用gettid()或getpid(),返回pid_t,所以線程也是當成輕量級里程看待的 pthread_setspecific(gTLS, this); //設置線程私有數據,把IPCThreadState關聯到全局靜態變量gTLS(Thread Local Storage),而gTLS在IPCThreadState::self()中創建和獲取,與gTLS關聯的私有數據釋放函數為IPCThreadState::threadDestructor(),當線程退出時調用該函數,其中又調用ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0); } |
transact():BpBinder實際上調用的是IPCThreadState::transact(),先調用writeTransactionData()構造數據,再調用waitForResponse()寫入數據並等待應答
talkWithDriver():讀取/寫入,調用ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr),把IPCThreadState::mOut(Parcel)中包含的binder_transaction_data封裝成binder_write_read寫到驅動,從驅動讀取到的binder_write_read中包含的binder_transaction_data寫到IPCThreadState::mIn(Parcel)
executeCommand():BR_***命令處理,對於BR_TRANSACTION,會調用BBinder::transact()。在joinThreadPool()、waitForResponse()中調用
joinThreadPool():循環結構,調用talkWithDriver()讀取命令,然后調用executeCommand()處理。函數名為加入線程池,更准確地說是調用binder_get_thread()在進程的內核數據中分配了一個binder_thread
writeTransactionData():把用戶的Parcel先轉換成binder_transaction_data,再把binder_transaction_data寫入IPCThreadState::mOut(也是Parcel),僅用來構造mOut。在transact()、sendReply()中調用
waitForResponse():寫入命令並等待應答,先調用talkWithDriver()寫入/讀取,然后再處理BR_***
Binder核心庫
源代碼:
frameworks\base\include\binder\Binder.h
frameworks\base\include\binder\BpBinder.h
frameworks\base\include\binder\IBinder.h
frameworks\base\libs\binder\Binder.cpp
frameworks\base\libs\binder\BpBinder.cpp
BpBinder
在ProcessState::getStrongProxyForHandle()創建,創建時會記錄下Service的handle,並增加句柄的引用計數(IPCThreadState::self()->incWeakHandle(handle);)
構造函數
參數為服務的handle
BpBinder::BpBinder(int32_t handle) : mHandle(handle) { extendObjectLifetime(OBJECT_LIFETIME_WEAK); IPCThreadState::self()->incWeakHandle(handle); } |
IPCThreadState::incWeakHandle()就是向驅動寫入了一個BC_INCREFS命令。
BpBinder::transact()
向服務端發送數據,實際上是調用IPCThreadState::transact()來實現。
BpBinder::transact() { IPCThreadState::self()->transact(mHandle,...) // mHandle在ProcessState::getStrongProxyForHandle()創建BpBinder時設置 IPCThreadState::writeTransactionData(BC_TRANSACTION,...) //構造寫入數據 IPCThreadState::waitForResponse() //寫入命令並等待應答 IPCThreadState::talkWithDriver //寫入和讀取 ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) // 處理BR_REPLY,...等命令 } |
BpRefBase
采用Bridge設計模式,它的構造函數中有一個參數sp<IBinder>,它有一個成員mRemote指向BpBinder,實際的通信工作是通過BpBinder來完成的。
對於一個服務對象,在進程中只有一個BpBinder,但可以有多個BpRefBase引用這個BpBinder
構造函數
參數為BpBinder
BpRefBase::BpRefBase(const sp<IBinder>& o) : mRemote(o.get()), mRefs(NULL), mState(0) { if (mRemote) { mRemote->incStrong(this); // Removed on first IncStrong(). mRefs = mRemote->createWeak(this); // Held for our entire lifetime. } } |
BBinder
IPCThreadState收到請求后,調用IPCThreadState::executeCommand()處理請求,其中會調用服務對象的BBinder::transact()方法,BBinder::transact()中又繼續調用BBinder派生類BnXXX重寫的onTransact()方法
Parcel
Parcel顧名思義:郵包,即是應用程序通過binder通信所使用的數據容器。
兩個重要的函數:Parcel::writeStrongBinder()、Parcel::readStrongBinder(),它們中會調用ProcessState::self()打開設備
Parcel::writeStrongBinder(constsp<IBinder>& val)
發送請求時,將binder信息寫入Parcel
Parcel::writeStrongBinder() //輸入BpBinder或BBinder,構造flat_binder_object { flat_binder_object obj; flatten_binder(ProcessState::self(), val, this); IBinder *local = binder->localBinder(); // localBinder()被IBinder定義且實現(返回NULL),被BBinder重寫(返回this) if (!local) { //參數是BpBinder,傳遞服務代理信息,客戶端A把它得到的服務對象的BpBinder告訴客戶端B,客戶端B不查詢ServiceManager也能使用服務,實現服務信息共享 BpBinder *proxy = binder->remoteBinder(); // remoteBinder()被IBinder定義且實現(返回NULL),被BpBinder重寫(返回this) const int32_t handle = proxy ? proxy->handle() : 0; obj.type = BINDER_TYPE_HANDLE; obj.handle = handle; //服務對象的handle obj.cookie = NULL; } else { //參數是BBinder,傳遞服務對象信息 obj.type = BINDER_TYPE_BINDER; obj.binder = local->getWeakRefs(); //服務對象的引用記錄的地址 obj.cookie = local; //服務對象的地址 } finish_flatten_binder() //把flat_binder_object寫到Parcel.mObjects緩沖區,在驅動傳輸的過程中(binder_transaction()),為創建binder_node、binder_ref Parcel::writeObject() } |
Parcel::readStrongBinder()
接收應答時,從Parcel取出binder信息
Parcel::readStrongBinder() //返回BpBinder或BBinder,會把handle轉換成BpBinder { unflatten_binder(ProcessState::self(), *this, &val); Parcel::readObject() //從Parcel.mObjects緩沖區讀取flat_binder_object switch (flat->type) { //讀取結構 flat_binder_object case BINDER_TYPE_BINDER: //客戶端和服務在同一進程,返回BBinder *out = static_cast<IBinder*>(flat->cookie); case BINDER_TYPE_HANDLE: //客戶端和服務不在同一進程,返回BpBinder *out = proc->getStrongProxyForHandle(flat->handle); } |
C++ Binder框架
源代碼:
frameworks\base\include\binder\IInterface.h
frameworks\base\include\binder\Parcel.h
frameworks\base\libs\binder\IInterface.cpp
frameworks\base\libs\binder\Parcel.cpp
IInterface
IInterface::asBinder()
asBinder()直接調用純虛函數IInterface::onAsBinder(),onAsBinder()分別在BnInterface、BpInterface中進行了實現,用於獲取BnInterface、BpBinder的地址,即IInterface的作用是通過接口獲取對應的Binder對象的本地地址/代理BpBinder的地址
sp<IBinder> IInterface::asBinder() { return this ? onAsBinder() : NULL; }
template<typename INTERFACE> IBinder* BnInterface<INTERFACE>::onAsBinder() { return this; }
template<typename INTERFACE> inline IBinder* BpInterface<INTERFACE>::onAsBinder() { return remote(); } |
BpInterface<XXX>
構造函數
參數為BpBinder
template<typename INTERFACE> inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote) : BpRefBase(remote) { } |
interface_cast<XXX>(constsp<IBinder>& obj)
看名字就知道它是一個進行類型轉換的函數,前面根據handle創建了BpBinder,進而創建了BpBinder,接下來就是要利用模板函數interface_cast<XXX>()根據BpBinder創建BpXXX。
函數的參數可以是BpBinder或BBinder,返回的是BpXXX或BnXXX。
template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); } |
函數直接調用了IXXX::asInterface(),它是通過宏DECLARE_META_INTERFACE、IMPLEMENT_META_INTERFACE來聲明和實現的。
DECLARE_META_INTERFACE、IMPLEMENT_META_INTERFACE
在IXXX類的聲明中,調用DECLARE_META_INTERFACE(XXX);,在IXXX類的實現中,調用IMPLEMENT_META_INTERFACE(XXX, "接口名稱");
其中關鍵的實現為:
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ ... android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ const android::sp<android::IBinder>& obj) \ { \ android::sp<I##INTERFACE> intr; \ if (obj != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == NULL) { \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ } \ |
注釋:
IBinder定義並實現了虛函數queryLocalInterface()(為空函數直接返回NULL),BpBinder繼承IBinder但未重寫該虛函數,BnInterface繼承BBinder繼承IBinder,重寫了該函數(if (_descriptor ==INTERFACE::descriptor) return this;),所以,如果asInterface()的參數為BpBinder,那么每次調用都會創建一個BpXXX,如果參數為BBinder,只是直接返回BBinder對象的地址,作用是在同一個進程中調用Binder將直接得到BBinder對象的地址。調用者無需要關心調用的對象是遠程的還是本地的
參數NAME只是接口的名字,無實質作用,和服務的名字不是一回事
實現服務
參考代碼:
frameworks\base\include\media\IMediaPlayerService.h
frameworks\base\media\libmedia\IMediaPlayerService.cpp
frameworks\base\media\libmediaplayerservice\MediaPlayerService.h
frameworks\base\media\libmediaplayerservice\MediaPlayerService.cpp
編碼
IXXX.h:
定義class IXXX:public IInterface:
調用宏DECLARE_META_INTERFACE(XXX);;
定義一系列接口用到的純虛函數,如:method_1()、method_2()
定義class BnXXX:public BnInterface<IXXX>:
重寫onTransact()
IXXX.cpp:
定義class BpXXX:public BpInterface<IXXX>:
構造函數中調用BpInterface<IXXX >(impl);
調用宏IMPLEMENT_META_INTERFACE(XXX,"android.xxx.IXXX");;
實現接口的方法(其中調用remote()->transact)
實現BnXXX::onTransact():
重寫onTransact(),其中調用由BnXXX派生類XXX實現的接口方法
XXX.h、XXX.cpp:
定義class XXX:public BnXXX
實現接口的方法
BpXXX
構造函數
參數為BpBinder,BpXXX的構造函數中有一個參數sp<IBinder>& impl,說明它采用了Bridge模式,BpBinder是它的實現。
BpXXX(const sp<IBinder>& impl) : BpInterface<IXXX>(impl) { } |
BpXXX::method_1()
該函數內不執行具體的操作,只是把請求發給服務端
virtual void method_1(int id) { Parcel data, reply; data.writeInt32(id); //構造發送數據
remote()->transact(CMD_METHOD_1, data, &reply); // CMD_METHOD_1是發送的命令 } |
BpXXX繼承BpRefBase,BpRefBase定義了成員函數remote(),該函數返回的實際上就是BpBinder,然后調用BpBinder::transact()發送數據
BnXXX
BnXXX::onTransact()
BnXXX::onTransact()在BBinder::transact()中調用,它根據收到的命令,分別調用對應的方法。
status_t BnXXX::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case CMD_METHOD_1: { pid_t pid = data.readInt32(); rtn = method_1(pid); //調用的是BnXXX的派生類XXX實現的method_1() reply->writeInt32(rtn); } } } |
XXX
實現XXX::method_1()
ServiceManager
源代碼:
frameworks\base\cmds\servicemanager\*
服務進程向ServiceManager注冊服務,客戶進程向ServiceManager查詢服務,從而得到訪問服務對象的handle。
ServiceManager維護服務名稱字符串,它本身也是一個服務,調用binder_become_context_manager()變為“Server大總管”的服務,他對於其它進程來說,它的handle永遠是0。它是第一個啟動的服務,在/init.rc中啟動。
ISericeManager本地功能BnServiceManager並沒有實現,本地功能實際上由servicemanager守護進程執行,而用戶程序通過調用BpServiceManager來獲得其他的服務。
ServiceManager主程序代碼
frameworks\base\cmds\servicemanager\service_manager.c
main() { // 其中調用binder_***()函數位於frameworks\base\cmds\servicemanager\binder.c binder_open(128*1024); open("/dev/binder") //調用驅動的binder_open() mmap() //把/dev/binder映射到一個128*1024字節大小的內存 binder_become_context_manager() ioctl(BINDER_SET_CONTEXT_MGR) binder_loop(bs, svcmgr_handler); //注冊請求處理函數 svcmgr_handler() binder_write() //寫命令BC_ENTER_LOOPER // 開始循環 ioctl(BINDER_WRITE_READ); //只是讀取 binder_parse() //調用svcmgr_handler()處理BR_TRANSACTION,...等命令, } |
svcmgr_handler()
請求處理函數
對於客戶端請求服務,返回的是Service的handle,binder類型是BINDER_TYPE_HANDLE,見函數bio_put_ref(),然后在驅動層binder_thread_write() ->binder_transaction()會進行轉換,如果請求的服務在同一進程里,則轉換類型成BINDER_TYPE_BINDER,直接使用服務對象的地址,而不使用handle,這在unflatten_binder()中有體現。
獲取ServiceManager服務代理
sp<IServiceManager> defaultServiceManager() { if (gDefaultServiceManager != NULL) return gDefaultServiceManager; //單一實例
{ AutoMutex _l(gDefaultServiceManagerLock); if (gDefaultServiceManager == NULL) { gDefaultServiceManager = interface_cast<IServiceManager>( //調用interface_cast<XXX>根據BpBinder生成BpServiceManager ProcessState::self()->getContextObject(NULL)); } }
return gDefaultServiceManager; }
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller) { if (supportsProcesses()) { return getStrongProxyForHandle(0); //調用ProcessState::getStrongProxyForHandle()創建BpBinder,handle為0 } else { return getContextObject(String16("default"), caller); } } |
注冊服務
status_t BpServiceManager::addService(const String16& name, const sp<IBinder>& service) //參數service可以是BpBinder或BBinder,binder驅動會記錄下對象的地址 { data.writeStrongBinder(service); remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); } |
查詢服務
sp<IBinder> BpServiceManager::getService(const String16& name) //函數返回BpBinder或BBinder { BpServiceManager::checkService() remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); reply.readStrongBinder() } |
調用服務
服務端
服務端如何工作
創建ProcessState對象,打開/dev/binder,映射好內存
調用defaultServiceManager()創建ServiceManager的代理
調用服務端類的方法instantiate(),創建服務端對象,並向ServiceManager注冊
ProcessState::self()->startThreadPool();,其中也會調用IPCThreadState::joinThreadPool(),參數是true,加上下面的,總共調用了2次
IPCThreadState::self()->joinThreadPool();,參數默認也是true,進入服務的循環監聽狀態。(網上有人測試過把最后一句屏蔽掉,也能正常工作。但是難道主線程提出了,程序還能不退出嗎?)
參考代碼:
frameworks\base\media\mediaserver\main_mediaserver.cpp
int main(int argc, char** argv) { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); LOGI("ServiceManager: %p", sm.get()); AudioFlinger::instantiate(); MediaPlayerService::instantiate(); CameraService::instantiate(); AudioPolicyService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }
void MediaPlayerService::instantiate() { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService()); //注冊時,要附上服務名稱、服務對象的地址,服務對象的地址最終是記錄在驅動中 } |
客戶端
客戶端如何調用服務
調用defaultServiceManager()創建ServiceManager的代理,其中會創建ProcessState對象
調用BpServiceManager::getService()獲取服務的handle,並生成對應的BpBinder
調用BpBinder::linkToDeath(),注冊服務死亡的通知
調用interface_cast<IXXX>()利用BpBinder生成BpXXX