在這篇文章中,我們將深入剖析一下Android系統的服務管理員ServiceManager。
ServiceManager是Android系統服務的管理者。所有需要通過Binder機制進行處理序間通訊的進程都要首先獲得Service Manager的代理對象才能進行Binder通訊。比如系統中有用於音頻混音的AudioFlingerService,用於照相的CameraService,用於媒體檔案播放的MediaPlayerService。所有這些服務都會向ServiceManager註冊,因此ServiceManager就維護了系統中所有服務的一個列表。任何應用程式要想使用這些服務,首先要向ServiceManager請求獲得這些服務的引用,從而建立起和這些服務的聯絡。
在本系列的第一篇文章中,ExampleService通過如下語句向系統註冊服務。
// File: ExampleService.cpp<br />int r = defaultServiceManager()->addService(String16("byn.example"), new ExampleService());
這裡有兩個問題:
1. defaultServiceManager()都完成了哪些工作,它返回的結果是什嗎?
2. 為什麼調用上一步返回對象的addService方法,就可以向系統註冊服務?這一註冊過程都完成了哪些工作?
這篇文章先回答問題1。
ServiceManager也是系統中的一個服務,那麼應用程式如何和它取得聯絡呢?答案就是通過defaultServiceManager()函數。defaultServiceManager()是系統在Android命名空間中定義的一個全域函數,用來獲得ServiceManager的代理對象的引用。我們看一下該函數的原始碼。
// File: framework/base/libs/binder/IServiceManager.cpp<br />sp<IServiceManager> defaultServiceManager()<br />{<br /> if (gDefaultServiceManager != NULL) return gDefaultServiceManager; // 如果該代理對象已經存在,直接返回該對象</p><p> {<br /> AutoMutex _l(gDefaultServiceManagerLock);<br /> if (gDefaultServiceManager == NULL) {<br /> gDefaultServiceManager = interface_cast<IServiceManager>(<br /> ProcessState::self()->getContextObject(NULL));<br /> }<br /> }</p><p> return gDefaultServiceManager;<br />}
gDefaultServiceManager在libutil中定義,因此任何程式或庫使用了libutil庫都會有該變數,它在一個進程中是唯一的。gDefaultServiceManager的初始值為NULL,所以先調用ProcessState::self()方法擷取一個ProcessState執行個體。這裡用到了Singleton的設計模式,從而可知一個進程只有一個ProcessState執行個體。// File: Frameworks/base/libs/binder/ProcessState.cpp<br />sp<ProcessState> ProcessState::self()<br />{<br /> if (gProcess != NULL) return gProcess;</p><p> AutoMutex _l(gProcessMutex);<br /> if (gProcess == NULL) gProcess = new ProcessState;<br /> return gProcess;<br />}
該ProcessState會開啟/dev/binder裝置供IPCThreadState使用。查看其建構函式便知。
// File: frameworks/base/libs/binder/ProcessState.cpp<br />ProcessState::ProcessState()<br /> : mDriverFD(open_driver())<br /> , mVMStart(MAP_FAILED)<br /> , mManagesContexts(false)<br /> , mBinderContextCheckFunc(NULL)<br /> , mBinderContextUserData(NULL)<br /> , mThreadPoolStarted(false)<br /> , mThreadPoolSeq(1)<br />{<br /> if (mDriverFD >= 0) {<br /> // XXX Ideally, there should be a specific define for whether we<br /> // have mmap (or whether we could possibly have the kernel module<br /> // availabla).<br />#if !defined(HAVE_WIN32_IPC)<br /> // mmap the binder, providing a chunk of virtual address space to receive transactions.<br /> mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);<br /> if (mVMStart == MAP_FAILED) {<br /> // *sigh*<br /> LOGE("Using /dev/binder failed: unable to mmap transaction memory./n");<br /> close(mDriverFD);<br /> mDriverFD = -1;<br /> }<br />#else<br /> mDriverFD = -1;<br />#endif<br /> }<br /> if (mDriverFD < 0) {<br /> // Need to run without the driver, starting our own thread pool.<br /> }<br />}
再看一下open_driver()方法的原始碼。
// File: frameworks/base/libs/binder/ProcessState.cpp<br />static int open_driver()<br />{<br /> if (gSingleProcess) {<br /> return -1;<br /> }</p><p> int fd = open("/dev/binder", O_RDWR);<br /> if (fd >= 0) {<br /> fcntl(fd, F_SETFD, FD_CLOEXEC);<br /> int vers;<br />#if defined(HAVE_ANDROID_OS)<br /> status_t result = ioctl(fd, BINDER_VERSION, &vers);<br />#else<br /> status_t result = -1;<br /> errno = EPERM;<br />#endif<br /> if (result == -1) {<br /> LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));<br /> close(fd);<br /> fd = -1;<br /> }<br /> if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {<br /> LOGE("Binder driver protocol does not match user space protocol!");<br /> close(fd);<br /> fd = -1;<br /> }<br />#if defined(HAVE_ANDROID_OS)<br /> size_t maxThreads = 15;<br /> result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);<br /> if (result == -1) {<br /> LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));<br /> }<br />#endif</p><p> } else {<br /> LOGW("Opening '/dev/binder' failed: %s/n", strerror(errno));<br /> }<br /> return fd;<br />}
open_driver()方法開啟binder裝置(/dev/binder),擷取binder版本號碼,設定最大線程個數,並返回binder裝置的檔案描述符。核心空間中分配約1M的連續空間(BINDER_VM_SIZE)給進程,並用mmap函數映射到進程的使用者空間。該空間用於transaction互動資料用。
回到defaultServiceManager()方法。我們可以看到defaultServiceManager()是調用ProcessState對象的getContextObject方法獲得ServiceManager的代理對象。我們再看一下getContextObject函數的原始碼:
// File: frameworks/base/libs/binder/ProcessState.cpp<br />sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)<br />{<br /> if (supportsProcesses()) {<br /> return getStrongProxyForHandle(0);<br /> } else {<br /> return getContextObject(String16("default"), caller);<br /> }<br />}
因為支援binder驅動(supportsProcesses()函數會判斷binder驅動是否開啟,以此來檢驗是否支援binder),這裡是以0為參數調用getStrongProxyForHandle()方法獲得ServiceManager的代理對象。我們再看一下getStrongProxyForHandle()方法的原始碼:
// File: frameworks/base/libs/binder/ProcessState.cpp<br />sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)<br />{<br /> sp<IBinder> result;</p><p> AutoMutex _l(mLock);</p><p> handle_entry* e = lookupHandleLocked(handle);</p><p> if (e != NULL) {<br /> // We need to create a new BpBinder if there isn't currently one, OR we<br /> // are unable to acquire a weak reference on this current one. See comment<br /> // in getWeakProxyForHandle() for more info about this.<br /> IBinder* b = e->binder;<br /> if (b == NULL || !e->refs->attemptIncWeak(this)) {<br /> b = new BpBinder(handle);<br /> e->binder = b;<br /> if (b) e->refs = b->getWeakRefs();<br /> result = b;<br /> } else {<br /> // This little bit of nastyness is to allow us to add a primary<br /> // reference to the remote proxy when this team doesn't have one<br /> // but another team is sending the handle to us.<br /> result.force_set(b);<br /> e->refs->decWeak(this);<br /> }<br /> }</p><p> return result;<br />}
getStrongProxyForHandle()首先調用lookupHandleLocked()方法尋找當前進程是否維護的Service代理對象的列表。我們再看一下lookupHandleLocked()方法的原始碼。
// File: ProcessState.cpp<br />ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)<br />{<br /> const size_t N=mHandleToObject.size();<br /> if (N <= (size_t)handle) {<br /> handle_entry e;<br /> e.binder = NULL;<br /> e.refs = NULL;<br /> status_t err = mHandleToObject.insertAt(e, N, handle+1-N);<br /> if (err < NO_ERROR) return NULL;<br /> }<br /> return &mHandleToObject.editItemAt(handle);<br />}
mHHandleToObject是一個以handle_entry類型為元素的Vector,維護當前進程的代理對象列表。其索引就是每個代理物件控點的值。比如ServiceManager對應的控制代碼肯定是0,那麼它就是這個列表的第1項。如果待查詢的的控制代碼的值大於等於當前列表的大小,說明待建立的Service代理對象條目尚未在當前進程中建立,那麼就需要插入新項。當前的列表大小是N,索引從0至N-1,如果待查詢的索引是handle,那麼就要插入handle-(N-1)項。如果該代理對象條目已經建立過了,那麼直接返回其引用就可以了。
註:這裡的“建立”只是在列表中建立相應的條目(e.binder = NULL;e.refs = NULL;),真正的代理對象要在稍後才建立。
現在回到getStrongProxyForHandle()方法。如果該代理對象尚未建立(e->binder==NULL),那麼就建立一個,並更新代理對象列表中的相應記錄。
我們再來看一下BpBinder類的建構函式做了什麼。
// File: frameworks/base/libs/binder/BpBinder.cpp<br />BpBinder::BpBinder(int32_t handle)<br /> : mHandle(handle)<br /> , mAlive(1)<br /> , mObitsSent(0)<br /> , mObituaries(NULL)<br />{<br /> LOGV("Creating BpBinder %p handle %d/n", this, mHandle);</p><p> extendObjectLifetime(OBJECT_LIFETIME_WEAK);<br /> IPCThreadState::self()->incWeakHandle(handle);<br />}
這裡調用了IPCThreadState類的incWeakHandle()方法來增加引用計數。我們再看看incWeakHandle()方法的原始碼。
// File: frameworks/base/libs/binder/IPCThreadState.cpp<br />void IPCThreadState::incWeakHandle(int32_t handle)<br />{<br /> LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)/n", handle);<br /> mOut.writeInt32(BC_INCREFS);<br /> mOut.writeInt32(handle);<br />}
這裡incWeakHandle()在輸出緩衝區增加了一條BC_INCREFS命令。
如果該handle對應的代理對象已經建立過了,那麼就增加它的引用計數。result是一個指向IBinder類型的強指標。Android系統中定義了sp(strong pointer)和wp(weak pointer)兩種智能指標。注意這裡的操作符"="已經被重載了。force_set是RefBase類專門為ProcessState類最佳化的一個方法,讓我們看一下它的原始碼。
// File: frameworks/base/include/utils/RefBase.h<br />template<typename T><br />void sp<T>::force_set(T* other)<br />{<br /> other->forceIncStrong(this);<br /> m_ptr = other;<br />}
設定好引用計數之後,getStrongProxyForHandle()方法返回代理對象的控制代碼。接下來會通過interface_cast將其轉換為IserviceManager類型。我們來看看這個轉換是怎麼實現的。
gDefaultServiceManager = interface_cast<IServiceManager>(<br /> ProcessState::self()->getContextObject(NULL));<br />
interface_cast<IServiceManager>,其實調用的是IServiceManager.asInterface方法:
// File: frameworks/base/include/binder/IInterface.h<br />template<typename INTERFACE><br />inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)<br />{<br /> return INTERFACE::asInterface(obj);<br />}
查看IServiceManager的源檔案,好像並沒有定義asInterface方法。不要急,我們先看一下IServiceManager的定義:
// File: frameworks/base/include/binder/IServiceManager.h<br />class IServiceManager : public IInterface<br />{<br />public:<br /> DECLARE_META_INTERFACE(ServiceManager);</p><p> /**<br /> * Retrieve an existing service, blocking for a few seconds<br /> * if it doesn't yet exist.<br /> */<br /> virtual sp<IBinder> getService( const String16& name) const = 0;</p><p> /**<br /> * Retrieve an existing service, non-blocking.<br /> */<br /> virtual sp<IBinder> checkService( const String16& name) const = 0;</p><p> /**<br /> * Register a service.<br /> */<br /> virtual status_t addService( const String16& name,<br /> const sp<IBinder>& service) = 0;</p><p> /**<br /> * Return list of all existing services.<br /> */<br /> virtual Vector<String16> listServices() = 0;</p><p> enum {<br /> GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,<br /> CHECK_SERVICE_TRANSACTION,<br /> ADD_SERVICE_TRANSACTION,<br /> LIST_SERVICES_TRANSACTION,<br /> };<br />};
這裡的宏DECLARE_META_INTERFACE在IInterface.h標頭檔中定義如下:
// File: frameworks/base/include/binder/IInterface.h<br />#define DECLARE_META_INTERFACE(INTERFACE) /<br /> static const String16 descriptor; /<br /> static sp<I##INTERFACE> asInterface(const sp<IBinder>& obj); /<br /> virtual const String16& getInterfaceDescriptor() const; /<br /> I##INTERFACE(); /<br /> virtual ~I##INTERFACE(); /
這裡,我們終於找到了asInterface方法的聲明。該方法是通過在IServiceManager.cpp檔案中的IMPLEMENT_META_INTERFACE宏來實現的。
// File: frameworks/base/include/binder/IServiceManager.cpp<br />IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
IMPLEMENT_META_INTERFACE宏定義如下:
// File: frameworks/base/include/binder/IInterface.h<br />#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) /<br /> const String16 I##INTERFACE::descriptor(NAME); /<br /> const String16& I##INTERFACE::getInterfaceDescriptor() const { /<br /> return I##INTERFACE::descriptor; /<br /> } /<br /> sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj) /<br /> { /<br /> sp<I##INTERFACE> intr; /<br /> if (obj != NULL) { /<br /> intr = static_cast<I##INTERFACE*>( /<br /> obj->queryLocalInterface( /<br /> I##INTERFACE::descriptor).get()); /<br /> if (intr == NULL) { /<br /> intr = new Bp##INTERFACE(obj); /<br /> } /<br /> } /<br /> return intr; /<br /> } /<br /> I##INTERFACE::I##INTERFACE() { } /<br /> I##INTERFACE::~I##INTERFACE() { } /
將上面這些宏展開後的最終結果就是,
sp<IServiceManager> IServiceManager::asInterface(const sp<IBinder>& obj)<br />{<br /> sp<IServiceManager> intr;<br /> if (obj != NULL) {<br /> intr = static_cast<IServiceManager*>(obj->queryLocalInterface(<br /> IServiceManager::descriptor).get());<br /> if (intr == NULL) {<br /> intr = new BpServiceManager(obj);<br /> }<br /> }<br /> return intr;<br />}
可見,IServiceManager::asInterface()函數最終會用一個IBinder對象建立一個BpServiceManager對象,並將它返回。
好了,現在我們總結一下擷取ServiceManager代理對象的全部過程:
defaultServiceManager(); // 擷取ServiceManager代理對象
{
interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL)); // 將返回的BpBinder類型的代理對象轉換成ServiceManager類型的代理對象
{
getStrongProxyForHandle(0); // 以0為參數即可獲得ServiceManager的代理對象
{
lookupHandleLocked(0);
b = new BpBinder(0); // 建立一個代理對象
返回根據handle產生的代理對象
}
返回根據handle產生的代理對象
}
返迴轉換成ServiceManager類型的代理對象
}
最後,我們可以回答問題1了:
問題: defaultServiceManager()都完成了哪些工作,它返回的結果是什嗎?
答: 如果當前進程已經產生了ServiceManager的代理對象,那麼該函數返回它的一個引用;如果當前進程還沒有產生過ServiceManager的代理對象,那麼建立它,並返回它的一個引用。
我們將在下篇文章中深入剖析為什麼調用該引用指向的getService方法就可以獲得ExampleService的代理對象的引用。