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