您的位置:首页 > 移动开发 > Android开发

Android Binder实列篇

2015-10-16 19:21 615 查看

前言

Binder是安卓应用最宽泛的进程间的通信方式,在分析安卓源码时少不了要和其打交道。对于一般开发人员而言只要知会其如何使用,如何实现进程间的通信即可,本文就是为了达到这个目的而写,一是给自己做一个备忘,二是让想了解binder通信的人员有个全局的认识。更深层次的研究请参考Android资料目录的Binder通信部分。

本文将通过实列的方式讲解如何实现binder通信,计划实现的列子框图如下:



SharedBufferService创建Ashmem并通过ServiceManager代理将自身加入系统服务。

ReadProcess/WriteProcess通过ServiceManager代理获取SharedBufferService代理,其后可以直接使用SharedBufferService提供的服务。

Service的实现

服务接口ISharedBuffer的声明

#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


ISharedBuffer.cpp的实现

#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;
}


点击下载源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 通信 binder