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的内核中的驱动实现。不过这个跟踪过程比较简单了。

时间: 2024-10-26 16:32:56

android中的计步问题及计步传感器分析的相关文章

Android 中View的绘制机制源码分析 三

到目前为止,measure过程已经讲解完了,今天开始我们就来学习layout过程,不过在学习layout过程之前,大家有没有发现我换了编辑器,哈哈,终于下定决心从Html编辑器切换为markdown编辑器,这里之所以使用"下定决心"这个词,是因为毕竟Html编辑器使用好几年了,很多习惯都已经养成了,要改变多年的习惯确实不易,相信这也是还有很多人坚持使用Html编辑器的原因.这也反应了一个现象,当人对某一事物非常熟悉时,一旦出现了新的事物想取代老的事物时,人们都有一种抵触的情绪,做技术的

Android 中View的绘制机制源码分析 二

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/46842891 本篇文章接着上篇文章的内容来继续讨论View的绘制机制,上篇文章中我们主要讲解了View的measure过程,今天我们就来学习ViewGroup的measure过程,由于ViewGroup只是一个抽象类,所以我们需要以一个具体的布局来分析measure过程,正如我上篇文章说的,我打算使用LinearLayout为例讲解measure过程,如果你还没有读过上篇文章,那么建议你先

Android中一个有趣的crash的日志分析

很久前写的一篇文章,发出来以作纪念:) Android中一个有趣的crash的日志分析 首先看看bugly平台中异常的统计信息,表面上是一个NullPointerException: 发生异常设备统计信息如下图,有意思的是全部都是root过的机器: 接下来看跟踪日志,在最下面可以看到这样的日志,抛出了NullpointerException: 引起异常的是com.lishu.net.LishuNet$2类,从类名看显然是某一个类的内部类. 第一个反应,当然是搜索一下应用的源代码,看看是不是有co

Android 中View的绘制机制源码分析 一

尊重原创: http://blog.csdn.net/yuanzeyao/article/details/46765113 差不多半年没有写博客了,一是因为工作比较忙,二是觉得没有什么内容值得写,三是因为自己越来越懒了吧,不过最近我对Android中View的绘制机制有了一些新的认识,所以想记录下来并分享给大家.在之后的几篇博客中,我会给大家分享如下的内容: 1.View中measure(),layout(),draw()函数执行过程分析,带领大家详细分析View的尺寸测量过程,位置计算,并最终

Android中使用Handler造成内存泄露的分析和解决

什么是内存泄露? Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收:另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到达,同样会被GC回收. Android中使用Handler造成内存泄露的原因 Handler mHand

Android中AsyncTask基本用法与源码分析(API 23)

原文链接 http://sparkyuan.github.io/2016/03/23/AsyncTask源码剖析(API 23)/ 转载请注明出处 Android的UI是线程不安全的,想在子线程中更新UI就必须使用Android的异步操作机制,直接在主线程中更新UI会导致程序崩溃. Android的异步操作主要有两种,AsyncTask和Handler.AsyncTask是一个轻量的异步类,简单.可控.本文主要结合API 23的源码讲解一下AsyncTask到底是什么. 基本用法 声明:Andr

Android中Google Drive显示黑屏问题分析

一.问题现象 在contacts中添加一个新的联系人,为新的联系人选择一个icon,在弹出的documents窗口中选择drive,在drive中选择一个图片,然后出现一段时间的黑屏. Platform:MT6572 Android版本:4.4KK BuildType:user 系统软件版本:SWC9G+UAG0 系统RAM:512M 二.关键log以及相关代码 三.问题初步分析 四.建议的问题解决方案 完整的分析流程请直接下载PDF文档: Drive_show_black_screen_iss

Android中dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent事件分析

因为触摸事件一定会触发的ACTION是DOWN,这个也是最先触发的,所以标题中的三个方法研究的也就是这个DOWN事件的传递情况. 下面直接贴出测试代码,边看边讲: 一个Activity,Activity中只有dispatchTouchEvent和onTouchEvent方法. public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { sup

Android 中 吐司显示不出来的原因分析

当你发现你的toast的show方法的确被执行了,但是却没有在界面中显示出来, 有问题的地方可能有两点: 1.Context上下文对象有问题,不是当前的上下文对象或者什么的: 2.message(即Toast要显示的问题)有问题,可能message最后为“”. 如果这两个问题都没有错的话,就要考虑安卓不允许在子线程中更改UI 要解决这个问题就简单了,在子线程中通过handler传递接收数据来显示Toast即可. 比如在实现反馈页面的时候. 这是反馈成功时子线程中的代码,反馈失败就不写了. Mes

Android中so使用知识和问题总结以及插件开发过程中加载so的方案解析

一.前言 Android中有时候为了效率以及平台开发库的支持,难免会用到NDK开发,那么都会产生一个so文件,通过native方法进行调用,开发和调用步骤很简单,这里就不多说了,本文主要来介绍,我们在使用so的时候总是会出现一些常见的问题,而现在插件化开发也很普遍了,有时候插件中也会包含一些so文件,需要加载,这时候也会出现一些问题.本文就来详细总结一下这些问题出现的原因,以及解决方法,主要还是通过源码来分析. 二.涉及到的源码类 因为本文主要通过分析源码来分析so使用的知识点和问题总结,所以涉