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) = '
主站蜘蛛池模板:
手机看片亚洲
|
另类五月
|
综合网伊人
|
欧美日韩国产一区二区三区欧
|
国产一二三区在线
|
欧美日韩性生活视频
|
秋霞一级特黄真人毛片
|
18到20女人一级毛片
|
国产aaa女人十八毛片
|
91精品国产91久久久久久最新
|
成人精品一区二区www
|
伊人久久大香
|
在线亚洲日产一区二区
|
wwwjizz欧美|
久久国产亚洲欧美日韩精品
|
波多野结衣资源在线
|
亚洲国产精品成
|
亚洲欧美一区二区三区图片
|
久久成人免费
|
国产精品国产精品国产专区不卡
|
男女激情视频软件
|
欧美70一80老妇性大片
|
男女羞羞视频免费
|
夜夜精品视频一区二区
|
亚洲最色网站
|
欧美一区二区三区男人的天堂
|
亚洲精品专区一区二区欧美
|
最新日本中文字幕
|
国产亚洲精品久久精品6
|
综合欧美一区二区三区
|
欧美jizzhd欧美精品巨大
|
欧美三级大片在线观看
|
视频1区
|
国产一级做a爰片久久毛片
国产一级做a爰片久久毛片99
|
久久精品国产400部免费看
|
亚洲欧美日韩网站
|
四虎在线永久精品高清
|
日本叼嘿视频
|
欧美一级爱爱
|
久草视频播放
|
国产精品99久久久久久人
|