(轉載)Binder系列6—獲取服務(getService)

原文鏈接:Binder系列6—獲取服務(getService) - CSDN博客

一、 獲取服務

在Native層的服務注冊,我們選擇以media為例來展開講解,先來看看media的類關系圖。

1.1 類圖

mediaplayerservice類圖

圖解:

????藍色: 代表獲取MediaPlayerService服務相關的類;

????綠色: 代表Binder架構中與Binder驅動通信過程中的最為核心的兩個類;

????紫色: 代表注冊服務和獲取服務的公共接口/父類;

二. 獲取Media服務

2.1 getMediaPlayerService

[-> framework/av/media/libmedia/IMediaDeathNotifier.cpp]

sp<IMediaPlayerService>&

IMediaDeathNotifier::getMediaPlayerService()

{

? ? Mutex::Autolock _l(sServiceLock);

? ? if (sMediaPlayerService == 0) {

? ? ? ? sp<IServiceManager> sm = defaultServiceManager(); //獲取ServiceManager

? ? ? ? sp<IBinder> binder;

? ? ? ? do {

? ? ? ? ? ? //獲取名為"media.player"的服務 【見2.2】

? ? ? ? ? ? binder = sm->getService(String16("media.player"));

? ? ? ? ? ? if (binder != 0) {

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }

? ? ? ? ? ? usleep(500000); // 0.5s

? ? ? ? } while (true);

? ? ? ? if (sDeathNotifier == NULL) {

? ? ? ? ? ? sDeathNotifier = new DeathNotifier(); //創(chuàng)建死亡通知對象

? ? ? ? }

? ? ? ? //將死亡通知連接到binder 【見流程14】

? ? ? ? binder->linkToDeath(sDeathNotifier);

? ? ? ? sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);

? ? }

? ? return sMediaPlayerService;

}

其中defaultServiceManager()過程在上一篇文章獲取ServiceManager已講過,返回BpServiceManager。

在請求獲取名為”media.player”的服務過程中,采用不斷循環(huán)獲取的方法。由于MediaPlayerService服務可能還沒向ServiceManager注冊完成或者尚未啟動完成等情況,故則binder返回為NULL,休眠0.5s后繼續(xù)請求,直到獲取服務為止。

2.2 BpSM.getService

[-> IServiceManager.cpp ::BpServiceManager]

virtual sp<IBinder> getService(const String16& name) const

? ? {

? ? ? ? unsigned n;

? ? ? ? for (n = 0; n < 5; n++){

? ? ? ? ? ? sp<IBinder> svc = checkService(name); //【見2.3】

? ? ? ? ? ? if (svc != NULL) return svc;

? ? ? ? ? ? sleep(1);

? ? ? ? }

? ? ? ? return NULL;

? ? }

通過BpServiceManager來獲取MediaPlayer服務:檢索服務是否存在,當服務存在則返回相應的服務,當服務不存在則休眠1s再繼續(xù)檢索服務。該循環(huán)進行5次。為什么是循環(huán)5次呢,這估計跟Android的ANR時間為5s相關。如果每次都無法獲取服務,循環(huán)5次,每次循環(huán)休眠1s,忽略checkService()的時間,差不多就是5s的時間。

2.3 BpSM.checkService

[-> IServiceManager.cpp ::BpServiceManager]

virtual sp<IBinder> checkService( const String16& name) const

{

? ? Parcel data, reply;

? ? //寫入RPC頭

? ? data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

? ? //寫入服務名

? ? data.writeString16(name);

? ? remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); //【見2.4】

? ? return reply.readStrongBinder(); //【見小節(jié)2.9】

}

檢索指定服務是否存在, 其中remote()為BpBinder。

2.4 BpBinder::transact

[-> BpBinder.cpp]

status_t BpBinder::transact(

? ? uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

? ? if (mAlive) {

? ? ? ? //【見流程2.5】

? ? ? ? status_t status = IPCThreadState::self()->transact(

? ? ? ? ? ? mHandle, code, data, reply, flags);

? ? ? ? if (status == DEAD_OBJECT) mAlive = 0;

? ? ? ? return status;

? ? }

? ? return DEAD_OBJECT;

}

Binder代理類調用transact()方法,真正工作還是交給IPCThreadState來進行transact工作,

2.4.1 IPCThreadState::self

[-> IPCThreadState.cpp]

IPCThreadState* IPCThreadState::self()

{

? ? if (gHaveTLS) {

restart:

? ? ? ? const pthread_key_t k = gTLS;

? ? ? ? IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);

? ? ? ? if (st) return st;

? ? ? ? return new IPCThreadState;? //初始IPCThreadState 【見小節(jié)2.4.2】

? ? }

? ? if (gShutdown) return NULL;

? ? pthread_mutex_lock(&gTLSMutex);

? ? if (!gHaveTLS) { //首次進入gHaveTLS為false

? ? ? ? if (pthread_key_create(&gTLS, threadDestructor) != 0) { //創(chuàng)建線程的TLS

? ? ? ? ? ? pthread_mutex_unlock(&gTLSMutex);

? ? ? ? ? ? return NULL;

? ? ? ? }

? ? ? ? gHaveTLS = true;

? ? }

? ? pthread_mutex_unlock(&gTLSMutex);

? ? goto restart;

}

TLS是指Thread local storage(線程本地儲存空間),每個線程都擁有自己的TLS,并且是私有空間,線程之間不會共享。通過pthread_getspecific/pthread_setspecific函數可以獲取/設置這些空間中的內容。從線程本地存儲空間中獲得保存在其中的IPCThreadState對象。

2.4.2 IPCThreadState初始化

[-> IPCThreadState.cpp]

IPCThreadState::IPCThreadState()

? ? : mProcess(ProcessState::self()),

? ? ? mMyThreadId(gettid()),

? ? ? mStrictModePolicy(0),

? ? ? mLastTransactionBinderFlags(0)

{

? ? pthread_setspecific(gTLS, this);

? ? clearCaller();

? ? mIn.setDataCapacity(256);

? ? mOut.setDataCapacity(256);

}

每個線程都有一個IPCThreadState,每個IPCThreadState中都有一個mIn、一個mOut。成員變量mProcess保存了ProcessState變量(每個進程只有一個)。

????mIn 用來接收來自Binder設備的數據,默認大小為256字節(jié);

????mOut用來存儲發(fā)往Binder設備的數據,默認大小為256字節(jié)。

2.5 IPC::transact

[-> IPCThreadState.cpp]

status_t IPCThreadState::transact(int32_t handle,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uint32_t code, const Parcel& data,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Parcel* reply, uint32_t flags)

{

? ? status_t err = data.errorCheck(); //數據錯誤檢查

? ? flags |= TF_ACCEPT_FDS;

? ? ....

? ? if (err == NO_ERROR) {

? ? ? ? // 傳輸數據 【見流程2.6】

? ? ? ? err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);

? ? }

? ? if (err != NO_ERROR) {

? ? ? ? if (reply) reply->setError(err);

? ? ? ? return (mLastError = err);

? ? }

? ? if ((flags & TF_ONE_WAY) == 0) { //flags=0進入該分支

? ? ? ? if (reply) {

? ? ? ? ? ? //等待響應 【見流程2.7】

? ? ? ? ? ? err = waitForResponse(reply);

? ? ? ? } else {

? ? ? ? ? ? Parcel fakeReply;

? ? ? ? ? ? err = waitForResponse(&fakeReply);

? ? ? ? }

? ? } else {

? ? ? ? //不需要響應消息的binder則進入該分支

? ? ? ? err = waitForResponse(NULL, NULL);

? ? }

? ? return err;

}

2.6 IPC.writeTransactionData

[-> IPCThreadState.cpp]

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.ptr = 0;

? ? tr.target.handle = handle; // handle = 0

? ? tr.code = code;? ? ? ? ? ? // code = CHECK_SERVICE_TRANSACTION

? ? tr.flags = binderFlags;? ? // binderFlags = 0

? ? tr.cookie = 0;

? ? tr.sender_pid = 0;

? ? tr.sender_euid = 0;

? ? // data為記錄Media服務信息的Parcel對象

? ? const status_t err = data.errorCheck();

? ? if (err == NO_ERROR) {

? ? ? ? tr.data_size = data.ipcDataSize();? // mDataSize

? ? ? ? tr.data.ptr.buffer = data.ipcData(); //mData

? ? ? ? tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t); //mObjectsSize

? ? ? ? tr.data.ptr.offsets = data.ipcObjects(); //mObjects

? ? } else if (statusBuffer) {

? ? ? ? ...

? ? } else {

? ? ? ? return (mLastError = err);

? ? }

? ? mOut.writeInt32(cmd);? ? ? ? //cmd = BC_TRANSACTION

? ? mOut.write(&tr, sizeof(tr));? //寫入binder_transaction_data數據

? ? return NO_ERROR;

}

其中handle的值用來標識目的端,注冊服務過程的目的端為service manager,此處handle=0所對應的是binder_context_mgr_node對象,正是service manager所對應的binder實體對象。binder_transaction_data結構體是binder驅動通信的數據結構,該過程最終是把Binder請求碼BC_TRANSACTION和binder_transaction_data結構體寫入到mOut。

2.7 IPC.waitForResponse

[-> 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; // 【見流程2.8】

? ? ? ? err = mIn.errorCheck();

? ? ? ? if (err < NO_ERROR) break;

? ? ? ? if (mIn.dataAvail() == 0) continue;

? ? ? ? cmd = mIn.readInt32();

? ? ? ? switch (cmd) {

? ? ? ? ? ? case BR_TRANSACTION_COMPLETE: ...

? ? ? ? ? ? case BR_DEAD_REPLY: ...

? ? ? ? ? ? case BR_FAILED_REPLY: ...

? ? ? ? ? ? case BR_ACQUIRE_RESULT: ...

? ? ? ? ? ? case BR_REPLY:

? ? ? ? ? ? {

? ? ? ? ? ? ? binder_transaction_data tr;

? ? ? ? ? ? ? err = mIn.read(&tr, sizeof(tr));

? ? ? ? ? ? ? if (reply) {

? ? ? ? ? ? ? ? ? if ((tr.flags & TF_STATUS_CODE) == 0) {

? ? ? ? ? ? ? ? ? ? ? reply->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);

? ? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? ? ...

? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? goto finish;

? ? ? ? ? ? default:

? ? ? ? ? ? ? ? err = executeCommand(cmd);

? ? ? ? ? ? ? ? if (err != NO_ERROR) goto finish;

? ? ? ? ? ? ? ? break;

? ? ? ? }

? ? }

? ? ...

? ? return err;

}

2.8 IPC.talkWithDriver

[-> IPCThreadState.cpp]

status_t IPCThreadState::talkWithDriver(bool doReceive)

{

? ? ...

? ? binder_write_read bwr;

? ? const bool needRead = mIn.dataPosition() >= mIn.dataSize();

? ? const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

? ? bwr.write_size = outAvail;

? ? bwr.write_buffer = (uintptr_t)mOut.data();

? ? if (doReceive && needRead) {

? ? ? ? //接收數據緩沖區(qū)信息的填充。如果以后收到數據,就直接填在mIn中了。

? ? ? ? bwr.read_size = mIn.dataCapacity();

? ? ? ? bwr.read_buffer = (uintptr_t)mIn.data();

? ? } else {

? ? ? ? bwr.read_size = 0;

? ? ? ? bwr.read_buffer = 0;

? ? }

? ? //當讀緩沖和寫緩沖都為空,則直接返回

? ? if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;

? ? bwr.write_consumed = 0;

? ? bwr.read_consumed = 0;

? ? status_t err;

? ? do {

? ? ? ? //通過ioctl不停的讀寫操作,跟Binder Driver進行通信【2.8.1】

? ? ? ? if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)

? ? ? ? ? ? err = NO_ERROR;

? ? ? ? ...

? ? } while (err == -EINTR); //當被中斷,則繼續(xù)執(zhí)行

? ? ...

? ? return err;

}

binder_write_read結構體用來與Binder設備交換數據的結構, 通過ioctl與mDriverFD通信,是真正與Binder驅動進行數據讀寫交互的過程。 先向service manager進程發(fā)送查詢服務的請求(BR_TRANSACTION),見Binder系列3—啟動ServiceManager。當service manager進程收到該命令后,會執(zhí)行do_find_service() 查詢服務所對應的handle,然后再binder_send_reply()應答 發(fā)起者,發(fā)送BC_REPLY協(xié)議,然后調用binder_transaction(),再向服務請求者的Todo隊列 插入事務。

接下來,再看看binder_transaction過程。

2.8.1 binder_transaction

static void binder_transaction(struct binder_proc *proc,

? ? ? ? ? ? ? struct binder_thread *thread,

? ? ? ? ? ? ? struct binder_transaction_data *tr, int reply){

? ? //根據各種判定,獲取以下信息:

? ? struct binder_thread *target_thread; //目標線程

? ? struct binder_proc *target_proc;? ? //目標進程

? ? struct binder_node *target_node;? ? //目標binder節(jié)點

? ? struct list_head *target_list;? ? ? //目標TODO隊列

? ? wait_queue_head_t *target_wait;? ? //目標等待隊列

? ? ...

? ? //分配兩個結構體內存

? ? struct binder_transaction *t = kzalloc(sizeof(*t), GFP_KERNEL);

? ? struct binder_work *tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);

? ? //從target_proc分配一塊buffer

? ? t->buffer = binder_alloc_buf(target_proc, tr->data_size,

? ? for (; offp < off_end; offp++) {

? ? ? ? switch (fp->type) {

? ? ? ? case BINDER_TYPE_BINDER: ...

? ? ? ? case BINDER_TYPE_WEAK_BINDER: ...

? ? ? ? case BINDER_TYPE_HANDLE:

? ? ? ? case BINDER_TYPE_WEAK_HANDLE: {

? ? ? ? ? struct binder_ref *ref = binder_get_ref(proc, fp->handle,

? ? ? ? ? ? ? ? fp->type == BINDER_TYPE_HANDLE);

? ? ? ? ? ...

? ? ? ? ? //此時運行在servicemanager進程,故ref->node是指向服務所在進程的binder實體,

? ? ? ? ? //而target_proc為請求服務所在的進程,此時并不相等。

? ? ? ? ? if (ref->node->proc == target_proc) {

? ? ? ? ? ? if (fp->type == BINDER_TYPE_HANDLE)

? ? ? ? ? ? ? fp->type = BINDER_TYPE_BINDER;

? ? ? ? ? ? else

? ? ? ? ? ? ? fp->type = BINDER_TYPE_WEAK_BINDER;

? ? ? ? ? ? fp->binder = ref->node->ptr;

? ? ? ? ? ? fp->cookie = ref->node->cookie; //BBinder服務的地址

? ? ? ? ? ? binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);

? ? ? ? ? } else {

? ? ? ? ? ? struct binder_ref *new_ref;

? ? ? ? ? ? //請求服務所在進程并非服務所在進程,則為請求服務所在進程創(chuàng)建binder_ref

? ? ? ? ? ? new_ref = binder_get_ref_for_node(target_proc, ref->node);

? ? ? ? ? ? fp->binder = 0;

? ? ? ? ? ? fp->handle = new_ref->desc; //重新賦予handle值

? ? ? ? ? ? fp->cookie = 0;

? ? ? ? ? ? binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);

? ? ? ? ? }

? ? ? ? } break;

? ? ? ? case BINDER_TYPE_FD: ...

? ? ? ? }

? ? }

? ? //分別target_list和當前線程TODO隊列插入事務

? ? t->work.type = BINDER_WORK_TRANSACTION;

? ? list_add_tail(&t->work.entry, target_list);

? ? tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;

? ? list_add_tail(&tcomplete->entry, &thread->todo);

? ? if (target_wait)

? ? ? ? wake_up_interruptible(target_wait);

? ? return;

}

這個過程非常重要,分兩種情況來說:

????當請求服務的進程與服務屬于不同進程,則為請求服務所在進程創(chuàng)建binder_ref對象,指向服務進程中的binder_node;

????當請求服務的進程與服務屬于同一進程,則不再創(chuàng)建新對象,只是引用計數加1,并且修改type為BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER。

2.8.2 binder_thread_read

binder_thread_read(...){

? ? ...

? ? //當線程todo隊列有數據則執(zhí)行往下執(zhí)行;當線程todo隊列沒有數據,則進入休眠等待狀態(tài)

? ? ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));

? ? ...

? ? while (1) {

? ? ? ? uint32_t cmd;

? ? ? ? struct binder_transaction_data tr;

? ? ? ? struct binder_work *w;

? ? ? ? struct binder_transaction *t = NULL;

? ? ? ? //先從線程todo隊列獲取事務數據

? ? ? ? if (!list_empty(&thread->todo)) {

? ? ? ? ? ? w = list_first_entry(&thread->todo, struct binder_work, entry);

? ? ? ? // 線程todo隊列沒有數據, 則從進程todo對獲取事務數據

? ? ? ? } else if (!list_empty(&proc->todo) && wait_for_proc_work) {

? ? ? ? ? ? ...

? ? ? ? }

? ? ? ? switch (w->type) {

? ? ? ? ? ? case BINDER_WORK_TRANSACTION:

? ? ? ? ? ? ? ? //獲取transaction數據

? ? ? ? ? ? ? ? t = container_of(w, struct binder_transaction, work);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case : ...?

? ? ? ? }

? ? ? ? //只有BINDER_WORK_TRANSACTION命令才能繼續(xù)往下執(zhí)行

? ? ? ? if (!t) continue;

? ? ? ? if (t->buffer->target_node) {

? ? ? ? ? ? ...

? ? ? ? } else {

? ? ? ? ? ? tr.target.ptr = NULL;

? ? ? ? ? ? tr.cookie = NULL;

? ? ? ? ? ? cmd = BR_REPLY; //設置命令為BR_REPLY

? ? ? ? }

? ? ? ? tr.code = t->code;

? ? ? ? tr.flags = t->flags;

? ? ? ? tr.sender_euid = t->sender_euid;

? ? ? ? if (t->from) {

? ? ? ? ? ? struct task_struct *sender = t->from->proc->tsk;

? ? ? ? ? ? //當非oneway的情況下,將調用者進程的pid保存到sender_pid

? ? ? ? ? ? tr.sender_pid = task_tgid_nr_ns(sender, current->nsproxy->pid_ns);

? ? ? ? } else {

? ? ? ? ? ? ...

? ? ? ? }

? ? ? ? tr.data_size = t->buffer->data_size;

? ? ? ? tr.offsets_size = t->buffer->offsets_size;

? ? ? ? tr.data.ptr.buffer = (void *)t->buffer->data +

? ? ? ? ? ? ? ? ? ? proc->user_buffer_offset;

? ? ? ? tr.data.ptr.offsets = tr.data.ptr.buffer +

? ? ? ? ? ? ? ? ? ? ALIGN(t->buffer->data_size,

? ? ? ? ? ? ? ? ? ? ? ? sizeof(void *));

? ? ? ? //將cmd和數據寫回用戶空間

? ? ? ? put_user(cmd, (uint32_t __user *)ptr);

? ? ? ? ptr += sizeof(uint32_t);

? ? ? ? copy_to_user(ptr, &tr, sizeof(tr));

? ? ? ? ptr += sizeof(tr);

? ? ? ? list_del(&t->work.entry);

? ? ? ? t->buffer->allow_user_free = 1;

? ? ? ? if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {

? ? ? ? ? ? ...

? ? ? ? } else {

? ? ? ? ? ? t->buffer->transaction = NULL;

? ? ? ? ? ? kfree(t); //通信完成則運行釋放

? ? ? ? }

? ? ? ? break;

? ? }

done:

? ? *consumed = ptr - buffer;

? ? if (proc->requested_threads + proc->ready_threads == 0 &&

? ? ? ? proc->requested_threads_started < proc->max_threads &&

? ? ? ? (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |

? ? ? ? BINDER_LOOPER_STATE_ENTERED))) {

? ? ? ? proc->requested_threads++;

? ? ? ? // 生成BR_SPAWN_LOOPER命令,用于創(chuàng)建新的線程

? ? ? ? put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer);

? ? }

? ? return 0;

}

2.9 readStrongBinder

[-> Parcel.cpp]

sp<IBinder> Parcel::readStrongBinder() const

{

? ? sp<IBinder> val;

? ? //【見小節(jié)2.9.1】

? ? unflatten_binder(ProcessState::self(), *this, &val);

? ? return val;

}

2.9.1 unflatten_binder

[-> Parcel.cpp]

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_BINDER:

? ? ? ? ? ? ? ? // 當請求服務的進程與服務屬于同一進程

? ? ? ? ? ? ? ? *out = reinterpret_cast<IBinder*>(flat->cookie);

? ? ? ? ? ? ? ? return finish_unflatten_binder(NULL, *flat, in);

? ? ? ? ? ? case BINDER_TYPE_HANDLE:

? ? ? ? ? ? ? ? //請求服務的進程與服務屬于不同進程【見2.9.2】

? ? ? ? ? ? ? ? *out = proc->getStrongProxyForHandle(flat->handle);

? ? ? ? ? ? ? ? //創(chuàng)建BpBinder對象

? ? ? ? ? ? ? ? return finish_unflatten_binder(

? ? ? ? ? ? ? ? ? ? static_cast<BpBinder*>(out->get()), *flat, in);

? ? ? ? }

? ? }

? ? return BAD_TYPE;

}

2.9.2 getStrongProxyForHandle

[-> ProcessState.cpp]

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)

{

? ? sp<IBinder> result;

? ? AutoMutex _l(mLock);

? ? //查找handle對應的資源項[2.9.3]

? ? handle_entry* e = lookupHandleLocked(handle);

? ? if (e != NULL) {

? ? ? ? IBinder* b = e->binder;

? ? ? ? if (b == NULL || !e->refs->attemptIncWeak(this)) {

? ? ? ? ? ? ...

? ? ? ? ? ? //當handle值所對應的IBinder不存在或弱引用無效時,則創(chuàng)建BpBinder對象

? ? ? ? ? ? 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的功能是flat_binder_object解析并創(chuàng)建BpBinder對象。

2.9.3 lookupHandleLocked

ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)

{

? ? const size_t N=mHandleToObject.size();

? ? //當handle大于mHandleToObject的長度時,進入該分支

? ? if (N <= (size_t)handle) {

? ? ? ? handle_entry e;

? ? ? ? e.binder = NULL;

? ? ? ? e.refs = NULL;

? ? ? ? //從mHandleToObject的第N個位置開始,插入(handle+1-N)個e到隊列中

? ? ? ? status_t err = mHandleToObject.insertAt(e, N, handle+1-N);

? ? ? ? if (err < NO_ERROR) return NULL;

? ? }

? ? return &mHandleToObject.editItemAt(handle);

}

根據handle值來查找對應的handle_entry。

二. 總結

請求服務(getService)過程,就是向servicemanager進程查詢指定服務,當執(zhí)行binder_transaction()時,會區(qū)分請求服務所屬進程情況。

? ? 1. 當請求服務的進程與服務屬于不同進程,則為請求服務所在進程創(chuàng)建binder_ref對象,指向服務進程中的binder_node;

? ? ? ? 1. 最終readStrongBinder(),返回的是BpBinder對象;

? ? 2. 當請求服務的進程與服務屬于同一進程,則不再創(chuàng)建新對象,只是引用計數加1,并且修改type為BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER。

? ? ? ? ?1. 最終readStrongBinder(),返回的是BBinder對象的真實子類;

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容