Android系统中常见的传感器有:加速度传感器、磁力计传感器、陀螺仪、光线传感器、接近传感器、方向传感器、压力传感器等。
HAL层的头文件代码位于hardware\libhardware\include\hardware\sensors.h。
HAL层支持13种类型的传感器:
/**
* Sensor types
*/
#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 // deprecated
#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
/**
* Every device data structure must begin with hw_device_t
* followed by module specific public methods and attributes.
*/
struct sensors_poll_device_t {
struct hw_device_t common;
/** Activate/deactivate one sensor.
*
* @param handle is the handle of the sensor to change.
* @param enabled set to 1 to enable, or 0 to disable the sensor.
*
* @return 0 on success, negative errno code otherwise
*/
int (*activate)(struct sensors_poll_device_t *dev,
int handle, int enabled);
/**
* Set the delay between sensor events in nanoseconds for a given sensor.
*
* If the requested value is less than sensor_t::minDelay, then it's
* silently clamped to sensor_t::minDelay unless sensor_t::minDelay is
* 0, in which case it is clamped to >= 1ms.
*
* @return 0 if successful, < 0 on error
*/
int (*setDelay)(struct sensors_poll_device_t *dev,
int handle, int64_t ns);
/**
* Returns an array of sensor data.
* This function must block until events are available.
*
* @return the number of events read on success, or -errno in case of an error.
* This function should never return 0 (no event).
*
*/
int (*poll)(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count);
};
注意所有传感器共享这个数据结构,在hw_module_methods_t.open函数中使用。
activate函数打开或关闭传感器;
setDelay函数设置两个传感器事件之间的间隔;
poll函数用阻塞实现传感器数据的返回,传感器数据是:
/**
* Union of the various types of sensor data
* that can be returned.
*/
typedef struct sensors_event_t {
/* must be sizeof(struct sensors_event_t) */
int32_t version;
/* sensor identifier */
int32_t sensor;
/* sensor type */
int32_t type;
/* reserved */
int32_t reserved0;
/* time is in nanosecond */
int64_t timestamp;
union {
float data[16];
/* acceleration values are in meter per second per second (m/s^2) */
sensors_vec_t acceleration;
/* magnetic vector values are in micro-Tesla (uT) */
sensors_vec_t magnetic;
/* orientation values are in degrees */
sensors_vec_t orientation;
/* gyroscope values are in rad/s */
sensors_vec_t gyro;
/* temperature is in degrees centigrade (Celsius) */
float temperature;
/* distance in centimeters */
float distance;
/* light in SI lux units */
float light;
/* pressure in hectopascal (hPa) */
float pressure;
/* relative humidity in percent */
float relative_humidity;
};
uint32_t reserved1[4];
} sensors_event_t;
sensors_event_t是HAL与上层交互的数据元素。
static struct hw_module_methods_t sensors_module_methods = {
open: open_sensors
};
struct sensors_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: SENSORS_HARDWARE_MODULE_ID,
name: "Sensor module",
author: "Texas Instruments Inc.",
methods: &sensors_module_methods,
dso : NULL,
reserved : {0},
},
get_sensors_list: sensors__get_sensors_list,
};
每个传感器的定义为:
struct sensor_t {
/* name of this sensors */
const char* name;
/* vendor of the hardware part */
const char* vendor;
/* version of the hardware part + driver. The value of this field
* must increase when the driver is updated in a way that changes the
* output of this sensor. This is important for fused sensors when the
* fusion algorithm is updated.
*/
int version;
/* handle that identifies this sensors. This handle is used to activate
* and deactivate this sensor. The value of the handle must be 8 bits
* in this version of the API.
*/
int handle;
/* this sensor's type. */
int type;
/* maximaum range of this sensor's value in SI units */
float maxRange;
/* smallest difference between two values reported by this sensor */
float resolution;
/* rough estimate of this sensor's power consumption in mA */
float power;
/* minimum delay allowed between events in microseconds. A value of zero
* means that this sensor doesn't report events at a constant rate, but
* rather only when a new data is available */
int32_t minDelay;
/* reserved fields, must be zero */
void* reserved[8];
};
定义一个C++类来管理传感器:
struct sensors_poll_context_t {
struct sensors_poll_device_t device; // must be first
sensors_poll_context_t();
~sensors_poll_context_t();
int activate(int handle, int enabled);
int setDelay(int handle, int64_t ns);
int pollEvents(sensors_event_t* data, int count);
private:
enum {
accel = 0,
temp = 1,
light = 2,
numSensorDrivers,
numFds,
};
static const size_t wake = numFds - 1;
static const char WAKE_MESSAGE = 'W';
struct pollfd mPollFds[numFds];
int mWritePipeFd;
SensorBase* mSensors[numSensorDrivers];
int handleToDriver(int handle) const {
switch (handle) {
case ID_A:
return accel;
case ID_TEMP:
return temp;
case ID_L:
return light;
}
return -EINVAL;
}
};
/*****************************************************************************/
sensors_poll_context_t::sensors_poll_context_t()
{
mSensors[accel] = new AccelSensor();
mPollFds[accel].fd = mSensors[accel]->getFd();
mPollFds[accel].events = POLLIN;
mPollFds[accel].revents = 0;
mSensors[temp] = new TempSensor();
mPollFds[temp].fd = mSensors[temp]->getFd();
mPollFds[temp].events = POLLIN;
mPollFds[temp].revents = 0;
mSensors[light] = new LightSensor();
mPollFds[light].fd = mSensors[light]->getFd();
mPollFds[light].events = POLLIN;
mPollFds[light].revents = 0;
int wakeFds[2];
int result = pipe(wakeFds);
ALOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
mWritePipeFd = wakeFds[1];
mPollFds[wake].fd = wakeFds[0];
mPollFds[wake].events = POLLIN;
mPollFds[wake].revents = 0;
}
sensors_poll_context_t::~sensors_poll_context_t() {
for (int i=0 ; ienable(handle, enabled);
if (enabled && !err) {
const char wakeMessage(WAKE_MESSAGE);
int result = write(mWritePipeFd, &wakeMessage, 1);
ALOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
}
return err;
}
int sensors_poll_context_t::setDelay(int handle, int64_t ns) {
int index = handleToDriver(handle);
ALOGD("%s[%d],index:0x%x",__func__,__LINE__,index);
if (index < 0) return index;
return mSensors[index]->setDelay(handle, ns);
}
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
{
int nbEvents = 0;
int n = 0;
do {
// see if we have some leftover from the last poll()
for (int i=0 ; count && ihasPendingEvents())) {
int nb = sensor->readEvents(data, count);
if (nb < count) {
// no more data for this sensor
mPollFds[i].revents = 0;
}
count -= nb;
nbEvents += nb;
data += nb;
}
}
if (count) {
// we still have some room, so try to see if we can get
// some events immediately or just wait if we don't have
// anything to return
n = poll(mPollFds, numFds, nbEvents ? 0 : -1);
if (n<0) {
ALOGE("poll() failed (%s)", strerror(errno));
return -errno;
}
if (mPollFds[wake].revents & POLLIN) {
char msg;
int result = read(mPollFds[wake].fd, &msg, 1);
ALOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
ALOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
mPollFds[wake].revents = 0;
}
}
// if we have events and space, go read them
} while (n && count);
return nbEvents;
}
/*****************************************************************************/
static int poll__close(struct hw_device_t *dev)
{
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
if (ctx) {
delete ctx;
}
return 0;
}
static int poll__activate(struct sensors_poll_device_t *dev,
int handle, int enabled) {
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
return ctx->activate(handle, enabled);
}
static int poll__setDelay(struct sensors_poll_device_t *dev,
int handle, int64_t ns) {
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
return ctx->setDelay(handle, ns);
}
static int poll__poll(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count) {
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
return ctx->pollEvents(data, count);
}
/*****************************************************************************/
/** Open a new instance of a sensor device using name */
static int open_sensors(const struct hw_module_t* module, const char* id,
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(module);
dev->device.common.close = poll__close;
dev->device.activate = poll__activate;
dev->device.setDelay = poll__setDelay;
dev->device.poll = poll__poll;
*device = &dev->device.common;
status = 0;
return status;
}
class SensorBase {
protected:
const char *dev_name;
const char *data_name;
char input_name[PATH_MAX];
int dev_fd;
int data_fd;
int openInput(const char *inputName);
static int64_t getTimestamp();
static int64_t timevalToNano(timeval const&t) {
return t.tv_sec*1000000000LL + t.tv_usec*1000;
}
int open_device();
int close_device();
public:
SensorBase(
const char *dev_name,
const char *data_name);
virtual ~SensorBase();
virtual int readEvents(sensors_event_t *data, int count) = 0;
virtual bool hasPendingEvents() const;
virtual int getFd() const;
virtual int setDelay(int32_t handle, int64_t ns);
virtual int enable(int32_t handle, int enabled) = 0;
};
SensorBase::SensorBase(
const char* dev_name,
const char* data_name)
: dev_name(dev_name), data_name(data_name),
dev_fd(-1), data_fd(-1)
{
if (data_name) {
data_fd = openInput(data_name);
}
}
SensorBase::~SensorBase() {
if (data_fd >= 0) {
close(data_fd);
}
if (dev_fd >= 0) {
close(dev_fd);
}
}
int SensorBase::open_device() {
if (dev_fd<0 && dev_name) {
dev_fd = open(dev_name, O_RDONLY);
ALOGE_IF(dev_fd<0, "Couldn't open %s (%s)", dev_name, strerror(errno));
}
return 0;
}
int SensorBase::close_device() {
if (dev_fd >= 0) {
close(dev_fd);
dev_fd = -1;
}
return 0;
}
int SensorBase::getFd() const {
if (!data_name) {
return dev_fd;
}
return data_fd;
}
int SensorBase::setDelay(int32_t handle, int64_t ns) {
return 0;
}
bool SensorBase::hasPendingEvents() const {
return false;
}
int64_t SensorBase::getTimestamp() {
struct timespec t;
t.tv_sec = t.tv_nsec = 0;
clock_gettime(CLOCK_MONOTONIC, &t);
return int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
}
int SensorBase::openInput(const char* inputName) {
int fd = -1;
const char *dirname = "/dev/input";
char devname[PATH_MAX];
char *filename;
DIR *dir;
struct dirent *de;
dir = opendir(dirname);
if(dir == NULL)
return -1;
strcpy(devname, dirname);
filename = devname + strlen(devname);
*filename++ = '/';
while((de = readdir(dir))) {
if(de->d_name[0] == '.' &&
(de->d_name[1] == '\0' ||
(de->d_name[1] == '.' && de->d_name[2] == '\0')))
continue;
strcpy(filename, de->d_name);
fd = open(devname, O_RDONLY);
if (fd>=0) {
char name[80];
if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
name[0] = '\0';
}
if (!strcmp(name, inputName)) {
strcpy(input_name, filename);
break;
} else {
close(fd);
fd = -1;
}
}
}
closedir(dir);
ALOGE_IF(fd<0, "couldn't find '%s' input device", inputName);
return fd;
}