
本文共 3205 字,大约阅读时间需要 10 分钟。
Android系统的硬件抽象层(Hardware Abstract Layer, HAL)运行在用户空间中,它向下屏蔽硬件驱动模块的实现细节,向上提供硬件访问服务。通过硬件抽抽象层,Android系统分为两层来支持硬件设备,其中一层实现在用户空间(User Space),另外一层是内核空间(Kernel Space)。传统的Linux系统将对硬件的支持完全放在内核空间中,但由于Android系统遵循开源协议GPL,如果对硬件的支持逻辑全部放在内核空间中,厂商的商业机密将无法保护。因此,Android系统将硬件支持分为两层:内核驱动层负责底层硬件操作,而硬件抽象层模块则负责上层接口定义和操作逻辑,保护厂商的利益。
硬件抽象层概述
硬件抽象层模块(HAL Module)在Android系统中以动态链接库(.so文件)的形式存在。模块文件的命名规范为“<MODULE_ID>.variant.so”,其中<MODULE_ID>为模块ID,variant表示系统属性(如ro.hardware、ro.product.board等),具体取值由系统属性决定。系统属性ro.hardware的值通常来自/proc/cmdline或/proc/cpuinfo文件,而ro.product.board、ro.board.platform和ro.arch则来自/system/build.prop文件。
硬件抽抽象层模块结构体hw_module_t和设备结构体hw_device_t的定义位于文件hardware/libhardware/hardware.h中。模块结构体hw_module_t包含模块标识、版本信息、模块ID、模块名称、作者信息以及操作方法列表等成员变量。设备结构体hw_device_t则包含设备标识、设备版本、所属模块以及设备操作接口。
开发Android硬件驱动程序
为了便于描述,我们开发一个虚拟字符硬件设备fake register,它有一个4字节的寄存器,支持读写操作。驱动程序的实现基于Linux内核的字符设备模型,定义了文件操作接口。驱动程序的实现如下:
#include#include ...struct Freg_struct { struct mutex mutex; struct cdev freg_cdev; char val;};static struct kobject *freg_kobj;static ssize_t freg_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { struct Freg_struct *dev = container_of(kobj, struct Freg_struct, freg_cdev); mutex_lock(&dev->mutex); val = dev->val; mutex_unlock(&dev->mutex); return snprintf(buf, PAGE_SIZE, "%d\n", val);}...
测试程序如下:
#include#include ...int main() { int fd = open("/dev/freg", O_RDWR); if (fd == -1) { printf("Failed to open device\n"); return -1; } printf("Read original value:\n"); read(fd, &val, sizeof(val)); printf("%d\n"); val = 5; printf("Write value %d to /dev/freg\n", val); write(fd, &val, sizeof(val)); printf("Read the value again:\n"); read(fd, &val, sizeof(val)); printf("%d\n"); close(fd); return 0;}
开发Android硬件抽象层模块
硬件抽象层模块freg的实现包括三个文件:freg.h、freg.cpp和Android.mk。
#ifndef ANDROID_FREF_INTERFACE_H#include...#define FREG_HARDWARE_MODULE_ID "freg"#define FREG_HARDWARE_DEVICE_ID "freg"struct freg_module_t { struct hw_module_t common;};struct freg_device_t { struct hw_device_t common; int fd; int (*set_val)(struct freg_device_t *dev, int val); int (*get_val)(struct freg_device_t *dev, int *val);};#endif
- freg.cpp 实现模块接口:
- Android.mk 编译脚本:
#include#include ...static int freg_device_open(const struct hw_module_t *module, const char *id, struct hw_device_t **device) { struct freg_device_t *dev = malloc(sizeof(struct freg_device_t)); if (!dev) return -1; dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.module = (struct hw_module_t *)module; dev->common.close = freg_device_close; dev->set_val = freg_set_val; dev->get_val = freg_get_val; if ((dev->fd = open("/dev/freg", O_RDWR)) == -1) { free(dev); return -1; } *device = (struct hw_device_t *)dev; return 0;}
LOCAL_MODULE := freg.defaultLOCAL_SRC_FILES := freg.cpp...include $(BUILD_SHARED_LIBRARY)
开发Android硬件访问服务
硬件访问服务FregService通过JNI方法与硬件抽象层模块通信,定义服务接口并运行在系统进程中。服务接口定义在aidl文件中,实现服务类并注册到Service Manager。
使用硬件访问服务
应用程序通过Binder进程间通信机制访问硬件访问服务,调用JNI方法进行硬件操作。最终实现了完整的硬件访问流程,满足应用程序对硬件的读写需求。
发表评论
最新留言
关于作者
