if(hello_device_open(&(module->common), &hello_device) == 0) { LOGI(\); return 0; } LOGE(\); return -1; } LOGE(\); return -1; } /*JNI方法表*/ static const JNINativeMethod method_table[] = { {\, \, (void*)hello_init}, {\, \, (void*)hello_setVal}, {\, \, (void*)hello_getVal}, }; /*注册JNI方法*/ int register_android_server_HelloService(JNIEnv *env) { return jniRegisterNativeMethods(env, \, method_table, NELEM(method_table)); } }; 注意文件的命名方法,com_android_server前缀表示的是包名,表示硬件服务HelloService是放在frameworks/base/services/java目录下的com/android/server目录的,即存在一个命名为com.android.server.HelloService的类。这里,我们暂时略去HelloService类的描述,在下一篇文章中,我们将回到HelloService类来。简单地说,HelloService是一个提供Java接口的硬件访问服务类 在这个cpp文件中,我们主要是做了以下事情
1、包括头文件
(尤其是在hal层所定义的头文件)
#define LOG_TAG \ #include \ #include \ #include \
#include
注意,linux driver -- hal -- jni, jni与linux driver并无直接关系,即jni的函数接口与linux driver不一定完全一一对应,很简单的一个例子便是在linux driver中可能只有一个ioctl函数,可是在hal层却通过对ioctl的调用实现了get,set,exchange等多个功能. /*通过硬件抽象层定义的硬件访问接口设置硬件寄存器val的值*/ static void hello_setVal(JNIEnv* env, jobject clazz, jint value) { int val = value; LOGI(\, val); if(!hello_device) { LOGI(\); return; } hello_device->set_val(hello_device, val); } /*通过硬件抽象层定义的硬件访问接口读取硬件寄存器val的值*/ static jint hello_getVal(JNIEnv* env, jobject clazz) { int val = 0; if(!hello_device) { LOGI(\); return val; } hello_device->get_val(hello_device, &val); LOGI(\, val); return val; } 3、定义jni加载函数,注册jni方法表 /*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/
static inline int hello_device_open(const hw_module_t* module, struct hello_device_t** device) { return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device); } /*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/ static jboolean hello_init(JNIEnv* env, jclass clazz) { hello_module_t* module; LOGI(\); if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) { LOGI(\); if(hello_device_open(&(module->common), &hello_device) == 0) { LOGI(\); return 0; } LOGE(\); return -1; } LOGE(\); return -1; } /*JNI方法表*/ static const JNINativeMethod method_table[] = { {\, \, (void*)hello_init}, {\, \, (void*)hello_setVal}, {\, \, (void*)hello_getVal}, }; /*注册JNI方法*/ int register_android_server_HelloService(JNIEnv *env) { return jniRegisterNativeMethods(env, \, method_table, NELEM(method_table)); } 其中,上面示例中的jni加载函数hello_init是通过hal中定义的hello_device_open函数实现的。在hello_init函数中,通过Android硬件抽象层提供的hw_get_module方法来加载模块ID为HELLO_HARDWARE_MODULE_ID的硬件抽象层模块,其中,
HELLO_HARDWARE_MODULE_ID是在
二、修改onload.cpp,使系统启动时自动加载JNI方法调用表
修改frameworks/base/services/jni/onload.cpp:
1、 在namespace android增加register_android_server_HelloService函数声明: 2、 namespace android { 3、 //...... 4、 int register_android_server_HelloService(JNIEnv *env); 5、 }; 6、 这样,在Android系统初始化时,就会自动加载该JNI方法调用表。
三、修改Android.mk文件,添加编译路径 打开frameworks/base/services/jni/Android.mk,在LOCAL_SRC_FILES变量中增加一行:
LOCAL_SRC_FILES:= com_android_server_AlarmManagerService.cpp com_android_server_BatteryService.cpp com_android_server_InputManager.cpp com_android_server_LightsService.cpp com_android_server_PowerManagerService.cpp com_android_server_SystemServer.cpp com_android_server_UsbService.cpp com_android_server_VibratorService.cpp com_android_server_location_GpsLocationProvider.cpp com_android_server_HelloService.cpp / onload.cpp
四、编译和重新生成system.img $:mmm frameworks/base/services/jni $:make snod
这样,重新打包的system.img镜像文件就包含我们刚才编写的JNI方法了
[编写Framework接口]
在Android系统中,硬件服务一般是运行在一个独立的进程中为各种应用程序提供服务。因此,调用这些硬件服务的应用程序与这些硬件服务之间的通信需要通过代理来进行。
一、定义通信接口
1、新增接口文件
进入到frameworks/base/core/java/android/os目录,新增IHelloService.aidl接口定义文件:
package android.os; interface IHelloService { void setVal(int val); int getVal(); } IHelloService接口主要提供了设备和获取硬件寄存器val的值的功能,分别通过setVal和getVal两个函数来实现。 2、添加编译路径
返回到frameworks/base目录,打开Android.mk文件,修改LOCAL_SRC_FILES变量的值,增加IHelloService.aidl源文件: LOCAL_SRC_FILES += /