Ashmem c++ 示例

2018/08/07 architecture

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 问题自测

Search

    Table of Contents