当前位置: 代码迷 >> Android >> Android Sensor系统剖析(2.3.5)(下)
  详细解决方案

Android Sensor系统剖析(2.3.5)(下)

热度:55   发布时间:2016-05-01 11:36:52.0
Android Sensor系统剖析(2.3.5)(上)

Author:[email protected]

本文希望通过对androidsensor系统的介绍,使大家在了解android sensor系统架构的同时,会对大家阅读和分析其他同类型代码框架有所帮助。

1:概览

首先看下应用层如何获取sensor数据

public class SensorActivity extends Activity, implements SensorEventListener {

     private final SensorManager mSensorManager;

     private final Sensor mAccelerometer;

     public SensorActivity() {

         //获取对应服务

         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);

         //获取指定sensor对象

         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

     }

     protected void onResume() {

         super.onResume();

         //注册listener用于数据回调

         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);

     }

     protected void onPause() {

         super.onPause();

         mSensorManager.unregisterListener(this);

     }

     public void onAccuracyChanged(Sensor sensor, int accuracy) {

     }

     public void onSensorChanged(SensorEvent event) {

     }

 }

从代码上看,应用首先要使用sensor service名来获取SensorManager对象实例,然后调用其成员函数registerListener并传入listener来得到回调数据。

Sensor service在后台和driver交互获取数据,各个应用连上service获取想要的sensor数据,从如上代码看,没有任何和service交互的代码,这一切都被封装到SensorManager里了。

2:Sensor service

Android轻量级的系统服务,一般都会运行于systemserver内,sensor service够轻量,当然不能例外。

System server起来时,会创建sensorserivice:

//frameworks/base/cmds/system_server/library/system_init.cpp

extern "C" status_t system_init()

{

    LOGI("Entered system_init()");

 

    sp<ProcessState> proc(ProcessState::self());

   

    sp<IServiceManager> sm = defaultServiceManager();

    LOGI("ServiceManager: %p\n", sm.get());

   

    sp<GrimReaper> grim = new GrimReaper();

    sm->asBinder()->linkToDeath(grim, grim.get(), 0);

   

    char propBuf[PROPERTY_VALUE_MAX];

    property_get("system_init.startsurfaceflinger", propBuf, "1");

    if (strcmp(propBuf, "1") == 0) {

        // Start the SurfaceFlinger

        SurfaceFlinger::instantiate();

    }

    // Start the sensor service

    SensorService::instantiate();

…..

}

通过调用SensorService的静态成员函数instantiate()来初始化并创建sensor service,在详细介绍这个函数的内部行为之前,先来看下SensorService类的声明。

//frameworks/base/services/sensorservice/Sensorservice.h

class SensorService :

        public BinderService<SensorService>,

        public BnSensorServer,

        protected Thread

{

   friend class BinderService<SensorService>;

   static const nsecs_t MINIMUM_EVENTS_PERIOD =   1000000; // 1000 Hz

   SensorService();

   virtual ~SensorService();

   virtual void onFirstRef();

   // Thread interface

   virtual bool threadLoop();

   // ISensorServer interface

    virtual Vector<Sensor> getSensorList();

    virtual sp<ISensorEventConnection> createSensorEventConnection();

    virtual status_t dump(int fd, const Vector<String16>& args);

    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);

    };

    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(); }

    };

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

    DefaultKeyedVector<int, SensorInterface*> getActiveVirtualSensors() const;

    String8 getSensorName(int handle) const;

    void recordLastValue(sensors_event_t const * buffer, size_t count);

    static void sortEventBuffer(sensors_event_t* buffer, size_t count);

    void registerSensor(SensorInterface* sensor);

    void registerVirtualSensor(SensorInterface* sensor);

    // constants

    Vector<Sensor> mSensorList;

    DefaultKeyedVector<int, SensorInterface*> mSensorMap;

    Vector<SensorInterface *> mVirtualSensorList;

    Permission mDump;

    status_t mInitCheck;

    // protected by mLock

    mutable Mutex mLock;

    DefaultKeyedVector<int, SensorRecord*> mActiveSensors;

    DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;

    SortedVector< wp<SensorEventConnection> > mActiveConnections;

    // The size of this vector is constant, only the items are mutable

    KeyedVector<int32_t, sensors_event_t> mLastEventSeen;

public:

    static char const* getServiceName() { return "sensorservice"; }

    void cleanupConnection(SensorEventConnection* connection);

    status_t enable(const sp<SensorEventConnection>& connection, int handle);

    status_t disable(const sp<SensorEventConnection>& connection, int handle);

    status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns);

};

 

这个类里面声明了很多函数和变量,我们如何区分哪些是框架性接口函数,哪些是功能辅助性的呢?很简单,看父类就知道了。

  class SensorService :

        public BinderService<SensorService>,

        public BnSensorServer,

        protected Thread

 

SensorService多重继承自如上三个类,下面简单介绍下:

BinderService<SensorService>

模板类,主要功能是提供一些静态函数创建service对象实例,并加到service manager,主要函数有instantiate()等。

Thread

线程辅助类,调用run创建并启动线程,然后在线程主函数内会回调threadloop函数,所以我们在使用这个它时,最简单得做法是派生自它,然后重写threadloop即可。

BnSensorServer

这个类派生自ISensorServerISensorServer则声明了sensor serverclient之间RPC通信接口,具体如下:

class ISensorServer : public IInterface

{

public:

    DECLARE_META_INTERFACE(SensorServer);

 

    virtual Vector<Sensor> getSensorList() = 0;

    virtual sp<ISensorEventConnection> createSensorEventConnection() = 0;

};

了解了三个父类的功能后,可以推出SensorService的核心功能如下:

1:SensorService:: instantiate()初始化sensorservice并创建线程

2:threadloop在线程启动后,从驱动获取sensor原始数据并通过RPC机制让sensor client获取。

3:BnSensorServer的成员函数负责让sensor client获取sensor信息和创建connection

接下去我们就从这几个函数着手进行详细分析!

先看SensorService:: instantiate():

 //frameworks/base/include/binder/BinderService.h

template<typename SERVICE>

class BinderService

{

public:

    static status_t publish() {

        sp<IServiceManager> sm(defaultServiceManager());

        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());

    }

    static void publishAndJoinThreadPool() {

        sp<ProcessState> proc(ProcessState::self());

        sp<IServiceManager> sm(defaultServiceManager());

        sm->addService(String16(SERVICE::getServiceName()), new SERVICE());

        ProcessState::self()->startThreadPool();

        IPCThreadState::self()->joinThreadPool();

    }

   static void instantiate() { publish(); }

    static status_t shutdown() {

        return NO_ERROR;

    }

BinderService是模板类,通过代码可以看到,instantiate直接调用了publish函数,publish函数先获取service manager,然后new了一个SensorService对象,接着调用addService并将sensor service name和新创建sensorservice对象传入。

可能有人会问,调用addService的目的是什么?我们不是通过newSensorService创建sensor后台服务了吗?是的,服务的确已经启动了,但是服务的目的是什么?是供他人使用,你要让他人使用你,前提是得让别人找到你,所以我觉得addService的主要功能有两点:

1:将sensor service信息传入binderkernel,然后binder kernel生成对应于sensor service的handle,并维护之。

2:service manager得到并维护对应servicename和handle供其他应用获取。

举例来说,这就好比你建立了一台设备,你要让别人连接你这台设备,你需要让你的设备与宽带服务器建立拨号连接,然后宽带服务器给你分配ip,别人拿到ip,就能与你建立通信链接了,但是ip太难记了,所以就有了域名

把例子中描述的和android机制对应下,设备对应sensor service,binder kernel对应宽带服务器,ip对应handle,service name对应域名,那service manager对应什么?当然是域名解析服务了。

所以现在就很明了了,客户端要与对应的服务建立通信,只需要通过服务名拿到对应的handle,然后用这个handle组建对应的proxy binder对象即可。

那从代码中呢,如何区分代码是用于创建本地服务还是创建远程代理呢?很简单,看类命名就可以了,以Sensor service举例,本地服务类为BnSensorServer,代理类则为BpSensorServer,开到类的开头没,Bn以为native binderBp则是proxy binder

Android RPC通信那块就简单介绍到这里,继续往下看。

服务创建时,new了一个SensorService对象实例,那接下去代码肯定走SensorService的构造函数:

//frameworks/base/services/sensorservice/SensorService.cpp

 SensorService::SensorService()

    : Thread(false),

      mDump("android.permission.DUMP"),

      mInitCheck(NO_INIT){

}

看到了,构造函数相当于啥也没做,既然sensorservice对象传给了ServiceManager::AddService,我们来看看AddService的函数声明

virtual status_t addService( const String16& name, const sp<IBinder>& service);

第二个参数是sp强引用对象,而非单纯的sensor service指针,在第一次构建sp强引用对象时,会调用onFirstRef():

void SensorService::onFirstRef()

{

    LOGD("nuSensorService starting...");

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

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

        uint32_t virtualSensorsNeeds =

                (1<<SENSOR_TYPE_GRAVITY) |

                (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |

                (1<<SENSOR_TYPE_ROTATION_VECTOR);

        sensor_t const* list;

        int count = dev.getSensorList(&list);

        mLastEventSeen.setCapacity(count);

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

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

            switch (list[i].type) {

                case SENSOR_TYPE_GRAVITY:

                case SENSOR_TYPE_LINEAR_ACCELERATION:

                case SENSOR_TYPE_ROTATION_VECTOR:

                    virtualSensorsNeeds &= ~(1<<list[i].type);

                    break;

            }

        }

 

        if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {

            registerVirtualSensor( new GravitySensor(list, count) );

        }

        if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {

            registerVirtualSensor( new LinearAccelerationSensor(list, count) );

        }

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

            registerVirtualSensor( new RotationVectorSensor(list, count) );

        }

 

        run("SensorService", PRIORITY_URGENT_DISPLAY);

        mInitCheck = NO_ERROR;

    }

}

这个函数先通过SensorDevice:: getInstance获取SensorDevice对象实例,所以我们接着看SensorDevice的构造函数:

SensorDevice::SensorDevice()

    :  mSensorDevice(0),

       mSensorModule(0)

{

    status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,

            (hw_module_t const**)&mSensorModule);

    LOGE_IF(err, "couldn't load %s module (%s)",

            SENSORS_HARDWARE_MODULE_ID, strerror(-err));

    if (mSensorModule) {

        err = sensors_open(&mSensorModule->common, &mSensorDevice);

        LOGE_IF(err, "couldn't open device for module %s (%s)",

                SENSORS_HARDWARE_MODULE_ID, strerror(-err));

        if (mSensorDevice) {

            sensor_t const* list;

            ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);

            mActivationCount.setCapacity(count);

            Info model;

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

                mActivationCount.add(list[i].handle, model);

                //初始将所有sensor设置为未激活状态

                mSensorDevice->activate(mSensorDevice, list[i].handle, 0);

            }

        }

    }

}

通过构造函数可以看出,SensorDevice封装了对SensorHAL层代码的调用,主要包含获取sensor list,poll sensor数据和是否激活指定sensor等,这里就不详细描述。

继续从SensorService::onFirstRef往下走,在得到SensorDevice对象实例后,通过调用dev.getSensorList(&list)获取sensor list,然后调用registersensor将所有sensor加到SensorService的成员变量mSensorList中。

接下去调用run启动线程:

run("SensorService", PRIORITY_URGENT_DISPLAY);

  线程启动后,threadloop会被回调

bool SensorService::threadLoop()

{

    LOGD("nuSensorService thread starting...");

 

    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 {

    //从设备获取已经激活sensor的数据,如果无一sensor被激活,该动作将会被

    //阻塞

        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) {

            const DefaultKeyedVector<int, SensorInterface*> virtualSensors(

                    getActiveVirtualSensors());

            const size_t activeVirtualSensorCount = virtualSensors.size();

            if (activeVirtualSensorCount) {

                size_t k = 0;

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

                    sensors_event_t const * const event = buffer;

                    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);

                }

            }

        }

 

        // 得到已有的client连接

        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) {

                //sensor数据发往client

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

            }

        }

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

 

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

    return false;

}

Threadloop主要通过调用sensor HAL函数获取已激活sensor的数据,然后将获取到的数据发往已经建立的connection。

Connection是如何建立的?我们之前描述的三个父类的功能中已经有过描述,ISensorServer定义了client和sensor service的RPC通信接口,client端在得到sensor service代理对象后,通过调用createSensorEventConnection与sensorservice建立connection,先看service端的实现代码:

sp<ISensorEventConnection> SensorService::createSensorEventConnection()

{

    sp<SensorEventConnection> result(new SensorEventConnection(this));

    return result;

}

  Service端仅仅创建了SensorEventConnection对象实例,然后将这个对象实例传给client端,这里有两个疑问:

1:将实例对象传给client,那是否SensorEventConnection实例也是个RPC服务?

2:sensor service不是保存了active connections,这里也没做保存操作,那在哪里保存?唯一的线索就是构造SensorEventConnection传入的this指针了。

 

先看第一个疑问,SensorEventConnection是不是RPC服务,看其构造函数先

class SensorEventConnection : public BnSensorEventConnection

看到没?父类是Bn开头的,说明其是native binder,的确是RPC服务,由于这个服务是私底下咱哥俩偷摸用的,所以就无需加入servicemanager了。

那这个connection是怎么加入sensorservice的action connections的,由于是RPC服务,所以这块动作应该是由client驱动的。

先看ISensorEventConnection

class ISensorEventConnection : public IInterface

{

public:

    DECLARE_META_INTERFACE(SensorEventConnection);

    virtual sp<SensorChannel> getSensorChannel() const = 0;

    virtual status_t enableDisable(int handle, bool enabled) = 0;

    virtual status_t setEventRate(int handle, nsecs_t ns) = 0;

};

共三个接口函数,setEventRate这个应该是设置sensor 数据上报频率的,跟active connection应该没啥关系;getSensorChannel是干嘛用的?等会介绍,但是看名字,也不像!剩下就是enableDisable这个函数了

status_t SensorService::SensorEventConnection::enableDisable(

        int handle, bool enabled)

{

    status_t err;

    if (enabled) {

        err = mService->enable(this, handle);

    } else {

        err = mService->disable(this, handle);

    }

    return err;

}

如果是enable,调用sensor service的enable函数

status_t SensorService::enable(const sp<SensorEventConnection>& connection,

        int handle)

{

    if (mInitCheck != NO_ERROR)

        return mInitCheck;

 

    Mutex::Autolock _l(mLock);

SensorInterface* sensor = mSensorMap.valueFor(handle);

//将对应sensor激活

    status_t err = sensor ? sensor->activate(connection.get(), true) : status_t(BAD_VALUE);

    if (err == NO_ERROR) {

        SensorRecord* rec = mActiveSensors.valueFor(handle);

        if (rec == 0) {

            rec = new SensorRecord(connection);

            mActiveSensors.add(handle, rec);

            if (sensor->isVirtual()) {

                mActiveVirtualSensors.add(handle, sensor);

            }

        } else {

            if (rec->addConnection(connection)) {

                // this sensor is already activated, but we are adding a

                // connection that uses it. Immediately send down the last

                // known value of the requested sensor.

                sensors_event_t scratch;

                sensors_event_t& event(mLastEventSeen.editValueFor(handle));

                if (event.version == sizeof(sensors_event_t)) {

                    connection->sendEvents(&event, 1);

                }

            }

        }

        if (err == NO_ERROR) {

            // connection now active

            //connection加入active connection

            if (connection->addSensor(handle)) {

                // the sensor was added (which means it wasn't already there)

                // so, see if this connection becomes active

                if (mActiveConnections.indexOf(connection) < 0) {

                    mActiveConnections.add(connection);

                }

            }

        }

    }

    return err;

}

在这个函数中,激活对应sensor,然后将当前connection加入active connection

 

到这里,知道了如何创建connection和activeconnection后,还有一个问题就是,sensor数据发送的?大家可能会说,不是通过调用SensorEventConnection ::sendEvents来实现的吗?但是回过头看下ISensorEventConnection的三个函数声明,没有sendEvents这个函数,也就说sendEvents只是一个供sensorservice端用的public函数而已。

status_t SensorService::SensorEventConnection::sendEvents(

        sensors_event_t const* buffer, size_t numEvents,

        sensors_event_t* scratch)

{

    //。。。。

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

    if (size == -EAGAIN) {

        // the destination doesn't accept events anymore, it's probably

        // full. For now, we just drop the events on the floor.

        LOGW("dropping %d events on the floor", count);

        return size;

    }

 

    LOGE_IF(size<0, "dropping %d events on the floor (%s)",

            count, strerror(-size));

 

    return size < 0 ? status_t(size) : status_t(NO_ERROR);

}

SensorEvent调用SensorChannel的wirte函数发送sensor数据,mChannel是在SensorEventConnection函数中初始化的。

ssize_t SensorChannel::write(void const* vaddr, size_t size)

{

    ssize_t len = ::write(mSendFd, vaddr, size);

    if (len < 0)

        return -errno;

    return len;

}

从这个函数中看到,sensorservice和client端的sensor数据不是通过RPC机制传递的,看下SensorChannel的构造函数

SensorChannel::SensorChannel()

    : mSendFd(-1), mReceiveFd(-1)

{

    int fds[2];

    if (pipe(fds) == 0) {

        mReceiveFd = fds[0];

        mSendFd = fds[1];

        fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);

        fcntl(mSendFd, F_SETFL, O_NONBLOCK);

    }

}

明白了,进程间数据共享是通过管道来实现的,现在知道ISensorEventConnection:: getSensorChannel的作用了,用于传递Receive FD给client的

status_t SensorChannel::writeToParcel(Parcel* reply) const

{

    if (mReceiveFd < 0)

        return -EINVAL;

 

    status_t result = reply->writeDupFileDescriptor(mReceiveFd);

    close(mReceiveFd);

    mReceiveFd = -1;

    return result;

}

 

Client端拿到received FD后,就可以读取sensor数据啦。至此,服务端已经说完了,接下去是客户端部分的讲解。


本文乃原创,转载请注明出处,谢谢。

  相关解决方案