原文鏈接:Binder系列6—獲取服務(getService) - CSDN博客
一、 獲取服務
在Native層的服務注冊,我們選擇以media為例來展開講解,先來看看media的類關系圖。
1.1 類圖

圖解:
????藍色: 代表獲取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對象的真實子類;