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

Android Sensor流程

2016-03-22 22:55 597 查看

一.首先看一下sensor的整体架构:

 

 


 

第一层是应用层:代表上层使用frameworks的接口注册或使用一个sensor:

Sensor sensor = sensorManager.getDefaultSensor(sensortype);
sensorManager.registerListener(mListener, sensor, SensorManager.SENSOR_DELAY_FASTEST);


第二层Frameworks层: 包含SensorService, 接收HAl层传上来的 sensor event 数据,并让应用层做出相应的动作,如陀螺仪转动,横竖屏切换等

第三层HAL层: kernel层的硬件驱动等, 有SensorDevice 的poll函数读取数据

  

二.分析SensorServier 的启动流程:

在android系统中每一个功能点都是由Service来调度, 如熟知的ActivityManagerService, PackageManagerService等等, 这些我会在以后的博客中逐个分析

先看调用时序图

 


 

SystemServer中唯一的一个JNI调用启动SensorService

SystemServer.java :

/**
* Start the sensor service.
*/
private static native void startSensorService();


 com_android_server_SystemServer.cpp:

void* sensorInit(void *arg) {
ALOGI("System server: starting sensor init.\n");
// Start the sensor service
SensorService::instantiate();
ALOGI("System server: sensor init done.\n");
return NULL;
}


使用Binder机制将SensorService启动。

 SensorService的初始化:

Service的初始在SensorService::onFirstRef函数中

SensorDevice& dev(SensorDevice::getInstance());  // 实例化SensorDevice
if (dev.initCheck() == NO_ERROR) {
sensor_t const* list;
ssize_t count = dev.getSensorList(&list);   // 获取sensor list
if (count > 0) {
ssize_t orientationIndex = -1;
bool hasGyro = false, hasAccel = false, hasMag = false;
... ...
mLastEventSeen.setCapacity(count);
for (ssize_t i=0 ; i<count ; i++) {
registerSensor( new HardwareSensor(list[i]) );  // 向HAL层注册触感器
... ...
mNextSensorRegIndex = 0;
for (int i = 0; i < SENSOR_REGISTRATIONS_BUF_SIZE; ++i) {
mLastNSensorRegistrations.push();
}

mInitCheck = NO_ERROR;
mAckReceiver = new SensorEventAckReceiver(this);
mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
run("SensorService", PRIORITY_URGENT_DISPLAY);
}
}

SensorService的初始化主要有:

1. 创建SensorDevice实例,获取Sensor列表

2. 调用SensorDevice.getSensorList(),获取Sensor模块所有传感器列表并为为每个传感器注册监听器

SensorDevice的初始化:
SensorDevice::SensorDevice()
:  mSensorDevice(0),
mSensorModule(0)
{
status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
(hw_module_t const**)&mSensorModule);
if (mSensorModule) {
err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
... ...
if (mSensorDevice) {
if (mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_1 ||
mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_2) {
}

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);
mSensorDevice->activate( reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),list[i].handle, 0);
... ...
}

SensorService 及SensorDevice的启动主要实现一下几件事:

1. 调用HAL层的hw_get_modele()方法,加载Sensor模块so文件
2. 调用sensor.h的sensors_open方法打开设备
3. 调用sensors_poll_device_t->activate()对Sensor模块使能

启动一个线程,获取HAL层的数据:
SensorService::threadLoop():

bool SensorService::threadLoop()
{
SensorDevice& device(SensorDevice::getInstance());
const size_t vcount = mVirtualSensorList.size();
const int halVersion = device.getHalDeviceVersion();
do {
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);  // 从HAL层读取数据
// Reset sensors_event_t.flags to zero for all events in the buffer.
for (int i = 0; i < count; i++) {
mSensorEventBuffer[i].flags = 0;
}
SortedVector< sp<SensorEventConnection> > activeConnections;
populateActiveConnections(&activeConnections);
... ...
// Send our events to clients. Check the state of wake lock for each client and release the
// lock if none of the clients need it.
bool needsWakeLock = false;
size_t numConnections = activeConnections.size();
for (size_t i=0 ; i < numConnections; ++i) {
if (activeConnections[i] != 0) {
activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
mMapFlushEventsToConnections);  // 向客户端发数据
needsWakeLock |= activeConnections[i]->needsWakeLock();
// If the connection has one-shot sensors, it may be cleaned up after first trigger.
// Early check for one-shot sensors.
if (activeConnections[i]->hasOneShotSensors()) {
cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer,
count);
}
}
}
... ...
abort();
return false;
}


进入while循环, 不停的从底层poll数据, 并sendEvent到上层
  

三. 客户端与服务端之间Sensor数据传递

先看服务器与客户端状态图:



1. 上图涉及两个线程:

橘黄色服务端: SensorService::threadLoop 它通过SensorDevice::poll 不停的从HAL获取数据

蓝色客户端:android_hardware_SensorManager::Receiver 从EventQueue中读数据

 

2. 传递数据是的一个关键宏:sensors_event_t

int32_t version;      // sensor 的version
int32_t sensor;      //sensor 标识每个sensor都唯一
int32_t type;        // sensor 的类型一个sensor可有多个类型 如: 陀螺仪有校准后与校准前类型
int32_t reserved0;
int64_t timestamp;  // sensor产生时间戳
union {
union {
float           data[16];
sensors_vec_t   acceleration;    //加速sensor
sensors_vec_t   magnetic;       // 磁场感应sensor
sensors_vec_t   orientation;     // 横竖屏sensor
sensors_vec_t   gyro;           // 陀螺仪sensor
float           temperature;    //温度sensor
float           distance;        // 距离sensor
float           light;            // 光感sensor
float           pressure;        //压力sensor
float           relative_humidity; // 相对湿度sensor
uncalibrated_event_t uncalibrated_gyro;      // 无定向的陀螺仪sensor
uncalibrated_event_t uncalibrated_magnetic;  // 无定向的磁场sensor

heart_rate_event_t heart_rate;  // 心率检测sensor
meta_data_event_t meta_data;
};
union {
uint64_t        data[8];
uint64_t        step_counter; // 步数检测sensor
} u64;
};
uint32_t flags;
uint32_t reserved1[3];
} sensors_event_t;

4. 使用管道传递数据的原因是由于sensor数据量较大, Binder不能胜任此任务, 所以需要BitTube管道来传递这些数据

5. 数据时序图:



根据图示可以看出客户端与服务端通过Binder建立链接, 通过BitTube管道进行数据传递。

BitTube init函数:

void BitTube::init(size_t rcvbuf, size_t sndbuf) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
// sine we don't use the "return channel", we keep it small...
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
fcntl(sockets[0], F_SETFL, O_NONBLOCK);
fcntl(sockets[1], F_SETFL, O_NONBLOCK);
mReceiveFd = sockets[0];   //socket[0]接受数据
mSendFd = sockets[1];     // socket[1]发送数据
} else {
mReceiveFd = -errno;
ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
}
}


    1. 使用socket[0] 来接收数据

2. 使用socket[1] 来发送数据

3.通过pipe(fds)创建管道,通过fcntl来设置操作管道的方式,设置通道两端的操作方式为O_NONBLOCK ,非阻塞IO方式,read或write调用返回-1和EAGAIN错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: