Binder是安卓应用最宽泛的进程间的通信方式,在分析安卓源码时少不了要和其打交道。对于一般开发人员而言只要知会其如何使用,如何实现进程间的通信即可,本文就是为了达到这个目的而写,一是给自己做一个备忘,二是让想了解binder通信的人员有个全局的认识。更深层次的研究请参考Android资料目录的Binder通信部分。
本文将通过实列的方式讲解如何实现binder通信,计划实现的列子框图如下:
SharedBufferService创建Ashmem并通过ServiceManager代理将自身加入系统服务。
ReadProcess/WriteProcess通过ServiceManager代理获取SharedBufferService代理,其后可以直接使用SharedBufferService提供的服务。
#ifndef ISHAREDBUFFER_H_
#define ISHAREDBUFFER_H_
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#define SHARED_BUFFER "HidAudioSharedBuffer"
#define SHARED_BUFFER_SIZE (sizeof(CircleBuff_Cblk_t)+200*568)
using namespace android;
class ISharedBuffer: public IInterface
{
public:
DECLARE_META_INTERFACE(SharedBuffer);
//服务提供getBuffer()和setStatus(int status)接口
virtual sp<IMemory> getBuffer() = 0;
virtual void setStatus(int status)=0;
};
class BnSharedBuffer: public BnInterface<ISharedBuffer>
{
public:
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
};
#endif
#define LOG_TAG "SharedBuffer"
#include <utils/Log.h>
#include <binder/MemoryBase.h>
#include "ISharedBuffer.h"
using namespace android;
enum
{
GET_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
SET_STATUS =IBinder::FIRST_CALL_TRANSACTION +1
};
class BpSharedBuffer: public BpInterface<ISharedBuffer>
{
public:
BpSharedBuffer(const sp<IBinder>& impl)
: BpInterface<ISharedBuffer>(impl)
{
}
public:
sp<IMemory> getBuffer()
{
ALOGD("ISharedBuffer at %d !\n",__LINE__);
Parcel data;
data.writeInterfaceToken(ISharedBuffer::getInterfaceDescriptor());
Parcel reply;
remote()->transact(GET_BUFFER, data, &reply);
sp<IMemory> buffer = interface_cast<IMemory>(reply.readStrongBinder());
return buffer;
}
void setStatus(int status){
//ALOGD("ISharedBuffer at %d status = %d !\n",__LINE__, status);
Parcel data;
data.writeInt32(status);
ALOGD("ISharedBuffer at %d status = %d !\n",__LINE__, status);
Parcel reply;
remote()->transact(SET_STATUS, data, &reply);
}
};
IMPLEMENT_META_INTERFACE(SharedBuffer, SHARED_BUFFER);
status_t BnSharedBuffer::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code)
{
case GET_BUFFER:
{
ALOGD("ISharedBuffer at %d \n",__LINE__ );
//CHECK_INTERFACE(ISharedBuffer, data, reply); //FIX ME ,have no right
sp<IMemory> buffer = getBuffer();
if(buffer != NULL)
{
reply->writeStrongBinder(buffer->asBinder());//匿名服务
}
return NO_ERROR;
}
case SET_STATUS:
{
ALOGD("ISharedBuffer at %d !\n",__LINE__ );
//CHECK_INTERFACE(ISharedBuffer, data, reply); //FIX ME,have no right
ALOGD("ISharedBuffer at %d !\n",__LINE__ );
setStatus(data.readInt32());
return NO_ERROR;
}
default:
{
ALOGD("ISharedBuffer at %d status = %d !\n",__LINE__,data.readInt32() );
return BBinder::onTransact(code, data, reply, flags);
}
}
}
#define LOG_TAG "SharedBuffer"
#include <utils/Log.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <sys/types.h>
#include <pthread.h>
#include <media/IAudioPolicyService.h>
#include <media/AudioSystem.h>
#include <system/audio.h>
#include "stdio.h"
#include "ISharedBuffer.h"
#include "circleBuffer.h"
int connected=0;
class SharedBufferService : public BnSharedBuffer
{
public:
SharedBufferService(){
CircleBuff_Cblk_t cblk;
sp<MemoryHeapBase> heap = new MemoryHeapBase(SHARED_BUFFER_SIZE, 0, "SharedBuffer");//创建ashmem
if(heap != NULL){
mMemory = new MemoryBase(heap, 0, SHARED_BUFFER_SIZE);
char * data = (char *)mMemory->pointer();
Mutex lock(Mutex::SHARED,"hidAudioBuffMutex");
if(data !=NULL){
cblk.freeSize = SHARED_BUFFER_SIZE -sizeof(cblk);
//cblk.buffLock =new Mutex(Mutex::SHARED,"hidAudioBuffMutex");
memcpy(&(cblk.buffLock),&lock,sizeof(lock));
cblk.writeIndex=0;
cblk.readIndex =0;
cblk.empty=1;
cblk.full =0;
cblk.offset =sizeof(cblk);
cblk.dataAvailed =0;
cblk.size = SHARED_BUFFER_SIZE - cblk.offset;
memcpy(data ,&cblk, sizeof(cblk));
}
}
}
virtual ~SharedBufferService()
{
mMemory = NULL;
}
public:
static void instantiate()
{
defaultServiceManager()->addService(String16(SHARED_BUFFER), new SharedBufferService());//通过instantiate()将服务添加到系统服务
}
//实现ISharedBuffer定义的服务接口
virtual sp<IMemory> getBuffer()
{
ALOGD("MonitorHidThread %d !\n",__LINE__ );
return mMemory;
}
virtual void setStatus(int status){
ALOGD("MonitorHidThread %d !\n",__LINE__ );
connected =status;
}
private:
sp<MemoryBase> mMemory;
};
int main(int argc, char** argv)
{
SharedBufferService::instantiate();//添加服务到系统
ProcessState::self()->startThreadPool();//实际和IPCThreadState::self()->joinThreadPool()效果一样
IPCThreadState::self()->joinThreadPool();//创建线程与binder内核驱动交互
//为什么要创建两个线程?人多力量大??
return 0;
}
#define LOG_TAG "SharedBufferClient"
#include <utils/Log.h>
#include <binder/MemoryBase.h>
#include <binder/IServiceManager.h>
#include "../ISharedBuffer.h"
#include "../circleBuffer.h"
#include <unistd.h>
int main()
{
sp<IBinder> binder = defaultServiceManager()->getService(String16(SHARED_BUFFER));//通过binder管理代理获取SHARED_BUFFER服务bpBinder
if(binder == NULL)
{
printf("Failed to get service: %s.\n", SHARED_BUFFER);
return -1;
}
sp<ISharedBuffer> service = interface_cast<ISharedBuffer>(binder);//创建SHARED_BUFFER服务代理对象
if(service == NULL)
{
return -2;
}
sp<IMemory> buffer = service->getBuffer();//获取服务提供的Ashmem
if(buffer == NULL)
{
return -3;
}
CircleBuff_Cblk_t *cblk = (CircleBuff_Cblk_t *)buffer->pointer();
if(cblk == NULL)
{
printf("get the cblk failed!");
return -4;
}
printf("size =%d wIndex =%d rIndex=%d empty=%d full=%d dataAvai=%d free =%d\n",cblk->size \
,cblk->writeIndex,cblk->readIndex,cblk->empty,cblk->full,cblk->dataAvailed,cblk->freeSize);
int i =0;
char buf[256];
memset(buf,0,sizeof(buf));
for(i=0; i<256 ;i++){
buf[i]=i;
}
int n=0 ,writed=0;
while(1){
writed = WriteData(cblk,buf+n,20);
if(writed !=20){
printf("error : write data != 20 !!! please check!\n");
}
printf("size =%d wIndex =%d rIndex=%d empty=%d full=%d dataAvai=%d free =%d\n",cblk->size \
,cblk->writeIndex,cblk->readIndex,cblk->empty,cblk->full,cblk->dataAvailed,cblk->freeSize);
n+=20;
if(n>235)
n=0;
sleep(1);
}
return 0;
}
点击下载源码