您的位置:首页 > 其它

Binder简单实例

2016-05-31 19:57 232 查看
       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("lanhai %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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: