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/incident_helper/Android.bp b/cmds/incident_helper/Android.bp
new file mode 100644
index 0000000..3ea823c
--- /dev/null
+++ b/cmds/incident_helper/Android.bp
@@ -0,0 +1,50 @@
+cc_defaults {
+    name: "incident_helper_defaults",
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-g",
+        "-O0"
+    ],
+
+    srcs: [
+        "IncidentHelper.cpp",
+        "strutil.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libprotobuf-cpp-full",
+        "libutils",
+    ],
+
+    static_libs: [
+        "libplatformprotos",
+    ],
+}
+
+cc_binary {
+    name: "incident_helper",
+    defaults: ["incident_helper_defaults"],
+    srcs: ["main.cpp"],
+}
+
+
+cc_test {
+    name: "incident_helper_test",
+    defaults: ["incident_helper_defaults"],
+
+    srcs: [
+        "tests/IncidentHelper_test.cpp",
+    ],
+
+    data: [
+        "testdata/*",
+    ],
+
+    static_libs: [
+        "libgmock",
+    ],
+}
\ No newline at end of file
diff --git a/cmds/incident_helper/IncidentHelper.cpp b/cmds/incident_helper/IncidentHelper.cpp
new file mode 100644
index 0000000..89d8947
--- /dev/null
+++ b/cmds/incident_helper/IncidentHelper.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "incident_helper"
+
+#include "IncidentHelper.h"
+#include "strutil.h"
+
+#include "frameworks/base/core/proto/android/os/kernelwake.pb.h"
+
+#include <algorithm>
+#include <android-base/file.h>
+#include <unistd.h>
+#include <sstream>
+#include <string>
+#include <vector>
+
+using namespace android::base;
+using namespace android::os;
+using namespace std;
+
+// ================================================================================
+status_t ReverseParser::Parse(const int in, const int out) const
+{
+    string content;
+    if (!ReadFdToString(in, &content)) {
+        fprintf(stderr, "[%s]Failed to read data from incidentd\n", this->name.string());
+        return -1;
+    }
+    // reverse the content
+    reverse(content.begin(), content.end());
+    if (!WriteStringToFd(content, out)) {
+        fprintf(stderr, "[%s]Failed to write data to incidentd\n", this->name.string());
+        return -1;
+    }
+    return NO_ERROR;
+}
+
+// ================================================================================
+// This list must be in order and sync with kernelwake.proto
+const char* kernel_wake_headers[] = {
+    "name",                  // id:  1
+    "active_count",          // id:  2
+    "event_count",           // id:  3
+    "wakeup_count",          // id:  4
+    "expire_count",          // id:  5
+    "active_since",          // id:  6
+    "total_time",            // id:  7
+    "max_time",              // id:  8
+    "last_change",           // id:  9
+    "prevent_suspend_time",  // id: 10
+};
+
+const string KERNEL_WAKEUP_LINE_DELIMITER = "\t";
+
+status_t KernelWakesParser::Parse(const int in, const int out) const {
+    // read the content, this is not memory-efficient though since it loads everything
+    // However the data will be held in proto anyway, and incident_helper is less critical
+    string content;
+    if (!ReadFdToString(in, &content)) {
+        fprintf(stderr, "[%s]Failed to read data from incidentd\n", this->name.string());
+        return -1;
+    }
+
+    istringstream iss(content);
+    string line;
+    vector<string> header;  // the header of /d/wakeup_sources
+    vector<string> record;  // retain each record
+    int nline = 0;
+
+    KernelWakeSources proto;
+
+    // parse line by line
+    while (getline(iss, line)) {
+        // parse head line
+        if (nline == 0) {
+          split(line, &header);
+          if (!assertHeaders(kernel_wake_headers, header)) {
+            fprintf(stderr, "[%s]Bad header:\n%s\n", this->name.string(), line.c_str());
+            return BAD_VALUE;
+          }
+          nline++;
+          continue;
+        }
+
+        // parse for each record, the line delimiter is \t only!
+        split(line, &record, KERNEL_WAKEUP_LINE_DELIMITER);
+
+        if (record.size() != header.size()) {
+          // TODO: log this to incident report!
+          fprintf(stderr, "[%s]Line %d has missing fields\n%s\n", this->name.string(), nline, line.c_str());
+          continue;
+        }
+
+        WakeupSourceProto* source = proto.add_wakeup_sources();
+        source->set_name(record.at(0).c_str());
+        // below are int32
+        source->set_active_count(atoi(record.at(1).c_str()));
+        source->set_event_count(atoi(record.at(2).c_str()));
+        source->set_wakeup_count(atoi(record.at(3).c_str()));
+        source->set_expire_count(atoi(record.at(4).c_str()));
+        // below are int64
+        source->set_active_since(atol(record.at(5).c_str()));
+        source->set_total_time(atol(record.at(6).c_str()));
+        source->set_max_time(atol(record.at(7).c_str()));
+        source->set_last_change(atol(record.at(8).c_str()));
+        source->set_prevent_suspend_time(atol(record.at(9).c_str()));
+
+        nline++;
+    }
+
+    fprintf(stderr, "[%s]Proto size: %d bytes\n", this->name.string(), proto.ByteSize());
+
+    if (!proto.SerializeToFileDescriptor(out)) {
+        fprintf(stderr, "[%s]Error writing proto back\n", this->name.string());
+        return -1;
+    }
+    close(out);
+
+    return NO_ERROR;
+}
diff --git a/cmds/incident_helper/IncidentHelper.h b/cmds/incident_helper/IncidentHelper.h
new file mode 100644
index 0000000..40792a8
--- /dev/null
+++ b/cmds/incident_helper/IncidentHelper.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCIDENT_HELPER_H
+#define INCIDENT_HELPER_H
+
+#include <utils/Errors.h>
+#include <utils/String8.h>
+
+using namespace android;
+
+/**
+ * Base class for text parser
+ */
+class TextParserBase {
+public:
+    String8 name;
+
+    TextParserBase(String8 name) : name(name) {};
+    virtual ~TextParserBase() {};
+
+    virtual status_t Parse(const int in, const int out) const = 0;
+};
+
+/**
+ * This parser is used for testing only, results in timeout.
+ */
+class TimeoutParser : public TextParserBase {
+public:
+    TimeoutParser() : TextParserBase(String8("TimeoutParser")) {};
+    ~TimeoutParser() {};
+
+    virtual status_t Parse(const int /** in */, const int /** out */) const { while (true); };
+};
+
+/**
+ * This parser is used for testing only, results in reversed input text.
+ */
+class ReverseParser : public TextParserBase {
+public:
+    ReverseParser() : TextParserBase(String8("ReverseParser")) {};
+    ~ReverseParser() {};
+
+    virtual status_t Parse(const int in, const int out) const;
+};
+
+/**
+ * Kernel wakeup sources parser, parses text to protobuf in /d/wakeup_sources
+ */
+extern const char* kernel_wake_headers[];
+
+class KernelWakesParser : public TextParserBase {
+public:
+    KernelWakesParser() : TextParserBase(String8("KernelWakeSources")) {};
+    ~KernelWakesParser() {};
+
+    virtual status_t Parse(const int in, const int out) const;
+};
+
+#endif  // INCIDENT_HELPER_H
diff --git a/cmds/incident_helper/README.md b/cmds/incident_helper/README.md
new file mode 100644
index 0000000..967f1e3
--- /dev/null
+++ b/cmds/incident_helper/README.md
@@ -0,0 +1,17 @@
+# incident_helper
+
+## How to build, deploy, unit test
+
+For the first time, build the test and create an empty directly on device:
+
+```
+root$ make -j incident_helper_test && adb shell mkdir /data/nativetest64/incident_helper_test
+```
+
+Run the test on a device
+
+```
+root$ mmm -j frameworks/base/cmds/incident_helper && \
+adb push $OUT/data/nativetest64/incident_helper_test/* /data/nativetest64/incident_helper_test/ && \
+adb shell /data/nativetest64/incident_helper_test/incident_helper_test 2>/dev/null
+```
diff --git a/cmds/incident_helper/main.cpp b/cmds/incident_helper/main.cpp
new file mode 100644
index 0000000..1e25c85
--- /dev/null
+++ b/cmds/incident_helper/main.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "incident_helper"
+
+#include "IncidentHelper.h"
+
+#include <android-base/file.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+using namespace android::base;
+using namespace std;
+
+static void usage(FILE* out) {
+    fprintf(out, "incident_helper is not designed to run manually, see README.md\n");
+    fprintf(out, "usage: incident_helper -s SECTION -i INPUT -o OUTPUT\n");
+    fprintf(out, "REQUIRED:\n");
+    fprintf(out, "  -s           section id, must be positive\n");
+    fprintf(out, "  -i           (default stdin) input fd\n");
+    fprintf(out, "  -o           (default stdout) output fd\n");
+}
+
+//=============================================================================
+static TextParserBase* selectParser(int section) {
+    switch (section) {
+        // IDs smaller than or equal to 0 are reserved for testing
+        case -1:
+            return new TimeoutParser();
+        case 0:
+            return new ReverseParser();
+/* ========================================================================= */
+        // IDs larger than 0 are reserved in incident.proto
+        case 2002:
+            return new KernelWakesParser();
+        default:
+            return NULL;
+    }
+}
+
+//=============================================================================
+int main(int argc, char** argv) {
+    fprintf(stderr, "Start incident_helper...\n");
+
+    // Parse the args
+    int opt;
+    int sectionID = 0;
+    int inputFd = STDIN_FILENO;
+    int outputFd = STDOUT_FILENO;
+    while ((opt = getopt(argc, argv, "hs:i:o:")) != -1) {
+        switch (opt) {
+            case 'h':
+                usage(stdout);
+                return 0;
+            case 's':
+                sectionID = atoi(optarg);
+                break;
+            case 'i':
+                inputFd = atoi(optarg);
+                break;
+            case 'o':
+                outputFd = atoi(optarg);
+                break;
+        }
+    }
+
+    // Check mandatory parameters:
+    if (inputFd < 0) {
+        fprintf(stderr, "invalid input fd: %d\n", inputFd);
+        return 1;
+    }
+    if (outputFd < 0) {
+        fprintf(stderr, "invalid output fd: %d\n", outputFd);
+        return 1;
+    }
+
+    fprintf(stderr, "Pasring section %d...\n", sectionID);
+    TextParserBase* parser = selectParser(sectionID);
+    if (parser != NULL) {
+        fprintf(stderr, "Running parser: %s\n", parser->name.string());
+        status_t err = parser->Parse(inputFd, outputFd);
+        if (err != NO_ERROR) {
+            fprintf(stderr, "Parse error in section %d: %s\n", sectionID, strerror(-err));
+            return -1;
+        }
+
+        delete parser;
+    }
+    fprintf(stderr, "Finish section %d, exiting...\n", sectionID);
+
+    return 0;
+}
diff --git a/cmds/incident_helper/strutil.cpp b/cmds/incident_helper/strutil.cpp
new file mode 100644
index 0000000..21b04a1
--- /dev/null
+++ b/cmds/incident_helper/strutil.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "incident_helper"
+
+#include "strutil.h"
+
+#include <sstream>
+
+std::string trim(const std::string& s, const std::string& whitespace) {
+    const auto head = s.find_first_not_of(whitespace);
+    if (head == std::string::npos) return "";
+
+    const auto tail = s.find_last_not_of(whitespace);
+    return s.substr(head, tail - head + 1);
+}
+
+// This is similiar to Split in android-base/file.h, but it won't add empty string
+void split(const std::string& line, std::vector<std::string>* words, const std::string& delimiters) {
+    words->clear();  // clear the buffer before split
+
+    size_t base = 0;
+    size_t found;
+    while (true) {
+        found = line.find_first_of(delimiters, base);
+        if (found != base) { // ignore empty string
+            // one char before found
+            words->push_back(line.substr(base, found - base));
+        }
+        if (found == line.npos) break;
+        base = found + 1;
+    }
+}
+
+bool assertHeaders(const char* expected[], const std::vector<std::string>& actual) {
+    for (size_t i = 0; i < actual.size(); i++) {
+        if (expected[i] == NULL || std::string(expected[i]) != actual.at(i)) {
+            return false;
+        }
+    }
+    return true;
+}
diff --git a/cmds/incident_helper/strutil.h b/cmds/incident_helper/strutil.h
new file mode 100644
index 0000000..fcc164d
--- /dev/null
+++ b/cmds/incident_helper/strutil.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STRUTIL_H
+#define STRUTIL_H
+
+#include <string>
+#include <vector>
+
+const std::string DEFAULT_WHITESPACE = " \t";
+
+std::string trim(const std::string& s, const std::string& whitespace = DEFAULT_WHITESPACE);
+void split(const std::string& line, std::vector<std::string>* words,
+    const std::string& delimiters = DEFAULT_WHITESPACE);
+bool assertHeaders(const char* expected[], const std::vector<std::string>& actual);
+
+#endif  // STRUTIL_H
diff --git a/cmds/incident_helper/testdata/kernel_wakeups.txt b/cmds/incident_helper/testdata/kernel_wakeups.txt
new file mode 100644
index 0000000..7f627cf
--- /dev/null
+++ b/cmds/incident_helper/testdata/kernel_wakeups.txt
@@ -0,0 +1,3 @@
+name		active_count	event_count	wakeup_count	expire_count	active_since	total_time	max_time	last_change	prevent_suspend_time
+ipc000000ab_ATFWD-daemon	8		8		0		0		0		0		0		131348		0
+ipc000000aa_ATFWD-daemon	143		143		0		0		0		123		3		2067286206		0
\ No newline at end of file
diff --git a/cmds/incident_helper/testdata/kernel_wakeups_bad_headers.txt b/cmds/incident_helper/testdata/kernel_wakeups_bad_headers.txt
new file mode 100644
index 0000000..4914d2e
--- /dev/null
+++ b/cmds/incident_helper/testdata/kernel_wakeups_bad_headers.txt
@@ -0,0 +1,3 @@
+THIS IS BAD HEADER
+ipc000000ab_ATFWD-daemon	8		8		0		0		0		0		0		131348		0
+ipc000000aa_ATFWD-daemon	143		143		0		0		0		123		3		2067286206		0
\ No newline at end of file
diff --git a/cmds/incident_helper/tests/IncidentHelper_test.cpp b/cmds/incident_helper/tests/IncidentHelper_test.cpp
new file mode 100644
index 0000000..9d5d9e4
--- /dev/null
+++ b/cmds/incident_helper/tests/IncidentHelper_test.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "IncidentHelper.h"
+
+#include "frameworks/base/core/proto/android/os/kernelwake.pb.h"
+
+#include <android-base/file.h>
+#include <android-base/test_utils.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <string.h>
+#include <fcntl.h>
+
+using namespace android::base;
+using namespace android::os;
+using ::testing::StrEq;
+using ::testing::Test;
+using ::testing::internal::CaptureStderr;
+using ::testing::internal::CaptureStdout;
+using ::testing::internal::GetCapturedStderr;
+using ::testing::internal::GetCapturedStdout;
+
+class IncidentHelperTest : public Test {
+public:
+    virtual void SetUp() override {
+
+    }
+
+protected:
+    const std::string kTestPath = GetExecutableDirectory();
+    const std::string kTestDataPath = kTestPath + "/testdata/";
+};
+
+TEST_F(IncidentHelperTest, ReverseParser) {
+    ReverseParser parser;
+    TemporaryFile tf;
+
+    ASSERT_TRUE(tf.fd != -1);
+    ASSERT_TRUE(WriteStringToFile("TestData", tf.path, false));
+
+    CaptureStdout();
+    ASSERT_EQ(NO_ERROR, parser.Parse(tf.fd, STDOUT_FILENO));
+    EXPECT_THAT(GetCapturedStdout(), StrEq("ataDtseT"));
+}
+
+TEST_F(IncidentHelperTest, KernelWakesParser) {
+    const std::string testFile = kTestDataPath + "kernel_wakeups.txt";
+    KernelWakesParser parser;
+    KernelWakeSources expected;
+    std::string expectedStr;
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+
+    WakeupSourceProto* record1 = expected.add_wakeup_sources();
+    record1->set_name("ipc000000ab_ATFWD-daemon");
+    record1->set_active_count(8);
+    record1->set_event_count(8);
+    record1->set_wakeup_count(0);
+    record1->set_expire_count(0);
+    record1->set_active_since(0l);
+    record1->set_total_time(0l);
+    record1->set_max_time(0l);
+    record1->set_last_change(131348l);
+    record1->set_prevent_suspend_time(0l);
+
+    WakeupSourceProto* record2 = expected.add_wakeup_sources();
+    record2->set_name("ipc000000aa_ATFWD-daemon");
+    record2->set_active_count(143);
+    record2->set_event_count(143);
+    record2->set_wakeup_count(0);
+    record2->set_expire_count(0);
+    record2->set_active_since(0l);
+    record2->set_total_time(123l);
+    record2->set_max_time(3l);
+    record2->set_last_change(2067286206l);
+    record2->set_prevent_suspend_time(0l);
+
+    ASSERT_TRUE(expected.SerializeToFileDescriptor(tf.fd));
+    ASSERT_TRUE(ReadFileToString(tf.path, &expectedStr));
+
+    int fd = open(testFile.c_str(), O_RDONLY, 0444);
+    ASSERT_TRUE(fd != -1);
+
+    CaptureStdout();
+    ASSERT_EQ(NO_ERROR, parser.Parse(fd, STDOUT_FILENO));
+    EXPECT_EQ(GetCapturedStdout(), expectedStr);
+    close(fd);
+}
+
+TEST_F(IncidentHelperTest, KernelWakesParserBadHeaders) {
+    const std::string testFile = kTestDataPath + "kernel_wakeups_bad_headers.txt";
+    KernelWakesParser parser;
+
+    int fd = open(testFile.c_str(), O_RDONLY, 0444);
+    ASSERT_TRUE(fd != -1);
+
+    CaptureStdout();
+    CaptureStderr();
+    ASSERT_EQ(BAD_VALUE, parser.Parse(fd, STDOUT_FILENO));
+    EXPECT_THAT(GetCapturedStdout(), StrEq(""));
+    EXPECT_THAT(GetCapturedStderr(), StrEq("[KernelWakeSources]Bad header:\nTHIS IS BAD HEADER\n"));
+    close(fd);
+}