Android Binder实列篇

前言

Binder是安卓应用最宽泛的进程间的通信方式,在分析安卓源码时少不了要和其打交道。对于一般开发人员而言只要知会其如何使用,如何实现进程间的通信即可,本文就是为了达到这个目的而写,一是给自己做一个备忘,二是让想了解binder通信的人员有个全局的认识。更深层次的研究请参考Android资料目录的Binder通信部分。
本文将通过实列的方式讲解如何实现binder通信,计划实现的列子框图如下:
Android Binder实列篇_第1张图片
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)