Android Sensor系統剖析(2.3.5)(上)

本文希望通過對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:

這個類派生自ISensorServer,ISensorServer則聲明瞭sensor server和client之間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 binder,Bp則是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的  www.aiwalls.com

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數據啦。至此,服務端已經說完瞭,接下去是客戶端部分的講解。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *