Implement Cpu Freq Section

When poll from sysfs, revents return POLLERR by default, handles
this edge case in this cl.

Bug: 68774444
Test: unit tested + on device tests
Change-Id: I23540299c026d3e7676497f56690e9f8646a47bd
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index b7633a4..30dd339 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -26,6 +26,7 @@
 #include <unistd.h>
 #include <wait.h>
 
+const bool DEBUG = false;
 const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
 const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
 
@@ -71,9 +72,11 @@
             mTimedOut = true;
             break;
         } else if (count < 0) {
+            if (DEBUG) ALOGD("poll failed: %s", strerror(errno));
             return -errno;
         } else {
             if ((pfds.revents & POLLERR) != 0) {
+                if (DEBUG) ALOGD("return event has error %s", strerror(errno));
                 return errno != 0 ? -errno : UNKNOWN_ERROR;
             } else {
                 ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
@@ -81,6 +84,7 @@
                     if (errno == EAGAIN || errno == EWOULDBLOCK) {
                         continue;
                     } else {
+                        if (DEBUG) ALOGD("Fail to read %d: %s", fd, strerror(errno));
                         return -errno;
                     }
                 } else if (amt == 0) {
@@ -95,7 +99,7 @@
 }
 
 status_t
-FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs)
+FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs, const bool isSysfs)
 {
     struct pollfd pfds[] = {
         { .fd = fd,     .events = POLLIN  },
@@ -135,12 +139,18 @@
             mTimedOut = true;
             break;
         } else if (count < 0) {
+            if (DEBUG) ALOGD("Fail to poll: %s", strerror(errno));
             return -errno;
         }
 
         // make sure no errors occur on any fds
         for (int i = 0; i < 3; ++i) {
             if ((pfds[i].revents & POLLERR) != 0) {
+                if (i == 0 && isSysfs) {
+                    if (DEBUG) ALOGD("fd %d is sysfs, ignore its POLLERR return value", fd);
+                    continue;
+                }
+                if (DEBUG) ALOGD("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
                 return errno != 0 ? -errno : UNKNOWN_ERROR;
             }
         }
@@ -155,6 +165,7 @@
             }
             if (amt < 0) {
                 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
+                    if (DEBUG) ALOGD("Fail to read fd %d: %s", fd, strerror(errno));
                     return -errno;
                 } // otherwise just continue
             } else if (amt == 0) {  // reach EOF so don't have to poll pfds[0].
@@ -176,6 +187,7 @@
             }
             if (amt < 0) {
                 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
+                    if (DEBUG) ALOGD("Fail to write toFd %d: %s", toFd, strerror(errno));
                     return -errno;
                 } // otherwise just continue
             } else {
@@ -202,6 +214,7 @@
         ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
         if (amt < 0) {
             if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
+                if (DEBUG) ALOGD("Fail to read fromFd %d: %s", fromFd, strerror(errno));
                 return -errno;
             } // otherwise just continue
         } else if (amt == 0) {
diff --git a/cmds/incidentd/src/FdBuffer.h b/cmds/incidentd/src/FdBuffer.h
index 8857ae7..48dc855 100644
--- a/cmds/incidentd/src/FdBuffer.h
+++ b/cmds/incidentd/src/FdBuffer.h
@@ -47,8 +47,10 @@
      * and stores the processed data from 'fromFd' in memory for later usage.
      * This function behaves in a streaming fashion in order to save memory usage.
      * Returns NO_ERROR if there were no errors or if we timed out.
+     *
+     * Poll will return POLLERR if fd is from sysfs, handle this edge case.
      */
-    status_t readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs);
+    status_t readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs, const bool isSysfs=false);
 
     /**
      * Whether we timed out.
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 892bcca..c08b9ea 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -232,6 +232,7 @@
      mFilename(filename)
 {
     name = filename;
+    mIsSysfs = strncmp(filename, "/sys/", 5) == 0;
 }
 
 FileSection::~FileSection() {}
@@ -264,7 +265,7 @@
 
     // parent process
     status_t readStatus = buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(), c2pPipe.readFd(),
-            this->timeoutMs);
+            this->timeoutMs, mIsSysfs);
     if (readStatus != NO_ERROR || buffer.timedOut()) {
         ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s, kill: %s",
             this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false",
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 0a1e03e..64558a6 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -69,6 +69,7 @@
 
 private:
     const char* mFilename;
+    bool mIsSysfs; // sysfs files are pollable but return POLLERR by default, handle it separately
 };
 
 /**