Skip to content

Latest commit

 

History

History
702 lines (456 loc) · 28.2 KB

1.Binder系统核心.md

File metadata and controls

702 lines (456 loc) · 28.2 KB
title date categories tags description
Binder系统核心
2021-03-14
Android
Android

Binder系统核心

先梳理Binder底层,底层的原理清楚了,再来看上层的C++和Java封装。上层的C++和Java,只是基于底层Binder实现,做成了面向对象的方式,更方便使用。

IPC 和 RPC

IPC(Inter-Process Communication,进程间通信)

进程A 发数据 给进程B,即成为 IPC, 这个概念泛指进程之间任何形式的通信行为

RPC(Remote Process Call)

进程A 想要调用进程B的 hello 方法。 那么进程A需要封装(构造)数据,将数据通过IPC发送给B进程,B进程收到后,取出数据,然后调用自己本地的 hello 方法。

这个过程中,好像A进程直接调用了B进程的 hello 方法一样,这个理解为RPC。

数据传输三大要素

进程A

  1. 目的 进程B

那么,进程A怎么能知道进程B呢。

用到 ServiceManager

进程B向ServiceManager注册, 然后进程A从ServiceManager查询,拿到进程B的handler。然后可以通过handler去调用进程B的hello方法

  1. 数据

Android的通信是基于Client-Server架构的,进程间的通信无非就是Client向Server发起请求,Server响应Client的请求。这里以发起请求为例:当Client向Server发起请求(例如,MediaPlayer向MediaPlayerService发起请求),Client会先将请求数据从用户空间拷贝到内核空间(将数据从MediaPlayer发给Binder驱动);数据被拷贝到内核空间之后,再通过驱动程序,将内核空间中的数据拷贝到Server位于用户空间的缓存中(Binder驱动将数据发给MediaPlayerService)。这样,就成功的将Client进程中的请求数据传递到了Server进程中。

在Binder驱动中,将句柄0指定为ServiceManager对应的句柄,通过这个特殊的句柄就能获取ServiceManager对象。

/Volumes/Android/android-source/android-4.0.4_r1/frameworks/base/cmds/servicemanager/service_manager.c

int main(int argc, char **argv)
{
    struct binder_state *bs;
    void *svcmgr = BINDER_SERVICE_MANAGER;

    // 打开驱动程序,内部会调用 bs->fd = open("/dev/binder", O_RDWR);
    bs = binder_open(128*1024);

    // 告知驱动程序,自己就是 servicemanager
    if (binder_become_context_manager(bs)) {
        LOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    svcmgr_handle = svcmgr;

    // 开始循环,死循环,不断从驱动中读取数据,解析数据,处理数据,并发送回复信息
    binder_loop(bs, svcmgr_handler);
    return 0;
}

/Volumes/Android/android-source/android-4.0.4_r1/frameworks/base/cmds/servicemanager/bctest.c

数据传输过程

binder_proc是描述进程上下文信息的,每一个用户空间的进程都对应一个binder_proc结构体。 binder_node是Binder实体对应的结构体,它是Service在Binder驱动中的体现。 binder_ref是Binder引用对应的结构体,它是Client在Binder驱动中的体现。

handle 是服务的引用。同一个服务,在不同的进程中handle不一致。它是按注册顺序来的。

handle 是进程A 对进程 B提供的服务X 的引用。 进程B可能提供多个服务,X,Y,Z 如果按照XYZ的顺序向进程servicemanager注册,那在servicemanager中, XYZ的handle分别是123 注册之后, 如果 A 去获取服务,按照顺序ZYX, 那对应ZYX的handle 分别是123。

按顺序来的

驱动中,用binder_node 来描述服务。 用 binder_ref 来描述 这个服务的引用(也就是用户态的handle)。 binder_ref 中有个成员 desc, 就等于这个handle值。

当向进程B的X服务发送数据,想要通过这个handle来找到进程B的X服务。 通过handle,在内核中就可以找到binder_ref,通过binder_ref,就能找到对应的服务:binder_node。

然后在binder_node中有个binder_proc ,表示这个服务从属于哪个进程的,这样就找到进程B。 这样,就可以把数据放入进程B的一个链表中,就行了。

注意,这里都是在内核态,是可以把数据放在其他进程的。

注册服务的时候

binder驱动在内核为每个服务创建 binder_node

binder_node 中有 proc=server进程

在Binder驱动转发该请求之前,它其实还做了两件很重要的事: (01) 当它知道该请求是由一个Serivce发送的时候,它会新建该Serivce对应的Binder实体(binder_node)。 (02) 它在ServiceManager的"保存Binder引用的红黑树"中查找是否存在该Service的Binder引用;找不到的话,就新建该Service对应的Binder引用,并将其添加到"ServiceManager的保存Binder引用的红黑树"中。简言之,Binder驱动会创建Serivce对应的Binder实体,并在ServiceManager的红黑树中添加该Binder实体的Binder引用。

然后binder驱动 会在内核中为servicemanager创建 binder_ref 指向 binder_node binder_ref.desc = handle 1 2 3

servicemanager在用户态会保存服务的链表,里面包含 服务名字 和 handle(就是 binder_ref.desc )

client 向 servicemanager 查询服务

传入 服务名字

servicemanager 用户态就会从链表中根据服务名字查找出handle并交给内核态(binder驱动)

binder驱动从 binder_ref 的红黑树中,根据 handle = binder_ref.desc 找到一个 binder_ref。然后再通过 binder_ref 找到 binder_node。

同时,给client 创建新的binder_ref,指向服务的 binder_node, 这个ref的desc也是从1开始。

然后把数据放在client的todo链表,唤醒client

对于servicemanager,在内核态,有一系列的 binder_ref(就是所有注册过的服务) 对于client,在内核态,也有一系列的binder_ref(就是所有client获取过的服务)

这时,client在内核态其实已经能够通过binder_ref找到想要的服务对应的 binder_node 节点了。 然后,client驱动返回desc给用户态,它就是handle

当client 想要发数据给这个handle,调用服务的方法的时候 驱动中根据handle,找到binder_ref,再找到binder_node,再找到server进程,然后把数据放在server进程的TODO列表。

数据复制

copy_from_user

copy_to_user

mmap, 只需要一次复制

ServiceManager流程详解

int main(int argc, char **argv)
{
    struct binder_state *bs;
    // 打开驱动程序,内部会调用 bs->fd = open("/dev/binder", O_RDWR);
    bs = binder_open(128*1024);
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }
    // 告知驱动程序,自己就是 servicemanager
    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

   ...

    // BINDER_SERVICE_MANAGER handler=0,表示的就是servicemanager
    svcmgr_handle = BINDER_SERVICE_MANAGER;
    // 开始循环,死循环,不断从驱动中读取数据,解析数据,处理数据,并发送回复信息
    binder_loop(bs, svcmgr_handler);

    return 0;
}

Binder流程

C++层

"本地服务"就是Service提供的服务本身,而"远程服务"就是服务的代理;"服务接口"则是抽象出了它们的通用接口。这3个角色都是通用的,对于不同的服务而言,它们的名称都不相同。

(01) 当Serivce启动之后,它会先将自己注册到ServiceManager中。注册时,Binder驱动会创建Serivce对应的Binder实体(binder_node),并将"Serivce对应的本地服务对象的地址(就是处理函数的指针)"保存到Binder实体中。注册成功之后,Serivce就进入消息循环(binder_loop),等待Client的请求。 (02) 当Client需要和Serivce通信时,会先获取到Serivce接入点,即获取到远程服务对象(从ServiceManager处获取);而且Client要获取的远程服务对象是"服务接口"类型的(就是IXXService这样的)。Client向ServiceManager发送获取服务的请求时,会通过IPCThreadState和Binder驱动进行通信;当ServiceManager反馈之后,IPCThreadState会将ServiceManager反馈的"Serivce的Binder引用信息"保存BpBinder中(具体来说,BpBinder的mHandle成员保存的就是Serivce的Binder引用信息)。然后,会根据该BpBinder对象创建对应的远程服务。这样,Client就获取到了远程服务对象,而且远程服务对象的成员中保存了Serivce的Binder引用信息。 (03) 当Client获取到远程服务对象之后,它就可以轻松的和Serivce进行通信了。当它需要向Serivce发送请求时,它会调用远程服务接口;远程服务能够获取到BpBinder对象,而BpBinder则通过IPCThreadState和Binder驱动进行通信。由于BpBinder中保存了Serivce在Binder驱动中的Binder引用;因此,IPCThreadState和Binder驱动通信时,是知道该请求是需要传给哪个Serivce的。Binder驱动通过Binder引用找到对应的Binder实体,然后将Binder实体中保存的"Serivce对应的本地服务对象的地址"返回给用户空间。当IPC收到Binder驱动反馈的内容之后,它从内容中找到"Serivce对应的本地服务对象",然后调用该对象的onTransact()。不同的本地服务都可以实现自己的onTransact();这样,不同的服务就可以按照自己的需求来处理请求。

(4) 在初始化完待处理事务t之后,接着将MediaPlayerService请求的数据拷贝到内核空间并解析出来。从数据中解析出MediaPlayerService请求数据中的flat_binder_object对象,只有一个flat_binder_object对象。该flat_binder_object对象的类型是BINDER_TYPE_BINDER,然后调用binder_get_node()在当前进程的上下文环境proc中查找fp->binder对应的Binder实体,fp->binder是Android的flatten_binder()中赋值的,它是MediaPlayerService对象的本地引用的描述(即MediaPlayerService对应的BBinder对象的描述);此外,在MediaPlayerService是初次与Binder驱动通信,因此肯定找不到该对象fp->binder对应的Binder实体;因此node=NULL。 接下来,就调用binder_new_node()新建fp->binder对应的Binder实体,这也就是MediaPlayerService对应的Binder实体。然后,调用binder_get_ref_for_node(target_proc, node)获取该Binder实体在target_proc(即ServiceManager的进程上下文环境)中的Binder引用,此时,在target_proc中肯定也找不到该Binder实体对应的引用;那么,就新建Binder实体的引用,并将其添加到target_proc->refs_by_node红黑树 和 target_proc->refs_by_desc红黑树中。 这样,Service Manager的进程上下文中就存在MediaPlayerService的Binder引用,Service Manager也就可以对MediaPlayerService进行管理了!然后,修改fp->type=BINDER_TYPE_HANDLE,并使fp->handle = ref->desc。这样,就将MediaPlayerService的请求数据解析出来,并且在Binder驱动中创建了MediaPlayerService对应的Binder实体,而且将该Binder实体添加到MediaPlayerService的进程上下文proc中。更重要的是,在ServiceManager的refs_by_node和refs_by_desc这两颗红黑树中创建了"MediaPlayerService对应的Binder实体的Binder引用"。这意味着,在Binder驱动中,已经能在ServiceManager的进程上下文中找到MediaPlayerService,其中该流程涉及的主要源码如下:

前面说过,Server是以服务的形式注册到ServiceManager中,而Server在Client中则是以远程服务的形式存在的。因此,这个图的主干就是理清楚本地服务和远程服务这两者之间的关系。 "本地服务"就是Server提供的服务本身,而"远程服务"就是服务的代理;"服务接口"则是抽象出了它们的通用接口。这3个角色都是通用的,对于不同的服务而言,它们的名称都不相同。例如,对于MediaPlayerService服务而言,本地服务就是MediaPlayerService自身,远程服务是BpMediaPlayerService,而服务接口是IMediaPlayerService。当Client需要向MediaPlayerService发送请求时,它需要先获取到服务的代理(即,远程服务对象),也就是BpMediaPlayerService实例,然后通过该实例和MediaPlayerService进行通信。

(01) 当Server启动之后,它会先将自己注册到ServiceManager中。注册时,Binder驱动会创建Server对应的Binder实体,并将"Server对应的本地服务对象的地址"保存到Binder实体中。注册成功之后,Server就进入消息循环,等待Client的请求。 (02) 当Client需要和Server通信时,会先获取到Server接入点,即获取到远程服务对象;而且Client要获取的远程服务对象是"服务接口"类型的。Client向ServiceManager发送获取服务的请求时,会通过IPCThreadState和Binder驱动进行通信;当ServiceManager反馈之后,IPCThreadState会将ServiceManager反馈的"Server的Binder引用信息"保存BpBinder中(具体来说,BpBinder的mHandle成员保存的就是Server的Binder引用信息)。然后,会根据该BpBinder对象创建对应的远程服务。这样,Client就获取到了远程服务对象,而且远程服务对象的成员中保存了Server的Binder引用信息。 (03) 当Client获取到远程服务对象之后,它就可以轻松的和Server进行通信了。当它需要向Server发送请求时,它会调用远程服务接口;远程服务能够获取到BpBinder对象,而BpBinder则通过IPCThreadState和Binder驱动进行通信。由于BpBinder中保存了Server在Binder驱动中的Binder引用;因此,IPCThreadState和Binder驱动通信时,是知道该请求是需要传给哪个Server的。Binder驱动通过Binder引用找到对应的Binder实体,然后将Binder实体中保存的"Server对应的本地服务对象的地址"返回给用户空间。当IPC收到Binder驱动反馈的内容之后,它从内容中找到"Server对应的本地服务对象",然后调用该对象的onTransact()。不同的本地服务都可以实现自己的onTransact();这样,不同的服务就可以按照自己的需求来处理请求。

Binder addService流程图

Binder getService 流程图

addService Framework实现

getService Framework实现

Android framework 调用服务

服务获取和服务调用 handle 的处理和服务处理函数地址的处理

服务获取,拿到handle,用handle 构造 BpBinder,进而构造 BinderProxy。我们知道BinderProxy是用来和Binder驱动进行通信的,那么怎么和服务端的业务逻辑牵涉起来呢,这个时候我们用一下asInterface方法就好了,用XXServiceNative.asInterface(BinderProxy) 或者 IXXService.Stub.asInterface(BinderProxy)就可以返回 return new XXManagerProxy(obj); 然后用 XXManagerProxy 调用服务端方法。

调用的时候,拿着 XXManagerProxy 去调用,指定code: mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); 进而调用 BinderProxy,然后调用 BpBinder 的方法。BpBinder 里是知道handle 是多少。在BpBinder中调用 status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); 这个mHandle 就是之前构造BpBinder 用的handle,也就是在客户端proc中的binder_ref红黑树中维护的服务的handle 然后进入:IPCThreadState::transact,传入handle

里面用: writeTransactionData 构造好binder_transaction_data

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer) { binder_transaction_data tr;

tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;

.... }

把handle 和 code 都放在binder_transaction_data里。注意这里没放cookie

放好后,调用 waitForResponse,里面talkWithDriver,里面ioctl,就去调用驱动了:binder.c 中 binder_ioctl 然后:binder_ioctl_write_read 里面先 binder_thread_write,走这个 case BC_TRANSACTION: case BC_REPLY: { struct binder_transaction_data tr;

		if (copy_from_user(&tr, ptr, sizeof(tr)))
			return -EFAULT;
		ptr += sizeof(tr);
		binder_transaction(proc, thread, &tr,
				   cmd == BC_REPLY, 0);
		break;
	}

进入 binder_transaction 走这个: if (tr->target.handle) { struct binder_ref *ref;

		/*
		 * There must already be a strong ref
		 * on this node. If so, do a strong
		 * increment on the node to ensure it
		 * stays alive until the transaction is
		 * done.
		 */
		binder_proc_lock(proc);
		ref = binder_get_ref_olocked(proc, tr->target.handle,
					     true);
		if (ref) {
			target_node = binder_get_node_refs_for_txn(
					ref->node, &target_proc,
					&return_error);
		} else {
			binder_user_error("%d:%d got transaction to invalid handle\n",
					  proc->pid, thread->pid);
			return_error = BR_FAILED_REPLY;
		}
		binder_proc_unlock(proc);
	} 

显然,我们调用服务的话, handle != 0 ; handle=0是 manager哦。 这个if中tr->target.handle 就是上面在: IPCThreadState::writeTransactionData 中构造好的。

这里的逻辑:

  1. 先根据 tr->target.handle 在客户端自己的进程中找 binder_ref 。能找到,因为之前getService的时候给客户端创建了 binder_ref

  2. 找到了,其实 ref->node 就是 服务实体 binder_node。代理这里调用了 static struct binder_node *binder_get_node_refs_for_txn( struct binder_node *node, struct binder_proc **procp, uint32_t *error) { struct binder_node *target_node = NULL;

    binder_node_inner_lock(node); if (node->proc) { target_node = node; binder_inc_node_nilocked(node, 1, 0, NULL); binder_inc_node_tmpref_ilocked(node); node->proc->tmp_ref++; *procp = node->proc; } else *error = BR_DEAD_REPLY; binder_node_inner_unlock(node);

    return target_node; }

显然,就是直接把 ref->node 赋值给target_node,并返回了。这样就拿到了 target_node,就是想要请求的服务的实体。 3. 拿到服务的实体(binder_node)之后,做了什么呢。 t->code = tr->code; t->buffer->transaction = t; t->buffer->target_node = target_node;

包装成 t, 放在 服务进程的 todo里去

下面解析 flat_binder_object。

flat_binder_object 是在 Pracel.writeStrongBinder的时候写入的。

writeStrongBinder 最终调用

writeStrongBinder肯定是写入binder实体。 正常请求服务都走这个if (!local)

status_t flatten_binder(const sp& proc, const sp& binder, Parcel* out) { flat_binder_object obj;

obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != NULL) {
    IBinder *local = binder->localBinder();
    if (!local) {
        // 正常请求服务都走这个
        BpBinder *proxy = binder->remoteBinder();
        if (proxy == NULL) {
            LOGE("null proxy");
        }
        const int32_t handle = proxy ? proxy->handle() : 0;
        obj.type = BINDER_TYPE_HANDLE;
        obj.handle = handle;
        obj.cookie = NULL;
    } else {
        //addService会走到该分支里面
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = local->getWeakRefs();
        obj.cookie = local;
    }
} else {
    obj.type = BINDER_TYPE_BINDER;
    obj.binder = NULL;
    obj.cookie = NULL;
}

return finish_flatten_binder(binder, obj, out);

}

flat_binder_object 就说的这,继续解析 flat_binder_object。

就走这个分支: case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { struct flat_binder_object *fp;

		fp = to_flat_binder_object(hdr);
		ret = binder_translate_handle(fp, t, thread);
		if (ret < 0) {
			return_error = BR_FAILED_REPLY;
			return_error_param = ret;
			return_error_line = __LINE__;
			goto err_translate_failed;
		}
	} break;

binder_translate_handle

static int binder_translate_handle(struct flat_binder_object *fp, struct binder_transaction *t, struct binder_thread *thread) { struct binder_proc *proc = thread->proc; struct binder_proc *target_proc = t->to_proc; struct binder_node *node; struct binder_ref_data src_rdata; int ret = 0;

// 使用 fp->handle 从客户端proc的红黑树找到 binder_ref,进而找到 node。有的
// 不知道为啥又找一遍
node = binder_get_node_from_ref(proc, fp->handle,
		fp->hdr.type == BINDER_TYPE_HANDLE, &src_rdata);
if (!node) {
	binder_user_error("%d:%d got transaction with invalid handle, %d\n",
			  proc->pid, thread->pid, fp->handle);
	return -EINVAL;
}
if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
	ret = -EPERM;
	goto done;
}

binder_node_lock(node);

// 这个条件应该是满足的。因为 node 就是我们要请求的的服务实体
if (node->proc == target_proc) {
	// 走这个
	if (fp->hdr.type == BINDER_TYPE_HANDLE)
		fp->hdr.type = BINDER_TYPE_BINDER;
	else
		fp->hdr.type = BINDER_TYPE_WEAK_BINDER;
	// flat_binder_object 的 binder 里放了 服务处理函数的地址,cookie放服务实体
	fp->binder = node->ptr;
	fp->cookie = node->cookie;
}

} binder_translate_handle大概就做了这些,把fp赋值了一些服务实体相关的东西

完了之后就唤醒 服务进程了

client醒来,取出 todo里的数据:binder_transaction

if (t->buffer->target_node) { struct binder_node *target_node = t->buffer->target_node; struct binder_priority node_prio;

        // 注意这里根据 targetNode 直接给 trd 赋值了
		trd->target.ptr = target_node->ptr;
		trd->cookie =  target_node->cookie;
		node_prio.sched_policy = target_node->sched_policy;
		node_prio.prio = target_node->min_priority;
		binder_transaction_priority(current, t, node_prio,
					    target_node->inherit_rt);
		cmd = BR_TRANSACTION;
	}

    给 trd 赋值,trd 是 binder_transaction_data。包括target的ptr,cookie

    还有:
    trd->code = t->code; // 请求哪个方法
	trd->flags = t->flags;



    然后是对 flat_binder_object 的处理
    trd->data_size = t->buffer->data_size;
	trd->offsets_size = t->buffer->offsets_size;
	trd->data.ptr.buffer = (binder_uintptr_t)
		((uintptr_t)t->buffer->data +
		binder_alloc_get_user_buffer_offset(&proc->alloc));
	trd->data.ptr.offsets = trd->data.ptr.buffer +
				ALIGN(t->buffer->data_size,
				    sizeof(void *));


                    处理完,就回到: IPCThreadState::talkWithDriver

                    进而回到:IPCThreadState::getAndExecuteCommand()
                    // 调用executeCommand()对数据进行处理。
                    result = executeCommand(cmd);

    case BR_TRANSACTION:
    {
        binder_transaction_data tr;
        result = mIn.read(&tr, sizeof(tr));
        ...

        Parcel buffer;
        buffer.ipcSetDataReference(
            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
            tr.data_size,
            reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
            tr.offsets_size/sizeof(size_t), freeBuffer, this);

        ...

        Parcel reply;
        ...
        if (tr.target.ptr) {// 这个上面赋值了,不空
            sp<BBinder> b((BBinder*)tr.cookie);// trd->cookie =  target_node->cookie;
            const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
            if (error < NO_ERROR) reply.setError(error);

        } else {
            ...
        }

ipcSetDataReference不知啥用

然后 tr.cookie 就是服务实体,转成BBinder,调用它的 transact方法。

由于JavaBBinder(C++)重写了onTransact()。所以调用JavaBBinder的onTransact

调用到Java层的Binder的execTransact方法

然后调用子类重新的onTransact //此时会调用子类重写之后的onTransact方法 res = onTransact(code, data, reply, flags);

        就进入到 JavaBBinder子类Stub处理onTransact方法。

        结束!

        不知道 前面把 target->node 放在了 binder_transaction_data,并且给tr.cookie  tr.target.ptr都赋值了,为啥还要flat_binder_object??

        是在 unflatten_binder 里用的
status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, sp<IBinder>* out)
{
    const flat_binder_object* flat = in.readObject(false);
    
    if (flat) {
        switch (flat->type) {
            // 如果是Binder,就创建 BBinder
            case BINDER_TYPE_BINDER:
                *out = static_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            // 如果是 handle,就创建 BpBinder
            case BINDER_TYPE_HANDLE:
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
        }        
    }
    return BAD_TYPE;
}

flat_binder_object 规律总结:

只有调用远程服务的时候,传入handle,转成binder

addService,传入binder,驱动就转成 handle,让ServiceManager保存 getService,传入handle,驱动就转成 binder实体,然后服务进程拿到后就调用 getService。 执行完,返回 handle,驱动不转。用 reply.readStrongBinder(); 读 普通服务调用,好像同 这个 flat_binder_object 没关系

普通调用方法,好像并不需要用它

总结: addService,要注册服务,当然传入服务实体 getService,传入handle,驱动转成binder实体,好调用方法 getService,方法返回,返回handle,不转 普通调用方法,好像并不需要用它

匿名Binder,也是服务实体。

比如getService。 mRemote.transact()之后就一直读。 用的就是 reply.readStrongBinder()。从flat_binder_object读到的就是handle,然后构造代理对象

virtual sp checkService( const String16& name) const { Parcel data, reply;//这个是不是有似曾相识的感觉 data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); return reply.readStrongBinder(); }

//ServiceManagerNative.java
public IBinder getService(String name) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    //这里的mRemote为BinderProxy
    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
    //从reply里面解析出获取的IBinder对象
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

总结

Android系统的Binder通信实现了RPC远程调用,BpXXX和BnXXX则负责RPC远程调用的业务,XXX就代表不同的服务业务。BpXXX和BnXXX都实现了IXXX接口,IXXX定义了业务接口函数,BpXXX则是客户进程对服务进程中的BnXXX的影子对象,客户进程在调用服务进程中的某个接口函数时,只需调用BpXXX中的对应函数即可,BpXXX屏蔽了进程间通信的整个过程,让远程函数调用看起来和本地调用一样,这就是Android系统的Binder设计思想。