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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章