Ashmem c++ 示例
TODO:writeStrongBinder/readStrongBinder 作用
common
common/ISharedBuffer.cpp
#define LOG_TAG "ISharedBuffer"
#include <utils/Log.h>
#include <binder/MemoryBase.h>
#include "ISharedBuffer.h"
using namespace android;
enum
{
GET_BUFFER = IBinder::FIRST_CALL_TRANSACTION
};
//注意到 模板参数
class BpSharedBuffer: public BpInterface<ISharedBuffer>
{
public:
BpSharedBuffer(const sp<IBinder>& impl): BpInterface<ISharedBuffer>(impl)
{
}
public:
sp<IMemory> getBuffer()
{
//Parcel 容器,用于 binder 进程间通信
Parcel data;
data.writeInterfaceToken(ISharedBuffer::getInterfaceDescriptor());
Parcel reply;
//会发生阻塞,等待 onTransact 返回
remote()->transact(GET_BUFFER,data,&reply);
sp<IMemory> buffer = interface_cast<IMemory>(reply.readStrongBinder());
return buffer;
}
};
//实现 getInterfaceDescriptor 等,对应 DECLARE_META_INTERFACE
IMPLEMENT_META_INTERFACE(SharedBuffer,"shy.luo.ISharedBuffer");
//定义了 SharedBufferService 的 binder 本地对象类 BnSharedBuffer 的成员函数 onTransact,用来处理 SharedBufferClient 发过来的 GET_BUFFER 的
//进程间通信请求
status_t BnSharedBuffer::onTransact(uint32_t code,const Parcel& data,Parcel* reply,uint32_t flags)
{
switch(code)
{
case GET_BUFFER:
{
CHECK_INTERFACE(ISharedBuffer,data,reply);
//在 onTransact 需要显示的调用执行 transact 所在的函数,不然 transact 会一直阻塞
sp<IMemory> buffer = getBuffer();
if(buffer != NULL)
{
reply->writeStrongBinder(IInterface::asBinder(buffer));
}
return NO_ERROR;
}
default:
{
return BBinder::onTransact(code,data,reply,flags);
}
}
}
common/ISharedBuffer.h
#ifndef ISHAREDBUFFER_H_
#define ISHAREDBUFFER_H_
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#define SHARED_BUFFER_SERVICE "shy.luo.SharedBuffer"
#define SHARED_BUFFER_SIZE 4
using namespace android;
//定义服务接口 ,getBuffer 用来返回一个匿名共享内存服务接口 IMemory
//DECLARE_META_INTERFACE宏 binder里面的东西了,展开后主要定义了 asInterface 静态成员函数,用于将 IBinder 对象转化为 ISharedBuffer 接口
//IBinder 又是从 servicemanger 里面获取到的,这样子 client 要获取服务就很 "套路" 了。
//servicemanager 获取 -> asInterface 转化 -> Ixxx service 函数
//当然这里只是申明,相关声明对应这实现 IMPLEMENT_META_INTERFACE
class ISharedBuffer: public IInterface
{
public:
DECLARE_META_INTERFACE(SharedBuffer);
virtual sp<IMemory> getBuffer() = 0;
};
// onTransact 接收进程间通信请求
class BnSharedBuffer: public BnInterface<ISharedBuffer>
{
public:
virtual status_t onTransact(uint32_t code,const Parcel& data,Parcel* reply,uint32_t flags = 0);
};
#endif
service
server/SharedBufferServer.cpp
#define LOG_TAG "SharedBufferServer"
#include <utils/Log.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "../common/ISharedBuffer.h"
//注册到 servicemanager 里面的是 BnSharedBuffer 的子类
class SharedBufferService : public BnSharedBuffer
{
public:
SharedBufferService()
{
//共享一整块内存 MemoryHeapBase ,创建后如果只想共享其中一部分则使用 MemoryBase
sp<MemoryHeapBase> heap = new MemoryHeapBase(SHARED_BUFFER_SIZE,0,"SharedBuffer");
if(heap != NULL)
{
mMemory = new MemoryBase(heap,0,SHARED_BUFFER_SIZE);
int32_t *data = (int32_t*)mMemory->pointer();
if(data != NULL)
{
*data = 0;
}
}
}
virtual ~SharedBufferService()
{
mMemory = NULL;
}
public:
static void instantiate()
{
// 注册进 servicemanager ,注意到注册进的 SharedBufferService 是 BnSharedBuffer 的子类
defaultServiceManager()->addService(String16(SHARED_BUFFER_SERVICE),new SharedBufferService());
}
//虚函数,getBuffer 由子类实现
virtual sp<IMemory> getBuffer()
{
return mMemory;
}
private:
sp<MemoryBase> mMemory;
};
int main(int argc,char** argv)
{
SharedBufferService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := ../common/ISharedBuffer.cpp \
SharedBufferServer.cpp
LOCAL_SHARED_LIBRARIES := libcutils libutils libbinder
LOCAL_MODULE := SharedBufferServer
include $(BUILD_EXECUTABLE)
client
client/SharedBufferClient.cpp
#define LOG_TAG "SharedBufferClient"
#include <utils/Log.h>
#include <binder/MemoryBase.h>
#include <binder/IServiceManager.h>
#include "../common/ISharedBuffer.h"
int main()
{
sp<IBinder> binder = defaultServiceManager()->getService(String16(SHARED_BUFFER_SERVICE));
if(binder == NULL)
{
printf("FAIELD TO GET SERVICE");
return -1;
}
sp<ISharedBuffer> service = ISharedBuffer::asInterface(binder);
if(service == NULL)
{
return -2;
}
sp<IMemory> buffer = service->getBuffer();
if(buffer == NULL)
{
return -3;
}
int32_t *data = (int32_t*)buffer->pointer();
if(data == NULL)
{
return -4;
}
printf("the value of the shared buffer is %d.\n",*data);
*data = *data + 1;
printf("Add value 1 to the shared buffer.\n");
return 0;
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := ../common/ISharedBuffer.cpp \
SharedBufferClient.cpp
LOCAL_SHARED_LIBRARIES := libcutils libutils libbinder
LOCAL_MODULE := SharedBufferClient
include $(BUILD_EXECUTABLE)
参考
老罗binder binder 问题自测