ril: [R3] Support traffic stats log convert tp pcap

convert traffic stats log(extended_log_datastall_pkt.txt) to pcap
when dump bugreport.

Bug: 154492175
Test: 1. I do see extended_log_datastall.pcap file
      in dumstate_board.bin when I trigger bugreport.
      (data/vendor/radio/extended_logs/extended_log_datastall.txt)
      2. I have do the test about incomplete/truncated logs, pcap just
      can parse to wrong information but not impact the dumpstate
      process.
Change-Id: Iea892bc66bbce8d7f219ca1cde3701cebb35ff80
diff --git a/dumpstate/Android.mk b/dumpstate/Android.mk
index 14f61c9..7a22935 100644
--- a/dumpstate/Android.mk
+++ b/dumpstate/Android.mk
@@ -32,7 +32,8 @@
     libdumpstateutil \
     libhidlbase \
     liblog \
-    libutils
+    libutils \
+    libpcap
 
 LOCAL_CFLAGS := -Werror -Wall
 
diff --git a/dumpstate/DumpstateDevice.cpp b/dumpstate/DumpstateDevice.cpp
index 9b670f9..f014f6b 100755
--- a/dumpstate/DumpstateDevice.cpp
+++ b/dumpstate/DumpstateDevice.cpp
@@ -28,6 +28,8 @@
 #include <pthread.h>
 #include <string.h>
 
+#include <pcap.h>
+
 #define _SVID_SOURCE
 #include <dirent.h>
 
@@ -52,6 +54,10 @@
 
 #define VENDOR_VERBOSE_LOGGING_ENABLED_PROPERTY "persist.vendor.verbose_logging_enabled"
 
+#define TIME_BUFFER 24
+#define STRING_BUFFER 550
+#define MAX_PACKET_LENGTH 150
+
 using android::os::dumpstate::CommandOptions;
 using android::os::dumpstate::DumpFileToFd;
 using android::os::dumpstate::PropertiesHelper;
@@ -113,6 +119,126 @@
     free(dirent_list);
 }
 
+// Get timestamp and packet data
+static void GetTimeStampAndPkt(char *pktbuf, unsigned char *packet, char *strtime, int totalbyte){
+    int idxLog = 0;
+    int idxPkt = 0;
+    int firstPktDataIdx = 2;
+    int lastPktDataIdx = totalbyte - 2;
+    char arrTmpTime[19];
+    char arrStrTime[TIME_BUFFER];
+    char* tmpPktByteStr;
+    char* pktDataStr = pktbuf;
+    unsigned char arrPktData[MAX_PACKET_LENGTH];
+
+    memset(arrTmpTime, 0, sizeof(arrTmpTime));
+    while ((tmpPktByteStr = strtok_r(pktDataStr, " ", &pktDataStr))) {
+      if(idxLog == 0) {
+        snprintf(arrTmpTime, sizeof(arrTmpTime),"%s", tmpPktByteStr);
+      }
+      if(idxLog == 1) {
+        snprintf(arrStrTime, sizeof(arrStrTime),"%s %s",arrTmpTime, tmpPktByteStr);
+      }
+      if(idxLog > firstPktDataIdx && idxLog <= lastPktDataIdx) {
+        int data;
+        unsigned char pktdata;
+        sscanf(tmpPktByteStr,"%02x", &data);
+        pktdata = (unsigned char)data;
+        arrPktData[idxPkt] = pktdata;
+        idxPkt++;
+      }
+      idxLog++;
+    }
+    memcpy(packet, arrPktData, MAX_PACKET_LENGTH);
+    memcpy(strtime, arrStrTime, TIME_BUFFER);
+}
+
+static void ProcessPcapDump(FILE *fp, pcap_dumper_t *dumper)
+{
+    ALOGD("ProcessPcapDump(): enter");
+    char strLogBuf[STRING_BUFFER];
+    char arrPktBuf[STRING_BUFFER];
+    char arrPktSplitBuf[STRING_BUFFER];
+    char arrStrTime[TIME_BUFFER];
+    unsigned char arrPktData[MAX_PACKET_LENGTH];
+
+    if(fp  == NULL) {
+      ALOGD("can not read extended_log_datastall file!");
+      return;
+    }
+    if(dumper == NULL) {
+      ALOGD("can not open pcap file.");
+      return;
+    }
+
+    while (!feof(fp)) {
+      while (fgets(strLogBuf,STRING_BUFFER,fp)) {
+        if(strLogBuf[0] == '\n') {
+          continue;
+        }
+        memcpy(arrPktBuf, strLogBuf, sizeof(arrPktBuf));
+        memcpy(arrPktSplitBuf, strLogBuf, sizeof(arrPktSplitBuf));
+
+        int countPktLen = 0;
+        char* tmpPktByteStr;
+        char* pktDataStr = arrPktSplitBuf;
+        while ((tmpPktByteStr = strtok_r(pktDataStr, " ", &pktDataStr))) {
+          countPktLen+=1;
+        }
+
+        // Get timestamp and packet data
+        GetTimeStampAndPkt(arrPktBuf ,arrPktData, arrStrTime, countPktLen);
+
+        // Build packet header
+        int timeMSec;
+        char* strTime;
+        char* strTimeMsec;
+        char* strTmpTime = arrStrTime;
+        struct pcap_pkthdr pcap_hdr;
+        while ((strTime = strtok_r(strTmpTime, ".", &strTmpTime))) {
+          time_t time;
+          struct tm timeStruct;
+          memset(&timeStruct, 0, sizeof(struct tm));
+          if(strlen(strTime) == 19) {
+            strptime(strTime, "%Y-%m-%d %H:%M:%S", &timeStruct);
+            time = mktime(&timeStruct);
+            pcap_hdr.ts.tv_sec = time;
+          }
+          strTimeMsec = strtok_r(strTmpTime, ".", &strTmpTime);
+          timeMSec = atoi(strTimeMsec);
+          pcap_hdr.ts.tv_usec = timeMSec;
+        }
+        pcap_hdr.caplen = sizeof(arrPktData);
+        pcap_hdr.len = pcap_hdr.caplen;
+        pcap_dump((u_char *)dumper, &pcap_hdr, arrPktData);
+      }
+    }
+}
+
+static void MergeAndConvertToPcap(char* logFile, char* oldlogFile, char* pcapFile) {
+
+    ALOGD("DumpPcap(): enter");
+    pcap_t *handle = pcap_open_dead(DLT_EN10MB, 1 << 16);
+    pcap_dumper_t *dumper = pcap_dump_open(handle, pcapFile);
+
+    if(dumper == NULL) {
+      ALOGD("can not open pcap file.");
+      return;
+    }
+
+    FILE *fp = fopen(oldlogFile, "r");
+    if(fp != NULL) {
+      ProcessPcapDump(fp, dumper);
+      fclose(fp);
+    }
+    fp = fopen(logFile, "r");
+    if(fp != NULL) {
+      ProcessPcapDump(fp, dumper);
+      fclose(fp);
+    }
+    pcap_dump_close(dumper);
+}
+
 static void *dumpModemThread(void *data)
 {
     long fdModem = (long)data;
@@ -169,6 +295,12 @@
     }
     RunCommandToFd(STDOUT_FILENO, "CP MODEM POWERON LOG", {"/vendor/bin/cp", diagPoweronLogPath.c_str(), modemLogAllDir.c_str()}, CommandOptions::WithTimeout(2).Build());
 
+    // dump to pcap
+    char fpcapname[]="/data/vendor/radio/extended_logs/extended_log_datastall.pcap";
+    char flogname[]="/data/vendor/radio/extended_logs/extended_log_datastall.txt";
+    char flogoldname[]="/data/vendor/radio/extended_logs/extended_log_datastall.txt.old";
+    MergeAndConvertToPcap(flogname, flogoldname, fpcapname);
+
     if (!PropertiesHelper::IsUserBuild()) {
         char cmd[256] = { 0 };