Android笔记 - Binder之Client请求Service代理对象
Posted demonyan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android笔记 - Binder之Client请求Service代理对象相关的知识,希望对你有一定的参考价值。
前言
之前两篇文章以 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.cpp
virtual 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.c
static 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.c
int 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.c
int 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.c
struct 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.c
void 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.c
static 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.cpp
status_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.cpp
virtual 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.cpp
sp<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.cpp
sp<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之servicemanager代理对象
Android笔记 - Binder之守护进程servicemanager