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