Android7.0 APP调用驱动流程 JNI层开发流程

Java Native Interface(JNI)是Java语言的本地编程接口,通过JNI能直接调用c++实现代码,Android系统也是通过JNI到达Java调用c++的目的。其中JNI的语法并且与c++数据结构之间的转换对应关系这里不解释,大家可以参考其他书籍。

上一章节我们已经在HAL层开发了硬件模块,在JNI层可以获取HAL层的硬件模块来完成对底层驱动的读写操作。

5.1 自定义与实现Jni接口

进入到目录:frameworks/base/services/core/jni 这里可以看到很多JNI实现。Android7.0 APP调用驱动流程 JNI层开发流程_第1张图片

我们可以随便找一个文件,按照上面的流程进行开发。这里可以看到com_android_server_IbankGpioService.cpp实现文件。

#define LOG_TAG "IbankGpioJNI"

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include 
#include 
#include 
#include 
#include 
#include 

GpioDev_device_t* m_pDev = NULL;
namespace android
{
	static void WriteDevNode(JNIEnv* env, jobject clazz, jint ptr, jint value) {
	//	GpioDev_device_t* device = (GpioDev_device_t*)ptr;
		GpioDev_device_t* device = m_pDev;
		ALOGE("grgDevice WriteDevNode");
		if(!device) {
			ALOGE("grgDevice gpio is not open.");
			return;
		}	
		int val = value;
		ALOGE("Set value %d to device gpio.", val);
		char path[10]={0};
		device->writeGpioNode(device, val,path);
	}
	
	static jint ReadDevNode(JNIEnv* env, jobject clazz, jint ptr) {
		GpioDev_device_t* device = m_pDev;
		ALOGE("grgDevice ReadDevNode");
		if(!device) {
			ALOGE("Device gpio is not open.");
			return 0;
		}
		int val = -1;
		device->readGpioNode(device, &val);
		ALOGE("Get value %d from device gpio.", val);
		return val;
	}
	
	static inline int gpio_device_open(const hw_module_t* module, struct GpioDev_device_t** device) {
		return module->methods->open(module, GRGDEV_HARDWARE_DEVICE_ID, (struct hw_device_t**)device);
	}
	
	static jint gpio_dev_init(JNIEnv* env, jclass clazz) {
		GpioDev_module_t* module;
		GpioDev_device_t* device;
		
		ALOGE("Initializing HAL stub gpio......");

		if(hw_get_module(GRGDEV_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {
			ALOGI("grg Device  found.");
			if(gpio_device_open(&(module->common), &device) == 0) {
				ALOGI("grg Device gpio is open.");
				m_pDev = device;
			//	return (jint)device;
				return (jint)1;
			}
			ALOGE("Failed to open device gpio.");
			return 0;
		}

		ALOGE("Failed to get HAL stub.");
		return 0;		
	}
	//将JNI接口与本地接口进行绑定,要注意数据类型的转换
	static const JNINativeMethod method_table[] = {
		{"init_native", "()I", (void*)gpio_dev_init},
		{"writeDevNode_native", "(II)V", (void*)WriteDevNode},
		{"readDevNode_native", "(I)I", (void*)ReadDevNode},
	};
 //注册JNI代码,并与接口进行绑定com/android/server/GrgIBanking/GrgIBankService
	int register_android_server_GpioDevService(JNIEnv *env) {
    		return jniRegisterNativeMethods(env, "com/android/server/GrgIBanking/GrgIBankService", method_table, NELEM(method_table));
	}
};

上面出现的GpioDev_device_t、GpioDev_module_t等数据结构是在HAL层定义的,这里可以通过GRGDEV_HARDWARE_MODULE_ID找到我们实现的HAL模块,在HAL层模块中又可以通过GRGDEV_HARDWARE_DEVICE_ID找到对应的驱动设备。

在上面gpio_dev_init函数中,通过系统函数hw_get_module()找到ID为GRGDEV_HARDWARE_MODULE_ID HAL模块驱动模块,然后调用模块的open函数(这里在HAL层已经对open赋值)。打开成功之后会返回一个GpioDev_device_t驱动设备,通过这个GpioDev_device_t驱动设备我们就可以调用HAL层的读写函数了。

 method_table 定义JNI函数接口与本地c++函数实现进行绑定,这里就会涉及到JNI编程标准数据结构转换,大家可以参考网上资料进行转换。定义完成之后通过jniRegisterNativeMethods进行注册。

完成com_android_server_IbankGpioService.cpp文件后,需要在当前目录下找到onload.cpp文件:

frameworks/base/services/core/jni/onload.cpp,并增加以下代码:

定义register_android_server_GpioDevService接口:Android7.0 APP调用驱动流程 JNI层开发流程_第2张图片

在JNI_OnLoad()函数里进行调用。

Android7.0 APP调用驱动流程 JNI层开发流程_第3张图片

这个register_android_server_GpioDevService接口实现是在com_android_server_IbankGpioService.cpp里面,也就是我们定义的JNI接口与本地C++实现函数进行绑定的地方,这里应该是说告诉Java JVM定义了哪些JNI接口,不然在java中无法调用这些JNI接口。

5.2 编译Jni接口

在当前目录下frameworks/base/services/core/jni/Android.mk 文件中找到LOCAL_SRC_FILES,按规则添加com_android_server_IbankGpioService.cpp ,这里是告诉编译器需要编译增加的JNI实现文件。

Android7.0 APP调用驱动流程 JNI层开发流程_第4张图片

至此,JNI的实现已经开发完成,从这里可以看出我们定义了三个JNI接口gpio_dev_init、WriteDevNode、ReadDevNode并且已经在com_android_server_IbankGpioService.cpp对其实现,也将其编译进入系统,在freamwork层中就可以使用JAVA代码进行调用。

你可能感兴趣的:(Android7.0,系统层开发教程)