Sensor系列之Sensor HAL层数据获取,基于Qualcomm平台
前面我们分析了Android Sensor HAL层源码分析(基于Qualcomm平台),该篇博文主要讲解了Sensor HAL的初始化,以及hal层是怎样获取所有sensor列表的。今天我们来进一步了解下sensor hal层的数据获取流程。
我们知道Native层SensorService启动后,会进入我们的treadLoop方法:
bool SensorService::threadLoop()
{
ALOGD("nuSensorService thread starting...");
// each virtual sensor could generate an event per "real" event, that's why we need
// to size numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT.
// in practice, this is too aggressive, but guaranteed to be enough.
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());
SensorDevice& device(SensorDevice::getInstance());
const size_t vcount = mVirtualSensorList.size();
const int halVersion = device.getHalDeviceVersion();
do {
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
if (count < 0) {
ALOGE("sensor poll failed (%s)", strerror(-count));
break;
}
// Reset sensors_event_t.flags to zero for all events in the buffer.
for (int i = 0; i < count; i++) {
mSensorEventBuffer[i].flags = 0;
}
// Make a copy of the connection vector as some connections may be removed during the
// course of this loop (especially when one-shot sensor events are present in the
// sensor_event buffer). Promote all connections to StrongPointers before the lock is
// acquired. If the destructor of the sp gets called when the lock is acquired, it may
// result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for
// cleanup. So copy all the strongPointers to a vector before the lock is acquired.
SortedVector< sp<SensorEventConnection> > activeConnections;
populateActiveConnections(&activeConnections);
Mutex::Autolock _l(mLock);
// Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The
// rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,
// sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should
// not be interleaved with decrementing SensorEventConnection::mWakeLockRefCount and
// releasing the wakelock.
bool bufferHasWakeUpEvent = false;
for (int i = 0; i < count; i++) {
if (isWakeUpSensorEvent(mSensorEventBuffer[i])) {
bufferHasWakeUpEvent = true;
break;
}
}
if (bufferHasWakeUpEvent && !mWakeLockAcquired) {
setWakeLockAcquiredLocked(true);
}
recordLastValueLocked(mSensorEventBuffer, count);
// handle virtual sensors
if (count && vcount) {
sensors_event_t const * const event = mSensorEventBuffer;
const size_t activeVirtualSensorCount = mActiveVirtualSensors.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) && k<minBufferSize ; i++) {
for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
if (count + k >= minBufferSize) {
ALOGE("buffer too small to hold all events: "
"count=%zd, k=%zu, size=%zu",
count, k, minBufferSize);
break;
}
sensors_event_t out;
SensorInterface* si = mActiveVirtualSensors.valueAt(j);
if (si->process(&out, event[i])) {
mSensorEventBuffer[count + k] = out;
k++;
}
}
}
if (k) {
// record the last synthesized values
recordLastValueLocked(&mSensorEventBuffer[count], k);
count += k;
// sort the buffer by time-stamps
sortEventBuffer(mSensorEventBuffer, count);
}
}
}
// handle backward compatibility for RotationVector sensor
if (halVersion < SENSORS_DEVICE_API_VERSION_1_0) {
for (int i = 0; i < count; i++) {
if (mSensorEventBuffer[i].type == SENSOR_TYPE_ROTATION_VECTOR) {
// All the 4 components of the quaternion should be available
// No heading accuracy. Set it to -1
mSensorEventBuffer[i].data[4] = -1;
}
}
}
// Map flush_complete_events in the buffer to SensorEventConnections which called
// flush on the hardware sensor. mapFlushEventsToConnections[i] will be the
// SensorEventConnection mapped to the corresponding flush_complete_event in
// mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).
for (int i = 0; i < count; ++i) {
mMapFlushEventsToConnections[i] = NULL;
if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {
const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;
SensorRecord* rec = mActiveSensors.valueFor(sensor_handle);
if (rec != NULL) {
mMapFlushEventsToConnections[i] = rec->getFirstPendingFlushConnection();
rec->removeFirstPendingFlushConnection();
}
}
}
// 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);
}
}
}
if (mWakeLockAcquired && !needsWakeLock) {
setWakeLockAcquiredLocked(false);
}
} while (!Thread::exitPending());
ALOGW("Exiting SensorService::threadLoop => aborting...");
abort();
return false;
}
其中在do…while循环体中通过device->poll方法进行去hal层读取sensor上报的数据。device的类型为sensors_poll_device_1_t结构体,在sensors_open方法中我们已经将其中的方法进行了初始化:
static int sensors_open(const struct hw_module_t* module, const char* id,
struct hw_device_t** device)
{
UNREFERENCED_PARAMETER(id);
int ret = -EINVAL;
SensorsContext *dev = SensorsContext::getInstance();
memset(&dev->device, 0, sizeof(sensors_poll_device_1_t));
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_3;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = sensors_close;
dev->device.activate = sensors_activate;
dev->device.setDelay = sensors_set_delay;
dev->device.poll = sensors_poll;
dev->device.batch = sensors_batch;
dev->device.flush = sensors_flush;
*device = &dev->device.common;
ret = 0;
return ret;
}
所以device->poll方法最终会调用到hal层的sensors_poll,因此我们跟进sensors_poll方法:
static int sensors_poll(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count)
{
SensorsContext *ctx = (SensorsContext *)dev;
return ctx->poll(data, count);
}
继而调用我们之前介绍过的SensorsContext对象的poll方法,其中数据将会填充到由类型为sensors_event_t* data的数据结构中。这个结构体定义在hal层,其结构体如下:
typedef struct sensors_event_t {
/* must be sizeof(struct sensors_event_t) */
int32_t version; // sensors版本
/* sensor identifier */
int32_t sensor; // sensor id
/* sensor type */
int32_t type; // sensor type
/* reserved */
int32_t reserved0;
/* time is in nanosecond */
int64_t timestamp;
union {
union {
float data[16];
/* acceleration values are in meter per second per second (m/s^2) */
sensors_vec_t acceleration;
/* magnetic vector values are in micro-Tesla (uT) */
sensors_vec_t magnetic;
/* orientation values are in degrees */
sensors_vec_t orientation;
/* gyroscope values are in rad/s */
sensors_vec_t gyro;
/* temperature is in degrees centigrade (Celsius) */
float temperature;
/* distance in centimeters */
float distance;
/* light in SI lux units */
float light;
/* pressure in hectopascal (hPa) */
float pressure;
/* relative humidity in percent */
float relative_humidity;
/* uncalibrated gyroscope values are in rad/s */
uncalibrated_event_t uncalibrated_gyro;
/* uncalibrated magnetometer values are in micro-Teslas */
uncalibrated_event_t uncalibrated_magnetic;
/* heart rate data containing value in bpm and status */
heart_rate_event_t heart_rate;
/* this is a special event. see SENSOR_TYPE_META_DATA above.
* sensors_meta_data_event_t events are all reported with a type of
* SENSOR_TYPE_META_DATA. The handle is ignored and must be zero.
*/
meta_data_event_t meta_data;
};
union {
uint64_t data[8];
/* step-counter */
uint64_t step_counter;
} u64;
};
/* Reserved flags for internal use. Set to zero. */
uint32_t flags;
uint32_t reserved1[3];
} sensors_event_t;
联合体会根据具体的sensor 类型来决定其数据该怎样封装到对应的vec结构体中。
我们继续跟进SensorsContext类的poll方法中去。
int SensorsContext::poll(sensors_event_t* data, int count)
{
int i = 0;
int err;
bool wakeup_event_being_processed = false;
int sensorFlag = -1;
HAL_LOG_DEBUG("%s: count: %d", __FUNCTION__, count );
pthread_mutex_lock(&data_cb->data_mutex);
while(i < count) {
/* check if any responses have been buffered */
if(!Utility::removeFromQueue(&data[i])) {
break;
}
if (data[i].type == SENSOR_TYPE_META_DATA) {
sensorFlag = mSensors[data[i].meta_data.sensor]->getFlags();
}
else {
sensorFlag = mSensors[data[i].sensor]->getFlags();
}
if (sensorFlag & SENSOR_FLAG_WAKE_UP) {
wakeup_event_being_processed = true;
Utility::decrement_wake_events_in_queue_count(data_cb);
}
i++;
}
/* Release wakelock if held */
pthread_mutex_lock(&data_cb->wakelock_mutex);
if (wakeup_event_being_processed == false &&
data_cb->wake_events_in_queue == 0 &&
data_cb->sensors_wakelock_held == true ) {
/*
* We purposely don't call release_sensor_wake_lock() here as we've already
* decremented the wake events in the queue counter.
*/
data_cb->sensors_wakelock_held = false;
release_wake_lock( SENSORS_WAKE_LOCK );
HAL_LOG_DEBUG("%s: released wakelock %s", __FUNCTION__, SENSORS_WAKE_LOCK);
}
pthread_mutex_unlock(&data_cb->wakelock_mutex);
while(i == 0) {
data_cb->is_ind_arrived = false;
/* wait for notify cb - wait indefinitely */
err = Utility::waitForResponse(0, &data_cb->data_mutex,
&data_cb->data_cond,
&data_cb->is_ind_arrived);
if(err == false) {
pthread_mutex_unlock(&data_cb->data_mutex);
return -ETIMEDOUT;
}
/* Data received */
while(i < count && Utility::removeFromQueue(&data[i])) {
if (data[i].type == SENSOR_TYPE_META_DATA) {
sensorFlag = mSensors[data[i].meta_data.sensor]->getFlags();
}
else {
sensorFlag = mSensors[data[i].sensor]->getFlags();
}
if (sensorFlag & SENSOR_FLAG_WAKE_UP) {
Utility::decrement_wake_events_in_queue_count(data_cb);
}
i++;
}
}
/* latency mesaure */
if (Latency::isLatencyMeasureEnabled()) {
struct timespec current_time;
uint64_t curr_timestamp = android::elapsedRealtimeNano();
Latency::latencyMeasure(curr_timestamp, data, i);
}
pthread_mutex_unlock(&data_cb->data_mutex);
HAL_LOG_DEBUG("%s:polldata:%d, sensor:%d, type:%d, x:%f y:%f z:%f",
__FUNCTION__, i,
data[0].sensor, data[0].type,
data[0].acceleration.x,
data[0].acceleration.y,
data[0].acceleration.z);
return i;
}
在while循环中,首先会通过Utility工具类的removeFromQueue方法去队列里尝试取数据,并将数据存储到data位置,如果有数据将会返回true,最后该数据也就达到了上层,反之返回false。
从这里我们也可以看出,sensor的数据是存放在一个队列里面的,所以肯定有另外一个地方往这个队列里存数据,然后我们的app通过SensorService的线程循环去这个队列里取到并返回给app。
bool Utility::removeFromQueue(sensors_event_t* data_ptr)
{
hal_sensor_dataq_t* q_ptr;
bool rv = false;
if (NULL != q_head_ptr) {
/* copy the data from head */
q_ptr = q_head_ptr;
*data_ptr = q_head_ptr->data;
/* update the pointers */
if (q_head_ptr == q_tail_ptr) {
/* queue has only one element */
q_tail_ptr = NULL;
}
q_head_ptr = q_head_ptr->next;
free(q_ptr);
rv = true;
}
return rv;
}
hal_sensor_dataq_t* Utility::q_head_ptr = NULL;
/* sensor event data buffer node */
typedef struct hal_sensor_dataq_t {
sensors_event_t data; /* sensor event data that will report to framework */
struct hal_sensor_dataq_t* next; /* pointer to the next sensor event data */
} hal_sensor_dataq_t;
如果没有数据,poll方法会通过waitForResponse等待indication消息notify返回,继续通过removeFromQueue取队列里的消息,然回返回。
如下的log展示了一个step counter的消息上报过程:
06-04 19:58:57.384 V/qti_sensors_hal: SAMSensor_sensor1_cb: msg_type 2, Sn 37, msg Id 5, txn Id 0
06-04 19:58:57.384 I/qti_sensors_hal: processInd: handle:49
06-04 19:58:57.384 D/qti_sensors_hal: processInd: SNS_SAM_PED_REPORT_IND_V01
06-04 19:58:57.384 D/qti_sensors_hal: processInd: handle 49, count=1
06-04 19:58:57.384 V/qti_sensors_hal: processInd:sensor android.sensor.step_counter
06-04 19:58:57.384 V/qti_sensors_hal: processInd: STEP COUNTER: steps 1, running_total 0 SAM TS: 22393870 HAL TS:679857437028 elapsedRealtimeNano:680554179479
06-04 19:58:57.385 D/qti_sensors_hal: poll:polldata:1, sensor:49, type:19, x:0.000000 y:0.000000 z:-0.000000
我们跟进stepCounter的hal包装层去取看看他是怎样将数据放入队列里的。
最后我们在stepCounter.cpp中,其processInd方法将驱动层上报的数据放入了队列里:
void StepCounter::processInd(sensor1_msg_header_s *msg_hdr, void *msg_ptr)
{
hal_sam_sample_t *sample_list = NULL;
hal_sam_sample_t *curr_sample = NULL;
sensors_event_t la_sample;
uint32_t i = 0;
uint32_t count = 0;
uint64_t steps = 0;
HAL_LOG_INFO("%s: handle:%d", __FUNCTION__, handle);
if (SNS_SAM_PED_REPORT_IND_V01 == msg_hdr->msg_id) {
HAL_LOG_DEBUG("%s: SNS_SAM_PED_REPORT_IND_V01", __FUNCTION__);
if( batching ) {
/* Switch from Async state to batching mode*/
sendBatchReq();
}
sns_sam_ped_report_ind_msg_v01* sam_ind =
(sns_sam_ped_report_ind_msg_v01*)msg_ptr;
sample_list = (hal_sam_sample_t *)malloc(sizeof(hal_sam_sample_t));
if (NULL == sample_list) {
HAL_LOG_ERROR( "%s: Malloc error", __FUNCTION__ );
} else {
count = 1;
sample_list->data[0] = sam_ind->report_data.step_count;
sample_list->data[1] = sam_ind->report_data.step_rate;
sample_list->data[2] = sam_ind->report_data.step_confidence;
sample_list->data[3] = sam_ind->report_data.step_event;
sample_list->data[4] = sam_ind->report_data.step_count_error;
sample_list->accuracy = 0;
sample_list->timestamp = sam_ind->timestamp;
}
}
else if (SNS_SAM_PED_GET_REPORT_RESP_V01 == msg_hdr->msg_id) {
HAL_LOG_DEBUG("%s: SNS_SAM_PED_GET_REPORT_RESP_V01", __FUNCTION__);
sns_sam_ped_get_report_resp_msg_v01 *sam_ind =
(sns_sam_ped_get_report_resp_msg_v01 *)msg_ptr;
if (sam_ind->timestamp_valid && sam_ind->report_data_valid) {
sample_list = (hal_sam_sample_t *)malloc( sizeof(hal_sam_sample_t) );
if (NULL == sample_list) {
HAL_LOG_ERROR( "%s: Malloc error", __FUNCTION__ );
} else {
count = 1;
sample_list->data[0] = sam_ind->report_data.step_count;
sample_list->data[1] = sam_ind->report_data.step_rate;
sample_list->data[2] = sam_ind->report_data.step_confidence;
sample_list->data[3] = 0; /* We don't want to generate extra step detector events */
sample_list->data[4] = sam_ind->report_data.step_count_error;
sample_list->accuracy = 0;
sample_list->timestamp = sam_ind->timestamp;
}
}
else {
HAL_LOG_WARN("%s: Received report with invalid data", __FUNCTION__);
}
}
else if(SNS_SAM_PED_BATCH_IND_V01 == msg_hdr->msg_id) {
HAL_LOG_DEBUG("%s: SNS_SAM_PED_BATCH_IND_V01", __FUNCTION__);
sns_sam_ped_batch_ind_msg_v01* sam_ind =
(sns_sam_ped_batch_ind_msg_v01*)msg_ptr;
sample_list = (hal_sam_sample_t *)malloc(sam_ind->items_len * sizeof(hal_sam_sample_t));
if (NULL == sample_list) {
HAL_LOG_ERROR( "%s: Malloc error", __FUNCTION__ );
}
else {
curr_sample = sample_list;
clock_gettime( CLOCK_BOOTTIME, &ts_event );
ts_poll.tv_sec = ts_event.tv_sec;
for(i = 0; i < sam_ind->items_len; i++) {
curr_sample->data[0] = sam_ind->items[ i ].report.step_count;
curr_sample->data[1] = sam_ind->items[ i ].report.step_rate;
curr_sample->data[2] = sam_ind->items[ i ].report.step_confidence;
curr_sample->data[3] = sam_ind->items[ i ].report.step_event;
curr_sample->data[4] = sam_ind->items[ i ].report.step_count_error;
curr_sample->accuracy = 0;
curr_sample->timestamp = sam_ind->items[ i ].timestamp;
}
/* Report only last event*/
count = 1;
curr_sample++;
}
}
else {
HAL_LOG_ERROR("%s: Unknown message ID = %d", __FUNCTION__, msg_hdr->msg_id);
}
if(count == 0) {
pthread_mutex_lock(&data_cb->data_mutex);
/* Release wakelock if held */
if (getFlags() & SENSOR_FLAG_WAKE_UP) {
Utility::release_sensor_wake_lock(data_cb, __FUNCTION__);
}
pthread_mutex_unlock(&data_cb->data_mutex);
}
for (i = 0; i < count; i++) {
HAL_LOG_DEBUG("%s: handle %d, count=%d", __FUNCTION__, handle, count);
curr_sample = &sample_list[i];
/* As we update all sensors associated with an algo when SAM sends a response,
* step counter needs a special handling to avoid spurious events generated
* from step detector or pedometer when either of them are registered/de-registered.
*/
if ((step_counter_running_total == 0) ||
(step_counter_current_instance != sample_list->data[0])) {
step_counter_current_instance = curr_sample->data[0]; // 取出传感器传回的距离值
steps = step_counter_running_total + step_counter_current_instance; // 计算当前的总步数
step_counter_running_instance = steps;
la_sample.type = SENSOR_TYPE_STEP_COUNTER;
if(bWakeUp == false) {
la_sample.sensor = HANDLE_SAM_STEP_COUNTER;
HAL_LOG_VERBOSE("%s:sensor %s ",__FUNCTION__,
Utility::SensorTypeToSensorString(getType()));
} else {
la_sample.sensor = HANDLE_SAM_STEP_COUNTER_WAKE_UP;
HAL_LOG_VERBOSE("%s:sensor %s (wake_up)",__FUNCTION__,
Utility::SensorTypeToSensorString(getType()));
}
la_sample.u64.step_counter = steps;
la_sample.version = sizeof(sensors_event_t);
if( step_counter_current_instance == 0) {
/* Step count didn't change.
* Use present time to make sure timestamp is larger than previous event timestamp. */
la_sample.timestamp = android::elapsedRealtimeNano();
} else {
la_sample.timestamp = time_service->timestampCalc((uint64_t)curr_sample->timestamp, la_sample.sensor);
}
HAL_LOG_VERBOSE("%s: STEP COUNTER: steps %" PRIu64", running_total %" PRIu64" SAM TS: %u HAL TS:%lld elapsedRealtimeNano:%lld",
__FUNCTION__, steps, step_counter_running_total, curr_sample->timestamp, la_sample.timestamp,
android::elapsedRealtimeNano());
pthread_mutex_lock(&data_cb->data_mutex);
if (Utility::insertQueue(&la_sample)) { // 将数据插入到队列中
Utility::signalInd(data_cb); // 告知有数据达到,另一边等待的waitReponse返回,poll方法便可通过removeQueue方法取到数据了,即我们当前行走的总步数
}
pthread_mutex_unlock(&data_cb->data_mutex);
}
}
free(sample_list);
}
遍历下insertQueue的地方,我们发现基本上所有具体的sensor实现文件的processInd方法中都会调用这个方法,根据自身数据的特点,对其数据结构做指定封装。也就是所谓的工厂模式,是不是很神奇。。。
./libhalsensors/src/MultiShake.cpp:198: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/GeoMagneticRotationVector.cpp:377: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/FaceNShake.cpp:195: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/MagneticCalibration.cpp:246: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/Gravity.cpp:522: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/SignificantMotionDetector.cpp:230: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/Sensor.cpp:97: if (Utility::insertQueue(&flush_evt)){
./libhalsensors/src/LinearAcceleration.cpp:524: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/Orientation.cpp:507: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/SpeedPulse.cpp:174: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/Tilt.cpp:200: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/QHeart.cpp:357: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/BringToEar.cpp:195: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/StepDetector.cpp:362: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/IOD.cpp:272: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/MagneticUncalibratedSAM.cpp:248: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/AbsoluteMotionDetector.cpp:200: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/GameRotationVector.cpp:363: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/Pedometer.cpp:248: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/PedestrianActivityMonitor.cpp:215: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/TiltDetector.cpp:307: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/Facing.cpp:194: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/VehicleMotionDetector.cpp:202: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/Thresh.cpp:354: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/RelativeMotionDetector.cpp:203: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/GyroTap.cpp:202: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/PickUpGesture.cpp:235: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/FastAbsoluteMotionDetector.cpp:196: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/SMGRSensor.cpp:849: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/StepCounter.cpp:526: if (Utility::insertQueue(&la_sample)) {
./libhalsensors/src/CoarseMotionClassifier.cpp:196: if (Utility::insertQueue(&sensor_data)) {
./libhalsensors/src/Utility.cpp:322: FUNCTION: insertQueue
./libhalsensors/src/Utility.cpp:325:bool Utility::insertQueue(sensors_event_t const *data_ptr)
数据拿到的过程已经清楚了,那么processInd又是怎样被调用的呢?
在Android Sensor HAL层源码分析(基于Qualcomm平台)一文中,我们讲到通过addSensor的时候会实例化我们的sensor hal层对象,我们在回过头复习下Step Counter的构造过程,先看下其初始化的部分log:
06-04 19:48:04.423 D/qti_sensors_hal: addSensor: STEP COUNTER enabled handle:49
06-04 19:48:04.423 D/libsensor1: sensor1_init
06-04 19:48:04.423 V/libsensor1: libsensor_add_client Adding client index 7 (62)
06-04 19:48:04.423 D/libsensor1: libsensor_add_client: waking up rx thread 51 52
06-04 19:48:04.423 D/libsensor1: libsensor_rx_thread: waking on wakeup pipe 51
06-04 19:48:04.424 I/qti_sensors_hal: SAMSensor: sensor() is_attrib_ok=1
06-04 19:48:04.424 D/libsensor1: libsensor_rx_thread: waiting on fd 55
06-04 19:48:04.424 I/qti_sensors_hal: StepCounter: handle:49
06-04 19:48:04.424 I/qti_sensors_hal: sendAlgoAttribReq:sensor(android.sensor.step_counter) svc no:37 handle:49
06-04 19:48:04.424 D/libsensor1: libsensor_rx_thread: waiting on fd 56
06-04 19:48:04.424 D/libsensor1: libsensor_rx_thread: waiting on fd 57
06-04 19:48:04.424 I/libsensor1: libsensor_log_ctl_write_pkt: fd 62; svc 37; msg 36; txn 0; cmd WRITE_QMI
06-04 19:48:04.424 D/qti_sensors_hal: waitForResponse: timeout=1000
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waking on fd 62
06-04 19:48:04.426 I/libsensor1: libsensor_log_read_pkt: fd 62; svc 37; msg 36; txn 0; type RESP; cmd WRITE_QMI
06-04 19:48:04.426 V/qti_sensors_hal: SAMSensor_sensor1_cb: msg_type 1, Sn 37, msg Id 36, txn Id 0
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 57
06-04 19:48:04.426 I/qti_sensors_hal: processResp: handle:49
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 59
06-04 19:48:04.426 D/qti_sensors_hal: processResp: Received SNS_SAM_PED_GET_ATTRIBUTES_RESP_V01
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 60
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 61
06-04 19:48:04.426 I/qti_sensors_hal: processAlgoAttribResp:sensor(android.sensor.step_counter) Received response 0 for svc_num 37 handle 49
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 62
06-04 19:48:04.426 D/libsensor1: libsensor_rx_thread: waiting on fd 51
06-04 19:48:04.426 I/qti_sensors_hal: processAlgoAttribResp:sensor(android.sensor.step_counter) sensor1 Version:1 Power:11796 MaxFreq:65536 MinFreq:18 MaxSampleFreq:3276800 MinSampleFreq:3276800
case HANDLE_SAM_STEP_COUNTER:
case HANDLE_SAM_STEP_COUNTER_WAKE_UP:
property_get( HAL_PROP_STEP_COUNTER, add_sensor, "true" );
if (!strncmp("true", add_sensor, 4)) {
HAL_LOG_DEBUG("%s: STEP COUNTER enabled handle:%d",
__FUNCTION__, handle);
mSensors[handle] = new StepCounter(handle);
} else {
HAL_LOG_DEBUG("%s: STEP COUNTER disabled!", __FUNCTION__);
}
break;
class StepCounter : public SAMSensor {
uint64_t step_counter_running_total;
uint64_t step_counter_running_instance;
uint64_t step_counter_current_instance;
bool step_counter_is_timer_created;
struct timespec ts_event, ts_poll;
uint64_t prev_stepcount;
bool asyncmode;
timer_t sc_timer;
/*===========================================================================
FUNCTION: sendGetReportReq
Get the last report data after enabling the sensor.
===========================================================================*/
int sendGetReportReq(bool bRespRequired);
public:
StepCounter(int handle);
~StepCounter();
int enable(int en);
/*===========================================================================
FUNCTION: processResp
Process the response to the sensor1 SENSOR1_MSG_TYPE_RESP
Parameters
@msg_hdr : sensor1 message header
@msg_ptr : sensor1 message data
===========================================================================*/
void processResp(sensor1_msg_header_s *msg_hdr, void *msg_ptr);
/*===========================================================================
FUNCTION: processInd
Process the response to the sensor1 SENSOR1_MSG_TYPE_IND
Parameters
@msg_hdr : sensor1 message header
@msg_ptr : sensor1 message data
===========================================================================*/
void processInd(sensor1_msg_header_s *msg_hdr, void *msg_ptr);
/*===========================================================================
FUNCTION: setSensorInfo
Fill the sensor specific information.
===========================================================================*/
void setSensorInfo();
/*===========================================================================
FUNCTION: sendBatchReq
Send request to receive stepcounter info at periodic intervals
===========================================================================*/
int sendBatchReq();
/*===========================================================================
FUNCTION: manageBatch
Timer handler which allows switching to async mode when activity stopped
===========================================================================*/
static void manageBatch( sigval_t );
/*===========================================================================
FUNCTION: initTimer
Setup timer handler
===========================================================================*/
int initTimer(void);
};
可以看到stepCounter继承自SAMSensor,因此在构建StepCounter实例的时候,也会创建我们的SAMSensor,
StepCounter有几个成员变量,这里解释下:
step_counter_running_total保存之前步行的总数;
step_counter_current_instance保存当前sensor检测到的行走步数;
step_counter_running_instance则为本次行走探测完毕后的总步数;
即step_counter_running_instance=step_counter_running_total(之前的步数) + step_counter_current_instance(当前行走步数);
我们在前面StepCounter的processInd方法中看到,得到的mSteps就是这二者之和,最终会将此值返回到app层,即我们在app的如下地方打印的值event.values[0]:
public void onSensorChanged(SensorEvent event) {
mSteps = event.values[0];
Log.i(TAG,"Detected step changes:"+event.values[0]);
tv.setText("您今天走了"+String.valueOf((int)mSteps)+"步");
}
在SAMSensor的构造方法中,会通过Sensor1_open打开一条客户端连接,传入回调函数SAMSensor_sensor1_cb。
/* open sensor1 connection for SAM Sensor */
err = sensor1_open(&sensor1_cb->sensor1_handle, &SAMSensor_sensor1_cb, (intptr_t)this);
if (SENSOR1_SUCCESS != err) {
HAL_LOG_ERROR("%s: sensor1 open failed for %s!", __FUNCTION__,
Utility::SensorTypeToSensorString(getType()));
setAttribOK(false);
} else {
setAttribOK(true);
report_rate = (int)lroundf(calcSampleRate(0));
}
HAL_LOG_INFO("%s: sensor(%s) is_attrib_ok=%d", __FUNCTION__,
Utility::SensorTypeToSensorString(getType()), getAttribOK());
所以最后得到的step数据都会通过注册的SAMSensor_sensor1_cb方法返回(这里不明白的请戳上一篇文章复习),这对应于上面贴出的log,这里再贴一遍。
06-04 19:58:57.384 V/qti_sensors_hal: SAMSensor_sensor1_cb: msg_type 2, Sn 37, msg Id 5, txn Id 0
06-04 19:58:57.384 I/qti_sensors_hal: processInd: handle:49
06-04 19:58:57.384 D/qti_sensors_hal: processInd: SNS_SAM_PED_REPORT_IND_V01
06-04 19:58:57.384 D/qti_sensors_hal: processInd: handle 49, count=1
06-04 19:58:57.384 V/qti_sensors_hal: processInd:sensor android.sensor.step_counter
06-04 19:58:57.384 V/qti_sensors_hal: processInd: STEP COUNTER: steps 1, running_total 0 SAM TS: 22393870 HAL TS:679857437028 elapsedRealtimeNano:680554179479
06-04 19:58:57.385 D/qti_sensors_hal: poll:polldata:1, sensor:49, type:19, x:0.000000 y:0.000000 z:-0.000000
我们接着看SAMSensor_sensor1_cb方法得具体处理:
void SAMSensor_sensor1_cb (intptr_t cb_data,
sensor1_msg_header_s *msg_hdr,
sensor1_msg_type_e msg_type,
void *msg_ptr)
{
SAMSensor *sam = (SAMSensor *)cb_data;
hal_sensor1_cb_t *sensor1_cb = sam->getSensor1Cb();
hal_data_cb_t *data_cb = Utility::getDataCb();
if (msg_hdr != NULL) {
HAL_LOG_VERBOSE("%s: msg_type %d, Sn %d, msg Id %d, txn Id %d", __FUNCTION__,
msg_type, msg_hdr->service_number, msg_hdr->msg_id, msg_hdr->txn_id );
}
else {
if (msg_type != SENSOR1_MSG_TYPE_BROKEN_PIPE &&
msg_type != SENSOR1_MSG_TYPE_REQ &&
msg_type != SENSOR1_MSG_TYPE_RETRY_OPEN ) {
HAL_LOG_ERROR("%s: Error - invalid msg type with NULL msg_hdr: %u",
__FUNCTION__, msg_type);
return;
}
else {
HAL_LOG_VERBOSE("%s: msg_type %d", __FUNCTION__, msg_type);
}
}
switch(msg_type) {
case SENSOR1_MSG_TYPE_RESP_INT_ERR:
pthread_mutex_lock(&sensor1_cb->cb_mutex);
Utility::signalResponse(true, sensor1_cb);
pthread_mutex_unlock(&sensor1_cb->cb_mutex);
break;
case SENSOR1_MSG_TYPE_RESP:
sam->processResp(msg_hdr, msg_ptr);
break;
case SENSOR1_MSG_TYPE_IND:
pthread_mutex_lock(&data_cb->data_mutex);
/* acquire wakelock to make sure system doesn't go into suspend
* till data/indication is received by Android */
if (sam->getFlags() & SENSOR_FLAG_WAKE_UP) {
Utility::acquire_sensor_wake_lock(data_cb, __FUNCTION__);
}
pthread_mutex_unlock(&data_cb->data_mutex);
sam->processInd(msg_hdr, msg_ptr);
break;
case SENSOR1_MSG_TYPE_BROKEN_PIPE:
HAL_LOG_WARN("%s: SENSOR1_MSG_TYPE_BROKEN_PIPE", __FUNCTION__);
if (sensor1_cb != NULL) {
pthread_mutex_lock(&sensor1_cb->cb_mutex);
Recovery::handleBrokenPipe(sensor1_cb, &SAMSensor_sensor1_cb, cb_data);
pthread_mutex_unlock(&sensor1_cb->cb_mutex);
if (sam->getAttribOK()) {
if (sam->getEnabled()) {
/* Before enable the sensor, it is better to disable the
sensor to reset the enabled variable */
sam->enable(0);
/* Re-enable the sensor */
sam->enable(1);
}
}
} else {
HAL_LOG_ERROR("%s: sensor1_cb is NULL!", __FUNCTION__);
return;
}
break;
case SENSOR1_MSG_TYPE_RETRY_OPEN:
HAL_LOG_WARN("%s: SENSOR1_MSG_TYPE_RETRY_OPEN", __FUNCTION__);
if (sensor1_cb != NULL) {
pthread_mutex_lock(&sensor1_cb->cb_mutex);
Recovery::reInit(sensor1_cb, &SAMSensor_sensor1_cb, cb_data);
pthread_mutex_unlock( &sensor1_cb->cb_mutex );
} else {
HAL_LOG_ERROR("%s: sensor1_cb is NULL!", __FUNCTION__);
return;
}
break;
case SENSOR1_MSG_TYPE_REQ:
default:
HAL_LOG_ERROR("%s: Error - invalid msg type in cb: %u", __FUNCTION__, msg_type);
break;
}
pthread_mutex_lock(&sensor1_cb->cb_mutex);
if (NULL != msg_ptr && sensor1_cb->sensor1_handle) {
sensor1_free_msg_buf(sensor1_cb->sensor1_handle, msg_ptr);
}
pthread_mutex_unlock(&sensor1_cb->cb_mutex);
return;
}
参数cb_data里面保存了我们的sensor上报的数据。
由于底层上报的数据msg_type为,即我们的SENSOR1_MSG_TYPE_IND,主动上报的,因此会进入该分支继续处理。
消息类型定义如下:
/**
* Defines the types of response messages
*/
typedef enum sensor1_msg_type_e {
SENSOR1_MSG_TYPE_REQ, /**< Request */
SENSOR1_MSG_TYPE_RESP, /**< Response to a request */
SENSOR1_MSG_TYPE_IND, /**< Asynchronous indication */
SENSOR1_MSG_TYPE_RESP_INT_ERR, /**< Error response due to internal error.
Request failed. The associated msg data is
not a valid response. The msg header should
be used to identify the failed REQ. */
SENSOR1_MSG_TYPE_BROKEN_PIPE = 250,
/**< This "message type" indicates that the
message pipe to the sensors has been broken,
and the associated client handle is no longer
usable. The client should call sensor1_close()
to free the client handle. */
SENSOR1_MSG_TYPE_RETRY_OPEN = 251
/**< This "message type" will be used if sensor1_open returns
SENSOR1_WOULDBLOCK. This indicates that the sensor client may now retry
calling sensor1_open to get a valid client handle. */
} sensor1_msg_type_e;
最后直接call其processInd方法进一步处理上报的数据,该方法在SAMSensor中未虚方法,因此需要对应的子类具体实现,我们现在上报的是StepCounter类的数据,因此,会进入到StepCounter类中的processInd方法中处理,而这里处理了数据后会将数据通过Utility::insertQueue(&la_sample)方法将数据插入到我们的全局变量hal_sensor_dataq_t* Utility::q_head_ptr = NULL;队列里面去,以供poll方法可以从中读取并返回给上层使用。这样就和我们之前的逻辑推导吻合了。
我们看看hal层step counter的数据封装:
/** Indication Message; Output report from the pedometer algorithm. */
typedef struct {
/* Mandatory */
uint8_t instance_id;
/**< Identifies the algorithm instance. */
/* Mandatory */
uint32_t timestamp;
/**< Timestamp of the input with which the latest step was detected; in SSC
ticks. */
/* Mandatory */
sns_sam_ped_report_data_s_v01 report_data;
/**< Pedometer algorithm output report. */
}sns_sam_ped_report_ind_msg_v01; /* Message */
typedef struct {
uint8_t step_event;
/**< Indicates whether a step has been detected since the last client-initiated
reset. If this flag is FALSE, all other output fields are to be ignored.
*/
uint8_t step_confidence;
/**< Confidence with which the latest step was detected, scaled to a percentage
(0 to 100).
*/
uint32_t step_count;
/**< Count of the steps detected since the last client-initiated reset.
*/
int32_t step_count_error;
/**< Error metric associated with the reported step count, in steps.
*/
float step_rate;
/**< Rate in Hz at which steps are detected since the last client report or
reset (whichever is latest).
*/
}sns_sam_ped_report_data_s_v01; /* Type */
这里提醒一下,每一个sensor的processInd都会有具体的实现,每个sensor的数据都有自己独有的数据结构,最终都会封装转换成sensors_event_t结构体插入到queue队列中去。
下图反映了该过程的一部分流程,关于hal层部分,我会后面补上,记得关注我哦。
到这里,hal层的数据驱动基本上就分析完,接下来我们会继续跟进hal层的数据来源,这就会涉及到SensorDaemon以及高通的aDsp芯片了,欢迎关注。