从Android 应用程序到Android Framework层到Android JNI层再到HAL层

Agenda:

首先做一个简单的概述:

Android 为什么要有HAL层?为什么不能将这层接口写在内核空间中?

我们知道,Linux内核源代码版权遵循GNU License,而Android源代码版权遵循Apache License,前者在发布产品时,必须公布源代码,而后者无须发布源代码。那么假如把HAL层和内核层整合在一起,就必须公开,这样就会损害厂家的利益,因为功能上的逻辑可是代表着这个公司的核心技术。所以就有了HAL层,这一层主要是功能上的逻辑实现,运行在用户空间。

下面是与硬件抽象层相关的各个层的关系:

首先在驱动上对硬件直接进行操作,但是这些操作都是最基本的,例如读写寄存器等等。而在HAL层是程序员为了实现一个特定功能,设计编写具体的操作逻辑。在HAL层是c代码,JNI层通过封装HAL层的接口为上层提供接口。

HAL 层具体介绍:

/hardware/libhardware/include/hardware$ vi hello.h

这里面的代码为:

#ifndef ANDROID_HELLO_INTERFACE_H  
#define ANDROID_HELLO_INTERFACE_H  
#include <hardware/hardware.h>  
  
__BEGIN_DECLS  
  
/*定义模块ID*/  
#define HELLO_HARDWARE_MODULE_ID "hello"  
  
/*硬件模块结构体*/  
struct hello_module_t {  
    struct hw_module_t common;  
};  
  
/*硬件接口结构体*/  
struct hello_device_t {  
    struct hw_device_t common;  
    int fd;  
    int (*set_val)(struct hello_device_t* dev, int val);  
    int (*get_val)(struct hello_device_t* dev, int* val);  
};  
  
__END_DECLS  
  
#endif 

首先介绍代码结构:HAL层代码一般放在hardware/libhardware中,这里我们假设内核中有个hello.so驱动模块,相应的在HAL层定义hal层模块为hello.default.so。

hello.h 里面按照Android硬件抽象层规范的要求,分别定义模块ID、模块结构体以及硬件接口结构体。

进入到hardware/libhardware/modules目录,新建hello目录,并添加hello.c文件。 hello.c的内容较多,我们分段来看。

首先是包含相关头文件和定义相关结构:

#define LOG_TAG "HelloStub"  
  
#include <hardware/hardware.h>  
#include <hardware/hello.h>  
#include <fcntl.h>  
#include <errno.h>  
#include <cutils/log.h>  
#include <cutils/atomic.h>  
  
#define DEVICE_NAME "/dev/hello"  
#define MODULE_NAME "Hello"  
#define MODULE_AUTHOR "shyluo@gmail.com"  
  
/*设备打开和关闭接口*/  
static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);  
static int hello_device_close(struct hw_device_t* device);  
  
/*设备访问接口*/  
static int hello_set_val(struct hello_device_t* dev, int val);  
static int hello_get_val(struct hello_device_t* dev, int* val);  
  
/*模块方法表*/  
static struct hw_module_methods_t hello_module_methods = {  
    open: hello_device_open  
};  
  
/*模块实例变量*/  
struct hello_module_t HAL_MODULE_INFO_SYM = {  
    common: {  
        tag: HARDWARE_MODULE_TAG,  
        version_major: 1,  
        version_minor: 0,  
        id: HELLO_HARDWARE_MODULE_ID,  
        name: MODULE_NAME,  
        author: MODULE_AUTHOR,  
        methods: &hello_module_methods,  
    }  
};
    static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {  
        struct hello_device_t* dev;dev = (struct hello_device_t*)malloc(sizeof(struct hello_device_t));  
          
        if(!dev) {  
            LOGE("Hello Stub: failed to alloc space");  
            return -EFAULT;  
        }  
      
        memset(dev, 0, sizeof(struct hello_device_t));  
        dev->common.tag = HARDWARE_DEVICE_TAG;  
        dev->common.version = 0;  
        dev->common.module = (hw_module_t*)module;  
        dev->common.close = hello_device_close;  
        dev->set_val = hello_set_val;dev->get_val = hello_get_val;  
      
        if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {  
            LOGE("Hello Stub: failed to open /dev/hello -- %s.", strerror(errno));free(dev);  
            return -EFAULT;  
        }  
      
        *device = &(dev->common);  
        LOGI("Hello Stub: open /dev/hello successfully.");  
      
        return 0;  
    }  


 
原文地址:https://www.cnblogs.com/alexjie/p/3548047.html