blob: 10ba0f0157309a78aa022c81a976d8497f6e7e58 [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 <pthread.h>
8#include <sys/sysinfo.h>
9#include <sys/prctl.h>
10#include <cutils/properties.h>
11
12#include "hawk_lib.h"
13#include "hawk_api.h"
14#include "hawk_sender.h"
15#include "hawk_statistics.h"
16#include "hawk_rild.h"
17
18#define HAWK_TIMESTAMP_DELTA 120 /* time in seconds between time from boot update */
19#define HAWK_FIFO_TIMEOUT (60*60*12) /* time in seconds (12 hours) */
20#define HAWK_STARTUP TEL_DIR "hawk_startup.sh"
21#define HAWK_CHECK_DATA TEL_DIR "hawk_check_data.sh"
22#define HAWK_CHECK_DATA_DELTA (60*60) /* time in seconds (1 hour) */
23
24extern struct hawk_object g_hawk;
25extern struct ml_fifo fifo;
26
27static __attribute__ ((noreturn))
28void *hawk_worker( __attribute__ ((unused))
29 void *ptr)
30{
31 struct hawk_msg *msg = NULL;
32
33 prctl(PR_SET_NAME, "hawk_worker");
34
35 while (1) {
36 /* pthread_cond_wait will first unlock and then lock the mutex */
37 pthread_mutex_lock(&g_hawk.cond_mutex);
38 while (list_empty(&g_hawk.msgq_head)) {
39 pthread_cond_wait(&g_hawk.cond, &g_hawk.cond_mutex);
40 }
41 msg = list_entry(g_hawk.msgq_head.next, struct hawk_msg, list);
42 list_del_init(g_hawk.msgq_head.next);
43 g_hawk.q_item_count--;
44 pthread_mutex_unlock(&g_hawk.cond_mutex);
45
46 if (msg == NULL)
47 continue;
48
49 sprintf(msg->msg_info.event_dir, "%s/hawk_default_dir", hawk_dir);
50
51 /*check and update missed messages */
52 hawk_mark_messages_as_offline();
53 /* process message and release the buffer */
54 switch (msg->msg_info.status) {
55 case HAWK_STATUS_LOGS_READY:
56 {
57 ///
58 /// ADD LOGS + HAWK_SPY
59 ///
60 unsigned long long free_space;
61
62 if (msg->msg_info.event_id[0] == 0) {
63 struct ml_uniqid uid;
64 sprintf(msg->msg_info.event_id, "%s", ml_get_uniqid(&uid));
65 }
66
67 sprintf(msg->msg_info.event_dir, "%s/%s", hawk_dir, msg->msg_info.event_id);
68 if (!ml_dir_update(hawk_dir))
69 break;
70 if (!ml_dir_update(msg->msg_info.event_dir))
71 break;
72 if (msg->msg_info.event_type == HAWK_EVENT_ASSERT ||
73 msg->msg_info.event_type == HAWK_EVENT_SILENT_RESET) {
74 hawk_update_assert_description(msg);
75 }
76 // 1. check if we have limit on housing space
77 // 1.1 check free space in the housing space
78 free_space = get_logs_free_space();
79 // 1.2 if free space bigger then 100K
80 if (free_space > HAWK_FILE_SIZE) {
81 hawk_spy_file(msg);
82 free_space -= HAWK_FILE_SIZE;
83 }
84 // 1.3 if free space bigger then 500K
85 if (msg->msg_info.include_dmesg_log == 1 && (free_space > HAWK_FILE_SIZE)) {
86 hawk_save_dmesg_file(msg);
87 free_space -= HAWK_FILE_SIZE;
88 }
89#if 0
90 /*number of sdl is defined as 2 in diag_fs.cfg each file 1MB
91 * check we have space for the files*/
92 if (free_space >= MAX_SDL_SIZE) {
93 hawk_save_sdl_log(msg);
94 free_space -= MAX_SDL_SIZE;
95 }
96 if (free_space >= msg->msg_info.binary_log_size) {
97 hawk_save_valuable_event_bin_log(msg);
98 free_space -= msg->msg_info.binary_log_size;
99 }
100#endif
101 // 1.4 create full_logs.tgz and tiny_logs.tgz
102 hawk_zip_create(msg);
103 //no break is intended to allow sending of event report
104 }
105 case HAWK_STATUS_IN_PROGRESS:
106 // if mgs is notification only, send to hawk sender
107 if (msg->msg_info.event_type != HAWK_EVENT_ASSERT_DETECTED)
108 hawk_send_event_report(&msg->msg_info);
109 break;
110 case HAWK_STATUS_HOST_COMMAND:
111 hawk_execute_host_command(&msg->msg_info);
112 break;
113 default:
114 ml_log_error("unknown event status %d ignoring event\n", msg->msg_info.status);
115 }
116 free(msg);
117 msg = NULL;
118 } /* while (1) */
119}
120
121/************************************************************************/
122/* */
123/************************************************************************/
124struct hawk_cached_string {
125 struct list_head list;
126 char *str;
127};
128
129static void hawk_str_to_cache(char *str, struct list_head *list)
130{
131 struct hawk_cached_string *cs;
132 cs = calloc(1, sizeof(*cs));
133 if (!cs) {
134 ml_log_error("OOM '%s'\n", strerror(errno));
135 ml_system_retry(1, 30, "eeh -T panic hawk_OOM");
136 exit(1);
137 }
138 cs->str = strdup(str);
139 if (!cs->str) {
140 ml_log_error("OOM '%s'\n", strerror(errno));
141 ml_system_retry(1, 30, "eeh -T panic hawk_OOM");
142 exit(1);
143 }
144 INIT_LIST_HEAD(&cs->list);
145
146 list_add_tail(&cs->list, list);
147 ml_log_debug("Adding to cache '%s'\n", str);
148}
149
150static __attribute__ ((noreturn))
151void *hawk_fifo_listen( __attribute__ ((unused))
152 void *ptr)
153{
154 char x[HAWK_FIFO_STRING_LEN], *res;
155 struct timeval timeout;
156 struct list_head cached_strings;
157 struct hawk_msg *msg;
158
159 prctl(PR_SET_NAME, "hawk_fifo_listener");
160
161 INIT_LIST_HEAD(&cached_strings);
162
163 fifo.fname = HAWK_FIFO_NAME;
164 if (ml_create_fifo(&fifo) != 0) {
165 ml_system_retry(1, 30, "eeh -T panic hawk_fifo_creation_failed");
166 exit(1);
167 }
168 while (1) {
169 if (!g_hawk.rild_init_done) {
170 timeout.tv_sec = 1;
171 timeout.tv_usec = 1l;
172 } else {
173 // Push all cached command strings into worker queue
174 while (!list_empty(&cached_strings)) {
175 struct hawk_cached_string *cs;
176 cs = list_entry(cached_strings.next, struct hawk_cached_string, list);
177 list_del_init(cached_strings.next);
178 ml_log_info("Remove from cache '%s'\n", cs->str);
179 if ((msg = hawk_str_to_msg(cs->str)) != NULL)
180 hawk_add_msg(msg);
181 free(cs->str);
182 free(cs);
183 }
184
185 timeout.tv_sec = HAWK_FIFO_TIMEOUT;
186 timeout.tv_usec = 1l;
187 }
188
189 res = ml_chomp(ml_read_fifo(&fifo, x, HAWK_FIFO_STRING_LEN, &timeout));
190
191 if (res == NULL || res[0] == 0)
192 continue;
193
194 // While rild init not done or cached queue have pending commands
195 // drop new commands into cache
196 // General purpose of CACHE queue is to cache commands before all HAWK init
197 // done.
198 if (!g_hawk.rild_init_done || !list_empty(&cached_strings)) {
199 hawk_str_to_cache(res, &cached_strings);
200 continue;
201 }
202
203 if ((msg = hawk_str_to_msg(res)) != NULL)
204 hawk_add_msg(msg);
205
206 }
207}
208
209static __attribute__ ((noreturn))
210void *hawk_data_check( __attribute__ ((unused))
211 void *ptr)
212{
213 prctl(PR_SET_NAME, "hawk_data_check");
214
215 while (1) {
216 sleep(HAWK_CHECK_DATA_DELTA);
217 system(HAWK_CHECK_DATA);
218 }
219}
220
221static void __attribute__ ((__noreturn__)) usage(const char *s)
222{
223 fprintf(stderr, "Usage: %s \n", s);
224 fprintf(stderr, "-h - print this help message\n");
225 fprintf(stderr, "-f - disable standalone fota thread\n");
226 fprintf(stderr, "-d - enable debug logs\n");
227 fprintf(stderr, "-p - enable data check\n");
228 exit(1);
229}
230
231int main(int argc, char *argv[])
232{
233
234 pthread_t thid1, thid2;
235 pthread_attr_t tattr1, tattr2;
236 long tmp = 0, file_updated = 0, delta = 0;
237 long next_keep_alive_time = hawk_uptime() + HAWK_KEEP_ALIVE_INTERVAL;
238 int res, data_check = 0;
239 struct ml_vers curVer;
240 struct ml_bld_vers bldVer;
241 int c;
242 int run_sa_fota_thread = 1;
243
244 do {
245 c = getopt(argc, argv, "hfdp");
246 if (c == EOF)
247 break;
248 switch (c) {
249 case '?':
250 case 'h':
251 usage(argv[0]);
252 case 'f':
253 run_sa_fota_thread = 0;
254 break;
255 case 'd':
256 ml_set_log_level(ML_LOG_DEBUG);
257 break;
258 case 'p':
259 data_check = 1;
260 break;
261 }
262 } while (1);
263
264 set_service_log_tag(HKName);
265
266 ml_system_retry(1, ML_SYSTEM_MAX_TIMEOUT, HAWK_STARTUP);
267
268 hawk_lib_init(HAWK_HOST_CONNECTION_TYPE_STANDALONE);
269
270 pthread_mutex_init(&g_hawk.cond_mutex, NULL);
271 pthread_mutex_init(&g_hawk.general_mutex, NULL);
272 pthread_mutex_init(&g_hawk.statistics_mutex, NULL);
273 pthread_cond_init(&g_hawk.cond, NULL);
274 INIT_LIST_HEAD(&g_hawk.msgq_head);
275 g_hawk.q_item_count = 0;
276
277 //In case of FW update/change we clear statistics
278 if (ml_get_vers(&curVer) != NULL) {
279 struct ml_vers prevVer;
280 property_get(HAWK_PROP_VERS, prevVer.s, "0");
281 ml_log_debug("previous version was %s", prevVer.s);
282 ml_log_debug("current version is %s", curVer.s);
283 if (strcmp(curVer.s,prevVer.s) != 0) { /* new version */
284 char command_buf[128];
285 //clear statistics
286 clear_statistics();
287 //clear ML properties
288 property_del(ML_MSEQ_PROP);
289 property_del(ML_BOOTSEQ_PROP);
290 property_del(ML_CP_VER_PROP);
291 //remove old RAMDUMPS and modem_dump directory
292 snprintf(command_buf, sizeof(command_buf) - 1, "rm -rf %sRAMDUMP* %s %s", hawk_mount, LOG_DIR_SD_MODEM, hawk_dir);
293 ml_system_retry(1, ML_SYSTEM_MAX_TIMEOUT, command_buf);
294 //update version property
295 property_set(HAWK_PROP_VERS, curVer.s);
296 //update build version property
297 if(ml_get_bld_vers(&bldVer) != NULL)
298 property_set(HAWK_PROP_BLD_VERS, bldVer.s);
299 }
300 }
301
302 pthread_attr_init(&tattr2);
303 pthread_attr_setdetachstate(&tattr2, PTHREAD_CREATE_DETACHED);
304 if (pthread_create(&thid2, &tattr2, hawk_worker, NULL)) {
305 ml_log_error("hawk worker pthread_create failed '%s'\n", strerror(errno));
306 return -1;
307 }
308
309 pthread_attr_init(&tattr1);
310 pthread_attr_setdetachstate(&tattr1, PTHREAD_CREATE_DETACHED);
311 if (pthread_create(&thid1, &tattr1, hawk_fifo_listen, NULL)) {
312 ml_log_error("fifo listen pthread_create failed '%s'\n", strerror(errno));
313 return -1;
314 }
315
316 if(ml_get_long_property("ro.hawk.fota.is_enabled") != 1)
317 run_sa_fota_thread = 0;
318
319 res = hawk_sender_create_worker(run_sa_fota_thread);
320 if (res != 0) {
321 ml_log_error("Failed to init hawk....\n");
322 return -1;
323 }
324
325 if (data_check) {
326 pthread_t thid3;
327 pthread_attr_t tattr3;
328 pthread_attr_init(&tattr3);
329 pthread_attr_setdetachstate(&tattr3, PTHREAD_CREATE_DETACHED);
330 if (pthread_create(&thid3, &tattr3, hawk_data_check, NULL)) {
331 ml_log_error("data check pthread_create failed '%s'\n", strerror(errno));
332 return -1;
333 }
334 }
335
336 while (1) {
337 if (!g_hawk.rild_init_done) {
338 sleep(2);
339 continue;
340 }
341 tmp = hawk_uptime();
342 delta = tmp - file_updated;
343
344 ml_log_debug("tmp=%ld, delta=%ld, next_keep_alive_time=%ld", tmp, delta, next_keep_alive_time);
345
346 if (delta >= HAWK_TIMESTAMP_DELTA) {
347 file_updated = tmp;
348 hawk_set_timestamp();
349 }
350
351 if (next_keep_alive_time < tmp) { /*current time ls larger then next keep alive event time */
352 hawk_send_keep_alive_event();
353 next_keep_alive_time = tmp + HAWK_KEEP_ALIVE_INTERVAL;
354 }
355
356 //save_statistics();
357 hawk_rild_get_rat();
358 sleep(delta >= HAWK_TIMESTAMP_DELTA ? HAWK_TIMESTAMP_DELTA : HAWK_TIMESTAMP_DELTA - delta + 1);
359 }
360}