欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Sensor系列之Sensor HAL层数据获取,基于Qualcomm平台

程序员文章站 2022-06-08 20:42:36
...

前面我们分析了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层部分,我会后面补上,记得关注我哦。

Sensor系列之Sensor HAL层数据获取,基于Qualcomm平台

到这里,hal层的数据驱动基本上就分析完,接下来我们会继续跟进hal层的数据来源,这就会涉及到SensorDaemon以及高通的aDsp芯片了,欢迎关注。

相关标签: Sensor HAL