Android Sensor Input类型 (四) Sensor HAL 实现
- Android Sensors 总览(基于高通android平台)
- Android Sensor Input类型 (一) 简介
- Android Sensor Input类型 (二) Device Driver
- Android Sensor Input类型 (三) Sensor Class
- Android Sensor Input类型 (四) Sensor HAL 实现
- Android Sensor Input类型 (五) Sensor HAL NativeSensorManager
msm8909 Sensor HAL
代码路径:code/hardware/qcom/sensors/
核心作用:封装对 sensor的方法,不直接通过本地C库直接访问
点击展开 全部文件
├── Accelerometer.cpp
├── AccelSensor.h
├── AkmSensor.cpp
├── AkmSensor.h
├── algo
├── Android.mk
├── Bmp180.cpp
├── CalibrationManager.cpp
├── CalibrationManager.h
├── CalibrationModule.h
├── calmodule.cfg
├── CompassSensor.cpp
├── CompassSensor.h
├── Gyroscope.cpp
├── GyroSensor.h
├── InputEventReader.cpp
├── InputEventReader.h
├── LICENSE
├── LightSensor.cpp
├── LightSensor.h
├── NativeSensorManager.cpp
├── NativeSensorManager.h
├── PressureSensor.h
├── ProximitySensor.cpp
├── ProximitySensor.h
├── SensorBase.cpp
├── SensorBase.h
├── sensors.cpp
├── sensors_extension.h
├── sensors.h
├── sensors_XML.cpp
├── sensors_XML.h
├── SignificantMotion.cpp
├── SignificantMotion.h
├── VirtualSensor.cpp
└── VirtualSensor.h
重要文件有:
sensors.cpp
sensors.cpp 中提供数据机构架构,提供 hw_device_t 封装; 让其他层可以获得这个结构,得以使用其中的方法;
通过实现的结构可以发现,所有的操作都使用了, NativeSensorManager用来做具体的操作
NativeSensorManager.cpp
Native SensorManager 是个class,继承Singleton; 单例模式,只存在一个对象;
即被多次定义引用的对象 sm; 它的存在是统一管理sensor HAL的sensor访问;
将存在的sensor统一存在数组里,不针对sensor具体类型; 是HAL的实际操作者;
SensorBase.cpp
VirtualSensor.cpp
sensors主要设备结构
sensor_t
struct sensor_t {
const char* name;
//!< sensor名称 By: jixuan
const char* vendor;
//!< 厂商名 By: jixuan
int version;
int handle
int type;
//!< 类型标识 By: jixuan
float maxRange;
float resolution;
//!< 解析度 即报告数值的最大差异范围 By: jixuan
float power;
int32_t minDelay;
uint32_t fifoReservedEventCount;
uint32_t fifoMaxEventCount;
//!< 类型字符串 Note By: yujixuan
const char* stringType;
//!< 权限 Note By: yujixuan
const char* requiredPermission;
void* reserved[2];
};
sensor_moudule_t
struct sensors_module_t {
struct hw_module_t common;
//!< hw_module_t 基础结构 >! NoteBy: yujixuan
int (*get_sensors_list)(struct sensors_module_t* module,
struct sensor_t const** list);
//!< 拓展接口,获取sensor 列表 >! NoteBy:yujixuan
int (*set_operation_mode)(unsigned int mode);
//!< 操作设置sensor mode >! NoteBy: yujixuan
};
//!< 定义 名为HMI的 hw_module_t 结构体(可以转型为包含它的具体设备类型,首地址保持相同),get_module 获取它 >! NoteBy: yujixuan
struct sensors_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG, //!< 固定名 >! NoteBy: yujixuan
version_major: 1,
version_minor: 0,
id: SENSORS_HARDWARE_MODULE_ID,
name: "Quic Sensor module",
author: "Quic",
methods: &sensors_module_methods, //!< hw_module_t 必要填充的方法 >! NoteBy: yujixuan
dso: NULL,
reserved: {0},
},
get_sensors_list: sensors__get_sensors_list, //!< sensor_module_t 拓展的方法 >! NoteBy: yujixuan
};
static struct hw_module_methods_t sensors_module_methods = {
open: open_sensors //!< 只有一个open函数,它的作用是返回具体的 device >! NoteBy: yujixuan
};
//!< 打开一个新的sensor 实例 填充具体的hw_device_t>! NoteBy: yujixuan
open函数实现:open_sensors
#define HAL_MODULE_INFO_SYM HMI
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
static int open_sensors(const struct hw_module_t* module, const char*,
struct hw_device_t** device)
{
int status = -EINVAL;
sensors_poll_context_t *dev = new sensors_poll_context_t();
NativeSensorManager& sm(NativeSensorManager::getInstance());
memset(&dev->device, 0, sizeof(sensors_poll_device_1_ext_t));
dev->device.common.tag = HARDWARE_DEVICE_TAG;
#if defined(SENSORS_DEVICE_API_VERSION_1_3)
ALOGI("Sensors device API version 1.3 supported\n");
dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_3;
#else
dev->device.common.version = SENSORS_DEVICE_API_VERSION_0_1;
#endif
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;
dev->device.calibrate = poll_calibrate;
#if defined(SENSORS_DEVICE_API_VERSION_1_3)
dev->device.batch = poll__batch;
dev->device.flush = poll__flush;
#endif
*device = &dev->device.common;
status = 0;
return status;
}
open_sensors新的sensor 实例,首先new了一个sensors_poll_context_t 的device ,然后设置该device,并返回 给到调用者;
针对 sensors_poll_context_t 下面内容会做具体分析;
static int sensors__get_sensors_list(struct sensors_module_t*,
struct sensor_t const** list)
{
NativeSensorManager& sm(NativeSensorManager::getInstance());
return sm.getSensorList(list);
}
拓展的sensors_module_t 中添加了 get_sensor_list方法;
可以看到它是通过NativeSensorManger 来做具体的Hal层访问;
Sensor服务用户程序不能直接访问,通过NativeSensorManager来访问。 (note: nativeSensorManager是指在HAL中的管理sensor的设备结构,需要区别于Android Framework中的SensorManager)
里面使用了NativeSensorManager,sensors__get_sensors_list函数中调用单例模式创建了一个实例sm,通过调用其中的成员函数获取传感器列表,并返回,返回值对应的sensor_t结构体;NativeSensorManager统一管理着所有的传感器、物理和虚拟传感器;
SensorHAL 解析
Native Sensor Hal框架中,最为主要的内容即是 open函数中对device的回调设置;简单的可以理解为是上层函数与调用底层驱动的桥接;
所以在Hal这个层次应着重分析这块内容;,由上可知,当前的代码里是通过sensors_poll_context_t来定义一个device; 以下是 sensors_poll_context_t 的内容:
sensors_poll_context_t
struct sensors_poll_context_t {
// extension for sensors_poll_device_1, must be first
struct sensors_poll_device_1_ext_t device;// must be first
//!< 必须放在首个位置,它是个联合体,首个属性是 hw_device_t; >! NoteBy: yujixuan
sensors_poll_context_t();
~sensors_poll_context_t();
//!<struct同样有构造函数,析构函数,完成重要的初始化功能 >! NoteBy: yujixuan
int activate(int handle, int enabled);
int setDelay(int handle, int64_t ns);
int pollEvents(sensors_event_t* data, int count);
int calibrate(int handle, cal_cmd_t *para);
int batch(int handle, int sample_ns, int latency_ns);
int flush(int handle);
private:
static const size_t wake = MAX_SENSORS;
static const char WAKE_MESSAGE = 'W';
struct pollfd mPollFds[MAX_SENSORS+1];
int mWritePipeFd;
SensorBase* mSensors[MAX_SENSORS];
mutable Mutex mLock;
};
通过open函数返回的的是hw_device_t,实际是传入的地址值;只要保证,包含此结构,且sensors_poll_device_1_ext_t放在首位,可以向上转型回具体的sensor
设备device;
实际device的函数调用 都是拓展的;比如上面的 activate; setDelay; pollEvents;等;
struct sensors_poll_device_1_ext_t {
union {
struct sensors_poll_device_1 aosp;
struct {
struct hw_device_t common;
int (*activate)(struct sensors_poll_device_t *dev,
int handle, int enabled);
int (*setDelay)(struct sensors_poll_device_t *dev,
int handle, int64_t period_ns);
int (*poll)(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count);
int (*batch)(struct sensors_poll_device_1* dev,
int handle, int flags, int64_t period_ns, int64_t timeout);
int (*flush)(struct sensors_poll_device_1* dev, int handle);
void (*reserved_procs[8])(void);
};
};
struct sensors_poll_device_t {
struct hw_device_t common;
int (*activate)(struct sensors_poll_device_t *dev,
int sensor_handle, int enabled);
int (*setDelay)(struct sensors_poll_device_t *dev,
int sensor_handle, int64_t sampling_period_ns);
int (*poll)(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count);
};
通过sensors_poll_device_1_ext_t也可以看出,实际sensors_poll_context_t 可以是sensors_poll_device_t
这是面向对象 多态的思想方式; 获取到的device根据具体的类型,再转换为具体的 device进行函数调用;
实际device的函数调用 都是拓展的;比如上面的 activate; setDelay; pollEvents;等;
在open函数中,new一个实例对象;sensors_poll_context_t会调用其构造函数完成最重要的初始化功能,如下:
sensors_poll_context_t::sensors_poll_context_t()
{
int number;
int i;
const struct sensor_t *slist;
const struct SensorContext *context;
NativeSensorManager& sm(NativeSensorManager::getInstance());
number = sm.getSensorList(&slist);
//!< 获取sensor个数; 与sensor构成的链表list >! NoteBy: yujixuan
/* use the dynamic sensor list */
for (i = 0; i < number; i++) {
context = sm.getInfoByHandle(slist[i].handle);
mPollFds[i].fd = (context == NULL) ? -1 : context->data_fd;
mPollFds[i].events = POLLIN;
mPollFds[i].revents = 0;
}
ALOGI("The avaliable sensor handle number is %d",i);
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[number].fd = wakeFds[0];
mPollFds[number].events = POLLIN;
mPollFds[number].revents = 0;
}
构造函数中,通过NativeSensorManager 获取了sensor 列表;
通过struct SensorContext *context;
context = sm.getInfoByHandle(slist[i].handle);
维系记录了handle对应的SensorContext对象指针的句柄;SensorContext 的结构如下:
SensorContext
struct SensorContext {
char name[SYSFS_MAXLEN]; // name of the sensor
char vendor[SYSFS_MAXLEN]; // vendor of the sensor
char enable_path[PATH_MAX]; // the control path of this sensor
char data_path[PATH_MAX]; // the data path to get sensor events
struct sensor_t *sensor; // point to the sensor_t structure in the sensor list
SensorBase *driver; // point to the sensor driver instance
int data_fd; // the file descriptor of the data device node
int enable; // indicate if the sensor is enabled
bool is_virtual; // indicate if this is a virtual sensor
int64_t delay_ns; // the poll delay setting of this sensor
int64_t latency_ns; // the max report latency of this sensor
struct listnode dep_list; // the background sensor type needed for this sensor
struct listnode listener; // the head of listeners of this sensor
};
从上可以看出: SensorContext中的 SensorBase *driver; 指向了具体的sensor实例;
在构造函数中,还完成了pollfd即mPollFds用来监听senso时用的文件描述符;
open函数的后面的部分,也就是对sensors_poll_context_t 拓展的那些方法的链接;
比如:
dev->device.common.close = poll__close;
dev->device.activate = poll__activate;
dev->device.setDelay = poll__setDelay;
dev->device.poll = poll__poll;
dev->device.calibrate = poll_calibrate;
poll函数分析
这里分析下,最重要的一个函数 poll__poll;
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;
//!< 这里就用到了 向上转型;将sensor_poll_device_t 转为 sensor_poll_context_t >! NoteBy: yujixuan
return ctx->pollEvents(data, count);
//!< 返回pollEvents >! NoteBy: yujixuan
}
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
{
int nbEvents = 0;
int n = 0;
NativeSensorManager& sm(NativeSensorManager::getInstance());
const sensor_t *slist;
int number = sm.getSensorList(&slist);
do {
// see if we have some leftover from the last poll()
for (int i = 0 ; count && i < number ; i++) {
if ((mPollFds[i].revents & POLLIN) || (sm.hasPendingEvents(slist[i].handle))) {
Mutex::Autolock _l(mLock);
int nb = sm.readEvents(slist[i].handle, data, count);
if (nb < 0) {
ALOGE("readEvents failed.(%d)", errno);
return nb;
}
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
do {
n = poll(mPollFds, number + 1, nbEvents ? 0 : -1);
} while (n < 0 && errno == EINTR);
if (n<0) {
ALOGE("poll() failed (%s)", strerror(errno));
return -errno;
}
if (mPollFds[number].revents & POLLIN) {
char msg;
int result = read(mPollFds[number].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[number].revents = 0;
}
}
// if we have events and space, go read them
} while (n && count);
return nbEvents;
}
主要函数:sm.readEvents(slist[i].handle, data, count);
NativeSensorManager::readEvents中调用了:
nb = list->driver->readEvents(data, count);
list->driver是一个SensorBase结构体,SensorBase结构体的函数readEvents,
这里就需要联合 nativesensormanger的实现来看具体的读取流程;
nativesensormanger相关内容,在后续的内容中分析;