程序员人生 网站导航

(gps)gps.conf中DEBUG_LEVEL的解析

栏目:综合技术时间:2015-03-28 08:31:03

gps.conf是gps的配置文件,这里面经常使用到的DEBUG_LEVEL配置项是gps HAL层logcat的开关,弄清楚这个配置项的解析流程一样对全部gps.conf的解析有很大的帮助,这里来走1下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信息只用read1次 // Initialize our defaults before reading of configuration file overwrites them. //初始化1些参数 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 "); } 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]))

这里面传入两个参数,1个是const char* conf_file_name,这里的值是”/etc/gps.conf”,另外一个是1个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项的第2个参数用到了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的第1步 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); //走过1边以后,conf_fp的文件指针已知道文件尾部了,rewind1下conf_fp又到了文件头部 rewind(conf_fp); } //这里是是读DEBUG_LEVEL的地方,重点跟进1下 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 ", __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 ", __func__, __LINE__, num_params); while(num_params) { //弄了半天,fp是有了但是1直没有读conf,这个fgets马上跟进 if(!fgets(input_buf, LOC_MAX_PARAM_LINE, conf_fp)) { //逐行来解析,如果读到文件尾就结束 LOC_LOGD("%s:%d]: fgets returned NULL ", __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之前,有1个类型需要关注1下:

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; //定义和初始化1个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) { //第2次用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做1下处理,清除里面的无用空格 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类型都存储1次 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(由因而逐行匹配,第1个就是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) = ''; } 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,那末所有信息也是可以打印的

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐