一.其主要框架如下图所示:
二.sensor的JNI层:android_hardware_SensorManager.cpp (frameworks\base\core\jni)
注册JNI:
register_android_hardware_SensorManager
jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager", gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$BaseEventQueue", gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
static JNINativeMethod gSystemSensorManagerMethods[] = {
(void*)nativeClassInit },
nativeClassInit :这函数的作用
jclass sensorClass = _env->FindClass("android/hardware/Sensor"); //得到Sensor.java (frameworks\base\core\java\android\hardware)的class引用
sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;"); //得到sensor的的引用值,这里应该是可以直接把数据传递到framework
sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;");
sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I");
(void*)nativeGetNextSensor },
size_t count = mgr.getSensorList(&sensorList); //得到sensor列表,返回sensor个数
*list = mSensorList; //在SensorManager.cpp (frameworks\native\libs\gui)中
return mSensors.size();
env->SetObjectField(sensor, sensorOffsets.name, name); //获得sensor的信息,就是nativeClassInit 中需要得到的
env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
};
static JNINativeMethod gBaseEventQueueMethods[] = {
(void*)nativeInitSensorEventQueue },
sp<SensorEventQueue> queue(mgr.createEventQueue());
queue = new SensorEventQueue(connection); //构造SensorEventQueue
mRecBuffer = new ASensorEvent[MAX_RECEIVE_BUFFER_EVENT_COUNT]; //生成一些ASensorEvent,用了记录sensor的信息
android_os_MessageQueue_getMessageQueue //得到_MessageQueue
(void*)nativeEnableSensor },
receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency, reservedFlags); //enable sensor
enableSensor //在SensorEventQueue.cpp (frameworks\native\libs\gui)中
mSensorEventConnection->enableDisable(handle, true, us2ns(samplingPeriodUs), us2ns(maxBatchReportLatencyUs), reservedFlags);
(void*)nativeDisableSensor }, //关闭sensor
(void*)nativeDestroySensorEventQueue },
(void*)nativeFlushSensor },
};
实现SensorManager.java中的native函数,它主要调用SenrsorManager.cpp和SensorEventQueue.cpp中的类来完成相关的工作。
SenrsorManager.cpp与SensorService.cpp主要以binder通信
三.SensorService.cpp
SensorService作为一个轻量级的system service,它运行于SystemServer内,即在system_init<system_init.cpp>调用SensorService::instantiate();
SensorService主要功能如下:
1) SensorService::instantiate创建实例对象,并增加到ServiceManager中,且创建并启动线程,并执行threadLoop
2) threadLoop从sensor驱动获取原始数据,然后通过SensorEventConnection把事件发送给客户端
3) BnSensorServer的成员函数负责让客户端获取sensor列表和创建SensorEventConnection
在addService时,第一次构建sp强引用对象时,会调用onFirstRef函数
void SensorService::onFirstRef()
SensorDevice& dev(SensorDevice::getInstance()); // 获取SensorDevice实例, 也就是调用下面的SensorDevice::SensorDevice()。
ssize_t count = dev.getSensorList(&list); 调用SensorDevice.getSensorList获取sensor_t列表
//虚拟的sensor,也就是没有硬件,通过其他硬件计算出来的。
uint32_t virtualSensorsNeeds = (1<<SENSOR_TYPE_GRAVITY) | (1<<SENSOR_TYPE_LINEAR_ACCELERATION) | (1<<SENSOR_TYPE_ROTATION_VECTOR);
registerSensor( new HardwareSensor(list[i]) ); //根据硬件sensor_t创建HardwareSensor,然后加入mSensorList(Sensor),和mSensorMap(HardwareSensor)中
mUserSensorList = mSensorList; // build the sensor list returned to users
/* 这里加入的前提是hasGyro,也就是需要陀螺仪 ,才能加入虚拟sensor*/
aSensor = registerVirtualSensor( new RotationVectorSensor() ); //根据硬件sensor_t创建对应的senosr(如GravitySensor), 根据硬件sensor_t创建对应的senosr(如GravitySensor),
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
mUserSensorList.add(aSensor); //加入UserSensorList,这里RotationVectorSensor,GravitySensor,LinearAccelerationSensor, OrientationSensor, CorrectedGyroSensor
}
/ *后面有一些关于batching的sensor的设置,batching sensor也就是支持批处理的sensor,有fifo */
Looper = new Looper(false); //消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper
mSensorEventBuffer = new sensors_event_t[minBufferSize]; //sensors_event用于藏消息
mSensorEventScratch = new sensors_event_t[minBufferSize];
run("SensorService", PRIORITY_URGENT_DISPLAY); // run("SensorService", PRIORITY_URGENT_DISPLAY);运行线程,并执行threadLoop
bool SensorService::threadLoop()
ssize_t count = device.poll(mSensorEventBuffer, numEventMax); //调用SensorDevice.poll获取sensors_event_t事件
fusion.process(event[i]);对每一个事件,执行SensorFusion.process
activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch, mMapFlushEventsToConnections); 调用SensorService::SensorEventConnection::sendEvents,把事件发送给所有的listener
status_t SensorService::SensorEventConnection::enableDisable
err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs, reservedFlags);
SensorService::enable
err = sensor->activate(connection.get(), true); //使能sensor
四.sensor上层调用中间层的入口
SensorDevice.cpp (frameworks\native\services\sensorservice)
SensorDevice::SensorDevice()
1.hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&mSensorModule); //这个在Sensors.c (vendor\mediatek\proprietary\hardware\sensor)
2.err = sensors_open_1(&mSensorModule->common, &mSensorDevice); 打开sensor
3.err = pressure_sensors_open(&mSensorDevicePressure); //这里我们加入的温度气压传感器
4. mSensorModule->get_sensors_list(mSensorModule, &list); //得到sensor列表,Sensors.c (vendor\mediatek\proprietary\hardware\sensor)
5.for (i=0; i<size_t(count-PRES_TEMP_SENSORS_CNT); i++) {
mActivationCount.add(list[i].handle, model); //把sensor加入到一个vector,handle是sensor唯一的标志 , Hwmsen_chip_info.c (vendor\mediatek\proprietary\hardware\sensor)
mSensorDevice->activate(reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), list[i].handle, 0); //激活sensor
}
6.for (; i<size_t(count); i++) {
mActivationCount.add(list[i].handle, model);
mSensorDevicePressure->activate(mSensorDevicePressure, list[i].handle, 0);
sensor的重要结构体
Sensor设备结构体sensors_poll_device_t,对标准硬件设备hw_device_t结构体的扩展,主要完成读取底层数据,并将数据存储在struct sensors_poll_device_t结构体中,poll函数用来获取底层数据,调用时将被阻塞定义如下:
struct sensors_poll_device_t {
struct hw_device_t common;
//Activate/deactivate one sensor
int (*activate)(struct sensors_poll_device_t *dev,
int handle, int enabled);
//Set the delay between sensor events in nanoseconds for a given sensor.
int (*setDelay)(struct sensors_poll_device_t *dev,
int handle, int64_t ns);
//获取数据
int (*poll)(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count);
};
|
- typedef struct hw_device_t {
- /** tag must be initialized to HARDWARE_DEVICE_TAG */
- uint32_t tag;
-
- /** version number for hw_device_t */
- uint32_t version;
-
- /** reference to the module this device belongs to */
- struct hw_module_t* module;
-
- /** padding reserved for future use */
- uint32_t reserved[12];
-
- /** Close this device */
- int (*close)(struct hw_device_t* device);
-
- } hw_device_t;
- 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;
来源:
struct pollfd {
int fd; /* 文件描述符 */
short events; /* 等待的事件 */
short revents; /* 实际发生了的事件 */
};
五.详解四中每一步
第1步
.hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&mSensorModule);
根据SENSORS_HARDWARE_MODULE_ID得到Sensors.c (vendor\mediatek\proprietary\hardware\sensor)中的HAL层代码
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 = "MTK SENSORS Module",
.author = "Mediatek",
.methods = &sensors_module_methods,
},
.get_sensors_list = sensors__get_sensors_list,
};
这里主要函数是:
sensors__get_sensors_list
*list = sSensorList; //得到sensorlist
struct sensor_t sSensorList[MAX_NUM_SENSOR] ={}; 在Hwmsen_chip_info.c (vendor\mediatek\proprietary\hardware\sensor)中,我推测是apk判断是否支持某种sensor的依据
#ifdef CUSTOM_KERNEL_ACCELEROMETER //这个与ProjectConfig.mk这个相对应
{
.name = ACCELEROMETER,
.vendor = ACCELEROMETER_VENDER,
.version = 3,
.handle = ID_ACCELEROMETER+ID_OFFSET, //这个在Hwmsensor.h (kernel-3.10\include\linux)中定义,是标示各种sensor的唯一值,调用的时候使用
.type = SENSOR_TYPE_ACCELEROMETER, //这个在Hwmsensor.h (kernel-3.10\include\linux)中定义,标示sensor的类型
.maxRange = ACCELEROMETER_RANGE,//32.0f,
.resolution = ACCELEROMETER_RESOLUTION,//4.0f/1024.0f ,上报的精度在4.0f---1024f
.power = ACCELEROMETER_POWER,//130.0f/1000.0f, //估计上电用的时间
.minDelay = 10000, //最少的上报时间=10ms
.maxDelay = 1000000, //1s,最大上报时间
.reserved = {}
},
#endif
第2步:
第3步:
pressure_sensors_open(&mSensorDevicePressure); //这里我们加入的温度气压传感器
sensors__open_sensors((struct hw_device_t**)device); //打开sensor
sensors_poll_context_t *dev = new sensors_poll_context_t();
mSensors[pre] = new PresSensor();
PresSensor::PresSensor() //进入构造函数
SensorBase(NULL, "lps331ap_prs") //在PresSensor.cpp (frameworks\native\services\sensorservice)
data_fd = openInput(data_name); //data_name = lps331ap_prs
dir = opendir(dirname); //dirname=/dev/input
readdir(dir) //循环读取dir下每一个文件,找到lps331ap_prs这个文件,pressure_presence_flag = 1
mEnabled(1),
mEnabledP(1),
mEnabledT(1),
currHzPollFreq(10.0f),
mInputReader(4)
mPendingEventP //设置mPendingEventP结构体,他一个sensors_event_t变量
property_get("ro.hardware.accsensor", buffer, INPUT_SYSFS_PATH_PRES); //得到INPUT_SYSFS_PATH_PRES "/sys/class/input/input5/device/"
getCompenseParam(); //得到补偿参数
LPS331AP_InitializeLibrary(calvalues); //算法相关的
dev->device.activate = poll__activate; //填充结构体
dev->device.setDelay = poll__setDelay;
dev->device.poll = poll__poll;
第4步:
mSensorModule->get_sensors_list(mSensorModule, &list); //得到sensor列表,Sensors.c (vendor\mediatek\proprietary\hardware\sensor)
第5步:
第六步:
6.for (; i<size_t(count); i++) {
mActivationCount.add(list[i].handle, model); //把sensor加入到一个vector,handle是sensor唯一的标志 , Hwmsen_chip_info.c
mSensorDevicePressure->activate(mSensorDevicePressure, list[i].handle, 0);
dev->device.activate = poll__activate; //在pressure_sensors_open里面赋值了这个函数指针
poll__activate //在Sensors.cpp (frameworks\native\services\sensorservice)中
ctx->activate(handle, enabled); //进行enable
sensors_poll_context_t::activate;在Sensors.cpp (frameworks\native\services\sensorservice)
index = handleToDriver(handle); //这里返回0
err = mSensors[index]->enable(handle, enabled);
PresSensor::enable //在PresSensor.cpp (frameworks\native\services\sensorservice)中
fd = open(input_sysfs_path, O_RDWR); //打开/得到INPUT_SYSFS_PATH_PRES "/sys/class/input/input5/device/enable"
err = write(fd, buf, sizeof(buf)); // 写入1,打开sensor
write(mWritePipeFd, &wakeMessage, 1);//写一个W到pipe,pipe在open的时候创建
创建pipe:Sensors.cpp (frameworks\native\services\sensorservice)的sensors_poll_context_t::sensors_poll_context_t()
int wakeFds[2];
int result = pipe(wakeFds); //创建pipe
ALOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
fcntl(wakeFds[0], F_SETFL, O_NONBLOCK); //设置文件的flags为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;
6.sensor数据的读取
bool SensorService::threadLoop() //
SensorService.cpp (frameworks\native\services\sensorservice)
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
SensorDevice::poll(sensors_event_t* buffer, size_t count) //SensorDevice.cpp (frameworks\native\services\sensorservice)
c_pressure = mSensorDevicePressure->poll(mSensorDevicePressure, buffer, PRES_TEMP_SENSORS_CNT);
//ALOGE( "SensorDevice::poll, mSensorDevicePressure return = %d\n", c_pressure);
c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), buffer+PRES_TEMP_SENSORS_CNT, count-PRES_TEMP_SENSORS_CNT);
return ctx->pollEvents(data, count); //Nusensors.cpp (vendor\mediatek\proprietary\hardware\sensor)
int nb = sensor->readEvents(data, count); //Sensors.cpp (frameworks\native\services\sensorservice)
int Hwmsen::readEvents(sensors_event_t* data, int count) //Hwmsen.cpp (vendor\mediatek\proprietary\hardware\sensor)
n = mInputReader.fill(mdata_fd); //后面有些细节没有深究了
n = poll(mPollFds, numFds, nbEvents ? 0 : -1); //poll,等待事件
7.虚拟sensor的读取过程
注册过程
SensorService::onFirstRef
ssize_t count = dev.getSensorList(&list); //得到sensorlist
if (hasGyro) { //注册各种sensor
aSensor = registerVirtualSensor( new RotationVectorSensor() );
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
mUserSensorList.add(aSensor);
}
aSensor = registerVirtualSensor( new GravitySensor(list, count) );
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
mUserSensorList.add(aSensor);
}
aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
mUserSensorList.add(aSensor);
}
aSensor = registerVirtualSensor( new OrientationSensor() );
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
// if we are doing our own rotation-vector, also add
// the orientation sensor and remove the HAL provided one.
mUserSensorList.replaceAt(aSensor, orientationIndex);
}
// virtual debugging sensors are not added to mUserSensorList
registerVirtualSensor( new CorrectedGyroSensor(list, count) );
registerVirtualSensor( new GyroDriftSensor() );
}
enable过程
//SensorService.cpp (frameworks\native\services\sensorservice)
SensorService::enable
SensorInterface* sensor = mSensorMap.valueFor(handle); //得到sensor的接口,虚拟sensor的interface
mActiveVirtualSensors.add(handle, sensor); //加入到mActiveVirtualSensors链
err = sensor->activate(connection.get(), true); //调用active
SensorFusion::activate(void* ident, bool enabled) //调用SensorFusion.cpp (frameworks\native\services\sensorservice)
mSensorDevice.activate(ident, mAcc.getHandle(), enabled); //使能加速度传感器
mSensorDevice.activate(ident, mMag.getHandle(), enabled); //使能磁传感器
mSensorDevice.activate(ident, mGyro.getHandle(), enabled); //使能陀螺仪
SensorDevice::activate //SensorDevice.cpp (frameworks\native\services\sensorservice) //这里就是开始使能实体sensor
获取数据过程
SensorService::threadLoop() //
count = device.poll(mSensorEventBuffer, numEventMax); //这里获取实体sensor的数据
// handle virtual sensors
if (count && vcount) { //如果是虚拟sensor
SensorFusion& fusion(SensorFusion::getInstance());
fusion.isEnabled() //如果使能
fusion.process(event[i]); //调用process
SensorFusion::process //调用SensorFusion.cpp (frameworks\native\services\sensorservice),这里传入的是实体sensor获取来的数据
mFusion.handleGyro(vec3_t(event.data), dT); //处理各自的数据
mFusion.handleMag(mag);
mFusion.handleAcc(acc);
SensorInterface* si = mActiveVirtualSensors.valueAt(j); //得到虚拟sensor的接口
if (si->process(&out, event[i])) { //获取计算好的值
mSensorEventBuffer[count + k] = out;}
// record the last synthesized values
recordLastValueLocked(&mSensorEventBuffer[count], k);
// sort the buffer by time-stamps
sortEventBuffer(mSensorEventBuffer, count); //给这些event排序
activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,),通过activeConnections发送到上层
注意:
如果加速度,磁传感器,陀螺仪的数据不正常可能导致虚拟传感器没有数据!!
- android sensor架构
Android Sensor 架构深入剖析 作者:倪键树,华清远见嵌入式学院讲师. 1.Android sensor架构 Android4.0系统内置对传感器的支持达13种,它们分别是:加速度传感器 ...
- Android Sensor 架构深入剖析【转】
本文转载自: 1.Android sensor架构 Android4.0系统内置对传感器的支持达13种,它们分别是:加速度传感器 (accelerometer).磁力传感器(magnetic fiel ...
- Qualcomm Android display架构分析
Android display架构分析(一) http://blog.csdn.net/BonderWu/archive/2010/08/12/5805961.aspx http://hi.baidu ...
- 高通Android display架构分析
目录(?)[-] Kernel Space Display架构介绍 函数和数据结构介绍 函数和数据结构介绍 函数和数据结构介绍 数据流分析 初始化过程分析 User Space display接口 K ...
- Android MVP架构分析
App架构在Android开发者中一直是讨论比较多的一个话题,目前讨论较多的有MVP.MVVM.Clean这三种.google官方对于架构的态度一直是非常开放的,让开发者自主选择组织和架构app的方式 ...
- (转)App工程结构搭建:几种常见Android代码架构分析
关于Android架构,因为手机的限制,目前我觉得也确实没什么大谈特谈的,但是从开发的角度,看到整齐的代码,优美的分层总是一种舒服的享受的. 从艺术的角度看,其实我们是在追求一种美. 本文先分析几个当 ...
- Android应用架构分析
一.res目录: 1.属性:Android必需: 2.作用:存放Android项目的各种资源文件.这些资源会自动生成R.java. 2.1.layout:存放界面布局文件. 2.2.strings.x ...
- Android Sensor详解(1)简介与架构【转】
本文转载自:https://blog.csdn.net/u013983194/article/details/53244686 最近在学习有关如何porting sensor的东西,仅借此机会写博客来 ...
- Android架构分析之Android消息处理机制(二)
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本号:4.4.2 在上一篇文章中我们看了一个使用Handler处理Message消息的样例,本文我们 ...
随机推荐
- java抓取东方财富股票数据(附源码)
背景 前段时间给朋友写了一个自动抓取同花顺股票数据的程序,不少人觉得不错. 这几天后台有粉丝给我留言让我也抓一下东方财富的数据,说东方财富的数据特别难抓,我还真不一定能搞得定. 本来我是一个德艺双磬且 ...
- MVC单文件上传
前言 现在来写下最基础的单文件上传,完成后可以扩展成各种不同的上传方式 HTML <input id="Input_File" type="file" / ...
- IDEA操作git的一些常用技巧
转自:https://blog.csdn.net/ck4438707/article/details/53455962 Git原理以后会分章节介绍,本次主要说一下intellij怎样操作git.int ...
- 创建本地yum源
1. 环境准备 在准备搭建yum源的服务器上安装createrepo,打开防火墙的80端口或者关闭防火墙. 注:createrepo命令只要不是最小化安装,都是支持的.如果是最小化安装,下载下图下载r ...
- Tarjan缩点入门
缩点 顾名思义,缩点就是把一个强连通分量缩成一个点 Tarjan 在dfs的过程中记录时间戳,若能够通过某个点返回已遍历的点,则可以缩点 inline void Tarjan(int x)// st栈 ...
- 通过阿里镜像网站制作iso文件安装CentOS6.9
基于网络安装 创建kickstart文件的方式: 1.复制模板/root/anaconda-ks.cfg,而后使用vim编辑配置 2.使用system-config-kickstart来生成,建议使用 ...
- SpringBoot第五集:整合Druid和MyBatis(2020最新最易懂)
SpringBoot第五集:整合Druid和MyBatis(2020最新最易懂) 1.SpringBoot整合Druid Druid是阿里巴巴的一个开源项目,是一个数据库连接池的实现,结合了C3P0. ...
- 带货直播源码开发采用MySQL有什么优越性
MySQL是世界上最流行的开源关系数据库,带货直播源码使用MySQL,可实现分钟级别的数据库部署和弹性扩展,不仅经济实惠,而且稳定可靠,易于运维.云数据库 MySQL 提供备份恢复.监控.容灾.快速扩 ...
- php 导出excel 10万数据
php导出excel 10万数据(此代码主要测试用) 在工作当中要对一些基本信息和其他信息导出 起初信息比较小无所谓.... 但当信息超出65535的时候 发现点问题了 超出了 而且 反应速度很慢 实 ...
- leetcode17gas-station
题目描述 环形路上有n个加油站,第i个加油站的汽油量是gas[i]. 你有一辆车,车的油箱可以无限装汽油.从加油站i走到下一个加油站(i+1)花费的油量是cost[i],你从一个加油站出发,刚开始的时 ...