分类: LINUX
2010-06-18 23:25:47
要点:
1、核心服务通常在独立的进程(Process)里执行。
2、必须提供IBinder 接口,让应用程序可以进行跨进程的绑定(Binding)和呼叫。
3、因为共享,所以必须确保多线裎安全(Thread-safe)。
4、以C++类别定义,诞生其对象,透过SM 之协助,将该对象参考值传给IServiceManager::addService()函数,就加入到Binder Driver 里了。
5、应用程序可透过SM 之协助而远距绑定该核心服务,此时SM 会回传IBinder 接口给应用程序。
6、应用程序可透过IBinder::transact()函数来与核心服务互传数据。
将AddService 核心服务加入Binder Driver
此范例功能为简单的整数加法(Add)运算,此核心服务命名为AddService。
Step-1:以C++撰写AddService 类别,其完整程序代码为:
/*--- AddService.h 定义档 ---*/
//AddService.h
#ifndef ANDROID_GUILH_ADD_SERVICE_H
#define ANDROID_GUILH_ADD_SERVICE_H
#include
#include
#include
#include
namespace android {
class AddService : public BBinder{
mutable Mutex mLock;
int32_t mNextConnId;
public:
static int instantiate();
AddService();
virtual ~AddService();
virtual status_t onTransact(
uint32_t, const Parcel&, Parcel*, uint32_t);
}}; //namespace
#endif
/*--- AddService.cpp 实作档 ---*/
// AddService.cpp
#include "AddService.h"
#include
#include
namespace android {
static struct sigaction oldact;
static pthread_key_t sigbuskey;
int AddService::instantiate() {
LOGE("AddService instantiate");
int r = defaultServiceManager()->addService(
String16("guilh.add"), new AddService());
LOGE("AddService r = %d\n", r);
return r;
}
AddService::AddService()
{ LOGV("AddService created");
mNextConnId = 1;
pthread_key_create(&sigbuskey, NULL);
}
AddService::~AddService()
{ pthread_key_delete(sigbuskey);
LOGV("AddService destroyed");
}
status_t AddService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
switch(code) {
case 0: {
pid_t pid = data.readInt32();
int num = data.readInt32();
num = num + 1000;
reply->writeInt32(num);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}}; //namespace
/*--- Make 檔 ---*/
//Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
AddService.cpp
LOCAL_C_INCLUDES := \
$(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := \
libutils
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libAdd
include $(BUILD_SHARED_LIBRARY)
执行上述Android.mk 档,就产出libAdd.so 档案了。
Step-2:以C++撰写一个可独立执行的addserver.cpp 程序,它的用途是:诞生一
个AddService 类别之对象,然后将该对象参考存入Binder Driver 里。其内容为:
5
/*--- addserver.cpp ---*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "../libadd/AddService.h"
//#include
using namespace android;
int main(int argc, char** argv)
{
sp
sp
LOGI("ServiceManager: %p", sm.get());
AddService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
编译并连结此addserver.cpp,产出addserver.exe 可执行程序。
Step-3:上述两个步骤分别产出了libAdd.so 类别库和addserver.exe 可执行程序了。
接着将libAdd.so 拷贝到Android 仿真器的/system/lib/里;也把addserver.exe 拷贝
到/system/bin/里。
Step-4:执行addserver.exe,其中的指令:
AddServer::instantiate();
就执行到AddServer 类别的instantiate()函数,其内容为:
int AddService::instantiate() {
LOGE("AddService instantiate");
int r = defaultServiceManager()->addService(
String16("guilh.add"), new AddService());
LOGE("AddService r = %d\n", r);
return r;
}
其先执行到new AddServer(),就诞生一个AddServer 类别之对象;接着,呼
叫defaultServiceManager()函数取得SM 的IServiceManager 接口,再呼叫
IServiceManager::addServer()将该对象参考存入Binder Driver 里,如下图所示:
写个Add 类别来使用AddService 核心服务
刚才已经成功地将AddService 服务加入到Binder Driver 里了。现在,兹写
个C++应用类别来系结(Bind)此核心服务。
Step-5:以C++撰写Add 类别,其完整程序代码为:
/*--- Add.h ---*/
#ifndef ANDROID_GUILH_ADD_H
#define ANDROID_GUILH_ADD_H
namespace android {
class Add {
public:
void setN(int n);
private:
static const void getAddService();
};
}; //namespace
#endif // ANDROID_GUILH_ADD_H
/*--- Add.cpp ---*/
#include
#include
#include "Add.h"
namespace android {
sp
void Add::setN(int n){
getAddService();
Parcel data, reply;
data.writeInt32(getpid());
data.writeInt32(n);
7
LOGE("BpAddService::create remote()->transact()\n");
binder->transact(0, data, &reply);
return;
}
const void Add::getAddService(){
sp
binder = sm->getService(String16("guilh.add"));
LOGE("Add::getAddService %p\n",sm.get());
if (binder == 0) {
LOGW("AddService not published, waiting...");
return;
}
}
}; //namespace
其中的setN()函数呼叫getAddService()函数来取得SM 的接口参考,然后要求
SM 去协助系结到AddService 核心服务,完成时SM 会回传BpBinder 对象的
IBinder 接口参考,然后暂存于binder 变量里。如下图所示:
写之后。还可以写个JNI Native 类别来使用Add 类别之对象,如下图所示。
由于大家已经熟悉JNI Native 函数的写法了,于此省略程序代码。透过JNI
Native 函数,就能与Java 层的Service 服务衔接起来,如下图: