轉(zhuǎn)載處:http://blog.csdn.net/xieqibao/article/details/6585143
ServiceMananger是android中比較重要的一個(gè)進(jìn)程,它是在init進(jìn)程啟動(dòng)之后啟動(dòng),從名字上就可以看出來(lái)它是用來(lái)管理系統(tǒng)中的service。比如:InputMethodService、ActivityManagerService等。在ServiceManager中有兩個(gè)比較重要的方法:add_service、check_service。系統(tǒng)的service需要通過(guò)add_service把自己的信息注冊(cè)到ServiceManager中,當(dāng)需要使用時(shí),通過(guò)check_service檢查該service是否存在。
主函數(shù)
從它的主函數(shù)代碼開(kāi)始:
- 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;
- }
從main函數(shù)中可以看出,它主要做了三件事情:
- 打開(kāi)/dev/binder設(shè)備,并在內(nèi)存中映射128K的空間。
- 通知Binder設(shè)備,把自己變成context_manager
- 進(jìn)入循環(huán),不停的去讀Binder設(shè)備,看是否有對(duì)service的請(qǐng)求,如果有的話,就去調(diào)用svcmgr_handler函數(shù)回調(diào)處理請(qǐng)求。
服務(wù)注冊(cè)
再來(lái)看看ServiceManager中是怎么樣去注冊(cè)服務(wù)的。先來(lái)看先,當(dāng)有對(duì)service的請(qǐng)求時(shí),調(diào)用的回調(diào)函數(shù)svcmgr_handler:
- int svcmgr_handler(struct binder_state *bs,
- struct binder_txn *txn,
- struct binder_io *msg,
- struct binder_io *reply)
- {
- struct svcinfo *si;
- uint16_t *s;
- unsigned len;
- void *ptr;
- uint32_t strict_policy;
-
-
- if (txn->target != svcmgr_handle)
- return -1;
-
-
-
-
- strict_policy = bio_get_uint32(msg);
- s = bio_get_string16(msg, &len);
- if ((len != (sizeof(svcmgr_id) / 2)) ||
- memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
- fprintf(stderr,"invalid id %s\n", str8(s));
- return -1;
- }
- switch(txn->code) {
- 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;
- 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;
- case SVC_MGR_LIST_SERVICES: {
- unsigned n = bio_get_uint32(msg);
- si = svclist;
- while ((n-- > 0) && si)
- si = si->next;
- if (si) {
- bio_put_string16(reply, si->name);
- return 0;
- }
- return -1;
- }
- default:
- LOGE("unknown code %d\n", txn->code);
- return -1;
- }
- bio_put_uint32(reply, 0);
- return 0;
- }
在該回調(diào)函數(shù)中會(huì)判斷Service有什么需要,如果是請(qǐng)求注冊(cè)service,那么久執(zhí)行:
- 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;
我們?cè)賮?lái)看看do_add_service中做了什么事情:
- int do_add_service(struct binder_state *bs,
- uint16_t *s, unsigned len,
- void *ptr, unsigned uid)
- {
- struct svcinfo *si;
-
- 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;
- }
在該函數(shù)中,首先會(huì)去檢查是否有權(quán)限注冊(cè)service,如果沒(méi)有權(quán)限就直接返回,不能注冊(cè)。
- if (!svc_can_register(uid, s)) {
- LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
- str8(s), ptr, uid);
- return -1;
- }
然后會(huì)去檢查該service是否已經(jīng)注冊(cè)過(guò)了,如果已經(jīng)注冊(cè)過(guò),那么就不能再注冊(cè)了:
- 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;
- }
再判斷內(nèi)存是否足夠:
- 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;
- }
如果都沒(méi)什么問(wèn)題,會(huì)注冊(cè)該service,加入到svcList中來(lái)。注意,在ServiceManager中維護(hù)service信息的地方就是svclist。里面存了service的name和handler。
服務(wù)獲取
通過(guò)以上幾個(gè)步驟,service就算注冊(cè)成功了。那么當(dāng)要獲得該service的時(shí)候又是怎么去處理的。還是來(lái)看下回調(diào)函數(shù)中的判斷:
- 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;
如果是獲取service,那么執(zhí)行SVC_MGR_CHECK_SERVICE,并把返回的數(shù)據(jù)寫(xiě)入reply,返回給客戶端。
do_find_service函數(shù)中主要執(zhí)行service的查找。
- void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len)
- {
- struct svcinfo *si;
- si = find_svc(s, len);
-
- if (si && si->ptr) {
- return si->ptr;
- } else {
- return 0;
- }
- }
這樣在ServiceManager中就完成了服務(wù)的注冊(cè)和查找。來(lái)看下ServiceManager的功能圖: