我們知道ActivityManager是運行在system_service進程里的,但是最近看代碼發(fā)現(xiàn)在這個進程的其他服務線程里為了獲取AMS調用: ActivityManagerService am = (ActivityManagerService)ServiceManager.getService("activity"); 驗證了下,返回的am確實是AMS的實例,沒問題 我們一般用ServiceManager.getService在其他進程中獲取AMS服務,返回的一個是遠端binder代理, 如果用在同一進程中會怎樣? 為了解釋這個問題,首先要復習下binder通信知識
Binder在內核中兩種形式: Binder實體(binder_node), Binder引用(binder_ref)
兩個典型流程 1. service在ServiceManager注冊: 然后Client可以通過這個app端的binder引用與AMS進行通信。
回到開始問題: 上面的步驟是在Client端請求AMS服務,這里Client與AMS在兩個不同進程,
static void binder_transaction(struct binder_proc *proc, struct binder_thread *thread, struct binder_transaction_data *tr, int reply) { switch (fp->type) { ... case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle, fp->type == BINDER_TYPE_HANDLE); if (ref == NULL) { binder_user_error("%d:%d got transaction with invalid handle, %d\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_binder_get_ref_failed; } if (ref->node->proc == target_proc) { if (fp->type == BINDER_TYPE_HANDLE) fp->type = BINDER_TYPE_BINDER; else fp->type = BINDER_TYPE_WEAK_BINDER; fp->binder = ref->node->ptr; fp->cookie = ref->node->cookie; binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL); trace_binder_transaction_ref_to_node(t, ref); binder_debug(BINDER_DEBUG_TRANSACTION, " ref %d desc %d -> node %d u%016llx\n", ref->debug_id, ref->desc, ref->node->debug_id, (u64)ref->node->ptr); } else { struct binder_ref *new_ref; new_ref = binder_get_ref_for_node(target_proc, ref->node); if (new_ref == NULL) { return_error = BR_FAILED_REPLY; goto err_binder_get_ref_for_node_failed; } fp->binder = 0; fp->handle = new_ref->desc; fp->cookie = 0; binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL); trace_binder_transaction_ref_to_ref(t, ref, new_ref); binder_debug(BINDER_DEBUG_TRANSACTION, " ref %d desc %d -> ref %d desc %d (node %d)\n", ref->debug_id, ref->desc, new_ref->debug_id, new_ref->desc, ref->node->debug_id); } } break; ... } }
看紅色代碼 所以通過SystemManager.getService("name")在同一進程獲取服務,會直接返回這個服務實例的引用,這是binder驅動支持的。 當然在一個進程里有更直接的辦法來獲取,但是在某些特殊情況用這種辦法也可以,只是效率稍低,因為經(jīng)歷了一次與serviceManager的ipc。 |
|