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

(gps)gps.conf中DEBUG_LEVEL的解析

时间:2015-03-06 17:10:56      阅读:579      评论: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);
        }
    }
    ...
}
这个init是gps的在jni层的入口,至于为什么会走这里,以后再讲了


所以接下来看下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/44101579

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