Android笔记 - Binder之Client请求Service代理对象
来源:互联网 发布:模拟量用电流没数据 编辑:程序博客网 时间:2024/05/16 15:38
前言
之前两篇文章以 MediaPlayerService 为例,分析了 Service 注册到服务管理者 servicemanager 的历程。我们知道,在请求注册 Service 之前,需要获取到 servicemanager 的代理对象。同理,在 Client 使用 Service 提供的服务之前,也需要获取到 Service 的代理对象。本文以 MediaPlayer 为例,分析 Client 端如何获取到 Service 代理对象 BpMediaPlayerService 的过程。BpMediaPlayerService 的类关系图如下所示:
由于 servicemanager 也是一个特殊的 Service,因此获取 servicemanager 的代理对象和获取 MediaPlayerService 的代理对象有很多相似之处。获取 servicemanager 代理对象的分析过程请参考文章 Binder之servicemanager代理对象。
MediaPlayer 进程发起请求
客户端 MediaPlayer 的实现在 frameworks/av/media/libmedia/mediaplayer.cpp
文件中,它通过 getMediaPlayerService 函数来获取 MediaPlayerService 的代理对象,下面看看 getMediaPlayerService 函数的定义:
代码路径:frameworks/av/media/libmedia/IMediaDeathNotifier.cpp/*static*/const sp<IMediaPlayerService>&IMediaDeathNotifier::getMediaPlayerService(){ Mutex::Autolock _l(sServiceLock); if (sMediaPlayerService == 0) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; do { binder = sm->getService(String16("media.player")); if (binder != 0) { break; } usleep(500000); // 0.5 s } while (true); if (sDeathNotifier == NULL) { sDeathNotifier = new DeathNotifier(); } binder->linkToDeath(sDeathNotifier); sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); } return sMediaPlayerService;}
首先通过 defaultServiceManager 函数获取 servicemanager 的代理对象 BpServiceManager,然后调用 BpServiceManager 的 getService 函数,注意函数参数为字符串 media.player
。getService 函数内部又调用了 checkService 函数,接下来看看 checkService 函数的定义:
代码路径:frameworks/native/libs/binder/IServiceManager.cppvirtual sp<IBinder> checkService(const String16& name) const{ Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); [1] data.writeString16(name); [2] remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); [3] return reply.readStrongBinder(); [4]}
[1] 通过 writeInterfaceToken 函数写入 RPC 头部信息。
[2] 使用 writeString16 函数写入请求服务的服务名,内容为 media.player
。
[3] 通过 remote 函数得到 BpServiceManager 保存在 BpRefBase 中的 BpBinder 对象,然后调用其 transact 函数。transact 函数包含三个参数:参数 CHECK_SERVICE_TRANSACTION 是获取 Service 代理对象的协议;参数 data 是一个 Parcel 对象,用于保存写入 Binder 驱动的数据;参数 reply 也是一个 Parcel 对象,用于接收返回数据。
[4] 通过 readStrongBinder 函数获取 Binder 驱动返回 的 Binder 对象,后文会详细分析此过程。
调用 transact 函数后,通过如下流程进入 Binder 驱动:
-> BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);-> IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);-> IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult);-> IPCThreadState::talkWithDriver(bool doReceive);-> ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr);
上述流程在 Binder之请求注册Service组件 这篇文章有分析,这里不再赘述。
Binder 驱动传递请求
ioctl 是一个系统调用,最终会进入 Binder 驱动的 binder_ioctl 函数。binder_ioctl 函数对用户空间传过来的 BINDER_WRITE_READ 命令进行处理,之前的文章也有分析。接下来进入 Binder 驱动的核心处理函数 binder_transaction,该函数定义如下:
代码路径:linux/drivers/staging/android/binder.cstatic void binder_transaction(struct binder_proc *proc, struct binder_thread *thread, struct binder_transaction_data *tr, int reply){ struct binder_transaction *t; struct binder_work *tcomplete; size_t *offp, *off_end; struct binder_proc *target_proc; struct binder_thread *target_thread = NULL; struct binder_node *target_node = NULL; struct list_head *target_list; wait_queue_head_t *target_wait; struct binder_transaction *in_reply_to = NULL; struct binder_transaction_log_entry *e; uint32_t return_error; ...... if (reply) { ...... } else { if (tr->target.handle) { ...... } else { target_node = binder_context_mgr_node; [1] if (target_node == NULL) { return_error = BR_DEAD_REPLY; goto err_no_context_mgr_node; } } target_proc = target_node->proc; [2] ...... } if (target_thread) { ...... } else { target_list = &target_proc->todo; [3] target_wait = &target_proc->wait; [4] } /* TODO: reuse incoming transaction for reply */ t = kzalloc(sizeof(*t), GFP_KERNEL); if (t == NULL) { return_error = BR_FAILED_REPLY; goto err_alloc_t_failed; } binder_stats_created(BINDER_STAT_TRANSACTION); tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL); ...... if (!reply && !(tr->flags & TF_ONE_WAY)) t->from = thread; [5] else t->from = NULL; t->sender_euid = proc->tsk->cred->euid; t->to_proc = target_proc; t->to_thread = target_thread; t->code = tr->code; t->flags = tr->flags; t->priority = task_nice(current); t->buffer = binder_alloc_buf(target_proc, tr->data_size, tr->offsets_size, !reply && (t->flags & TF_ONE_WAY)); if (t->buffer == NULL) { return_error = BR_FAILED_REPLY; goto err_binder_alloc_buf_failed; } t->buffer->allow_user_free = 0; t->buffer->debug_id = t->debug_id; t->buffer->transaction = t; t->buffer->target_node = target_node; if (target_node) binder_inc_node(target_node, 1, 0, NULL); offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *))); if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) { [6] ...... } ...... off_end = (void *)offp + tr->offsets_size; for (; offp < off_end; offp++) { [7] ...... } if (reply) { ...... } else if (!(t->flags & TF_ONE_WAY)) { BUG_ON(t->buffer->async_transaction != 0); t->need_reply = 1; t->from_parent = thread->transaction_stack; thread->transaction_stack = t; [8] } else { ...... } t->work.type = BINDER_WORK_TRANSACTION; list_add_tail(&t->work.entry, target_list); [9] tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; list_add_tail(&tcomplete->entry, &thread->todo); [10] if (target_wait) wake_up_interruptible(target_wait); [11] return; ......}
binder_transaction 函数包含四个参数,其中参数 proc 为指向请求发起进程也就是 MediaPlayer 进程的指针;参数 thread 为指向请求发起线程也就是 MediaPlayer 当前线程的指针;参数 tr 是结构体 binder_transaction_data 的指针,指向需要处理的事务数据,也就是从 MediaPlayer 传递过来通信数据;参数 reply 是一个布尔变量,如果值为 true,表示正在处理 BC_REPLY 协议,否则表示正在处理 BC_TRANSACTION 协议。
[1] 由于 tr->target.handle
值为0,因此 target_node 变量赋值为 servicemanager 的 Binder 实体对象。
[2] 由于需要通过 servicemanager 获取服务的句柄值,因此 target_proc 赋值为 servicemanager 的宿主进程。
[3] 根据 target_proc 获取 servicemanager 进程的待处理工作队列 target_list。
[4] 根据 target_proc 获取 servicemanager 进程的等待队列 target_wait。
[5] 初始化发起事务的线程 t->from 为 MediaPlayer 的当前线程。
[6] 使用 copy_from_user 函数从 tr 中拷贝通信数据到待处理事务 t 中。
[7] 由于通信数据不存在 Binder 对象,因此不会进入 for 循环。
[8] 将待处理事务 t 添加到事务发起线程(MediaPlayer 的当前线程)的事务堆栈。
[9] 将待处理事务 t 加入到 servicemanager 进程的待处理工作队列 target_list 中,注意事务类型为 BINDER_WORK_TRANSACTION。
[10] 将待完成工作项 tcomplete 加入到事务发起线程(MediaPlayer 的当前线程)的待处理工作队列中。MediaPlayer 当前线程对工作项 tcomplete 的处理过程请查阅文章 Binder之请求注册Service组件 。
[11] 唤醒目标进程 servicemanager 处理刚刚添加到待处理工作队列 target_list 中的待处理事务 t。
综上,binder_transaction 函数的工作主要是创建一个待处理事务 t,初始化完成后将其添加到目标进程 servicemanager 的待处理工作队列 target_list 中,最后唤醒 servicemanager 来处理该事务。
servicemanager 处理请求
如果没有进程间通信请求需要处理,servicemanager 会在 binder_thread_read 函数中调用 wait_event_freezable_exclusive 进入睡眠等待状态。servicemanager 被唤醒后,会通过 binder_has_proc_work 函数来检查是否有新的请求需要处理,也就是检查当前进程的待处理工作队列 todo 是否为空。由于之前 Binder 驱动将待处理事务 t 添加到了 servicemanager 进程的待处理工作队列中,接下来继续执行 binder_thread_read 函数,将待处理事务从 Binder 驱动转发到 servicemanager 用户空间,这个过程请参考文章 Binder之处理注册Service组件请求 第2小节。
binder_thread_read 函数执行完后会回到 binder_ioctl 函数,然后从 ioctl 系统调用返回到 binder_loop 函数中,也就是从 Binder 驱动重新回到了 servicemanager 用户空间。接下来 binder_loop 调用 binder_parse 函数解析从 Binder 驱动程序拷贝回来的 binder_transaction_data 结构体内容,如下所示:
代码路径:frameworks/native/cmds/servicemanager/binder.cint binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr, uint32_t size, binder_handler func){ int r = 1; uint32_t *end = ptr + (size / 4); while (ptr < end) { uint32_t cmd = *ptr++; switch(cmd) { case BR_NOOP: break; case BR_TRANSACTION_COMPLETE: break; ...... case BR_TRANSACTION: { struct binder_txn *txn = (void *) ptr; ...... if (func) { unsigned rdata[256/4]; struct binder_io msg; struct binder_io reply; int res; bio_init(&reply, rdata, sizeof(rdata), 4); [1] bio_init_from_txn(&msg, txn); [2] res = func(bs, txn, &msg, &reply); [3] binder_send_reply(bs, &reply, txn->data, res); [4] } ptr += sizeof(*txn) / sizeof(uint32_t); break; } ...... } } return r;}
[1] 使用函数 bio_init 初始化保存返回结果的变量 reply。
[2] 使用函数 bio_init_from_txn 初始化通信数据 msg。
注:binder_io 结构体对应于 Client 端的 Parcel 类,binder_txn 结构体对应于 Client 端的 binder_transaction_data 结构体。(-。-;),很喜欢这种对称美。
[3] 调用函数指针 func 指向的函数,这里 func 实际指向 svcmgr_handler 函数。
[4] 使用函数 binder_send_reply 返回查询服务的结果。
在分析 svcmgr_handler 函数的实现之前,回顾下之前 checkService 函数写入的请求内容:
接下来看看 svcmgr_handler 函数的具体内容,如下所示:
代码路径:frameworks/native/cmds/servicemanager/service_manager.cint svcmgr_handler(struct binder_state *bs, struct binder_txn *txn, struct binder_io *msg, struct binder_io *reply){ struct svcinfo *si; uint16_t *s; unsigned len; void *ptr; uint32_t strict_policy; int allow_isolated; if (txn->target != svcmgr_handle) return -1; // Equivalent to Parcel::enforceInterface(), reading the RPC // header with the strict mode policy mask and the interface name. // Note that we ignore the strict_policy and don't propagate it // further (since we do no outbound RPCs anyway). strict_policy = bio_get_uint32(msg); s = bio_get_string16(msg, &len); [1] if ((len != (sizeof(svcmgr_id) / 2)) || memcmp(svcmgr_id, s, sizeof(svcmgr_id))) { fprintf(stderr,"invalid id %s\n", str8(s)); return -1; } switch(txn->code) { case SVC_MGR_GET_SERVICE: case SVC_MGR_CHECK_SERVICE: s = bio_get_string16(msg, &len); [2] ptr = do_find_service(bs, s, len, txn->sender_euid); [3] if (!ptr) break; bio_put_ref(reply, ptr); [4] return 0; ...... } bio_put_uint32(reply, 0); return 0;}
[1] 使用 bio_get_string16 函数从 msg 中读取接口名 android.os.IServiceManager
。
[2] 使用 bio_get_string16 函数从 msg 中读取服务名 media.player
。
[3] 调用 do_find_service 查询服务名 media.player
对应的句柄值。
[4] 调用 bio_put_ref 将句柄值保存到一个 Bind 引用对象。
do_find_service 又是通过调用 find_svc 函数来查询句柄值,后者定义如下:
代码路径:frameworks/native/cmds/servicemanager/service_manager.cstruct svcinfo{ struct svcinfo *next; void *ptr; struct binder_death death; int allow_isolated; unsigned len; uint16_t name[0];};struct svcinfo *find_svc(uint16_t *s16, unsigned len){ struct svcinfo *si; for (si = svclist; si; si = si->next) { if ((len == si->len) && !memcmp(s16, si->name, len * sizeof(uint16_t))) { return si; } } return 0;}
其中参数 s16 的值为 media.player
,假设之前 MediaPlayerService 已经注册成功,那么肯定可以找到 name 为 media.player
的 svcinfo 结构体,该结构体的成员变量 ptr 指向对应的句柄值。
返回到 svcmgr_handler,调用函数 bio_put_ref 保存查询到的句柄值,如下所示:
代码路径:frameworks/native/cmds/servicemanager/binder.cvoid bio_put_ref(struct binder_io *bio, void *ptr){ struct binder_object *obj; if (ptr) obj = bio_alloc_obj(bio); [1] else obj = bio_alloc(bio, sizeof(*obj)); if (!obj) return; obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; obj->type = BINDER_TYPE_HANDLE; [2] obj->pointer = ptr; [3] obj->cookie = 0;}
[1] 调用 bio_alloc_obj 函数创建一个 Binder 对象。
[2] Binder 对象的成员变量 type 赋值为 BINDER_TYPE_HANDLE。
[3] Binder 对象的成员变量 pointer 赋值为指向句柄值的指针。
binder_io 结构体对应于 Client 端的 flat_binder_object 结构体。
svcmgr_handler 执行完后,返回到 binder_parse 中,继续调用 binder_send_reply 函数返回查询服务的结果 reply。binder_send_reply 内部会调用 binder_write 函数将查询结果传递给 Binder 驱动,该过程请参考文章 Binder之处理注册Service组件请求第3节。
Binder 驱动传递结果
binder_write 函数内部通过系统调用 ioctl(bs->fd, BINDER_WRITE_READ, &bwr)
来与 Binder 驱动进行交互,最终又一次进入 Binder 驱动的 binder_transaction 函数,注意此时参数 reply 的值为 true,接下来看看这个过程:
代码路径:linux/drivers/staging/android/binder.cstatic void binder_transaction(struct binder_proc *proc, struct binder_thread *thread, struct binder_transaction_data *tr, int reply){ struct binder_transaction *t; struct binder_work *tcomplete; size_t *offp, *off_end; struct binder_proc *target_proc; struct binder_thread *target_thread = NULL; struct binder_node *target_node = NULL; struct list_head *target_list; wait_queue_head_t *target_wait; struct binder_transaction *in_reply_to = NULL; ...... if (reply) { in_reply_to = thread->transaction_stack; [1] ...... thread->transaction_stack = in_reply_to->to_parent; target_thread = in_reply_to->from; [2] ...... target_proc = target_thread->proc; [3] } else { ...... } if (target_thread) { e->to_thread = target_thread->pid; target_list = &target_thread->todo; target_wait = &target_thread->wait; } else { ...... } e->to_proc = target_proc->pid; /* TODO: reuse incoming transaction for reply */ t = kzalloc(sizeof(*t), GFP_KERNEL); ...... tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL); ...... if (!reply && !(tr->flags & TF_ONE_WAY)) t->from = thread; else t->from = NULL; t->sender_euid = proc->tsk->cred->euid; t->to_proc = target_proc; t->to_thread = target_thread; t->code = tr->code; t->flags = tr->flags; t->priority = task_nice(current); trace_binder_transaction(reply, t, target_node); t->buffer = binder_alloc_buf(target_proc, tr->data_size, tr->offsets_size, !reply && (t->flags & TF_ONE_WAY)); if (t->buffer == NULL) { return_error = BR_FAILED_REPLY; goto err_binder_alloc_buf_failed; } t->buffer->allow_user_free = 0; t->buffer->debug_id = t->debug_id; t->buffer->transaction = t; t->buffer->target_node = target_node; trace_binder_transaction_alloc_buf(t->buffer); if (target_node) binder_inc_node(target_node, 1, 0, NULL); offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *))); if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) { ...... } if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) { ...... } off_end = (void *)offp + tr->offsets_size; for (; offp < off_end; offp++) { struct flat_binder_object *fp; ...... fp = (struct flat_binder_object *)(t->buffer->data + *offp); [4] switch (fp->type) { ...... case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); [5] ...... if (ref->node->proc == target_proc) { [6] ...... } else { struct binder_ref *new_ref; new_ref = binder_get_ref_for_node(target_proc, ref->node); [7] if (new_ref == NULL) { return_error = BR_FAILED_REPLY; goto err_binder_get_ref_for_node_failed; } fp->handle = new_ref->desc; [8] binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL); ...... } } break; ...... } } if (reply) { BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction(target_thread, in_reply_to); } ...... t->work.type = BINDER_WORK_TRANSACTION; list_add_tail(&t->work.entry, target_list); [9] tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; list_add_tail(&tcomplete->entry, &thread->todo); if (target_wait) wake_up_interruptible(target_wait); [10] return; ......}
[1] 初始化 in_reply_to 为指向当前线程 thread(servicemanager 线程) 的事务堆栈 binder_transaction 的指针。之前 binder_thread_read 函数将处理事务加入到了 thread 的事务堆栈,因此 in_reply_to 指针实际指向了之前加入的事务。
[2] 根据事务 in_reply_to 初始化目标线程 target_thread 为 MediaPlayer 的当前线程。
[3] 根据 target_thread 初始化目标进程 target_proc 为 MediaPlayer 进程。
[4] 从接收到的查询结果数据中获得一个 flat_binder_object 对象,该对象就是之前调用 bio_alloc_obj 函数创建的对象。
[5] 通过 binder_get_ref 函数找到句柄值 fp->handle
对应的 Binder 引用对象,实际上就是找到 MediaPlayerService 在 Binder 驱动中的引用对象。
由文章 Binder之请求注册Service组件可知,Service 在第一次请求注册时,Binder 驱动会通过 binder_get_ref_for_node 函数为 servicemanager 进程创建一个 Binder 引用对象,注册处理过程就是将 Binder 引用对象对应的句柄值保存到 servicemanager 的结构体 svcinfo 中。
[6] ref->node->proc
为创建 MediaPlayerService 的进程也就是 servicemanager 进程,而 target_proc 为 MediaPlayer 进程。两者不是同一进程,因此 if 条件判断不满足。
[7] 通过 binder_get_ref_for_node 函数为 MediaPlayer 进程创建一个 Binder 引用对象。
注:虽然 servicemanager 进程和 MediaPlayer 进程中的 Binder 引用对象不同,但引用对象都指向同一个 Binder 实体对象。
[8] 修改 fp->handle
的值为刚创建 Binder 引用对象的句柄值。
[9] 将待处理事务 t 加入到目标线程 MediaPlayer 的待处理工作队列 target_list 中。
[10] 唤醒目标线程 MediaPlayer 处理刚刚添加到待处理工作队列 target_list 中的待处理事务 t。
MediaPlayer 当前线程被唤醒后,继续执行 binder_thread_read 函数处理刚刚添加的事务,最终通过 copy_to_user 系统函数将事务中的数据传递到 MediaPlayer 进程的用户空间。
MediaPlayer 进程封装代理对象
回到 MediaPlayer 进程的用户空间,接下来执行流程返回到 waitForResponse 函数,如下所示:
代码路径:frameworks/native/libs/binder/IPCThreadState.cppstatus_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){ int32_t cmd; int32_t err; while (1) { if ((err=talkWithDriver()) < NO_ERROR) break; err = mIn.errorCheck(); if (err < NO_ERROR) break; if (mIn.dataAvail() == 0) continue; cmd = mIn.readInt32(); switch (cmd) { case BR_TRANSACTION_COMPLETE: if (!reply && !acquireResult) goto finish; break; ...... case BR_REPLY: { binder_transaction_data tr; err = mIn.read(&tr, sizeof(tr)); [1] if (err != NO_ERROR) goto finish; if (reply) { if ((tr.flags & TF_STATUS_CODE) == 0) { reply->ipcSetDataReference( [2] 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); } else { ...... } } ...... } goto finish; default: ...... } }finish: if (err != NO_ERROR) { if (acquireResult) *acquireResult = err; if (reply) reply->setError(err); mLastError = err; } return err;}
[1] 将事务数据从成员变量 mIn 读取到结构体 binder_transaction_data 中。
[2] ipcSetDataReference 函数又将 binder_transaction_data 中的数据保存到参数 reply,此时 reply 中的数据就是 servicemanager 调用 binder_send_reply 函数返回的查询结果。
注:Binder 引用对象的句柄值在 binder_transaction 函数中被修改了。
接下来通过 goto 语句跳出 while 循环,继续一路向北返回到 checkService 函数,如下所示:
代码路径:frameworks/native/libs/binder/IServiceManager.cppvirtual sp<IBinder> 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();}
注:无论走了多远,都不忘来时的路。
最后调用 readStrongBinder 函数读取 MediaPlayService 对应的 Binder 代理对象,如下所示:
代码路径:frameworks/native/libs/binder/Parcel.cppsp<IBinder> Parcel::readStrongBinder() const{ sp<IBinder> val; unflatten_binder(ProcessState::self(), *this, &val); return val;}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) { ...... case BINDER_TYPE_HANDLE: *out = proc->getStrongProxyForHandle(flat->handle); return finish_unflatten_binder( static_cast<BpBinder*>(out->get()), *flat, in); } } return BAD_TYPE;}
getStrongProxyForHandle 函数根据句柄值 flat->handle
获取代理对象,该函数第一次调用时会新建一个 BpBinder 代理对象并保存在 Vector 中,之后调用时 lookupHandleLocked 函数直接从 Vector 中获取 BpBinder 代理对象。getStrongProxyForHandle 函数定义如下:
代码路径:frameworks/native/libs/binder/ProcessState.cppsp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle){ sp<IBinder> result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); 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. IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { if (handle == 0) { Parcel data; status_t status = IPCThreadState::self()->transact( 0, IBinder::PING_TRANSACTION, data, NULL, 0); if (status == DEAD_OBJECT) return NULL; } b = new BpBinder(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } else { result.force_set(b); e->refs->decWeak(this); } } return result;}
回到 readStrongBinder 函数,此时 val 的值为新建的 Binder 代理对象。接下来返回到刚开始的 getMediaPlayerService 函数。
代码路径:frameworks/av/media/libmedia/IMediaDeathNotifier.cpp/*static*/const sp<IMediaPlayerService>&IMediaDeathNotifier::getMediaPlayerService(){ Mutex::Autolock _l(sServiceLock); if (sMediaPlayerService == 0) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; do { binder = sm->getService(String16("media.player")); if (binder != 0) { break; } usleep(500000); // 0.5 s } while (true); if (sDeathNotifier == NULL) { sDeathNotifier = new DeathNotifier(); } binder->linkToDeath(sDeathNotifier); sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); } return sMediaPlayerService;}
历经艰难险阻,语句
sm->getService(String16("media.player"))
终于执行完并返回了 BpBinder 代理对象。
为了方便 Client 端使用,使用函数模板 interface_cast<IMediaPlayerService>
将返回的代理对象 BpBinder 封装成 MediaPlayerService 的代理对象 sMediaPlayerService,详细过程请参考文章 Binder之servicemanager代理对象第2小节。
至此,以 MediaPlayer 为例,在 Client 端获取 Service 代理对象的整个流程分析完成。当然,由于个人水平和篇幅所限,文章忽略掉相当多的细节内容,只介绍了我所理解的关键点部分。如果对这部分内容很感兴趣,可以按照这个分析流程走几遍代码,再结合 Binder之基本概念这篇文章中 Binder 各角色之间的关系图去理解,相信会很有收获。以下是 Binder 各角色之间的关系图:
参考资料:
1. Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析
- Android笔记 - Binder之Client请求Service代理对象
- Android笔记 - Binder之servicemanager代理对象
- Android笔记 - Binder之请求注册Service组件
- Android笔记 - Binder之处理注册Service组件请求
- android service 之 Binder
- Android源码解析之Binder中Server和Client获得Service Manager接口
- Android - Binder机制 - client和普通service交互
- android IPC binder -- client/server与service manager交互流程
- Android Binder中的Server和Client获得Service Manager接口
- android IPC binder 的(service 和 client)简单应用
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
- Welcome to my new blog!
- 享元模式
- 如何配置apache服务器
- sql语句创建唯一索引
- hdu4507
- Android笔记 - Binder之Client请求Service代理对象
- fedora21 LAMP配置站点
- poj1426 Find The Multiple 题解
- 前端图形化展示js
- windows下如何github ssh 公钥
- 快速掌握Lua 5.3 —— 数据操作
- Greenplum数据库整体架构
- Python--多线程
- CS模式下的自动填充框(高效率,解决输入法多次回发问题并进行延迟处理)