• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_update_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 }
457 
458 /*=============================================================================
459  *
460  *   Define and Structures for Parsing Location Process Configuration File
461  *
462  *============================================================================*/
463 #define MAX_NUM_STRINGS   20
464 
465 //We can have 8 masks for now
466 #define CONFIG_MASK_TARGET_ALL           0X01
467 #define CONFIG_MASK_TARGET_FOUND         0X02
468 #define CONFIG_MASK_TARGET_CHECK         0X03
469 #define CONFIG_MASK_BASEBAND_ALL         0X04
470 #define CONFIG_MASK_BASEBAND_FOUND       0X08
471 #define CONFIG_MASK_BASEBAND_CHECK       0x0c
472 #define CONFIG_MASK_AUTOPLATFORM_ALL     0x10
473 #define CONFIG_MASK_AUTOPLATFORM_FOUND   0x20
474 #define CONFIG_MASK_AUTOPLATFORM_CHECK   0x30
475 #define CONFIG_MASK_SOCID_ALL            0x40
476 #define CONFIG_MASK_SOCID_FOUND          0x80
477 #define CONFIG_MASK_SOCID_CHECK          0xc0
478 
479 #define LOC_FEATURE_MASK_GTP_WIFI_BASIC            0x01
480 #define LOC_FEATURE_MASK_GTP_WIFI_PREMIUM          0X02
481 #define LOC_FEATURE_MASK_GTP_CELL_BASIC            0X04
482 #define LOC_FEATURE_MASK_GTP_CELL_PREMIUM          0X08
483 #define LOC_FEATURE_MASK_SAP_BASIC                 0x40
484 #define LOC_FEATURE_MASK_SAP_PREMIUM               0X80
485 #define LOC_FEATURE_MASK_GTP_WAA_BASIC             0X100
486 #define LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC      0X400
487 #define LOC_FEATURE_MASK_ODCPI                     0x1000
488 #define LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT     0x2000
489 #define LOC_FEATURE_MASK_SUPL_WIFI                 0x4000
490 #define LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO      0x8000
491 
492 typedef struct {
493     char proc_name[LOC_MAX_PARAM_STRING];
494     char proc_argument[LOC_MAX_PARAM_STRING];
495     char proc_status[LOC_MAX_PARAM_STRING];
496     char group_list[LOC_MAX_PARAM_STRING];
497     unsigned int premium_feature;
498     unsigned int loc_feature_mask;
499     char platform_list[LOC_MAX_PARAM_STRING];
500     char baseband[LOC_MAX_PARAM_STRING];
501     char low_ram_targets[LOC_MAX_PARAM_STRING];
502     char soc_id_list[LOC_MAX_PARAM_STRING];
503     unsigned int sglte_target;
504     char feature_gtp_mode[LOC_MAX_PARAM_STRING];
505     char feature_gtp_waa[LOC_MAX_PARAM_STRING];
506     char feature_sap[LOC_MAX_PARAM_STRING];
507     char feature_odcpi[LOC_MAX_PARAM_STRING];
508     char feature_free_wifi_scan_inject[LOC_MAX_PARAM_STRING];
509     char feature_supl_wifi[LOC_MAX_PARAM_STRING];
510     char feature_wifi_supplicant_info[LOC_MAX_PARAM_STRING];
511     char auto_platform[LOC_MAX_PARAM_STRING];
512     unsigned int vendor_enhanced_process;
513 } loc_launcher_conf;
514 
515 /* process configuration parameters */
516 static loc_launcher_conf conf;
517 
518 /* gps.conf Parameter spec table */
519 static const loc_param_s_type gps_conf_parameter_table[] = {
520     {"SGLTE_TARGET",        &conf.sglte_target,           NULL, 'n'},
521 };
522 
523 /* location feature conf, e.g.: izat.conf feature mode table*/
524 static const loc_param_s_type loc_feature_conf_table[] = {
525     {"GTP_MODE",              &conf.feature_gtp_mode,               NULL, 's'},
526     {"GTP_WAA",               &conf.feature_gtp_waa,                NULL, 's'},
527     {"SAP",                   &conf.feature_sap,                    NULL, 's'},
528     {"ODCPI",                 &conf.feature_odcpi,                  NULL, 's'},
529     {"FREE_WIFI_SCAN_INJECT", &conf.feature_free_wifi_scan_inject,  NULL, 's'},
530     {"SUPL_WIFI",             &conf.feature_supl_wifi,              NULL, 's'},
531     {"WIFI_SUPPLICANT_INFO",  &conf.feature_wifi_supplicant_info,   NULL, 's'},
532 };
533 
534 /* location process conf, e.g.: izat.conf Parameter spec table */
535 static const loc_param_s_type loc_process_conf_parameter_table[] = {
536     {"PROCESS_NAME",               &conf.proc_name,                NULL, 's'},
537     {"PROCESS_ARGUMENT",           &conf.proc_argument,            NULL, 's'},
538     {"PROCESS_STATE",              &conf.proc_status,              NULL, 's'},
539     {"PROCESS_GROUPS",             &conf.group_list,               NULL, 's'},
540     {"PREMIUM_FEATURE",            &conf.premium_feature,          NULL, 'n'},
541     {"IZAT_FEATURE_MASK",          &conf.loc_feature_mask,         NULL, 'n'},
542     {"PLATFORMS",                  &conf.platform_list,            NULL, 's'},
543     {"SOC_IDS",                    &conf.soc_id_list,            NULL, 's'},
544     {"BASEBAND",                   &conf.baseband,                 NULL, 's'},
545     {"LOW_RAM_TARGETS",            &conf.low_ram_targets,          NULL, 's'},
546     {"HARDWARE_TYPE",              &conf.auto_platform,            NULL, 's'},
547     {"VENDOR_ENHANCED_PROCESS",    &conf.vendor_enhanced_process,  NULL, 'n'},
548 };
549 
550 /*===========================================================================
551 FUNCTION loc_read_process_conf
552 
553 DESCRIPTION
554    Parse the specified conf file and return info for the processes defined.
555    The format of the file should conform with izat.conf.
556 
557 PARAMETERS:
558    conf_file_name: configuration file to read
559    process_count_ptr: pointer to store number of processes defined in the conf file.
560    process_info_table_ptr: pointer to store the process info table.
561 
562 DEPENDENCIES
563    The file must be in izat.conf format.
564 
565 RETURN VALUE
566    0: success
567    none-zero: failure
568 
569 SIDE EFFECTS
570    N/A
571 
572 NOTES:
573    On success, memory pointed by (*process_info_table_ptr) must be freed.
574 ===========================================================================*/
loc_read_process_conf(const char * conf_file_name,uint32_t * process_count_ptr,loc_process_info_s_type ** process_info_table_ptr)575 int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_ptr,
576                           loc_process_info_s_type** process_info_table_ptr) {
577     loc_process_info_s_type *child_proc = nullptr;
578     volatile int i=0;
579     unsigned int j=0;
580     gid_t gid_list[LOC_PROCESS_MAX_NUM_GROUPS];
581     char *split_strings[MAX_NUM_STRINGS];
582     int name_length=0, group_list_length=0, platform_length=0, baseband_length=0, ngroups=0, ret=0;
583     int auto_platform_length = 0, soc_id_list_length=0;
584     int group_index=0, nstrings=0, status_length=0;
585     FILE* conf_fp = nullptr;
586     char platform_name[PROPERTY_VALUE_MAX], baseband_name[PROPERTY_VALUE_MAX];
587     int low_ram_target=0;
588     char autoplatform_name[PROPERTY_VALUE_MAX], socid_value[PROPERTY_VALUE_MAX];
589     unsigned int loc_service_mask=0;
590     unsigned char config_mask = 0;
591     unsigned char proc_list_length=0;
592     int gtp_cell_ap_enabled = 0;
593     char arg_gtp_waa[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
594     char arg_gtp_modem_cell[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
595     char arg_gtp_wifi[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
596     char arg_sap[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
597     char arg_disabled[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_DISABLED;
598     char arg_basic[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_BASIC;
599     char arg_premium[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_PREMIUM;
600 
601     if (process_count_ptr == NULL || process_info_table_ptr == NULL) {
602         return -1;
603     }
604 
605     //Read gps.conf and fill parameter table
606     UTIL_READ_CONF(LOC_PATH_GPS_CONF, gps_conf_parameter_table);
607 
608     //Form argument strings
609     strlcat(arg_gtp_waa, LOC_FEATURE_GTP_WAA, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
610     strlcat(arg_gtp_modem_cell, LOC_FEATURE_GTP_MODEM_CELL, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
611     strlcat(arg_gtp_wifi, LOC_FEATURE_GTP_WIFI, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
612     strlcat(arg_sap, LOC_FEATURE_SAP, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
613 
614     //Get platform name from ro.board.platform property
615     loc_get_platform_name(platform_name, sizeof(platform_name));
616     //Get baseband name from ro.baseband property
617     loc_get_target_baseband(baseband_name, sizeof(baseband_name));
618     //Identify if this is an automotive platform
619     loc_get_auto_platform_name(autoplatform_name,sizeof(autoplatform_name));
620     //Identify if this is a low ram target from ro.config.low_ram property
621     low_ram_target = loc_identify_low_ram_target();
622     // Get the soc-id for this device.
623     loc_get_device_soc_id(socid_value, sizeof(socid_value));
624 
625     UTIL_READ_CONF(conf_file_name, loc_feature_conf_table);
626 
627     //Set service mask for GTP_MODE
628     if(strcmp(conf.feature_gtp_mode, "DISABLED") == 0) {
629         LOC_LOGD("%s:%d]: GTP MODE DISABLED", __func__, __LINE__);
630     }
631     else if(strcmp(conf.feature_gtp_mode, "LEGACY_WWAN") == 0) {
632         LOC_LOGD("%s:%d]: Setting GTP MODE to mode: LEGACY_WWAN", __func__, __LINE__);
633         loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC;
634     }
635     else if(strcmp(conf.feature_gtp_mode, "SDK") == 0) {
636         LOC_LOGD("%s:%d]: Setting GTP MODE to mode: SDK", __func__, __LINE__);
637         loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC;
638     }
639     //conf file has a garbage value
640     else {
641         LOC_LOGE("%s:%d]: Unrecognized value for GTP MODE Mode."\
642                  " Setting GTP WIFI to default mode: DISABLED", __func__, __LINE__);
643     }
644     //Set service mask for GTP_WAA
645     if(strcmp(conf.feature_gtp_waa, "BASIC") == 0) {
646       LOC_LOGD("%s:%d]: Setting GTP WAA to mode: BASIC", __func__, __LINE__);
647       loc_service_mask |= LOC_FEATURE_MASK_GTP_WAA_BASIC;
648     }
649     else if(strcmp(conf.feature_gtp_waa, "DISABLED") == 0) {
650       LOC_LOGD("%s:%d]: GTP WAA DISABLED", __func__, __LINE__);
651     }
652     //conf file has a garbage value
653     else {
654       LOC_LOGE("%s:%d]: Unrecognized value for GTP WAA Mode."\
655                " Setting GTP WAA to default mode: DISABLED", __func__, __LINE__);
656     }
657 
658     //Set service mask for SAP
659     if(strcmp(conf.feature_sap, "PREMIUM") == 0 ||
660        strcmp(conf.feature_sap, "PREMIUM_ENV_AIDING") == 0) {
661         LOC_LOGD("%s:%d]: Setting SAP to mode: PREMIUM", __func__, __LINE__);
662         loc_service_mask |= LOC_FEATURE_MASK_SAP_PREMIUM;
663     }
664     else if(strcmp(conf.feature_sap, "BASIC") == 0) {
665         LOC_LOGD("%s:%d]: Setting SAP to mode: BASIC", __func__, __LINE__);
666         loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
667     }
668     else if(strcmp(conf.feature_sap, "MODEM_DEFAULT") == 0) {
669         LOC_LOGD("%s:%d]: Setting SAP to mode: MODEM_DEFAULT", __func__, __LINE__);
670     }
671     else if(strcmp(conf.feature_sap, "DISABLED") == 0) {
672 #ifdef USE_GLIB
673         /* Enable slim_daemon even when SAP is set to DISABLED*/
674         loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
675 #else
676         LOC_LOGD("%s:%d]: Setting SAP to mode: DISABLED", __func__, __LINE__);
677 #endif
678     }
679     else {
680        LOC_LOGE("%s:%d]: Unrecognized value for SAP Mode."\
681                 " Setting SAP to default mode: BASIC", __func__, __LINE__);
682        loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
683     }
684 
685     // Set service mask for ODCPI
686     if(strcmp(conf.feature_odcpi, "BASIC") == 0) {
687         LOC_LOGD("%s:%d]: Setting ODCPI to mode: BASIC", __func__, __LINE__);
688         loc_service_mask |= LOC_FEATURE_MASK_ODCPI;
689     }
690     else if(strcmp(conf.feature_odcpi, "DISABLED") == 0) {
691         LOC_LOGD("%s:%d]: Setting ODCPI to mode: DISABLED", __func__, __LINE__);
692     }
693     else if(strcmp(conf.feature_odcpi, "PREMIUM") == 0) {
694         LOC_LOGD("%s:%d]: Unrecognized value for ODCPI mode."\
695             "Setting ODCPI to default mode: BASIC", __func__, __LINE__);
696         loc_service_mask |= LOC_FEATURE_MASK_ODCPI;
697     }
698 
699     // Set service mask for FREE_WIFI_SCAN_INJECT
700     if(strcmp(conf.feature_free_wifi_scan_inject, "BASIC") == 0) {
701         LOC_LOGD("%s:%d]: Setting FREE_WIFI_SCAN_INJECT to mode: BASIC", __func__, __LINE__);
702         loc_service_mask |= LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT;
703     }
704     else if(strcmp(conf.feature_free_wifi_scan_inject, "DISABLED") == 0) {
705         LOC_LOGD("%s:%d]: Setting FREE_WIFI_SCAN_INJECT to mode: DISABLED", __func__, __LINE__);
706     }
707     else if(strcmp(conf.feature_free_wifi_scan_inject, "PREMIUM") == 0) {
708         LOC_LOGD("%s:%d]: Unrecognized value for FREE_WIFI_SCAN_INJECT mode."\
709             "Setting FREE_WIFI_SCAN_INJECT to default mode: BASIC", __func__, __LINE__);
710         loc_service_mask |= LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT;
711     }
712 
713     // Set service mask for SUPL_WIFI
714     if(strcmp(conf.feature_supl_wifi, "BASIC") == 0) {
715         LOC_LOGD("%s:%d]: Setting SUPL_WIFI to mode: BASIC", __func__, __LINE__);
716         loc_service_mask |= LOC_FEATURE_MASK_SUPL_WIFI;
717     }
718     else if(strcmp(conf.feature_supl_wifi, "DISABLED") == 0) {
719         LOC_LOGD("%s:%d]: Setting SUPL_WIFI to mode: DISABLED", __func__, __LINE__);
720     }
721     else if(strcmp(conf.feature_supl_wifi, "PREMIUM") == 0) {
722         LOC_LOGD("%s:%d]: Unrecognized value for SUPL_WIFI mode."\
723             "Setting SUPL_WIFI to default mode: BASIC", __func__, __LINE__);
724         loc_service_mask |= LOC_FEATURE_MASK_SUPL_WIFI;
725     }
726 
727     // Set service mask for WIFI_SUPPLICANT_INFO
728     if(strcmp(conf.feature_wifi_supplicant_info, "BASIC") == 0) {
729         LOC_LOGD("%s:%d]: Setting WIFI_SUPPLICANT_INFO to mode: BASIC", __func__, __LINE__);
730         loc_service_mask |= LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO;
731     }
732     else if(strcmp(conf.feature_wifi_supplicant_info, "DISABLED") == 0) {
733         LOC_LOGD("%s:%d]: Setting WIFI_SUPPLICANT_INFO to mode: DISABLED", __func__, __LINE__);
734     }
735     else if(strcmp(conf.feature_wifi_supplicant_info, "PREMIUM") == 0) {
736         LOC_LOGD("%s:%d]: Unrecognized value for WIFI_SUPPLICANT_INFO mode."\
737             "Setting LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO to default mode: BASIC", __func__, __LINE__);
738         loc_service_mask |= LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO;
739     }
740 
741     LOC_LOGD("%s:%d]: loc_service_mask: %x\n", __func__, __LINE__, loc_service_mask);
742 
743     if((conf_fp = fopen(conf_file_name, "r")) == NULL) {
744         LOC_LOGE("%s:%d]: Error opening %s %s\n", __func__,
745                  __LINE__, conf_file_name, strerror(errno));
746         ret = -1;
747         goto err;
748     }
749 
750     //Parse through the file to find out how many processes are to be launched
751     proc_list_length = 0;
752     do {
753         conf.proc_name[0] = 0;
754         //Here note that the 3rd parameter is passed as 1.
755         //This is so that only the first parameter in the table which is "PROCESS_NAME"
756         //is read. We do not want to read the entire block of parameters at this time
757         //since we are only counting the number of processes to launch.
758         //Therefore, only counting the occurrences of PROCESS_NAME parameter
759         //should suffice
760         if(loc_read_conf_r(conf_fp, loc_process_conf_parameter_table, 1)) {
761             LOC_LOGE("%s:%d]: Unable to read conf file. Failing\n", __func__, __LINE__);
762             ret = -1;
763             goto err;
764         }
765         name_length=(int)strlen(conf.proc_name);
766         if(name_length) {
767             proc_list_length++;
768             LOC_LOGD("Process name:%s", conf.proc_name);
769         }
770     } while(name_length);
771     LOC_LOGD("Process cnt = %d", proc_list_length);
772 
773     child_proc = (loc_process_info_s_type *)calloc(proc_list_length, sizeof(loc_process_info_s_type));
774     if(child_proc == NULL) {
775         LOC_LOGE("%s:%d]: ERROR: Malloc returned NULL\n", __func__, __LINE__);
776         ret = -1;
777         goto err;
778     }
779 
780     //Move file descriptor to the beginning of the file
781     //so that the parameters can be read
782     rewind(conf_fp);
783 
784     for(j=0; j<proc_list_length; j++) {
785         //Set defaults for all the child process structs
786         child_proc[j].proc_status = DISABLED;
787         memset(child_proc[j].group_list, 0, sizeof(child_proc[j].group_list));
788         config_mask=0;
789         if(loc_read_conf_r(conf_fp, loc_process_conf_parameter_table,
790                            sizeof(loc_process_conf_parameter_table)/sizeof(loc_process_conf_parameter_table[0]))) {
791             LOC_LOGE("%s:%d]: Unable to read conf file. Failing\n", __func__, __LINE__);
792             ret = -1;
793             goto err;
794         }
795 
796         name_length=(int)strlen(conf.proc_name);
797         group_list_length=(int)strlen(conf.group_list);
798         platform_length = (int)strlen(conf.platform_list);
799         baseband_length = (int)strlen(conf.baseband);
800         status_length = (int)strlen(conf.proc_status);
801         auto_platform_length = (int)strlen(conf.auto_platform);
802         soc_id_list_length = (int)strlen(conf.soc_id_list);
803 
804         if(!name_length || !group_list_length || !platform_length ||
805            !baseband_length || !status_length || !auto_platform_length || !soc_id_list_length) {
806             LOC_LOGE("%s:%d]: Error: i: %d; One of the parameters not specified in conf file",
807                      __func__, __LINE__, i);
808             continue;
809         }
810 
811         if (!isVendorEnhanced() && (conf.vendor_enhanced_process != 0)) {
812             LOC_LOGD("%s:%d]: Process %s is disabled via vendor enhanced process check",
813                      __func__, __LINE__, conf.proc_name);
814             child_proc[j].proc_status = DISABLED_VIA_VENDOR_ENHANCED_CHECK;
815             continue;
816         }
817 
818         if(strcmp(conf.proc_status, "DISABLED") == 0) {
819             LOC_LOGD("%s:%d]: Process %s is disabled in conf file",
820                      __func__, __LINE__, conf.proc_name);
821             child_proc[j].proc_status = DISABLED_FROM_CONF;
822             continue;
823         }
824         else if(strcmp(conf.proc_status, "ENABLED") == 0) {
825             LOC_LOGD("%s:%d]: Process %s is enabled in conf file",
826                      __func__, __LINE__, conf.proc_name);
827         }
828 
829         //Since strlcpy copies length-1 characters, we add 1 to name_length
830         if((name_length+1) > LOC_MAX_PARAM_STRING) {
831             LOC_LOGE("%s:%d]: i: %d; Length of name parameter too long. Max length: %d",
832                      __func__, __LINE__, i, LOC_MAX_PARAM_STRING);
833             continue;
834         }
835         strlcpy(child_proc[j].name[0], conf.proc_name, sizeof (child_proc[j].name[0]));
836 
837         child_proc[j].num_groups = 0;
838         ngroups = loc_util_split_string(conf.group_list, split_strings, MAX_NUM_STRINGS, ' ');
839         for(i=0; i<ngroups; i++) {
840             struct group* grp = getgrnam(split_strings[i]);
841             if (grp) {
842                 child_proc[j].group_list[child_proc[j].num_groups] = grp->gr_gid;
843                 child_proc[j].num_groups++;
844                 LOC_LOGd("Group %s = %d", split_strings[i], grp->gr_gid);
845             }
846         }
847 
848         nstrings = loc_util_split_string(conf.platform_list, split_strings, MAX_NUM_STRINGS, ' ');
849         if(strcmp("all", split_strings[0]) == 0) {
850             if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
851                 LOC_LOGD("%s:%d]: Enabled for all targets\n", __func__, __LINE__);
852                 config_mask |= CONFIG_MASK_TARGET_ALL;
853             }
854             else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
855                 config_mask |= CONFIG_MASK_TARGET_FOUND;
856                 for (i=2; i<nstrings; i++) {
857                     if(strcmp(platform_name, split_strings[i]) == 0) {
858                         LOC_LOGD("%s:%d]: Disabled platform %s\n", __func__, __LINE__, platform_name);
859                         config_mask &= ~CONFIG_MASK_TARGET_FOUND;
860                         break;
861                     }
862                 }
863             }
864         }
865         else {
866             for(i=0; i<nstrings; i++) {
867                 if(strcmp(platform_name, split_strings[i]) == 0) {
868                     LOC_LOGD("%s:%d]: Matched platform: %s\n",
869                              __func__, __LINE__, split_strings[i]);
870                     config_mask |= CONFIG_MASK_TARGET_FOUND;
871                     break;
872                 }
873             }
874         }
875 
876         // SOC Id's check
877         nstrings = loc_util_split_string(conf.soc_id_list, split_strings, MAX_NUM_STRINGS, ' ');
878         if (strcmp("all", split_strings[0]) == 0) {
879             if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
880                 LOC_LOGd("Enabled for all SOC ids\n");
881                 config_mask |= CONFIG_MASK_SOCID_ALL;
882             }
883             else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
884                 config_mask |= CONFIG_MASK_SOCID_FOUND;
885                 for (i = 2; i < nstrings; i++) {
886                     if (strcmp(socid_value, split_strings[i]) == 0) {
887                         LOC_LOGd("Disabled for SOC id %s\n", socid_value);
888                         config_mask &= ~CONFIG_MASK_SOCID_FOUND;
889                         break;
890                     }
891                 }
892             }
893         }
894         else {
895             for (i = 0; i < nstrings; i++) {
896                 if (strcmp(socid_value, split_strings[i]) == 0) {
897                     LOC_LOGd("Matched SOC id : %s\n", split_strings[i]);
898                     config_mask |= CONFIG_MASK_SOCID_FOUND;
899                     break;
900                 }
901             }
902         }
903 
904         nstrings = loc_util_split_string(conf.baseband, split_strings, MAX_NUM_STRINGS, ' ');
905         if(strcmp("all", split_strings[0]) == 0) {
906             if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
907                 LOC_LOGD("%s:%d]: Enabled for all basebands\n", __func__, __LINE__);
908                 config_mask |= CONFIG_MASK_BASEBAND_ALL;
909             }
910             else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
911                 config_mask |= CONFIG_MASK_BASEBAND_FOUND;
912                 for (i=2; i<nstrings; i++) {
913                     if(strcmp(baseband_name, split_strings[i]) == 0) {
914                         LOC_LOGD("%s:%d]: Disabled band %s\n", __func__, __LINE__, baseband_name);
915                         config_mask &= ~CONFIG_MASK_BASEBAND_FOUND;
916                         break;
917                     }
918                 }
919             }
920         }
921         else {
922             for(i=0; i<nstrings; i++) {
923                 if(strcmp(baseband_name, split_strings[i]) == 0) {
924                     LOC_LOGD("%s:%d]: Matched baseband: %s\n",
925                              __func__, __LINE__, split_strings[i]);
926                     config_mask |= CONFIG_MASK_BASEBAND_FOUND;
927                     break;
928                 }
929                 //Since ro.baseband is not a reliable source for detecting sglte
930                 //the alternative is to read the SGLTE_TARGET parameter from gps.conf
931                 //this parameter is read into conf_sglte_target
932                 else if((strcmp("sglte", split_strings[i]) == 0 ) && conf.sglte_target) {
933                     LOC_LOGD("%s:%d]: Matched baseband SGLTE\n", __func__, __LINE__);
934                     config_mask |= CONFIG_MASK_BASEBAND_FOUND;
935                     break;
936                 }
937             }
938         }
939 
940         nstrings = loc_util_split_string(conf.auto_platform, split_strings, MAX_NUM_STRINGS, ' ');
941         if(strcmp("all", split_strings[0]) == 0) {
942             LOC_LOGD("%s:%d]: Enabled for all auto platforms\n", __func__, __LINE__);
943             config_mask |= CONFIG_MASK_AUTOPLATFORM_ALL;
944         }
945         else {
946             for(i=0; i<nstrings; i++) {
947                 if(strcmp(autoplatform_name, split_strings[i]) == 0) {
948                     LOC_LOGD("%s:%d]: Matched auto platform: %s\n",
949                              __func__, __LINE__, split_strings[i]);
950                     config_mask |= CONFIG_MASK_AUTOPLATFORM_FOUND;
951                     break;
952                 }
953             }
954         }
955 
956         nstrings = loc_util_split_string(conf.low_ram_targets, split_strings, MAX_NUM_STRINGS, ' ');
957         if (!strcmp("DISABLED", split_strings[0]) && low_ram_target) {
958             LOC_LOGd("Disabled for low ram targets\n");
959             child_proc[j].proc_status = DISABLED;
960             continue;
961         }
962 
963         if((config_mask & CONFIG_MASK_TARGET_CHECK) &&
964            (config_mask & CONFIG_MASK_BASEBAND_CHECK) &&
965            (config_mask & CONFIG_MASK_AUTOPLATFORM_CHECK) &&
966            (config_mask & CONFIG_MASK_SOCID_CHECK) &&
967            (child_proc[j].proc_status != DISABLED_FROM_CONF) &&
968            (child_proc[j].proc_status != DISABLED_VIA_VENDOR_ENHANCED_CHECK)) {
969 
970             //Set args
971             //The first argument passed through argv is usually the name of the
972             //binary when started from commandline.
973             //getopt() seems to ignore this first argument and hence we assign it
974             //to the process name for consistency with command line args
975             i = 0;
976             char* temp_arg = ('/' == child_proc[j].name[0][0]) ?
977                 (strrchr(child_proc[j].name[0], '/') + 1) : child_proc[j].name[0];
978             strlcpy (child_proc[j].args[i++], temp_arg, sizeof (child_proc[j].args[0]));
979 
980             if(conf.premium_feature) {
981                if(conf.loc_feature_mask & loc_service_mask) {
982                     LOC_LOGD("%s:%d]: Enabled. %s has service mask: %x\n",
983                              __func__, __LINE__, child_proc[j].name[0], conf.loc_feature_mask);
984                     child_proc[j].proc_status = ENABLED;
985 
986                     if(conf.loc_feature_mask &
987                        (LOC_FEATURE_MASK_GTP_WIFI_BASIC | LOC_FEATURE_MASK_GTP_WIFI_PREMIUM)) {
988                         if(loc_service_mask & LOC_FEATURE_MASK_GTP_WIFI_BASIC) {
989                             strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
990                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
991                             strlcpy(child_proc[j].args[i++], arg_basic,
992                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
993                         }
994                         else if(loc_service_mask & LOC_FEATURE_MASK_GTP_WIFI_PREMIUM) {
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_premium,
998                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
999                         }
1000                         else
1001                         {
1002                             strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
1003                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1004                             strlcpy(child_proc[j].args[i++], arg_disabled,
1005                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1006                         }
1007                     }
1008                     if(conf.loc_feature_mask &
1009                        (LOC_FEATURE_MASK_GTP_CELL_BASIC | LOC_FEATURE_MASK_GTP_CELL_PREMIUM )) {
1010                         if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC) {
1011                             strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell,
1012                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1013                             strlcpy(child_proc[j].args[i++], arg_basic,
1014                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1015                         }
1016                         else {
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_disabled,
1020                                      LOC_PROCESS_MAX_ARG_STR_LENGTH);
1021                        }
1022                     }
1023                     if(conf.loc_feature_mask &
1024                        (LOC_FEATURE_MASK_SAP_BASIC | LOC_FEATURE_MASK_SAP_PREMIUM)) {
1025                         if(loc_service_mask & LOC_FEATURE_MASK_SAP_BASIC) {
1026                             strlcpy(child_proc[j].args[i++], arg_sap,
1027                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1028                             strlcpy(child_proc[j].args[i++], arg_basic,
1029                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1030                         }
1031                         else if(loc_service_mask & LOC_FEATURE_MASK_SAP_PREMIUM) {
1032                             strlcpy(child_proc[j].args[i++], arg_sap,
1033                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1034                             strlcpy(child_proc[j].args[i++], arg_premium,
1035                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1036                         }
1037                         else
1038                         {
1039                             strlcpy(child_proc[j].args[i++], arg_sap,
1040                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1041                             strlcpy(child_proc[j].args[i++], arg_disabled,
1042                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
1043                         }
1044                     }
1045 
1046                     if(conf.loc_feature_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) {
1047                       if(loc_service_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) {
1048                         strlcpy(child_proc[j].args[i++], arg_gtp_waa,
1049                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
1050                         strlcpy(child_proc[j].args[i++], arg_basic,
1051                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
1052                       }
1053                       else
1054                       {
1055                         strlcpy(child_proc[j].args[i++], arg_gtp_waa,
1056                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
1057                         strlcpy(child_proc[j].args[i++], arg_disabled,
1058                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
1059                       }
1060                     }
1061                     IF_LOC_LOGD {
1062                         LOC_LOGD("%s:%d]: %s args\n", __func__, __LINE__, child_proc[j].name[0]);
1063                         for(unsigned int k=0; k<LOC_PROCESS_MAX_NUM_ARGS; k++) {
1064                             if(child_proc[j].args[k][0] != '\0') {
1065                                 LOC_LOGD("%s:%d]: k: %d, %s\n", __func__, __LINE__, k,
1066                                          child_proc[j].args[k]);
1067                             }
1068                         }
1069                         LOC_LOGD("%s:%d]: \n", __func__, __LINE__);
1070                     }
1071                 }
1072                 else {
1073                     LOC_LOGD("%s:%d]: Disabled. %s has service mask:  %x \n",
1074                              __func__, __LINE__, child_proc[j].name[0], conf.loc_feature_mask);
1075                 }
1076             }
1077             else {
1078                 LOC_LOGD("%s:%d]: %s not a premium feature. Enabled\n",
1079                          __func__, __LINE__, child_proc[j].name[0]);
1080                 child_proc[j].proc_status = ENABLED;
1081             }
1082 
1083             /*Fill up the remaining arguments from configuration file*/
1084             LOC_LOGD("%s] Parsing Process_Arguments from Configuration: %s \n",
1085                       __func__, conf.proc_argument);
1086             if(0 != conf.proc_argument[0])
1087             {
1088                 /**************************************
1089                 ** conf_proc_argument is shared by all the programs getting launched,
1090                 ** hence copy to process specific argument string and parse the same.
1091                 ***************************************/
1092                 strlcpy(child_proc[j].argumentString, conf.proc_argument,
1093                         sizeof(child_proc[j].argumentString));
1094                 char *temp_args[LOC_PROCESS_MAX_NUM_ARGS];
1095                 memset (temp_args, 0, sizeof (temp_args));
1096                 loc_util_split_string(child_proc[j].argumentString, &temp_args[i],
1097                                       (LOC_PROCESS_MAX_NUM_ARGS - i), ' ');
1098                 // copy argument from the pointer to the memory
1099                 for (unsigned int index = i; index < LOC_PROCESS_MAX_NUM_ARGS; index++) {
1100                     if (temp_args[index] == NULL) {
1101                         break;
1102                     }
1103                     strlcpy (child_proc[j].args[index], temp_args[index],
1104                              sizeof (child_proc[j].args[index]));
1105                 }
1106             }
1107         }
1108         else {
1109             LOC_LOGD("%s:%d]: Process %s is disabled\n",
1110                      __func__, __LINE__, child_proc[j].name[0]);
1111         }
1112     }
1113 
1114 err:
1115     if (conf_fp) {
1116         fclose(conf_fp);
1117     }
1118     if (ret != 0) {
1119         LOC_LOGE("%s:%d]: ret: %d", __func__, __LINE__, ret);
1120         if (child_proc) {
1121             free (child_proc);
1122             child_proc = nullptr;
1123         }
1124         *process_count_ptr = 0;
1125         *process_info_table_ptr = nullptr;
1126 
1127     }
1128     else {
1129         *process_count_ptr = proc_list_length;
1130         *process_info_table_ptr = child_proc;
1131     }
1132 
1133     return ret;
1134 }
1135