Android4.1系统内置对传感器的支持达13种,他们分别是:加速度传感器(accelerometer)、磁力传感器(magnetic field)、方向传感器(orientation)、陀螺仪(gyroscope)、环境光照传感器(light)、压力传感器(pressure)、温度传感器(temperature)和距离传感器(proximity)等。Android实现传感器系统包括以下几个部分:
n java层
n JNI层
n HAL层
n 驱动层
各部分之间架构图如下:
2 Sensor HAL层接口
Google为Sensor提供了统一的HAL接口,不同的硬件厂商需要根据该接口来实现并完成具体的硬件抽象层,Android中Sensor的HAL接口定义在:
hardware/libhardware/include/hardware/sensors.h
n 对传感器类型的定义:
#define SENSOR_TYPE_ACCELEROMETER 1 //加速度传感器 #define SENSOR_TYPE_MAGNETIC_FIELD 2 //磁力传感器 #define SENSOR_TYPE_ORIENTATION 3 //方向 #define SENSOR_TYPE_GYROSCOPE 4 //陀螺仪 #define SENSOR_TYPE_LIGHT 5 //环境光照传感器 #define SENSOR_TYPE_PRESSURE 6 //压力传感器 #define SENSOR_TYPE_TEMPERATURE 7 //温度传感器 #define SENSOR_TYPE_PROXIMITY 8 //距离传感器 #define SENSOR_TYPE_GRAVITY 9 #define SENSOR_TYPE_LINEAR_ACCELERATION 10 //线性加速度 #define SENSOR_TYPE_ROTATION_VECTOR 11 #define SENSOR_TYPE_RELATIVE_HUMIDITY 12 //湿度传感器 #define SENSOR_TYPE_AMBIENT_TEMPERATURE 13 |
n 传感器模块的定义结构体如下:
struct sensors_module_t { struct hw_module_t common; int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t const** list); }; |
该接口的定义实际上是对标准的硬件模块hw_module_t的一个扩展,增加了一个get_sensors_list函数,用于获取传感器的列表。
n 对任意一个sensor设备都会有一个sensor_t结构体,其定义如下:
struct sensor_t { const char* name; //传感器名字 const char* vendor; int version; //版本 int handle; //传感器的handle句柄 int type; //传感器类型 float maxRange; //最大范围 float resolution; //解析度 float power; //消耗能源 int32_t minDelay; //事件间隔最小时间 void* reserved[8]; //保留字段,必须为0 }; |
n 每个传感器的数据由sensors_event_t结构体表示,定义如下:
typedef struct sensors_event_t { int32_t version; int32_t sensor; //标识符 int32_t type; //传感器类型 int32_t reserved0; int64_t timestamp; //时间戳 union { float data[16]; sensors_vec_t acceleration; //加速度 sensors_vec_t magnetic; //磁矢量 sensors_vec_t orientation; //方向 sensors_vec_t gyro; //陀螺仪 float temperature; //温度 float distance; //距离 float light; //光照 float pressure; //压力 float relative_humidity; //相对湿度 }; uint32_t reserved1[4]; } sensors_event_t; |
其中,sensor为传感器的标志符,而不同的传感器则采用union方式来表示,sensors_vec_t结构体用来表示不同传感器的数据,
n sensors_vec_t定义如下:
typedef struct { union { float v[3]; struct { float x; float y; float z; }; struct { float azimuth; float pitch; float roll; }; }; int8_t status; uint8_t reserved[3]; } sensors_vec_t; |
n Sensor设备结构体sensors_poll_device_t,对标准硬件设备hw_device_t结构体的扩展,主要完成读取底层数据,并将数据存储在struct sensors_poll_device_t结构体中,poll函数用来获取底层数据,调用时将被阻塞定义如下:
struct sensors_poll_device_t { struct hw_device_t common; //Activate/deactivate one sensor int (*activate)(struct sensors_poll_device_t *dev, int handle, int enabled); //Set the delay between sensor events in nanoseconds for a given sensor. int (*setDelay)(struct sensors_poll_device_t *dev, int handle, int64_t ns); //获取数据 int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int count); }; |
n 控制设备打开/关闭结构体定义如下:
static inline int sensors_open(const struct hw_module_t* module, struct sensors_poll_device_t** device) { return module->methods->open(module, SENSORS_HARDWARE_POLL, (struct hw_device_t**)device); }
static inline int sensors_close(struct sensors_poll_device_t* device) { return device->common.close(&device->common); } |
3 Sensor HAL实现(以bma250为例子)
3.1打开设备流程图
SensorDevice属于JNI层,与HAL进行通信的接口,在JNI层调用了HAL层的open_sensors()方法打开设备模块,再调用poll__activate()对设备使能,然后调用poll__poll读取数据。
3.2实现代码分析
在bma250传感器中,只有加速度传感器,所以在sensor.cpp中,首先需要定义传感器数组sSensorList,其实就是初始化struct sensor_t结构体,只有加速传感器,初始化如下:
static const struct sensor_t sSensorList[] = {
{ "BMA250 3-axis Accelerometer", "Bosch", 1, 0, SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/1024.0f, 0.2f, 0, { } }, }; |
static const struct sensor_t sSensorList[] = {
{ "BMA250 3-axis Accelerometer", "Bosch", 1, 0, SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/1024.0f, 0.2f, 0, { } }, }; |
static const struct sensor_t sSensorList[] = {
{ "BMA250 3-axis Accelerometer", "Bosch", 1, 0, SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/1024.0f, 0.2f, 0, { } }, }; |
static const struct sensor_t sSensorList[] = {
{ "BMA250 3-axis Accelerometer", "Bosch", 1, 0, SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/1024.0f, 0.2f, 0, { } }, }; |
static const struct sensor_t sSensorList[] = {
{ "BMA250 3-axis Accelerometer", "Bosch", 1, 0, SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/1024.0f, 0.2f, 0, { } }, }; |
n 定义open_sensors函数,来打开Sensor模块,代码如下:
static struct hw_module_methods_t sensors_module_methods = { open : open_sensors }; static int open_sensors(const struct hw_module_t* module, const char* name, struct hw_device_t** device) { int status = -EINVAL;
sensors_poll_context_t *dev = new sensors_poll_context_t(); memset(&dev->device, 0, sizeof(sensors_poll_device_t));
dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 0; dev->device.common.module = const_cast<hw_module_t*>(module); dev->device.common.close = poll__close; dev->device.activate = poll__activate; dev->device.setDelay = poll__setDelay; dev->device.poll = poll__poll;
if(sensor_get_class_path(dev) < 0) { ALOGD("g sensor get class path error \n"); return -1; }
dev->fd = open_input_device(); *device = &dev->device.common; status = 0;
return status; } |
在这个方法中,首先需要为hw_device_t分配内存空间,并对其初始化,设置重要方法的实现,然后调用open_input_device打开设备节点,返回文件描述符。
n poll__activate()对设备使能
static int poll__activate(struct sensors_poll_device_t *device, int handle, int enabled) { sensors_poll_context_t *dev = (sensors_poll_context_t *)device; char buffer[20]; int bytes = sprintf(buffer, "%d\n", enabled); set_sysfs_input_attr(dev->class_path,"enable",buffer,bytes); return 0; } static int set_sysfs_input_attr(char *class_path, const char *attr, char *value, int len) { char path[256]; int fd; if (class_path == NULL || *class_path == '\0' || attr == NULL || value == NULL || len < 1) { return -EINVAL; } snprintf(path, sizeof(path), "%s/%s", class_path, attr); path[sizeof(path) - 1] = '\0'; fd = open(path, O_RDWR); if (fd < 0) { return -errno; } if (write(fd, value, len) < 0) { close(fd); return -errno; } close(fd); return 0; } |
代码很简单,通过系统调用open方法打开设备,然后调用write()方法写指令使能。
n poll__poll(),读取数据
static int poll__poll(struct sensors_poll_device_t *device, sensors_event_t* data, int count) {
struct input_event event; int ret; sensors_poll_context_t *dev = (sensors_poll_context_t *)device;
if (dev->fd < 0) return 0; while (1) { ret = read(dev->fd, &event, sizeof(event)); if (event.type == EV_ABS) {
switch (event.code) { #ifdef GSENSOR_XY_REVERT case ABS_Y: data->acceleration.x = event.value * CONVERT_X; break; case ABS_X: data->acceleration.y = event.value * CONVERT_Y; break; #else case ABS_X: data->acceleration.x = event.value * CONVERT_X; break; case ABS_Y: data->acceleration.y = event.value * CONVERT_Y; break; #endif case ABS_Z: data->acceleration.z =
|