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

Posted 王玉成的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 floats
                    float 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 
            float           data[16];
            ASensorVector   vector;
            ASensorVector   acceleration;
            ASensorVector   magnetic;
            float           temperature;
            float           distance;
            float           light;
            float           pressure;
            float           relative_humidity;
            AUncalibratedEvent uncalibrated_gyro;
            AUncalibratedEvent uncalibrated_magnetic;
            AMetaDataEvent meta_data;
        ;  
        union 
            uint64_t        data[8];
            uint64_t        step_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 
204     VHANDLER_LOG;
205 
206     int nbEvents = 0;
207     int nb, polltime = -1;
208 
209     polltime = ((MPLSensor*) mSensor)->getStepCountPollTime();
210 
211     // look for new events
212     nb = poll(mPollFds, numFds, polltime);
213     LOGI_IF(0, "poll nb=%d, count=%d, pt=%d", nb, count, polltime);
214     if (nb > 0) 
215         for (int i = 0; count && i < numSensorDrivers; i++) 
216             if (mPollFds[i].revents & (POLLIN | POLLPRI))                
217                 LOGI_IF(0, "poll found=%d", i);
218                 nb = 0;
219                 if (i == mpl) 
220                     ((MPLSensor*) mSensor)->buildMpuEvent();
221                     mPollFds[i].revents = 0;
222                  else if (i == compass) 
223                     ((MPLSensor*) mSensor)->buildCompassEvent();
224                     mPollFds[i].revents = 0;
....
268         if(((MPLSensor*) mSensor)->hasStepCountPendingEvents() == true) 
269             nb = 0;
270             nb = ((MPLSensor*) mSensor)->readDmpPedometerEvents(data, count, ID_SC, SENSOR_TYPE_STEP_COUNTER, 0);
271             LOGI_IF(HANDLER_DATA, "sensors_mpl:readStepCount() - nb=%d, count=%d, nbEvents=%d, data->timestamp=%lld, data->data[0]=%f,",
272                           nb, count, nbEvents, data->timestamp, data->data[0]);
273             if (nb > 0) 
274                 count -= nb;
275                 nbEvents += nb;
276                 data += 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的文档,现在的实现有变化,大致可以参考一下。

http://processors.wiki.ti.com/index.php/Android_Sensor_PortingGuide  内核层的更改方法。


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





以上是关于android中的计步问题及计步传感器分析的主要内容,如果未能解决你的问题,请参考以下文章

需求-Android开发计步器调研与选型参考

安卓计步器的简单实现

如何将加速度计传感器数据转换为计步器?

安卓 计步传感器

手机计步是啥原理

ios 计步器的简单实现