拳头暴君蝎子打野天赋:Android-IPC-Binder(2)

来源:百度文库 编辑:偶看新闻 时间:2024/04/30 19:18:57

Generate AudioFlinger Service

media_server程序会启动AudioFlinger服务。相关代码如下:

view plaincopy to clipboard

  1. // frameworks/base/media/mediaserver/main_mediaserver.cpp   
  2. 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

    1. // frameworks/base/libs/audioflinger/AudioFlinger.cpp   
    2. void AudioFlinger::instantiate() {  
  •   defaultServiceManager()->addService(  
  •           String16("media.audio_flinger"), new AudioFlinger());  
  • }  
  • AudioFlinger继承自BnAudioFlinger,BnAudioFlinger是一个BnInterface模板类的实例。

    view plaincopy to clipboard

    1. // frameworks/base/include/media/IAudioFlinger.h   
    2. 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

    1. // frameworks/base/include/binder/IInterface.h   
    2. 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

    1. // frameworks/base/include/binder/Binder.cpp   
    2. 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

    1. // frameworks/base/media/libmedia/IaudioFlinger.cpp   
    2. status_t BnAudioFlinger::onTransact(  
    3.     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

    1. // frameworks/base/libs/binder/IPCThreadState.cpp   
    2. 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

    1. // frameworks/base/libs/binder/IServiceManager.cpp   
    2. 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

    1. // frameworks/base/libs/binder/Parcel.cpp   
    2. status_t Parcel::writeStrongBinder(const sp& val)  
  • {  
  •   return flatten_binder(ProcessState::self(), val, this);  
  • }  
  • flatten_binder会生成一个Binder命令。因为BBinder是一个本地的binder对象,因此该代码分支标为红色。

    view plaincopy to clipboard

    1. // frameworks/base/libs/binder/Parcel.cpp   
    2. 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

    1. // frameworks/base/libs/binder/BpBinder.cpp   
    2. status_t BpBinder::transact(  
    3.     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

    1. // frameworks/base/libs/binder/IPCThreadState.cpp   
    2. status_t IPCThreadState::transact(int32_t handle,  
    3.                            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

    1. // frameworks/base/libs/binder/IPCThreadState.cpp   
    2. status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,  
    3.     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

    1. // frameworks/base/libs/binder/IPCThreadState.cpp   
    2. #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。