本文主要是介绍Android Sensor Input类型 (五) Sensor HAL NativeSensorManager,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
NativeSensorManager
代码路径:
code/hardware/qcom/sensors/NativeSensorManager.cpp
code/hardware/qcom/sensors/NativeSensorManager.h
NativeSensorManager类定义
class NativeSensorManager : public Singleton<NativeSensorManager> {friend class Singleton<NativeSensorManager>;NativeSensorManager();~NativeSensorManager();struct sensor_t sensor_list[MAX_SENSORS]; //!< sensorlist数组 >! NoteBy: yujixuanstruct SensorContext context[MAX_SENSORS]; //!< context数组 >! NoteBy: yujixuanstruct SensorEventMap event_list[MAX_SENSORS]; //!< 用于上报的evnet 数组 >! NoteBy: yujixuanstatic const struct SysfsMap node_map[]; //sysfs 设备节点名static const struct sensor_t virtualSensorList[];static char virtualSensorName[][SYSFS_MAXLEN]; //虚拟sensor相关int mSensorCount;bool mScanned;int mEventCount;DefaultKeyedVector<int32_t, struct SensorContext*> type_map;DefaultKeyedVector<int32_t, struct SensorContext*> handle_map;DefaultKeyedVector<int, struct SensorContext*> fd_map;void compositeVirtualSensorName(const char *sensor_name, char *chip_name, int type);int getNode(char *buf, char *path, const struct SysfsMap *map);int getSensorListInner();int getDataInfo();int registerListener(struct SensorContext *hw, struct SensorContext *virt);int initCalibrate(const SensorContext *list);int initVirtualSensor(struct SensorContext *ctx, int handle, struct sensor_t info);int addDependency(struct SensorContext *ctx, int handle);int getEventPath(const char *sysfs_path, char *event_path);int getEventPathOld(const struct SensorContext *list, char *event_path);
public:int getSensorList(const sensor_t **list); //!< 获取sensor列表 >! NoteBy: yujixuaninline SensorContext* getInfoByFd(int fd) { return fd_map.valueFor(fd); };inline SensorContext* getInfoByHandle(int handle) { return handle_map.valueFor(handle); };inline SensorContext* getInfoByType(int type) { return type_map.valueFor(type); };int getSensorCount() {return mSensorCount;}void dump();int hasPendingEvents(int handle);int activate(int handle, int enable);int setDelay(int handle, int64_t ns);int readEvents(int handle, sensors_event_t *data, int count); //!< 读取events >! NoteBy: yujixuanint calibrate(int handle, struct cal_cmd_t *para);int batch(int handle, int64_t sample_ns, int64_t latency_ns);int flush(int handle);
};
class NativeSensorManager 继承了Singleton,单例模式,只存在一个实例对象,即在SensorHal 中被多次访问使用的sm;
通过NativeSensorManager class的定义可知 主要有以下内容:
- 定义维护了 在SensorHAL 中由 sensor_t 组成的 sensor_list 数组;
- 定义由SensorContext 组成的 Context数组;
- 定义了SensorEventMap 组成的 event_list 数组;
- 定义了用于记录sensor 在sys中设备节点路径的 SysfsMap;
SysfsMap node_map
struct SysfsMap {int offset;const char *node;int type;int required;
};
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},{offsetof(struct sensor_t, resolution), SYSFS_RESOLUTION, TYPE_FLOAT, 1},{offsetof(struct sensor_t, power), SYSFS_POWER, TYPE_FLOAT, 1},
......
};
SensorEventMap
struct SensorEventMap {char data_name[80];char data_path[PATH_MAX];
};
继承Singleton 单例模式
前面可知,NativeSensorManager : public Singleton,集成了Sigleton, 是单例模式;
Singleton模板类,指定了 template的类型,T为 NativeSensorManager; (note:C++模板)
在NativeSensorManager.cpp的最开始,创建了实例;
ANDROID_SINGLETON_STATIC_INSTANCE(NativeSensorManager);
代码路径:system/core/include/utils/Singleton.h
template <typename TYPE>
class ANDROID_API Singleton
{
public:static TYPE& getInstance() {Mutex::Autolock _l(sLock);TYPE* instance = sInstance;if (instance == 0) {instance = new TYPE();sInstance = instance;}//如果实例对象不存在,实例化一个对象, 已存在直接返回;//TYPE == NativeSensorManagerreturn *instance;}static bool hasInstance() {Mutex::Autolock _l(sLock);return sInstance != 0;}
protected:~Singleton() { };Singleton() { };
private:Singleton(const Singleton&);Singleton& operator = (const Singleton&);static Mutex sLock;static TYPE* sInstance;
};
#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) \template<> ::android::Mutex \(::android::Singleton< TYPE >::sLock)(::android::Mutex::PRIVATE); \template<> TYPE* ::android::Singleton< TYPE >::sInstance(0); \template class ::android::Singleton< TYPE >;
由上分析可知,NativeSensorManager未实例化在第一次调用时有 instance = new TYPE(); 即 new NativeSensorManager();
以下是 NativeSensorManager类构造器的实现:
NativeSensorManager::NativeSensorManager():mSensorCount(0), mScanned(false), mEventCount(0), type_map(NULL), handle_map(NULL), fd_map(NULL)
{int i;memset(sensor_list, 0, sizeof(sensor_list));memset(context, 0, sizeof(context));type_map.setCapacity(MAX_SENSORS);handle_map.setCapacity(MAX_SENSORS);fd_map.setCapacity(MAX_SENSORS);for (i = 0; i < MAX_SENSORS; i++) {context[i].sensor = &sensor_list[i];sensor_list[i].name = context[i].name;sensor_list[i].vendor = context[i].vendor;list_init(&context[i].listener);list_init(&context[i].dep_list);}if(getDataInfo()) {ALOGE("Get data info failed\n");}dump();
}
通过getDataInfo 初始化sensor list数组,sensor context数组,对NativeSensorManager 做实际的数据填充;
dump 显示当前NativeSensorManager的主要内容;
getDataInfo 填充数据
NativeSensorManager是管理sensor HAL 处理的核心,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;struct sensor_t sensor_mag;struct sensor_t sensor_acc;struct sensor_t sensor_light;struct sensor_t sensor_proximity;struct sensor_t sensor_gyro;mSensorCount = getSensorListInner();//1:完成SensorContext list 获取和填充 包含sensor_tfor (i = 0; i < mSensorCount; i++) {struct SensorRefMap *item;list = &context[i];list->is_virtual = false;item = new struct SensorRefMap;item->ctx = list;/* hardware sensor depend on itself */list_add_tail(&list->dep_list, &item->list);if (strlen(list->data_path) != 0)list->data_fd = open(list->data_path, O_RDONLY | O_CLOEXEC | O_NONBLOCK);//open event 路径,获取文件描述符if (list->data_fd > 0) {fd_map.add(list->data_fd, list);// DefaultKeyedVector<int, struct SensorContext*> fd_map;// 添加到sm的fd_map中;}type_map.add(list->sensor->type, list);// DefaultKeyedVector<int32_t, struct SensorContext*> type_map;// 添加到sm的type_map中;handle_map.add(list->sensor->handle, list);// DefaultKeyedVector<int32_t, struct SensorContext*> handle_map;// 添加到sm的handle_map中;//根据不同的sensor type,创建不同的SensorBase子类实例;switch (list->sensor->type) {case SENSOR_TYPE_ACCELEROMETER:has_acc = 1;list->driver = new AccelSensor(list);//假设,type是acc,new一个 AccelSensor; 一个SensorBase子类实例sensor_acc = *(list->sensor);break;case SENSOR_TYPE_MAGNETIC_FIELD:has_compass = 1;list->driver = new CompassSensor(list);sensor_mag = *(list->sensor);break;case SENSOR_TYPE_PROXIMITY:has_proximity = 1;//......list->driver = new LightSensor(list);sensor_light = *(list->sensor);break;//......default:list->driver = NULL;ALOGE("No handle %d for this type sensor!", i);break;}initCalibrate(list);//校准相关}//virtual sensors //......
}
校准相关,virtual sensor相关暂不分析; 通过以上代码,可知在getDataInfo 中主要实现了:
- 通过getSensorListInner 完成SensorContext list 获取和填充 包含sensor_t
- 通过for循环,对每一个sensor做处理,打开其event patch,记录得到的文件描述符fd到map中;
- 判断sensor type 根据返回的结果 创建基于SensorBase的sensor driver实例;
getSensorListInner获取
通过前面的blog可知,sensor kernel driver 注册了sensor class类,提供了若干api 用于往sensor class注册;
sensor driver的具体实现中注册了 input device;通过adb, 可以直观的相关的device node如下:
msm8909:/sys/class/sensors # ls
MPU6050-accel MPU6050-gyro mmc3416x-mag stk3x1x-light stk3x1x-proximitymsm8909:/sys/class/sensors/MPU6050-accel # ls
calibrate enable_wakeup flags max_delay min_delay power sensor_power uevent
device fifo_max_event_count flush max_latency name resolution subsystem vendor
enable fifo_reserved_event_count handle max_range poll_delay self_test type versionmsm8909:/sys/class/sensors/MPU6050-accel/device # ls
MPU6050-accel capabilities enable id name poll_delay properties subsystem uniq
addr device event4 modalias phys power reg uevent writemsm8909:/sys/class/sensors/MPU6050-accel/device # cat uevent
PRODUCT=18/0/0/0
NAME="MPU6050-accel"
PROP=0
EV=9
ABS=100 7
MODALIAS=input:b0018v0000p0000e0000-e0,3,kra0,1,2,28,mlsfw
通过adb 可以直接与这些device node做交互,控制sensor,读取event数据等, 在sensor hal的代码中如何完成这些操作?
前面的内容提到,getDataInfo 填充NativeSensorManager,其中关键是getSensorListInner 完成SensorContext list 获取和填充,下面是它的具体实现:
int NativeSensorManager::getSensorListInner()
{int number = 0;int err = -1;const char *dirname = SYSFS_CLASS;//1: SYSFS_CLASS == "/sys/class/sensors/"char devname[PATH_MAX];char *filename;char *nodename;DIR *dir;struct dirent *de;struct SensorContext *list;unsigned int i;dir = opendir(dirname);strlcpy(devname, dirname, PATH_MAX);filename = devname + strlen(dirname);//2:filename指针指在SYSFS_CLASS之后,即/sys/class/sensors/ 后while ((de = readdir(dir))) {if(de->d_name[0] == '.' &&(de->d_name[1] == '\0' ||(de->d_name[1] == '.' && de->d_name[2] == '\0')))continue; //3:去掉. .. 等无关目录list = &context[number];//4:发现一个目标目录,实现一个list 元素;strlcpy(filename, de->d_name, PATH_MAX - strlen(SYSFS_CLASS));//5:把读到目录名赋值到file name指针的位置;即填充了 devname[PATH_MAX]中 /sys/class/sensors/ 后的内容nodename = filename + strlen(de->d_name);//6:同样的,nodename 指针指向 filename后的位置*nodename++ = '/';for (i = 0; i < ARRAY_SIZE(node_map); i++) {strlcpy(nodename, node_map[i].node, PATH_MAX - strlen(SYSFS_CLASS) - strlen(de->d_name));//7:把node_map中的 预设的name 传入err = getNode((char*)(list->sensor), devname, &node_map[i]);if (err) {ALOGE("Get node for %s failed.\n", devname);break;}//8;过程与上相同,获取每个node的具体路径}list->sensor->handle = SENSORS_HANDLE(number);//#define SENSORS_HANDLE(x) (SENSORS_HANDLE_BASE + x + 1)strlcpy(nodename, "", SYSFS_MAXLEN);strlcpy(list->enable_path, devname, PATH_MAX);/* initialize data path */strlcpy(nodename, "device", SYSFS_MAXLEN);//路径指向: /sys/class/sensors/MPU6050-accel/deviceif (getEventPath(devname, list->data_path) == -ENODEV) {getEventPathOld(list, list->data_path);}//9:获取event 节点路径,用来读取数据, 比如 MPU6050-accel, 注册的input event路径是:///dev/input/event4number++;}closedir(dir);return number;
}
在/code/hardware/qcom/sensors/sensors.h 中已经预设了 若干信息,例如:
#define SYSFS_CLASS "/sys/class/sensors/"
#define SYSFS_NAME "name"
#define SYSFS_VENDOR "vendor" #define SYSFS_VERSION "version"
getSensorListInner 完成对sys中sensor class下每一个sensor的处理;
通过getNode把每一个sensor下的节点数据获取到,并填充保存到相应的数据结构中;
通过getEventPatch 获取到sensor driver驱动中注册的 input device在 input 下的路径;
比如通过adb 可以看到/sys/class/sensors/MPU6050-accel/device
下event的编号是event4, 则记录input device的device node 是/dev/input/event4, 后续读取sensor data 则是通过这个路径。
以下是getNode的实现:
getNode
int NativeSensorManager::getNode(char *buf, char *path, const struct SysfsMap *map) {char * fret;ssize_t len = 0;int fd;char tmp[SYSFS_MAXLEN];//......memset(tmp, 0, sizeof(tmp));fd = open(path, O_RDONLY);//......len = read(fd, tmp, sizeof(tmp) - 1);//......tmp[len - 1] = '\0';if (tmp[strlen(tmp) - 1] == '\n')tmp[strlen(tmp) - 1] = '\0';//把p 指向sensor_t map->offset 的位置,以name为例,指向指向sensor_t 的nameif (map->type == TYPE_INTEGER) {int *p = (int *)(buf + map->offset);*p = atoi(tmp);} else if (map->type == TYPE_STRING) {char **p = (char **)(buf + map->offset);strlcpy(*p, tmp, SYSFS_MAXLEN);} else if (map->type == TYPE_FLOAT) {float *p = (float*)(buf + map->offset);*p = atof(tmp);} else if (map->type == TYPE_INTEGER64) {int64_t *p = (int64_t *)(buf + map->offset);*p = atoll(tmp);}//read node中的内容,并根据node map中预设的类型 做好转换,把每个sesnor_t 的内容填充上close(fd);return 0;
}
getNode把每一个sensor下的节点数据获取到,根据map->type 做好指的转换并记录下;
node_map 前面提过,它是SysfsMap元素组成的 预设的数组
struct SysfsMap {int offset;const char *node;int type;int required;
};
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},{offsetof(struct sensor_t, resolution), SYSFS_RESOLUTION, TYPE_FLOAT, 1},{offsetof(struct sensor_t, power), SYSFS_POWER, TYPE_FLOAT, 1},{offsetof(struct sensor_t, minDelay), SYSFS_MINDELAY, TYPE_INTEGER, 1},{offsetof(struct sensor_t, fifoReservedEventCount), SYSFS_FIFORESVCNT, TYPE_INTEGER, 0},{offsetof(struct sensor_t, fifoMaxEventCount), SYSFS_FIFOMAXCNT, TYPE_INTEGER, 0},
#if defined(SENSORS_DEVICE_API_VERSION_1_3)
#if defined(__LP64__){offsetof(struct sensor_t, maxDelay), SYSFS_MAXDELAY, TYPE_INTEGER64, 0},{offsetof(struct sensor_t, flags), SYSFS_FLAGS, TYPE_INTEGER64, 0},
#else{offsetof(struct sensor_t, maxDelay), SYSFS_MAXDELAY, TYPE_INTEGER, 0},{offsetof(struct sensor_t, flags), SYSFS_FLAGS, TYPE_INTEGER, 0},
#endif
#endif
};
SensorBase
在前面的getDataInfo处理过程中,其中判断sensor type 根据返回的结果 创建基于SensorBase的sensor driver实例是很关键的一步;
HAL中完成框架性的处理,实际操作需要根据每个sensor的特性对不同的sensor种类做不同的定义处理,以下是以acc为例:
在getDataInfo中,new了一个AccelSensor:
switch (list->sensor->type) {case SENSOR_TYPE_ACCELEROMETER:has_acc = 1;list->driver = new AccelSensor(list);
AccelSensor类的定义如下:
class AccelSensor : public SensorBase {InputEventCircularReader mInputReader;sensors_event_t mPendingEvent;bool mHasPendingEvent;int64_t mEnabledTime;int setInitialState();
public:AccelSensor();AccelSensor(char *name);AccelSensor(struct SensorContext *context);virtual ~AccelSensor();virtual int readEvents(sensors_event_t* data, int count);virtual bool hasPendingEvents() const;virtual int setDelay(int32_t handle, int64_t ns);virtual int enable(int32_t handle, int enabled);virtual int calibrate(int32_t handle, struct cal_cmd_t *para,struct cal_result_t *cal_result);virtual int initCalibrate(int32_t handle, struct cal_result_t *cal_result);
};
它继承自SensorBase类, SensorBase也是各类sensor类的父类,以下是SensorBase的类的定义:
class SensorBase {
protected:const char* dev_name;const char* data_name;const sensor_cal_algo_t* algo;char input_name[PATH_MAX];int dev_fd;int data_fd;int64_t report_time;bool mUseAbsTimeStamp;sensors_meta_data_event_t meta_data;char input_sysfs_path[PATH_MAX];int input_sysfs_path_len;int mEnabled;int mHasPendingMetadata;int64_t sysclk_sync_offset;int openInput(const char* inputName);static int64_t getTimestamp();static int64_t getClkOffset();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,const struct SensorContext* context = NULL);virtual ~SensorBase();virtual int readEvents(sensors_event_t* data, int count) = 0;virtual int injectEvents(sensors_event_t* data, int count);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;virtual int calibrate(int32_t handle, struct cal_cmd_t *para, struct cal_result_t *cal_result);virtual int initCalibrate(int32_t handle, struct cal_result_t *cal_result);virtual int setLatency(int32_t handle, int64_t ns);virtual int flush(int32_t handle);
};
SensorBase类中定义了如,readEvents,enable,flush等操作函数,AccelSensor继承了这些虚函数,并且完成了重写;
前文提到,读取poll_poll是调用了NativeSensorManager::readEvents,
list->driver->readEvents(data, count); 即是取出SensorBase指针指向的对象,调用它的readEvents函数;(note:多态的应用,通过指向父类类型对象,调用虚函数,实际调用到子类重写的具体的readEvents函数)
InputEventCircularReader
AccelSensor类定义的首个元素是:mInputReader,它是InputEventCircularReader 类对象;如其名称,输入事件循环读取,它主要用于对sensor event data的获取;
InputEventCircularReader 类定义如下:
class InputEventCircularReader
{struct input_event* const mBuffer;struct input_event* const mBufferEnd;struct input_event* mHead;struct input_event* mCurr;ssize_t mFreeSpace;
public:InputEventCircularReader(size_t numEvents);~InputEventCircularReader();ssize_t fill(int fd);ssize_t readEvent(input_event const** events);void next();
};
ssize_t InputEventCircularReader::fill(int fd)
{size_t numEventsRead = 0;if (mFreeSpace) {const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));if (nread<0 || nread % sizeof(input_event)) {// we got a partial event!!return nread<0 ? -errno : -EINVAL;}numEventsRead = nread / sizeof(input_event);if (numEventsRead) {mHead += numEventsRead;mFreeSpace -= numEventsRead;if (mHead > mBufferEnd) {size_t s = mHead - mBufferEnd;memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));mHead = mBuffer + s;}}}return numEventsRead;
}
ssize_t InputEventCircularReader::readEvent(input_event const** events)
{*events = mCurr;ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;return available ? 1 : 0;
}
void InputEventCircularReader::next()
{mCurr++;mFreeSpace++;if (mCurr >= mBufferEnd) {mCurr = mBuffer;}
}
InputEventCircularReader 提供了fill,和 readEvent函数;
AccelSensor中的readEvents函数是使用它们来完成;以下是 readEvents的实现,这也是 读取HAL读取event data的最终实现的部分;
int AccelSensor::readEvents(sensors_event_t* data, int count)
{if (count < 1)return -EINVAL;if (mHasPendingEvent) {mHasPendingEvent = false;mPendingEvent.timestamp = getTimestamp();*data = mPendingEvent;return mEnabled ? 1 : 0;}if (mHasPendingMetadata) {mHasPendingMetadata--;meta_data.timestamp = getTimestamp();*data = meta_data;return mEnabled ? 1 : 0;}ssize_t n = mInputReader.fill(data_fd);if (n < 0)return n;int numEventReceived = 0;input_event const* event;
#if FETCH_FULL_EVENT_BEFORE_RETURN
again:
#endifwhile (count && mInputReader.readEvent(&event)) {int type = event->type;if (type == EV_ABS) {float value = event->value;if (event->code == EVENT_TYPE_ACCEL_X) {mPendingEvent.data[0] = value * CONVERT_ACCEL_X;} else if (event->code == EVENT_TYPE_ACCEL_Y) {mPendingEvent.data[1] = value * CONVERT_ACCEL_Y;} else if (event->code == EVENT_TYPE_ACCEL_Z) {mPendingEvent.data[2] = value * CONVERT_ACCEL_Z;}} else if (type == EV_SYN) {switch (event->code){case SYN_TIME_SEC:{mUseAbsTimeStamp = true;report_time = event->value*1000000000LL;}break;case SYN_TIME_NSEC:{mUseAbsTimeStamp = true;mPendingEvent.timestamp = report_time+event->value;}break;case SYN_REPORT:{if(mUseAbsTimeStamp != true) {mPendingEvent.timestamp = timevalToNano(event->time);}mPendingEvent.timestamp -= sysclk_sync_offset;if (mEnabled) {*data++ = mPendingEvent;numEventReceived++;count--;}}break;}} else {ALOGE("AccelSensor: unknown event (type=%d, code=%d)",type, event->code);}mInputReader.next();}
#if FETCH_FULL_EVENT_BEFORE_RETURN/* if we didn't read a complete event, see if we can fill andtry again instead of returning with nothing and redoing poll. */if (numEventReceived == 0 && mEnabled == 1) {n = mInputReader.fill(data_fd);if (n)goto again;}
#endifreturn numEventReceived;
}
这篇关于Android Sensor Input类型 (五) Sensor HAL NativeSensorManager的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!