BInder方面的资料虽然感觉看的比较多,但是真正用的时候才发现有很多地方模棱两棵的,所以,打算用一个实例再来巩固一下binder的使用方法
首先看下目录结构:
- leaves@leaves-desktop:~/android/android2/android/frameworks/tv_print/services$ ls T*
- TestBinderClient:
- Android.mk ITestBinderService.cpp
-
- TestBinderServer:
- Android.mk ITestBinderService.h main_testBinder.cpp testBinder.cpp TestBinderService.cpp TestBinderService.h
- leaves@leaves-desktop:~/android/android2/android/frameworks/tv_print/services$
TestBinderClient下面是Binder的客户端,TestBinderServer是binder的服务端
我们先来看下biner服务端代码
1、ITestBinderService.h
- #ifndef ANDROID_ITESTBINDERSERVICE_H_
- #define ANDROID_ITESTBINDERSERVICE_H_
-
- #include <utils/RefBase.h>
- #include <binder/IInterface.h>
- #include <binder/Parcel.h>
-
-
- namespace android {
-
- class Parcel;
-
- class ITestBinderService: public IInterface {
- public:
- DECLARE_META_INTERFACE(TestBinderService);
-
- virtual int add(int a, int b) = 0;
- };
-
- class BnTestBinderService: public BnInterface<ITestBinderService> {
- public:
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags = 0);
- };
-
- }
-
- #endif /* ANDROID_ITESTBINDERSERVICE_H_ */
这里主要是定义了两个类ITestBinderService 和 BnTestBinderService,ITestBinderService 是TestBinderService 的基类,
这里主要是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();
把TestBinderService代入进去
- #define DECLARE_META_INTERFACE(TestBinderService) \
- static const android::String16 descriptor; \
- static android::sp<I##TestBinderService> asInterface( \
- const android::sp<android::IBinder>& obj); \
- virtual const android::String16& getInterfaceDescriptor() const; \
- I##TestBinderService(); \
- virtual ~I##TestBinderService();
其中封装了实现binder所需要的一些类成员变量和成员函数,通过这些成员函数可以为一个binder实现创建proxy
2、TestBinderService.h
- #ifndef ANDROID_TESTBINDERSERVICE_H_
- #define ANDROID_TESTBINDERSERVICE_H_
-
- #include <utils/KeyedVector.h>
- #include "ITestBinderService.h"
-
- namespace android {
-
- class TestBinderService: public BnTestBinderService {
- public:
- static void instantiate();
- int add(int a,int b);
- private:
- TestBinderService();
- virtual ~TestBinderService();
- };
-
- }
-
- #endif /* ANDROID_TESTBINDERSERVICE_H_ */
这个文件比较简单,主要就是定义了一个类TestBinderService,继承于前面 的BnTestBinderService,并定义了一个方法add函数和instantiate
3、TestBinderService.cpp
- #define LOG_TAG "TestBinderService"
-
- #include <utils/Log.h>
- #include <binder/IServiceManager.h>
- #include <binder/IPCThreadState.h>
-
- #include "TestBinderService.h"
- static int debug_flag = 1;
- namespace android {
-
- void TestBinderService::instantiate() {
- LOGI("Enter TestBinderService::instantiate");
- status_t st = defaultServiceManager()->addService(
- String16("my.test.binder"), new TestBinderService());
- LOGD("ServiceManager addService ret=%d", st);
- LOGD("instantiate> end");
- }
-
- TestBinderService::TestBinderService() {
- LOGD(" TestBinderServicet");
- }
-
- TestBinderService::~TestBinderService() {
- LOGD("TestBinderService destroyed,never destroy normally");
- }
-
- int TestBinderService::add(int a,int b) {
-
- LOGI("TestBinderService::add a = %d, b = %d.", a , b);
- return a+b;
- }
-
- }
在instantiate函数中,将TestBinderService注册到系统的binder service列表中,这样以后就可以使用这个service提供的方法
该service提供了一个add 方法,返回两个数的和
再来看下clinet端 的代码
1、ITestBinderService.cpp
- #define LOG_TAG "ITeeveePlayerService"
-
- #include <utils/Log.h>
-
- #include "../TestBinderServer/ITestBinderService.h"
-
- namespace android {
-
- enum {
- TEST_ADD = IBinder::FIRST_CALL_TRANSACTION,
- };
-
- class BpTestBinderService: public BpInterface<ITestBinderService> {
- public:
- BpTestBinderService(const sp<IBinder>& impl) :
- BpInterface<ITestBinderService> (impl) {
- }
-
- int add(int a, int b) {
-
- Parcel data, reply;
- LOGI("Enter BpTestBinderService add,a = %d , b = %d", a, b);
- data.writeInterfaceToken(ITestBinderService::getInterfaceDescriptor());
- data.writeInt32(a);
- data.writeInt32(b);
- remote()->transact(TEST_ADD, data, &reply);
- int sum = reply.readInt32();
- LOGI("BpTestBinderService sum = %d", sum);
- return sum;
- }
- };
-
- IMPLEMENT_META_INTERFACE(TestBinderService, "android.test.ITestBinderService");
-
-
-
- status_t BnTestBinderService::onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags) {
- switch (code) {
- case TEST_ADD: {
-
- CHECK_INTERFACE(ITestBinderService, data, reply);
- int a = data.readInt32();
- int b = data.readInt32();
- LOGI("Enter BnTestBinderService add,a = %d , b = %d", a, b);
- int sum = 0;
- sum = add(a, b);
- LOGI("BnTestBinderService sum = %d", sum);
- reply->writeInt32(sum);
- return sum;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
- }
-
- }
定义了一个类BpTestBinderService,提供add方法,该方法通过调用远端的binder service提供的服务返回两个数的和
重载了BnTestBinderService的onTransact方法,使其在TEST_ADD时调用add方法
这个文件里面也使用了一个宏IMPLEMENT_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(TestBinderService, "android.test.ITestBinderService") \
- const android::String16 ITestBinderService::descriptor("android.test.ITestBinderService"); \
- const android::String16& \
- ITestBinderService::getInterfaceDescriptor() const { \
- return ITestBinderService::descriptor; \
- } \
- android::sp<ITestBinderService> ITestBinderService::asInterface( \
- const android::sp<android::IBinder>& obj) \
- { \
- android::sp<ITestBinderService> intr; \
- if (obj != NULL) { \
- intr = static_cast<ITestBinderService*>( \
- obj->queryLocalInterface( \
- ITestBinderService::descriptor).get()); \
- if (intr == NULL) { \
- intr = new BpTestBinderService(obj); \
- } \
- } \
- return intr; \
- } \
- ITestBinderService::ITestBinderService() { } \
- ITestBinderService::~ITestBinderService() { }
这里重点看 一下asInterface函数,IBinder::queryLocalInterface函数位于framework/base/libs/binder/Binder.cpp文件中
- sp<IInterface> IBinder::queryLocalInterface(const String16& descriptor)
- {
- return NULL;
- }
由此可见,最终会调用下面语句:
intr = new BpTestBinderService(obj)
这样,server和client端的binder代码主写好了,接着就需要把binder service加入到binder中
这里有两种方法:
1、在system_init.cpp中添加
TestBinderService::instantiate();
如果是在这里加的话可以去掉TestBinderService中实现的instantiate方法,同时将TestBinderService继承自BinderService,因为在BinderService实现了这一方法,同时将其添加到binder service
2、以单独的程序启动
main_testBinder.cpp
- #include <binder/IPCThreadState.h>
- #include <binder/ProcessState.h>
- #include <binder/IServiceManager.h>
- #include <utils/Log.h>
-
-
- #include "TestBinderService.h"
-
- using namespace android;
-
- int main(int argc, char** argv)
- {
-
- sp<ProcessState> proc(ProcessState::self());
- sp<IServiceManager> sm = defaultServiceManager();
- LOGI("TestBinderService before");
- TestBinderService::instantiate();
- LOGI("TestBinderService End");
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
- return 0;
-
- }
这里调用的是TestBinderService自己的instantiate来添加的
再来看下测试case,testBinder.cpp
- #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 "../TestBinderServer/ITestBinderService.h"
-
-
- #include "TestBinderService.h"
-
- using namespace android;
-
- int main(int argc, char** argv)
- {
- int sum = 0;
- sp<ITestBinderService> mTestBinserService;
- if (mTestBinserService.get() == 0) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder;
- do {
- binder = sm->getService(String16("my.test.binder"));
- if (binder != 0)
- break;
- LOGI("getService fail");
- usleep(500000);
- } while (true);
- mTestBinserService = interface_cast<ITestBinderService> (binder);
- LOGE_IF(mTestBinserService == 0, "no ITestBinserService!?");
- }
- sum = mTestBinserService->add(3, 4);
- LOGI("sum = %d", sum);
- return 0;
-
- }
这里先根据名字获取Service,再使用其提供的相应 服务
看下串口打印,
启动service:
- C:\adb>adb shell
- # cd /system/bin
- cd /system/bin
- # chmod 777 main_*
- chmod 777 main_*
- # ./main_testBinder
- ./main_testBinder
client:
- I/ServiceManager( 1369): Waiting for service my.test.binder...
- I/ServiceManager( 1369): Waiting for service my.test.binder...
- I/ServiceManager( 1369): Waiting for service my.test.binder...
- I/ServiceManager( 1369): Waiting for service my.test.binder...
- I/ServiceManager( 1369): Waiting for service my.test.binder...
- I/PlayServiceManager-JNI( 1369): getService fail
- I/ServiceManager( 1369): Waiting for service my.test.binder...
- I/ServiceManager( 1369): Waiting for service my.test.binder...
- I/ServiceManager( 1369): Waiting for service my.test.binder...
- I/ServiceManager( 1369): Waiting for service my.test.binder...
- I/ ( 1373): TestBinderService before
- I/TestBinderService( 1373): Enter TestBinderService::instantiate
- D/TestBinderService( 1373): TestBinderServicet
- D/TestBinderService( 1373): ServiceManager addService ret=0
- D/TestBinderService( 1373): instantiate> end
- I/ ( 1373): TestBinderService End
- I/ITeeveePlayerService( 1369): Enter BpTestBinderService add,a = 3 , b = 4
- I/ITeeveePlayerService( 1373): Enter BnTestBinderService add,a = 3 , b = 4
- I/TestBinderService( 1373): TestBinderService::add a = 3, b = 4.
- I/ITeeveePlayerService( 1373): BnTestBinderService sum = 7
- I/ITeeveePlayerService( 1369): BpTestBinderService sum = 7
- I/PlayServiceManager-JNI( 1369): sum = 7
前面 的Waiting for service my.test.binder...是在还没有启动service的时候打印出来的
这样,需要使用TestBinserService 提供的服务时,只需要先获取其service,再使用其提供的方法
相关代码:
http://download.csdn.net/detail/new_abc/4673623