1、实现硬件访问服务的JNI方法
~/android-2.3_r1/frameworks/base/services/jni
----com_android_server_FregService.cpp
----onload.cpp
----Android.mk
com_android_server_FregService.cpp
#define LOG_TAG "FregServiceJNI"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include
#include
#include
#include
#include
namespace android
{
static void freg_setVal(JNIEnv* env, jobject clazz, jint ptr, jint value) {//ptr为硬件设备地址,value为要写入的数据
freg_device_t* device = (freg_device_t*)ptr;
if(!device) {
LOGE("Device freg is not open.");
return;
}
int val = value;
LOGI("Set value %d to device freg.", val);
device->set_val(device, val);//调用硬件抽象层的freg_set_val方法
}
static jint freg_getVal(JNIEnv* env, jobject clazz, jint ptr) {//ptr为硬件设备地址
freg_device_t* device = (freg_device_t*)ptr;
if(!device) {
LOGE("Device freg is not open.");
return 0;
}
int val = 0;
device->get_val(device, &val);//调用硬件抽象层的freg_get_val方法
LOGI("Get value %d from device freg.", val);
return val;
}
static inline int freg_device_open(const hw_module_t* module, struct freg_device_t** device) {
return module->methods->open(module, FREG_HARDWARE_DEVICE_ID, (struct hw_device_t**)device);//调用硬件抽象层的函数freg_device_open根据ID来打开对应的设备,并返回硬件设备地址返回
}
static jint freg_init(JNIEnv* env, jclass clazz) {
freg_module_t* module;
freg_device_t* device;
LOGI("Initializing HAL stub freg......");
if(hw_get_module(FREG_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {//根据ID获取硬件抽象层模块
LOGI("Device freg found.");
if(freg_device_open(&(module->common), &device) == 0) {//调用上面的函数
LOGI("Device freg is open.");
return (jint)device;//返回硬件设备地址
}
LOGE("Failed to open device freg.");
return 0;
}
LOGE("Failed to get HAL stub freg.");
return 0;
}
static const JNINativeMethod method_table[] = {//要注册的函数,只有注册才能够供上层调用
{"init_native", "()I", (void*)freg_init},
{"setVal_native", "(II)V", (void*)freg_setVal},
{"getVal_native", "(I)I", (void*)freg_getVal},
};
int register_android_server_FregService(JNIEnv *env) {//注册JNI函数
return jniRegisterNativeMethods(env, "com/android/server/FregService", method_table, NELEM(method_table));
}
};
在函数freg_init中,首先通过Android硬件抽象层提供的hw_get_module函数来加载模块ID为FREG_HARDWARE_MODULE_ID的硬件抽象层模块。
hw_get_module实现如下:
~/android-2.3_r1/hardware/libhardware
----hardware.c
.....
#include
#include
#include
#include
#include
#include
#include
#define LOG_TAG "HAL"
#include
/** Base path of the hal modules */
#define HAL_LIBRARY_PATH1 "/system/lib/hw" //编译好的模块文件位于out/target/product/generic/system/lib/hw目录中,而这个目录经过打包后,就对应设备上的/system/lib/hw目录
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
....
static const char *variant_keys[] = { //系统属性
"ro.hardware", /* This goes first so that it can pick up a different
file on the emulator. */
"ro.product.board",
"ro.board.platform",
"ro.arch"
};
static const int HAL_VARIANT_KEYS_COUNT =
(sizeof(variant_keys)/sizeof(variant_keys[0]));//大小
/**
* Load the file defined by the variant and if successful
* return the dlopen handle and the hmi.
* @return 0 = success, !0 = failure.
*/
static int load(const char *id,
const char *path,
const struct hw_module_t **pHmi)
{
int status;
void *handle;
struct hw_module_t *hmi;
/*
* load the symbols resolving undefined symbols before
* dlopen returns. Since RTLD_GLOBAL is not or'd in with
* RTLD_NOW the external symbols will not be global
*/
handle = dlopen(path, RTLD_NOW);//path为/system/lib/hw/freg.default.so
if (handle == NULL) {
char const *err_str = dlerror();
LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}
/* Get the address of the struct hal_module_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;//HMI
hmi = (struct hw_module_t *)dlsym(handle, sym);//根据HMI获取到在硬件抽象层定义的freg_module_t结构体HAL_MODULE_INFO_SYM指针,并转换为一个hw_module_t结构体指针
if (hmi == NULL) {
LOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}
/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {//FREG_HARDWARE_MODULE_ID==FREG_HARDWARE_MODULE_ID
LOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}
hmi->dso = handle;//模块句柄值handle保存在hw_module_t结构体指针hmi的成员变量dso中。
/* success */
status = 0;
done:
if (status != 0) {
hmi = NULL;
if (handle != NULL) {
dlclose(handle);
handle = NULL;
}
} else {
LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}
*pHmi = hmi;//把指向hw_module_t结构体的指针返回去
return status;
}
int hw_get_module(const char *id, const struct hw_module_t **module)
{
int status;
int i;
const struct hw_module_t *hmi = NULL;
char prop[PATH_MAX];
char path[PATH_MAX];
/*
* Here we rely on the fact that calling dlopen multiple times on
* the same .so will simply increment a refcount (and not load
* a new copy of the library).
* We also assume that dlopen() is thread-safe.
*/
/* Loop through the configuration variants looking for a module */
for (i=0 ; i
硬件访问服务FregService的JNI方法编写完成之后,我们还需要修改frameworks/base/services/jni目录下的onLoad.cpp文件,在里面增加register_android_server_FregService函数的声明和调用。
onload.cpp
namespace android {
..............................................................................................
int register_android_server_FregService(JNIEnv *env);
};
在JNI_onLoad增加register_android_server_FregService函数调用:
extern "C" jint JNI_onLoad(JavaVM* vm, void* reserved)
{
.................................................................................................
register_android_server_FregService(env);
.................................................................................................
}
Android.mk
LOCAL_SRC_FILES:= \
.......
com_android_server_FregService.cpp /
onload.cpp
2、编译
硬件访问服务的JNI方法
编译后得到的libandroid_servers.so位于out/target/product/generic/system/lib,就包含有init_native、setVal_native和getVal_native这三个JNI方法了。
打包:
在out/target/product/gerneri目录下会生成Android系统镜像文件system.img。