blob: 9a67de587ffbe21c32d635f6cf1fc49b9fbd5d26 [file] [log] [blame]
#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;
}