Binder简单实例

       Binder通信是Android用的比较多的一种通信机制,它是一种client-server的通信结构。Binder通信具有以下特点:1、用驱动程序来推进进程间的通信;2、可以通过共享内存的方式来提供性能;3、 可以为进程请求分配每个进程的线程池;4、针对系统中的对象引入了引用计数和跨进程的对象引用映射;5、可以方便的进行进程同步调用。Binder方面的资料网上非常多,单对于初学者来学,有些资料有些深刻,所以先打算写一个最简单的Binder实例来开始对Binder的学习。

       首先看看整个实例的目录:

    Binder下面放的是启动Binder服务程序,Binderserver下面放的是Binder服务的server和client端,而Test下面放的是一个简单的测试Binder服务的测试程序。

     先来看Binderserver下面的内容:

1、IBinderTest.h

#ifndef IBINDERTEST_H_
#define IBINDERTEST_H_

#include <inttypes.h>
#include <utils/Errors.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>

namespace android {

class Parcel;


class IBinderTest : public IInterface {
    public:
		DECLARE_META_INTERFACE(BinderTest);

		virtual int32_t testCmd(uint32_t cmdId,  uint32_t paramLen) = 0;
};

class BnBinderTest: public BnInterface<IBinderTest> {
    public:
        virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                uint32_t flags = 0);
	 private:
       bool checkPermission(const String16& permission);
};

}; // namespace android
#endif

       这里主要实现了两个类,IBinderTest跟BnBinderTest,IBinderTest是BinderTest的基类。

      在IBinderTest.h里面有个比较重要的宏,DECLARE_META_INTERFACE,该宏定义在:frameworks\base\include\binder\IInterface.h中

#define DECLARE_META_INTERFACE(INTERFACE)                               \
    static const android::String16 descriptor;                          \
    static android::sp<I##INTERFACE> asInterface(                       \
            const android::sp<android::IBinder>& obj);                  \
    virtual const android::String16& getInterfaceDescriptor() const;    \
    I##INTERFACE();                                                     \
    virtual ~I##INTERFACE();                                            \

     代入BinderTest后:

#define DECLARE_META_INTERFACE(BinderTest) \
    static const android::String16 descriptor;                          \
    static android::sp<IBinderTest> asInterface(                       \
            const android::sp<android::IBinder>& obj);                  \
    virtual const android::String16& getInterfaceDescriptor() const;    \
    IBinderTest();                                                     \
    virtual ~"IBinderTest(); 

       DECLARE_META_INTERFACE封装了实现binder所需要的一些类成员变量和成员函数,通过这些成员函数可以为一个binder实现创建proxy,这里主要是申明了asInterface这个函数,后面会说明这个函数的实现。

2、IBinderTest.cpp

      IBinderTest.cpp主要是实现IBinderTest.h里面申明的一些函数:

#include <stdint.h>
#include <sys/types.h>
#include <utils/Log.h>
#include <binder/Parcel.h>

#include "IBinderTest.h"

namespace android {

enum {
	TEST_CMD = IBinder::FIRST_CALL_TRANSACTION, 
};

class BpBinderTest : public BpInterface<IBinderTest>
{
public:
    BpBinderTest(const sp<IBinder>& impl) :
            BpInterface<IBinderTest>(impl) {
    }

    int32_t testCmd(uint32_t cmdId, uint32_t paramLen) {
            Parcel data, reply;
            data.writeInterfaceToken(descriptor);
            data.writeInt32(cmdId);
            data.writeInt32(paramLen);
            remote()->transact(TEST_CMD, data, &reply);
            reply.readExceptionCode();
            return reply.readInt32();
      } 
};

	IMPLEMENT_META_INTERFACE(BinderTest, "android.hardware.fingerprint.IBinderTest");


status_t BnBinderTest::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
        uint32_t flags) {
   switch(code) {
        case TEST_CMD: {
            CHECK_INTERFACE(IBinderTest, data, reply);
            int32_t cmdId = data.readInt32();
            int32_t paramLen = data.readInt32();
           // const uint8_t* param = static_cast<const uint8_t *>(data.readInplace(paramLen));
            ALOGV("%s, %s, %d", cmdId,  paramLen); 	    
			const int32_t ret = testCmd(cmdId, paramLen); 
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        }

        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
} 

bool BnBinderTest::checkPermission(const String16& permission) {
    bool ret = true;
    if (permission.size())
        return true;
    return ret;

}

}; // namespace android

    这里主要看看IMPLEMENT_META_INTERFACE这个宏,跟DECLARE_META_INTERFACE一样,也定义在frameworks\base\include\binder\IInterface.h中:

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    const android::String16 I##INTERFACE::descriptor(NAME);             \
    const android::String16&                                            \
            I##INTERFACE::getInterfaceDescriptor() const {              \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
            const android::sp<android::IBinder>& obj)                   \
    {                                                                   \
        android::sp<I##INTERFACE> intr;                                 \
        if (obj != NULL) {                                              \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \

     代入相应参数展开后:

#define IMPLEMENT_META_INTERFACE(BinderTest, "android.hardware.fingerprint.IBinderTest")                       \
    const android::String16 IBinderTest::descriptor(“android.hardware.fingerprint.IBinderTest”);             
    const android::String16&                                            \
            IBinderTest::getInterfaceDescriptor() const {              \
        return IBinderTest::descriptor;                                \
    }                                                                   \
    android::sp<IBinderTest> IBinderTest::asInterface(                \
            const android::sp<android::IBinder>& obj)                   \
    {                                                                   \
        android::sp<IBinderTest> intr;                                 \
        if (obj != NULL) {                                              \
            intr = static_cast<IBinderTest*>(                          \
                obj->queryLocalInterface(                               \
                        IBinderTest::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new BpBinderTest(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    IBinderTest::IBinderTest() { }                                    \
    IBinderTest::~IBinderTest() { }                                   \

       宏IMPLEMENT_META_INTERFACE主要是来实现asInterface,asInterface里面先调用queryLocalInterface,这个方法是IBinder定义的,默认实现是返回NULL,而在BBinder的子类BnInterface中,重载了该方法,返回this,而BpInterface并没有重载,使用IBinder的默认实现,返回NULL。而如果queryLocalInterface返回NULL,就构造一个BpXXXService返回,Client得到的正是这个BpXXXService。所以如果传进来的obj参数,是一个BBinder,就返回自身(这种情况应该是service和client在同一进程),如果是一个BpBinder,就new一个代理对象返回(这种情况应该是service和client在不同进程)。

3、BinderTest.h

#ifndef BINDERTEST_H_
#define BINDERTEST_H_


#include "IBinderTest.h"


namespace android {

	class BinderTest : public BnBinderTest{
		public:
			static BinderTest* getInstance() {
				if (sInstance == NULL) {
					ALOGD("%s", __func__);
					sInstance = new BinderTest();
				}
				return sInstance;
			}

		static void instantiate();
		virtual int32_t testCmd(uint32_t cmdId,  uint32_t paramLen);


		 private:	
			BinderTest();
			virtual ~BinderTest();
			void binderDied(const wp<IBinder>& who);
			static BinderTest* sInstance;
	};

} // namespace android

#endif

   这个文件比较简单,主要就是定义了一个BinderTest类,然后实现定义一些类里面的方法,函数instantiate跟testCmd。

  4、BinderTest.cpp:

#define LOG_TAG "BinderTest"

#include <binder/IServiceManager.h>
#include <hardware/hardware.h>
//#include <hardware/hw_auth_token.h>
#include <utils/Log.h>

#include "BinderTest.h"


namespace android {

	BinderTest* BinderTest::sInstance = NULL;

	
	BinderTest::BinderTest() {
		ALOGD("BinderTeststarted (pid=%d)", getpid());
		
		ALOGD("BinderTestend (pid=%d)", getpid());
	}

	BinderTest::~BinderTest() {
		ALOGD("BinderTest started (pid=%d)", getpid());
	}

	void BinderTest::instantiate() {
		ALOGD("Enter %s", __func__);
		status_t st = defaultServiceManager()->addService(  
                           String16("my.test.binder"), new BinderTest());  
    	        ALOGD("ServiceManager addService ret=%d", st); 
		ALOGD("Enter %s", __func__);
	}
	

	int32_t BinderTest::testCmd(uint32_t cmdId,  uint32_t paramLen) {
		ALOGD("cmdif = %d,  paramLen = %d", cmdId,  paramLen);
		
		return 0;
	}  
	
	void BinderTest::binderDied(const wp<IBinder>& who) {
		ALOGD("binder died");
		
	} 
}

       在instantiate函数里面,将BinderTest注册到系统的binder service列表中,这样以后就可以使用这个service提供的方法。而testCmd函数只是做了简单的打印操作。
       至此Binder服务的client跟server端都已经实现,下面就是如何启动我们定义的这个服务,我们可以在系统的system_init.cpp里面加载instantiate函数来启动该服务,也可以以单独的程序来启动,如下所示:

#include <cutils/log.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
#include <utils/String16.h>
#include <hardware/hardware.h>

#include "../fptestserver/BinderTest.h"

#define LOG_TAG "BinderTest"

using namespace android;

int main()
{
        ALOGI("TestService Starting " LOG_TAG);
	sp<ProcessState> proc(ProcessState::self());  
	sp<IServiceManager> sm = defaultServiceManager();  
	BinderTest::instantiate();
	ProcessState::self()->startThreadPool();  
        IPCThreadState::self()->joinThreadPool();  
	ALOGI("TestService end " LOG_TAG);
        return 0;
}

     这里直接调用了BinderTest里面的instantiate函数来实现的。
     下面看看测试程序:

#define LOG_TAG "TestBinserService"  
  
#include <utils/Log.h>  
#include <nativehelper/jni.h>  
#include <nativehelper/JNIHelp.h>  
#include <android_runtime/AndroidRuntime.h>  
#include <binder/IServiceManager.h> 

 
#include "../fptestserver/BinderTest.h"
#include "../fptestserver/IBinderTest.h"

  
using namespace android;  
  
int main(int argc, char** argv)  
 {  
     int sum = 0;  
     const uint8_t* param;
     ALOGE("main enter");
     sp<IBinderTest> mTestBinserService;  
     if (mTestBinserService.get() == 0) {  
        sp<IServiceManager> sm = defaultServiceManager();  
        sp<IBinder> binder;  
        do {  
		ALOGE("binder enter");
                binder = sm->getService(String16("my.test.binder"));
                if (binder != 0) {  
		      ALOGE("getService ok");  
                      break;  
                }
                ALOGE("getService fail");  
                usleep(500000); // 0.5 s  
            } while (true);  
           mTestBinserService = interface_cast<IBinderTest> (binder); 
	   ALOGE("mTestBinserService");  
           ALOGE_IF(mTestBinserService == 0, "no ITestBinserService!?");  
    }  
    sum = mTestBinserService->testCmd(3, param,4);  
    ALOGI("sum = %d", sum);  
    return 0;  
  
}  

启动Binderserver服务:


打印log如下:

E/TestBinserService( 3449): main enter

E/TestBinserService( 3449): binder enter

E/TestBinserService( 3449): getService ok

E/TestBinserService( 3449): mTestBinserService

D/BinderTest( 3440): cmdif = 3,  paramLen = 4

I/TestBinserService( 3449): sum = 0

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值