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通信其實就是遠程過程調用的過程。