上一篇博客《Android 6.0 如何添加完整的系统服务(app-framework-kernel)》http://www.cnblogs.com/hackfun/p/7418902.html
介绍了如何添加一个系统服务,客户端和服务端都是基于JAVA实现的OpersysService。经过进一步的学习,我将
演示如何使用C++实现一个相同功能的系统服务hfnativeservice。为了兼容OpersysService,将保留Opersys-
Service服务端中的HAL和driver,供hfnativeservice使用,即OpersysService和hfnativeservice这两个Service
都是用相同的HAL和driver。其中,hfnativeservice增加了一个服务端死亡通知机制,即hfnative-service的服
务端进程被杀掉时,客户端会收到这个通知,并做相应的清理工作。
主要围绕以下几个步骤添加一个完整的C++系统服务:
(A) 添加HAL和Driver
(B) 添加服务接口,生成动态库
(C) 添加服务端
(D) 注册服务端
(E) 添加客户端
(F) 测试
(A) 添加HAL和Driver
这部分参考上一篇博客《Android 6.0 如何添加完整的系统服务(app-framework-kernel)》的
(A) 添加circular-char驱动
(B) 添加opersyshw_qemu HAL
(B) 添加服务接口,生成动态库
为了对外只提供服务端或客户端的接口,这里把客户端和服务端之间的通信实现细节放在一起,生成动态库so
文件,服务端和客户端在使用的时候,加载这个so就可以了。IHfNativeService.cpp对客户端和服务端提供了相同
的接口,并实现了proxy和native之间的Binder通信细节。HfNativeManager.cpp根据IHfNativeService.cpp提供的
接口,进一步封装,隐藏了客户端的是操作细节,如服务的获取,注册死亡通知等。
相关头文件:
frameworks/native/include/hfnative/HfNativeManager.h
#ifndef ANDROID_HACKFUN_HACKFUN_NATIVE_SERVICE_H
#define ANDROID_HACKFUN_HACKFUN_NATIVE_SERVICE_H #include <stdint.h>
#include <sys/types.h> #include <binder/IBinder.h> #include <utils/RefBase.h>
#include <utils/Singleton.h>
#include <utils/threads.h>
#include <hfnative/IHfNativeService.h> namespace android {
// --------------------------------------------------------------------------- class HfNativeManager : public Singleton<HfNativeManager>
{
public:
HfNativeManager();
~HfNativeManager(); int init_hfnative(void);
void deinit_hfnative(void);
int read_queue(char *buff, int len);
int write_queue(char *buff, int len);
int test_hfnative(int value); status_t assertState();
bool checkService() const;
void resetServiceStatus(); private:
bool isDied;
// DeathRecipient interface
void hfNativeServiceDied(); mutable sp<IHfNativeService> mHfNativeServer;
mutable sp<IBinder::DeathRecipient> mDeathObserver;
}; }; // namespace android #endif // ANDROID_HACKFUN_HACKFUN_NATIVE_SERVICE_H
frameworks/native/include/hfnative/IHfNativeService.h
#ifndef ANDROID_HACKFUN_HACKFUN_COMPOSER_CLIENT_H
#define ANDROID_HACKFUN_HACKFUN_COMPOSER_CLIENT_H #include <stdint.h>
#include <sys/types.h> #include <utils/Errors.h>
#include <utils/RefBase.h> #include <binder/IInterface.h> namespace android {
// ---------------------------------------------------------------------------- class IHfNativeService : public IInterface
{
public:
DECLARE_META_INTERFACE(HfNativeService); virtual int init_native(void) = ;
virtual void finalize_native(void) = ;
virtual int read_native(char *Buff, int Len) = ;
virtual int write_native(char *Buff, int Len) = ;
virtual int test_native(int value) = ;
}; // ---------------------------------------------------------------------------- class BnHfNativeService: public BnInterface<IHfNativeService> {
public:
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = );
}; // ---------------------------------------------------------------------------- }; // namespace android #endif // ANDROID_HACKFUN_HACKFUN_COMPOSER_CLIENT_H
源文件:
frameworks/native/libs/hfnative/IHfNativeService.cpp
#define LOG_TAG "HfNativeService" #include <stdio.h>
#include <stdint.h>
#include <malloc.h>
#include <sys/types.h> #include <binder/Parcel.h>
#include <binder/IMemory.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <hfnative/IHfNativeService.h> namespace android { enum {
INIT_NATIVE = IBinder::FIRST_CALL_TRANSACTION,
FINALIZE_NATIVE,
READ_NATIVE,
WRITE_NATIVE,
TEST_NATIVE
}; class BpHfNativeService : public BpInterface<IHfNativeService>
{
public:
BpHfNativeService(const sp<IBinder>& impl)
: BpInterface<IHfNativeService>(impl)
{
} int init_native(void)
{
Parcel data, reply; data.writeInterfaceToken(IHfNativeService::getInterfaceDescriptor());
remote()->transact(INIT_NATIVE, data, &reply); return (int)reply.readInt32();
} void finalize_native(void)
{
Parcel data, reply; data.writeInterfaceToken(IHfNativeService::getInterfaceDescriptor());
remote()->transact(FINALIZE_NATIVE, data, &reply);
} int read_native(char *Buff, int Len)
{
Parcel data, reply; data.writeInterfaceToken(IHfNativeService::getInterfaceDescriptor());
data.writeInt32(Len);
remote()->transact(READ_NATIVE, data, &reply);
reply.read((void *)Buff, (size_t)Len);
return (int) reply.readInt32();
} int write_native(char *Buff, int Len)
{
Parcel data, reply; data.writeInterfaceToken(IHfNativeService::getInterfaceDescriptor());
data.writeInt32(Len);
data.write((const void *)Buff, (size_t)Len);
remote()->transact(WRITE_NATIVE, data, &reply);
return (int) reply.readInt32();
} int test_native(int value)
{
Parcel data, reply; data.writeInterfaceToken(IHfNativeService::getInterfaceDescriptor());
data.writeInt32(value);
remote()->transact(TEST_NATIVE, data, &reply);
return (int) reply.readInt32();
}
}; IMPLEMENT_META_INTERFACE(HfNativeService, "android.hfnative.HfNativeService"); status_t BnHfNativeService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
char *buff;
int len, retval;
status_t status; switch(code) {
case INIT_NATIVE:
CHECK_INTERFACE(IHfNativeService, data, reply);
retval = init_native();
reply->writeInt32(retval);
return NO_ERROR; case FINALIZE_NATIVE:
CHECK_INTERFACE(IHfNativeService, data, reply);
finalize_native();
return NO_ERROR; case READ_NATIVE: {
CHECK_INTERFACE(IHfNativeService, data, reply);
len = data.readInt32();
buff = (char *)malloc(len);
retval = read_native(buff, len);
reply->write((const void *)buff, (size_t)len);
free(buff);
reply->writeInt32(retval);
return NO_ERROR;
} break; case WRITE_NATIVE: {
CHECK_INTERFACE(IHfNativeService, data, reply);
len = data.readInt32();
buff = (char *)malloc(len);
status = data.read((void *)buff, (size_t)len);
retval = write_native(buff, len);
free(buff);
reply->writeInt32(retval);
return NO_ERROR;
} break; case TEST_NATIVE:
CHECK_INTERFACE(IHfNativeService, data, reply);
retval = test_native(data.readInt32());
reply->writeInt32(retval);
return NO_ERROR; default:
return BBinder::onTransact(code, data, reply, flags);
}
} }; // namespace android
frameworks/native/libs/hfnative/HfNativeManager.cpp
#define LOG_TAG "HfNative" #include <stdint.h>
#include <sys/types.h> #include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Singleton.h> #include <binder/IBinder.h>
#include <binder/IServiceManager.h> #include <hfnative/IHfNativeService.h>
#include <hfnative/HfNativeManager.h> // ----------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------- HfNativeManager::HfNativeManager() : isDied(false)
{ } HfNativeManager::~HfNativeManager()
{
} void HfNativeManager::hfNativeServiceDied()
{
isDied = true;
mHfNativeServer.clear();
} status_t HfNativeManager::assertState() {
if (mHfNativeServer == NULL) {
// try for one second
const String16 name("hfnativeservice");
for (int i= ; i< ; i++) {
status_t err = getService(name, &mHfNativeServer);
if (err == NAME_NOT_FOUND) {
usleep();
continue;
}
if (err != NO_ERROR) {
return err;
}
break;
} init_hfnative();
ALOGI("test hfnativeservice [%d]", test_hfnative()); class DeathObserver : public IBinder::DeathRecipient {
HfNativeManager& mHfNativeManager;
virtual void binderDied(const wp<IBinder>& who) {
ALOGW("hfnativeservice died [%p]", who.unsafe_get());
mHfNativeManager.hfNativeServiceDied();
}
public:
DeathObserver(HfNativeManager& mgr) : mHfNativeManager(mgr) { }
}; mDeathObserver = new DeathObserver(*const_cast<HfNativeManager *>(this));
mHfNativeServer->asBinder(mHfNativeServer)->linkToDeath(mDeathObserver);
} return NO_ERROR;
} bool HfNativeManager::checkService() const
{
return isDied? true:false;
} void HfNativeManager::resetServiceStatus()
{
isDied = false;
} int HfNativeManager::init_hfnative(void)
{
return mHfNativeServer->init_native();
} void HfNativeManager::deinit_hfnative(void)
{
mHfNativeServer->finalize_native();
} int HfNativeManager::read_queue(char *buff, int len)
{
return mHfNativeServer->read_native(buff,len);
} int HfNativeManager::write_queue(char *buff, int len)
{
return mHfNativeServer->write_native(buff,len);
} int HfNativeManager::test_hfnative(int value)
{
return mHfNativeServer->test_native(value);
}
// ----------------------------------------------------------------------------
}; // namespace android
frameworks/native/libs/hfnative/Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) LOCAL_SRC_FILES:= \
IHfNativeService.cpp \
HfNativeManager.cpp LOCAL_SHARED_LIBRARIES := \
libbinder \
libcutils \
libutils LOCAL_MODULE:= libhfnativemgriface #ifneq ($(filter generic%,$(TARGET_DEVICE)),)
# Emulator build
# LOCAL_CFLAGS += -DUSE_FENCE_SYNC
#endif include $(BUILD_SHARED_LIBRARY) #ifeq (,$(ONE_SHOT_MAKEFILE))
#include $(call first-makefiles-under,$(LOCAL_PATH))
#endif
(C) 添加服务端
服务端说白了就是客户端的远程调用,如,客户端调用write_native()的时候,服务端的write_native()
也会被调用。为什么客户端不能直接调用服务端的write_native(),就是因为客户端和服务端分别处于不同的
进程中,进程间的通讯必须通过Binder、socket等机制进行传递。
frameworks/native/services/hfnativeservice/HfNativeService.h
#ifndef ANDROID_HACKFUN_NATIVE_SERVICE_H
#define ANDROID_HACKFUN_NATIVE_SERVICE_H #include <stdint.h>
#include <sys/types.h> #include <cutils/compiler.h> #include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/SortedVector.h>
#include <utils/threads.h> #include <binder/BinderService.h> #include <hfnative/IHfNativeService.h> namespace android { // --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
class HfNativeService : public BinderService<HfNativeService>,
public BnHfNativeService
{
public:
static char const* getServiceName() {
return "hfnativeservice";
} HfNativeService(); private:
virtual int init_native(void);
virtual void finalize_native(void);
virtual int read_native(char *Buff, int Len);
virtual int write_native(char *Buff, int Len);
virtual int test_native(int value);
}; // ---------------------------------------------------------------------------
}; // namespace android #endif // ANDROID_HACKFUN_NATIVE_SERVICE_H
frameworks/native/services/hfnativeservice/HfNativeService.cpp
#include <stdint.h>
#include <math.h>
#include <sys/types.h> #include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Singleton.h>
#include <utils/String16.h> #include <binder/BinderService.h>
#include <binder/IServiceManager.h> #include <hfnative/IHfNativeService.h> #include "HfNativeService.h" #include <utils/misc.h>
#include <hardware/hardware.h>
#include <hardware/opersyshw.h> #include <stdio.h> namespace android {
// --------------------------------------------------------------------------- opersyshw_device_t* opersyshw_dev; HfNativeService::HfNativeService()
{
} int HfNativeService::init_native(void)
{
int err;
hw_module_t* module;
opersyshw_device_t* dev = NULL; ALOGI("init_native()"); err = hw_get_module(OPERSYSHW_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == ) {
if (module->methods->open(module, "", ((hw_device_t**) &dev)) != ) {
ALOGE("Can't open opersys module!!!");
return ;
}
} else {
ALOGE("Can't get opersys module!!!");
return ;
} opersyshw_dev = dev; return ;
} void HfNativeService::finalize_native(void)
{
opersyshw_device_t* dev = opersyshw_dev; ALOGI("finalize_native()"); if (dev == NULL) {
return;
} dev->close(); free(dev);
} int HfNativeService::read_native(char *Buff, int Len)
{
opersyshw_device_t* dev = opersyshw_dev;
char* real_byte_array = Buff;
int length; ALOGI("read_native()"); if (dev == NULL) {
return ;
} length = dev->read((char*) real_byte_array, Len); ALOGI("read data from hal: %s", (char *)real_byte_array); return length;
} int HfNativeService::write_native(char *Buff, int Len)
{
opersyshw_device_t* dev = opersyshw_dev;
char* real_byte_array = Buff;
int length; ALOGI("write_native()"); if (dev == NULL) {
return ;
} length = dev->write((char*) real_byte_array, Len); ALOGI("write data to hal: %s", (char *)real_byte_array); return length;
} int HfNativeService::test_native(int value)
{
opersyshw_device_t* dev = opersyshw_dev; if (dev == NULL) {
return ;
} ALOGI("test_native()"); return dev->test(value);
} // ---------------------------------------------------------------------------
}; // namespace android
frameworks/native/services/hfnativeservice/Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) LOCAL_SRC_FILES:= \
HfNativeService.cpp \ LOCAL_CFLAGS:= -DLOG_TAG=\"HfNativeService\" LOCAL_C_INCLUDES += \
$(call include-path-for, libhardware)/hardware LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libhardware \
libhfnativemgriface LOCAL_MODULE:= libhfnativeservice include $(BUILD_SHARED_LIBRARY)
(D) 注册服务端
这里启动添加的的服务,使其运行于一个独立的进程中,等待客户端的请求。
frameworks/native/cmds/hfnative/main_hfnativeservice.cpp
#include <binder/BinderService.h>
#include <HfNativeService.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h> #include <hfnative/IHfNativeService.h> using namespace android; int main(int argc, char** argv) {
#if 1
HfNativeService::publishAndJoinThreadPool(true);
// Like the SurfaceFlinger, limit the number of binder threads to 4.
ProcessState::self()->setThreadPoolMaxThreadCount();
#else sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); sm->addService(String16("hfnativeservice"), new HfNativeService()); ProcessState::self()->startThreadPool();
ProcessState::self()->giveThreadPoolName();
IPCThreadState::self()->joinThreadPool();
ProcessState::self()->setThreadPoolMaxThreadCount();
#endif
return ;
}
frameworks/native/cmds/hfnative/Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) LOCAL_SRC_FILES:= \
main_hfnativeservice.cpp LOCAL_SHARED_LIBRARIES := \
libhfnativeservice \
libbinder \
libutils LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../../services/hfnativeservice LOCAL_MODULE:= hfnativeservice include $(BUILD_EXECUTABLE)
(E) 添加客户端
用户可以根据客户端提供的接口直接使用,无需关心复杂的客户端和服务端的通信细节。使用HfNativeManager
提供的接口,就能实现远程调用。这里创建了一个独立的线程用于等待接收服务端的死亡通知。
frameworks/base/tests/Hfnative/main_hfnativeclient.cpp
#define LOG_TAG "HfNativeClient" #include <fcntl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <unistd.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h> #include <hfnative/HfNativeManager.h> using namespace android; class HfThread: public Thread {
public:
HfNativeManager *hfmgr; HfThread(void *ptr) {
this->hfmgr = (HfNativeManager *)ptr;
} bool threadLoop();
}; bool HfThread::threadLoop()
{
if (hfmgr->checkService()) {
ALOGW("hfnativeservice Died, please do some clear!");
hfmgr->resetServiceStatus();
} usleep(); return true;
} int main(int argc, char **argv)
{
const char *str = {"Hello, Android !\0"};
char buff[strlen(str)]; HfNativeManager *hfmgr = new HfNativeManager(); if (hfmgr->assertState() == NO_ERROR) {
hfmgr->write_queue(const_cast<char *>(str), strlen(str));
usleep();
hfmgr->read_queue(buff, sizeof(buff));
ALOGI("Service returned: %s", buff);
} sp<HfThread> th = new HfThread((void *)hfmgr);
th->run(); ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool(); return ;
}
frameworks/base/tests/Hfnative/Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) LOCAL_SRC_FILES:= \
main_hfnativeclient.cpp LOCAL_SHARED_LIBRARIES := \
libhfnativemgriface \
libbinder \
libutils \
libcutils LOCAL_C_INCLUDES := \
$(ANDROID_SOURCE)/frameworks/native/include/ LOCAL_MODULE:= hfnativeclient include $(BUILD_EXECUTABLE)
(F) 测试
编译后生成对应文件:
out/target/product/<device>/.../system/lib/libhfnativemgriface.so
out/target/product/<device>/.../system/lib/libhfnativeservice.so
out/target/product/<device>/.../system/bin/hfnativeservice
out/target/product/<device>/.../system/bin/hfnativeclient
然后push到机器的相应目录
在机器根目录下,执行以下命令,并观察对应的输出打印(注意要先启动服务端进程):
# cd system/bin
# hfnativeservice &
# service check hfnativeservice
Service hfnativeservice: found
# hfnativeclient &
# kill - pid
对应的输出打印:
......
- ::55.148 I HfNativeService: init_native() - ::55.149 D opersyshw_qemu: OPERSYS HW has been initialized - ::55.150 I HfNativeService: test_native() - ::55.151 I HfNative: test hfnativeservice [] - ::55.151 I HfNativeService: write_native() - ::55.151 D opersyshw_qemu: OPERSYS HW - write()for bytes called - ::55.151 D opersyshw_qemu: write data to driver: Hello, Android ! - ::55.151 I HfNativeService: write data to hal: Hello, Android ! - ::55.252 I HfNativeService: read_native() - ::55.252 D opersyshw_qemu: OPERSYS HW - read()for bytes called - ::55.252 D opersyshw_qemu: read data from driver: Hello, Android ! - ::55.252 I HfNativeService: read data from hal: Hello, Android ! - ::55.252 I HfNativeClient: Service returned: Hello, Android !
......
- ::08.210 W HfNative: hfnativeservice died [0xb6cc90c0] - ::08.210 I ServiceManager: service 'hfnativeservice' died - ::08.269 W HfNativeClient: hfnativeservice Died, please do some clear!
......