我是靠谱客的博主 义气丝袜,最近开发中收集的这篇文章主要介绍Android8.0 下的 qcom8953 平台上的 sensor 调用过程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、Android Sensor的框架

在刚开始的时候,Android上的sensor调用还是在走内核的,通过芯片厂商编写相应的设备驱动来生成设备节点供上层访问,以读取设备节点的方式来读取sensor数据,但是后来人们发现这样做会增加功耗,因为sensor需要不断的上报数据,不断的更新数据,所以这就要求处理器不断为其工作,所以就会影响待机功耗,故高通在MSM8960之后就提出了一种方案,把sensor数据的处理放到ADSP中处理,ADSP在处理音频数据的数据顺便把sensor数据处理掉,降低功耗。因此在MSM8953后sensor数据的处理都放在ADSP中处理,并向以往那样通过节点的方式来获取数据。下面就是sensor数据处理的结构框图:

二、sensor的调用流程

1.framework调用流程图

1.1 hardware加载sensor hal层模块的代码流程

      上层会起一个SensorService服务,在随后的第一次初始化时,其onFirstRef会被调用(均继承自RefBase虚基类),紧接着,它会获取Sensors::Sensors()构造函数,去通过hw_get_module()函数去加载sensor hal层的代码以及sensor 结构体。

Sensors::Sensors()
    : mInitCheck(NO_INIT),
      mSensorModule(nullptr),
      mSensorDevice(nullptr) {
    status_t err = OK;
    if (UseMultiHal()) {
        mSensorModule = ::get_multi_hal_module_info();
    } else {
        err = hw_get_module(
            SENSORS_HARDWARE_MODULE_ID,
            (hw_module_t const **)&mSensorModule);
    }
    if (mSensorModule == NULL) {
        err = UNKNOWN_ERROR;
    }

    if (err != OK) {
        LOG(ERROR) << "Couldn't load "
                   << SENSORS_HARDWARE_MODULE_ID
                   << " module ("
                   << strerror(-err)
                   << ")";

        mInitCheck = err;
        return;
    }

    err = sensors_open_1(&mSensorModule->common, &mSensorDevice);

    if (err != OK) {
        LOG(ERROR) << "Couldn't open device for module "
                   << SENSORS_HARDWARE_MODULE_ID
                   << " ("
                   << strerror(-err)
                   << ")";

        mInitCheck = err;
        return;
    }

    // Require all the old HAL APIs to be present except for injection, which
    // is considered optional.
    CHECK_GE(getHalDeviceVersion(), SENSORS_DEVICE_API_VERSION_1_3);

    if (getHalDeviceVersion() == SENSORS_DEVICE_API_VERSION_1_4) {
        if (mSensorDevice->inject_sensor_data == nullptr) {
            LOG(ERROR) << "HAL specifies version 1.4, but does not implement inject_sensor_data()";
        }
        if (mSensorModule->set_operation_mode == nullptr) {
            LOG(ERROR) << "HAL specifies version 1.4, but does not implement set_operation_mode()";
        }
    }

    mInitCheck = OK;
}

识别HAL层模块是通过ID来匹配识别的,ID:SENSORS_HARDWARE_MODULE_ID,识别到了会返回一个handle句柄,这个句柄会赋给mSensorModule,这个句柄我们可以在vendor/qcom/proprietary/sensors/dsps/libhalsensors/src/sensors_hal.cpp中查看到,就是下面的结构体,会把这个结构体返回给mSensorModule,上层后期会通过这个结构体来打开sensor驱动;

static struct hw_module_methods_t sensors_module_methods = {
    .open = sensors_open
};

struct sensors_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .module_api_version = (uint16_t)SENSORS_DEVICE_API_VERSION_1_4,
        .hal_api_version = HARDWARE_HAL_API_VERSION,
        .id = SENSORS_HARDWARE_MODULE_ID,
        .name = "QTI Sensors Module",
        .author = "Qualcomm Technologies, Inc.",
        .methods = &sensors_module_methods,
        .dso = NULL,
        .reserved = {0},
    },
    .get_sensors_list = sensors_get_sensors_list,
    .set_operation_mode = sensors_set_operation_mode
};
struct sensors_module_t {
    struct hw_module_t common;

    /**
     * Enumerate all available sensors. The list is returned in "list".
     * return number of sensors in the list
     */
    int (*get_sensors_list)(struct sensors_module_t* module,
            struct sensor_t const** list);

    /**
     *  Place the module in a specific mode. The following modes are defined
     *
     *  0 - Normal operation. Default state of the module.
     *  1 - Loopback mode. Data is injected for the supported
     *      sensors by the sensor service in this mode.
     * return 0 on success
     *         -EINVAL if requested mode is not supported
     *         -EPERM if operation is not allowed
     */
    int (*set_operation_mode)(unsigned int mode);
};

那么问题来了,hardware是如何加载到vendor/qcom/proprietary/sensors/dsps/下的HAL层的呢?

加载流程如下:

SensorService::onFirstRef()---->sensorService启动时加载
    Sensors::Sensors()
        hw_get_module(SENSORS_HARDWARE_MODULE_ID,(hw_module_t const **)&mSensorModule);--->通过ID去匹配
            hw_get_module_by_class();
                load(class_id, path, module);---->加载sensor hal层编译出来的.so库文件,使用load()去加载这个库文件,
这个.so文件是根据Android.mk里面的规则来编译出来的。可通过readelf -s 命令读取这个.so文件;

static int load(const char *id,
        const char *path,
        const struct hw_module_t **pHmi)
{
    int status = -EINVAL;
    void *handle = NULL;
    struct hw_module_t *hmi = NULL;
 
    /*
     * load the symbols resolving undefined symbols before
     * dlopen returns. Since RTLD_GLOBAL is not or'd in with
     * RTLD_NOW the external symbols will not be global
     */
    handle = dlopen(path, RTLD_NOW);
    if (handle == NULL) {
        char const *err_str = dlerror();
        ALOGE("load: module=%sn%s", path, err_str?err_str:"unknown");
        status = -EINVAL;
        goto done;
    }
 
    /* Get the address of the struct hal_module_info. */
    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
    hmi = (struct hw_module_t *)dlsym(handle, sym);
    if (hmi == NULL) {
        ALOGE("load: couldn't find symbol %s", sym);
        status = -EINVAL;
        goto done;
    }
 
    /* Check that the id matches */
    if (strcmp(id, hmi->id) != 0) {
        ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
        status = -EINVAL;
        goto done;
    }
 
    hmi->dso = handle;
 
    /* success */
    status = 0;
 
    done:
    if (status != 0) {
        hmi = NULL;
        if (handle != NULL) {
            dlclose(handle);
            handle = NULL;
        }
    } else {
        ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
                id, path, *pHmi, handle);
    }
 
    *pHmi = hmi;
 
    return status;
}

1. 首先通过dlopen打开sensors.xxx.so模块,获得其句柄handle;

2.调用dlsym去获取结构体hw_module_t结构体的地址,注意这里传入的字符串为HAL_MODULE_INFO_SYM_AS_STR,定义在hardware.h头文件中;

readelf -s sensors.XXX.so

   528: 0001073d     4 FUNC    GLOBAL DEFAULT   12 _ZN10ThermopileD2Ev
   529: 0002f564    40 FUNC    GLOBAL DEFAULT   12 __floatunsisf
   530: 00010179   176 FUNC    GLOBAL DEFAULT   12 _ZN22AbsoluteMotionDetect
   531: 00010229     4 FUNC    GLOBAL DEFAULT   12 _ZN22AbsoluteMotionDetect
   532: 0001bbb1   540 FUNC    GLOBAL DEFAULT   12 _ZN24PersistentMotionDete
   533: 0002c97d    96 FUNC    GLOBAL DEFAULT   12 _ZN7Utility28isDirectChan
   534: 00028cb1   440 FUNC    GLOBAL DEFAULT   12 _ZN3Tap6enableEi
   535: 0002f3d4   400 FUNC    GLOBAL DEFAULT   12 __aeabi_fadd
   536: 0002b2c1   188 FUNC    GLOBAL DEFAULT   12 _ZN15TimeSyncService13rol
   537: 00017259   404 FUNC    GLOBAL DEFAULT   12 _ZN18LinearAcceleration12
   538: 0003d0a4     4 OBJECT  GLOBAL DEFAULT   22 _ZN7Latency25latency_meas
   539: 00020a6d   444 FUNC    GLOBAL DEFAULT   12 _ZN10SMGRSensor13SMGRRepo
   540: 00013b85   948 FUNC    GLOBAL DEFAULT   12 _ZN18GameRotationVector10
   541: 0003d010   136 OBJECT  GLOBAL DEFAULT   21 HMI
   542: 00011a79   540 FUNC    GLOBAL DEFAULT   12 _ZN17DeviceOrientation6en
   543: 000296e5    14 FUNC    GLOBAL DEFAULT   12 _ZN6ThreshD0Ev
   544: 00016085     8 FUNC    GLOBAL DEFAULT   12 _ZN9Gyroscope13prepareAdd
   545: 00015f65   288 FUNC    GLOBAL DEFAULT   12 _ZN9Gyroscope16processRep
   546: 00028149   604 FUNC    GLOBAL DEFAULT   12 _ZN12StepDetector6enableE
   547: 000299e9   572 FUNC    GLOBAL DEFAULT   12 _ZN6Thresh6enableEi

高通的Sensor实现了自己的HAL,其源码在vendor/qcom/proprietary/sensors/dsps/libhalsensors路径下,通过Android.mk我们也可以确定他确实是我们前面load方法打开的动态链接库,其编译后会生成sensors.ssc.so:

# vendor/qcom/proprietary/sensors/dsps/libhalsensors/Android.mk
ifeq ($(USE_SENSOR_MULTI_HAL),true)
LOCAL_MODULE := sensors.ssc
LOCAL_CLANG := false
else
LOCAL_MODULE := sensors.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_RELATIVE_PATH := hw
endif

到这里整个hw_get_module()加载完毕,会把sensor hal层的HAL_MODULE_INFO_SYM这个结构体返回给hw_get_module()里的mSensorModule变量,然后在sensors_open_1(&mSensorModule->common, &mSensorDevice);去打开这个sensor驱动函数;


static inline int sensors_open_1(const struct hw_module_t* module,
        sensors_poll_device_1_t** device) {
    return module->methods->open(module,
            SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);
}
 
static inline int sensors_close_1(sensors_poll_device_1_t* device) {
    return device->common.close(&device->common);

由HMI的结构体定义,其中module->common->open被赋值为sensors_module_methods,其只有一个open方法,因此,module->methods->open最终会调用sensors_open方法来打开驱动程序;

 

2.sensor 驱动文件的添加

2.1 在头文件中注册sensor ,添加该款的sensor的变量;

路径:vendor/qcom/non-hlos-msm8953/ADSP.8953.2.8.4/adsp_proc/Sensors/dd/qcom/inc/sns_dd.h;

extern sns_ddf_driver_if_s sns_mag_akm8963_driver_fn_list;
extern sns_ddf_driver_if_s sns_mag_akm8975_driver_fn_list;
extern sns_ddf_driver_if_s sns_alt_bmp085_driver_fn_list;
extern sns_ddf_driver_if_s sns_dd_acc_lis3dh_if;
extern sns_ddf_driver_if_s sns_dd_mag_lsm303dlhc_if;

1.2 添加驱动文件

路径:

未完待续......

最后

以上就是义气丝袜为你收集整理的Android8.0 下的 qcom8953 平台上的 sensor 调用过程的全部内容,希望文章能够帮你解决Android8.0 下的 qcom8953 平台上的 sensor 调用过程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部