zoukankan      html  css  js  c++  java
  • SensorService architechure’ note

    (albert luo 2013.8.17)             

    对SensorService类的作用的理解:

    SensorService是android的sensor方面相关核心的类,其实是android系统SystemServer中的一个,是在android系统运行SystemServer时会自动运行起来,其实就是创建了一个线程,用来专门处理sensor相关的数据从hal到app(client)的传输以及对sensor的控制等功能。

     

    下面对SensorService类的架构分析。

    SensorService的作用主要是沟通app和底层hal的桥梁。我的理解是这样的。大概的连接图如下:

     

     

    如上图,SensorService与HAL和client的沟通通过的是抽离出来的SensorDevice和SensorEventConnection两个类,sensordevice是hal与sensorservice之间,SensorEventConection是client和sensorservice之间。

    所以Sensorservice类相当于控制中心,负责调度管理contrl SensorEventConnection和sensordevice的工作,真正具体的怎么实现交由这两个具体实现。那么其实SensorEventConnetion和sensordevice是sensorservice与上下层之间沟通的interface。

    这样的架构功能划分很清楚,以及各个模块之间的独立性很好,也很方便将来对于部分模块的修改与代码维护。

    下面具体的来看看:

    Sensorservice必须实体化一些上面的interface的具体对象,所以sensorservice定义一些容器来存储相关的对象。

    1. 数据容器存放所有sensor相关对象

    Vector<Sensor> mSensorList; //sensor对象容器

    //handle与与之对应的sensor对象指针的map容器

    //SensorInterface内封装的sensor

    DefaultKeyedVector<int, SensorInterface*> mSensorMap;

    Vector<SensorInterface *> mVirtualSensorList;

    //记录与sensorservcie连接的sensor对象容器

    DefaultKeyedVector<int, SensorRecord*> mActiveSensors;

    //记录与sensorservcie连接的virtual sensor对象容器

    DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;

    //记录client与sensorservice连接的SensorEventConnection

    SortedVector< wp<SensorEventConnection> > mActiveConnections;

     

    2.所有sensor对象的获取方式

    前面说过SensorService与hal层的沟通通过SensorDevice,因此获取sensor对象 就必须实例化一个sensordevice对象。在sensorservice的onFirstref函数中:

    void SensorService::onFirstRef()

    {

       LOGD("nuSensorService starting...");

        SensorDevice& dev(SensorDevice::getInstance());   

        if (dev.initCheck() == NO_ERROR) {

            sensor_t const* list;

            ssize_t count = dev.getSensorList(&list);

            if (count > 0) {

                     ssize_t orientationIndex = -1;

               bool hasGyro = false;

               uint32_t virtualSensorsNeeds =

                       (1<<SENSOR_TYPE_GRAVITY) |

                        (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |

                       (1<<SENSOR_TYPE_ROTATION_VECTOR);

                mLastEventSeen.setCapacity(count);

               for (ssize_t i=0 ; i<count ; i++) {

                    registerSensor( new HardwareSensor(list[i]) );

                    switch (list[i].type) {

                       case SENSOR_TYPE_ORIENTATION:

                            orientationIndex = i;

                           break;

                        case SENSOR_TYPE_GYROSCOPE:

                            hasGyro = true;

                            break;

                    }

                }

               // build the sensor list returned to users

                mUserSensorList = mSensorList;

         if (hasGyro && (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {

    if (orientationIndex >= 0) {                 

      mUserSensorList.removeItemsAt(orientationIndex);

                 }

               }

               run("SensorService",PRIORITY_URGENT_DISPLAY);

               mInitCheck = NO_ERROR;

            }

        }

    }

     

    首先调用SensorDevice& dev(SensorDevice::getInstance());得到一个dev对象,调用dev的方法getSensorList(&list);获取sensor所有对象给list。然后调用registerSensor函数将所有sensor对象加入到sensor容器中,如下:

    for (ssize_t i=0 ; i<count ; i++) {

    registerSensor( new HardwareSensor(list[i]) );

    看看registerSensor的具体内容:

    void SensorService::registerSensor(SensorInterface* s)

    {

        sensors_event_t event;

        memset(&event, 0, sizeof(event));

                const Sensor sensor(s->getSensor());

        // add to the sensor list (returned to clients)

            mSensorList.add(sensor);

        // add to our handle->SensorInterface mapping

            mSensorMap.add(sensor.getHandle(), s);

            // create an entry in the mLastEventSeen array

            mLastEventSeen.add(sensor.getHandle(), event);

        }

    可以看到是将所有sensor对象获取逐一添加到容器中。

    这里面registerSesnor函数传入的参数不是直接传的sensor对象,

    而是传的Sensorinterface,然后函数内部再通过Sensorinterface的getsensor对象获取sensor。一下是整个sensors获取的架构图:

     

    我对上面sensors的获取架构的理解:

    其实sensorService从hal层获取sensors还是通过Sensordevice,但是中间经过一个SensorInterface,这个其实就是对Sensor的一个处理,参看SensorInterface.cpp的源码中Hardware类就可以知道,

    其实Hardware中只是对所有的sensor对象做了一个简单处理,比如获取handler,name等,然后将SensorInterface和Sensor分别都存入两个容器中,而且两个容器中的sensor和sensorInterface其实是一一对应上的。构建SensorInterface,主要是便于后面对Sensor的各种简单的处理,通过调用SensorInterface的一些统一封装好的函数。便于对sensor的统一处理,比如说在registerSensor中通过gethandler获取到handler,这就是便于日后handler与sensor的匹配。

     

    1. 数据event的处理

    SensorService类继承Thread类,其中在onFirestRef函数中最后run一个线程,这个线程专门是用来管理从hal层获取sensor_event_t的。在threadLoop()函数中:

    bool SensorService::threadLoop()

    {

        const size_t numEventMax = 16 * (1 + mVirtualSensorList.size());

        sensors_event_t buffer[numEventMax];

        sensors_event_t scratch[numEventMax];

        SensorDevice& device(SensorDevice::getInstance());

        const size_t vcount = mVirtualSensorList.size();

        ssize_t count;

        do {

            count = device.poll(buffer, numEventMax);

            if (count<0) {

                LOGE("sensor poll failed (%s)", strerror(-count));

                break;

            }

            recordLastValue(buffer, count);

           // handle virtual sensors

            if (count && vcount) {

                sensors_event_t const * const event = buffer;

                const DefaultKeyedVector<int, SensorInterface*> virtualSensors(

                       getActiveVirtualSensors());

               const size_t activeVirtualSensorCount = virtualSensors.size();

                if (activeVirtualSensorCount) {

                    size_t k = 0;

     SensorFusion& fusion(SensorFusion::getInstance());

                    if (fusion.isEnabled()) {

                        for (size_t i=0 ; i<size_t(count) ; i++) {

                           fusion.process(event[i]);

                       }

                   }

              for (size_t i=0 ; i<size_t(count) ; i++) {

                    for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {

                           sensors_event_t out;

               if (virtualSensors.valueAt(j)->process(&out, event[i])) {

                         buffer[count + k] = out;

                         k++;

               }               }

                  }

               if (k) {

                       // record the last synthesized values

                        recordLastValue(&buffer[count], k);

                       count += k;

                       // sort the buffer by time-stamps

                       sortEventBuffer(buffer, count);

                    }

               }

           }

           // send our events to clients...

    const SortedVector< wp<SensorEventConnection> > activeConnections(

                    getActiveConnections());

            size_t numConnections = activeConnections.size();

            for (size_t i=0 ; i<numConnections ; i++) {

                sp<SensorEventConnection> connection(

                        activeConnections[i].promote());

                if (connection != 0) {

                   connection->sendEvents(buffer, count, scratch);

               }

           }

        } while (count >= 0 || Thread::exitPending());

        LOGW("Exiting SensorService::threadLoop!");

        return false;

    }

    SensorDevice& device(SensorDevice::getInstance());同样实例化一个SensorDevice device,然后调用device的poll方法如下,

    count = device.poll(buffer, numEventMax);来获取从hal的event,将event放入临时buffer中。中间通过fusion类的一些处理函数处理,通过对fusion类的源码分析,它主要做的是对从hal层传递过来的数据做些过滤和检查处理,然后调用  sortEventBuffer(buffer, count);将所有有效sensor_event_t按time-stamps排序好准备发给client。那么这个是如何发送给client,当然就是前面说的SensorEventConnection模块。看看代码:

       // send our events to clients...

      const SortedVector< wp<SensorEventConnection> > activeConnections(getActiveConnections());

    size_t numConnections = activeConnections.size();

    for (size_t i=0 ; i<numConnections ; i++) {

    sp<SensorEventConnection> connection(

    activeConnections[i].promote());

          if (connection != 0) {

              connection->sendEvents(buffer, count, scratch);

          }

        }

    可以看到首先是获取到所有与sensorservice有效连接的client对应的ensorEventConnection,然后通过调用sendEvents将所有buffer中的events发给client。架构图如下:

     

    整个data相关event传递的架构是很完美也很清晰的我感觉。

    整个过程就好像是一个寄邮件的过程,而sensorservice就相当于中间的快递公司,而sensordevice和sensorEventConnetcion就好比是收邮件和派送邮件的两个快递员,快递公司sensorService不管发送两个快递员sensordevice和sensorEventConnetcion具体收和送的具体实现细节,只是发个命令让他们接和送。

    这样的架构很清晰,分工很明确,这样也很好的屏蔽封装了sensorservice和client之间通信传递数据的具体细节,这样安全性和维护性更好,功能模块之间独立性比较好,不互相影响。

     

    可以看看sensorEventConnection的源码:

    class SensorEventConnection : public BnSensorEventConnection {

      virtual ~SensorEventConnection();

      virtual void onFirstRef();

      virtual sp<SensorChannel> getSensorChannel() const;

       virtual status_t enableDisable(int handle, bool enabled);

       virtual status_t setEventRate(int handle, nsecs_t ns);

       sp<SensorService> const mService;

      sp<SensorChannel> const mChannel;

      mutable Mutex mConnectionLock;

         // protected by SensorService::mLock

          SortedVector<int> mSensorInfo;

      public:

       SensorEventConnection(const sp<SensorService>& service);

        status_t sendEvents(sensors_event_t const* buffer, size_t count,

                  sensors_event_t* scratch = NULL);

          bool hasSensor(int32_t handle) const;

          bool hasAnySensor() const;

         bool addSensor(int32_t handle);

         bool removeSensor(int32_t handle);

       };

    SensorEvenConnection内部其实主要是定义有与之对应的SensorChanel和SensorService,而sensorChanel则是sensorEventConnection和client之间的沟通桥梁,sensorservice先将event传给sensorEventConnection,再由sensorEventConnection通过SensorChanel给client,具体可以看看sendEvents方法源码,其中有这么一句:

    ssize_t size =mChannel->write(scratch,count*sizeof(sensors_event_t));

    可以看到原来SensorChannel是调用它的write将event传给client的。通过查看sensorchannel的源码,我发现sensorchannel是通过管道将event给client。

     

    1. sensor的控制

    从sensorEventConnection的enabledisable()方法可以看到它其实是调用sensorservice的enable和disable函数,而sensorservice函数则是调用sensor的active等sensor的开关函数。

     

    1. 类sensorRecord

    先看看类sensorrecord的定义:

    class SensorRecord {

    SortedVector< wp<SensorEventConnection> > mConnections;

    public:

    SensorRecord(const sp<SensorEventConnection>& connection);

    bool addConnection(const sp<SensorEventConnection>& connection);

    bool removeConnection(const wp<SensorEventConnection>& connection);

    size_t getNumConnections() const { return mConnections.size(); }

    };

    从它的定义中可以看出来它主要负责的是sensorService对SensorEveentConnection容器list记录维护与控制,即对connections的增删等。

    Sensorservice将这个功能块也独立出来,以一个独立的累得方式来处理所有connection的list记录。这是一种很好的方式。将所有关于connections的操作集中起来,将方法的一种归类。

     

    6.关于Virtual sensor

    在SebsorService中,你会看到几个虚拟sensor,GravitySensor,LinearAccelerationSensor,RotationVectorSensor,所谓虚拟sensor就是不是物理上真实存在的,像accsensor那样硬件实实在在存在的,而是逻辑上有的,就是通过实实在在存在的sensor加上一些逻辑上运算得到的sensor。

    对于它们的处理sensorService其实是视为和其它物理sensor一样处理,不过和其它物理上真实存在的sensor不同的是它的数据获取不是通过硬件从外界获取,而是在现有这些物理传感器的得到的数据上进行一些处理从而得到自己的数据。

    所以在SensorService.cpp同一层目录下,andorid分别为山歌虚拟sensor写了自己的class,让他们都继承sensorInterface类,分别实现自己的process函数,这个函数内部其实就是对物理传感器获取到的数据做的逻辑上的处理,得到自己的数据。这可以看源码就知道。看其中一个的的源码:

    bool LinearAccelerationSensor::process(sensors_event_t* outEvent,

            const sensors_event_t& event)

    {

        bool result = mGravitySensor.process(outEvent, event);

        if (result) {

            if (event.type == SENSOR_TYPE_ACCELEROMETER) {

                mData[0] = event.acceleration.x;

                mData[1] = event.acceleration.y;

                mData[2] = event.acceleration.z;

            }

            outEvent->data[0] = mData[0] - outEvent->data[0];

            outEvent->data[1] = mData[1] - outEvent->data[1];

            outEvent->data[2] = mData[2] - outEvent->data[2];

            outEvent->sensor = '_lin';

            outEvent->type = SENSOR_TYPE_LINEAR_ACCELERATION;

        }

        return result;

    }

    可以看到 LinearAccelerationSensor的data是在mData 减去acc sensor的x,y,z。在sensorservice的threadloop函数中可以看到都调用了process函数处理了数据。

      for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {

                            sensors_event_t out;

        if (virtualSensors.valueAt(j)->process(&out, event[i])) {

                                buffer[count + k] = out;

                                k++;

             }

     }

     

    在sensorservice的onFirstRef函数中,

    利用函数registerVirtualSensor函数分别将三个虚拟sensor添加到sensorservice的 mActiveVirtualSensors和mActiveSensors等容器中,便于后面发给client。

    1. 总体架构总结

    最后从整体上对sensorservice的架构做出总结。

     

     

     

  • 相关阅读:
    asp.net连接数据库,在web.config中配置数据库连接
    在处理向该请求提供服务所需的配置文件时出错。请检查下面的特定错误详细信息并适当地修改配置文件如何解决
    centos7查看CPU的利用率
    阿里云云盘在线扩容
    微信和支付宝付款码条码规则(官方)
    微信和支付宝付款码条码规则
    IPFS与般若文海
    Moira果老星宗七政四余排盘软件下载
    Odoo 电子公章/印章模块
    playtoearn
  • 原文地址:https://www.cnblogs.com/microliang/p/3418165.html
Copyright © 2011-2022 走看看