美文网首页
Android-Binder是如何启动和获取service_ma

Android-Binder是如何启动和获取service_ma

作者: zzq_nene | 来源:发表于2020-12-19 19:27 被阅读0次
    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,这样就跨进程调用。

    相关文章

      网友评论

          本文标题:Android-Binder是如何启动和获取service_ma

          本文链接:https://www.haomeiwen.com/subject/oheeuktx.html