This cl does the following things:

0) Implements a skeleton of incident_helper
1) Implements FileSection class which calls incident_helper to parse
   file content to protobuf
2) Adds Kernel Wake Sources to incident.proto and makes it parsed by
   FileSection
3) Adds basic gtests to test FdBuffer, io_utils, FileSection
implementation

Bug: 62923266
Bug: 62926061
Test: manual - push incidentd, incident_helper and incident to my device
      and verify kernel wakeup sources file is able to be parsed.
Change-Id: I2aa6b6158d962ce70e6fa6c8a9c42213a45ff41c
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index 527d7ee..7743301 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -24,11 +24,11 @@
 #include <fcntl.h>
 #include <poll.h>
 #include <unistd.h>
+#include <wait.h>
 
-const ssize_t BUFFER_SIZE = 16 * 1024;
+const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
 const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
 
-
 FdBuffer::FdBuffer()
     :mBuffers(),
      mStartTime(-1),
@@ -109,6 +109,135 @@
     return NO_ERROR;
 }
 
+status_t
+FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs)
+{
+    struct pollfd pfds[] = {
+        { .fd = fd,     .events = POLLIN  },
+        { .fd = toFd,   .events = POLLOUT },
+        { .fd = fromFd, .events = POLLIN  },
+    };
+
+    mStartTime = uptimeMillis();
+
+    // mark all fds non blocking
+    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
+    fcntl(toFd, F_SETFL, fcntl(toFd, F_GETFL, 0) | O_NONBLOCK);
+    fcntl(fromFd, F_SETFL, fcntl(fromFd, F_GETFL, 0) | O_NONBLOCK);
+
+    // A circular buffer holds data read from fd and writes to parsing process
+    uint8_t cirBuf[BUFFER_SIZE];
+    size_t cirSize = 0;
+    int rpos = 0, wpos = 0;
+
+    // This is the buffer used to store processed data
+    uint8_t* buf = NULL;
+    while (true) {
+        if (mCurrentWritten >= BUFFER_SIZE || mCurrentWritten < 0) {
+            if (mBuffers.size() == MAX_BUFFER_COUNT) {
+                mTruncated = true;
+                break;
+            }
+            buf = (uint8_t*)malloc(BUFFER_SIZE);
+            if (buf == NULL) {
+                return NO_MEMORY;
+            }
+            mBuffers.push_back(buf);
+            mCurrentWritten = 0;
+        }
+
+        int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
+        if (remainingTime <= 0) {
+            mTimedOut = true;
+            break;
+        }
+
+        // wait for any pfds to be ready to perform IO
+        int count = poll(pfds, 3, remainingTime);
+        if (count == 0) {
+            mTimedOut = true;
+            break;
+        } else if (count < 0) {
+            return -errno;
+        }
+
+        // make sure no errors occur on any fds
+        for (int i = 0; i < 3; ++i) {
+            if ((pfds[i].revents & POLLERR) != 0) {
+                return errno != 0 ? -errno : UNKNOWN_ERROR;
+            }
+        }
+
+        // read from fd
+        if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
+            ssize_t amt;
+            if (rpos >= wpos) {
+                amt = ::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos);
+            } else {
+                amt = :: read(fd, cirBuf + rpos, wpos - rpos);
+            }
+            if (amt < 0) {
+                if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
+                    return -errno;
+                } // otherwise just continue
+            } else if (amt == 0) {  // reach EOF so don't have to poll pfds[0].
+                ::close(pfds[0].fd);
+                pfds[0].fd = -1;
+            } else {
+                rpos += amt;
+                cirSize += amt;
+            }
+        }
+
+        // write to parsing process
+        if (cirSize > 0 && pfds[1].fd != -1) {
+            ssize_t amt;
+            if (rpos > wpos) {
+                amt = ::write(toFd, cirBuf + wpos, rpos - wpos);
+            } else {
+                amt = ::write(toFd, cirBuf + wpos, BUFFER_SIZE - wpos);
+            }
+            if (amt < 0) {
+                if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
+                    return -errno;
+                } // otherwise just continue
+            } else {
+                wpos += amt;
+                cirSize -= amt;
+            }
+        }
+
+        // if buffer is empty and fd is closed, close write fd.
+        if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
+            ::close(pfds[1].fd);
+            pfds[1].fd = -1;
+        }
+
+        // circular buffer, reset rpos and wpos
+        if (rpos >= BUFFER_SIZE) {
+            rpos = 0;
+        }
+        if (wpos >= BUFFER_SIZE) {
+            wpos = 0;
+        }
+
+        // read from parsing process
+        ssize_t amt = ::read(fromFd, buf + mCurrentWritten, BUFFER_SIZE - mCurrentWritten);
+        if (amt < 0) {
+            if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
+                return -errno;
+            } // otherwise just continue
+        } else if (amt == 0) {
+            break;
+        } else {
+            mCurrentWritten += amt;
+        }
+    }
+
+    mFinishTime = uptimeMillis();
+    return NO_ERROR;
+}
+
 size_t
 FdBuffer::size()
 {