首页 > 代码库 > 实现硬件访问服务的JNI方法
实现硬件访问服务的JNI方法
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 <utils/misc.h> #include <utils/Log.h> #include <hardware/hardware.h> #include <hardware/freg.h> #include <stdio.h> 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 <hardware/hardware.h> #include <cutils/properties.h> #include <dlfcn.h> #include <string.h> #include <pthread.h> #include <errno.h> #include <limits.h> #define LOG_TAG "HAL" #include <utils/Log.h> /** 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<HAL_VARIANT_KEYS_COUNT+1 ; i++) { if (i < HAL_VARIANT_KEYS_COUNT) { if (property_get(variant_keys[i], prop, NULL) == 0) {//首先获得的系统属性"ro.hardware"值,在Android模拟器中,这个属性的值定义为"goldfish" continue; } snprintf(path, sizeof(path), "%s/%s.%s.so",//path为/system/lib/hw/freg/goldfish.so HAL_LIBRARY_PATH1, id, prop); if (access(path, R_OK) == 0) break; //判断是否有对应的文件 snprintf(path, sizeof(path), "%s/%s.%s.so",//path为/vendor/lib/hw/freg/goldfish.so HAL_LIBRARY_PATH2, id, prop); if (access(path, R_OK) == 0) break;//判断是否有对应的文件 } else {//如果都没有,执行下面代码 snprintf(path, sizeof(path), "%s/%s.default.so",//path为/system/lib/hw/freg.default.so HAL_LIBRARY_PATH1, id); if (access(path, R_OK) == 0) break;//判断是否有对应的文件,此时有。 } } status = -ENOENT; if (i < HAL_VARIANT_KEYS_COUNT+1) { /* load the module, if this fails, we're doomed, and we should not try * to load a different variant. */ status = load(id, path, module);//id为freg,path为/system/lib/hw/freg.default.so,module为hw_module_t指针的指针 } return status; }
硬件访问服务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 / onl oad.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。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。