企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
在Android系统中,通常把硬件访问服务的JNI方法实现在frameworks/base/services/jni目录中,因此,我们把实现了硬件访问服务FregService的JNI方法的com_android_server_FregService.cpp文件也保存在这个目录中,它的内容如下所示。 **frameworks/base/services/jni/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 { /*设置虚拟硬件设备freg的寄存器的值*/ static void freg_setVal(JNIEnv* env, jobject clazz, jint ptr, jint value) { /*将参数ptr转换为freg_device_t结构体变量*/ 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的寄存器的值*/ static jint freg_getVal(JNIEnv* env, jobject clazz, jint ptr) { /*将参数ptr转换为freg_device_t结构体变量*/ 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); LOGI("Get value %d from device freg.", val); return val; } /*打开虚拟硬件设备freg*/ 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*/ static jint freg_init(JNIEnv* env, jclass clazz) { freg_module_t* module; freg_device_t* device; LOGI("Initializing HAL stub freg......"); /*加载硬件抽象层模块freg*/ if(hw_get_module(FREG_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) { LOGI("Device freg found."); /*打开虚拟硬件设备freg*/ if(freg_device_open(&(module->common), &device) == 0) { LOGI("Device freg is open."); /*将freg_device_t接口转换为整型值返回*/ return (jint)device; } LOGE("Failed to open device freg."); return 0; } LOGE("Failed to get HAL stub freg."); return 0; } /*Java本地接口方法表*/ 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}, }; /*注册Java本地接口方法*/ int register_android_server_FregService(JNIEnv *env) { return jniRegisterNativeMethods(env, "com/android/server/FregService", method_table, NELEM(method_table)); } }; ~~~ 在函数freg_init中,首先通过Android硬件抽象层提供的hw_get_module函数来加载模块ID为FREG_HARDWARE_MODULE_ID的硬件抽象层模块。在2.3.3小节中,我们已经介绍过hw_get_module函数是如何根据FREG_HARDWARE_MODULE_ID来加载Android硬件抽象层模块freg的了。函数hw_get_module最终返回一个hw_module_t接口给freg_init函数,这个hw_module_t接口实际指向的是自定义的一个硬件抽象层模块对象,即一个freg_module_t对象。 函数freg_init接着调用函数freg_device_open来打开设备ID为FREG_HARDWARE_DEVICE_ID的硬件设备,而后者又是通过调用前面获得的hw_module_t接口的操作方法列表中的open函数来打开指定的硬件设备的。在2.3.2小节中,我们将硬件抽象层模块freg的操作方法列表中的open函数设置为freg_device_open,这个函数最终返回一个freg_device_t接口给freg_init函数。 函数freg_init最后把获得的freg_device_t接口转换成一个整型句柄值,然后返回给调用者。 函数freg_setVal和freg_getVal都是首先把参数ptr转换为一个freg_device_t接口,然后分别调用它的成员函数set_val和get_val来访问虚拟硬件设备freg的寄存器val的值。 注意:在调用freg_setVal和freg_getVal这两个JNI方法之前,调用者首先要调用JNI方法freg_init打开虚拟硬件设备freg,以便可以获得一个freg_device_t接口。 文件接着定义了一个JNI方法表method_table,分别将函数freg_init、freg_setVal和freg_getVal的JNI方法注册为init_native、setVal_native和getVal_native。文件最后调用了jniRegisterNativeMethods函数把JNI方法表method_table注册到Java虚拟机中,以便提供给硬件访问服务FregService使用。 硬件访问服务FregService的JNI方法编写完成之后,我们还需要修改frameworks/base/services/jni目录下的onload.cpp文件,在里面增加register_android_server_FregService函数的声明和调用。 **frameworks/base/services/jni/onload.cpp** ~~~ #include "JNIHelp.h" #include "jni.h" #include "utils/Log.h" #include "utils/misc.h" namespace android { ...... int register_android_server_FregService(JNIEnv* env); }; using namespace android; extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { ...... register_android_server_FregService(env); return JNI_VERSION_1_4; } ~~~ onload.cpp文件实现在libandroid_servers模块中。当系统加载libandroid_servers模块时,就会调用实现在onload.cpp文件中的JNI_OnLoad函数。这样,就可以将前面定义的三个JNI方法init_native、setVal_native和getVal_native注册到Java虚拟机中。 最后,进入到frameworks/base/services/jni目录中,打开里面的Android.mk文件,修改变量LOCAL_SRC_FILES的值。 ~~~ LOCAL_SRC_FILES += \ ...... com_android_server_FregService.cpp \ onload.cpp ~~~ 修改好这个文件之后,我们就可以执行mmm命令来重新编译libandroid_servers模块了。 ~~~ USER@MACHINE:~/Android$ mmm ./frameworks/base/services/jni/ ~~~ 编译后得到的libandroid_servers.so文件就包含有init_native、setVal_native和getVal_native这三个JNI方法了。 至此,硬件访问服务FregService的实现就介绍完了。下面我们继续介绍如何在系统进程System中启动它。