sensor中间层 --- NativeSensorManager

Posted Achillisjack

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sensor中间层 --- NativeSensorManager相关的知识,希望对你有一定的参考价值。

NativeSensorManager

NativeSensorManager定义如下,

class NativeSensorManager : public Singleton<NativeSensorManager> 
friend class Singleton<NativeSensorManager>;
NativeSensorManager();
~NativeSensorManager();
struct sensor_t sensor_list[MAX_SENSORS];
struct SensorContext context[MAX_SENSORS];
struct SensorEventMap event_list[MAX_SENSORS];
•••

sensor_list表示每个sensor属性的数组;context表示每个sensor完整信息的信息,里面的每个SensorContext 类型的元素都完整的描述了

一个sensor 的所有信息,包括sensor设备节点路径和对应的event设备节点的路径等;event_list则为所有实际sensor的事件信息列表;

其它变量在分析具体代码的时候再讲述。

NativeSensorManager的getNode方法如下,

int NativeSensorManager:: getNode(char *buf, char *path, const struct SysfsMap *map) 
char * fret;
ssize_t len = 0;
int fd;
char tmp[SYSFS_MAXLEN];
•••

这个函数根据输入参数path(表示设备的节点路径)和map(描述节点下各个属性节点的信息)获取某个设备节点下的属性节点信息,path一般为/sys/class/sensors/xxxx(deivce)/xxx(node)的形式,如light sensor 的name节点,则为/sys/class/sensors/ltr559-light/name,读取该节点则会

调用到底层驱动的sensors_name_show函数,这里该函数会返回ltr559-light。

const struct SysfsMap NativeSensorManager::node_map[] = 
offsetof(struct sensor_t, name), SYSFS_NAME, TYPE_STRING, 1, 
offsetof(struct sensor_t, vendor), SYSFS_VENDOR, TYPE_STRING,1,
offsetof(struct sensor_t, version), SYSFS_VERSION, TYPE_INTEGER,1,
offsetof(struct sensor_t, type), SYSFS_TYPE, TYPE_INTEGER, 1,
offsetof(struct sensor_t, maxRange), SYSFS_MAXRANGE, TYPE_FLOAT,1,
•••

上面描述每个sensor驱动设备节点中的属性节点信息,所有sensor驱动设备都会包含上面的节点,HAL正是通过这些节点来访问和控制底层驱动。

NativeSensorManager的addDependency方法如下,

int NativeSensorManager::addDependency(struct SensorContext *ctx,int handle)

struct SensorContext *dep;
struct listnode *node;
struct SensorRefMap *ref, *item;
•••

将handle对应的sensor添加到ctx的dep_list中,dep_list是ctx所依赖的其它sensor的链表,如virtual sensor Compass就依赖于acc和mag。

initVirtualSensor方法如下,

int NativeSensorManager::initVirtualSensor(struct SensorContext *ctx, int handle,
struct sensor_t info)

CalibrationManager& cm(CalibrationManager::getInstance());
SensorRefMap *item;
struct SensorContext *ref;
unsigned int i;
•••

该函数初始化一个virtual sensor, 它和实际sensor 的主要区别在于data_fd,data_path,enable_path均为空,is_virtual 为true,因为

virtual sensor的值都是来自于实际sensor,经过一定的算法计算得来。

getEventPathOld方法如下,

int NativeSensorManager::getEventPathOld(const struct SensorContext *list, char *event_path)

struct dirent **namelist;
char *file;
char path[PATH_MAX];
char name[80];
int nNodes;
int fd = -1;
int j;
•••

android5.1中, 将android5.0中的getDataInfo函数里提供的查找sensor对应event设备的方法代码抽取出来,设计成了单独的函数取名

为getEventPathOld。扫描"/dev/input"中的event设备或取其信息,event_list[mEventCount].data_path存储/dev/input/eventX,event_list[mEventCount].data_name 

 存储/dev/input  下面的event设备对应input_dev中的name值,逐个比较当前sensor的name字段和/dev/input/中所有的event 设备对应的

输入设备input_dev 的name字段,若相同,则把对应的event_list[j].data_path复制给content[i]的data_path字段,若所有event_list中都没有

找到匹配的,则把sensor->type转换为name,再和所有event设备对应的输入设备input_dev的name字段比较,同样将匹配的event_list[j]的

data_path复制给content[i]的data_path字段;

getEventPath方法如下,

int NativeSensorManager::getEventPath(const char *sysfs_path, char *event_path)

DIR *dir;
struct dirent *de;
char symlink[PATH_MAX];
int len;
char *needle;
dir = opendir(sysfs_path);
•••

getEventPath是andoid5.1中寻找event设备路径路径的函数,如果getEventPath查找失败,仍然会采用getEventPathOld的方法

(该方法是原来android5.0中的方法)查找;sysfs_path参数为/sys/class/sensors/xxx/device,其 中xxx软链接指向…/input/input3/light 或者是sys/devices/soc.0/78b6000.i2c/i2c-0/0-0023/sensors/light,由驱动决定,而device软链接则指向dev->parent->kobj,即input3 目录或者是0-0023

目录,读取sysfs_path指向的内容,即设备xxx的parent目录;从上面的代码可知sensors_classdev 设备应该注册为对应输入设备的子设备,这样可

以加速sensor service初始化的时间,因为如果sensors_classdev 注册为inputX 的子目录,则其软链接device指向inputX 目录,inputX 目录下面

对应的eventX则是对应sensor的事件节点,这样就不用每次都循环去比较所有的event设备对应的input_dev 的name字段,提高了效率。

int NativeSensorManager::getSensorListInner()

int number = 0;
int err = -1;
const char *dirname = SYSFS_CLASS;
char devname[PATH_MAX];
char *filename;
char *nodename;
DIR *dir;
struct dirent *de;
struct SensorContext *list;
unsigned int i;
•••

SYSFS_CLASS 为/sys/class/sensors/,首先依次读取/sys/class/sensors/下的每个设备目录,即驱动中所有注册了的sensor,此时若filename 

为ltr559-light ,则devicename为/sys/class/sensors/ltr559-light,接着根据node_map提供的信息依次获取该设备下每个属性节点的信息,当循环结束,

则会填充完类中类型为sensor_t的sensor_list数组,该数组保存系统中所有的sensors设备基本信息;接着为每个sensor分配一个独一无二的的

handle值,以后HAL通过该handle值就能找到对应的sensor;从上面可知nodename 指向/sys/class/sensors/xxx/字符串的末尾,因此list->enable_path 即为/sys/class/sensors/xxx/,hal 接口则每次通过该路径去访问对应sensor的节点;最后通过getEventPath或getEventPathOld函数获取event设备节点的路径,

存于list->data_path中。

compositeVirtualSensorName方法如下,

void NativeSensorManager::compositeVirtualSensorName(const char *sensor_name, char *chip_name, int type)

char *save_ptr;
const char *token;
char temp[SYSFS_MAXLEN];
strlcpy(temp, sensor_name, SYSFS_MAXLEN);
token = strtok_r(temp, "-_ ", &save_ptr);
•••

该函数将sensor_name中的xxx-yyy的xxx-type_to_name(type)复制给chip_name,组成VirtualSensor的name。

getDataInfo方法如下,

int NativeSensorManager::getDataInfo() 
int i, j;
struct SensorContext *list;
int has_acc = 0;
int has_compass = 0;
int has_gyro = 0;
int has_light = 0;
int has_proximity = 0;
•••

这个方法在初始化时被调用,它会调用前面所分析的几个方法,获取sensor的所有信息;首先通过getSensorListInner()获取每个sensor设备的信息,

包括sensor的属性、节点路径和对应的event节点路径,前文有对该函数的详细介绍,上面的type_map.add(list->sensor->type, list)将sensor的type

与与对应的content关联起来,以后通过type就能找到对应的content;handle_map.add(list->sensor->handle, list)将sensor的handle与content关联

起来,以后通过handle就能找到对应的content;然后为每个实际的物理sensor 创建该sensor 对应的驱动对象,并将sensor 对应content的driver字段

指向该对象;如,list->driver = new LightSensor(list);最后通过这些实际的sensor创建virtual sensor。

registerListener方法

int NativeSensorManager::registerListener(struct SensorContext *hw,struct SensorContext *virt)

struct listnode *node;
struct SensorContext *ctx;
struct SensorRefMap *item;
•••

该函数把virt添加到hw的listener 的链表中,每个实际sensor的listener 链表保存着所有依赖于它的virtual sensor,顾名思义就是被监听。

syncDelay方法如下,

int NativeSensorManager::syncDelay(int handle)

const SensorRefMap *item;
SensorContext *ctx;
const SensorContext *list;
struct listnode *node;
int64_t min_ns;
list = getInfoByHandle(handle);
•••

该函数同步delay,取本sensor中所有监听sensor最小的delay_ns,然后将这个值设置到本sensor中。

activate方法如下,

int NativeSensorManager::activate(int handle, int enable)

SensorContext *list;
int i;
int number = getSensorCount();
int err = 0;
struct listnode *node;
struct SensorContext *ctx;
struct SensorRefMap *item;
•••

这个方法主要是使能和屏蔽某个sensor,如果使能某个sensor,则必须找到该sensor所有依赖的sensor,并把该sensor链入到所依赖

sensor的listener 节点上,然后要同步所有依赖sensor和监听sensor的delay和latency,并使能所依赖的sensor;如果屏蔽某个sensor,

则必须找到该sensor所有依赖的sensor,并把该sensor从所依赖sensor的listener 链表中移除掉,并同步所有依赖sensor监听sensor的

delay和latency,而且只要该sensor还有监听sensor,则不会屏蔽该sensor;如果是virtual sensor则在最后需要对该virtual sensor进行

使能和屏蔽,但如果是实际的sensor,则不需要,因为实际sensor都会出现在自己的dep_list链表中;

readEvents方法如下,

int NativeSensorManager::readEvents(int handle, sensors_event_t* data, int count)

const SensorContext *list;
int i, j;
int number = getSensorCount(); 
int nb;
struct listnode *node;
struct SensorRefMap *item;
list = getInfoByHandle(handle);
•••

该函数比较简单,就是用来读取输入事件,返回的输入事件都是对应的sesnor驱动转换好的事件,是最终上传到上层的事件,如果该sensor

有正在监听它的sesnor,并且监听它的sensor不是它自己,则把该事件插入到所有监听它的sensor的事件buffer中,所有virtual sensor的

输入事件buffer都是通过injectEvents 得来的。

以上是关于sensor中间层 --- NativeSensorManager的主要内容,如果未能解决你的问题,请参考以下文章

OpenHarmony 通俗易懂讲解Sensor订阅流程

心率传感器pulse sensor 与单片机相连接来测心率,中间要加放大和滤波的元器件吗?

Android Sensor详解Sensor ADSP Sensor1 api使用

pir sensor和ir sensor的区别

G-sensor 与M-sensor区别

如何使用 Regex 从数据集中删除“Sensor_”?这是示例集,["Sensor_01", "Sensor_10"