(轉(zhuǎn)載)Binder系列5—注冊(cè)服務(wù)(addService)

原文鏈接:Binder系列5—注冊(cè)服務(wù)(addService) - CSDN博客

framework/native/libs/binder/

? - Binder.cpp

? - BpBinder.cpp

? - IPCThreadState.cpp

? - ProcessState.cpp

? - IServiceManager.cpp

? - IInterface.cpp

? - Parcel.cpp

frameworks/native/include/binder/

? - IInterface.h (包括BnInterface, BpInterface)

一.概述

1.1 media服務(wù)注冊(cè)

media入口函數(shù)是main_mediaserver.cpp中的main()方法,代碼如下:

int main(int argc __unused, char** argv)

{

? ? ...

? ? InitializeIcuOrDie();

? ? //獲得ProcessState實(shí)例對(duì)象【見(jiàn)小節(jié)2.1】

? ? sp<ProcessState> proc(ProcessState::self());

? ? //獲取BpServiceManager對(duì)象

? ? sp<IServiceManager> sm = defaultServiceManager();

? ? AudioFlinger::instantiate();

? ? //注冊(cè)多媒體服務(wù)? 【見(jiàn)小節(jié)3.1】

? ? MediaPlayerService::instantiate();

? ? ResourceManagerService::instantiate();

? ? CameraService::instantiate();

? ? AudioPolicyService::instantiate();

? ? SoundTriggerHwService::instantiate();

? ? RadioService::instantiate();

? ? registerExtensions();

? ? //啟動(dòng)Binder線程池

? ? ProcessState::self()->startThreadPool();

? ? //當(dāng)前線程加入到線程池

? ? IPCThreadState::self()->joinThreadPool();

}

過(guò)程說(shuō)明:

獲取ServiceManager: 講解了defaultServiceManager()返回的是BpServiceManager對(duì)象, 用于跟servicemanager進(jìn)程通信;

理解Binder線程池的管理, 講解了startThreadPool和joinThreadPool過(guò)程.

本文的重點(diǎn)就是講解Native層服務(wù)注冊(cè)的過(guò)程。

1.2 類圖

在Native層的服務(wù)以media服務(wù)為例,來(lái)說(shuō)一說(shuō)服務(wù)注冊(cè)過(guò)程,先來(lái)看看media的整個(gè)的類關(guān)系圖。?

Binder框架類圖

圖解:

藍(lán)色代表的是注冊(cè)MediaPlayerService服務(wù)所涉及的類;

綠色代表的是Binder架構(gòu)中與Binder驅(qū)動(dòng)通信過(guò)程中的最為核心的兩個(gè)類;

紫色代表的是注冊(cè)服務(wù)和獲取服務(wù)的公共接口/父類;

1.3 時(shí)序圖

先通過(guò)一幅圖來(lái)說(shuō)說(shuō),media服務(wù)啟動(dòng)過(guò)程是如何向servicemanager注冊(cè)服務(wù)的。

media服務(wù)啟動(dòng)過(guò)程

二. ProcessState

2.1 ProcessState::self

[-> ProcessState.cpp]

sp<ProcessState> ProcessState::self()

{

? ? Mutex::Autolock _l(gProcessMutex);

? ? if (gProcess != NULL) {

? ? ? ? return gProcess;

? ? }

? ? //實(shí)例化ProcessState 【見(jiàn)小節(jié)2.2】

? ? gProcess = new ProcessState;

? ? return gProcess;

}

獲得ProcessState對(duì)象: 這也是單例模式,從而保證每一個(gè)進(jìn)程只有一個(gè)ProcessState對(duì)象。其中g(shù)Process和gProcessMutex是保存在Static.cpp類的全局變量。

2.2 ProcessState初始化

[-> ProcessState.cpp]

ProcessState::ProcessState()

? ? : mDriverFD(open_driver()) // 打開(kāi)Binder驅(qū)動(dòng)【見(jiàn)小節(jié)2.3】

? ? , mVMStart(MAP_FAILED)

? ? , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)

? ? , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)

? ? , mExecutingThreadsCount(0)

? ? , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)

? ? , mManagesContexts(false)

? ? , mBinderContextCheckFunc(NULL)

? ? , mBinderContextUserData(NULL)

? ? , mThreadPoolStarted(false)

? ? , mThreadPoolSeq(1)

{

? ? if (mDriverFD >= 0) {

? ? ? ? //采用內(nèi)存映射函數(shù)mmap,給binder分配一塊虛擬地址空間【見(jiàn)小節(jié)2.4】

? ? ? ? mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

? ? ? ? if (mVMStart == MAP_FAILED) {

? ? ? ? ? ? close(mDriverFD); //沒(méi)有足夠空間分配給/dev/binder,則關(guān)閉驅(qū)動(dòng)

? ? ? ? ? ? mDriverFD = -1;

? ? ? ? }

? ? }

}

1. ProcessState的單例模式的惟一性,因此一個(gè)進(jìn)程只打開(kāi)binder設(shè)備一次,其中ProcessState的成員變量mDriverFD記錄binder驅(qū)動(dòng)的fd,用于訪問(wèn)binder設(shè)備。

2. BINDER_VM_SIZE = (1*1024*1024) - (4096 *2), binder分配的默認(rèn)內(nèi)存大小為1M-8k。

3. DEFAULT_MAX_BINDER_THREADS = 15,binder默認(rèn)的最大可并發(fā)訪問(wèn)的線程數(shù)為16。

2.3 open_driver

[-> ProcessState.cpp]

static int open_driver()

{

? ? // 打開(kāi)/dev/binder設(shè)備,建立與內(nèi)核的Binder驅(qū)動(dòng)的交互通道

? ? int fd = open("/dev/binder", O_RDWR);

? ? if (fd >= 0) {

? ? ? ? fcntl(fd, F_SETFD, FD_CLOEXEC);

? ? ? ? int vers = 0;

? ? ? ? status_t result = ioctl(fd, BINDER_VERSION, &vers);

? ? ? ? if (result == -1) {

? ? ? ? ? ? close(fd);

? ? ? ? ? ? fd = -1;

? ? ? ? }

? ? ? ? if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {

? ? ? ? ? ? close(fd);

? ? ? ? ? ? fd = -1;

? ? ? ? }

? ? ? ? size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;

? ? ? ? // 通過(guò)ioctl設(shè)置binder驅(qū)動(dòng),能支持的最大線程數(shù)

? ? ? ? result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);

? ? ? ? if (result == -1) {

? ? ? ? ? ? ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));

? ? ? ? }

? ? } else {

? ? ? ? ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));

? ? }

? ? return fd;

}

open_driver作用是打開(kāi)/dev/binder設(shè)備,設(shè)定binder支持的最大線程數(shù)。關(guān)于binder驅(qū)動(dòng)的相應(yīng)方法,見(jiàn)文章Binder Driver初探

ProcessState采用單例模式,保證每一個(gè)進(jìn)程都只打開(kāi)一次Binder Driver。

2.4 mmap

//原型

void*?mmap(void* addr, size_t size,?int?prot,?int?flags,?int?fd, off_t offset)?//此處?mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD,?0);

參數(shù)說(shuō)明:

addr: 代表映射到進(jìn)程地址空間的起始地址,當(dāng)值等于0則由內(nèi)核選擇合適地址,此處為0;

size: 代表需要映射的內(nèi)存地址空間的大小,此處為1M-8K;

prot: 代表內(nèi)存映射區(qū)的讀寫等屬性值,此處為PROT_READ(可讀取);

flags: 標(biāo)志位,此處為MAP_PRIVATE(私有映射,多進(jìn)程間不共享內(nèi)容的改變)和 MAP_NORESERVE(不保留交換空間)

fd: 代表mmap所關(guān)聯(lián)的文件描述符,此處為mDriverFD;

offset:偏移量,此處為0。

mmap()經(jīng)過(guò)系統(tǒng)調(diào)用,執(zhí)行binder_mmap過(guò)程。

三. 服務(wù)注冊(cè)

3.1 instantiate

[-> MediaPlayerService.cpp]

void MediaPlayerService::instantiate() {

? ? //注冊(cè)服務(wù)【見(jiàn)小節(jié)3.2】

? ? defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());

}

注冊(cè)服務(wù)MediaPlayerService:由defaultServiceManager()返回的是BpServiceManager,同時(shí)會(huì)創(chuàng)建ProcessState對(duì)象和BpBinder對(duì)象。 故此處等價(jià)于調(diào)用BpServiceManager->addService。其中MediaPlayerService位于libmediaplayerservice庫(kù)。

3.2 BpSM.addService

[-> IServiceManager.cpp ::BpServiceManager]

virtual?status_t?addService(const?String16& name,?const?sp<IBinder>& service,?bool?allowIsolated)?{

? ? Parcel data, reply; //Parcel是數(shù)據(jù)通信包

? ? //寫入頭信息"android.os.IServiceManager"

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

? ? data.writeString16(name);? ? ? ? // name為 "media.player"

? ? data.writeStrongBinder(service); // MediaPlayerService對(duì)象【見(jiàn)小節(jié)3.2.1】

? ? data.writeInt32(allowIsolated ? 1 : 0); // allowIsolated= false

? ? //remote()指向的是BpBinder對(duì)象【見(jiàn)小節(jié)3.3】

? ? status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);

? ? return err == NO_ERROR ? reply.readExceptionCode() : err;

}

服務(wù)注冊(cè)過(guò)程:向ServiceManager注冊(cè)服務(wù)MediaPlayerService,服務(wù)名為”media.player”;

3.2.1 writeStrongBinder

[-> parcel.cpp]

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)

{

? ? return flatten_binder(ProcessState::self(), val, this);

}

3.2.2 flatten_binder

[-> parcel.cpp]

status_t flatten_binder(const sp<ProcessState>& /*proc*/,

? ? const sp<IBinder>& binder, Parcel* out)

{

? ? flat_binder_object obj;

? ? obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;

? ? if (binder != NULL) {

? ? ? ? IBinder *local = binder->localBinder(); //本地Binder不為空

? ? ? ? if (!local) {

? ? ? ? ? ? BpBinder *proxy = binder->remoteBinder();

? ? ? ? ? ? const int32_t handle = proxy ? proxy->handle() : 0;

? ? ? ? ? ? obj.type = BINDER_TYPE_HANDLE;

? ? ? ? ? ? obj.binder = 0;

? ? ? ? ? ? obj.handle = handle;

? ? ? ? ? ? obj.cookie = 0;

? ? ? ? } else { //進(jìn)入該分支

? ? ? ? ? ? obj.type = BINDER_TYPE_BINDER;

? ? ? ? ? ? obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());

? ? ? ? ? ? obj.cookie = reinterpret_cast<uintptr_t>(local);

? ? ? ? }

? ? } else {

? ? ? ? ...

? ? }

? ? //【見(jiàn)小節(jié)3.2.3】

? ? return finish_flatten_binder(binder, obj, out);

}

將Binder對(duì)象扁平化,轉(zhuǎn)換成flat_binder_object對(duì)象。

? ? 1.?對(duì)于Binder實(shí)體,則cookie記錄Binder實(shí)體的指針;

? ? 2.?對(duì)于Binder代理,則用handle記錄Binder代理的句柄;

關(guān)于localBinder,代碼見(jiàn)Binder.cpp。

BBinder* BBinder::localBinder()

{

? ? return this;

}

BBinder* IBinder::localBinder()

{

? ? return NULL;

}

3.2.3 finish_flatten_binder

inline static status_t finish_flatten_binder(

? ? const sp<IBinder>& , const flat_binder_object& flat, Parcel* out)

{

? ? return out->writeObject(flat, false);

}

將flat_binder_object寫入out。

3.3 BpBinder::transact

[-> BpBinder.cpp]

status_t BpBinder::transact(

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

{

? ? if (mAlive) {

? ? ? ? // code=ADD_SERVICE_TRANSACTION【見(jiàn)小節(jié)3.4】

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

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

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

? ? ? ? return status;

? ? }

? ? return DEAD_OBJECT;

}

Binder代理類調(diào)用transact()方法,真正工作還是交給IPCThreadState來(lái)進(jìn)行transact工作。先來(lái)看看IPCThreadState::self的過(guò)程。

3.3.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àn)小節(jié)3.3.2】

? ? }

? ? if (gShutdown) return NULL;

? ? pthread_mutex_lock(&gTLSMutex);

? ? if (!gHaveTLS) { //首次進(jìn)入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(線程本地儲(chǔ)存空間),每個(gè)線程都擁有自己的TLS,并且是私有空間,線程之間不會(huì)共享。通過(guò)pthread_getspecific/pthread_setspecific函數(shù)可以獲取/設(shè)置這些空間中的內(nèi)容。從線程本地存儲(chǔ)空間中獲得保存在其中的IPCThreadState對(duì)象。

3.3.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);

}

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

????mIn 用來(lái)接收來(lái)自Binder設(shè)備的數(shù)據(jù),默認(rèn)大小為256字節(jié);

????mOut用來(lái)存儲(chǔ)發(fā)往Binder設(shè)備的數(shù)據(jù),默認(rèn)大小為256字節(jié)。

3.4 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(); //數(shù)據(jù)錯(cuò)誤檢查

? ? flags |= TF_ACCEPT_FDS;

? ? ....

? ? if (err == NO_ERROR) { // 傳輸數(shù)據(jù) 【見(jiàn)小節(jié)3.5】

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

? ? }

? ? ...

? ? if ((flags & TF_ONE_WAY) == 0) {

? ? ? ? if (reply) {

? ? ? ? ? ? //等待響應(yīng) 【見(jiàn)小節(jié)3.6】

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

? ? ? ? } else {

? ? ? ? ? ? Parcel fakeReply;

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

? ? ? ? }

? ? } else {

? ? ? ? //oneway,則不需要等待reply的場(chǎng)景

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

? ? }

? ? return err;

}

IPCThreadState進(jìn)行transact事務(wù)處理分3部分:

????errorCheck() //數(shù)據(jù)錯(cuò)誤檢查

????writeTransactionData() // 傳輸數(shù)據(jù)

????waitForResponse() //f等待響應(yīng)

3.5 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 = ADD_SERVICE_TRANSACTION

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

? ? tr.cookie = 0;

? ? tr.sender_pid = 0;

? ? tr.sender_euid = 0;

? ? // data為記錄Media服務(wù)信息的Parcel對(duì)象

? ? 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數(shù)據(jù)

? ? return NO_ERROR;

}

其中handle的值用來(lái)標(biāo)識(shí)目的端,注冊(cè)服務(wù)過(guò)程的目的端為service manager,此處handle=0所對(duì)應(yīng)的是binder_context_mgr_node對(duì)象,正是service manager所對(duì)應(yīng)的binder實(shí)體對(duì)象。binder_transaction_data結(jié)構(gòu)體是binder驅(qū)動(dòng)通信的數(shù)據(jù)結(jié)構(gòu),該過(guò)程最終是把Binder請(qǐng)求碼BC_TRANSACTION和binder_transaction_data結(jié)構(gòu)體寫入到mOut。

transact過(guò)程,先寫完binder_transaction_data數(shù)據(jù),其中Parcel data的重要成員變量:

????mDataSize:保存再data_size,binder_transaction的數(shù)據(jù)大小;

????mData: 保存在ptr.buffer, binder_transaction的數(shù)據(jù)的起始地址;

????mObjectsSize:保存在ptr.offsets_size,記錄著flat_binder_object結(jié)構(gòu)體的個(gè)數(shù);

????mObjects: 保存在offsets, 記錄著flat_binder_object結(jié)構(gòu)體在數(shù)據(jù)偏移量;

接下來(lái)執(zhí)行waitForResponse()方法。

3.6 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; // 【見(jiàn)小節(jié)3.7】

? ? ? ? ...

? ? ? ? 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: ...

? ? ? ? ? ? ? ? goto finish;

? ? ? ? ? ? default:

? ? ? ? ? ? ? ? err = executeCommand(cmd);? //【見(jiàn)小節(jié)3.x】

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

? ? ? ? ? ? ? ? break;

? ? ? ? }

? ? }

? ? ...

? ? return err;

}

在waitForResponse過(guò)程, 首先執(zhí)行BR_TRANSACTION_COMPLETE;另外,目標(biāo)進(jìn)程收到事務(wù)后,處理BR_TRANSACTION事務(wù)。 然后發(fā)送給當(dāng)前進(jìn)程,再執(zhí)行BR_REPLY命令。

3.7 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) {

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

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

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

? ? } else {

? ? ? ? bwr.read_size = 0;

? ? ? ? bwr.read_buffer = 0;

? ? }

? ? //當(dāng)讀緩沖和寫緩沖都為空,則直接返回

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

? ? bwr.write_consumed = 0;

? ? bwr.read_consumed = 0;

? ? status_t err;

? ? do {

? ? ? ? //通過(guò)ioctl不停的讀寫操作,跟Binder Driver進(jìn)行通信

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

? ? ? ? ? ? err = NO_ERROR;

? ? ? ? ...

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

? ? ...

? ? return err;

}

binder_write_read結(jié)構(gòu)體用來(lái)與Binder設(shè)備交換數(shù)據(jù)的結(jié)構(gòu), 通過(guò)ioctl與mDriverFD通信,是真正與Binder驅(qū)動(dòng)進(jìn)行數(shù)據(jù)讀寫交互的過(guò)程。 主要是操作mOut和mIn變量。

ioctl()經(jīng)過(guò)系統(tǒng)調(diào)用后進(jìn)入Binder Driver。

四. Binder Driver

ioctl -> binder_ioctl -> binder_ioctl_write_read

4.1 binder_ioctl_write_read

[-> binder.c]

static int binder_ioctl_write_read(struct file *filp,

? ? ? ? ? ? ? ? unsigned int cmd, unsigned long arg,

? ? ? ? ? ? ? ? struct binder_thread *thread)

{

? ? struct binder_proc *proc = filp->private_data;

? ? void __user *ubuf = (void __user *)arg;

? ? struct binder_write_read bwr;

? ? //將用戶空間bwr結(jié)構(gòu)體拷貝到內(nèi)核空間

? ? copy_from_user(&bwr, ubuf, sizeof(bwr));

? ? ...

? ? if (bwr.write_size > 0) {

? ? ? ? //將數(shù)據(jù)放入目標(biāo)進(jìn)程【見(jiàn)小節(jié)4.2】

? ? ? ? ret = binder_thread_write(proc, thread,

? ? ? ? ? ? ? ? ? ? ? bwr.write_buffer,

? ? ? ? ? ? ? ? ? ? ? bwr.write_size,

? ? ? ? ? ? ? ? ? ? ? &bwr.write_consumed);

? ? ? ? ...

? ? }

? ? if (bwr.read_size > 0) {

? ? ? ? //讀取自己隊(duì)列的數(shù)據(jù) 【見(jiàn)小節(jié)】

? ? ? ? ret = binder_thread_read(proc, thread, bwr.read_buffer,

? ? ? ? ? ? bwr.read_size,

? ? ? ? ? ? &bwr.read_consumed,

? ? ? ? ? ? filp->f_flags & O_NONBLOCK);

? ? ? ? if (!list_empty(&proc->todo))

? ? ? ? ? ? wake_up_interruptible(&proc->wait);

? ? ? ? ...

? ? }

? ? //將內(nèi)核空間bwr結(jié)構(gòu)體拷貝到用戶空間

? ? copy_to_user(ubuf, &bwr, sizeof(bwr));

? ? ...

}?

4.2 binder_thread_write

static int binder_thread_write(struct binder_proc *proc,

? ? ? ? ? ? struct binder_thread *thread,

? ? ? ? ? ? binder_uintptr_t binder_buffer, size_t size,

? ? ? ? ? ? binder_size_t *consumed)

{

? ? uint32_t cmd;

? ? void __user *buffer = (void __user *)(uintptr_t)binder_buffer;

? ? void __user *ptr = buffer + *consumed;

? ? void __user *end = buffer + size;

? ? while (ptr < end && thread->return_error == BR_OK) {

? ? ? ? //拷貝用戶空間的cmd命令,此時(shí)為BC_TRANSACTION

? ? ? ? if (get_user(cmd, (uint32_t __user *)ptr)) -EFAULT;

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

? ? ? ? switch (cmd) {

? ? ? ? case BC_TRANSACTION:

? ? ? ? case BC_REPLY: {

? ? ? ? ? ? struct binder_transaction_data tr;

? ? ? ? ? ? //拷貝用戶空間的binder_transaction_data

? ? ? ? ? ? if (copy_from_user(&tr, ptr, sizeof(tr)))? return -EFAULT;

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

? ? ? ? ? ? // 見(jiàn)小節(jié)4.3】

? ? ? ? ? ? binder_transaction(proc, thread, &tr, cmd == BC_REPLY);

? ? ? ? ? ? break;

? ? ? ? }

? ? ? ? ...

? ? }

? ? *consumed = ptr - buffer;

? }

? return 0;

}

4.3 binder_transaction

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;

? ? ...

? ? if (reply) {

? ? ? ? ...

? ? }else {

? ? ? ? if (tr->target.handle) {

? ? ? ? ? ? ...

? ? ? ? } else {

? ? ? ? ? ? // handle=0則找到servicemanager實(shí)體

? ? ? ? ? ? target_node = binder_context_mgr_node;

? ? ? ? }

? ? ? ? //target_proc為servicemanager進(jìn)程

? ? ? ? target_proc = target_node->proc;

? ? }

? ? if (target_thread) {

? ? ? ? ...

? ? } else {

? ? ? ? //找到servicemanager進(jìn)程的todo隊(duì)列

? ? ? ? target_list = &target_proc->todo;

? ? ? ? target_wait = &target_proc->wait;

? ? }

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

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

? ? //非oneway的通信方式,把當(dāng)前thread保存到transaction的from字段

? ? if (!reply && !(tr->flags & TF_ONE_WAY))

? ? ? ? t->from = thread;

? ? else

? ? ? ? t->from = NULL;

? ? t->sender_euid = task_euid(proc->tsk);

? ? t->to_proc = target_proc; //此次通信目標(biāo)進(jìn)程為servicemanager進(jìn)程

? ? t->to_thread = target_thread;

? ? t->code = tr->code;? //此次通信code = ADD_SERVICE_TRANSACTION

? ? t->flags = tr->flags;? // 此次通信flags = 0

? ? t->priority = task_nice(current);

? ? //從servicemanager進(jìn)程中分配buffer

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

? ? ? ? tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));

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

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

? ? t->buffer->target_node = target_node;

? ? if (target_node)

? ? ? ? binder_inc_node(target_node, 1, 0, NULL); //引用計(jì)數(shù)加1

? ? offp = (binder_size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));

? ? //分別拷貝用戶空間的binder_transaction_data中ptr.buffer和ptr.offsets到內(nèi)核

? ? copy_from_user(t->buffer->data,

? ? ? ? (const void __user *)(uintptr_t)tr->data.ptr.buffer, tr->data_size);

? ? copy_from_user(offp,

? ? ? ? (const void __user *)(uintptr_t)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);

? ? ? ? off_min = *offp + sizeof(struct flat_binder_object);

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

? ? ? ? ? ? case BINDER_TYPE_BINDER:

? ? ? ? ? ? case BINDER_TYPE_WEAK_BINDER: {

? ? ? ? ? ? ? struct binder_ref *ref;

? ? ? ? ? ? ? //【見(jiàn)4.3.1】

? ? ? ? ? ? ? struct binder_node *node = binder_get_node(proc, fp->binder);

? ? ? ? ? ? ? if (node == NULL) {

? ? ? ? ? ? ? ? //服務(wù)所在進(jìn)程 創(chuàng)建binder_node實(shí)體【見(jiàn)4.3.2】

? ? ? ? ? ? ? ? node = binder_new_node(proc, fp->binder, fp->cookie);

? ? ? ? ? ? ? ? ...

? ? ? ? ? ? ? }

? ? ? ? ? ? ? //servicemanager進(jìn)程binder_ref【見(jiàn)4.3.3】

? ? ? ? ? ? ? ref = binder_get_ref_for_node(target_proc, node);

? ? ? ? ? ? ? ...

? ? ? ? ? ? ? //調(diào)整type為HANDLE類型

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

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

? ? ? ? ? ? ? else

? ? ? ? ? ? ? ? fp->type = BINDER_TYPE_WEAK_HANDLE;

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

? ? ? ? ? ? ? fp->handle = ref->desc; //設(shè)置handle值

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

? ? ? ? ? ? ? binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,

? ? ? ? ? ? ? ? ? ? ? &thread->todo);

? ? ? ? ? ? } break;

? ? ? ? ? ? case :...

? ? }

? ? if (reply) {

? ? ? ? ..

? ? } else if (!(t->flags & TF_ONE_WAY)) {

? ? ? ? //BC_TRANSACTION 且 非oneway,則設(shè)置事務(wù)棧信息

? ? ? ? t->need_reply = 1;

? ? ? ? t->from_parent = thread->transaction_stack;

? ? ? ? thread->transaction_stack = t;

? ? } else {

? ? ? ? ...

? ? }

? ? //將BINDER_WORK_TRANSACTION添加到目標(biāo)隊(duì)列,本次通信的目標(biāo)隊(duì)列為target_proc->todo

? ? t->work.type = BINDER_WORK_TRANSACTION;

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

? ? //將BINDER_WORK_TRANSACTION_COMPLETE添加到當(dāng)前線程的todo隊(duì)列

? ? tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;

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

? ? //喚醒等待隊(duì)列,本次通信的目標(biāo)隊(duì)列為target_proc->wait

? ? if (target_wait)

? ? ? ? wake_up_interruptible(target_wait);

? ? return;

}

注冊(cè)服務(wù)的過(guò)程,傳遞的是BBinder對(duì)象,故[小節(jié)3.2.1]的writeStrongBinder()過(guò)程中l(wèi)ocalBinder不為空, 從而flat_binder_object.type等于BINDER_TYPE_BINDER。

服務(wù)注冊(cè)過(guò)程是在服務(wù)所在進(jìn)程創(chuàng)建binder_node,在servicemanager進(jìn)程創(chuàng)建binder_ref。 對(duì)于同一個(gè)binder_node,每個(gè)進(jìn)程只會(huì)創(chuàng)建一個(gè)binder_ref對(duì)象。

向servicemanager的binder_proc->todo添加BINDER_WORK_TRANSACTION事務(wù),接下來(lái)進(jìn)入ServiceManager進(jìn)程。

4.3.1 binder_get_node

static struct binder_node *binder_get_node(struct binder_proc *proc,

? ? ? ? ? ? binder_uintptr_t ptr)

{

? struct rb_node *n = proc->nodes.rb_node;

? struct binder_node *node;

? while (n) {

? ? node = rb_entry(n, struct binder_node, rb_node);

? ? if (ptr < node->ptr)

? ? ? n = n->rb_left;

? ? else if (ptr > node->ptr)

? ? ? n = n->rb_right;

? ? else

? ? ? return node;

? }

? return NULL;

}

從binder_proc來(lái)根據(jù)binder指針ptr值,查詢相應(yīng)的binder_node。

4.3.2 binder_new_node

static struct binder_node *binder_new_node(struct binder_proc *proc,

? ? ? ? ? ? ? ? ? ? ? binder_uintptr_t ptr,

? ? ? ? ? ? ? ? ? ? ? binder_uintptr_t cookie)

{

? ? struct rb_node **p = &proc->nodes.rb_node;

? ? struct rb_node *parent = NULL;

? ? struct binder_node *node;

? ? ... //紅黑樹(shù)位置查找

? ? //給新創(chuàng)建的binder_node 分配內(nèi)核空間

? ? node = kzalloc(sizeof(*node), GFP_KERNEL);

? ? // 將新創(chuàng)建的node添加到proc紅黑樹(shù);

? ? rb_link_node(&node->rb_node, parent, p);

? ? rb_insert_color(&node->rb_node, &proc->nodes);

? ? node->debug_id = ++binder_last_id;

? ? node->proc = proc;

? ? node->ptr = ptr;

? ? node->cookie = cookie;

? ? node->work.type = BINDER_WORK_NODE; //設(shè)置binder_work的type

? ? INIT_LIST_HEAD(&node->work.entry);

? ? INIT_LIST_HEAD(&node->async_todo);

? ? return node;

}

4.3.3 binder_get_ref_for_node

static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,

? ? ? ? ? ? ? struct binder_node *node)

{

? struct rb_node *n;

? struct rb_node **p = &proc->refs_by_node.rb_node;

? struct rb_node *parent = NULL;

? struct binder_ref *ref, *new_ref;

? //從refs_by_node紅黑樹(shù),找到binder_ref則直接返回。

? while (*p) {

? ? parent = *p;

? ? ref = rb_entry(parent, struct binder_ref, rb_node_node);

? ? if (node < ref->node)

? ? ? p = &(*p)->rb_left;

? ? else if (node > ref->node)

? ? ? p = &(*p)->rb_right;

? ? else

? ? ? return ref;

? }

? //創(chuàng)建binder_ref

? new_ref = kzalloc_preempt_disabled(sizeof(*ref));

? new_ref->debug_id = ++binder_last_id;

? new_ref->proc = proc; //記錄進(jìn)程信息

? new_ref->node = node; //記錄binder節(jié)點(diǎn)

? rb_link_node(&new_ref->rb_node_node, parent, p);

? rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);

? //計(jì)算binder引用的handle值,該值返回給target_proc進(jìn)程

? new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1;

? //從紅黑樹(shù)最最左邊的handle對(duì)比,依次遞增,直到紅黑樹(shù)遍歷結(jié)束或者找到更大的handle則結(jié)束。

? for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {

? ? //根據(jù)binder_ref的成員變量rb_node_desc的地址指針n,來(lái)獲取binder_ref的首地址

? ? ref = rb_entry(n, struct binder_ref, rb_node_desc);

? ? if (ref->desc > new_ref->desc)

? ? ? break;

? ? new_ref->desc = ref->desc + 1;

? }

? // 將新創(chuàng)建的new_ref 插入proc->refs_by_desc紅黑樹(shù)

? p = &proc->refs_by_desc.rb_node;

? while (*p) {

? ? parent = *p;

? ? ref = rb_entry(parent, struct binder_ref, rb_node_desc);

? ? if (new_ref->desc < ref->desc)

? ? ? p = &(*p)->rb_left;

? ? else if (new_ref->desc > ref->desc)

? ? ? p = &(*p)->rb_right;

? ? else

? ? ? BUG();

? }

? rb_link_node(&new_ref->rb_node_desc, parent, p);

? rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc);

? if (node) {

? ? hlist_add_head(&new_ref->node_entry, &node->refs);

? }

? return new_ref;

}

handle值計(jì)算方法規(guī)律:

? ??每個(gè)進(jìn)程binder_proc所記錄的binder_ref的handle值是從1開(kāi)始遞增的;

? ??所有進(jìn)程binder_proc所記錄的handle=0的binder_ref都指向service manager;

? ??同一個(gè)服務(wù)的binder_node在不同進(jìn)程的binder_ref的handle值可以不同;

五. ServiceManager

Binder系列3—啟動(dòng)ServiceManager已介紹其原理,循環(huán)在binder_loop()過(guò)程, 會(huì)調(diào)用binder_parse()方法。

5.1 binder_parse

[-> servicemanager/binder.c]

int?binder_parse(struct?binder_state *bs,?struct?binder_io *bio, uintptr_t ptr, size_t size, binder_handler func)?{

? ? int r = 1;

? ? uintptr_t end = ptr + (uintptr_t) size;

? ? while (ptr < end) {

? ? ? ? uint32_t cmd = *(uint32_t *) ptr;

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

? ? ? ? switch(cmd) {

? ? ? ? case BR_TRANSACTION: {

? ? ? ? ? ? struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;

? ? ? ? ? ? ...

? ? ? ? ? ? binder_dump_txn(txn);

? ? ? ? ? ? if (func) {

? ? ? ? ? ? ? ? unsigned rdata[256/4];

? ? ? ? ? ? ? ? struct binder_io msg;

? ? ? ? ? ? ? ? struct binder_io reply;

? ? ? ? ? ? ? ? int res;

? ? ? ? ? ? ? ? bio_init(&reply, rdata, sizeof(rdata), 4);

? ? ? ? ? ? ? ? bio_init_from_txn(&msg, txn); //從txn解析出binder_io信息

? ? ? ? ? ? ? ? // 收到Binder事務(wù) 【見(jiàn)小節(jié)5.2】

? ? ? ? ? ? ? ? res = func(bs, txn, &msg, &reply);

? ? ? ? ? ? ? ? // 發(fā)送reply事件【見(jiàn)小節(jié)5.4】

? ? ? ? ? ? ? ? binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);

? ? ? ? ? ? }

? ? ? ? ? ? ptr += sizeof(*txn);

? ? ? ? ? ? break;

? ? ? ? }

? ? ? ? case : ...

? ? }

? ? return r;

}

5.2 svcmgr_handler

[-> service_manager.c]

int?svcmgr_handler(struct?binder_state *bs,?struct?binder_transaction_data *txn,?struct?binder_io *msg,?struct?binder_io *reply)?{

? ? struct svcinfo *si;

? ? uint16_t *s;

? ? size_t len;

? ? uint32_t handle;

? ? uint32_t strict_policy;

? ? int allow_isolated;

? ? ...

? ? strict_policy = bio_get_uint32(msg);

? ? s = bio_get_string16(msg, &len);

? ? ...

? ? switch(txn->code) {

? ? ? case SVC_MGR_ADD_SERVICE:

? ? ? ? ? s = bio_get_string16(msg, &len);

? ? ? ? ? ...

? ? ? ? ? handle = bio_get_ref(msg); //獲取handle

? ? ? ? ? allow_isolated = bio_get_uint32(msg) ? 1 : 0;

? ? ? ? ? //注冊(cè)指定服務(wù) 【見(jiàn)小節(jié)5.3】

? ? ? ? ? if (do_add_service(bs, s, len, handle, txn->sender_euid,

? ? ? ? ? ? ? allow_isolated, txn->sender_pid))

? ? ? ? ? ? ? return -1;

? ? ? ? ? break;

? ? ? case :...

? ? }

? ? bio_put_uint32(reply, 0);

? ? return 0;

}

5.3 do_add_service

[-> service_manager.c]

int do_add_service(struct binder_state *bs,

? ? ? ? ? ? ? ? ? const uint16_t *s, size_t len,

? ? ? ? ? ? ? ? ? uint32_t handle, uid_t uid, int allow_isolated,

? ? ? ? ? ? ? ? ? pid_t spid)

{

? ? struct svcinfo *si;

? ? if (!handle || (len == 0) || (len > 127))

? ? ? ? return -1;

? ? //權(quán)限檢查

? ? if (!svc_can_register(s, len, spid)) {

? ? ? ? return -1;

? ? }

? ? //服務(wù)檢索

? ? si = find_svc(s, len);

? ? if (si) {

? ? ? ? if (si->handle) {

? ? ? ? ? ? svcinfo_death(bs, si); //服務(wù)已注冊(cè)時(shí),釋放相應(yīng)的服務(wù)

? ? ? ? }

? ? ? ? si->handle = handle;

? ? } else {

? ? ? ? si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));

? ? ? ? if (!si) {? //內(nèi)存不足,無(wú)法分配足夠內(nèi)存

? ? ? ? ? ? return -1;

? ? ? ? }

? ? ? ? si->handle = handle;

? ? ? ? si->len = len;

? ? ? ? memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); //內(nèi)存拷貝服務(wù)信息

? ? ? ? si->name[len] = '\0';

? ? ? ? si->death.func = (void*) svcinfo_death;

? ? ? ? si->death.ptr = si;

? ? ? ? si->allow_isolated = allow_isolated;

? ? ? ? si->next = svclist; // svclist保存所有已注冊(cè)的服務(wù)

? ? ? ? svclist = si;

? ? }

? ? //以BC_ACQUIRE命令,handle為目標(biāo)的信息,通過(guò)ioctl發(fā)送給binder驅(qū)動(dòng)

? ? binder_acquire(bs, handle);

? ? //以BC_REQUEST_DEATH_NOTIFICATION命令的信息,通過(guò)ioctl發(fā)送給binder驅(qū)動(dòng),主要用于清理內(nèi)存等收尾工作。

? ? binder_link_to_death(bs, handle, &si->death);

? ? return 0;

}

svcinfo記錄著服務(wù)名和handle信息,保存到svclist列表。

5.4 binder_send_reply

[-> servicemanager/binder.c]

void?binder_send_reply(struct?binder_state *bs,?struct?binder_io *reply, binder_uintptr_t buffer_to_free,?int?status)?{

? ? struct {

? ? ? ? uint32_t cmd_free;

? ? ? ? binder_uintptr_t buffer;

? ? ? ? uint32_t cmd_reply;

? ? ? ? struct binder_transaction_data txn;

? ? } __attribute__((packed)) data;

? ? data.cmd_free = BC_FREE_BUFFER; //free buffer命令

? ? data.buffer = buffer_to_free;

? ? data.cmd_reply = BC_REPLY; // reply命令

? ? data.txn.target.ptr = 0;

? ? data.txn.cookie = 0;

? ? data.txn.code = 0;

? ? if (status) {

? ? ? ? ...

? ? } else {

? ? ? ? data.txn.flags = 0;

? ? ? ? data.txn.data_size = reply->data - reply->data0;

? ? ? ? data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);

? ? ? ? data.txn.data.ptr.buffer = (uintptr_t)reply->data0;

? ? ? ? data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;

? ? }

? ? //向Binder驅(qū)動(dòng)通信

? ? binder_write(bs, &data, sizeof(data));

}

binder_write進(jìn)入binder驅(qū)動(dòng)后,將BC_FREE_BUFFER和BC_REPLY命令協(xié)議發(fā)送給Binder驅(qū)動(dòng), 向client端發(fā)送reply。

六. 總結(jié)

服務(wù)注冊(cè)過(guò)程(addService)核心功能:在服務(wù)所在進(jìn)程創(chuàng)建binder_node,在servicemanager進(jìn)程創(chuàng)建binder_ref。 其中binder_ref的desc再同一個(gè)進(jìn)程內(nèi)是唯一的:

????每個(gè)進(jìn)程binder_proc所記錄的binder_ref的handle值是從1開(kāi)始遞增的;

????所有進(jìn)程binder_proc所記錄的handle=0的binder_ref都指向service manager;

????同一個(gè)服務(wù)的binder_node在不同進(jìn)程的binder_ref的handle值可以不同;????

Media服務(wù)注冊(cè)的過(guò)程涉及到MediaPlayerService(作為Client進(jìn)程)和Service Manager(作為Service進(jìn)程),通信流程圖如下所示:

通信流程圖

過(guò)程分析:

1. MediaPlayerService進(jìn)程調(diào)用ioctl()向Binder驅(qū)動(dòng)發(fā)送IPC數(shù)據(jù),該過(guò)程可以理解成一個(gè)事務(wù)binder_transaction(記為T1),執(zhí)行當(dāng)前操作的線程binder_thread(記為thread1),則T1->from_parent=NULL,T1->from =thread1,thread1->transaction_stack=T1。其中IPC數(shù)據(jù)內(nèi)容包含:

????Binder協(xié)議為BC_TRANSACTION;

????Handle等于0;

????RPC代碼為ADD_SERVICE;

????RPC數(shù)據(jù)為”media.player”。

2.?Binder驅(qū)動(dòng)收到該Binder請(qǐng)求,生成BR_TRANSACTION命令,選擇目標(biāo)處理該請(qǐng)求的線程,即ServiceManager的binder線程(記為thread2),則 T1->to_parent = NULL,T1->to_thread =thread2。并將整個(gè)binder_transaction數(shù)據(jù)(記為T2)插入到目標(biāo)線程的todo隊(duì)列;

3.?Service Manager的線程thread2收到T2后,調(diào)用服務(wù)注冊(cè)函數(shù)將服務(wù)”media.player”注冊(cè)到服務(wù)目錄中。當(dāng)服務(wù)注冊(cè)完成后,生成IPC應(yīng)答數(shù)據(jù)(BC_REPLY),T2->form_parent = T1,T2->from = thread2, thread2->transaction_stack = T2。

4.?Binder驅(qū)動(dòng)收到該Binder應(yīng)答請(qǐng)求,生成BR_REPLY命令,T2->to_parent = T1,T2->to_thread = thread1, thread1->transaction_stack = T2。 在MediaPlayerService收到該命令后,知道服務(wù)注冊(cè)完成便可以正常使用。

整個(gè)過(guò)程中,BC_TRANSACTION和BR_TRANSACTION過(guò)程是一個(gè)完整的事務(wù)過(guò)程;BC_REPLY和BR_REPLY是一個(gè)完整的事務(wù)過(guò)程。 到此,其他進(jìn)行便可以獲取該服務(wù),使用服務(wù)提供的方法,下一篇文章將會(huì)講述如何獲取服務(wù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,497評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 176,305評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 62,962評(píng)論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,727評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,193評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,411評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,945評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,777評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,978評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,216評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,642評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,878評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,657評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,960評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容