blob: e344cb71f928adae0cf833c88579c4c204f6fd54 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#include <errno.h>
2#include <stdio.h>
3#include <string.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <time.h>
7#include <sys/sysinfo.h>
8#include <sys/stat.h>
9#include <cutils/properties.h>
10
11#include <paths_defs.h>
12#include <limits.h>
13#include "ml_utils.h"
14#include "hawk_lib.h"
15#include "hawk_api.h"
16#include "hawk_sender.h"
17#include "hawk_rild.h"
18
19/* Global variables */
20struct hawk_object g_hawk;
21char hawk_dir[512];
22char hawk_mount[256];
23/*hawk_lib internal veriables*/
24
25/*connection type from Eshel to Tablet default to adb*/ ;
26static struct hawk_host_apis g_host_apis;
27
28unsigned long hawk_uptime(void)
29{
30 struct sysinfo info;
31 info.uptime = 0;
32 sysinfo(&info);
33 return info.uptime;
34}
35
36void hawk_set_timestamp(void)
37{
38 struct timeval tv;
39 struct tm result;
40 size_t n;
41 time_t curtime;
42 char str[50 + 50 + 1];
43
44 memset(&tv, 0, sizeof(tv));
45 memset(&result, 0, sizeof(result));
46 gettimeofday(&tv, NULL);
47 curtime = tv.tv_sec;
48
49 n = strftime(str, 50, "[%H:%M:%S]", localtime_r(&curtime, &result));
50 snprintf(str + n, 50, "[%08lu.00]", hawk_uptime());
51 pthread_mutex_lock(&g_hawk.general_mutex);
52 ml_str2file(HAWK_UPTIME_FILE, str, strlen(str) + 1);
53 pthread_mutex_unlock(&g_hawk.general_mutex);
54}
55
56int hawk_get_current_mcc()
57{
58 return ml_get_property(HAWK_PROP_MCC);
59}
60
61int hawk_get_last_cell_location(int *mnc, int *mcc)
62{
63 static char buf[64];
64
65 if (ml_file2str(HAWK_CELL_INFO_FILE,buf,sizeof(buf),0)==NULL)
66 return 0;
67 if ((sscanf(buf,"%d;%d", mnc, mcc))==2)
68 return 1;
69 return 0;
70}
71
72/**
73 * void hawk_save_cell_info(const char* mcc, const char* mnc)
74 *
75 * Save network location in HAWK_CELL_INFO_FILE to be used in event data
76 * note: we use the file for all events, to avoid unneeded access to CP
77 *
78 * @param mnc - input - the mobile network code.
79 * mcc - input - the mobile contry code.
80 * lac - input - location area code.
81 * cid - input - cell ID.
82 * @author Yaniv Yizhak
83 * @version 1.0
84 */
85void hawk_save_cell_info(const char* mcc, const char* mnc)
86{
87 char str[64];
88 ENTER;
89 /* Set the mrvl.hawk.mcc for the selection of the server */
90 property_set(HAWK_PROP_MCC, mcc);
91 snprintf(str, sizeof(str), "%s;%s;", mnc, mcc);
92 pthread_mutex_lock(&g_hawk.general_mutex);
93 ml_str2file(HAWK_CELL_INFO_FILE, str, strlen(str) + 1);
94 pthread_mutex_unlock(&g_hawk.general_mutex);
95}
96
97/* lib API functions */
98/**
99 * hawk_lib_init
100 * This is the init function for the hawk librery.
101 * this function does all the internal initialisation and setup
102 * function must be called prior to using any hawk lib function.
103 *
104 * @param connection_type - mode of comunication with the hawk sender
105 * @return 0 for success, none zero value for faile
106 */
107int hawk_lib_init(enum hawk_host_connection_type connection_type)
108{
109 int rc = 1;
110 int retries = 16;
111 char *imei_str = NULL;
112 struct ml_imei imei;
113 char *cpver_str = NULL;
114 struct ml_cp_ver cpver;
115 int mcc = 0;
116 char error_info[32];
117
118 if (!hawk_set_log_dir()){
119 ml_log_error("Can't set log dir");
120 strncpy(error_info, "set_log_dir_failed", sizeof(error_info));
121 goto out_assert;
122 }
123
124 hawk_set_host_connection_type(connection_type);
125
126 if(!hawk_rild_register()) {
127 strncpy(error_info, "rild_register_failed", sizeof(error_info));
128 goto out_assert;
129 }
130
131 g_hawk.rild_init_done = 0;
132 imei_str = ml_get_imei(&imei);
133 cpver_str = ml_get_cp_ver(&cpver);
134 mcc = hawk_get_current_mcc();
135 retries = 16;
136
137 while (!imei_str || !cpver_str || !mcc) {
138
139 if (!imei_str)
140 hawk_rild_get_imei();
141
142 if (!cpver_str)
143 ml_extract_cp_from_full_vers();
144
145 if (!mcc)
146 hawk_rild_get_imsi();
147
148 imei_str = ml_get_imei(&imei);
149 cpver_str = ml_get_cp_ver(&cpver);
150 mcc = hawk_get_current_mcc();
151
152 if (imei_str && cpver_str && mcc)
153 break;
154
155 sleep(5);
156 if (retries--)
157 continue;
158
159 ml_log_error("Unable to get IMEI, IMSI or CP version\n");
160 strncpy(error_info, "imei_cp_imsi_failed", sizeof(error_info));
161 goto out_assert;
162 }
163
164 ml_log_debug("IMEI = %s, MCC = %d, CP_VER = %s", imei_str, mcc, cpver_str);
165 if(!hawk_rild_ena_indications()) {
166 strncpy(error_info, "rild_indications_failed", sizeof(error_info));
167 goto out_assert;
168 }
169
170 hawk_rild_get_rat();
171
172 g_hawk.rild_init_done = 1;
173 return rc;
174
175out_assert:
176 {
177 char assert_cmd[64];
178 sprintf(assert_cmd, "eeh -T panic hawk_%s", error_info);
179 ml_system_retry(1, 30, assert_cmd);
180 }
181 exit(1);
182}
183
184/**
185 * hawk_set_host_connection_type
186 *
187 * @param new_type the new connection mode to be used;
188 */
189void hawk_set_host_connection_type(enum hawk_host_connection_type new_type)
190{
191 char type[32];
192 switch (new_type) {
193#ifdef HAWK_ADB
194 case HAWK_HOST_CONNECTION_TYPE_ADB:
195 hawk_adb_get_host_api(&g_host_apis);
196 snprintf(type, sizeof(type), "ADB");
197 break;
198#endif
199 case HAWK_HOST_CONNECTION_TYPE_STANDALONE:
200 hawk_sender_get_host_api(&g_host_apis);
201 snprintf(type, sizeof(type), "STANDALONE");
202 break;
203 default:
204 ml_log_error("hawk: error unknown connection type %d\n", new_type);
205 ml_system_retry(1, 30, "eeh -T panic hawk_unknown_connection_type");
206 exit(1);
207 }
208 ml_log_debug("hawk: host connection type was changed to %s\n", type);
209}
210
211/**
212 * void hawk_send_event_report(struct hawk_event_report)
213 * This function is used to send report in an hawk event
214 * to the host application (hawk sender). this indecates that an event
215 * is in progress and/or that new logs are ready to be sent.
216 * the function send based on host_connection type
217 *
218 * @param report_info a structure containing the report information
219 */
220void hawk_send_event_report(struct hawk_event_report *report_info)
221{
222 if (g_host_apis.send_event_report_fptr)
223 g_host_apis.send_event_report_fptr(report_info);
224 else
225 ml_log_error("hawk: can't sent event to host, no function defined\n");
226}
227
228/**
229 * hawk_send_keep_alive_event
230 *
231 * this function create a new event (keep alive)
232 * and adds it to the hawk message Q
233 */
234void hawk_send_keep_alive_event(void)
235{
236 struct hawk_msg *msg = NULL;
237 msg = hawk_alloc_msg();
238 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_KEEP_ALIVE);
239 def_vtype_upstr(msg->msg_info.status, HAWK_STATUS_LOGS_READY);
240 snprintf(msg->msg_info.description, sizeof(msg->msg_info.description), "Keep alive event");
241 def_vtype_upstr(msg->msg_info.initiator, HAWK_INITIATOR_AUX);
242 hawk_add_msg(msg);
243}
244
245/**
246 * hawk_str_to_msg
247 * This function does the translation of fifo message string and returns
248 * hawk message allocated and filled with the event info
249 * it is the responsibility of the caller to free the returned message.
250 *
251 * @param fifo_message a string of ASCII chars containing the message.
252 * @return hawk_msg allocated and valid hawk messege. NULL is returned in case of error.
253 */
254struct hawk_msg *hawk_str_to_msg(const char *fifo_message)
255{
256 struct hawk_msg *msg = NULL;
257 int argc;
258 char sender[128], command[128], param3[128], param4[128];
259
260 memset(param3, 0, sizeof(param3));
261 memset(param4, 0, sizeof(param4));
262
263 ml_log_debug("Recieved msg: %s", fifo_message);
264 //try to read all 4 and check return value for real number of parameters
265 argc = sscanf(fifo_message, "%128s %128s %128s %128[^\n]", sender, command, param3, param4);
266 if (argc < 2 || argc > 4) { /*error in input string */
267 ml_log_error("failed to parse fifo message '%s' error %d\n", fifo_message, argc);
268 return NULL;
269 }
270 msg = hawk_alloc_msg();
271 if (strcmp("eeh", sender) == 0) { /*this is a message from EEH */
272 def_vtype_upstr(msg->msg_info.initiator, HAWK_INITIATOR_AUX);
273 if (strcmp("boot", command) == 0) {
274 snprintf(msg->msg_info.description, sizeof(msg->msg_info.description), "Boot message");
275 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_BOOT_DONE);
276 def_vtype_upstr(msg->msg_info.status, HAWK_STATUS_LOGS_READY);
277 } else if (strcmp("assert_notify", command) == 0) {
278 snprintf(msg->msg_info.description, sizeof(msg->msg_info.description), "Assert in progress");
279 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_ASSERT);
280 def_vtype_upstr(msg->msg_info.status, HAWK_STATUS_IN_PROGRESS);
281 } else if (strcmp("assert_ready", command) == 0) {
282 if (argc != 3)
283 goto exit_error;
284 snprintf(msg->msg_info.description, sizeof(msg->msg_info.description), "Assert done");
285 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_ASSERT);
286 def_vtype_upstr(msg->msg_info.status, HAWK_STATUS_LOGS_READY);
287 snprintf(msg->msg_info.event_id, sizeof(msg->msg_info.event_id), "%s", param3);
288 } else if (strcmp("assert_detected", command) == 0) {
289 if (argc != 3)
290 goto exit_error;
291 hawk_create_file(atoi(param3));
292 snprintf(msg->msg_info.description, sizeof(msg->msg_info.description), "Assert detected");
293 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_ASSERT_DETECTED);
294 def_vtype_upstr(msg->msg_info.status, HAWK_STATUS_IN_PROGRESS);
295 } else if (strcmp("sr_notify", command) == 0) {
296 snprintf(msg->msg_info.description, sizeof(msg->msg_info.description),
297 "silent reset in progress");
298 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_SILENT_RESET);
299 def_vtype_upstr(msg->msg_info.status, HAWK_STATUS_IN_PROGRESS);
300 } else if (strcmp("sr_ready", command) == 0) {
301 if (argc != 3)
302 goto exit_error;
303 snprintf(msg->msg_info.description, sizeof(msg->msg_info.description), "Silent reset done");
304 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_SILENT_RESET);
305 def_vtype_upstr(msg->msg_info.status, HAWK_STATUS_LOGS_READY);
306 msg->msg_info.include_sd_log = 1;
307 snprintf(msg->msg_info.event_id, sizeof(msg->msg_info.event_id), "%s", param3);
308 } else if (strcmp("mtsd_ok", command) == 0) {
309 snprintf(msg->msg_info.description, sizeof(msg->msg_info.description), "MTSD online");
310 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_MTSD_ONLINE);
311 def_vtype_upstr(msg->msg_info.status, HAWK_STATUS_LOGS_READY);
312 msg->msg_info.include_sd_log = 1;
313 } else {
314 ml_log_error("unknown command error\n");
315 goto exit_error;
316 }
317 } else if (strcmp("host", sender) == 0) { /*tablet application message */
318 def_vtype_upstr(msg->msg_info.initiator, HAWK_INITIATOR_HOST);
319 def_vtype_upstr(msg->msg_info.status, HAWK_STATUS_HOST_COMMAND);
320 if (strcmp("do_keep_alive", command) == 0) {
321 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_KEEP_ALIVE);
322 } else if (strcmp("do_assert", command) == 0) {
323 if (argc != 3)
324 goto exit_error;
325 if (strcmp("comm", param3) == 0)
326 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_FORCE_CP_ASSERT);
327 else
328 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_FORCE_AP_ASSERT);
329 } else if (strcmp("do_reset", command) == 0) {
330 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_FORCE_RESET);
331 } else if (strcmp("do_fota", command) == 0) {
332 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_FOTA);
333 } else { /*unknown command */
334 ml_log_error("unknown command error\n");
335 goto exit_error;
336 }
337 } else { /*unknown sender */
338 ml_log_error("unknown sender error\n");
339 goto exit_error;
340 }
341 return msg;
342exit_error:
343 ml_log_error("%s error: argc = %d, sender %s, command %s, param3 %s, param4 %s\n",
344 __func__, argc, sender, command, param3, param4);
345 free(msg);
346 return NULL;
347}
348
349/**
350 * hawk_exceute_host_command
351 * This function excecutes commands recived from HOST application
352 *
353 * @param report_info the message from host to exceute.
354 */
355void hawk_execute_host_command(struct hawk_event_report *report_info)
356{
357 switch (report_info->event_type) {
358 case HAWK_EVENT_FORCE_CP_ASSERT:
359 ml_system_retry(1, 30, "eeh -T CPASSERT");
360 break;
361 case HAWK_EVENT_FORCE_AP_ASSERT:
362 ml_system_retry(1, 30, "eeh -T panic");
363 break;
364 case HAWK_EVENT_FORCE_RESET:
365 ml_reboot_service(0, 0, NULL);
366 break;
367 case HAWK_EVENT_KEEP_ALIVE:
368 hawk_send_keep_alive_event();
369 break;
370 case HAWK_EVENT_FOTA:
371 ml_system_retry(1, ML_SYSTEM_MAX_TIMEOUT, HAWK_SENDER_FOTA_COMMAND);
372 break;
373 default:
374 ml_log_error("hawk: host command type unknown\n");
375 }
376}
377
378/*hawk message Q functions*/
379
380/**
381 * hawk_add_msg
382 * This function adds a new message to the end of the messages q of hawk
383 * message should be allocated using hawk_alloc_msg function.
384 *
385 * @see hawk_alloc_msg
386 * @param msg the message to add to the message Q
387 */
388void hawk_add_msg(struct hawk_msg *msg)
389{
390 /* Add message to queue */
391 pthread_mutex_lock(&g_hawk.cond_mutex);
392
393 list_add_tail(&msg->list, &g_hawk.msgq_head);
394 g_hawk.q_item_count++;
395 pthread_cond_signal(&g_hawk.cond);
396 pthread_mutex_unlock(&g_hawk.cond_mutex);
397}
398
399/**
400 * hawk_alloc_msg
401 * This function allocates a new message buffer, and inits the message list
402 *
403 * @return msg the message to add to the message Q
404 */
405struct hawk_msg *hawk_alloc_msg(void)
406{
407 struct hawk_msg *msg;
408
409 msg = calloc(1, sizeof(*msg));
410 if (!msg) {
411 ml_log_error("OOM '%s'\n", strerror(errno));
412 ml_system_retry(1, 30, "eeh -T panic hawk_alloc_msg_OOM");
413 exit(1);
414 }
415 INIT_LIST_HEAD(&msg->list);
416 return msg;
417}
418
419/**
420 * get_logs_free_space
421 * This function checks free space in hawk logs dedicated directory,
422 * considering max size limit
423 *
424 * @return free size number
425 */
426unsigned long long get_logs_free_space(void)
427{
428 unsigned long long logs_size_limit;
429 unsigned long long logs_dir_size;
430
431 if (!ml_dir_update(hawk_dir))
432 return 0;
433
434 //Check if logs free space is limited
435 logs_size_limit = ml_get_ulong_long_property("ro.mrvl.hawk.logs.max_size");
436 if (logs_size_limit == 0) //if limit is set to 0 -> no limit, return MAX size
437 return ULLONG_MAX;
438
439 logs_dir_size = ml_get_dir_size(hawk_dir);
440 ml_log_debug("%s size=%llu\n", hawk_dir, logs_dir_size);
441
442 if (logs_size_limit < logs_dir_size)
443 return 0; //no space left
444
445 return (logs_size_limit - logs_dir_size); //calculate size
446}
447
448/**
449 * hawk_set_log_dir
450 * This function sets full path to hawk logs dedicated directory
451 * to a global variable hawk_dir
452 */
453int hawk_set_log_dir(void)
454{
455 char local_path[256];
456 property_get("ro.hawk.logs.mount_point", hawk_mount, SDCARD_MOUNT);
457 property_get("ro.hawk.logs.local_path", local_path, "ut_logs");
458 snprintf(hawk_dir, sizeof(hawk_dir) - 1, "%s%s", hawk_mount, local_path);
459 if (!ml_check_path(hawk_mount, 1, 1))
460 return 0;
461
462 return ml_dir_update(hawk_dir);
463}
464
465#ifdef HAWK_ADB
466/*Hezi - hawkHostIP is defined in hawk_adb.c*/
467extern char hawkHostIP[32];
468
469static int hawk_get_battery_info(struct hawk_battery_info *info)
470{
471 char tbuf[64] = { 0 };
472 struct stat buf;
473 static int battery_supported = 1;
474 int vbut_reads = 0;
475
476 if (!battery_supported)
477 return -1;
478
479 if (battery_supported == 1 && stat("/sys/class/power_supply/battery/capacity", &buf) != 0) {
480 ml_log_error("Battery capacity & status unsupported\n");
481 battery_supported = 0;
482 return -1;
483 }
484 battery_supported = 2;
485
486 memset(info->status, 0, sizeof(info->status));
487
488 if (ml_file2str("/sys/class/power_supply/battery/capacity", tbuf, sizeof(tbuf), 0) == NULL)
489 return -1;
490
491 info->capacity = atoi(tbuf);
492
493 if (ml_file2str("/sys/class/power_supply/battery/status", info->status, sizeof(info->status), 0) == NULL)
494 return -1;
495 ml_chomp(info->status);
496
497 do {
498 if (vbut_reads++) {
499 ml_log_error("Retry VBUT read - seems we have low voltage. (%d / %d)", info->voltage_now,
500 HAWK_HALT_ON_LOW_VOLTAGE);
501 sleep(1);
502 }
503 if (ml_file2str("/sys/class/power_supply/battery/voltage_now", tbuf, sizeof(tbuf), 0) == NULL)
504 return -1;
505
506 info->voltage_now = atoi(tbuf);
507
508 } while (info->voltage_now < HAWK_HALT_ON_LOW_VOLTAGE && vbut_reads < 4);
509
510 return 0;
511}
512
513/**
514 * hawk_send_battery_status
515 * this function sends battery indication to the host
516 *
517 * @author Chen Reichbach
518 * @version 1.1
519 */
520static void hawk_send_battery_status(void)
521{
522 struct hawk_battery_info info;
523
524 if (hawk_get_battery_info(&info) != 0)
525 return;
526
527 ml_log_error("battery capacity %d voltage %d\n", info.capacity, info.voltage_now);
528 if (info.voltage_now < HAWK_HALT_ON_LOW_VOLTAGE) {
529 char command[1024];
530 ml_log_error("battery voltage too low (capacity %d, voltage %d < %d). halt.\n",
531 info.capacity, info.voltage_now, HAWK_HALT_ON_LOW_VOLTAGE);
532 memset(command, 0, sizeof(command));
533 snprintf(command, sizeof(command), "ping -c 1 -W 1 -w 1 %s", hawkHostIP);
534 if (0 != ml_system_retry(2, 30, command)) {
535 ml_log_error("HALT due to low voltage and peer that not responding.\n");
536 sleep(1);
537 ml_reboot_service(0, 0, NULL);
538 } else {
539 ml_log_error("voltage low but TABLET still responding. continue.\n");
540 }
541 }
542
543 if (g_host_apis.send_battery_status_fptr)
544 g_host_apis.send_battery_status_fptr(&info);
545 else
546 ml_log_error("hawk: failed to sent battery update, no fuction defined\n");
547}
548
549/**
550 * Prepare and send event with battery status/ capacity info
551 * If battery not supported - it does nothing.
552 */
553void hawk_send_battery_event(void)
554{
555 struct hawk_msg *msg = hawk_alloc_msg();
556
557 def_vtype_upstr(msg->msg_info.initiator, HAWK_INITIATOR_AUX);
558 def_vtype_upstr(msg->msg_info.event_type, HAWK_EVENT_BATTERY_STATUS);
559 def_vtype_upstr(msg->msg_info.status, HAWK_STATUS_HOST_COMMAND);
560 snprintf(msg->msg_info.description, sizeof(msg->msg_info.description), "Battery status");
561
562 hawk_add_msg(msg);
563}
564#endif