ServiceMananger是android中比較重要的一個進程,它是在init進程啟動之後啟動,從名字上就可以看出來它是用來管理系統中的service。比如:InputMethodService、ActivityManagerService等。在ServiceManager中有兩個比較重要的方法:add_service、check_service。系統的service需要通過add_service把自己的資訊註冊到ServiceManager中,當需要使用時,通過check_service檢查該service是否存在。
主函數
從它的主函數代碼開始:
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函數中可以看出,它主要做了三件事情:
- 開啟/dev/binder裝置,並在記憶體中映射128K的空間。
- 通知Binder裝置,把自己變成context_manager
- 進入迴圈,不停的去讀Binder裝置,看是否有對service的請求,如果有的話,就去調用svcmgr_handler函數回調處理請求。
服務註冊
再來看看ServiceManager中是怎麼樣去註冊服務的。先來看先,當有對service的請求時,調用的回呼函數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;// LOGI("target=%p code=%d pid=%d uid=%d\n",// txn->target, txn->code, txn->sender_pid, txn->sender_euid); if (txn->target != svcmgr_handle) return -1; // Equivalent to Parcel::enforceInterface(), reading the RPC // header with the strict mode policy mask and the interface name. // Note that we ignore the strict_policy and don't propagate it // further (since we do no outbound RPCs anyway). 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;}
在該回呼函數中會判斷Service有什麼需要,如果是請求註冊service,那麼久執行:
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;
我們再來看看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,如果沒有許可權就直接返回,不能註冊。
if (!svc_can_register(uid, s)) { LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n", str8(s), ptr, uid); return -1; }
然後會去檢查該service是否已經註冊過了,如果已經註冊過,那麼就不能再註冊了:
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; }
再判斷記憶體是否足夠:
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; }
如果都沒什麼問題,會註冊該service,加入到svcList中來。注意,在ServiceManager中維護service資訊的地方就是svclist。裡面存了service的name和handler。
服務擷取
通過以上幾個步驟,service就算註冊成功了。那麼當要獲得該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;
如果是擷取service,那麼執行SVC_MGR_CHECK_SERVICE,並把返回的資料寫入reply,返回給用戶端。
do_find_service函數中主要執行service的尋找。
void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len){ struct svcinfo *si; si = find_svc(s, len);// LOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0); if (si && si->ptr) { return si->ptr; } else { return 0; }}
這樣在ServiceManager中就完成了服務的註冊和尋找。來看下ServiceManager的功能圖: