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 =
|