android中的计步问题及计步传感器分析

今天打开博客,才发现居然有一年多没有写博客了。。。

最近由于公司要分析android上的计步问题,顺便把计步器在android上的实现跟踪了一下。结果发现悲催的是,android的api19上,是用的硬件本身的计步实现了。

android源码中的流程追踪如下:

frameworks/base/core/java/android/hardware/Sensor.java 中定义了TYPE_STEP_DETECTOR和TYPE_STEP_COUNTER。 请注意,detector启动后,确认了,才启动counter.

然后在jni以下查到调用。

frameworks/base/core/jni/android_hardware_SensorManager.cpp

virtual int handleEvent(int fd, int events, void* data) {JNIEnv* env = AndroidRuntime::getJNIEnv();sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);ssize_t n;ASensorEvent buffer[16];while ((n = q->read(buffer, 16)) > 0) {for (int i=0 ; i<n ; i++) {if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {// step-counter returns a uint64, but the java API only deals with floatsfloat value = float(buffer[i].u64.step_counter);env->SetFloatArrayRegion(mScratch, 0, 1, &value);} else {env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);}可以看到,如果是计步器,直接从q里面读出的原生值。其中q被转化成了SensorEventQueue.查找转化方法:

frameworks/native/libs/gui/SensorEventQueue.cpp

ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) {if (mAvailable == 0) {ssize_t err = BitTube::recvObjects(mSensorChannel,mRecBuffer, MAX_RECEIVE_BUFFER_EVENT_COUNT);if (err < 0) {return err;}mAvailable = err;mConsumed = 0;}size_t count = numEvents < mAvailable ? numEvents : mAvailable;memcpy(events, mRecBuffer + mConsumed, count*sizeof(ASensorEvent));mAvailable -= count;mConsumed += count;return count;}也就是说,SensorEvent是保存在ASensorEvent的结构中。查找原型。

frameworks/native/include/android/sensor.h

/* NOTE: Must match hardware/sensors.h */typedef struct ASensorEvent {int32_t version; /* sizeof(struct ASensorEvent) */int32_t sensor;int32_t type;int32_t reserved0;int64_t timestamp;union {union {floatdata[16];ASensorVector vector;ASensorVector acceleration;ASensorVector magnetic;floattemperature;floatdistance;floatlight;floatpressure;floatrelative_humidity;AUncalibratedEvent uncalibrated_gyro;AUncalibratedEvent uncalibrated_magnetic;AMetaDataEvent meta_data;};union {uint64_tdata[8];uint64_tstep_counter;} u64;};int32_t reserved1[4];} ASensorEvent;这时数据出来了。。。。直接调用硬件上的计步器实现。

hal层的相关文件。

./hardware/libhardware/include/hardware/sensors.h#define SENSOR_TYPE_STEP_DETECTOR(18)…#define SENSOR_TYPE_STEP_COUNTER(19)OK。这时候查找hal层的使用方法。

invensense/65xx/libsensors_iio/sensors_mpl.cpp

202 int sensors_poll_context_t::pollEvents(sensors_event_t *data, int count)203 {204VHANDLER_LOG;205 206int nbEvents = 0;207int nb, polltime = -1;208 209polltime = ((MPLSensor*) mSensor)->getStepCountPollTime();210 211// look for new events212nb = poll(mPollFds, numFds, polltime);213LOGI_IF(0, "poll nb=%d, count=%d, pt=%d", nb, count, polltime);214if (nb > 0) {215for (int i = 0; count && i < numSensorDrivers; i++) {216if (mPollFds[i].revents & (POLLIN | POLLPRI)) {217LOGI_IF(0, "poll found=%d", i);218nb = 0;219if (i == mpl) {220((MPLSensor*) mSensor)->buildMpuEvent();221mPollFds[i].revents = 0;222} else if (i == compass) {223((MPLSensor*) mSensor)->buildCompassEvent();224mPollFds[i].revents = 0;….268if(((MPLSensor*) mSensor)->hasStepCountPendingEvents() == true) {269nb = 0;270nb = ((MPLSensor*) mSensor)->readDmpPedometerEvents(data, count, ID_SC, SENSOR_TYPE_STEP_COUNTER, 0);271LOGI_IF(HANDLER_DATA, "sensors_mpl:readStepCount() – nb=%d, count=%d, nbEvents=%d, data->timestamp=%lld, data->data[0]=%f,",272nb, count, nbEvents, data->timestamp, data->data[0]);273if (nb > 0) {274count -= nb;275nbEvents += nb;276data += nb;277}278}可以看出,270行把数据读出来了。。。

顺便查了一下android中的sensor的实现方法。

https://source.android.com/devices/sensors/sensor-stack.html 官方的介绍。sensor层次的介绍,,不是很详细。

https://docs.google.com/file/d/0B2IJqxU5nzCyQWZ1TzhGd3FUWlNCQjhqV0psV1l3dw/edit 2012的文档,现在的实现有变化,大致可以参考一下。

内核层的更改方法。

手上没有nexus5的内核源码,所以暂时没有跟n5中的step counter的内核中的驱动实现。不过这个跟踪过程比较简单了。

要温暖还是怕麻烦。

android中的计步问题及计步传感器分析

相关文章:

你感兴趣的文章:

标签云: