Generate AudioFlinger Service
media_server程序会启动AudioFlinger服务。相关代码如下:
view plaincopy to clipboard
- // frameworks/base/media/mediaserver/main_mediaserver.cpp
- int main(int argc, char** argv)
{ sp proc(ProcessState::self()); sp sm = defaultServiceManager(); LOGI("ServiceManager: %p", sm.get()); AudioFlinger::instantiate(); MediaPlayerService::instantiate(); CameraService::instantiate(); AudioPolicyService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } AudioFlinger::instantiate()函数会调用IServiceManager::addService远程调用。
view plaincopy to clipboard
- // frameworks/base/libs/audioflinger/AudioFlinger.cpp
- void AudioFlinger::instantiate() {
defaultServiceManager()->addService( String16("media.audio_flinger"), new AudioFlinger()); } AudioFlinger继承自BnAudioFlinger,BnAudioFlinger是一个BnInterface模板类的实例。
view plaincopy to clipboard
- // frameworks/base/include/media/IAudioFlinger.h
- class BnAudioFlinger : public BnInterface
{ public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); }; BnInterface继承自BBinder。
view plaincopy to clipboard
- // frameworks/base/include/binder/IInterface.h
- template
class BnInterface : public INTERFACE, public BBinder { public: virtual sp queryLocalInterface(const String16& _descriptor); virtual const String16& getInterfaceDescriptor() const; protected: virtual IBinder* onAsBinder(); }; template IBinder* BnInterface::onAsBinder() { return this; } 根据BnInterface的实现,我们看到传递给IServiceManager::addService的参数是一个AudioFlinger实例的地址。BBinder继承自IBinder,它的transact()函数调用onTransact虚函数(多态)。
view plaincopy to clipboard
- // frameworks/base/include/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()。BnAudioFlinger实现了该虚函数。在本文的例子中我们只需要关注SET_MODE分支。
view plaincopy to clipboard
- // frameworks/base/media/libmedia/IaudioFlinger.cpp
- status_t BnAudioFlinger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{ switch(code) { …… case SET_MODE: { CHECK_INTERFACE(IAudioFlinger, data, reply); int mode = data.readInt32(); reply->writeInt32( setMode(mode) ); return NO_ERROR; } break; …… } media_server会通过IPCThreadState::joinThreadPool进入一个循环,就像service_manager,它会通过调用talkWithDriver()函数等待其他进程传入数据。
view plaincopy to clipboard
- // frameworks/base/libs/binder/IPCThreadState.cpp
- void IPCThreadState::joinThreadPool(bool isMain)
{ mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); status_t result; do { int32_t cmd; …… // now get the next command to be processed, waiting if necessary result = talkWithDriver(); if (result >= NO_ERROR) { size_t IN = mIn.dataAvail(); if (IN < sizeof(int32_t)) continue; cmd = mIn.readInt32(); IF_LOG_COMMANDS() { alog << "Processing top-level Command: " << getReturnString(cmd) << endl; } result = executeCommand(cmd); } …… } while (result != -ECONNREFUSED && result != -EBADF); mOut.writeInt32(BC_EXIT_LOOPER); talkWithDriver(false); }
假设你想要实现你自己的IFunnyTest服务,必须遵循以下步骤:
- 实现你自己的BnFunnyTest类;
- 在执行你的服务的进程中,调用IPCThreadState::joinThreadPool()函数
RPC Call IServiceManager::addService
当我们调用IServiceManager::addService时,实际上调用的是BpServiceManager::addService。
view plaincopy to clipboard
- // frameworks/base/libs/binder/IServiceManager.cpp
- class BpServiceManager : public BpInterface
{ public: …… virtual status_t addService(const String16& name, const sp& service) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service); status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readInt32() : err; } …… } Parcel类型很简单。我们可以把它认为是一块连续的缓冲区。注意,参数service是指向BBinder对象(AudioFlinger从Bn继承来)的指针。
view plaincopy to clipboard
- // frameworks/base/libs/binder/Parcel.cpp
- status_t Parcel::writeStrongBinder(const sp& val)
{ return flatten_binder(ProcessState::self(), val, this); } flatten_binder会生成一个Binder命令。因为BBinder是一个本地的binder对象,因此该代码分支标为红色。
view plaincopy to clipboard
- // frameworks/base/libs/binder/Parcel.cpp
- status_t flatten_binder(const sp& proc,
const sp& binder, Parcel* out) { flat_binder_object obj; obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; if (binder != NULL) { IBinder *local = binder->localBinder(); if (!local) { BpBinder *proxy = binder->remoteBinder(); if (proxy == NULL) { LOGE("null proxy"); } const int32_t handle = proxy ? proxy->handle() : 0; obj.type = BINDER_TYPE_HANDLE; obj.handle = handle; obj.cookie = NULL; } else { obj.type = BINDER_TYPE_BINDER; obj.binder = local->getWeakRefs(); obj.cookie = local; } } else { obj.type = BINDER_TYPE_BINDER; obj.binder = NULL; obj.cookie = NULL; } return finish_flatten_binder(binder, obj, out); } 注意红色的代码行。本地地址被放入到一个包(以后会用到)中。在该addService远程调用的包构造完成后,BpServiceManager::addService()将会调用BpBinder的transact()函数。
view plaincopy to clipboard
- // frameworks/base/libs/binder/BpBinder.cpp
- status_t BpBinder::transact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{ // Once a binder has died, it will never come back to life. if (mAlive) { status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0; return status; } return DEAD_OBJECT; } BpBinder调用IPCThreadState::transact来根据mHandle启动一个针对binder对象的(处理)事务。在本文的例子中,mHandle为0。
view plaincopy to clipboard
- // frameworks/base/libs/binder/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_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand " << handle << " / code " << TypeCode(code) << ": " << indent << data << dedent << endl; } if (err == NO_ERROR) { LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(), (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY"); 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) { if (reply) { err = waitForResponse(reply); } else { Parcel fakeReply; err = waitForResponse(&fakeReply); } IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand " << handle << ": "; if (reply) alog << indent << *reply << dedent << endl; else alog << "(none requested)" << endl; } } else { err = waitForResponse(NULL, NULL); } return err; } IPCThreadState::transact首先调用writeTransactionData函数为binder内核驱动构造一个transaction结构。注意以下几行,它对于binder内核驱动识别事务(transaction)目标非常重要
view plaincopy to clipboard
- // frameworks/base/libs/binder/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.handle = handle; tr.code = code; tr.flags = binderFlags; const status_t err = data.errorCheck(); if (err == NO_ERROR) { tr.data_size = data.ipcDataSize(); tr.data.ptr.buffer = data.ipcData(); tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t); tr.data.ptr.offsets = data.ipcObjects(); } else if (statusBuffer) { tr.flags |= TF_STATUS_CODE; *statusBuffer = err; tr.data_size = sizeof(status_t); tr.data.ptr.buffer = statusBuffer; tr.offsets_size = 0; tr.data.ptr.offsets = NULL; } else { return (mLastError = err); } mOut.writeInt32(cmd); mOut.write(&tr, sizeof(tr)); return NO_ERROR; } 然后waitForResponse()通过talkWithDriver()函数去调用BINDER_WRITE_READ的ioctl()。
view plaincopy to clipboard
- // frameworks/base/libs/binder/IPCThreadState.cpp
- #if defined(HAVE_ANDROID_OS)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) err = NO_ERROR; else err = -errno; #else 于是到现在为止,事务数据已经发送到了binder内核驱动。
小结:
Proxy(代理)对象会为RPC调用生成必需的包,然后调用BINDER_WRITE_READ将包写入binder内核驱动。该包为格式化的。对于RPC调用,它是BC_TRANSACTION类型的包。
假设你要实现你自己的IFunnyTest的服务,你必须要:
- 在服务运行的进程中调用IServiceManager::addService()函数将服务注册到servier_manger。