Android系統的Binder機制之一——ServiceManager
Android雖然構建在Linux上面,但是在IPC(進程間)機制方面,沒有利用Linux提供IPC機制,而是自己實現了一套輕量級的IPC機制 ——binder機制。並且Android Binder機制之上,Android框架提供了一套封裝,可以實現對象代理(在本地進程中代理遠程進程的對象)。本文簡單分析一下Android Binder機制。
Binder情景分析
一個IPC通訊我們可以理解成客戶端-服務器模式,因此我們先在這裏分析一下典型的Binder應用模式:
1、客戶端通過某種方式(後文會詳細介紹)得到服務器端的代理對象。從客戶端角度看來代理對象和他的本地對象沒有什麼差別。它可以像其他本地對象一樣調用其方法,訪問其變量。
2、客戶端通過調用服務器代理對象的方法向服務器端發送請求。
3、代理對象把用戶請求通過Android內核(Linux內核)的Binder驅動發送到服務器進程。
4、服務器進程處理用戶請求,並通過Android內核(Linux內核)的Binder驅動返回處理結果給客戶端的服務器代理對象。
5、客戶端收到服務器端的返回結果。
如果你對COM或者Corba熟悉的話,以上的情景是否會讓你聯想到什麼呢?沒錯!都是對象代理。以上的情景,在Android中經常會被用到。如果你還沒有注意到這點兒,那麼本文非常適合你。
Binder機制的組成
1、Binder驅動
binder是內核中的一個字符驅動設備位於:/dev/binder。這個設備是Android系統IPC的核心部分,客戶端的服務代理用來通過它向服 務器(server)發送請求,服務器也是通過它把處理結果返回給客戶端的服務代理對象。我們只需要知道它的功能就可以了,本文我們的重點不在這裏,所以後面不會專門介紹這部分,因爲很少會有人會顯示打開這個設備去開發Android程序。如果想深入瞭解的話,請研究內核源碼中的binder.c。
2、Service Manager
負責管理服務。對應於第一步中,客戶端需要向Service Manager來查詢和獲得所需要服務。服務器也需要向ServiceManager註冊自己提供的服務。可以看出Service Manager是服務的大管家。
3、服務(Server)
需要強調的是這裏服務是指的是System Server,而不是SDK server,請參考《(轉)高煥堂——Android框架底層結構知多少?》關於兩種Server的介紹(其實應該是三種,丟掉了init調用的server,在init.rc中配置)。
4、客戶端
一般是指Android系統上面的應用程序。它可以請求Server中的服務。
5、對象代理
是指在客戶端應用程序中生成的Server代理(proxy)。從應用程序角度看代理對象和本地對象沒有差別,都可以調用其方法,方法都是同步的,並且返回相應的結果。
大內總管——Service Manager
Android系統Binder機制的總管是Service Manager,所有的Server(System Server)都需要向他註冊,應用程序需要向其查詢相應的服務。可見其作用是多麼的重要,所以本文首先介紹Service Manager。
通過上面介紹我們知道ServiceManager非常重要,責任重大。那麼怎樣才能成爲Service Manager呢?是不是誰都可以成爲Service Manager呢?怎樣處理server的註冊和應用程序的查詢和獲取服務呢?爲了回答這些問題先查看,Android中Service Manager的源碼,其源碼位於:
frameworks\base\cmds\servicemanager\service_manager.c
我們發現了main函數,說明他自己就是一個進程,在init.rc中我們發現:
service servicemanager /system/bin/servicemanager
user system
critical
onrestart restart zygote
onrestart restart media
說明其是Android核心程序,開機就會自動運行。
下面我們在研究一下它的代碼,main函數很簡單:
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
LOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
我們看到它先調用binder_open打開binder設備(/dev/binder),其次它調用了binder_become_context_manager函數,這個函數使他自己變爲了“Server大總管”,其代碼如下:
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
也就是通過ioctl向binder設備聲明“我就是server大總管”。
Service Manager作爲一個Server大總管,本身也是一個server。既然是一個server就要時刻準備爲客戶端提供服務。最好Service Manager調用binder_loop進入到循環狀態,並提供了一個回調函數,等待用戶的請求。注意他的ServiceManager的客戶端既包括應用程序(查詢和獲取服務),也包括Server(註冊服務)。
Service Manager的客戶怎樣才能請求其服務呢?答案是上文我們提到的情景一樣。客戶需要在自己進程中創建一個服務器代理。現在沒有地方去查詢服務,那麼怎樣它的客戶怎樣生成他的服務代理對象呢?答案是binder設備(/devbinder)爲每一個服務維護一個句柄,調用 binder_become_context_manager函數變爲“Server大總管”的服務,他的句柄永遠是0,是一個“衆所周知”的句柄,這樣 每個程序都可以通過binder機制在自己的進程空間中創建一個
Service Manager代理對象了。其他的服務在binder設備在設備中的句柄是不定的,需要向“Server大總管”查詢才能知道。
現在我們需要研究Server怎樣註冊服務了,還是在其源碼中,我們可以看到在其服務處理函數中(上文提到binder_loop函數註冊給binder設備的回調函數)有如下代碼:
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);
if (do_add_service(bs, s, len, ptr, txn->sender_euid))
return -1;
break;
有server向binder設備寫入請求註冊Service時,Service Manager的服務處理回調函數將會被調用。我們在仔細看看do_add_service函數的實現:
int do_add_service(struct binder_state *bs,
uint16_t *s, unsigned len,
void *ptr, unsigned uid)
{
struct svcinfo *si;
// LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);
if (!ptr || (len == 0) || (len > 127))
return -1;
if (!svc_can_register(uid, s)) {
LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
str8(s), ptr, uid);
return -1;
}
si = find_svc(s, len);
if (si) {
if (si->ptr) {
LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",
str8(s), ptr, uid);
return -1;
}
si->ptr = ptr;
} else {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
str8(s), ptr, uid);
return -1;
}
si->ptr = ptr;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = svcinfo_death;
si->death.ptr = si;
si->next = svclist;
svclist = si;
}
binder_acquire(bs, ptr);
binder_link_to_death(bs, ptr, &si->death);
return 0;
}
我們看到首先檢查是否有權限註冊service,沒權限就對不起了,出錯返回;然後檢查是否已經註冊過,註冊過的 service將不能再次註冊。然後構造一個svcinfo對象,並加入一個全局鏈表中svclist中。最後通知binder設備:有一個 service註冊進來。
我們再來看看客戶端怎樣通過ServiceManager獲得Service,還是在服務處理函數中(上文提到binder_loop函數註冊給binder設備的回調函數)有如下代碼:
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
ptr = do_find_service(bs, s, len);
if (!ptr)
break;
bio_put_ref(reply, ptr);
return 0;
我們可以看到通過do_find_service查找Service如果查找到的話,寫入reply中返回給客戶端。
本文我們簡單分析了一下ServiceManager,後續我們會繼續分析Android binder機制的其他部分。
Android系統的Binder機制之二——服務代理對象(1)
上文《Android系統的Binder機制之一——ServiceManager》我們學習了Service Manager在Android Binder中的作用——服務(Service)註冊,服務(Service)查詢的功能。本文我們一起學習服務(Service)在客戶端中的代理機制。重點介紹其核心對象BpBinder。
1、服務代理的原理
如下是客戶端請求service服務的場景:
1、首先客戶端向Service manager查找相應的Service。上文《Android系統的Binder機制之一——ServiceManager》有比較詳細的介紹。注意客戶端和Service可能在兩個不同的進程中。
2、Android系統將會爲客戶端進程中創建一個Service代理。下文將詳細介紹該創建過程。
3、客 戶端視角只有Service代理,他所有對Service的請求都發往Service代理,然後有Service代理把用戶請求轉發給Service本 身。Service處理完成之後,把結果返回給Service代理,Service代理負責把處理結果返回給客戶端。注意客戶端對Service代理的調 用都是同步調用(調用掛住,直到調用返回爲止),這樣客戶端視角來看調用遠端Service的服務和調用本地的函數沒有任何區別。這也是Binder機制 的一個特點。
2、Android進程環境——ProcessState類型和對象
在Android系統中任進程何,要想使用Binder機制,必須要創建一個ProcessState對象和IPCThreadState對象。當然如果 Android進程不使用Binder機制,那麼這兩個對象是不用創建的。這種情況很少見,因爲Binder機制是整個Android框架的基礎,可以說 影響到Android方方面面。所以說了解這兩個對象的作用非常重要。
臺灣的高煥堂先生一片文章《認識ProcessState類型和對象》,可以在我的博文《(轉)高煥堂——Android框架底層結構知多少?》中找到。可以先通過這篇文章對ProcessState進行一個大概瞭解。
ProcessState是一個singleton類型,一個進程只能創建一個他的對象。他的作用是維護當前進程中所有Service代理(BpBinder對象)。一個客戶端進程可能需要多個Service的服務,這樣可能會創建多個Service代理(BpBinder對象),客戶端進程中的ProcessState對象將會負責維護這些Service代理。
我們研究一下創建一個Service代理的代碼:
1: sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
2: {
3: sp<IBinder> result;
4:
5: AutoMutex _l(mLock);
6:
7: handle_entry* e = lookupHandleLocked(handle);
8:
9: if (e != NULL) {
10: // We need to create a new BpBinder if there isn't currently one, OR we
11: // are unable to acquire a weak reference on this current one. See comment
12: // in getWeakProxyForHandle() for more info about this.
13: IBinder* b = e->binder;
14: if (b == NULL || !e->refs->attemptIncWeak(this)) {
15: b = new BpBinder(handle);
16: e->binder = b;
17: if (b) e->refs = b->getWeakRefs();
18: result = b;
19: } else {
20: // This little bit of nastyness is to allow us to add a primary
21: // reference to the remote proxy when this team doesn't have one
22: // but another team is sending the handle to us.
23: result.force_set(b);
24: e->refs->decWeak(this);
25: }
26: }
27:
28: return result;
29: }
getWeakProxyForHandle函數的作用是根據一個binder句柄(上文《Android系統的Binder機制之一——Service Manager》提到Binder驅動爲每個Service維護一個Binder句柄,客戶端可以通過句柄來和Service通訊)創建對應的Service代理對象。
當前進程首先調用lookupHandleLocked函數去查看當前進程維護的Service代理對象的列表,該待創建Service代理對象是否已經 在當前進程中創建,如果已經創建過了,則直接返回其引用就可以了。否則將會在Service代理對象的列表增加相應的位置(注意系統爲了減少分配開銷,可 能會多分配一些空間,策略是“以空間換時間”),保存將要創建的代理對象。具體代碼請參考lookupHandleLocked的源碼。
後面代碼就好理解了,如果Service代理對象已經創建過了,直接增加引用計數就行了。若沒有創建過,則需要創建一個新的Service代理對象。
3、Android進程環境——IPCThreadState類型和對象
Android進程中可以創建一個ProcessState對象,該對象創建過程中會打開/dev/binder設備,並保存其句柄。並初始化該設備。代碼如下:
1: ProcessState::ProcessState()
2: : mDriverFD(open_driver())
3: , mVMStart(MAP_FAILED)
4: , mManagesContexts(false)
5: , mBinderContextCheckFunc(NULL)
6: , mBinderContextUserData(NULL)
7: , mThreadPoolStarted(false)
8: , mThreadPoolSeq(1)
9: {
10: if (mDriverFD >= 0) {
11: // XXX Ideally, there should be a specific define for whether we
12: // have mmap (or whether we could possibly have the kernel module
13: // availabla).
14:#if !defined(HAVE_WIN32_IPC)
15: // mmap the binder, providing a chunk of virtual address space to receive transactions.
16: mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
17: if (mVMStart == MAP_FAILED) {
18: // *sigh*
19: LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
20: close(mDriverFD);
21: mDriverFD = -1;
22: }
23:#else
24: mDriverFD = -1;
25:#endif
26: }
27: if (mDriverFD < 0) {
28: // Need to run without the driver, starting our own thread pool.
29: }
30: }
mDriverFD保存了/dev/binder設備的句柄,如果仔細查看ProcessState的源碼會發現這個句柄不會被ProcessState 對象使用。那麼保存這個句柄做什麼用呢?被誰使用呢?非常奇怪。經過查看ProcessState的頭文件,發現如下代碼:
1:friendclass IPCThreadState;
發現IPCThreadState是ProcessState的友元類,那麼就可以懷疑這個句柄是被IPCThreadState的對象使用的,然後查看代碼發現確實如此。
IPCThreadState也是一個singleton的類型,一個進程中也只能有一個這樣的對象。我們查看一下它的talkWithDriver函數:
1: ...........
2:if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
3: err = NO_ERROR;
4:else
5: err = -errno;
6: ...........
IPCThreadState通過ioctl系統調用對ProcessState打開的句柄進行讀寫。這樣我們也可以看出IPCThreadState對象的作用:
1、維護當前進程中所有對/dev/binder的讀寫。換句話說當前進程通過binder機制進行跨進程調用都是通過IPCThreadState對象來完成的。
2、IPCThreadState也可以理解成/dev/binder設備的封裝,用戶可以不直接通過ioctl來操作binder設備,都通過IPCThreadState對象來代理即可。
我們這裏可以再深入地聊一下,不管是客戶端進程和Service進程都是需要用IPCThreadState來和binder設備通訊的。如果是客戶端進 程則通過服務代理BpBinder對象,調用transact函數,該函數作用就是把客戶端的請求寫入binder設備另一端的Service進程,具體 請參閱IPCThreadState類的transact方法。作爲Service進程,當他完成初始化工作之後,他需要他們需要進入循環狀態等待客戶端 的請求,Service進程調用它的IPCThreadState對象的joinThreadPool方法,開始輪詢binder設備,等待客戶端請求的 到來,後面我們討論Service時候會進一步討論joinThreadPool方法。有興趣的朋友可以先通過查看代碼來了解 joinThreadPool方法。
4、Service代理對象BpBinder
上文關於ProcessState的介紹提到了,客戶端進程創建的Service代理對象其實就是BpBinder對象。
我們首先了解怎樣創建BpBinder對象。
1: BpBinder::BpBinder(int32_t handle)
2: : mHandle(handle)
3: , mAlive(1)
4: , mObitsSent(0)
5: , mObituaries(NULL)
6: {
7: LOGV("Creating BpBinder %p handle %d\n", this, mHandle);
8:
9: extendObjectLifetime(OBJECT_LIFETIME_WEAK);
10: IPCThreadState::self()->incWeakHandle(handle);
11: }
我們可以看出首先是通過IPCThreadState讀寫binder設備增加中相應binder句柄上的Service的引用計數。然後本地保存代理Service的binder句柄mHandle。
客戶進程對Service的請求都通過調用BpBinder的transact方法來完成:
1: status_t BpBinder::transact(
2: uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3: {
4: // Once a binder has died, it will never come back to life.
5: if (mAlive) {
6: status_t status = IPCThreadState::self()->transact(
7: mHandle, code, data, reply, flags);
8: if (status == DEAD_OBJECT) mAlive = 0;
9: return status;
10: }
11:
12: return DEAD_OBJECT;
13: }
在transact方法中,還是調用客戶進程的IPCThreadState對象來完成對相應Service請求。注意transact方法是同步方法,將會掛住客戶進程的當前線程,直到service把請求處理完成,並返回結果。這時客戶進程當前線程的 transact方法返回。
5、Android系統對Binder機制的抽象——IBinder
上面我們講解了Binder機制比較底層的機制,這些機制直接用還是比較麻煩的,比如使用binder設備的ioctl,需要記住很多ioctl的代碼。
Android爲了是Binder機制容易使用,對Binder機制進行了抽象,定義了IBinder接口,該接口在C/C++和Java層都有定義。IBinder定義了一套使用Binder機制使用和實現客戶程序和服務器的通訊協議。可以理解如下定義:
1、向Android註冊的Service也必須是IBinder(繼承擴展IBinder接口)對象。後續文章中我們討論Service的時候我們會介紹到這方面的內容。
2、客戶端得到Service代理對象也必須定義成IBinder(繼承擴展IBinder接口)對象。這也是爲什麼BpBinder就是繼承自IBinder。
3、客戶端發送請求給客戶端,調用接口的Service代理對象IBinder接口的transact方法。
4、Android系統Binder機制將負責把用戶的請求,調用Service對象IBinder接口的onTransact方法。具體實現我們將在以後介紹Service的時候討論。
6、Service Manager代理對象
我們知道ServiceManager是Android Binder機制的大管家。所有需要通過Binder通訊的進程都需要先獲得Service Manager的代理對象才能進行Binder通訊。Service Manager即在C/C++層面提供服務代理,又在Java層面提供服務代理,本文先介紹一下C/C++層面的服務代理,Java層面的服務代理將在後 續文章中介紹。
進程在C/C++層面上面,Android在Android命名空間中定義了一個全局的函數defaultServiceManager(定義在framework/base/libs/binder),通過這個函數可以使進程在C/C++層面獲得Service Manager的代理。我們先看一下該函數的定義:
1: sp<IServiceManager> defaultServiceManager()
2: {
3: if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
4:
5: {
6: AutoMutex _l(gDefaultServiceManagerLock);
7: if (gDefaultServiceManager == NULL) {
8: gDefaultServiceManager = interface_cast<IServiceManager>(
9: ProcessState::self()->getContextObject(NULL));
10: }
11: }
12:
13: return gDefaultServiceManager;
14: }
我們可以看到defaultServiceManager是調用ProcessState對象的getContextObject方法獲得Service Manager的getContextObject方法獲得Service Manager代理對象。我們再看一下getContextObject函數的定義:
1: sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
2: {
3: if (supportsProcesses()) {
4: return getStrongProxyForHandle(0);
5: } else {
6: return getContextObject(String16("default"), caller);
7: }
8: }
我們可以看出其實是調用我們上面描述過的getStrongProxyForHandle方法,並以句柄0爲參數來獲得Service Manager的代理對象。
ProcessState::self()->getContextObject(NULL)返回一個IBinder對象,怎樣把它轉化成一個 IServiceManager的對象呢?這就是模板函數interface_cast<IServiceManager>的作用了。調用的是IServiceManager.asInterface方法。IServiceManager的asInterface方法通過 DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE宏來定義,詳細情況請查看IServiceManager類的定義。IMPLEMENT_META_INTERFACE宏關於asInterface的定義如下:
1: android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
2: const android::sp<android::IBinder>& obj) \
3: { \
4: android::sp<I##INTERFACE> intr; \
5: if (obj != NULL) { \
6: intr = static_cast<I##INTERFACE*>( \
7: obj->queryLocalInterface( \
8: I##INTERFACE::descriptor).get()); \
9: if (intr == NULL) { \
10: intr = new Bp##INTERFACE(obj); \
11: } \
12: } \
13: return intr; \
14: } \
最終asInterface將會用一個IBinder對象創建一個BpServiceManager對象,並且BpServiceManager繼承自 IServiceManager,這樣我們就把IBinder對象轉換成了IServiceManager對象。如果你仔細查看 BpServiceManager的定義,你會發現查詢Service,增加Service等方法其實都是調用底層的IBinder對象來完成的。
當我們在C/C++層面編寫程序使用Binder機制的時候將會調用defaultServiceManager函數來獲得Service Manager,比如:很多Android系統Service都是在C/C++層面實現的,他們就需要向Service Manager註冊其服務,那麼這些服務將調用defaultServiceManager獲得Service Manager代理對象。我們在後續介紹Android系統Service的時候將會詳細介紹。
7、總結
本文中我們介紹了C++層面的Service代理,後續文章我們將介紹Java層面的Service代理。
Android系統的Binder機制之三——服務代理對象(2)
上文《Android系統的Binder機制之二——服務代理對象(1)》我們學習了進程的C/C++層面的服務代理對象BpBinder,和Binder底層處理方式。本文我們將深入分析一下在進程的Java層面服務代理對象的創建和使用。
Android進程的C/C++層面和Java層
Android中程序大部分都是java開發,底層通過JNI調用C/C++的代碼。這樣一個程序就分爲了兩個層面C/C++層面和Java層面。運行狀態下,我們說它們都在一個進程之中,擁有相同的進程屬性(UID,GID等等)。
Binder客戶程序的C/C++層面的對象和原理我們在上文《Android系統的Binder機制之二——服務代理對象(1)》已經學習。下面我們將介紹客戶程序怎樣在Java層面通過JNI調用底層C/C++代碼的創建服務代理。
ServiceManager類型和對象
我在《Android系統的Binder機制之一——ServiceManager》中介紹過,客戶端要想獲得服務代理,首先要向ServiceManager查詢Service。在Java層面也是這樣,所以我們首先分析Java層面ServiceManager類。
我們通過查看ServiceManager的源碼我們發現,ServiceManager類型也是一個Singleton類型。所有的方法都是靜態方法,所有靜態方法都是訪問它的IServiceManager類型的靜態變量sServiceManager,定義如下:
1:privatestatic IServiceManager sServiceManager;
所以可以理解ServiceManager就是IServiceManager對象的一個代理。爲創建和訪問這個變量都是通過ServiceManager的getIServiceManager方法,定義如下:
1:privatestatic IServiceManager getIServiceManager() {
2: if (sServiceManager != null) {
3: return sServiceManager;
4: }
5:
6: // Find the service manager
7: sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
8: return sServiceManager;
9: }
通過上面的代碼,非常清晰的告訴我們ServiceManager類型是一個Singleton類型。現在我們主要研究sServiceManager對象怎樣創建的。如下代碼創建IServiceManager對象:
1: sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
我們首先查看BinderInternal類的getContextObject方法的代碼,發現是Native代 碼(哈哈!有終於到達C/C++層面了,我們已經熟悉了),對應的代碼爲android_util_binder.cpp中的android_os_BinderInternal_getContextObject函數,代碼如下:
1:static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
2: {
3: sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
4: return javaObjectForIBinder(env, b);
5: }
終於看到我們上文《Android系統的Binder機制之二——服務代理對象(1)》介紹過的ProcessState對象了,我們再去查看ProcessState對象的getContextObject方法,代碼如下:
1: sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
2: {
3: if (supportsProcesses()) {
4: return getStrongProxyForHandle(0);
5: } else {
6: return getContextObject(String16("default"), caller);
7: }
8: }
我們看到在當前進程的ProcessState對象其實是調用getStrongProxyForHandle方法來創建binder句柄爲0的服務代理對象——BpBinder對象,我們在《Android系統的Binder機制之一——Service Manager》提到過ServiceManager的binder句柄是一個聞名句柄0。上文《Android系統的Binder機制之二——服務代理對象(1)》已經介紹過ProcessState對象的getStrongProxyForHandle方法,這裏就不多說了。
我們可以看出Java調用C/C++,創建一個服務代理對象BpBinder,在查看BpBinder的定義我們發現繼承自IBinder接口,然後在 android_util_binder.cpp中的方法android_os_BinderInternal_getContextObject中,把 C/C++層面的IBinder對象封裝成Java層面的IBinder對象。具體實現可以查看上文的 android_os_BinderInternal_getContextObject方法。
至此我們已經清楚BinderInternal.getContextObject(),返回的是ServiceManager的服務代理對象—— BpBinder對象。那麼ServiceManagerNative類的靜態方法asInterface做什麼用呢?我們還是通過代碼來分析,在 ServiceManagerNative.java中,asInterface的代碼如下:
1:staticpublic IServiceManager asInterface(IBinder obj)
2: {
3: if (obj == null) {
4: return null;
5: }
6: IServiceManager in =
7: (IServiceManager)obj.queryLocalInterface(descriptor);
8: if (in != null) {
9: return in;
10: }
11:
12: returnnew ServiceManagerProxy(obj);
13: }
將會用IBinder對象創建一個ServiceManagerProxy對象,ServiceManagerProxy類型繼承了IServiceManager接口,所以asInterface方法最終目的是用一個 IBinder對象創建一個IServiceManager對象。
爲什麼要用IBinder對象創建一個IServiceManager對象呢?通過ServiceManager的代理對象——IBinder對象(BpBinder對象)應該可以直接請求ServiceManager中的服務了啊?我們在前文《Android系統的Binder機制之二——服務代理對象(1)》簡單介紹了一下IBinder類型,客戶端通過transact方法向Service發送請求,客戶端的onTransact被調用處理客戶端的請求,請求通過請求代碼來區分。具體請參考Android手冊。如果客戶端直接用調用ServiceManager的代理對象的IBinder接口,那麼客戶端必須要記住所有請求的請求代碼,對客戶端來說不太友好。所以在ServiceManagerNative類中就把ServiceManager的代理對象——IBinder對象(BpBinder對象)封裝成 ServiceManagerProxy對象,暴露給客戶程序一個IServiceManager接口,這樣IServiceManager對象將會代理 客戶程序發往ServiceManager的代理對象的請求。並且是調用IServiceManager對象的方法來給ServiceManager發送請求,這樣對客戶程序來講和本地的函數調用是一致的,接口非常友好。比如我們客戶程序需要調用IServiceManager的getService方法 來查詢一個Service,ServiceManagerProxy實現代碼如下:
1:public IBinder getService(String name) throws RemoteException {
2: Parcel data = Parcel.obtain();
3: Parcel reply = Parcel.obtain();
4: data.writeInterfaceToken(IServiceManager.descriptor);
5: data.writeString(name);
6: mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
7: IBinder binder = reply.readStrongBinder();
8: reply.recycle();
9: data.recycle();
10: return binder;
11: }
我們可以非常清晰的看到ServiceManagerProxy對象將客戶程序的請求轉換成對ServiceManager代理對象——IBinder對 象(BpBinder對象)的調用。後文我們將會詳細介紹怎樣通過IServiceManager查詢和獲得一個系統Service代理對象。
到這裏我們已經分析完了,ServiceManager的Singleton對象——sServiceManager的創建。如果有不清楚的地方請查看代碼。
查詢和獲得Service代理對象
客戶程序通過調用ServiceManager類型的靜態方法asInterface獲得了IServiceManager對象,但是最終目的一般都是要查詢和獲得其他的Service,一般都是要調用IServiceManager的getService方法,向ServiceManager獲得其他的Service。比如:
1: IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
上面的代碼中就是調用ServiceManager的靜態方法獲得網絡管理服務代理對象。我們順藤摸瓜,看看系統是怎樣生成這個Service代理對象的。這裏只是簡單說明一下調用順序,詳細過程請查看源碼。
1、調用ServiceManager.java中的ServiceManager靜態方法getService。
2、調用ServiceManagerNative.java中的ServiceManagerProxy方法getService。代碼如下:
1:public IBinder getService(String name) throws RemoteException {
2: Parcel data = Parcel.obtain();
3: Parcel reply = Parcel.obtain();
4: data.writeInterfaceToken(IServiceManager.descriptor);
5: data.writeString(name);
6: mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
7: IBinder binder = reply.readStrongBinder();
8: reply.recycle();
9: data.recycle();
10: return binder;
11: }
請注意IBinder的transact方法是同步方法(本例中ServiceManager處理完成請求之後纔會返回),我們可以看出調用transact之後,調用reply.readStrongBinder()來讀取IBinder對象。
3、查看Parcel.java中的readStrongBinder方法,發現是Native方法,將會調用到C/C++的代碼。
4、查看android_util_binder.cpp中的android_os_Parcel_readStrongBinder函數。代碼如下:
1:static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
2: {
3: Parcel* parcel = parcelForJavaObject(env, clazz);
4: if (parcel != NULL) {
5: return javaObjectForIBinder(env, parcel->readStrongBinder());
6: }
7: return NULL;
8: }
parcel->readStrongBinder()將會產生一個IBinder對象。
5、查看Parcel.cpp中,Parcel的方法readStrongBinder。代碼如下:
1: sp<IBinder> Parcel::readStrongBinder() const
2: {
3: sp<IBinder> val;
4: unflatten_binder(ProcessState::self(), *this, &val);
5: return val;
6: }
6、查看Parcel.cpp中,Parcel的方法unflatten_binder。代碼如下:
1: status_t unflatten_binder(const sp<ProcessState>& proc,
2: const Parcel& in, sp<IBinder>* out)
3: {
4: const flat_binder_object* flat = in.readObject(false);
5:
6: if (flat) {
7: switch (flat->type) {
8: case BINDER_TYPE_BINDER:
9: *out = static_cast<IBinder*>(flat->cookie);
10: return finish_unflatten_binder(NULL, *flat, in);
11: case BINDER_TYPE_HANDLE:
12: *out = proc->getStrongProxyForHandle(flat->handle);
13: return finish_unflatten_binder(
14: static_cast<BpBinder*>(out->get()), *flat, in);
15: }
16: }
17: return BAD_TYPE;
18: }
終於看到調用我們的老朋友ProcessState對象的getStrongProxyForHandle方法了,這樣將會創建一個BpBinder對象,然後該BpBinder對象將會被轉換成IBinder對象返回給Java層。
7、Java層爲了用使用Service方便,可以把Service代理對象——BpBinder對象(IBinder對象)封裝成一個對客戶程序友好的代理對象,就如前面ServiceManagerProxy所示那樣。
8、用戶程序就可以通過該代理對象訪問相應Service了。
通過所述,我們瞭解了Service代理對象在Java層的創建和使用。Android系統的Binder機制博大精深,我在本文中很多方面都是蜻蜓點水,如果想深入學習請參閱Android的源碼。
參考資料:
IPC框架分析 Binder,Service,Service manager
Android系統的Binder機制之四——系統Service
前面我們已經介紹了Android Binder機制的ServiceManager,Service對象代理1,Service對象代理2。本文將介紹一下Android機制的另外一個重要部分——系統Service。
1、系統Service實例——Media server
首先我們先看一下Android一個實例Media Service,代碼位於framework/base/media/mediaserver/main_mediaserver.cpp文件:
1:// System headers required for setgroups, etc.
2:#include <sys/types.h>
3:#include <unistd.h>
4:#include <grp.h>
5:
6:#include <binder/IPCThreadState.h>
7:#include <binder/ProcessState.h>
8:#include <binder/IServiceManager.h>
9:#include <utils/Log.h>
10:
11:#include <AudioFlinger.h>
12:#include <CameraService.h>
13:#include <MediaPlayerService.h>
14:#include <AudioPolicyService.h>
15:#include <private/android_filesystem_config.h>
16:
17:usingnamespace android;
18:
19:int main(int argc, char** argv)
20: {
21: sp<ProcessState> proc(ProcessState::self());
22: sp<IServiceManager> sm = defaultServiceManager();
23: LOGI("ServiceManager: %p", sm.get());
24: AudioFlinger::instantiate();
25: MediaPlayerService::instantiate();
26: CameraService::instantiate();
27: AudioPolicyService::instantiate();
28: ProcessState::self()->startThreadPool();
29: IPCThreadState::self()->joinThreadPool();
30: }
我們發現Media Server是一個進程,並且該程序的實現表面上也挺簡單,其實並不簡單,讓我們慢慢分析一下Media Server。
1、第一句創建創建一個ProcessState的引用,但是這個對象後面並沒有被調用到,那麼爲什麼創建呢?請回想一下我在博文《Android系統的Binder機制之二——服務代理對象(1)》中介紹ProcessState對象時提到:如果一個進程要使用Binder機制,那麼他的進程中必須要創建一個ProcessState對象來負責管理Service的代理對象。
2、第二句調用defaultServiceManager獲得一個Service Manager代理對象,我在《Android系統的Binder機制之二——服務代理對象(1)》已經對此有了詳細的介紹這裏就不贅述了。
3、後面幾行都是創建具體的Service,我們展開之後發現都是一些調用Service Manager的addService進行註冊的函數,以AudioFlinger爲例,instantiate代碼如下:
1:void AudioFlinger::instantiate() {
2: defaultServiceManager()->addService(
3: String16("media.audio_flinger"), new AudioFlinger());
4: }
4、最後調用ProcessState的startThreadPool方法和IPCThreadState的joinThreadPool使Media Server進入等待請求的循環當中。
我們可以看出一個進程中可以有多個Service,Media Server這個進程中就存在AudioFlinger,MediaPlayerService,CameraService,AudioPolicyService四個Service。
2、系統Service的基礎——BBinder
我們仔細查看一下MediaServer中定義的四個Service我們將會發現他們都是繼承自BBinder,而BBinder又繼承自IBinder接口,詳細情況請自行查看他們的代碼。每個Service都改寫了BBinder的onTransact虛函數,當用戶發送請求到達Service時,框架將會調用Service的 onTransact函數,後面我們將會詳細的介紹這個機制。
3、Service註冊
每個Service都需要向“大管家”Service Manager進行註冊,調用Service Manager的addService方法註冊。這樣Service Manager將會運行客戶端查詢和獲取該Service(代理對象),然後客戶端就可以通過該Service的代理對象請求該Service的服務。
4、Service進入等待請求的循環
每個Service必須要進入死循環,等待客戶端請求的到達,本例中最後兩句就是使Service進行等待請求的循環之中。ProcessState的 startThreadPool方法最終調用的也是IPCThreadState的joinThreadPool方法,具體請查看代碼。 IPCThreadState的joinThreadPool方法的代碼如下:
1:void IPCThreadState::joinThreadPool(bool isMain)
2: {
3: ......
4: do {
5: int32_t cmd;
6:
7: ......
8:
9: // now get the next command to be processed, waiting if necessary
10: result = talkWithDriver();
11: if (result >= NO_ERROR) {
12: ......
13:
14: result = executeCommand(cmd);
15: }
16:
17: ......
18: } while (result != -ECONNREFUSED && result != -EBADF);
19:
20: ......
21: }
Service在IPCThreadState的joinThreadPool方法中,調用talkWithDriver方法和Binder驅動進行交互,讀取客戶端的請求。當客戶端請求到達之後調用executeCommand方法進行處理。
我們再看一下Service怎樣處理客戶端的請求?我們們查看一下executeCommand方法的源碼:
1: status_t IPCThreadState::executeCommand(int32_t cmd)
2: {
3: BBinder* obj;
4: RefBase::weakref_type* refs;
5: status_t result = NO_ERROR;
6:
7: switch (cmd) {
8: ......
9: case BR_TRANSACTION:
10: {
11: ......
12: if (tr.target.ptr) {
13: sp<BBinder> b((BBinder*)tr.cookie);
14: const status_t error = b->transact(tr.code, buffer, &reply, 0);
15: if (error < NO_ERROR) reply.setError(error);
16:
17: }
18: ......
19: }
20: break;
21:
22: ......
23: }
24:
25: if (result != NO_ERROR) {
26: mLastError = result;
27: }
28:
29: return result;
30: }
可以看到IPCThreadState將會直接調用BBinder的transact方法來處理客戶端請求,我們再看一下BBinder的transact方法:
1: status_t BBinder::transact(
2: uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
3: {
4: data.setDataPosition(0);
5:
6: status_t err = NO_ERROR;
7: switch (code) {
8: case PING_TRANSACTION:
9: reply->writeInt32(pingBinder());
10: break;
11: default:
12: err = onTransact(code, data, reply, flags);
13: break;
14: }
15:
16: if (reply != NULL) {
17: reply->setDataPosition(0);
18: }
19:
20: return err;
21: }
我們發現他將會叫用自己的虛函數onTransact。我們前面提到所有的Service都集成自BBinder,並且都改寫了onTransact虛函數。那麼IPCThreadState將會調用Service定義onTransact方法來響應客戶請求。
5、結論
本文簡單介紹了一下系統Service的原理,臺灣的高煥堂先生有一篇文章,手把手教怎樣實現一個系統Service,你可以在我的博文《(轉)高煥堂——Android框架底層結構知多少?》中找到。