Android-Binder是如何启动和获取service_manager服务

image.png

一、启动service_manager服务

ServiceManager也是一个服务,其handle==0。
ServiceManager其实就是用来获取AMS、PMS等服务的Binder对象,然后就可以通过AMS等服务的IBinder对象与对应的AMS进行跨进程通信。AMS等服务在启动的时候就会把其IBinder对象注册到ServiceManager中,然后客户端找到ServiceManager,然后通过ServiceManager找到AMS的IBinder返回给客户端,然后客户端就可以通过该AMS的IBinder与AMS进行跨进程通信。
就是在system/core/rootdir/init.rc中,有
service servicemanager /system/bin/servicemanager这样的命令,执行这个命令之后,就会进行native/cmds/servicemanager/service_manager.c中的main方法

service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm

1.native/cmds/servicemanager/service_manager.c中的main方法

这里完成service_manager(SM)的注册:主要分三步(这是流程)

  • (1)打开binder驱动,将SM与binder驱动进行内存映射,SM内存大小与128KB
  • (2)设置SM为大管家(设置为守护进程)--- SM作用:为了管理系统服务
  • 创建binder_node结构体对象
  • 将binder_node添加到proc->nodes中
  • 创建work和todo队列,保存客户端和服务端需要处理的消息
  • (3)直接BC_ENTER_LOOPER命令
  • 向thread->looper写入状态为ENTER
  • 读取数据,修改thread->looper状态,并且调用ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));使SM进入阻塞等待状态
int main(int argc, char **argv)
{
    struct binder_state *bs;
    // 这个binder_open是native层的binder_open,而不是驱动层的binder_open
    // 这里其实就是调用了native/cmds/servicemanager/binder.c的binder_open方法
    // 在native层binder.c的binder_open方法中会调用open方法,这个open方法就是调用了kernel层binder.c的binder_open方法
    // 然后在native层binder.c的binder_open方法中还会调用mmap方法,这个mmap方法就是调用了kernel层binder.c的binder_mmap方法
    // sm的内存大小是128K
    // 这里主要就是做两件事:1.打开驱动;2.映射SM和Binder驱动的内存地址
    bs = binder_open(128*1024);
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }
    // 把service_manager设置为大管家(大管家就是为了管理系统服务的,其实就是守护进程)
    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    selinux_enabled = is_selinux_enabled();
    sehandle = selinux_android_service_context_handle();
    selinux_status_open(true);

    if (selinux_enabled > 0) {
        if (sehandle == NULL) {
            ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
            abort();
        }

        if (getcon(&service_manager_context) != 0) {
            ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
            abort();
        }
    }

    union selinux_callback cb;
    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);
    cb.func_log = selinux_log_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    // 进入无限循环。不断监听有没有人访问ServiceManager
    // 轮询处理数据
    binder_loop(bs, svcmgr_handler);

    return 0;
}

2.native/cmds/servicemanager/binder.c#binder_open

在native/cmds/servicemanager/service_manager.c中的main方法中调用了binder_open,进入该方法。

struct binder_state *binder_open(size_t mapsize)
{
    struct binder_state *bs;
    struct binder_version vers;

    bs = malloc(sizeof(*bs));
    if (!bs) {
        errno = ENOMEM;
        return NULL;
    }

    // 调用驱动,这里开启的是binder驱动。
    // 这里调用open,实际上就是根据native与kernel层的方法关系,调用到了驱动层的binder.c的binder_open方法
    bs->fd = open("/dev/binder", O_RDWR);
    if (bs->fd < 0) {
        fprintf(stderr,"binder: cannot open device (%s)\n",
                strerror(errno));
        goto fail_open;
    }

    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
        fprintf(stderr,
                "binder: kernel driver version (%d) differs from user space version (%d)\n",
                vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
        goto fail_open;
    }

    bs->mapsize = mapsize;
    // 这里就是把SM的虚拟内存和Binder驱动的虚拟内存做地址映射
    // 这里调用mmap,实际上就是根据native与kernel层的方法关系,调用到了驱动层的binder.c的binder_mmap方法
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    if (bs->mapped == MAP_FAILED) {
        fprintf(stderr,"binder: cannot map device (%s)\n",
                strerror(errno));
        goto fail_map;
    }

    return bs;

fail_map:
    close(bs->fd);
fail_open:
    free(bs);
    return NULL;
}

3.native/cmds/servicemanager/binder.c#binder_become_context_manager

在native/cmds/servicemanager/service_manager.c中的main方法中调用了binder_become_context_manager方法进入,在这里其实就是直接调用了ioctl,而这里是native的ioctl方法,native层的ioctl方法与kernel(驱动层)的binder_ioctl方法映射,就直接调用的是驱动层的binder_ioctl方法,这里传入了命令是BINDER_SET_CONTEXT_MGR,这样在binder_ioctl就会处理BINDER_SET_CONTEXT_MGR分支的内容

int binder_become_context_manager(struct binder_state *bs)
{
    // 直接调用了ioctl,命令是BINDER_SET_CONTEXT_MGR
    // 其实就是调用了kernel下的binder.c的binder_ioctl
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

在这里我们看下驱动层的binder_ioctl方法:因为这里是从native层binder.c的ioctl函数,映射调用到了kernel层的binder.c的binder_ioctl函数

/**
 * 主要是读写操作的
 * 
 */ 
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    int ret;
    struct binder_proc *proc = filp->private_data;
    struct binder_thread *thread;
    unsigned int size = _IOC_SIZE(cmd);
    void __user *ubuf = (void __user *)arg;

    /*pr_info("binder_ioctl: %d:%d %x %lx\n",
            proc->pid, current->pid, cmd, arg);*/

    trace_binder_ioctl(cmd, arg);

    // 这里是一个挂起中断,正常情况下是不会中断的
    ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
    if (ret)
        goto err_unlocked;

    binder_lock(__func__);
    thread = binder_get_thread(proc);
    if (thread == NULL) {
        ret = -ENOMEM;
        goto err;
    }

    switch (cmd) {
    case BINDER_WRITE_READ:
        // 读写命令 --- 读写操作的时候,由应用层ioctl(BINDER_WRITE_READ)调用
        ret = binder_ioctl_write_read(filp, cmd, arg, thread);
        if (ret)
            goto err;
        break;
    case BINDER_SET_MAX_THREADS:
        if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
            ret = -EINVAL;
            goto err;
        }
        break;
    case BINDER_SET_CONTEXT_MGR:
        ret = binder_ioctl_set_ctx_mgr(filp);
        if (ret)
            goto err;
        break;
    case BINDER_THREAD_EXIT:
        binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
                 proc->pid, thread->pid);
        binder_free_thread(proc, thread);
        thread = NULL;
        break;
    case BINDER_VERSION: {
        struct binder_version __user *ver = ubuf;

        if (size != sizeof(struct binder_version)) {
            ret = -EINVAL;
            goto err;
        }
        if (put_user(BINDER_CURRENT_PROTOCOL_VERSION,
                 &ver->protocol_version)) {
            ret = -EINVAL;
            goto err;
        }
        break;
    }
    default:
        ret = -EINVAL;
        goto err;
    }
    ret = 0;
err:
    if (thread)
        thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
    binder_unlock(__func__);
    wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
    if (ret && ret != -ERESTARTSYS)
        pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
    trace_binder_ioctl_done(ret);
    return ret;
}

可以看到BINDER_SET_CONTEXT_MGR命令,主要就是调用了binder_ioctl_set_ctx_mgr方法
看kernel/drivers/staging/android/binder.c#binder_ioctl_set_ctx_mgr方法:
在这里就会创建了service_manager的实体,binder_new_node就是代表了service_manager服务

/**
 * 只创建一次
 */ 
static int binder_ioctl_set_ctx_mgr(struct file *filp)
{
    int ret = 0;
    struct binder_proc *proc = filp->private_data;
    struct binder_context *context = proc->context;

    kuid_t curr_euid = current_euid();

    // 判断是否存在,如果存在,则直接返回
    if (context->binder_context_mgr_node) {
        pr_err("BINDER_SET_CONTEXT_MGR already set\n");
        ret = -EBUSY;
        goto out;
    }
    ret = security_binder_set_context_mgr(proc->tsk);
    if (ret < 0)
        goto out;
    // 这里第一次SM的uid是无效的
    if (uid_valid(context->binder_context_mgr_uid)) {
        if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) {
            pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
                   from_kuid(&init_user_ns, curr_euid),
                   from_kuid(&init_user_ns,
                     context->binder_context_mgr_uid));
            ret = -EPERM;
            goto out;
        }
    } else {
        // 设置uid
        context->binder_context_mgr_uid = curr_euid;
    }
    // 创建sm的实体,这里的binder_new_node创建的node其实就是代表了service_manager
    // 会添加到proc->nodes中
    // 并且会对这个node做初始化
    // 不过最先会对这个node分配虚拟内存
    // context中的binder_context_mgr_node就是代表了SM的实体
    context->binder_context_mgr_node = binder_new_node(proc, 0, 0);
    if (!context->binder_context_mgr_node) {
        ret = -ENOMEM;
        goto out;
    }
    context->binder_context_mgr_node->local_weak_refs++;
    context->binder_context_mgr_node->local_strong_refs++;
    context->binder_context_mgr_node->has_strong_ref = 1;
    context->binder_context_mgr_node->has_weak_ref = 1;
out:
    return ret;
}

在这里会创建了binder_node,这个binder_node其实就是SM实体,通过调用kernel/drivers/staging/android/binder.c#binder_new_node方法

/**
 * 1.创建了binder_node结构体对象
 * 2.proc --> binder_node
 * 3.创建work和todo消息队列,分别由客户端和服务端进行不断的读取消息,
 * 类似于Handler中的MessageQueue
 */ 
static struct binder_node *binder_new_node(struct binder_proc *proc,
                       binder_uintptr_t ptr,
                       binder_uintptr_t cookie)
{
    struct rb_node **p = &proc->nodes.rb_node;
    struct rb_node *parent = NULL;
    struct binder_node *node;

    while (*p) {
        parent = *p;
        node = rb_entry(parent, struct binder_node, rb_node);

        if (ptr < node->ptr)
            p = &(*p)->rb_left;
        else if (ptr > node->ptr)
            p = &(*p)->rb_right;
        else
            return NULL;
    }
    // 分配内存空间
    node = kzalloc(sizeof(*node), GFP_KERNEL);
    if (node == NULL)
        return NULL;
    binder_stats_created(BINDER_STAT_NODE);
    rb_link_node(&node->rb_node, parent, p);
    // 添加到proc->nodes中
    rb_insert_color(&node->rb_node, &proc->nodes);
    // 进行node初始化
    node->debug_id = ++binder_last_id;
    node->proc = proc;
    node->ptr = ptr;
    node->cookie = cookie;
    node->work.type = BINDER_WORK_NODE;
    // work和todo,这是客户端和服务端用来处理的消息队列
    // 因为存在客户端和服务端,所以需要两个来不断的读取消息的消息队列
    INIT_LIST_HEAD(&node->work.entry);
    INIT_LIST_HEAD(&node->async_todo);
    binder_debug(BINDER_DEBUG_INTERNAL_REFS,
             "%d:%d node %d u%016llx c%016llx created\n",
             proc->pid, current->pid, node->debug_id,
             (u64)node->ptr, (u64)node->cookie);
    return node;
}

4.native/cmds/servicemanager/binder.c#binder_loop

在native层的service_manager.c的main方法,创建驱动对象,并且调用binder_ioctl创建了service_manager服务之后,就会在native层的service_manager.c的main方法中调用binder_loop函数
最初始的时候,binder_loop方法,主要是做两个工作:

  • 根据命令BC_ENTER_LOOPER,向thread_looper写入状态,为BINDER_LOOPER_STATE_ENTERED,即进入binder_looper
  • 读取数据,首先修改thread->looper的状态为BINDER_LOOPER_STATE_WAITING,即进入等待状态,然后根据wait_for_proc_work=true,调用ret = wait_event_freezable_exclusive方法进入阻塞等待状态,等待需要处理的消息的进入
/**
 * 循环处理数据的
 */ 
void binder_loop(struct binder_state *bs, binder_handler func)
{
    int res;
    // binder_write_read是在kernel层中的binder.h中定义的
    struct binder_write_read bwr;
    uint32_t readbuf[32];

    bwr.write_size = 0;
    bwr.write_consumed = 0;
    bwr.write_buffer = 0;

    // 进入BC_ENTER_LOOPER命令,进入循环
    readbuf[0] = BC_ENTER_LOOPER;
    // 将readbuf写入
    // 这里是处理write
    // 写入BC_ENTER_LOOPER命令,根据该命令设置thread->looper的状态
    binder_write(bs, readbuf, sizeof(uint32_t));

    // 无限死循环不断读取数据
    for (;;) {
        // 在进入for循环的时候,write_size最初是为0的
        // 而read_size是不为0
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;
        // 又是通过BINDER_WRITE_READ命令进行读写,进入kernel层的binder_ioctl方法
        // 这里是处理read
        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;
        }
    }
}

binder_write_read结构体

/*
 * On 64-bit platforms where user code may run in 32-bits the driver must
 * translate the buffer (and local binder) addresses appropriately.
 */

struct binder_write_read {
    binder_size_t       write_size; /* bytes to write */
    binder_size_t       write_consumed; /* bytes consumed by driver */
    binder_uintptr_t    write_buffer;
    binder_size_t       read_size;  /* bytes to read */
    binder_size_t       read_consumed;  /* bytes consumed by driver */
    binder_uintptr_t    read_buffer;
};
(1)写入BC_ENTER_LOOPER命令

在native/cmds/servicemanager/binder.c#binder_loop中调用binder_write写入readbuf数据,而readbuf中是只有一个命令数据。binder_write写入BC_ENTER_LOOPER命令的时候,就是将该命令数据保存在binder_write_read实体对象中的write_buffer中,然后调用驱动层的binder_ioctl函数,执行BINDER_WRITE_READ分支的功能,此时因为binder_write_read实体的write_buffer中有数据,所以会执行binder_ioctl函数的write功能。

/**
 * 写数据
 */ 
int binder_write(struct binder_state *bs, void *data, size_t len)
{
    struct binder_write_read bwr;
    int res;
    // 因为是写数据,所以write_size不为0
    bwr.write_size = len;
    bwr.write_consumed = 0;
    // 这里的data其实就是readbuf命令数据,将命令数据保存在binder_write_read
    // 这个结构体的对象的write_buffer中
    bwr.write_buffer = (uintptr_t) data;
    // 写数据,所以read部分的信息都是0
    bwr.read_size = 0;
    bwr.read_consumed = 0;
    bwr.read_buffer = 0;
    // 初始化binder_write_read之后,调用ioctl执行BINDER_WRITE_READ功能
    // 这里就是调用了kernel层的binder_ioctl,触发调用BINDER_WRITE_READ部分功能
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    if (res < 0) {
        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
                strerror(errno));
    }
    return res;
}

在在native/cmds/servicemanager/binder.c#binder_write中调用了ioctl写入进入循环的命令,接着就会调用kernel层的binder.c#binder_ioctl方法,而触发的是BINDER_WRITE_READ分支,所以会最终调用了binder_ioctl_write_read方法

/**
 * binder_ioctl
 * 读写操作
 * 
 */ 
static int binder_ioctl_write_read(struct file *filp,
                unsigned int cmd, unsigned long arg,
                struct binder_thread *thread)
{
    int ret = 0;
    struct binder_proc *proc = filp->private_data;
    unsigned int size = _IOC_SIZE(cmd);
    void __user *ubuf = (void __user *)arg;
    struct binder_write_read bwr;

    if (size != sizeof(struct binder_write_read)) {
        ret = -EINVAL;
        goto out;
    }
    // 这里copy的不是有效数据,copy的是数据头。但是也是将用户空间的数据拷贝到内核空间
    // 这里拷贝的依然是数据头,即readbuf[0] = BC_ENTER_LOOPER;这个数据的数据头
    if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
        ret = -EFAULT;
        goto out;
    }
    binder_debug(BINDER_DEBUG_READ_WRITE,
             "%d:%d write %lld at %016llx, read %lld at %016llx\n",
             proc->pid, thread->pid,
             (u64)bwr.write_size, (u64)bwr.write_buffer,
             (u64)bwr.read_size, (u64)bwr.read_buffer);
    // 判断写入数据是否有
    // 这里的bwr其实就是在native/cmds/servicemanager/binder.c#binder_write
    // 方法中初始化的binder_write_read结构体对象bwr
    // 这里的bwr.buffer其实就是readbuf[0]=BC_ENTER_LOOPER
    // write_size是大于0的
    if (bwr.write_size > 0) {
        // 这里就会处理命令,这里的命令是BC_ENTER_LOOPER
        // 进入binder_thread_write方法中进行处理该命令
        ret = binder_thread_write(proc, thread,
                      bwr.write_buffer,
                      bwr.write_size,
                      &bwr.write_consumed);
        trace_binder_write_done(ret);
        if (ret < 0) {
            bwr.read_consumed = 0;
            if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
                ret = -EFAULT;
            goto out;
        }
    }
    // 判断读的数据是否有
    if (bwr.read_size > 0) {
        ret = binder_thread_read(proc, thread, bwr.read_buffer,
                     bwr.read_size,
                     &bwr.read_consumed,
                     filp->f_flags & O_NONBLOCK);
        trace_binder_read_done(ret);
        if (!list_empty(&proc->todo))
            wake_up_interruptible(&proc->wait);
        if (ret < 0) {
            if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
                ret = -EFAULT;
            goto out;
        }
    }
    binder_debug(BINDER_DEBUG_READ_WRITE,
             "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
             proc->pid, thread->pid,
             (u64)bwr.write_consumed, (u64)bwr.write_size,
             (u64)bwr.read_consumed, (u64)bwr.read_size);
    // 把内核空间的数据拷贝到用户空间
    if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
        ret = -EFAULT;
        goto out;
    }
out:
    return ret;
}

因为在binder_loop流程中,首先是需要写入BC_ENTER_LOOPER命令,所以binder_write_read实体的write_buffer有值,并且write_size>0,所以在驱动层binder.c的binder_ioctl_write_read函数中,会调用bwr.write_size>0的if条件,即调用到了binder_thread_write函数
在kernel/drivers/staging/android/binder.c中的binder_thread_write方法中进行处理BC_ENTER_LOOPER命令,主要处理代码如下:
这里其实就是设置了thread->looper的状态

        case BC_ENTER_LOOPER:
            binder_debug(BINDER_DEBUG_THREADS,
                     "%d:%d BC_ENTER_LOOPER\n",
                     proc->pid, thread->pid);
            if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
                thread->looper |= BINDER_LOOPER_STATE_INVALID;
                binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",
                    proc->pid, thread->pid);
            }
            thread->looper |= BINDER_LOOPER_STATE_ENTERED;
            break;
(2)处理BC_ENTER_LOOPER命令

写入操作完成之后,在native/cmds/servicemanager/binder.c#binder_loop方法中的for循环,会循环调用ioctl,这里就是对binder_write_read的read数据做初始化,去读取BC_ENTER_LOOPER命令数据,然后调用ioctl的BINDER_WRITE_READ指令操作,这里因为对binder_write_read的read数据做了初始,read_size>0,而write_size不是大于0,所以会调用到kernel/drivers/staging/android/binder.c中的binder_ioctl,最终根据BINDER_WRITE_READ指令调用到了binder_ioctl_write_read方法,又因为read_size>0,所以最终调用到了binder_thread_read方法

/**
 * binder_ioctl
 * 读写操作
 * 
 */ 
static int binder_ioctl_write_read(struct file *filp,
                unsigned int cmd, unsigned long arg,
                struct binder_thread *thread)
{
    int ret = 0;
    struct binder_proc *proc = filp->private_data;
    unsigned int size = _IOC_SIZE(cmd);
    void __user *ubuf = (void __user *)arg;
    struct binder_write_read bwr;

    if (size != sizeof(struct binder_write_read)) {
        ret = -EINVAL;
        goto out;
    }
    // 这里copy的不是有效数据,copy的是数据头。但是也是将用户空间的数据拷贝到内核空间
    if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
        ret = -EFAULT;
        goto out;
    }
    binder_debug(BINDER_DEBUG_READ_WRITE,
             "%d:%d write %lld at %016llx, read %lld at %016llx\n",
             proc->pid, thread->pid,
             (u64)bwr.write_size, (u64)bwr.write_buffer,
             (u64)bwr.read_size, (u64)bwr.read_buffer);
    // 判断写入数据是否有
    if (bwr.write_size > 0) {
        ret = binder_thread_write(proc, thread,
                      bwr.write_buffer,
                      bwr.write_size,
                      &bwr.write_consumed);
        trace_binder_write_done(ret);
        if (ret < 0) {
            bwr.read_consumed = 0;
            if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
                ret = -EFAULT;
            goto out;
        }
    }
    // 判断读的数据是否有,在native/cmds/servicemanager/binder.c中的binder_loop方法中
    // for循环的read数据不为0,read_size>0,调用kernel层的binder_ioctl
    // 进而根据BINDER_WRITE_READ调用此方法,根据read_size>0调用这里
    if (bwr.read_size > 0) {
        ret = binder_thread_read(proc, thread, bwr.read_buffer,
                     bwr.read_size,
                     &bwr.read_consumed,
                     filp->f_flags & O_NONBLOCK);
        trace_binder_read_done(ret);
        if (!list_empty(&proc->todo))
            wake_up_interruptible(&proc->wait);
        if (ret < 0) {
            if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
                ret = -EFAULT;
            goto out;
        }
    }
    binder_debug(BINDER_DEBUG_READ_WRITE,
             "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
             proc->pid, thread->pid,
             (u64)bwr.write_consumed, (u64)bwr.write_size,
             (u64)bwr.read_consumed, (u64)bwr.read_size);
    // 把内核空间的数据拷贝到用户空间
    if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
        ret = -EFAULT;
        goto out;
    }
out:
    return ret;
}

接着调用binder_thread_read方法,进入处理BC_ENTER_LOOPER命令的过程,让SM进入等待状态,进行阻塞,等待消息的进入。
在执行到ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));的时候,service_manager服务就进入阻塞,等待消息的进入。

/**
 * 这里wait_for_proc_work=true
 * 而会调用ret = wait_event_freezable_exclusive方法,SM进入阻塞状态
 */ 
static int binder_thread_read(struct binder_proc *proc,
                  struct binder_thread *thread,
                  binder_uintptr_t binder_buffer, size_t size,
                  binder_size_t *consumed, int non_block)
{
    // 这里的buffer其实就是bwr中的read_buffer
    void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
    void __user *ptr = buffer + *consumed;
    void __user *end = buffer + size;

    int ret = 0;
    int wait_for_proc_work;

    // 这里的read_consumed是为0的
    if (*consumed == 0) {
        // 如果是从native层的binder.c中的binder_loop方法调用binder_ioctl
        // 这里的ptr就是在binder_loop调用ioctl传入的bwr
        // ptr中其实是有很多个命令的,以先入先出的原则,先进入的命令先处理
        if (put_user(BR_NOOP, (uint32_t __user *)ptr))
            return -EFAULT;
        ptr += sizeof(uint32_t);
    }

retry:
    // wait_for_proc_work这里是为true
    // 因为两个条件都满足为null
    wait_for_proc_work = thread->transaction_stack == NULL &&
                list_empty(&thread->todo);

    if (thread->return_error != BR_OK && ptr < end) {
        if (thread->return_error2 != BR_OK) {
            if (put_user(thread->return_error2, (uint32_t __user *)ptr))
                return -EFAULT;
            ptr += sizeof(uint32_t);
            binder_stat_br(proc, thread, thread->return_error2);
            if (ptr == end)
                goto done;
            thread->return_error2 = BR_OK;
        }
        if (put_user(thread->return_error, (uint32_t __user *)ptr))
            return -EFAULT;
        ptr += sizeof(uint32_t);
        binder_stat_br(proc, thread, thread->return_error);
        thread->return_error = BR_OK;
        goto done;
    }


    thread->looper |= BINDER_LOOPER_STATE_WAITING;
    // 这里进行已经准备好的线程++,后面就会--
    // 这里++是告诉binder已经service_manager已经准备好
    // 已经在等待消息的进入,而如果SM在处理消息,则会ready_threads--,表示正在处理消息
    if (wait_for_proc_work)
        proc->ready_threads++;

    binder_unlock(__func__);

    trace_binder_wait_for_work(wait_for_proc_work,
                   !!thread->transaction_stack,
                   !list_empty(&thread->todo));
    if (wait_for_proc_work) {
        if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
                    BINDER_LOOPER_STATE_ENTERED))) {
            binder_user_error("%d:%d ERROR: Thread waiting for process work before calling BC_REGISTER_LOOPER or BC_ENTER_LOOPER (state %x)\n",
                proc->pid, thread->pid, thread->looper);
            wait_event_interruptible(binder_user_error_wait,
                         binder_stop_on_user_error < 2);
        }
        binder_set_nice(proc->default_priority);
        // sm进入的时候,这里是阻塞的,所以non_block是false
        if (non_block) {
            if (!binder_has_proc_work(proc, thread))
                ret = -EAGAIN;
        } else
            ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));// 这里就是进行一个等待,因为没有数据
    } else {
        if (non_block) {
            if (!binder_has_thread_work(thread))
                ret = -EAGAIN;
        } else
            ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
    }

    binder_lock(__func__);

    if (wait_for_proc_work)
        proc->ready_threads--;
    thread->looper &= ~BINDER_LOOPER_STATE_WAITING;

    if (ret)
        return ret;

    while (1) {
        uint32_t cmd;
        struct binder_transaction_data tr;
        struct binder_work *w;
        struct binder_transaction *t = NULL;

        if (!list_empty(&thread->todo)) {
            w = list_first_entry(&thread->todo, struct binder_work,
                         entry);
        } else if (!list_empty(&proc->todo) && wait_for_proc_work) {
            w = list_first_entry(&proc->todo, struct binder_work,
                         entry);
        } else {
            /* no data added */
            if (ptr - buffer == 4 &&
                !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN))
                goto retry;
            break;
        }

        if (end - ptr < sizeof(tr) + 4)
            break;

        switch (w->type) {
        case BINDER_WORK_TRANSACTION: {
            t = container_of(w, struct binder_transaction, work);
        } break;
        case BINDER_WORK_TRANSACTION_COMPLETE: {
            cmd = BR_TRANSACTION_COMPLETE;
            if (put_user(cmd, (uint32_t __user *)ptr))
                return -EFAULT;
            ptr += sizeof(uint32_t);

            binder_stat_br(proc, thread, cmd);
            binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE,
                     "%d:%d BR_TRANSACTION_COMPLETE\n",
                     proc->pid, thread->pid);

            list_del(&w->entry);
            kfree(w);
            binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
        } break;
        case BINDER_WORK_NODE: {
            struct binder_node *node = container_of(w, struct binder_node, work);
            uint32_t cmd = BR_NOOP;
            const char *cmd_name;
            int strong = node->internal_strong_refs || node->local_strong_refs;
            int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong;

            if (weak && !node->has_weak_ref) {
                cmd = BR_INCREFS;
                cmd_name = "BR_INCREFS";
                node->has_weak_ref = 1;
                node->pending_weak_ref = 1;
                node->local_weak_refs++;
            } else if (strong && !node->has_strong_ref) {
                cmd = BR_ACQUIRE;
                cmd_name = "BR_ACQUIRE";
                node->has_strong_ref = 1;
                node->pending_strong_ref = 1;
                node->local_strong_refs++;
            } else if (!strong && node->has_strong_ref) {
                cmd = BR_RELEASE;
                cmd_name = "BR_RELEASE";
                node->has_strong_ref = 0;
            } else if (!weak && node->has_weak_ref) {
                cmd = BR_DECREFS;
                cmd_name = "BR_DECREFS";
                node->has_weak_ref = 0;
            }
            if (cmd != BR_NOOP) {
                if (put_user(cmd, (uint32_t __user *)ptr))
                    return -EFAULT;
                ptr += sizeof(uint32_t);
                if (put_user(node->ptr,
                         (binder_uintptr_t __user *)ptr))
                    return -EFAULT;
                ptr += sizeof(binder_uintptr_t);
                if (put_user(node->cookie,
                         (binder_uintptr_t __user *)ptr))
                    return -EFAULT;
                ptr += sizeof(binder_uintptr_t);

                binder_stat_br(proc, thread, cmd);
                binder_debug(BINDER_DEBUG_USER_REFS,
                         "%d:%d %s %d u%016llx c%016llx\n",
                         proc->pid, thread->pid, cmd_name,
                         node->debug_id,
                         (u64)node->ptr, (u64)node->cookie);
            } else {
                list_del_init(&w->entry);
                if (!weak && !strong) {
                    binder_debug(BINDER_DEBUG_INTERNAL_REFS,
                             "%d:%d node %d u%016llx c%016llx deleted\n",
                             proc->pid, thread->pid,
                             node->debug_id,
                             (u64)node->ptr,
                             (u64)node->cookie);
                    rb_erase(&node->rb_node, &proc->nodes);
                    kfree(node);
                    binder_stats_deleted(BINDER_STAT_NODE);
                } else {
                    binder_debug(BINDER_DEBUG_INTERNAL_REFS,
                             "%d:%d node %d u%016llx c%016llx state unchanged\n",
                             proc->pid, thread->pid,
                             node->debug_id,
                             (u64)node->ptr,
                             (u64)node->cookie);
                }
            }
        } break;
        case BINDER_WORK_DEAD_BINDER:
        case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
        case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
            struct binder_ref_death *death;
            uint32_t cmd;

            death = container_of(w, struct binder_ref_death, work);
            if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
                cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
            else
                cmd = BR_DEAD_BINDER;
            if (put_user(cmd, (uint32_t __user *)ptr))
                return -EFAULT;
            ptr += sizeof(uint32_t);
            if (put_user(death->cookie,
                     (binder_uintptr_t __user *)ptr))
                return -EFAULT;
            ptr += sizeof(binder_uintptr_t);
            binder_stat_br(proc, thread, cmd);
            binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
                     "%d:%d %s %016llx\n",
                      proc->pid, thread->pid,
                      cmd == BR_DEAD_BINDER ?
                      "BR_DEAD_BINDER" :
                      "BR_CLEAR_DEATH_NOTIFICATION_DONE",
                      (u64)death->cookie);

            if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
                list_del(&w->entry);
                kfree(death);
                binder_stats_deleted(BINDER_STAT_DEATH);
            } else
                list_move(&w->entry, &proc->delivered_death);
            if (cmd == BR_DEAD_BINDER)
                goto done; /* DEAD_BINDER notifications can cause transactions */
        } break;
        }

        if (!t)
            continue;

        BUG_ON(t->buffer == NULL);
        if (t->buffer->target_node) {
            struct binder_node *target_node = t->buffer->target_node;

            tr.target.ptr = target_node->ptr;
            tr.cookie =  target_node->cookie;
            t->saved_priority = task_nice(current);
            if (t->priority < target_node->min_priority &&
                !(t->flags & TF_ONE_WAY))
                binder_set_nice(t->priority);
            else if (!(t->flags & TF_ONE_WAY) ||
                 t->saved_priority > target_node->min_priority)
                binder_set_nice(target_node->min_priority);
            cmd = BR_TRANSACTION;
        } else {
            tr.target.ptr = 0;
            tr.cookie = 0;
            cmd = BR_REPLY;
        }
        tr.code = t->code;
        tr.flags = t->flags;
        tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);

        if (t->from) {
            struct task_struct *sender = t->from->proc->tsk;

            tr.sender_pid = task_tgid_nr_ns(sender,
                            task_active_pid_ns(current));
        } else {
            tr.sender_pid = 0;
        }

        tr.data_size = t->buffer->data_size;
        tr.offsets_size = t->buffer->offsets_size;
        tr.data.ptr.buffer = (binder_uintptr_t)(
                    (uintptr_t)t->buffer->data +
                    proc->user_buffer_offset);
        tr.data.ptr.offsets = tr.data.ptr.buffer +
                    ALIGN(t->buffer->data_size,
                        sizeof(void *));

        if (put_user(cmd, (uint32_t __user *)ptr))
            return -EFAULT;
        ptr += sizeof(uint32_t);
        if (copy_to_user(ptr, &tr, sizeof(tr)))
            return -EFAULT;
        ptr += sizeof(tr);

        trace_binder_transaction_received(t);
        binder_stat_br(proc, thread, cmd);
        binder_debug(BINDER_DEBUG_TRANSACTION,
                 "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",
                 proc->pid, thread->pid,
                 (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
                 "BR_REPLY",
                 t->debug_id, t->from ? t->from->proc->pid : 0,
                 t->from ? t->from->pid : 0, cmd,
                 t->buffer->data_size, t->buffer->offsets_size,
                 (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);

        list_del(&t->work.entry);
        t->buffer->allow_user_free = 1;
        if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
            t->to_parent = thread->transaction_stack;
            t->to_thread = thread;
            thread->transaction_stack = t;
        } else {
            t->buffer->transaction = NULL;
            kfree(t);
            binder_stats_deleted(BINDER_STAT_TRANSACTION);
        }
        break;
    }

done:

    *consumed = ptr - buffer;
    if (proc->requested_threads + proc->ready_threads == 0 &&
        proc->requested_threads_started < proc->max_threads &&
        (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
         BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
         /*spawn a new thread if we leave this out */) {
        proc->requested_threads++;
        binder_debug(BINDER_DEBUG_THREADS,
                 "%d:%d BR_SPAWN_LOOPER\n",
                 proc->pid, thread->pid);
        if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
            return -EFAULT;
        binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
    }
    return 0;
}

二、如何获取service_manager服务

主要是native层。native/cmds/libs/binder/下
IServiceManager.cpp中的defaultServiceManager方法
获取sm的情况:

  • 注册服务到sm -- native
  • 通过sm获取服务 -- java
    java层:ServiceManagerProxy->BinderProxy->BpBinder(java层获取SM)
    java层,比如AIDL中,其Proxy代理类中,会有一个mRemote,这个mRemote其实就是BinderProxy,而BinderProxy这个代理类其实在native就是调用BpBinder,而这里的BpBinder其实就是客户端的SM代理,用来代理服务端的BBinder,而服务端的BBinder其实就可以认为是SM
    native层:BpServiceManager->BpBinder(native获取sm)

1.frameworks/native/libs/binder/IServiceManager.cpp#defaultServiceManager()

这里主要分析defaultServiceManager中调用的三个部分:

  • (1)ProcessState::self()
  • (2)getContextObject(NULL)
  • (3)interface_cast<IServiceManager>
sp<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
    
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        // 这里的while循环,就是为了防止SM还没有注册,或者是正在注册但是未注册完成
        // 这样的情况下,进入循环的进入睡眠状态进行等待SM注册完成
        while (gDefaultServiceManager == NULL) {
            // ProcessState::self()->getContextObject(NULL)返回的其实就是BpBinder对象,
            // BpBinder其实就是执行服务端的
            // BBinder是服务端的对象,而BpBinder可以认为是BBinder的代理
            // 这里就可以把BpBinder认为是SM的代理,而BBinder认为是SM
            // 因为客户端没有办法拿到BBinder(sm),而客户端可以创建BpBinder
            // 可以认为BpBinder是BBinder的代理(sm的代理),客户端就可以通过BpBinder操作BBinder
            // 即通过sm代理跨进程远程操作sm进程
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
            // 如果没有获取到,则睡眠
            if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }
    
    return gDefaultServiceManager;
}

2.frameworks/native/libs/binder/ProcessState.cpp#self()

这里主要就是处理ProcessState,new了一个ProcessState对象。
而ProcessState::self()其实就是创建进程对象,然后通过ProcessState的getContextObject函数获取到对应的BpBinder对象,用BpBinder对象与服务端的BBinder进行通信。而在这里,就会创建对应的内存大小,这里其实就是native层对binder的内存大小限制,这里限制的大小就是1M-8K。就是10241024-(40962)
new ProcessState做的事情:

  • 打开驱动 -- 调用open_driver,设置最大线程数为15
  • mmap -- 将设置ProcessState内存大小,并且与Binder驱动做内存映射
// 在IServiceManager.cpp中的defaultServiceManager中调用
sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != NULL) {
        return gProcess;
    }
    gProcess = new ProcessState;
    return gProcess;
}

看ProcessState在new的时候做了什么操作:

ProcessState::ProcessState()
    : mDriverFD(open_driver())// 打开设备(其实就是binder)
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)// 最大线程数 -- 15个
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // XXX Ideally, there should be a specific define for whether we
        // have mmap (or whether we could possibly have the kernel module
        // availabla).
#if !defined(HAVE_WIN32_IPC)
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        // 这里是注册服务到SM中 -- ProcessState也是服务端
        // 这里就是设置ProcessState与binder驱动的内存映射
        // 通过mmap设置共享内存(binder和服务端之间的内存大小),大小是((1*1024*1024) - (4096 *2))=1M-8K
        // 这是普通服务的内存大小
        // #define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
            close(mDriverFD);
            mDriverFD = -1;
        }
#else
        mDriverFD = -1;
#endif
    }

    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}
(1)打开binder驱动 -- 设置最大线程数(默认最大线程数15)
// 打开设备(其实就是打开binder驱动)
static int open_driver()
{
    // 打开binder驱动,这里就是调用了kernel层的binder_open方法
    int fd = open("/dev/binder", O_RDWR);
    if (fd >= 0) {
        fcntl(fd, F_SETFD, FD_CLOEXEC);
        int vers = 0;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        if (result == -1) {
            ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
            close(fd);
            fd = -1;
        }
        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
            ALOGE("Binder driver protocol does not match user space protocol!");
            close(fd);
            fd = -1;
        }
        // 设置最大线程数 -- 15个
        size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
        // 这里就是将最大线程数写入,具体实现设置的功能
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
        if (result == -1) {
            ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        }
    } else {
        ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
    }
    return fd;
}

3.frameworks/native/libs/binder/ProcessState.cpp#getContextObject

这里通过调用getStrongProxyForHandle方法,传入handle=0
getContextObject做的事情:

  • 创建一个BpBinder --- 这是客户端的对象,是服务端的BBinder的代理类,服务端的BBinder其实就是SM(service_manager服务)

其实BpBinder就相当于service_manager的引用,是相对于服务端的BBinder,服务端的BBinder其实就是相当于service_manager的引用,而客户端的BpBinder就是相当于服务端BBinder的代理,客户端使用SM的时候,其实就是通过BpBinder来使用SM,而BpBinder使用其内部具体是依赖于服务端的BBinder来使用SM。

可以根据Java层的来看:

Java层操作ServiceManager,在低版本中使用类似AIDL的方式,而在高版本系统是直接使用AIDL的方式。而AIDL在编译完成之后,会有对应的Java代码,即对应的实现了android.os.IInterface接口的interface,在这个interface中会有一个内部抽象类Stub,而在Stub中会有一个Proxy(其实Proxy可以不需要在Stub中),这个Proxy就是interface的实现类。
比如ServiceManager相关的ServiceManagerProxy可以认为是AIDL中的Proxy,而在Proxy中会通过操作mRemote来进行跨进程,而mRemote就是一个IBinder,而mRemote的值其实在ServiceManagerProxy中就是BinderProxy,而BinderProxy就是代理了native层的BpBinder,而BpBinder其实就是客户端在native层的对于服务端BBinder的代理,服务端的BBinder其实就是SM(service_manager)
ServiceManagerProxy-->BinderProxy-->BpBinder

从native层来看:

native层操作ServiceManager是通过BpServiceManager操作BpBinder。
BpServiceManager-->BpBinder
操作ServiceManager,Java层和native层最终都是通过BpBinder来操作,最终都是由BpBinder进行transact操作,因为BpBinder其实是BBinder的代理,类似于上面的Proxy的方式,BpBinder会代理一个BBinder对象,通过BpBinder的transact之后调用到BBinder对象的transact之后,然后调用到BBinder的onTransact,这样就进行了跨进程,从客户端跨越到了服务端。
因为客户端是需要跨进程,客户端部分是没有真正的SM的,而服务端的SM,其实就是BBinder,客户端是通过BBinder的代理,即BpBinder来实现对SM的调用。

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);

    // 查找handle对应的资源线,获取handle_entry结构体对象
    handle_entry* e = lookupHandleLocked(handle);
    // 这个e不为null
    if (e != NULL) {
        // We need to create a new BpBinder if there isn't currently one, OR we
        // are unable to acquire a weak reference on this current one.  See comment
        // in getWeakProxyForHandle() for more info about this.
        // 获取handle_entry中的binder对象
        IBinder* b = e->binder;
        // 查看弱引用是否存在(当前是不存在的)
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            // handle为0
            if (handle == 0) {
                // Special case for context manager...
                // The context manager is the only object for which we create
                // a BpBinder proxy without already holding a reference.
                // Perform a dummy transaction to ensure the context manager
                // is registered before we create the first local reference
                // to it (which will occur when creating the BpBinder).
                // If a local reference is created for the BpBinder when the
                // context manager is not present, the driver will fail to
                // provide a reference to the context manager, but the
                // driver API does not return status.
                //
                // Note that this is not race-free if the context manager
                // dies while this code runs.
                //
                // TODO: add a driver API to wait for context manager, or
                // stop special casing handle 0 for context manager and add
                // a driver API to get a handle to the context manager with
                // proper reference counting.

                // 这里就是测试binder是否准备就绪
                // 通过PING命令测试
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }

            // 创建了BpBinder,里面调用incWeakHandle,会进行弱引用计数
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            // This little bit of nastyness is to allow us to add a primary
            // reference to the remote proxy when this team doesn't have one
            // but another team is sending the handle to us.
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }
    // 返回BpBinder
    return result;
}

4.frameworks/native/include/binder/IInterface.h#interface_cast

interface_cast主要是:

  • 根据上面创建的BpBinder对象创建了BpServiceManager(BpBinder)对象,BpServiceManager对象中会有一个mRemote
  • 通过mRemote.transact进行远程调用
  • mRemote其实就是BpBinder,而BpBinder是客户端的,是服务端的BBinder的代理类,调用BpBinder其实就是调用了BBinder,然后进而调用了BBinder的onTransact,这样实现了跨进程调用SM

这里使用的是一个模板方法,具体的模板实现就是在IInterface.h中定义的。而asInterface就是在IInterface.h通过#define宏定义进行展开

template<typename INTERFACE>
// 这里的obj其实就是BpBinder
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    // 这里的INTERFACE可以认为是泛型,就是将IServiceManager替换INTERFACE
    return INTERFACE::asInterface(obj);
}

宏定义,定义了asInterface方法,而这里的就是需要把INTERFACE替换成IServiceManager

#define DECLARE_META_INTERFACE(INTERFACE)                               
    static const android::String16 descriptor;                          
    static android::sp<I##INTERFACE> asInterface(                       
            const android::sp<android::IBinder>& obj);                  
    virtual const android::String16& getInterfaceDescriptor() const;    
    I##INTERFACE();                                                     
    virtual ~I##INTERFACE();                                            


#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       
    const android::String16 I##INTERFACE::descriptor(NAME);             
    const android::String16&                                            
            I##INTERFACE::getInterfaceDescriptor() const {              
        return I##INTERFACE::descriptor;                                
    }                                                                   
    android::sp<I##INTERFACE> I##INTERFACE::asInterface(                
            const android::sp<android::IBinder>& obj)                   
    {                                                                   
        android::sp<I##INTERFACE> intr;                                 
        if (obj != NULL) {                                              
            intr = static_cast<I##INTERFACE*>(                          
                obj->queryLocalInterface(                               
                        I##INTERFACE::descriptor).get());               
            if (intr == NULL) {                                        
                intr = new Bp##INTERFACE(obj);                          
            }                                                           
        }                                                               
        return intr;                                                    
    }                                                                   
    I##INTERFACE::I##INTERFACE() { }                                    
    I##INTERFACE::~I##INTERFACE() { }                                   

针对DECLARE_META_INTERFACE部分做替换展开
DECLARE_META_INTERFACE部分主要是声明asInterface和getInterfaceDescriptor方法的

static const android::String16 descriptor;
static android::sp< IServiceManager > asInterface(const
    android::sp<android::IBinder>& obj)
virtual const android::String16& getInterfaceDescriptor() const;
IServiceManager ();
virtual ~IServiceManager();

针对IMPLEMENT_META_INTERFACE部分做替换展开
这部分是asInterface和getInterfaceDescriptor方法的具体实现

const android::String16
IServiceManager::descriptor(“android.os.IServiceManager”);
const android::String16& IServiceManager::getInterfaceDescriptor() const
{
    return IServiceManager::descriptor;
}
// 这里的obj其实就是BpBinder
android::sp<IServiceManager> IServiceManager::asInterface(const
    android::sp<android::IBinder>& obj)
{
    android::sp<IServiceManager> intr;
    if(obj != NULL) {
        intr = static_cast<IServiceManager *>(
        obj->queryLocalInterface(IServiceManager::descriptor).get());
        if (intr == NULL) {
            // 等价于 new BpServiceManager(BpBinder)
            // BpServiceManager是在IServiceManager的内部类
            intr = new BpServiceManager(obj);
        }
    }
    return intr;
}
IServiceManager::IServiceManager () { }
IServiceManager::~ IServiceManager() { }

调用asInterface之后,其内部会new BpServiceManager,在new BpServiceManager的时候,会传入BpBinder对象。

    BpServiceManager(const sp<IBinder>& impl)
        : BpInterface<IServiceManager>(impl)
    {
    }
template<typename INTERFACE>
// 调用了BpRefBase,这里的remote其实就是BpBinder
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)
{
}

而BpInterface是实现了frameworks/native/libs/binder/Binder.cpp中的

BpRefBase::BpRefBase(const sp<IBinder>& o)
    : mRemote(o.get()), mRefs(NULL), mState(0)
{
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);

    if (mRemote) {
        mRemote->incStrong(this);           // Removed on first IncStrong().
        mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
    }
}

这里的o其实还是BpBinder
而这里又有mRemote,说明BpServiceManager中也会有一个mRemote,这个mRemote是对BpBinder的封装,而调用mRemote.transact的时候,其实就是调用了BpBinder.transact,而BpBinder又是BBinder的代理,所以就是调用了BBinder.transact,这样就跨进程调用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容