3 JNI
3.1 初始化Lights设备
在LightsService初始化时调用的init_native方法如下:
static jlong init_native(JNIEnv* /* env */, jobject /* clazz */)
{
int err;
hw_module_t* module;
Devices* devices;
devices = (Devices*)malloc(sizeof(Devices));
err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
devices->lights[LIGHT_INDEX_BACKLIGHT]
= get_device(module, LIGHT_ID_BACKLIGHT);
devices->lights[LIGHT_INDEX_KEYBOARD]
= get_device(module, LIGHT_ID_KEYBOARD);
...
} ...
return (jlong)devices;
}
该方法主要是完成lights设备的初始化,为每一个light绑定一个硬件设备对象。其中devices是一个灯设备的数组,
用来保存本地为灯设备分配的存储空间,最终会返回这个数组的首地址,它的定义如下:
struct Devices {light_device_t* lights[LIGHT_COUNT];};
light_device_t的定义位于lights.h中,定义如下:
struct light_device_t {
struct hw_device_t common;
int (*set_light)(struct light_device_t* dev,
struct light_state_t const* state);
};
其中包含了一个硬件设备结构体,定义在hardware.h,类似于面向对象中的继承,也就是light_device_t是继承自hw_device_t的。
在完成数组空间分配后,通过hw_get_module方法会获取一个灯设备的硬件模型赋值给module指针,通过这个硬件模型可以为
每一个灯设备打开一个逻辑硬件设备,这个过程是通过get_device方法完成的:
static light_device_t* get_device(hw_module_t* module, char const* name)
{
int err;
hw_device_t* device;
err = module->methods->open(module, name, &device);
if (err == 0) {
return (light_device_t*)device;
} else {
return NULL;
}
}
通过module调用open方法来打开硬件设备,这个open方法是每一个硬件模型中都具备的方法,详细实现过程将在分析硬件
抽象层代码时进行讲述。在此处还将硬件设备强制转换返回到light设备,用到了向下转型(downcast)。在初始化过程中会为
每个灯分配空间并打开对应的硬件设备。
3.2 本地setLight方法
本地设置灯的方法如下:
static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
{
Devices* devices = (Devices*)ptr;
light_state_t state;
if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
return ;
}
memset(&state, 0, sizeof(light_state_t));
state.color = colorARGB;
state.flashMode = flashMode;
state.flashOnMS = onMS;
state.flashOffMS = offMS;
state.brightnessMode = brightnessMode;
devices->lights[light]->set_light(devices->lights[light], &state);
}
可以看到在JNI方法中,都会携带诸如JNIEnv,jobject这样的参数类型,而Java层的LightsService并没有带这些参数。
实际上它代表的是子类的实例化对象指针,类似于this指针,JNIEnv的定义如下:
typedef const struct JNINativeInterface *JNIEnv;
JNINativeInterface是一个JNI的本地接口,定义在jni.h,包含了很多实用的函数。而jobject则代表了这个本地类方法对应的java类实例[3]。
该方法将出入的参数赋值给light_state_t结构体,这个结构体定义在light.h中。通过调用底层方法set_light时将设置的状态传入,
set_light方法位于底层代码light.c中,接下来会分析。