您的位置:首页 > 移动开发 > Android开发

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

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


1:概览

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

[java] view
plain copy

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:

[java] view
plain copy

//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类的声明。

[java] view
plain copy

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

};

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

[java] view
plain copy

class SensorService :

public BinderService<SensorService>,

public BnSensorServer,

protected Thread

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

[java] view
plain copy

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():

[java] view
plain copy

//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的构造函数:

[java] view
plain copy

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

SensorService::SensorService()

: Thread(false),

mDump("android.permission.DUMP"),

mInitCheck(NO_INIT){

}

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

[java] view
plain copy

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

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

[java] view
plain copy

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的构造函数:

[java] view
plain copy

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启动线程:

[java] view
plain copy

run("SensorService", PRIORITY_URGENT_DISPLAY);

线程启动后,threadloop会被回调:

[java] view
plain copy

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端的实现代码:

[java] view
plain copy

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服务,看其构造函数先

[java] view
plain copy

class SensorEventConnection : public BnSensorEventConnection

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

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

先看ISensorEventConnection

[java] view
plain copy

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这个函数了

[java] view
plain copy

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函数

[java] view
plain copy

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函数而已。

[java] view
plain copy

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函数中初始化的。

[java] view
plain copy

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的构造函数

[java] view
plain copy

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的

[java] view
plain copy

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数据啦。至此,服务端已经说完了,接下去是客户端部分的讲解。

本文乃原创,转载请注明出处,谢谢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: