| #include <errno.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <time.h> |
| #include <pthread.h> |
| #include <sys/sysinfo.h> |
| #include <cutils/properties.h> |
| #include <ml_utils.h> |
| |
| #include "paths_defs.h" |
| #include "hawk_lib.h" |
| #include "hawk_api.h" |
| #include "hawk_statistics.h" |
| |
| #define HAWK_SKEY_LIMIT 128 |
| #define HAWK_SVAL_LIMIT 512 |
| #define MIN_LOG_SIZE (50*1024) /*50KB*/ |
| |
| |
| #define DEBUG_DIR SDCARD_MOUNT |
| |
| #define HAWK_MARK_OFFLINE_DIRS_COMMAND TEL_DIR "hawk_mark_offline_dirs.sh" |
| #define HAWK_ARCHIVE_LOGS_COMMAND TEL_DIR "hawk_archive_logs.sh" |
| #define HAWK_PACK_LOGS_COMMAND TEL_DIR "hawk_pack_logs_tar_gz.sh" |
| #define HAWK_LOG_LIST_FILE TEL_DIR "hawk_loglist.txt" |
| |
| struct ml_fifo fifo; |
| |
| __attribute__((unused)) static char *hawk_get_board_id(void) |
| { |
| static char buf[4]; |
| static int board_updated = 0; |
| |
| if (board_updated) |
| return buf; |
| |
| property_get("ro.cmdline.BOAR", buf, "00"); |
| board_updated = 1; |
| |
| return buf; |
| } |
| |
| static char *hawk_get_product(void) |
| { |
| static char buf[16]; |
| static int device_updated = 0; |
| |
| if (device_updated) |
| return buf; |
| |
| property_get("ro.product.device", buf, "pxa1826"); |
| device_updated =1; |
| |
| return buf; |
| } |
| |
| __attribute__((unused)) static char *hawk_get_cpu_id(void) |
| { |
| static char buf[4]; |
| static int chip_updated = 0; |
| |
| if (chip_updated) |
| return buf; |
| |
| property_get("ro.cmdline.CHIP", buf, "-1"); |
| chip_updated =1; |
| |
| return buf; |
| } |
| |
| void hawk_zip_create(struct hawk_msg *msg) |
| { |
| char command_buf[256]; |
| |
| ml_log_debug("NEW ZIP %s\n", msg->msg_info.event_dir); |
| |
| snprintf(command_buf, sizeof(command_buf) - 1, "%s %s", HAWK_ARCHIVE_LOGS_COMMAND, msg->msg_info.event_dir); |
| ml_system_retry(1, ML_SYSTEM_MAX_TIMEOUT, command_buf); |
| } |
| |
| static void add_property(char *prop_name, char *key_name, char **s){ |
| char tmp[512]; |
| int n; |
| property_get(prop_name, tmp, "0"); |
| if (strcmp(tmp,"0") != 0){ |
| n = sprintf(*s, "[key:] %s [value:] %s\n", key_name, tmp); |
| *s += n; |
| } |
| } |
| |
| static void add_hawk_statistics(char **s){ |
| |
| //ADD SENT DATA USAGE |
| add_property(HAWK_PROP_2G_TX, "TX2", s); |
| add_property(HAWK_PROP_3G_TX, "TX3", s); |
| add_property(HAWK_PROP_4G_TX, "TX4", s); |
| |
| //ADD RECEIVED DATA USAGE |
| add_property(HAWK_PROP_2G_RX, "RX2", s); |
| add_property(HAWK_PROP_3G_RX, "RX3", s); |
| add_property(HAWK_PROP_4G_RX, "RX4", s); |
| |
| //ADD VOICE CALL COUNT |
| add_property(HAWK_PROP_2G_TX_VC_CNT, "OutCount2G", s); |
| add_property(HAWK_PROP_2G_RX_VC_CNT, "InCount2G", s); |
| add_property(HAWK_PROP_3G_TX_VC_CNT, "OutCount3G", s); |
| add_property(HAWK_PROP_3G_RX_VC_CNT, "InCount3G", s); |
| add_property(HAWK_PROP_4G_TX_VC_CNT, "OutCount4G", s); |
| add_property(HAWK_PROP_4G_RX_VC_CNT, "InCount4G", s); |
| |
| //ADD INITIATED VOICE CALL DURATION |
| add_property(HAWK_PROP_2G_TX_VC_TIME, "OutDuration2G", s); |
| add_property(HAWK_PROP_3G_TX_VC_TIME, "OutDuration3G", s); |
| add_property(HAWK_PROP_4G_TX_VC_TIME, "OutDuration4G", s); |
| |
| //ADD RECEIVED VOICE CALL DURATION |
| add_property(HAWK_PROP_2G_RX_VC_TIME, "InDuration2G", s); |
| add_property(HAWK_PROP_3G_RX_VC_TIME, "InDuration3G", s); |
| add_property(HAWK_PROP_4G_RX_VC_TIME, "InDuration4G", s); |
| |
| //ADD SENT SMS COUNT |
| add_property(HAWK_PROP_2G_TX_SMS, "OutSMS2G", s); |
| add_property(HAWK_PROP_3G_TX_SMS, "OutSMS3G", s); |
| add_property(HAWK_PROP_4G_TX_SMS, "OutSMS4G", s); |
| |
| //ADD RECEIVED SMS COUNT |
| add_property(HAWK_PROP_2G_RX_SMS, "InSMS2G", s); |
| add_property(HAWK_PROP_3G_RX_SMS, "InSMS3G", s); |
| add_property(HAWK_PROP_4G_RX_SMS, "InSMS4G", s); |
| |
| //ADD RECEIVED SMS COUNT |
| add_property(HAWK_PROP_2G_TOTAL, "TimeIn2G", s); |
| add_property(HAWK_PROP_3G_TOTAL, "TimeIn3G", s); |
| add_property(HAWK_PROP_4G_TOTAL, "TimeIn4G", s); |
| } |
| |
| void hawk_spy_file(struct hawk_msg *msg) |
| { |
| char file[HAWK_FILE_SIZE], tmp[512]; |
| int n; |
| char *s = file; |
| |
| n = sprintf(s, "[key:] Initiator [value:] %s\n", msg->msg_info.initiator_str); |
| s += n; |
| |
| n = sprintf(s, "[key:] EventID [value:] %s\n", msg->msg_info.event_id); |
| s += n; |
| |
| n = sprintf(s, "[key:] EventType [value:] %s\n", msg->msg_info.event_type_str); |
| s += n; |
| |
| n = sprintf(s, "[key:] AssertLine [value:] %s\n", msg->msg_info.description); |
| s += n; |
| |
| n = sprintf(s, "[key:] BootSequence [value:] %d\n", ml_get_boot_sequence()); |
| s += n; |
| |
| n = sprintf(s, "[key:] MsgSeqNumber [value:] %d\n", ml_get_property(ML_MSEQ_PROP)); |
| s += n; |
| |
| if (msg->msg_info.event_type == HAWK_EVENT_BOOT_DONE) { |
| //read from file |
| char a[50], b[50], z[120]; |
| ml_file2str(HAWK_UPTIME_FILE, z, 100, 1); |
| if (z[0] != '0') { |
| sscanf(z, "[%50[^]]][%50[^.]]", a, b); |
| } else { |
| sprintf(b, "%d", 0); |
| } |
| n = sprintf(s, "[key:] TimeFromBoot [value:] %u\n", atoi(b)); |
| hawk_set_timestamp(); |
| } else if (msg->msg_info.event_type == HAWK_EVENT_ASSERT) { |
| n = sprintf(s, "[key:] TimeFromBoot [value:] %u\n", msg->msg_info.assert_time); |
| } else { |
| n = sprintf(s, "[key:] TimeFromBoot [value:] %ld\n", hawk_uptime()); |
| } |
| s += n; |
| |
| n = sprintf(s, "[key:] EventTimeIn32Tick [value:] %u\n", msg->msg_info.event_time); |
| s += n; |
| |
| if (ml_get_bld_vers((struct ml_bld_vers *)tmp) != NULL) { |
| n = sprintf(s, "[key:] AppSoftwareVersion [value:] %s\n", tmp); |
| s += n; |
| } |
| |
| if (ml_get_cp_ver((struct ml_cp_ver *)tmp) != NULL) { |
| n = sprintf(s, "[key:] CommSoftwareVersion [value:] %s\n", tmp); |
| s += n; |
| } |
| |
| n = sprintf(s, "[key:] ProductName [value:] %s\n", hawk_get_product()); |
| s += n; |
| |
| if (ml_get_imei((struct ml_imei *)tmp) != NULL) { |
| n = sprintf(s, "[key:] IMEI [value:] %s\n", tmp); |
| s += n; |
| } |
| |
| add_hawk_statistics(&s); |
| { |
| int mnc, mcc; |
| if (hawk_get_last_cell_location(&mnc, &mcc)){ |
| n = sprintf(s, "[key:] MCC [value:] %d\n", mcc); |
| s += n; |
| n = sprintf(s, "[key:] MNC [value:] %d\n", mnc); |
| s += n; |
| } |
| } |
| { |
| struct timeval tv; |
| struct tm result; |
| size_t n; |
| time_t curtime; |
| |
| memset(&tv, 0, sizeof(tv)); |
| memset(&result, 0, sizeof(result)); |
| gettimeofday(&tv, NULL); |
| curtime = tv.tv_sec; |
| |
| if (gmtime_r(&curtime, &result) != NULL) { |
| strftime(tmp, sizeof(tmp) - 1, "%d-%m-%Y %H:%M:%S", &result); |
| n = sprintf(s, "[key:] Date [value:] %s\n", tmp); |
| s += n; |
| } |
| } |
| |
| sprintf(tmp, "%s/Spy.txt", msg->msg_info.event_dir); |
| ml_str2file(tmp, file, strlen(file) + 1); |
| |
| return; |
| } |
| |
| void hawk_save_valuable_event_bin_log(struct hawk_msg *msg) |
| { |
| char tmp[512]; |
| FILE *file = NULL; |
| |
| if (msg->msg_info.event_type != HAWK_EVENT_VALUABLE_EVENT) |
| return; //no VE bin log for this events |
| if (msg->msg_info.binary_log_size <= 0 || msg->msg_info.binary_log_size > sizeof(msg->msg_info.binary_log)) |
| return; //no bin log present |
| |
| sprintf(tmp, "%s/ve_bin_log.bin", msg->msg_info.event_dir); |
| file = fopen(tmp, "wb"); |
| if (file == NULL) { |
| ml_log_error("failed to create valuable event bin log\n"); |
| return; |
| } |
| fwrite(msg->msg_info.binary_log, sizeof(char), msg->msg_info.binary_log_size, file); |
| fclose(file); |
| } |
| |
| void hawk_save_sdl_log(struct hawk_msg *msg) |
| { |
| #define DIAG_SDL_TMP_DIR "LogCPSR" |
| #define LOG_CPSR_DIR LOG_DIR DIAG_SDL_TMP_DIR |
| char tmp[256]; |
| |
| if (!msg->msg_info.include_sd_log) |
| return; |
| |
| if ((msg->msg_info.event_type == HAWK_EVENT_SILENT_RESET) && |
| !access(LOG_CPSR_DIR, F_OK)) { |
| /* "LogCPSR" created by EEH first, |
| * but handled by HAWK only after further event "MTSD ok" |
| * The current HAWK Log000 has not CPSR SDLs but "MTSD ok" |
| */ |
| snprintf(tmp, sizeof(tmp), "mv %s/*.sdl %s; rm -r %s", |
| LOG_CPSR_DIR, msg->msg_info.event_dir, LOG_CPSR_DIR); |
| ml_system_retry(1, 120, tmp); |
| return; |
| } |
| |
| ml_system_retry(1, 30, "diag_mmi stop"); |
| snprintf(tmp, sizeof(tmp), "cp %s/Log000/*.sdl %s; rm %s/Log000/*.sdl; diag_mmi start;", |
| LOG_DIR, msg->msg_info.event_dir, LOG_DIR); |
| ml_system_retry(1, 120, tmp); |
| } |
| |
| void hawk_save_dmesg_file(struct hawk_msg *msg) |
| { |
| char tmp[256]; |
| |
| if (!msg->msg_info.include_dmesg_log) |
| return; |
| |
| snprintf(tmp, sizeof(tmp) - 1, "dmesg > %s/dmesg.txt", msg->msg_info.event_dir); |
| ml_system_retry(1, ML_SYSTEM_MAX_TIMEOUT, tmp); |
| } |
| |
| void hawk_update_assert_description(struct hawk_msg *msg) |
| { |
| char dir[256]; |
| char tmp_buff[128]; |
| char new_dec[128]; |
| char tmp1[50], tmp2[50]; |
| int argc; |
| |
| snprintf(dir, 254, "%s/description.txt", msg->msg_info.event_dir); |
| memset(tmp_buff, 0, sizeof(tmp_buff)); |
| |
| if (ml_file2str(dir, tmp_buff, sizeof(tmp_buff) - 1, 0) == NULL) { |
| ml_log_error("failed to open assert description file\n"); |
| return; |
| } |
| /*remove the time from boot print at the start of the line */ |
| argc = sscanf(tmp_buff, "[%50[^]]] [%50[^]]] %127[^\n]", tmp1, tmp2, new_dec); |
| if (argc != 3) { |
| ml_log_error("error parseing file, argc=%d, tmp1=%s, tmp2=%s, new_dec=%s\n", argc, tmp1, tmp2, |
| new_dec); |
| strcpy(new_dec, tmp_buff); |
| } else { |
| msg->msg_info.assert_time = atoi(tmp2); |
| } |
| |
| strncpy(msg->msg_info.description, new_dec, sizeof(msg->msg_info.description)); |
| ml_log_info("event new description is '%s'\n", msg->msg_info.description); |
| } |
| |
| void hawk_mark_messages_as_offline() |
| { |
| static long hawk_dir_scanned = 0; |
| char command_buf[512]; |
| long tmp = 0; |
| tmp = hawk_uptime(); |
| |
| // This should prevent abuse if this function called to many times at once |
| // Depending on amount of dirs on SDCARD it might be very long execution too |
| if ((tmp - hawk_dir_scanned) < HAWK_SCAN_SDCARD_PERIOD) |
| return; |
| hawk_dir_scanned = tmp; |
| snprintf(command_buf, sizeof(command_buf) - 1, "%s %s", HAWK_MARK_OFFLINE_DIRS_COMMAND, hawk_dir); |
| ml_system_retry(1, ML_SYSTEM_MAX_TIMEOUT, command_buf); |
| } |
| |
| void hawk_create_file(int mode) |
| { |
| int retval; |
| FILE *pJournal_file, *pDescription_file; |
| char *buffer; |
| char *ptr, *ptr1; |
| char filename_src[256]; |
| char tmp[260]; |
| char command_buf[256]; |
| char dir_des[256]; |
| char logs_dir[256] = LOG_DIR; |
| int number_of_exceptions = 0; |
| fpos_t position; |
| int ramdump_number; |
| struct ml_uniqid unique_id; |
| |
| unsigned long long free_space = 0; |
| |
| free_space = get_logs_free_space(); |
| //Lets check if we have free space (if SD is not mounted free_space will be 0) |
| if (free_space < MIN_LOG_SIZE) { |
| ml_log_error("Warning! lack of free space, space left=%lluB\n", free_space); |
| //NO RETURN, We should continue, RD will be erased in case of no free space. |
| //return; |
| } |
| |
| /* opening the file for read to parsing it |
| * and for write to mark the exception as used*/ |
| pJournal_file = fopen(EEH_JOURNAL_FILE, "r+"); |
| if (pJournal_file == NULL) |
| return; |
| |
| /* allocate memory to contain the whole file: */ |
| buffer = (char *)malloc((sizeof(char) * (256))); |
| if (buffer == NULL) { |
| fclose(pJournal_file); |
| return; |
| } |
| |
| /*Look-Forward in eeh_journal for relevant exceptions */ |
| ptr = fgets(buffer, (sizeof(char) * (256)), pJournal_file); |
| while (ptr != NULL) { |
| if (((strstr(buffer, APPS_EXCEPTION_TEMPLATE) != NULL) || (strstr(buffer, COMM_EXCEPTION_TEMPLATE) != NULL)) |
| && (strchr(buffer, USED_EXCEPTION_TEMPLATE) == NULL)) { |
| /*send to the HAWK server that the latest |
| exception was handled */ |
| if (number_of_exceptions) { |
| char x[200]; |
| snprintf(x, 200, EEH2HAWK_ASSERT_READY, (char *)&unique_id); |
| ml_write_fifo(&fifo, x, strlen(x)); |
| } |
| number_of_exceptions++; |
| snprintf(dir_des, sizeof(dir_des) - 1, "%s/%s", hawk_dir, ml_get_uniqid(&unique_id)); |
| retval = mkdir(dir_des, 0777); |
| if (retval) |
| goto release_resources; |
| /* parsing eeh_journal to get the fields content */ |
| /* eeh_journal example for APPS assert: */ |
| /* global time;boot_time;error_type;error_description */ |
| /* [07:48:17] [00:01:57] APPS ASSERT DESC: description */ |
| |
| /*create description file */ |
| snprintf(command_buf, sizeof(command_buf) - 1, "%s/description.txt", dir_des); |
| pDescription_file = fopen(command_buf, "wt"); |
| if (pDescription_file == NULL) |
| goto release_resources; |
| fprintf(pDescription_file, "%s", buffer); |
| fclose(pDescription_file); |
| |
| fgetpos(pJournal_file, &position); |
| fseek(pJournal_file, -2, SEEK_CUR); |
| fputc(USED_EXCEPTION_TEMPLATE, pJournal_file); |
| fsetpos(pJournal_file, &position); |
| |
| ptr = fgets(buffer, (sizeof(char) * (256)), pJournal_file); |
| while (ptr != NULL) { |
| unsigned long long rd_size; |
| /* if we got the next exception that mean |
| that there is no available information */ |
| if ((strstr(buffer, APPS_EXCEPTION_TEMPLATE) != NULL) |
| || (strstr(buffer, COMM_EXCEPTION_TEMPLATE) != NULL)) |
| break; |
| if (strstr(buffer, "Saving log into") != NULL) { |
| ptr = strchr(buffer, '/'); |
| if (ptr == NULL) |
| break; |
| ptr1 = strchr(buffer, '\n'); |
| if (ptr1 == NULL) |
| break; |
| strncpy(logs_dir, ptr, ptr1 - ptr); |
| } else if (strstr(buffer, "RAMDUMP") != NULL) { |
| ptr = strchr(buffer, 'P'); |
| if (ptr == NULL) |
| break; |
| ramdump_number = atoi(++ptr); |
| |
| snprintf(filename_src, |
| sizeof(filename_src) - 1, |
| "%sRAMDUMP%.4d", DEBUG_DIR, ramdump_number); |
| // Check gz and txt sizes |
| // in case we have no free space delete RD |
| snprintf(tmp, sizeof(tmp) - 1, "%s.txt", filename_src); |
| rd_size = ml_get_dir_size(tmp); |
| snprintf(tmp, sizeof(tmp) - 1, "%s.gz", filename_src); |
| rd_size += ml_get_dir_size(tmp); |
| if (free_space > rd_size) { |
| snprintf(command_buf, |
| sizeof(command_buf) - 1, "mv %s.* %s", filename_src, dir_des); |
| free_space -= rd_size; |
| } else { |
| snprintf(command_buf, |
| sizeof(command_buf) - 1, "rm %s.*", filename_src); |
| } |
| ml_system_retry(1, ML_SYSTEM_MAX_TIMEOUT, command_buf); |
| break; |
| } |
| ptr = fgets(buffer, (sizeof(char) |
| * (256)), pJournal_file); |
| } |
| } else |
| ptr = fgets(buffer, (sizeof(char) * (256)) |
| , pJournal_file); |
| } |
| |
| if (number_of_exceptions > 0) { |
| unsigned long long logs_size; |
| char *logs_list_fname = HAWK_LOG_LIST_FILE; |
| char buffer[1024] = {0}; /*assume log list file size is less then 1024 bytes*/ |
| ml_file2str(logs_list_fname, buffer, 1024, 0); |
| // Check file sizes in case we have no free space ignore |
| logs_size = ml_get_files_size(buffer); |
| if (free_space > logs_size) { |
| snprintf(command_buf, sizeof(command_buf) - 1,"%s %s %s", HAWK_PACK_LOGS_COMMAND, dir_des, logs_list_fname); |
| ml_system_retry(1, ML_SYSTEM_MAX_TIMEOUT, command_buf); |
| } |
| char x[200]; |
| if (mode == EEH2HAWK_ASSERT_READY_MODE) |
| snprintf(x, 200, EEH2HAWK_ASSERT_READY, (char *)&unique_id); |
| else |
| snprintf(x, 200, EEH2HAWK_SIRESET_READY, (char *)&unique_id); |
| ml_write_fifo(&fifo, x, strlen(x)); |
| } |
| release_resources: |
| free(buffer); |
| fclose(pJournal_file); |
| return; |
| } |