Android Sensor代码流程简介

                                                                                                     Android  Sensor 代码流程简介

 

如今的传感器被越来越多用到设备开发当中,今天我们就来讲解下Qualcomm DragonBoard 410c的sensor架构,本篇主要基于Android5.1.1 来介绍sensor的Framework ,JNI,HAL以及lib,基于mma7660.c驱动的源码分析。


一:Framework分析

 我们先来分析SystemSensorManager源码。

1.SystemSensorManager构造函数

 

    public SystemSensorManager(Context context,Looper mainLooper) {

        mMainLooper = mainLooper;

        mTargetSdkLevel =context.getApplicationInfo().targetSdkVersion;

        synchronized(sSensorModuleLock) {

            if (!sSensorModuleInitialized) {

                sSensorModuleInitialized =true;

 

                nativeClassInit();

 

                // initialize the sensor list

                final ArrayListfullList = sFullSensorsList;

                int i = 0;

                do {

                    Sensor sensor = newSensor();

                    i = nativeGetNextSensor(sensor,i);

                    if (i>=0) {

                        //Log.d(TAG,"found sensor: " + sensor.getName() +

                        //        ", handle=" +sensor.getHandle());

                        fullList.add(sensor);

                        sHandleToSensor.append(sensor.getHandle(),sensor);

                    }

                } while (i>0);

            }

        }

    }

构造函数接收Context和looper参数。理解这两个参数很重要,后面在讲到传感器数据读取时就是利用主线程的looper来读取数据(这和Android5.0之前创建线程读取数据不同)。

构造函数先保留Context和looper私有变量。然后查看SystemSensorManager对象是否被初始化过,如果已经初始化了则什么也不做,反之,初始化JNI,获取传感器列表,并形成传感器handler和sensor的映射关系。


2.注册监听器


    protected booleanregisterListenerImpl(SensorEventListener listener, Sensor sensor,

            int delayUs, Handler handler, intmaxBatchReportLatencyUs, int reservedFlags) {

        if (listener == null || sensor == null){

            Log.e(TAG, "sensor or listeneris null");

            return false;

        }

        // Trigger Sensors should use therequestTriggerSensor call.

        if (sensor.getReportingMode() ==Sensor.REPORTING_MODE_ONE_SHOT) {

            Log.e(TAG, "Trigger Sensorsshould use the requestTriggerSensor.");

            return false;

        }

        if (maxBatchReportLatencyUs < 0 ||delayUs < 0) {

            Log.e(TAG, "maxBatchReportLatencyUsand delayUs should be non-negative");

            return false;

        }

 

        // Invariants to preserve:

        // - one Looper per SensorEventListener

        // - one Looper per SensorEventQueue

        // We map SensorEventListener to aSensorEventQueue, which holds the looper

        synchronized (mSensorListeners) {

            SensorEventQueue queue =mSensorListeners.get(listener);

            if (queue == null) {

                Looper looper = (handler !=null) ? handler.getLooper() : mMainLooper;

                queue = newSensorEventQueue(listener, looper, this);

                if (!queue.addSensor(sensor,delayUs, maxBatchReportLatencyUs, reservedFlags)) {

                    queue.dispose();

                    return false;

                }

                mSensorListeners.put(listener,queue);

                return true;

            } else {

                return queue.addSensor(sensor,delayUs, maxBatchReportLatencyUs, reservedFlags);

            }

        }

    }

 

监听数据的思想如下:

讲监听器Listener包装到SensorEventQueue事件队列中。SensorEventQueue这个事件队列在获取传感器数据后会调用Listener。其中主要的数据获取逻辑包装在SensorEventQueue中。

 

3. SensorEventQueue分析


SensorEventQueue类继承自BaseEventQueue。

 

   a. SensorEventQueue构造函数


       public SensorEventQueue(SensorEventListener listener, Looper looper,

                SystemSensorManager manager) {

           super(looper, manager);

           mListener = listener;

       }

构造函数传入的三个参数为listener,looper和manager。从构造函数中,looper和manager传递给父构造函数。Listener有SensorEventQueue维护。

当传感器数据到来时,会调用       

protectedabstract void dispatchSensorEvent(int handle, float[] values, int accuracy,

                long timestamp);

SensorEventQueue在dispatchSensorEvent函数中调用listener。

 

    b. BaseEventQueue构造函数

        BaseEventQueue(Looper looper,SystemSensorManager manager) {

            nSensorEventQueue= nativeInitBaseEventQueue(this, looper.getQueue(), mScratch);

           mCloseGuard.open("dispose");

            mManager =manager;

        }

Looper参数主要是用来在JNI中读取传感器的值。

 

二. JNI分析

JNI文件的源码为android_hardware_SensorManager.cpp中。整个文件的核心在于Receiver类。该类负责从sensor服务端获取数据,并回调1.3.1中的dispatchSensorEvent函数分发数据。

这里主要讲

nativeInitSensorEventQueue函数和Receive类。nativeInitSensorEventQueue负责与服务端建立连接管道,后者用于读取管道中的值和数据分发。

 

static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz,jobject eventQ, jobject msgQ, jfloatArray scratch) {

    SensorManager&mgr(SensorManager::getInstance());

    spqueue(mgr.createEventQueue());

 

    spmessageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);

    if (messageQueue == NULL){

       jniThrowRuntimeException(env, "MessageQueue is notinitialized.");

        return 0;

    }

 

    spreceiver = new Receiver(queue, messageQueue, eventQ, scratch);

    receiver->incStrong((void*)nativeInitSensorEventQueue);

    returnjlong(receiver.get());

}

 

该函数主要是调用Sensormanager创建一个事件队列。然后利用事件队列和消息队列构造出Receiver。

 

类Receiver。

Class Reveiver : public LooperCallback。

重要的成员和方法为

mSensorQueue :数据通道的队列

mMessageQueue :looper的消息队列

mReceiverObject:被Framework层引用

mScratch:数据容器

 

    virtual void onFirstRef(){

       LooperCallback::onFirstRef();

       mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,

               ALOOPER_EVENT_INPUT, this, mSensorQueue.get());

    }

在引用时调用,将数据通道队列中的数据上报文件描述符添加到looper的epool模型中。

      virtual int handleEvent(int fd, int events, void* data)。当looper中的epool模型监测到onFirstRef中添加的文件描述符有事件发生时,被调用。该函数的实现主要是从数据通道中读取传感器事件,回调dispatchSensorEvent函数像应用注册的监听器发送数据。

 

三. HAL设计

Android 5.1.1HAL层的设计和Android5.0之前的设计思想相同,实现的原理相同。基本思想为:

Sensorserver.cpp文件中维护与SensorEventQueue对应的SensorEventConnection链表。一个SensroEventQueue对用一个SensorEventConnection。同时Sensorserver.cpp创建一个线程去读取传感器的数据,然后向这个SensorEventConnection链表进行分发(向Connection的文件描述符写入),在JNIlooper线程中这个写入动作会被epool模型监测到,JNI就可以去读取connection中的数值。

因为Android中任何cpp类继承与RefBase类,因此在引用的时候调用onFirstRef。SensorService类在系统启动时初始化,主要初始化程序在onFirstRef中

onRirstRef函数中主要执行以下几个任务。

1.引用SensorDevice类获取sensor列表。

2.将获取到的sensor列表注册到本地列表

3.检查是否有虚拟sensor,如果有,注册到本地列表。

4.调用run()函数来执行threadlooper。

下面分析threadlooper函数

Threadoppe函数主要执行下面的工作:

1.调用SensorDevice类的poll来获取传感器数据

2.传感器融合逻辑

3.扫面connection链表,将传感器数据分达到connection链表中。

 

SensorDevice类。

SensorDevice类负责与lib库交互,主要是为sensorserver类提供统一的接口。

SensorDevice构造函数

该函数实现了两个功能:

1 获取sensormodule

2 打开sensordevice

3 获取sensor列表并保存在本地

 

四. Lib库

高通的lib库在文档

80-NT275-1_A_MSM8916_8939_8909_Native_Sensors_Overview.pdf描述的非常清楚。与Androoid原生代码的区别在于高通提供了一个NativeSensorManager类

1.该类可以用来定制厂商的融合逻辑。

2.方便的读取内核中sysfs文件系统中的sensor信息(主要方法就是扫面固定目录下的所有目录和目录下所有文件的属性,然后将扫描结果保存在本地)。

 

 以上就是sensor在框架层中的代码结构了。kernel层的驱动由各个厂商实现了,我们只需集成到我们的系统当中即可。

 

 

 

 

你可能感兴趣的:(Android Sensor代码流程简介)