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 ; i<numSensorDrivers ; i++) { delete mSensors[i]; } close(mPollFds[wake].fd); close(mWritePipeFd); } int sensors_poll_context_t::activate(int handle, int enabled) { int index = handleToDriver(handle); if (index < 0) return index; int err = mSensors[index]->enable(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 && i<numSensorDrivers ; i++) { SensorBase* const sensor(mSensors[i]); if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) { 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<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; *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; }