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