Android Binder序列3(实例)

Android Binder序列3(实例)---创建Native Binder Service

首先在编译Binder相关的程序需要链接到Binder动态链接库,应用开发环境下使用ndk编程是不能链接binder动态链接库的,故此需要在源码开发环境下进行,本实例是放在Android源码目录的vender目录下面,然后创建一个NativeBinder文件夹,该文件夹的目录结构如下:

Android.mk 这个不用多说
     Test.h     里面定义了本地方法的相关接口和本地接口代理BBxxxx
     ITestService.cpp  里面定义了Bpxxxx和Bnxxxx::onTransact
     TestService.cpp   这个就是Natavite Binder的实现
     TestClient.cpp    这个就是通过Binder对Nataive Binder Service的使用了

1)Android.mk的具体实现,代码如下:

#生成binder native  service的服务端
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
	libcutils \
	libutils \
	libbinder \
	liblog
LOCAL_MODULE := TestServer
LOCAL_SRC_FILES := \
	TestService.cpp \
	ITestService.cpp
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
 
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
	libcutils \
	libutils \
	libbinder \
	liblog

#生成binder native service的客户端
LOCAL_MODULE := TestClient
LOCAL_SRC_FILES := \
	ITestService.cpp \
	TestClient.cpp
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)

关于Android.mk的相关语法问题,我在这里就不多做细说了,如果还不太了解的可以上百度或者谷歌去需求帮助。

 2)Android Native Binder Service接口的定义,Test.h具体就是做的这个工作,下面给出代码

#ifndef TEST_H_H
#define TEST_H_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/file.h>//flock's head
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <android/log.h>
#include <cutils/properties.h>
#include <unistd.h>


#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IBinder.h>
#include <binder/Binder.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <android/log.h>

using namespace android;

#define LOGE(TAG,...) if(1) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
#define TAG "NativeService"

namespace android
{
	 class ITestService : public IInterface
	    {
	        public:
	         /*使用该宏,相当于添加了一些代码,后面会有详细分析*/
	        DECLARE_META_INTERFACE(TestService); // declare macro
	        virtual void test()=0;
	    };
	 
	    enum
	    {
	        TEST = IBinder::FIRST_CALL_TRANSACTION,
	    };
	 
	 class BnTestService: public BnInterface<ITestService>
	 {
		public:
		virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,uint32_t flags = 0);
		virtual void test()
		{
			LOGE(TAG,"Now get test\n");
		}

	 };
}
#endif

(1)使用DECLARE_META_INTERFACE(TestService);相当于添加了下述代码:

     static const android::String16 descriptor;
     static android::sp<ITestService> asInterface(
     const android::sp<android::IBinder>& obj);
     virtual const android::String16& getInterfaceDescriptor() const;
     ITestService ();
     virtual ~ITestService();

(2)为ITestService接口的所有方法声明枚举,一个枚举值对应ITestService接口的一个方法(Test.h)

    enum
    {
        TEST = IBinder::FIRST_CALL_TRANSACTION,
    };

TEST相当于ITestService接口里的test方法,后续会为该枚举值调用test方法(Test.h)

 3)ITestService.cpp,该文件主要创建了BpTestService和实现了BnTestService::onTransact,不多说直接上代码:

#include "Test.h"
namespace android
{

	class BpTestService:public BpInterface<ITestService>
	{
		public:
			BpTestService(const sp<IBinder>& impl):
			BpInterface<ITestService>(impl)
			{
			}

		void test()
		{
			printf("in the get Test\n");
			         Parcel data, reply;
			         data.writeInterfaceToken(ITestService::getInterfaceDescriptor());
			         remote()->transact(TEST, data, &reply);
			         printf("send Print %d\n", reply.readInt32());
		}

	};


	IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService");

	status_t BnTestService::onTransact(uint32_t code,const Parcel& data,Parcel* reply,uint32_t flags) 
		{
			switch (code) {
				case TEST: {
						printf("got the client msg\n");
						CHECK_INTERFACE(ITest, data, reply);
						test();
						reply->writeInt32(100);
						return NO_ERROR;
					}
					break;
					
					default:
					break;
			}
			return NO_ERROR;
		}
}

4)实现ITestService接口的方法(ITestService.cpp)

IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService");

使用IMPLEMENT_META_INTERFACE(TestService, “android.TestServer.ITestService”);相当于添加了下述代码:

/*初始化用宏DECLARE_META_INTERFACE声明的静态字段descriptor*/
const android::String16 ITestService::descriptor("android.TestServer.ITestService");
/*实现用宏DECLARE_META_INTERFACE声明的方法getInterfaceDescriptor */
const android::String16&                                          
ITestService::getInterfaceDescriptor() const { 
return ITestService::descriptor;                   
}                                                                   
/*实现用宏DECLARE_META_INTERFACE声明的方法asInterface */
android::sp<ITestService> ITestService::asInterface(   
const android::sp<android::IBinder>& obj)      
{                                                      
 android::sp<ITestService> intr;                    
if (obj != NULL) {           
/*在binder实体类BnInterface里会执行queryLocalInterface*/                      
intr = static_cast<ITestService*>(             
obj->queryLocalInterface(                  
 ITestService::descriptor).get());  
/*在binder引用类BpInterface里会创建BpInterface的子类对象*/            
if (intr == NULL) {                            
intr = new BpTestService(obj);             
}                                              
}                                                  
return intr;                                       
}                                                      
/*实现用宏DECLARE_META_INTERFACE声明的构造器和析构器 */
ITestService::ITestService() { }                     
ITestService::~ITestService() { };

 5)实现Client端(TestClient.cpp)

#include "Test.h"
using namespace android;
#define TAG "TestClient"

int main()
{
	sp < IServiceManager > sm = defaultServiceManager();
	sp < IBinder > binder = sm->getService(String16("service.testservice"));
	sp<ITestService> cs = interface_cast <ITestService> (binder);
	LOGE(TAG,"Hello Native service\n");
	cs->test();
	return 0;
}

    Service的Client通过Service Manager拿到的ITestService接口对象其实就是一个binder引用,也就是说其实是一个BpTestService对象,它也会实现ITestService接口的test方法,但是它并没有实现test的功能,而是跨进程调用Binder实体对象BnInterface的test方法。因为

涉及到跨进程调用,所以并没有直接调用,而是通过binder驱动转交给服务进程一些参数,然后就阻塞住。服务进程收到这些参数后,知道client端调用test方法,此时服务端调用test方法,执行完成后把执行结果通过binder驱动再返回给client所在进程,此时client的test方法收到结果后

再返回。

实际的开发过程中并没有直接和binder驱动交互,而是通过Android为binder专门设计的一些核心库和框架来交互,这样就简化了代码编写复杂度。像BpInterface便是核心库和框架提供的一个类,我们在实现时,只需要调用BpInterface的构造器,并实现ITestService接口的test方法即可,实现test方法时,通过remote()调用transact方法就能把数据提交至service端,servcie的返回结果会放在reply里。interface_cast(binder)实际上调用的方法是用宏DECLARE_META_INTERFACE声明的方法ITestService::asInterface,这里用了内联函数模版。

ProcessState和IPCThreadState是真正直接和binder驱动交互的类,核心库和框架层都是通过和这两个类交互才能和驱动间接交互。它们通过ioctl和binder驱动交互,ProcessState主要负责管理所有的binder引用,IPCThreadState则和binder传输数据。以后如果有时间再详细介绍这两个类。

 6)实现Service端(ServiceTest.cpp)

#include "Test.h"
#define TAG "TestService"
namespace android {
	 class TestService: public BnTestService
	 {
	  public:
		   TestService();
		   ~TestService();
		   void test();
	 };
	 
	 
	 TestService::TestService()
	 {
	 }
	 TestService::~TestService()
	 {
	 }



	 static int getCallPackageName(char *processName) 
	 {
	 	  long pid = 0;
		  pid = IPCThreadState::self()->getCallingPid();
		  int ret;
		  char cmdline[256] = {0};
		  char buf[128] = {0};
	 
		  sprintf(cmdline, "/proc/%d/cmdline", pid);
		  int fd =0;
		  fd = open(cmdline, O_RDONLY);
		  if (fd < 0) {
			  LOGE("PERSSION","open /proc/xxx/cmdline error");
			  return -1;
		  }
	 
		  ret = read(fd, buf, sizeof(buf));
		  if (ret <= 0) {
			  LOGE("PERSSION","read /proc/xxx/cmdline error");
			  close(fd);
			  return -1;
		  }
	 
		  close(fd);
		  LOGE("PERSSION","current pid = %d , package name = %s", getpid(), buf);
		  strcpy(processName,buf);
		  return 0;
	 }

	 
	 void TestService::test()
	 {
	 	char processName[256] = {0};
		getCallPackageName(processName);
	  	printf("hello test\n");
		LOGE(TAG,"hello test from %s\n", processName);
	 }
 
}
 
 
 int main()
 {
	  sp < ProcessState > proc(ProcessState::self());
	  sp < IServiceManager > sm = defaultServiceManager();
	  sm->addService(String16("service.testservice"), new TestService());
	  //启动服务
	  LOGE(TAG,"Start testservice");
	  ProcessState::self()->startThreadPool();
	  IPCThreadState::self()->joinThreadPool();
	  return 0;
 }

其中声明并实现binder实体类BnInterface是如下代码实现的,定义在Test.h文件中,定义如下:

	 class BnTestService: public BnInterface<ITestService>
	 {
		public:
		virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,uint32_t flags = 0);
		virtual void test()
		{
			LOGE(TAG,"Now get test\n");
		}

	 };

BnInterface也是binder核心库和框架中的类,表示binder实体类,在onTransact函数里,会根据客户端提交的操作代码调用不同的函数,而操作代码就是2)里声明的枚举值,在本实例里是TEST,我们收到test后会调用test方法。本实例里将onTransact的实现放在下面的代码中实现:

	IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService");

	status_t BnTestService::onTransact(uint32_t code,const Parcel& data,Parcel* reply,uint32_t flags) 
	{
			switch (code) {
				case TEST: {
						printf("got the client msg\n");
						CHECK_INTERFACE(ITest, data, reply);
						test();
						reply->writeInt32(100);
						return NO_ERROR;
					}
					break;
					
					default:
					break;
			}
			return NO_ERROR;
	}

在这里的onTransact调用了test()方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值