Binder驱动部分的主要内容已经基本分析完了,现在回到native层,把之前源码分析三中未分析的部分拿出来分析一遍,注意目的是说明BBinder的作用。我把这一部分内容放在这里分析其实是有原因的,因为如果不理解Binder驱动部分的内容,那么肯定很难理解waitForResponse后面对接收到协议的处理
源码分析三我们分析了waitForResponse中发送数据的部分,我们接着看waitForResponse的后半部分。分析后半部分时,我们不能用前面服务向sm注册或客户向sm请求为例进行分析,我们必须设想另一个场景才能讲清楚BBinder的作用。
设想一下这种情形,客户端已经取得了服务端,并且向服务端发送了请求,请求的协议为BR_TRANSACTION。现在服务端准备接收这个请求,并作出处理。
waitForResponse分段2
while(1){
//...talkWithDriver将请求读取到mIn,这部分代码略过。
cmd = (uint32_t)mIn.readInt32();
switch (cmd) {
//...对case的处理,略去
default:
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
调用完talkWithDriver之后,当检查到mIn中有值时,从mIn中读取协议cmd。下面的switch case和executeCommand的作用根据协议进行相应的处理。而对BR_TRANSACTION的处理在executeCommand中。
executeCommand对BR_TRANSACTION的处理
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch ((uint32_t)cmd) {
//...
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));//从mIn中读出binder_transaction_data
ALOG_ASSERT(result == NO_ERROR,
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;
Parcel buffer;
//将tr恢复成Parcel
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
const pid_t origPid = mCallingPid;
const uid_t origUid = mCallingUid;
const int32_t origStrictModePolicy = mStrictModePolicy;
const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
mLastTransactionBinderFlags = tr.flags;
int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
if (curPrio > ANDROID_PRIORITY_NORMAL) {
setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
set_sched_policy(mMyThreadId, SP_BACKGROUND);
}
}
Parcel reply;
status_t error;
if (tr.target.ptr) {
if (reinterpret_cast<RefBase::weakref_type*>(
tr.target.ptr)->attemptIncStrong(this)) {
//注意这个调用
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags);
reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
} else {
error = UNKNOWN_TRANSACTION;
}
} else {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
if (error < NO_ERROR) reply.setError(error);
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
}
mCallingPid = origPid;
mCallingUid = origUid;
mStrictModePolicy = origStrictModePolicy;
mLastTransactionBinderFlags = origTransactionBinderFlags;
}
break;
忽略具体实现的细节,我们大致可以知道在对BR_TRANSACTION的处理中,首先是从mIn中读取数据恢复binder_transaction_data tr,然后再构造出Parcel Buffer,其实就是前面数据发送的逆过程,同样用一张图总结如下:
executeCommand中最重要的是下面这条语句。
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags);
这个cookie值是什么?答案就在源码分析五中对binder_thread_read的分析中。截取部分代码如下:
if (t->buffer->target_node) {
//得到sm对应的binder_node
struct binder_node *target_node = t->buffer->target_node;
struct binder_priority node_prio;
//根据上篇博文的分析我们知道,ptr和cookie指向服务类
tr.target.ptr = target_node->ptr;
tr.cookie = target_node->cookie;//注意这里对cookie进行赋值
当target_node不为空时,cookie值等于target_node的cookie。在源码分析四中我们知道,binder_node的cookie等于obj的cookie,而在源码分析二中我们知道,obj的cookie等于服务类例如MediaPlayerService的指针。
所以传递的数据包Parcel就交给了服务类的transact函数。而服务类是BBinder的派生类,也就相当于交给了BBinder的transact处理。
BBinder
//\frameworks\native\libs\binder\Binder.cpp
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
if (reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
又将数据交给了onTransact函数,onTransact都是虚函数,所以实际上处理数据的是BBinder继承者的onTransact()。比如BnMediaPlayerService的onTransact():
// \frameworks\av\media\libmedia\IMediaPlayerService.cpp
status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case CREATE: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaPlayerClient> client =
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
audio_session_t audioSessionId = (audio_session_t) data.readInt32();
sp<IMediaPlayer> player = create(client, audioSessionId);
reply->writeStrongBinder(IInterface::asBinder(player));
return NO_ERROR;
} break;
//...
onTransact()就是根据code的值调用不同的函数。正如前面在分析BpBinder的transact函数时所提到的,code的值决定BBinder受到数据后会做什么样的处理。从这里就可以看出Binder通信其实就是远程过程调用的过程。