Android-Binder系统APP实现

来源:互联网 发布:乾隆 贡献 知乎 编辑:程序博客网 时间:2024/06/14 23:04

Client(APP):

1、首先打开Binder驱动

2、获取服务(server的Handle)

3、构造Binder_io结构体

4、调用Binder_call(); 

5、分析返回的Binder_io的结构体,取出返回值

Server怎么写:

1、open_Binder

2、注册服务

3、读驱动ioctl命令

4、解析数据过来的是  struct binder_write_read bwr;转化成Binder_io然后取出参数调用函数将返回值封装在reply中.

test_server.c这里在bctest.c文件的基础上修改自己的server程序。

按照上述4个步骤编写APP,假设服务端提供的服务是Hello, Hello to。两个函数。

 ret = svcmgr_publish(bs, svcmgr, "hello", 123);//////////////////////向SM注册服务名字为hello
    if (!ret) {
        fprintf(stderr, "failed to svcmgr_publish service\n");
        return -1;
    }

    binder_loop(bs, hello_service_handler);///////循环读驱动用ioctl命令

     在循环里

        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);

先看这个func是int hello_service_handler(struct binder_state *bs,struct binder_transaction_data *txn,struct binder_io *msg,struct binder_io *reply)

根据service_handler函数写出的函数

    switch(txn->code) {
    case HELLO_SVR_CMD_SAYHELLO :
        sayhello();
    case HELLO_SVR_CMD_SAYHELLOTO :
        s = bio_get_string16(msg, &len);
        for(i = 0; i<len; i++)
            name[i] = s[i];
        name[i] = '\0';
        i = sayhelloto(name);
        bio_put_uint32(reply, i);

switch  case结构两个命令。一个没有参数一个有参数。

/////////////////////////////

void sayhello(void)
{
    static int cnt = 0;
    fprintf(stderr,"say hello : %d\n", cnt++);
}
int  sayhelloto (char &name)
{
    static int cnt = 0;
    fprintf(stderr,"say hello to : %s, %d\n",name, cnt++);    
    return cnt;
}///////////////测试函数

//////////////////////////////////////

再看这个解析函数做了什么

    先处理数据然后调用了这个处理函数 res = func(bs, txn, &msg, &reply);

    struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;txn是传输过来的数据里面含有Handle,code等重要信息。然后就是i上面的处理函数。


OK

接下来是客户端一端获取服务的程序

bs = binder_open(128*1024);/////////////////打开驱动
    if (!bs) {
        fprintf(stderr, "failed to open binder driver\n");
        return -1;
    }
    g_bs = bs;
    handle = svcmgr_lookup(g_bs, svcmgr, "hello");////////////////找到服务返回handle

    if (argc == 2)
        sayhello();
    else if (argc == 3){
        ret = sayhelloto(argv[2]);
        fprintf(stderr, "ret = %d\n", ret);
    }  //////////////////////使用如果 ./test_client name name<>    或   ./test_client name

////////////////实现两个函数///////////////////////////

void sayhello(void)
{
    unsigned iodata[512/4];
    struct binder_io msg, reply;

    bio_init(&msg, iodata, sizeof(iodata), 4);/////////////////构造msg
    bio_put_uint32(&msg, 0);                        //////////////////////////开头必须是0        DNS嘛

    if(binder_call(g_bs, &msg, &reply, g_handle, HELLO_SVR_CMD_SAYHELLO))////////////调binder_call
        return 0;
    binder_done(bs, &msg, &reply);////////////结束
}
int sayhelloto(char *name)
{
    unsigned iodata[512/4];
    struct binder_io msg, reply;
    int ret;
    bio_init(&msg, iodata, sizeof(iodata), 4);
    bio_put_uint32(&msg, 0);
    bio_put_string16_x(&msg, name);////////////////参数

    if(binder_call(g_bs, &msg, &reply, g_handle, HELLO_SVR_CMD_SAYHELLO_TO))
        return 0;

    ret = bio_get_uint32(&reply);/////////////////收到回复
    binder_done(bs, &msg, &reply);
    return ret;

}

//////////////////完毕//////////////////////

接下来编译运行