日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

system

 一楠tech 2019-09-11

我們知道ActivityManager是運行在system_service進程里的,但是最近看代碼發(fā)現(xiàn)在這個進程的其他服務線程里為了獲取AMS調用:

ActivityManagerService am = (ActivityManagerService)ServiceManager.getService("activity");

驗證了下,返回的am確實是AMS的實例,沒問題

我們一般用ServiceManager.getService在其他進程中獲取AMS服務,返回的一個是遠端binder代理,

如果用在同一進程中會怎樣? 為了解釋這個問題,首先要復習下binder通信知識


Binder IPC模型

 

Binder在內核中兩種形式: Binder實體(binder_node), Binder引用(binder_ref)
binder_node:
{
  binder_proc* proc; //service進程信息
  void__user* ptr; //service實例指針
}
binder_ref:
{
  binder_proc* proc; //service進程信息
  binder_node* node; //指向Binder實體
  unit32_t desc; //service handle值,唯一標識一個service
}

 

兩個典型流程

1. service在ServiceManager注冊:
  在內核創(chuàng)建一個binder實體(橙色矩形),一個binder引用(藍色六邊形),
  在ServiceManager里用map保存這個service的名字和binder引用(藍色曲線四邊形)。
2. Client通過ServiceManager getService("activity"):
  Client首先與ServiceManager進程通信
  Client端先構造一個handle為0的binder引用(灰色曲線四邊形),
  通過這個引用向內核發(fā)送數(shù)據(jù)(包含servcie的名字"activity"),
  在內核空間創(chuàng)建一個ServiceManager的biner引用(灰色六邊形),
  找到ServiceManager的binder實體(灰色矩形),
  然后喚醒ServiceManager進程,
  通過binder實體中的ServiceManager實例,調用它的getService方法,
  ServiceManager通過名字"activity"找到ActivityManagerService服務的binder引用,把數(shù)據(jù)寫回內核
  在內核為Client進程創(chuàng)建一個ActivityManagerService binder引用(藍色六邊形)
  返回包含binder的handle值的數(shù)據(jù)給Client,在Client創(chuàng)建一個app端的binder引用(藍色曲線四邊形)

  然后Client可以通過這個app端的binder引用與AMS進行通信。
  在app-service通信中,binder內核驅動擔任dns的功能,也就是通過binder引用,找對應服務的binder實體

 

回到開始問題:

上面的步驟是在Client端請求AMS服務,這里Client與AMS在兩個不同進程,
而如果在同一進程,AMS運行在system_server進程中,如果其他服務線程通過SystemManager.getService("activity")請求AMS服務,
那么這個接口將直接返回 ActivityManagerService實例的引用。
原因主要是在case 2步驟中藍色部分,binder驅動會進行檢查:

 

復制代碼
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;
...
}
}
復制代碼

 

看紅色代碼
首先判斷ref->node->proc == target_proc,即判斷注冊的AMS進程和要獲取AMS的進程是否是同一個,
如果是,則改寫fp->type為BINDER_TYPE_BINDER,設fp->binder = ref->node->ptr;
后續(xù)把AMS的binder實體中的實例引用返回給請求者,

所以通過SystemManager.getService("name")在同一進程獲取服務,會直接返回這個服務實例的引用,這是binder驅動支持的。 當然在一個進程里有更直接的辦法來獲取,但是在某些特殊情況用這種辦法也可以,只是效率稍低,因為經(jīng)歷了一次與serviceManager的ipc。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多