码迷,mamicode.com
首页 > 其他好文 > 详细

(gps)gps.conf中DEBUG_LEVEL的解析

时间:2015-03-06 19:09:11      阅读:714      评论:0      收藏:0      [点我收藏+]

标签:gps

gps.conf是gps的配置文件,这里面常用到的DEBUG_LEVEL配置项是gps HAL层logcat的开关,搞清楚这个配置项的解析流程同样对整个gps.conf的解析有很大的帮助,这里来走一下flow。

hardware/qcom/gps/loc_api/libloc_api_50001/gps.c

     const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
    {
        return get_gps_interface();
    } 

在前面open_gps里面有提到过,gps__get_gps_interface()是在那里绑定的,如下:

    static int open_gps(const struct hw_module_t* module, char const* name,
            struct hw_device_t** device)
    {
        struct gps_device_t *dev = (struct gps_device_t *) malloc(sizeof(struct gps_device_t));

        if(dev == NULL)
            return -1;

        memset(dev, 0, sizeof(*dev));

        dev->common.tag = HARDWARE_DEVICE_TAG;
        dev->common.version = 0;
        dev->common.module = (struct hw_module_t*)module;
        dev->get_gps_interface = gps__get_gps_interface;

        *device = (struct hw_device_t*)dev;
        return 0;
    }

所以需要查到get_gps_interface在哪里调用的,如下:

frameworks/base/services/core/jni/com_android_server_location_GpsLocationProvider.cpp

    static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
        int err;
        hw_module_t* module;
        ...
        if (err == 0) {
            hw_device_t* device;
            err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
            if (err == 0) {
                gps_device_t* gps_device = (gps_device_t *)device;
                sGpsInterface = gps_device->get_gps_interface(gps_device);
            }
        }
        ...
    }

所以接下来看下get_gps_interface()定义,如下:

hardware/qcom/gps/loc_api/libloc_api_50001/loc.cpp

    extern "C" const GpsInterface* get_gps_interface()
    {
        unsigned int target = TARGET_DEFAULT;
        loc_eng_read_config();
        ...
    }

hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp

    int loc_eng_read_config(void)
    {
        ENTRY_LOG_CALLFLOW();
        if(configAlreadyRead == false)
        {
            //gps config信息只用read一次
            // Initialize our defaults before reading of configuration file overwrites them.
            //初始化一些参数
            loc_default_parameters();
            // We only want to parse the conf file once. This is a good place to ensure that.
            // In fact one day the conf file should go into context.
            //暂时先只关注GPS_CONF_FILE,也就是/etc/gps.conf
            UTIL_READ_CONF(GPS_CONF_FILE, gps_conf_table);
            UTIL_READ_CONF(SAP_CONF_FILE, sap_conf_table);
            configAlreadyRead = true;
        } else {
            LOC_LOGV("GPS Config file has already been read\n");
        }
        EXIT_LOG(%d, 0);
        return 0;
    }

看下UTIL_READ_CONF的定义:
hardware/qcom/gps/utils/loc_cfg.h

    #define UTIL_READ_CONF(filename, config_table) \
        loc_read_conf((filename), (config_table), sizeof(config_table) / sizeof(config_table[0]))

这里面传入两个参数,一个是const char* conf_file_name,这里的值是”/etc/gps.conf”,另一个是一个gps_conf_table,有必要看下这个table的类型:

hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp

    static loc_param_s_type gps_conf_table[] =
    {
      {"GPS_LOCK",                       &gps_conf.GPS_LOCK,                       NULL, ‘n‘},
      {"SUPL_VER",                       &gps_conf.SUPL_VER,                       NULL, ‘n‘},
      {"LPP_PROFILE",                    &gps_conf.LPP_PROFILE,                    NULL, ‘n‘},
      {"A_GLONASS_POS_PROTOCOL_SELECT",  &gps_conf.A_GLONASS_POS_PROTOCOL_SELECT,  NULL, ‘n‘},
      {"AGPS_CERT_WRITABLE_MASK",        &gps_conf.AGPS_CERT_WRITABLE_MASK,        NULL, ‘n‘},
      {"SUPL_MODE",                      &gps_conf.SUPL_MODE,                      NULL, ‘n‘},
      {"INTERMEDIATE_POS",               &gps_conf.INTERMEDIATE_POS,               NULL, ‘n‘},
      {"ACCURACY_THRES",                 &gps_conf.ACCURACY_THRES,                 NULL, ‘n‘},
      {"NMEA_PROVIDER",                  &gps_conf.NMEA_PROVIDER,                  NULL, ‘n‘},
      {"CAPABILITIES",                   &gps_conf.CAPABILITIES,                   NULL, ‘n‘},
      {"USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL",  &gps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL,          NULL, ‘n‘},
    };

数组的每个单项的类型是loc_param_s_type,这个单项的定义如下:

hardware/qcom/gps/utils/loc_cfg.h

    typedef struct
    {
      char                           param_name[LOC_MAX_PARAM_NAME];
      void                          *param_ptr;
      uint8_t                       *param_set;   /* was this value set by config file? */
      char                           param_type;  /* ‘n‘ for number,
                                                     ‘s‘ for string,
                                                     ‘f‘ for float */
    } loc_param_s_type;

table项的第二个参数用到了gps_conf变量,而gps_conf是loc_gps_cfg_s_type类型的,定义如下:

hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.h

    typedef struct loc_gps_cfg_s
    {
        uint32_t       INTERMEDIATE_POS;
        uint32_t       ACCURACY_THRES;
        uint32_t       SUPL_VER;
        uint32_t       SUPL_MODE;
        uint32_t       CAPABILITIES;
        uint32_t       LPP_PROFILE;
        uint32_t       XTRA_VERSION_CHECK;
        char        XTRA_SERVER_1[MAX_XTRA_SERVER_URL_LENGTH];
        char        XTRA_SERVER_2[MAX_XTRA_SERVER_URL_LENGTH];
        char        XTRA_SERVER_3[MAX_XTRA_SERVER_URL_LENGTH];
        uint32_t       USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL;
        uint32_t       NMEA_PROVIDER;
        uint32_t       GPS_LOCK;
        uint32_t       A_GLONASS_POS_PROTOCOL_SELECT;
        uint32_t       AGPS_CERT_WRITABLE_MASK;
    } loc_gps_cfg_s_type;

hardware/qcom/gps/utils/loc_cfg.cpp

    void loc_read_conf(const char* conf_file_name, loc_param_s_type* config_table,
                       uint32_t table_length)
    {
        FILE *conf_fp = NULL;
        char *lasts;
        loc_param_v_type config_value;
        uint32_t i;

        //打开/etc/gps.conf,拿到fp,这个是读取conf的第一步
        if((conf_fp = fopen(conf_file_name, "r")) != NULL)
        {
            LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name);
            if(table_length && config_table) {
                //table_length和config_table前面有定义,肯定是走这里啦,这里面是填充config_table的    
                loc_read_conf_r(conf_fp, config_table, table_length);
                //走过一边之后,conf_fp的文件指针已经知道文件尾部了,rewind一下conf_fp又到了文件头部
                rewind(conf_fp);
            }
            //这里是是读DEBUG_LEVEL的地方,重点跟进一下
            loc_read_conf_r(conf_fp, loc_param_table, loc_param_num);
            fclose(conf_fp);
        }
        /* Initialize logging mechanism with parsed data */
        loc_logger_init(DEBUG_LEVEL, TIMESTAMP);
    }

先看下loc_param_table的定义和初始化:

    /* Parameter data */
    static uint8_t DEBUG_LEVEL = 0xff;                                                                    
    static uint8_t TIMESTAMP = 0;

    /* Parameter spec table */
    static loc_param_s_type loc_param_table[] =
    {
        {"DEBUG_LEVEL",    &DEBUG_LEVEL, NULL,    ‘n‘},
        {"TIMESTAMP",      &TIMESTAMP,   NULL,    ‘n‘},
    };
    int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type);

在来看下loc_read_conf_r的具体实现:

    int loc_read_conf_r(FILE *conf_fp, loc_param_s_type* config_table, uint32_t table_length)
    {
        //conf_fp rewind到文件头部了,config_table的定义和初始化前面也做了,table_length就是loc_param_num,这里值是2
        int ret=0;

        unsigned int num_params=table_length;
        if(conf_fp == NULL) {
            LOC_LOGE("%s:%d]: ERROR: File pointer is NULL\n", __func__, __LINE__);
            ret = -1;
            goto err;
        }

        /* Clear all validity bits */
        //param_set全部初始化为NULL,表明这些值还没有被conf file设置
        for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
        {
            if(NULL != config_table[i].param_set)
            {
                *(config_table[i].param_set) = 0;
            }
        }

        char input_buf[LOC_MAX_PARAM_LINE];  /* declare a char array */

        LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
        while(num_params)
        {
            //弄了半天,fp是有了但是一直没有读conf,这个fgets马上跟进
            if(!fgets(input_buf, LOC_MAX_PARAM_LINE, conf_fp)) {
                //逐行来解析,如果读到文件尾就结束
                LOC_LOGD("%s:%d]: fgets returned NULL\n", __func__, __LINE__);
                break;
            }

            //根据读取的行,解析出里面的内容填充到config_table中,如果config_table填充完毕(就是说table里面的DEBUG_LEVEL和TIMESTAMP都填充完),这个循环同样结束
            num_params -= loc_fill_conf_item(input_buf, config_table, table_length);
        }

    err:
        return ret;
    }

在loc_fill_conf_item之前,有一个类型需要关注一下:

    typedef struct loc_param_v_type
    {
        char* param_name;
        char* param_str_value;
        int param_int_value;
        double param_double_value;
    }loc_param_v_type;

这个是用来存储从conf里面读出来的内容的,param_name用来存储conf的key的,param_str_value是用来存储value的字符串形态,param_int_value是用来存储value的int形态,param_double_value是用来存储value的double形态

int loc_fill_conf_item(char* input_buf,
                       loc_param_s_type* config_table, uint32_t table_length)
{
    int ret = 0;

    if (input_buf && config_table) {
        char *lasts;
        //定义和初始化一个loc_param_v_type,用来存储fgets读出来的这行conf
        loc_param_v_type config_value;
        memset(&config_value, 0, sizeof(config_value));

        /* Separate variable and value */
        把这行conf用strtok_r分离出key,直接存储到param_name中
        config_value.param_name = strtok_r(input_buf, "=", &lasts);
        /* skip lines that do not contain "=" */
        if (config_value.param_name) {
            //第二次用strtok_r分离出value来,但是目前暂时不知道value的类型
            config_value.param_str_value = strtok_r(NULL, "=", &lasts);

            /* skip lines that do not contain two operands */
            if (config_value.param_str_value) {
                /* Trim leading and trailing spaces */
                //对key和value做一下处理,清除里面的无用空格
                loc_util_trim_space(config_value.param_name);
                loc_util_trim_space(config_value.param_str_value);

                /* Parse numerical value */
                if ((strlen(config_value.param_str_value) >=3) &&
                    (config_value.param_str_value[0] == ‘0‘) &&
                    (tolower(config_value.param_str_value[1]) == ‘x‘))
                {
                    //如果value的前两个字符是0x,那么认为value是int类型
                    /* hex */
                    config_value.param_int_value = (int) strtol(&config_value.param_str_value[2],
                                                                (char**) NULL, 16);
                }
                else {
                    //否则int和double类型都存储一次
                    config_value.param_double_value = (double) atof(config_value.param_str_value); /* float */
                    config_value.param_int_value = atoi(config_value.param_str_value); /* dec */
                }

                //前面的动作是把fgets拿到的行填充到loc_param_v_type struct里面去,接下来要把这个struct填充到config_table里面去
                //针对DEBUG_LEVEL这个conf项,这里填充的结果如下:
                //param_name:           DEBUG_LEVEL
                //param_str_value:      5
                //param_int_value:      5
                //param_double_value:   5   (由于没有0x开头,所以double也被填充了)
                for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
                {
                    //table_length是2,前面有说到,也就是说把fgets拿到的行在config_table里面逐行的匹配
                    if(!loc_set_config_entry(&config_table[i], &config_value)) {
                        ret += 1;
                    }
                }
            }
        }
    }

    return ret;
}

看下是config_table里面的DEBUG_LEVEL是怎么被赋值的:

    int loc_set_config_entry(loc_param_s_type* config_entry, loc_param_v_type* config_value)
    {
        //loc_param_s_type在前面有定义过
        int ret=-1;
        if(NULL == config_entry || NULL == config_value)
        {
            LOC_LOGE("%s: INVALID config entry or parameter", __FUNCTION__);
            return ret;
        }

        //填充好的config_value的param_name(前面有分析的结果是DEBUG_LEVEL)跟config_table的param_name(由于是逐行匹配,第一个就是DEBUG_LEVEL)做匹配
        if (strcmp(config_entry->param_name, config_value->param_name) == 0 &&
            config_entry->param_ptr)
        {
            //如果匹配成功,且param_ptr的值不是NULL则继续分析
            switch (config_entry->param_type)
            {
            //config_table的定义和初始化前面有给出,param_type的值都是‘n‘
            case ‘s‘:
                if (strcmp(config_value->param_str_value, "NULL") == 0)
                {
                    *((char*)config_entry->param_ptr) = ‘\0‘;
                }
                else {
                    strlcpy((char*) config_entry->param_ptr,
                            config_value->param_str_value,
                            LOC_MAX_PARAM_STRING + 1);
                }
                /* Log INI values */
                LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__,
                         config_entry->param_name, (char*)config_entry->param_ptr);

                if(NULL != config_entry->param_set)
                {
                    *(config_entry->param_set) = 1;
                }
                ret = 0;
                break;
            case ‘n‘:
                //config_value的param_int_value赋值给config_entry的param_ptr,这里的值是5,这样子DEBUG_LEVEL的值就被改成了conf中的值了(也就是5)
                *((int *)config_entry->param_ptr) = config_value->param_int_value;
                /* Log INI values */
                LOC_LOGD("%s: PARAM %s = %d", __FUNCTION__,
                         config_entry->param_name, config_value->param_int_value);                        

                if(NULL != config_entry->param_set)
                {
                    //param_set置1,说明该config_entry被conf修改过
                    *(config_entry->param_set) = 1;
                }
                ret = 0;
                break;
            case ‘f‘:
                *((double *)config_entry->param_ptr) = config_value->param_double_value;
                /* Log INI values */
                LOC_LOGD("%s: PARAM %s = %f", __FUNCTION__,
                         config_entry->param_name, config_value->param_double_value);

                if(NULL != config_entry->param_set)
                {
                    *(config_entry->param_set) = 1;
                }
                ret = 0;
                break;
            default:
                LOC_LOGE("%s: PARAM %s parameter type must be n, f, or s",
                         __FUNCTION__, config_entry->param_name);
            }
        }
        return ret;
    }

DEBUG_LEVEL已经写入,那么接下来看下DEBUG_LEVEL是怎么使能的:

    void loc_logger_init(unsigned long debug, unsigned long timestamp)
    {
       //这个函数主要是把传入的参数填充到loc_logger里面
       loc_logger.DEBUG_LEVEL = debug;
    #ifdef TARGET_BUILD_VARIANT_USER
       // force user builds to 2 or less
       if (loc_logger.DEBUG_LEVEL > 2) {
           loc_logger.DEBUG_LEVEL = 2;
       }
    #endif
       loc_logger.TIMESTAMP   = timestamp;
    }

loc_logger是loc_logger_s类型的,看下具体的定义:

    hardware/qcom/gps/utils/log_util.h
    typedef struct loc_logger_s
    {
      unsigned long  DEBUG_LEVEL;
      unsigned long  TIMESTAMP;
    } loc_logger_s_type;

到目前为止,我们拿到了填充好的loc_logger变量,有必要看下log是如何打印的了:
看下LOC_LOGE:

    #define LOC_LOGE(...) \
    IF_LOC_LOGE { ALOGE("E/" __VA_ARGS__); }     else if (loc_logger.DEBUG_LEVEL == 0xff) { ALOGE("E/" __VA_ARGS__); }

转换之后的代码如下:

    if ((loc_logger.DEBUG_LEVEL >= 1) && (loc_logger.DEBUG_LEVEL <= 5)){ 
        ALOGE("E/" __VA_ARGS__);
    } else if (loc_logger.DEBUG_LEVEL == 0xff) { 
        ALOGE("E/" __VA_ARGS__); 
    }

gps.conf默认的DEBUG_LEVEL是3,也就是说这个会调用ALOGE(“E/” VA_ARGS);,也就是说LOC_LOGE在默认情况下是可以打印的

对比看下LOC_LOGV:

    #define LOC_LOGV(...) \
    IF_LOC_LOGV { ALOGE("V/" __VA_ARGS__); }       else if (loc_logger.DEBUG_LEVEL == 0xff) { ALOGV("V/" __VA_ARGS__); }

转换之后的代码如下:

    if ((loc_logger.DEBUG_LEVEL >= 5) && (loc_logger.DEBUG_LEVEL <= 5)){ 
        ALOGE("E/" __VA_ARGS__);
    } else if (loc_logger.DEBUG_LEVEL == 0xff) { 
        ALOGE("E/" __VA_ARGS__); 
    }

如果DEBUG_LEVEL是3,则LOC_LOGV是无法打印的,必须要改成5才行

如果gps.conf中没有DEBUG_LEVEL的配置项,那么loc_logger.DEBUG_LEVEL会使用默认的0xff,那么所有信息也是可以打印的

(gps)gps.conf中DEBUG_LEVEL的解析

标签:gps

原文地址:http://blog.csdn.net/lele_cheny/article/details/44102949

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!