android HAL层例子

上一篇文章已经写了led驱动,这篇文章我们再封装HAL层

1.在源码hardware/libhardware/include/hardware/目录下增加test_led_hal.h

内容如下

#ifndef TEST_LED_HAL_H
#define TEST_LED_HAL_H

#include <hardware/hardware.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>

#define LED_HARDWARE_MODULE_ID "test_led"


//HAL 规定不能直接使用hw_module_t结构,因此需要做这么一个继承。
//见hardware.h中的hw_module_t定义的说明,xxx_module_t的第一个成员必须是hw_module_t类型,其次才是模块的一此相关信息,当然也可以不定义,  
//这里就没有定义模块相关信息
struct led_module_t {
	struct hw_module_t common; 
	/* support API for LEDServices constructor */
};


//自定义的一个针对Led控制的结构,包含hw_device_t和支持的API操作 
//见hardware.h中的hw_device_t的说明,要求自定义xxx_device_t的第一个成员必须是hw_device_t类型,其次才是其它的一些接口信息. 
struct led_control_device_t {
	struct hw_device_t common;
	/* supporting control APIs go here */
	int (*led_set_on)(struct led_control_device_t *dev);

};

#endif

 

 2.在源码hardware\libhardware\modules目录下建一个目录test_led,再在该目录下面创建两个文件test_led_hal.c、Android.mk 内容分别如下:

#define LOG_TAG "LedStub"
#include <hardware/hardware.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#include <sys/ioctl.h>
#include <hardware/test_led_hal.h>

#define LED_ON 0x4800

//硬件led的设备描述符 。你也可以用led_control_device_t结构中定义的fd 
int fd;

static int led_device_close(struct hw_device_t* device) {
	struct led_control_device_t* ctx = (struct led_control_device_t*) device;
	if (ctx) {
		free(ctx);
	}
	close(fd);
	return 0;
}

static int led_set_on(struct led_control_device_t *dev) {
	//FIXME: do system call to control gpio led
	LOGI("led_set_on");
	ioctl(fd, LED_ON, NULL);
	return 0;
}

static int led_device_open(const struct hw_module_t* module, const char* name,
		struct hw_device_t** device) {

	struct led_control_device_t* dev = (struct led_control_device_t*) malloc(
			sizeof(struct led_control_device_t)); //动态分配空间  

	if (!dev) {
		LOGE("TestLed Stub: failed to alloc space");
		return -EFAULT;
	}

	memset(dev, 0, sizeof(struct led_control_device_t));

	//对dev->common的内容赋值,   
	dev->common.tag = HARDWARE_DEVICE_TAG;  //必须为这个值
	dev->common.version = 0;
	dev->common.module = (hw_module_t*) module;
	dev->common.close = led_device_close;

	// 初始化控制 API
	dev->led_set_on = led_set_on; //实例化支持的操作
	//打开硬件设备 
	if ((fd = open("/dev/testLed2", O_RDWR)) == -1) {
		LOGI("open error");
		free(dev);
		return -EFAULT;
	} else {
		LOGI("open ok\n");
	}
	 //将实例化后的led_control_device_t地址返回给jni层  ,这样jni层就可以直接调用API方法了
	*device = (struct hw_device_t *) (&(dev->common));
	return 0;
}

static struct hw_module_methods_t led_module_methods = {
	open: led_device_open
};

//定义这个对象等于向系统注册了一个ID为LED_HARDWARE_MODULE_ID的stub。注意这里HAL_MODULE_INFO_SYM的名称不能改。  
const struct led_module_t HAL_MODULE_INFO_SYM = {
	common: {
		tag: HARDWARE_MODULE_TAG,        //必须为 HARDWARE_MODULE_TAG
		version_major: 1,
		version_minor: 0,
		id: LED_HARDWARE_MODULE_ID,
		name: "led HAL module",
		author: "kk",
		methods: &led_module_methods,//实现了一个open的方法供jni层调用,  从而实例化led_control_device_t 
	},
	/* supporting APIs go here */
};

 

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test_led.default
LOCAL_PRELINK_MODULE := false
LOCAL_SHARED_LIBRARIES := liblog libcutils lm -llog

# set shared libary out path
#TARGET_OUT_SHARED_LIBRARIES:= $(TARGET_OUT)/lib/hw 
LOCAL_MODULE_PATH :=$(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SRC_FILES := test_led_hal.c

include $(BUILD_SHARED_LIBRARY) 

3.重新编译,生成HAL层接口。APP可以直接通过jni代码调用HAL,也可以再封装一层SystemServer,SystemServer调用HAL,然后APP通过AIDL调用SystemServer

4.以下为jni调用的部分例子代码:com_android_server_test_led.cpp

#define LOG_TAG "LedService"
#include "utils/Log.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <jni.h>
#include "test_led_hal.h"

namespace android {

static led_control_device_t *sLedDevice = 0;
static led_module_t* sLedModule = 0;

static jint led_setOn(JNIEnv* env, jobject thiz) {
	ALOGE("%s E", __func__);
	if (sLedDevice) {
		sLedDevice->led_set_on(sLedDevice); //调用hal层的注册的方法  
	} else {
		ALOGE("sLedDevice is null");
	}
	return 0;
}

/** helper APIs */
static inline int led_control_open(const struct hw_module_t* module,
		struct led_control_device_t** device) {
	ALOGE("%s E ", __func__);
	return module->methods->open(module, LED_HARDWARE_MODULE_ID,
			(struct hw_device_t**) device);
	//这个过程非常重要,jni通过LED_HARDWARE_MODULE_ID找到对应的stub  
}

//hw_get_module获得一个hw_module_t结构体 ,调用 module->methods->open(module, device_name, &device) 获得一个hw_device_t结构体,并且把hw_device_t结构体转换为设备自定义的结构体  

static jint led_init(JNIEnv *env, jclass clazz) {
	led_module_t const * module;
	ALOGE("%s E ", __func__);

	if (hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**) &module)
			== 0) {
		//根据LED_HARDWARE_MODULE_ID找到hw_module_t,参考hal层的实现
		ALOGE("get Module OK");
		sLedModule = (led_module_t *) module;
		if (led_control_open(&module->common, &sLedDevice) != 0) {
			//通过hw_module_t找到led_control_device_t  
			ALOGE("led_init error");
			return -1;
		}
	}

	ALOGE("led_init success");
	return 0;
}

//Framework层调用的映射,第一个参数为jni暴露给java的方法,第三个参数为jni层的方法,即为一个函数指针
//第二个参数:“()” 中的字符表示参数,后面的则代表返回值。例如”()V” 就表示void * Fun();
//		“(II)V” 表示 void Fun(int a, int b);
//		“(II)I” 表示 int addInt(int a, int b);
//		"()Ljava/lang/String;" 表示String getStr();

static const JNINativeMethod gMethods[] = { { "led_init", "()I",
		(void*) led_init }, { "set_on", "()I", (void*) led_setOn }, };

int register_android_server_TestLedService(JNIEnv* env) {

	//注意:必须和你Framework层的service类名相同
//	static const char* const kClassName = "com/android/server/test_led";
	//或者jni暴露给java层的类所在路径相同,这里因为不做成SystemServer,所以名字可以修改为com/test/hardware/TestLed,只需要在app保护一个类com.test.hardware.TestLed.java即可,
	static const char* const kClassName = "com/test/hardware/TestLed";

	jclass clazz;
	/* look up the class */
	clazz = env->FindClass(kClassName);
	if (clazz == NULL) {
		ALOGE("Can't find class %s\n", kClassName);
		return -1;
	}

	/* register all the methods */
	if (env->RegisterNatives(clazz, gMethods,
			sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK) {
		ALOGE("Failed registering methods for %s\n", kClassName);
		return -1;
	}
	/* fill out the rest of the ID cache */
	return 0;
}

/*
 *
 *  java调用 System.loadLibrary触发该函数。因为在这里我们直接集成到libandroid_servers.so,所以这个函数不使用
 */
//jint JNI_OnLoad(JavaVM* vm, void* reserved) {
//
//	JNIEnv* env = NULL;
//	ALOGE("JNI_OnLoad");
//
//	//从JavaVM获取JNIEnv,一般使用1.4的版本
//	if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
//		ALOGE("ERROR: GetEnv failed\n");
//		return -1;
//	}
//
//	if (env == NULL) {
//
//		ALOGE("ERROR: env is NULL\n");
//		return -1;
//	}
//
//	if (register_android_server_TestLedServi(env) != 0) { //注册你的JNINativeMethod  
//		ALOGE("ERROR: PlatformLibrary native registration failed\n");
//		return -1;
//	}
//	//这里很重要,必须返回版本,否则加载会失败
//	return JNI_VERSION_1_4;
//}
}

 

猜你喜欢

转载自blog.csdn.net/jingzitakk66/article/details/89146695