Binder系列-service_manager.c

1. service_manager的任务

  • open 驱动
  • 告诉驱动,它是“servicemanager”
  • 在一个循环里
        从驱动读取数据
        解析数据
        调用,根据code执行注册服务或者获取服务

(图来自韦老师的视频)

2.代码流程

2.1.open驱动
//frameworks\native\cmds\servicemanager\service_manager.c

int main(int argc, char **argv)
{
    struct binder_state *bs;

    bs = binder_open(128*1024); //第一步打开驱动
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }

    //其他代码省略

    return 0;
}
 2.2.告诉驱动,它是“servicemanager”

binder_become_context_manager

//frameworks\native\cmds\servicemanager\service_manager.c

int main(int argc, char **argv)
{
    struct binder_state *bs;

    bs = binder_open(128*1024); //第一步打开驱动
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }

    if (binder_become_context_manager(bs)) { //第二步告诉驱动,它是ServiceManager
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

   //其他代码省略

    return 0;
}

 

//frameworks\native\cmds\servicemanager\binder.c

int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
2.3.循环binder_loop
//frameworks\native\cmds\servicemanager\service_manager.c

int main(int argc, char **argv)
{
    struct binder_state *bs;

    bs = binder_open(128*1024); //打开驱动
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }

    if (binder_become_context_manager(bs)) { //告诉驱动,它是ServiceManager
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    //省略掉部分代码

    binder_loop(bs, svcmgr_handler); //循环,读驱动获取数据,解析数据,调用注册服务或者获取服务

    return 0;
}
//frameworks\native\cmds\servicemanager\binder.c

void binder_loop(struct binder_state *bs, binder_handler func)
{
    //省略部分代码

    for (;;) {//循环
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); //读数据

        if (res < 0) {
            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
            break;
        }

        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);  //解析数据
        if (res == 0) {
            ALOGE("binder_loop: unexpected reply?!\n");
            break;
        }
        if (res < 0) {
            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
            break;
        }
    }
}
2.3.1.解析binder_parse
//frameworks\native\cmds\servicemanager\binder.c

int binder_parse(struct binder_state *bs, struct binder_io *bio,
                 uintptr_t ptr, size_t size, binder_handler func)
{
    int r = 1;
    uintptr_t end = ptr + (uintptr_t) size;

    while (ptr < end) {
        uint32_t cmd = *(uint32_t *) ptr;
        ptr += sizeof(uint32_t);
#if TRACE
        fprintf(stderr,"%s:\n", cmd_name(cmd));
#endif
        switch(cmd) {
        ......
        case BR_TRANSACTION: {
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
            if ((end - ptr) < sizeof(*txn)) {
                ALOGE("parse: txn too small!\n");
                return -1;
            }
            binder_dump_txn(txn);
            if (func) {
                unsigned rdata[256/4];
                struct binder_io msg;
                struct binder_io reply;
                int res;

                bio_init(&reply, rdata, sizeof(rdata), 4);
                bio_init_from_txn(&msg, txn);
                res = func(bs, txn, &msg, &reply); //处理数据
                binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); //有必要的话,返回一些信息
            }
            ptr += sizeof(*txn);
            break;
        }
        ......
        default:
            ALOGE("parse: OOPS %d\n", cmd);
            return -1;
        }
    }

    return r;
}
2.3.2.处理svcmgr_handler
//frameworks\native\cmds\servicemanager\service_manager.c

int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
    //省略部分代码

    switch(txn->code) {
    case SVC_MGR_GET_SERVICE: //获取服务
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid); //获取服务
        if (!handle)
            break;
        bio_put_ref(reply, handle);
        return 0;

    case SVC_MGR_ADD_SERVICE: //注册服务
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = bio_get_ref(msg);
        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
        if (do_add_service(bs, s, len, handle, txn->sender_euid,
            allow_isolated, txn->sender_pid))
            return -1;
        break;

    case SVC_MGR_LIST_SERVICES: {
        uint32_t n = bio_get_uint32(msg);

        if (!svc_can_list(txn->sender_pid)) {
            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
                    txn->sender_euid);
            return -1;
        }
        si = svclist;
        while ((n-- > 0) && si)
            si = si->next;
        if (si) {
            bio_put_string16(reply, si->name);
            return 0;
        }
        return -1;
    }
    default:
        ALOGE("unknown code %d\n", txn->code);
        return -1;
    }

    bio_put_uint32(reply, 0);
    return 0;
}