1 /* Copyright (c) 2011-2015, 2018-2020 The Linux Foundation. All rights reserved.
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are
5  * met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above
9  *       copyright notice, this list of conditions and the following
10  *       disclaimer in the documentation and/or other materials provided
11  *       with the distribution.
12  *     * Neither the name of The Linux Foundation, nor the names of its
13  *       contributors may be used to endorse or promote products derived
14  *       from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #define LOG_NDEBUG 0
31 #define LOG_TAG "LocSvc_utils_cfg"
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <pthread.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <unistd.h>
39 #include <time.h>
40 #include <grp.h>
41 #include <errno.h>
42 #include <loc_cfg.h>
43 #include <loc_pla.h>
44 #include <loc_target.h>
45 #include <loc_misc_utils.h>
46 #ifdef USE_GLIB
47 #include <glib.h>
48 #endif
49 #include "log_util.h"
50 
51 /*=============================================================================
52  *
53  *                          GLOBAL DATA DECLARATION
54  *
55  *============================================================================*/
56 
57 /* Parameter data */
58 static uint32_t DEBUG_LEVEL = 0xff;
59 static uint32_t TIMESTAMP = 0;
60 static uint32_t DATUM_TYPE = 0;
61 static bool sVendorEnhanced = true;
62 static uint32_t sLogBufferEnabled = 0;
63 
64 /* Parameter spec table */
65 static const loc_param_s_type loc_param_table[] =
66 {
67     {"DEBUG_LEVEL",             &DEBUG_LEVEL,        NULL, 'n'},
68     {"TIMESTAMP",               &TIMESTAMP,          NULL, 'n'},
69     {"DATUM_TYPE",              &DATUM_TYPE,         NULL, 'n'},
70     {"LOG_BUFFER_ENABLED",      &sLogBufferEnabled,  NULL, 'n'},
71 };
72 static const int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type);
73 
74 typedef struct loc_param_v_type
75 {
76     char* param_name;
77     char* param_str_value;
78     int param_int_value;
79     double param_double_value;
80 }loc_param_v_type;
81 
82 // Reference below arrays wherever needed to avoid duplicating
83 // same conf path string over and again in location code.
84 const char LOC_PATH_GPS_CONF[] = LOC_PATH_GPS_CONF_STR;
85 const char LOC_PATH_IZAT_CONF[] = LOC_PATH_IZAT_CONF_STR;
86 const char LOC_PATH_FLP_CONF[] = LOC_PATH_FLP_CONF_STR;
87 const char LOC_PATH_LOWI_CONF[] = LOC_PATH_LOWI_CONF_STR;
88 const char LOC_PATH_SAP_CONF[] = LOC_PATH_SAP_CONF_STR;
89 const char LOC_PATH_APDR_CONF[] = LOC_PATH_APDR_CONF_STR;
90 const char LOC_PATH_XTWIFI_CONF[] = LOC_PATH_XTWIFI_CONF_STR;
91 const char LOC_PATH_QUIPC_CONF[] = LOC_PATH_QUIPC_CONF_STR;
92 const char LOC_PATH_ANT_CORR[] = LOC_PATH_ANT_CORR_STR;
93 const char LOC_PATH_SLIM_CONF[] = LOC_PATH_SLIM_CONF_STR;
94 const char LOC_PATH_VPE_CONF[] = LOC_PATH_VPE_CONF_STR;
95 
isVendorEnhanced()96 bool isVendorEnhanced() {
97     return sVendorEnhanced;
98 }
setVendorEnhanced(bool vendorEnhanced)99 void setVendorEnhanced(bool vendorEnhanced) {
100     sVendorEnhanced = vendorEnhanced;
101 }
102 
103 /*===========================================================================
104 FUNCTION loc_get_datum_type
105 
106 DESCRIPTION
107    get datum type
108 
109 PARAMETERS:
110    N/A
111 
112 DEPENDENCIES
113    N/A
114 
115 RETURN VALUE
116    DATUM TYPE
117 
118 SIDE EFFECTS
119    N/A
120 ===========================================================================*/
loc_get_datum_type()121 int loc_get_datum_type()
122 {
123     return DATUM_TYPE;
124 }
125 
126 /*===========================================================================
127 FUNCTION loc_set_config_entry
128 
129 DESCRIPTION
130    Potentially sets a given configuration table entry based on the passed in
131    configuration value. This is done by using a string comparison of the
132    parameter names and those found in the configuration file.
133 
134 PARAMETERS:
135    config_entry: configuration entry in the table to possibly set
136    config_value: value to store in the entry if the parameter names match
137 
138 DEPENDENCIES
139    N/A
140 
141 RETURN VALUE
142    None
143 
144 SIDE EFFECTS
145    N/A
146 ===========================================================================*/
loc_set_config_entry(const loc_param_s_type * config_entry,loc_param_v_type * config_value,uint16_t string_len=LOC_MAX_PARAM_STRING)147 int loc_set_config_entry(const loc_param_s_type* config_entry,
148                         loc_param_v_type* config_value,
149                         uint16_t string_len = LOC_MAX_PARAM_STRING)
150 {
151     int ret=-1;
152     if(NULL == config_entry || NULL == config_value)
153     {
154         LOC_LOGE("%s: INVALID config entry or parameter", __FUNCTION__);
155         return ret;
156     }
157 
158     if (strcmp(config_entry->param_name, config_value->param_name) == 0 &&
159         config_entry->param_ptr)
160     {
161         switch (config_entry->param_type)
162         {
163         case 's':
164             if (strcmp(config_value->param_str_value, "NULL") == 0)
165             {
166                 *((char*)config_entry->param_ptr) = '\0';
167             }
168             else {
169                 strlcpy((char*) config_entry->param_ptr,
170                         config_value->param_str_value,
171                         string_len);
172             }
173             /* Log INI values */
174             LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__,
175                      config_entry->param_name, (char*)config_entry->param_ptr);
176 
177             if(NULL != config_entry->param_set)
178             {
179                 *(config_entry->param_set) = 1;
180             }
181             ret = 0;
182             break;
183         case 'n':
184             *((int *)config_entry->param_ptr) = config_value->param_int_value;
185             /* Log INI values */
186             LOC_LOGD("%s: PARAM %s = %d", __FUNCTION__,
187                      config_entry->param_name, config_value->param_int_value);
188 
189             if(NULL != config_entry->param_set)
190             {
191                 *(config_entry->param_set) = 1;
192             }
193             ret = 0;
194             break;
195         case 'f':
196             *((double *)config_entry->param_ptr) = config_value->param_double_value;
197             /* Log INI values */
198             LOC_LOGD("%s: PARAM %s = %f", __FUNCTION__,
199                      config_entry->param_name, config_value->param_double_value);
200 
201             if(NULL != config_entry->param_set)
202             {
203                 *(config_entry->param_set) = 1;
204             }
205             ret = 0;
206             break;
207         default:
208             LOC_LOGE("%s: PARAM %s parameter type must be n, f, or s",
209                      __FUNCTION__, config_entry->param_name);
210         }
211     }
212     return ret;
213 }
214 
215 /*===========================================================================
216 FUNCTION loc_fill_conf_item
217 
218 DESCRIPTION
219    Takes a line of configuration item and sets defined values based on
220    the passed in configuration table. This table maps strings to values to
221    set along with the type of each of these values.
222 
223 PARAMETERS:
224    input_buf : buffer contanis config item
225    config_table: table definition of strings to places to store information
226    table_length: length of the configuration table
227 
228 DEPENDENCIES
229    N/A
230 
231 RETURN VALUE
232    0: Number of records in the config_table filled with input_buf
233 
234 SIDE EFFECTS
235    N/A
236 ===========================================================================*/
loc_fill_conf_item(char * input_buf,const loc_param_s_type * config_table,uint32_t table_length,uint16_t string_len=LOC_MAX_PARAM_STRING)237 int loc_fill_conf_item(char* input_buf,
238                        const loc_param_s_type* config_table,
239                        uint32_t table_length, uint16_t string_len = LOC_MAX_PARAM_STRING)
240 {
241     int ret = 0;
242 
243     if (input_buf && config_table) {
244         char *lasts;
245         loc_param_v_type config_value;
246         memset(&config_value, 0, sizeof(config_value));
247 
248         /* Separate variable and value */
249         config_value.param_name = strtok_r(input_buf, "=", &lasts);
250         /* skip lines that do not contain "=" */
251         if (config_value.param_name) {
252             config_value.param_str_value = strtok_r(NULL, "\0", &lasts);
253 
254             /* skip lines that do not contain two operands */
255             if (config_value.param_str_value) {
256                 /* Trim leading and trailing spaces */
257                 loc_util_trim_space(config_value.param_name);
258                 loc_util_trim_space(config_value.param_str_value);
259 
260                 /* Parse numerical value */
261                 if ((strlen(config_value.param_str_value) >=3) &&
262                     (config_value.param_str_value[0] == '0') &&
263                     (tolower(config_value.param_str_value[1]) == 'x'))
264                 {
265                     /* hex */
266                     config_value.param_int_value = (int) strtol(&config_value.param_str_value[2],
267                                                                 (char**) NULL, 16);
268                 }
269                 else {
270                     config_value.param_double_value = (double) atof(config_value.param_str_value); /* float */
271                     config_value.param_int_value = atoi(config_value.param_str_value); /* dec */
272                 }
273 
274                 for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
275                 {
276                     if(!loc_set_config_entry(&config_table[i], &config_value, string_len)) {
277                         ret += 1;
278                     }
279                 }
280             }
281         }
282     }
283 
284     return ret;
285 }
286 
287 /*===========================================================================
288 FUNCTION loc_read_conf_r_long (repetitive)
289 
290 DESCRIPTION
291    Reads the specified configuration file and sets defined values based on
292    the passed in configuration table. This table maps strings to values to
293    set along with the type of each of these values.
294    The difference between this and loc_read_conf is that this function returns
295    the file pointer position at the end of filling a config table. Also, it
296    reads a fixed number of parameters at a time which is equal to the length
297    of the configuration table. This functionality enables the caller to
298    repeatedly call the function to read data from the same file.
299 
300 PARAMETERS:
301    conf_fp : file pointer
302    config_table: table definition of strings to places to store information
303    table_length: length of the configuration table
304 
305 DEPENDENCIES
306    N/A
307 
308 RETURN VALUE
309    0: Table filled successfully
310    1: No more parameters to read
311   -1: Error filling table
312 
313 SIDE EFFECTS
314    N/A
315 ===========================================================================*/
loc_read_conf_r_long(FILE * conf_fp,const loc_param_s_type * config_table,uint32_t table_length,uint16_t string_len)316 int loc_read_conf_r_long(FILE *conf_fp, const loc_param_s_type* config_table,
317                          uint32_t table_length, uint16_t string_len)
318 {
319     int ret=0;
320     char input_buf[string_len];  /* declare a char array */
321     unsigned int num_params=table_length;
322 
323     if(conf_fp == NULL) {
324         LOC_LOGE("%s:%d]: ERROR: File pointer is NULL\n", __func__, __LINE__);
325         ret = -1;
326         goto err;
327     }
328 
329     /* Clear all validity bits */
330     for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
331     {
332         if(NULL != config_table[i].param_set)
333         {
334             *(config_table[i].param_set) = 0;
335         }
336     }
337 
338     LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
339     while(num_params)
340     {
341         if(!fgets(input_buf, string_len, conf_fp)) {
342             LOC_LOGD("%s:%d]: fgets returned NULL\n", __func__, __LINE__);
343             break;
344         }
345 
346         num_params -= loc_fill_conf_item(input_buf, config_table, table_length, string_len);
347     }
348 
349 err:
350     return ret;
351 }
352 
353 /*===========================================================================
354 FUNCTION loc_udpate_conf_long
355 
356 DESCRIPTION
357    Parses the passed in buffer for configuration items, and update the table
358    that is also passed in.
359 
360 Reads the specified configuration file and sets defined values based on
361    the passed in configuration table. This table maps strings to values to
362    set along with the type of each of these values.
363 
364 PARAMETERS:
365    conf_data: configuration items in bufferas a string
366    length: strlen(conf_data)
367    config_table: table definition of strings to places to store information
368    table_length: length of the configuration table
369 
370 DEPENDENCIES
371    N/A
372 
373 RETURN VALUE
374    number of the records in the table that is updated at time of return.
375 
376 SIDE EFFECTS
377    N/A
378 ===========================================================================*/
loc_update_conf_long(const char * conf_data,int32_t length,const loc_param_s_type * config_table,uint32_t table_length,uint16_t string_len)379 int loc_update_conf_long(const char* conf_data, int32_t length,
380                          const loc_param_s_type* config_table,
381                          uint32_t table_length, uint16_t string_len)
382 {
383     int ret = -1;
384 
385     if (conf_data && length && config_table && table_length) {
386         // make a copy, so we do not tokenize the original data
387         char* conf_copy = (char*)malloc(length+1);
388 
389         if (conf_copy != NULL)
390         {
391             memcpy(conf_copy, conf_data, length);
392             // we hard NULL the end of string to be safe
393             conf_copy[length] = 0;
394 
395             // start with one record off
396             uint32_t num_params = table_length - 1;
397             char* saveptr = NULL;
398             char* input_buf = strtok_r(conf_copy, "\n", &saveptr);
399             ret = 0;
400 
401             LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
402             while(num_params && input_buf) {
403                 ret++;
404                 num_params -=
405                         loc_fill_conf_item(input_buf, config_table, table_length, string_len);
406                 input_buf = strtok_r(NULL, "\n", &saveptr);
407             }
408             free(conf_copy);
409         }
410     }
411 
412     return ret;
413 }
414 
415 /*===========================================================================
416 FUNCTION loc_read_conf_long
417 
418 DESCRIPTION
419    Reads the specified configuration file and sets defined values based on
420    the passed in configuration table. This table maps strings to values to
421    set along with the type of each of these values.
422 
423 PARAMETERS:
424    conf_file_name: configuration file to read
425    config_table: table definition of strings to places to store information
426    table_length: length of the configuration table
427 
428 DEPENDENCIES
429    N/A
430 
431 RETURN VALUE
432    None
433 
434 SIDE EFFECTS
435    N/A
436 ===========================================================================*/
loc_read_conf_long(const char * conf_file_name,const loc_param_s_type * config_table,uint32_t table_length,uint16_t string_len)437 void loc_read_conf_long(const char* conf_file_name, const loc_param_s_type* config_table,
438                         uint32_t table_length, uint16_t string_len)
439 {
440     FILE *conf_fp = NULL;
441 
442     log_buffer_init(false);
443     if((conf_fp = fopen(conf_file_name, "r")) != NULL)
444     {
445         LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name);
446         if(table_length && config_table) {
447             loc_read_conf_r_long(conf_fp, config_table, table_length, string_len);
448             rewind(conf_fp);
449         }
450         loc_read_conf_r_long(conf_fp, loc_param_table, loc_param_num, string_len);
451         fclose(conf_fp);
452     }
453     /* Initialize logging mechanism with parsed data */
454     loc_logger_init(DEBUG_LEVEL, TIMESTAMP);
455     log_buffer_init(sLogBufferEnabled);
456     log_tag_level_map_init();
457 }
458 
459 /*=============================================================================
460  *
461  *   Define and Structures for Parsing Location Process Configuration File
462  *
463  *============================================================================*/
464 #define MAX_NUM_STRINGS   20
465 
466 //We can have 8 masks for now
467 #define CONFIG_MASK_TARGET_ALL           0X01
468 #define CONFIG_MASK_TARGET_FOUND         0X02
469 #define CONFIG_MASK_TARGET_CHECK         0X03
470 #define CONFIG_MASK_BASEBAND_ALL         0X04
471 #define CONFIG_MASK_BASEBAND_FOUND       0X08
472 #define CONFIG_MASK_BASEBAND_CHECK       0x0c
473 #define CONFIG_MASK_AUTOPLATFORM_ALL     0x10
474 #define CONFIG_MASK_AUTOPLATFORM_FOUND   0x20
475 #define CONFIG_MASK_AUTOPLATFORM_CHECK   0x30
476 #define CONFIG_MASK_SOCID_ALL            0x40
477 #define CONFIG_MASK_SOCID_FOUND          0x80
478 #define CONFIG_MASK_SOCID_CHECK          0xc0
479 
480 #define LOC_FEATURE_MASK_GTP_WIFI_BASIC            0x01
481 #define LOC_FEATURE_MASK_GTP_WIFI_PREMIUM          0X02
482 #define LOC_FEATURE_MASK_GTP_CELL_BASIC            0X04
483 #define LOC_FEATURE_MASK_GTP_CELL_PREMIUM          0X08
484 #define LOC_FEATURE_MASK_SAP_BASIC                 0x40
485 #define LOC_FEATURE_MASK_SAP_PREMIUM               0X80
486 #define LOC_FEATURE_MASK_GTP_WAA_BASIC             0X100
487 #define LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC      0X400
488 #define LOC_FEATURE_MASK_ODCPI                     0x1000
489 #define LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT     0x2000
490 #define LOC_FEATURE_MASK_SUPL_WIFI                 0x4000
491 #define LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO      0x8000
492 
493 typedef struct {
494     char proc_name[LOC_MAX_PARAM_STRING];
495     char proc_argument[LOC_MAX_PARAM_STRING];
496     char proc_status[LOC_MAX_PARAM_STRING];
497     char group_list[LOC_MAX_PARAM_STRING];
498     unsigned int premium_feature;
499     unsigned int loc_feature_mask;
500     char platform_list[LOC_MAX_PARAM_STRING];
501     char baseband[LOC_MAX_PARAM_STRING];
502     char low_ram_targets[LOC_MAX_PARAM_STRING];
503     char soc_id_list[LOC_MAX_PARAM_STRING];
504     unsigned int sglte_target;
505     char feature_gtp_mode[LOC_MAX_PARAM_STRING];
506     char feature_gtp_waa[LOC_MAX_PARAM_STRING];
507     char feature_sap[LOC_MAX_PARAM_STRING];
508     char feature_odcpi[LOC_MAX_PARAM_STRING];
509     char feature_free_wifi_scan_inject[LOC_MAX_PARAM_STRING];
510     char feature_supl_wifi[LOC_MAX_PARAM_STRING];
511     char feature_wifi_supplicant_info[LOC_MAX_PARAM_STRING];
512     char auto_platform[LOC_MAX_PARAM_STRING];
513     unsigned int vendor_enhanced_process;
514 } loc_launcher_conf;
515 
516 /* process configuration parameters */
517 static loc_launcher_conf conf;
518 
519 /* gps.conf Parameter spec table */
520 static const loc_param_s_type gps_conf_parameter_table[] = {
521     {"SGLTE_TARGET",        &conf.sglte_target,           NULL, 'n'},
522 };
523 
524 /* location feature conf, e.g.: izat.conf feature mode table*/
525 static const loc_param_s_type loc_feature_conf_table[] = {
526     {"GTP_MODE",              &conf.feature_gtp_mode,               NULL, 's'},
527     {"GTP_WAA",               &conf.feature_gtp_waa,                NULL, 's'},
528     {"SAP",                   &conf.feature_sap,                    NULL, 's'},
529     {"ODCPI",                 &conf.feature_odcpi,                  NULL, 's'},
530     {"FREE_WIFI_SCAN_INJECT", &conf.feature_free_wifi_scan_inject,  NULL, 's'},
531     {"SUPL_WIFI",             &conf.feature_supl_wifi,              NULL, 's'},
532     {"WIFI_SUPPLICANT_INFO",  &conf.feature_wifi_supplicant_info,   NULL, 's'},
533 };
534 
535 /* location process conf, e.g.: izat.conf Parameter spec table */
536 static const loc_param_s_type loc_process_conf_parameter_table[] = {
537     {"PROCESS_NAME",               &conf.proc_name,                NULL, 's'},
538     {"PROCESS_ARGUMENT",           &conf.proc_argument,            NULL, 's'},
539     {"PROCESS_STATE",              &conf.proc_status,              NULL, 's'},
540     {"PROCESS_GROUPS",             &conf.group_list,               NULL, 's'},
541     {"PREMIUM_FEATURE",            &conf.premium_feature,          NULL, 'n'},
542     {"IZAT_FEATURE_MASK",          &conf.loc_feature_mask,         NULL, 'n'},
543     {"PLATFORMS",                  &conf.platform_list,            NULL, 's'},
544     {"SOC_IDS",                    &conf.soc_id_list,            NULL, 's'},
545     {"BASEBAND",                   &conf.baseband,                 NULL, 's'},
546     {"LOW_RAM_TARGETS",            &conf.low_ram_targets,          NULL, 's'},
547     {"HARDWARE_TYPE",              &conf.auto_platform,            NULL, 's'},
548     {"VENDOR_ENHANCED_PROCESS",    &conf.vendor_enhanced_process,  NULL, 'n'},
549 };
550 
551 /*===========================================================================
552 FUNCTION loc_read_process_conf
553 
554 DESCRIPTION
555    Parse the specified conf file and return info for the processes defined.
556    The format of the file should conform with izat.conf.
557 
558 PARAMETERS:
559    conf_file_name: configuration file to read
560    process_count_ptr: pointer to store number of processes defined in the conf file.
561    process_info_table_ptr: pointer to store the process info table.
562 
563 DEPENDENCIES
564    The file must be in izat.conf format.
565 
566 RETURN VALUE
567    0: success
568    none-zero: failure
569 
570 SIDE EFFECTS
571    N/A
572 
573 NOTES:
574    On success, memory pointed by (*process_info_table_ptr) must be freed.
575 ===========================================================================*/
loc_read_process_conf(const char * conf_file_name,uint32_t * process_count_ptr,loc_process_info_s_type ** process_info_table_ptr)576 int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_ptr,
577                           loc_process_info_s_type** process_info_table_ptr) {
578     loc_process_info_s_type *child_proc = nullptr;
579     volatile int i=0;
580     unsigned int j=0;
581     gid_t gid_list[LOC_PROCESS_MAX_NUM_GROUPS];
582     char *split_strings[MAX_NUM_STRINGS];
583     int name_length=0, group_list_length=0, platform_length=0, baseband_length=0, ngroups=0, ret=0;
584     int auto_platform_length = 0, soc_id_list_length=0;
585     int group_index=0, nstrings=0, status_length=0;
586     FILE* conf_fp = nullptr;
587     char platform_name[PROPERTY_VALUE_MAX], baseband_name[PROPERTY_VALUE_MAX];
588     int low_ram_target=0;
589     char autoplatform_name[PROPERTY_VALUE_MAX], socid_value[PROPERTY_VALUE_MAX];
590     unsigned int loc_service_mask=0;
591     unsigned char config_mask = 0;
592     unsigned char proc_list_length=0;
593     int gtp_cell_ap_enabled = 0;
594     char arg_gtp_waa[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
595     char arg_gtp_modem_cell[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
596     char arg_gtp_wifi[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
597     char arg_sap[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
598     char arg_disabled[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_DISABLED;
599     char arg_basic[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_BASIC;
600     char arg_premium[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_PREMIUM;
601 
602     if (process_count_ptr == NULL || process_info_table_ptr == NULL) {
603         return -1;
604     }
605 
606     //Read gps.conf and fill parameter table
607     UTIL_READ_CONF(LOC_PATH_GPS_CONF, gps_conf_parameter_table);
608 
609     //Form argument strings
610     strlcat(arg_gtp_waa, LOC_FEATURE_GTP_WAA, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
611     strlcat(arg_gtp_modem_cell, LOC_FEATURE_GTP_MODEM_CELL, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
612     strlcat(arg_gtp_wifi, LOC_FEATURE_GTP_WIFI, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
613     strlcat(arg_sap, LOC_FEATURE_SAP, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
614 
615     //Get platform name from ro.board.platform property
616     loc_get_platform_name(platform_name, sizeof(platform_name));
617     //Get baseband name from ro.baseband property
618     loc_get_target_baseband(baseband_name, sizeof(baseband_name));
619     //Identify if this is an automotive platform
620     loc_get_auto_platform_name(autoplatform_name,sizeof(autoplatform_name));
621     //Identify if this is a low ram target from ro.config.low_ram property
622     low_ram_target = loc_identify_low_ram_target();
623     // Get the soc-id for this device.
624     loc_get_device_soc_id(socid_value, sizeof(socid_value));
625 
626     UTIL_READ_CONF(conf_file_name, loc_feature_conf_table);
627 
628     //Set service mask for GTP_MODE
629     if (strcmp(conf.feature_gtp_mode, "DISABLED") == 0) {
630         LOC_LOGD("%s:%d]: GTP MODE DISABLED", __func__, __LINE__);
631     }
632     else if (strcmp(conf.feature_gtp_mode, "LEGACY_WWAN") == 0) {
633         LOC_LOGD("%s:%d]: Setting GTP MODE to mode: LEGACY_WWAN", __func__, __LINE__);
634         loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC;
635     }
636     else if (strcmp(conf.feature_gtp_mode, "SDK") == 0) {
637         LOC_LOGD("%s:%d]: Setting GTP MODE to mode: SDK", __func__, __LINE__);
638         loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC;
639     }
640     else if (strcmp(conf.feature_gtp_mode, "SDK_WIFI") == 0) {
641         LOC_LOGD("%s:%d]: Setting GTP MODE to mode: SDK", __func__, __LINE__);
642         loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC;
643     }
644     //conf file has a garbage value
645     else {
646         LOC_LOGE("%s:%d]: Unrecognized value for GTP MODE Mode."\
647                  " Setting GTP WIFI to default mode: DISABLED", __func__, __LINE__);
648     }
649     //Set service mask for GTP_WAA
650     if (strcmp(conf.feature_gtp_waa, "BASIC") == 0) {
651       LOC_LOGD("%s:%d]: Setting GTP WAA to mode: BASIC", __func__, __LINE__);
652       loc_service_mask |= LOC_FEATURE_MASK_GTP_WAA_BASIC;
653     }
654     else if (strcmp(conf.feature_gtp_waa, "DISABLED") == 0) {
655       LOC_LOGD("%s:%d]: GTP WAA DISABLED", __func__, __LINE__);
656     }
657     //conf file has a garbage value
658     else {
659       LOC_LOGE("%s:%d]: Unrecognized value for GTP WAA Mode."\
660                " Setting GTP WAA to default mode: DISABLED", __func__, __LINE__);
661     }
662 
663     //Set service mask for SAP
664     if(strcmp(conf.feature_sap, "PREMIUM") == 0 ||
665        strcmp(conf.feature_sap, "PREMIUM_ENV_AIDING") == 0) {
666         LOC_LOGD("%s:%d]: Setting SAP to mode: PREMIUM", __func__, __LINE__);
667         loc_service_mask |= LOC_FEATURE_MASK_SAP_PREMIUM;
668     }
669     else if (strcmp(conf.feature_sap, "BASIC") == 0) {
670         LOC_LOGD("%s:%d]: Setting SAP to mode: BASIC", __func__, __LINE__);
671         loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
672     }
673     else if (strcmp(conf.feature_sap, "MODEM_DEFAULT") == 0) {
674         LOC_LOGD("%s:%d]: Setting SAP to mode: MODEM_DEFAULT", __func__, __LINE__);
675         loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
676     }
677     else if (strcmp(conf.feature_sap, "DISABLED") == 0) {
678 #ifdef USE_GLIB
679         /* Enable slim_daemon even when SAP is set to DISABLED*/
680         loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
681 #else
682         LOC_LOGD("%s:%d]: Setting SAP to mode: DISABLED", __func__, __LINE__);
683 #endif
684     }
685     else {
686        LOC_LOGE("%s:%d]: Unrecognized value for SAP Mode."\
687                 " Setting SAP to default mode: BASIC", __func__, __LINE__);
688        loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
689     }
690 
691     // Set service mask for ODCPI
692     if (strcmp(conf.feature_odcpi, "BASIC") == 0) {
693         LOC_LOGD("%s:%d]: Setting ODCPI to mode: BASIC", __func__, __LINE__);
694         loc_service_mask |= LOC_FEATURE_MASK_ODCPI;
695     }
696     else if (strcmp(conf.feature_odcpi, "DISABLED") == 0) {
697         LOC_LOGD("%s:%d]: Setting ODCPI to mode: DISABLED", __func__, __LINE__);
698     }
699     else if (strcmp(conf.feature_odcpi, "PREMIUM") == 0) {
700         LOC_LOGD("%s:%d]: Unrecognized value for ODCPI mode."\
701             "Setting ODCPI to default mode: BASIC", __func__, __LINE__);
702         loc_service_mask |= LOC_FEATURE_MASK_ODCPI;
703     }
704 
705     // Set service mask for FREE_WIFI_SCAN_INJECT
706     if (strcmp(conf.feature_free_wifi_scan_inject, "BASIC") == 0) {
707         LOC_LOGD("%s:%d]: Setting FREE_WIFI_SCAN_INJECT to mode: BASIC", __func__, __LINE__);
708         loc_service_mask |= LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT;
709     }
710     else if (strcmp(conf.feature_free_wifi_scan_inject, "DISABLED") == 0) {
711         LOC_LOGD("%s:%d]: Setting FREE_WIFI_SCAN_INJECT to mode: DISABLED", __func__, __LINE__);
712     }
713     else if (strcmp(conf.feature_free_wifi_scan_inject, "PREMIUM") == 0) {
714         LOC_LOGD("%s:%d]: Unrecognized value for FREE_WIFI_SCAN_INJECT mode."\
715             "Setting FREE_WIFI_SCAN_INJECT to default mode: BASIC", __func__, __LINE__);
716         loc_service_mask |= LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT;
717     }
718 
719     // Set service mask for SUPL_WIFI
720     if (strcmp(conf.feature_supl_wifi, "BASIC") == 0) {
721         LOC_LOGD("%s:%d]: Setting SUPL_WIFI to mode: BASIC", __func__, __LINE__);
722         loc_service_mask |= LOC_FEATURE_MASK_SUPL_WIFI;
723     }
724     else if (strcmp(conf.feature_supl_wifi, "DISABLED") == 0) {
725         LOC_LOGD("%s:%d]: Setting SUPL_WIFI to mode: DISABLED", __func__, __LINE__);
726     }
727     else if (strcmp(conf.feature_supl_wifi, "PREMIUM") == 0) {
728         LOC_LOGD("%s:%d]: Unrecognized value for SUPL_WIFI mode."\
729             "Setting SUPL_WIFI to default mode: BASIC", __func__, __LINE__);
730         loc_service_mask |= LOC_FEATURE_MASK_SUPL_WIFI;
731     }
732 
733     // Set service mask for WIFI_SUPPLICANT_INFO
734     if (strcmp(conf.feature_wifi_supplicant_info, "BASIC") == 0) {
735         LOC_LOGD("%s:%d]: Setting WIFI_SUPPLICANT_INFO to mode: BASIC", __func__, __LINE__);
736         loc_service_mask |= LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO;
737     }
738     else if (strcmp(conf.feature_wifi_supplicant_info, "DISABLED") == 0) {
739         LOC_LOGD("%s:%d]: Setting WIFI_SUPPLICANT_INFO to mode: DISABLED", __func__, __LINE__);
740     }
741     else if (strcmp(conf.feature_wifi_supplicant_info, "PREMIUM") == 0) {
742         LOC_LOGD("%s:%d]: Unrecognized value for WIFI_SUPPLICANT_INFO mode."\
743             "Setting LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO to default mode: BASIC", __func__, __LINE__);
744         loc_service_mask |= LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO;
745     }
746 
747     LOC_LOGD("%s:%d]: loc_service_mask: %x\n", __func__, __LINE__, loc_service_mask);
748 
749     if((conf_fp = fopen(conf_file_name, "r")) == NULL) {
750         LOC_LOGE("%s:%d]: Error opening %s %s\n", __func__,
751                  __LINE__, conf_file_name, strerror(errno));
752         ret = -1;
753         goto err;
754     }
755 
756     //Parse through the file to find out how many processes are to be launched
757     proc_list_length = 0;
758     do {
759         conf.proc_name[0] = 0;
760         //Here note that the 3rd parameter is passed as 1.
761         //This is so that only the first parameter in the table which is "PROCESS_NAME"
762         //is read. We do not want to read the entire block of parameters at this time
763         //since we are only counting the number of processes to launch.
764         //Therefore, only counting the occurrences of PROCESS_NAME parameter
765         //should suffice
766         if(loc_read_conf_r(conf_fp, loc_process_conf_parameter_table, 1)) {
767             LOC_LOGE("%s:%d]: Unable to read conf file. Failing\n", __func__, __LINE__);
768             ret = -1;
769             goto err;
770         }
771         name_length=(int)strlen(conf.proc_name);
772         if(name_length) {
773             proc_list_length++;
774             LOC_LOGD("Process name:%s", conf.proc_name);
775         }
776     } while(name_length);
777     LOC_LOGD("Process cnt = %d", proc_list_length);
778 
779     child_proc = (loc_process_info_s_type *)calloc(proc_list_length, sizeof(loc_process_info_s_type));
780     if(child_proc == NULL) {
781         LOC_LOGE("%s:%d]: ERROR: Malloc returned NULL\n", __func__, __LINE__);
782         ret = -1;
783         goto err;
784     }
785 
786     //Move file descriptor to the beginning of the file
787     //so that the parameters can be read
788     rewind(conf_fp);
789 
790     for(j=0; j<proc_list_length; j++) {
791         //Set defaults for all the child process structs
792         child_proc[j].proc_status = DISABLED;
793         memset(child_proc[j].group_list, 0, sizeof(child_proc[j].group_list));
794         config_mask=0;
795         if(loc_read_conf_r(conf_fp, loc_process_conf_parameter_table,
796                            sizeof(loc_process_conf_parameter_table)/sizeof(loc_process_conf_parameter_table[0]))) {
797             LOC_LOGE("%s:%d]: Unable to read conf file. Failing\n", __func__, __LINE__);
798             ret = -1;
799             goto err;
800         }
801 
802         name_length=(int)strlen(conf.proc_name);
803         group_list_length=(int)strlen(conf.group_list);
804         platform_length = (int)strlen(conf.platform_list);
805         baseband_length = (int)strlen(conf.baseband);
806         status_length = (int)strlen(conf.proc_status);
807         auto_platform_length = (int)strlen(conf.auto_platform);
808         soc_id_list_length = (int)strlen(conf.soc_id_list);
809 
810         if(!name_length || !group_list_length || !platform_length ||
811            !baseband_length || !status_length || !auto_platform_length || !soc_id_list_length) {
812             LOC_LOGE("%s:%d]: Error: i: %d; One of the parameters not specified in conf file",
813                      __func__, __LINE__, i);
814             continue;
815         }
816 
817         if (!isVendorEnhanced() && (conf.vendor_enhanced_process != 0)) {
818             LOC_LOGD("%s:%d]: Process %s is disabled via vendor enhanced process check",
819                      __func__, __LINE__, conf.proc_name);
820             child_proc[j].proc_status = DISABLED_VIA_VENDOR_ENHANCED_CHECK;
821             continue;
822         }
823 
824         if (strcmp(conf.proc_status, "DISABLED") == 0) {
825             LOC_LOGD("%s:%d]: Process %s is disabled in conf file",
826                      __func__, __LINE__, conf.proc_name);
827             child_proc[j].proc_status = DISABLED_FROM_CONF;
828             continue;
829         }
830         else if (strcmp(conf.proc_status, "ENABLED") == 0) {
831             LOC_LOGD("%s:%d]: Process %s is enabled in conf file",
832                      __func__, __LINE__, conf.proc_name);
833         }
834 
835         //Since strlcpy copies length-1 characters, we add 1 to name_length
836         if((name_length+1) > LOC_MAX_PARAM_STRING) {
837             LOC_LOGE("%s:%d]: i: %d; Length of name parameter too long. Max length: %d",
838                      __func__, __LINE__, i, LOC_MAX_PARAM_STRING);
839             continue;
840         }
841         strlcpy(child_proc[j].name[0], conf.proc_name, sizeof (child_proc[j].name[0]));
842 
843         child_proc[j].num_groups = 0;
844         ngroups = loc_util_split_string(conf.group_list, split_strings, MAX_NUM_STRINGS, ' ');
845         for(i=0; i<ngroups; i++) {
846             struct group* grp = getgrnam(split_strings[i]);
847             if (grp) {
848                 child_proc[j].group_list[child_proc[j].num_groups] = grp->gr_gid;
849                 child_proc[j].num_groups++;
850                 LOC_LOGd("Group %s = %d", split_strings[i], grp->gr_gid);
851             }
852         }
853 
854         nstrings = loc_util_split_string(conf.platform_list, split_strings, MAX_NUM_STRINGS, ' ');
855         if (strcmp("all", split_strings[0]) == 0) {
856             if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
857                 LOC_LOGD("%s:%d]: Enabled for all targets\n", __func__, __LINE__);
858                 config_mask |= CONFIG_MASK_TARGET_ALL;
859             }
860             else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
861                 config_mask |= CONFIG_MASK_TARGET_FOUND;
862                 for (i=2; i<nstrings; i++) {
863                     if (strcmp(platform_name, split_strings[i]) == 0) {
864                         LOC_LOGD("%s:%d]: Disabled platform %s\n", __func__, __LINE__, platform_name);
865                         config_mask &= ~CONFIG_MASK_TARGET_FOUND;
866                         break;
867                     }
868                 }
869             }
870         }
871         else {
872             for(i=0; i<nstrings; i++) {
873                 if (strcmp(platform_name, split_strings[i]) == 0) {
874                     LOC_LOGD("%s:%d]: Matched platform: %s\n",
875                              __func__, __LINE__, split_strings[i]);
876                     config_mask |= CONFIG_MASK_TARGET_FOUND;
877                     break;
878                 }
879             }
880         }
881 
882         // SOC Id's check
883         nstrings = loc_util_split_string(conf.soc_id_list, split_strings, MAX_NUM_STRINGS, ' ');
884         if (strcmp("all", split_strings[0]) == 0) {
885             if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
886                 LOC_LOGd("Enabled for all SOC ids\n");
887                 config_mask |= CONFIG_MASK_SOCID_ALL;
888             }
889             else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
890                 config_mask |= CONFIG_MASK_SOCID_FOUND;
891                 for (i = 2; i < nstrings; i++) {
892                     if (strcmp(socid_value, split_strings[i]) == 0) {
893                         LOC_LOGd("Disabled for SOC id %s\n", socid_value);
894                         config_mask &= ~CONFIG_MASK_SOCID_FOUND;
895                         break;
896                     }
897                 }
898             }
899         }
900         else {
901             for (i = 0; i < nstrings; i++) {
902                 if (strcmp(socid_value, split_strings[i]) == 0) {
903                     LOC_LOGd("Matched SOC id : %s\n", split_strings[i]);
904                     config_mask |= CONFIG_MASK_SOCID_FOUND;
905                     break;
906                 }
907             }
908         }
909 
910         nstrings = loc_util_split_string(conf.baseband, split_strings, MAX_NUM_STRINGS, ' ');
911         if (strcmp("all", split_strings[0]) == 0) {
912             if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
913                 LOC_LOGD("%s:%d]: Enabled for all basebands\n", __func__, __LINE__);
914                 config_mask |= CONFIG_MASK_BASEBAND_ALL;
915             }
916             else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
917                 config_mask |= CONFIG_MASK_BASEBAND_FOUND;
918                 for (i=2; i<nstrings; i++) {
919                     if (strcmp(baseband_name, split_strings[i]) == 0) {
920                         LOC_LOGD("%s:%d]: Disabled band %s\n", __func__, __LINE__, baseband_name);
921                         config_mask &= ~CONFIG_MASK_BASEBAND_FOUND;
922                         break;
923                     }
924                 }
925             }
926         }
927         else {
928             for(i=0; i<nstrings; i++) {
929                 if (strcmp(baseband_name, split_strings[i]) == 0) {
930                     LOC_LOGD("%s:%d]: Matched baseband: %s\n",
931                              __func__, __LINE__, split_strings[i]);
932                     config_mask |= CONFIG_MASK_BASEBAND_FOUND;
933                     break;
934                 }
935                 //Since ro.baseband is not a reliable source for detecting sglte
936                 //the alternative is to read the SGLTE_TARGET parameter from gps.conf
937                 //this parameter is read into conf_sglte_target
938                 else if((strcmp("sglte", split_strings[i]) == 0 ) && conf.sglte_target) {
939                     LOC_LOGD("%s:%d]: Matched baseband SGLTE\n", __func__, __LINE__);
940                     config_mask |= CONFIG_MASK_BASEBAND_FOUND;
941                     break;
942                 }
943             }
944         }
945 
946         nstrings = loc_util_split_string(conf.auto_platform, split_strings, MAX_NUM_STRINGS, ' ');
947         if (strcmp("all", split_strings[0]) == 0) {
948             LOC_LOGD("%s:%d]: Enabled for all auto platforms\n", __func__, __LINE__);
949             config_mask |= CONFIG_MASK_AUTOPLATFORM_ALL;
950         }
951         else {
952             for(i=0; i<nstrings; i++) {
953                 if (strcmp(autoplatform_name, split_strings[i]) == 0) {
954                     LOC_LOGD("%s:%d]: Matched auto platform: %s\n",
955                              __func__, __LINE__, split_strings[i]);
956                     config_mask |= CONFIG_MASK_AUTOPLATFORM_FOUND;
957                     break;
958                 }
959             }
960         }
961 
962         nstrings = loc_util_split_string(conf.low_ram_targets, split_strings, MAX_NUM_STRINGS, ' ');
963         if (!strcmp("DISABLED", split_strings[0]) && low_ram_target) {
964             LOC_LOGd("Disabled for low ram targets\n");
965             child_proc[j].proc_status = DISABLED;
966             continue;
967         }
968 
969         if((config_mask & CONFIG_MASK_TARGET_CHECK) &&
970            (config_mask & CONFIG_MASK_BASEBAND_CHECK) &&
971            (config_mask & CONFIG_MASK_AUTOPLATFORM_CHECK) &&
972            (config_mask & CONFIG_MASK_SOCID_CHECK) &&
973            (child_proc[j].proc_status != DISABLED_FROM_CONF) &&
974            (child_proc[j].proc_status != DISABLED_VIA_VENDOR_ENHANCED_CHECK)) {
975 
976             //Set args
977             //The first argument passed through argv is usually the name of the
978             //binary when started from commandline.
979             //getopt() seems to ignore this first argument and hence we assign it
980             //to the process name for consistency with command line args
981             i = 0;
982             char* temp_arg = ('/' == child_proc[j].name[0][0]) ?
983                 (strrchr(child_proc[j].name[0], '/') + 1) : child_proc[j].name[0];
984             strlcpy (child_proc[j].args[i++], temp_arg, sizeof (child_proc[j].args[0]));
985 
986             if(conf.premium_feature) {
987                if(conf.loc_feature_mask & loc_service_mask) {
988                     LOC_LOGD("%s:%d]: Enabled. %s has service mask: %x\n",
989                              __func__, __LINE__, child_proc[j].name[0], conf.loc_feature_mask);
990                     child_proc[j].proc_status = ENABLED;
991 
992                     if(conf.loc_feature_mask &
993                        (LOC_FEATURE_MASK_GTP_WIFI_BASIC | LOC_FEATURE_MASK_GTP_WIFI_PREMIUM)) {
994                         if(loc_service_mask & LOC_FEATURE_MASK_GTP_WIFI_BASIC) {
995                             strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
996                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
997                             strlcpy(child_proc[j].args[i++], arg_basic,
998                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
999                         }
1000                         else if(loc_service_mask & LOC_FEATURE_MASK_GTP_WIFI_PREMIUM) {
1001                             strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
1002                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1003                             strlcpy(child_proc[j].args[i++], arg_premium,
1004                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1005                         }
1006                         else
1007                         {
1008                             strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
1009                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1010                             strlcpy(child_proc[j].args[i++], arg_disabled,
1011                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1012                         }
1013                     }
1014                     if(conf.loc_feature_mask &
1015                        (LOC_FEATURE_MASK_GTP_CELL_BASIC | LOC_FEATURE_MASK_GTP_CELL_PREMIUM )) {
1016                         if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC) {
1017                             strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell,
1018                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1019                             strlcpy(child_proc[j].args[i++], arg_basic,
1020                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1021                         }
1022                         else {
1023                              strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell,
1024                                      LOC_PROCESS_MAX_ARG_STR_LENGTH);
1025                              strlcpy(child_proc[j].args[i++], arg_disabled,
1026                                      LOC_PROCESS_MAX_ARG_STR_LENGTH);
1027                        }
1028                     }
1029                     if(conf.loc_feature_mask &
1030                        (LOC_FEATURE_MASK_SAP_BASIC | LOC_FEATURE_MASK_SAP_PREMIUM)) {
1031                         if(loc_service_mask & LOC_FEATURE_MASK_SAP_BASIC) {
1032                             strlcpy(child_proc[j].args[i++], arg_sap,
1033                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1034                             strlcpy(child_proc[j].args[i++], arg_basic,
1035                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1036                         }
1037                         else if(loc_service_mask & LOC_FEATURE_MASK_SAP_PREMIUM) {
1038                             strlcpy(child_proc[j].args[i++], arg_sap,
1039                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1040                             strlcpy(child_proc[j].args[i++], arg_premium,
1041                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1042                         }
1043                         else
1044                         {
1045                             strlcpy(child_proc[j].args[i++], arg_sap,
1046                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1047                             strlcpy(child_proc[j].args[i++], arg_disabled,
1048                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1049                         }
1050                     }
1051 
1052                     if(conf.loc_feature_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) {
1053                       if(loc_service_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) {
1054                         strlcpy(child_proc[j].args[i++], arg_gtp_waa,
1055                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
1056                         strlcpy(child_proc[j].args[i++], arg_basic,
1057                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
1058                       }
1059                       else
1060                       {
1061                         strlcpy(child_proc[j].args[i++], arg_gtp_waa,
1062                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
1063                         strlcpy(child_proc[j].args[i++], arg_disabled,
1064                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
1065                       }
1066                     }
1067                     IF_LOC_LOGD {
1068                         LOC_LOGD("%s:%d]: %s args\n", __func__, __LINE__, child_proc[j].name[0]);
1069                         for(unsigned int k=0; k<LOC_PROCESS_MAX_NUM_ARGS; k++) {
1070                             if(child_proc[j].args[k][0] != '\0') {
1071                                 LOC_LOGD("%s:%d]: k: %d, %s\n", __func__, __LINE__, k,
1072                                          child_proc[j].args[k]);
1073                             }
1074                         }
1075                         LOC_LOGD("%s:%d]: \n", __func__, __LINE__);
1076                     }
1077                 }
1078                 else {
1079                     LOC_LOGD("%s:%d]: Disabled. %s has service mask:  %x \n",
1080                              __func__, __LINE__, child_proc[j].name[0], conf.loc_feature_mask);
1081                 }
1082             }
1083             else {
1084                 LOC_LOGD("%s:%d]: %s not a premium feature. Enabled\n",
1085                          __func__, __LINE__, child_proc[j].name[0]);
1086                 child_proc[j].proc_status = ENABLED;
1087             }
1088 
1089             /*Fill up the remaining arguments from configuration file*/
1090             LOC_LOGD("%s] Parsing Process_Arguments from Configuration: %s \n",
1091                       __func__, conf.proc_argument);
1092             if(0 != conf.proc_argument[0])
1093             {
1094                 /**************************************
1095                 ** conf_proc_argument is shared by all the programs getting launched,
1096                 ** hence copy to process specific argument string and parse the same.
1097                 ***************************************/
1098                 strlcpy(child_proc[j].argumentString, conf.proc_argument,
1099                         sizeof(child_proc[j].argumentString));
1100                 char *temp_args[LOC_PROCESS_MAX_NUM_ARGS];
1101                 memset (temp_args, 0, sizeof (temp_args));
1102                 loc_util_split_string(child_proc[j].argumentString, &temp_args[i],
1103                                       (LOC_PROCESS_MAX_NUM_ARGS - i), ' ');
1104                 // copy argument from the pointer to the memory
1105                 for (unsigned int index = i; index < LOC_PROCESS_MAX_NUM_ARGS; index++) {
1106                     if (temp_args[index] == NULL) {
1107                         break;
1108                     }
1109                     strlcpy (child_proc[j].args[index], temp_args[index],
1110                              sizeof (child_proc[j].args[index]));
1111                 }
1112             }
1113         }
1114         else {
1115             LOC_LOGD("%s:%d]: Process %s is disabled\n",
1116                      __func__, __LINE__, child_proc[j].name[0]);
1117         }
1118     }
1119 
1120 err:
1121     if (conf_fp) {
1122         fclose(conf_fp);
1123     }
1124     if (ret != 0) {
1125         LOC_LOGE("%s:%d]: ret: %d", __func__, __LINE__, ret);
1126         if (child_proc) {
1127             free (child_proc);
1128             child_proc = nullptr;
1129         }
1130         *process_count_ptr = 0;
1131         *process_info_table_ptr = nullptr;
1132 
1133     }
1134     else {
1135         *process_count_ptr = proc_list_length;
1136         *process_info_table_ptr = child_proc;
1137     }
1138 
1139     return ret;
1140 }
1141