Implement c++ native lib for streaming proto, part 1

Extract protobuf class out and creates EncodedBuffer class
which holds protobuf data.
Next step is to create a ProtoOutputStream and let incident helper
adapt the change as well.
please see frameworks/base/core/java/android/util/proto

Bug: 65641021
Test: unit tested
Change-Id: I0dd343b2e62d60f091c8f857fae3452ec8da6b96
diff --git a/cmds/incidentd/src/EncodedBuffer.cpp b/cmds/incidentd/src/EncodedBuffer.cpp
deleted file mode 100644
index e8f2c11..0000000
--- a/cmds/incidentd/src/EncodedBuffer.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * 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 "EncodedBuffer.h"
-#include "io_util.h"
-#include "protobuf.h"
-
-#include <deque>
-
-const size_t BUFFER_SIZE = 4 * 1024; // 4 KB
-
-/**
- * Read varint from iterator, the iterator will point to next available byte.
- * Return the number of bytes of the varint.
- */
-static uint32_t
-read_raw_varint(FdBuffer::iterator* it)
-{
-    uint32_t val = 0;
-    int i = 0;
-    bool hasNext = true;
-    while (hasNext) {
-        hasNext = ((**it & 0x80) != 0);
-        val += (**it & 0x7F) << (7*i);
-        (*it)++;
-        i++;
-    }
-    return val;
-}
-
-/**
- * Write the field to buf based on the wire type, iterator will point to next field.
- * If skip is set to true, no data will be written to buf. Return number of bytes written.
- */
-static size_t
-write_field_or_skip(FdBuffer::iterator* iter, vector<uint8_t>* buf, uint8_t wireType, bool skip)
-{
-    FdBuffer::iterator snapshot = iter->snapshot();
-    size_t bytesToWrite = 0;
-    uint32_t varint = 0;
-    switch (wireType) {
-        case WIRE_TYPE_VARINT:
-            varint = read_raw_varint(iter);
-            if(!skip) return write_raw_varint(buf, varint);
-            break;
-        case WIRE_TYPE_FIXED64:
-            bytesToWrite = 8;
-            break;
-        case WIRE_TYPE_LENGTH_DELIMITED:
-            bytesToWrite = read_raw_varint(iter);
-            if(!skip) write_raw_varint(buf, bytesToWrite);
-            break;
-        case WIRE_TYPE_FIXED32:
-            bytesToWrite = 4;
-            break;
-    }
-    if (skip) {
-        *iter += bytesToWrite;
-    } else {
-        for (size_t i=0; i<bytesToWrite; i++) {
-            buf->push_back(**iter);
-            (*iter)++;
-        }
-    }
-    return skip ? 0 : *iter - snapshot;
-}
-
-/**
- * Strip next field based on its private policy and request spec, then stores data in buf.
- * Return NO_ERROR if succeeds, otherwise BAD_VALUE is returned to indicate bad data in FdBuffer.
- *
- * The iterator must point to the head of a protobuf formatted field for successful operation.
- * After exit with NO_ERROR, iterator points to the next protobuf field's head.
- */
-static status_t
-stripField(FdBuffer::iterator* iter, vector<uint8_t>* buf, const Privacy* parentPolicy, const PrivacySpec& spec)
-{
-    if (iter->outOfBound() || parentPolicy == NULL) return BAD_VALUE;
-
-    uint32_t varint = read_raw_varint(iter);
-    uint8_t wireType = read_wire_type(varint);
-    uint32_t fieldId = read_field_id(varint);
-    const Privacy* policy = parentPolicy->lookup(fieldId);
-
-    if (policy == NULL || !policy->IsMessageType() || !policy->HasChildren()) {
-        bool skip = !spec.CheckPremission(policy);
-        size_t amt = buf->size();
-        if (!skip) amt += write_header(buf, fieldId, wireType);
-        amt += write_field_or_skip(iter, buf, wireType, skip); // point to head of next field
-        return buf->size() != amt ? BAD_VALUE : NO_ERROR;
-    }
-    // current field is message type and its sub-fields have extra privacy policies
-    deque<vector<uint8_t>> q;
-    uint32_t msgSize = read_raw_varint(iter);
-    size_t finalSize = 0;
-    FdBuffer::iterator start = iter->snapshot();
-    while ((*iter - start) != (int)msgSize) {
-        vector<uint8_t> v;
-        status_t err = stripField(iter, &v, policy, spec);
-        if (err != NO_ERROR) return err;
-        if (v.empty()) continue;
-        q.push_back(v);
-        finalSize += v.size();
-    }
-
-    write_header(buf, fieldId, wireType);
-    write_raw_varint(buf, finalSize);
-    buf->reserve(finalSize); // reserve the size of the field
-    while (!q.empty()) {
-        vector<uint8_t> subField = q.front();
-        for (vector<uint8_t>::iterator it = subField.begin(); it != subField.end(); it++) {
-            buf->push_back(*it);
-        }
-        q.pop_front();
-    }
-    return NO_ERROR;
-}
-
-// ================================================================================
-EncodedBuffer::EncodedBuffer(const FdBuffer& buffer, const Privacy* policy)
-        : mFdBuffer(buffer),
-          mPolicy(policy),
-          mBuffers(),
-          mSize(0)
-{
-}
-
-EncodedBuffer::~EncodedBuffer()
-{
-}
-
-status_t
-EncodedBuffer::strip(const PrivacySpec& spec)
-{
-    // optimization when no strip happens
-    if (mPolicy == NULL || !mPolicy->HasChildren() || spec.RequireAll()) {
-        if (spec.CheckPremission(mPolicy)) mSize = mFdBuffer.size();
-        return NO_ERROR;
-    }
-
-    FdBuffer::iterator it = mFdBuffer.begin();
-    vector<uint8_t> field;
-    field.reserve(BUFFER_SIZE);
-
-    while (it != mFdBuffer.end()) {
-        status_t err = stripField(&it, &field, mPolicy, spec);
-        if (err != NO_ERROR) return err;
-        if (field.size() > BUFFER_SIZE) { // rotate to another chunk if buffer size exceeds
-            mBuffers.push_back(field);
-            mSize += field.size();
-            field.clear();
-        }
-    }
-    if (!field.empty()) {
-        mBuffers.push_back(field);
-        mSize += field.size();
-    }
-    return NO_ERROR;
-}
-
-void
-EncodedBuffer::clear()
-{
-    mSize = 0;
-    mBuffers.clear();
-}
-
-size_t
-EncodedBuffer::size() const { return mSize; }
-
-status_t
-EncodedBuffer::flush(int fd)
-{
-    if (size() == mFdBuffer.size()) return mFdBuffer.flush(fd);
-
-    for (vector<vector<uint8_t>>::iterator it = mBuffers.begin(); it != mBuffers.end(); it++) {
-        status_t err = write_all(fd, it->data(), it->size());
-        if (err != NO_ERROR) return err;
-    }
-    return NO_ERROR;
-}
-
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index bb399b5..b7633a4 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "incidentd"
 
 #include "FdBuffer.h"
-#include "io_util.h"
 
 #include <cutils/log.h>
 #include <utils/SystemClock.h>
@@ -31,10 +30,9 @@
 const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
 
 FdBuffer::FdBuffer()
-    :mBuffers(),
+    :mBuffer(BUFFER_SIZE),
      mStartTime(-1),
      mFinishTime(-1),
-     mCurrentWritten(-1),
      mTimedOut(false),
      mTruncated(false)
 {
@@ -42,11 +40,6 @@
 
 FdBuffer::~FdBuffer()
 {
-    const int N = mBuffers.size();
-    for (int i=0; i<N; i++) {
-        uint8_t* buf = mBuffers[i];
-        free(buf);
-    }
 }
 
 status_t
@@ -60,20 +53,12 @@
 
     fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
 
-    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;
+        if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
+            mTruncated = true;
+            break;
         }
+        if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
 
         int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
         if (remainingTime <= 0) {
@@ -91,7 +76,7 @@
             if ((pfds.revents & POLLERR) != 0) {
                 return errno != 0 ? -errno : UNKNOWN_ERROR;
             } else {
-                ssize_t amt = ::read(fd, buf + mCurrentWritten, BUFFER_SIZE - mCurrentWritten);
+                ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
                 if (amt < 0) {
                     if (errno == EAGAIN || errno == EWOULDBLOCK) {
                         continue;
@@ -101,11 +86,10 @@
                 } else if (amt == 0) {
                     break;
                 }
-                mCurrentWritten += amt;
+                mBuffer.wp()->move(amt);
             }
         }
     }
-
     mFinishTime = uptimeMillis();
     return NO_ERROR;
 }
@@ -132,20 +116,12 @@
     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;
+        if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
+            mTruncated = true;
+            break;
         }
+        if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
 
         int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
         if (remainingTime <= 0) {
@@ -223,7 +199,7 @@
         }
 
         // read from parsing process
-        ssize_t amt = ::read(fromFd, buf + mCurrentWritten, BUFFER_SIZE - mCurrentWritten);
+        ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
         if (amt < 0) {
             if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
                 return -errno;
@@ -231,7 +207,7 @@
         } else if (amt == 0) {
             break;
         } else {
-            mCurrentWritten += amt;
+            mBuffer.wp()->move(amt);
         }
     }
 
@@ -242,105 +218,11 @@
 size_t
 FdBuffer::size() const
 {
-    if (mBuffers.empty()) return 0;
-    return ((mBuffers.size() - 1) * BUFFER_SIZE) + mCurrentWritten;
+    return mBuffer.size();
 }
 
-status_t
-FdBuffer::flush(int fd) const
+EncodedBuffer::iterator
+FdBuffer::data() const
 {
-    size_t i=0;
-    status_t err = NO_ERROR;
-    for (i=0; i<mBuffers.size()-1; i++) {
-        err = write_all(fd, mBuffers[i], BUFFER_SIZE);
-        if (err != NO_ERROR) return err;
-    }
-    return write_all(fd, mBuffers[i], mCurrentWritten);
-}
-
-FdBuffer::iterator
-FdBuffer::begin() const
-{
-    return iterator(*this, 0, 0);
-}
-
-FdBuffer::iterator
-FdBuffer::end() const
-{
-    if (mBuffers.empty() || mCurrentWritten < 0) return begin();
-    if (mCurrentWritten == BUFFER_SIZE)
-        // FdBuffer doesn't allocate another buf since no more bytes to read.
-        return FdBuffer::iterator(*this, mBuffers.size(), 0);
-    return FdBuffer::iterator(*this, mBuffers.size() - 1, mCurrentWritten);
-}
-
-// ===============================================================================
-FdBuffer::iterator::iterator(const FdBuffer& buffer, ssize_t index, ssize_t offset)
-        : mFdBuffer(buffer),
-          mIndex(index),
-          mOffset(offset)
-{
-}
-
-FdBuffer::iterator&
-FdBuffer::iterator::operator=(iterator& other) const { return other; }
-
-FdBuffer::iterator&
-FdBuffer::iterator::operator+(size_t offset)
-{
-    size_t newOffset = mOffset + offset;
-    while (newOffset >= BUFFER_SIZE) {
-        mIndex++;
-        newOffset -= BUFFER_SIZE;
-    }
-    mOffset = newOffset;
-    return *this;
-}
-
-FdBuffer::iterator&
-FdBuffer::iterator::operator+=(size_t offset) { return *this + offset; }
-
-FdBuffer::iterator&
-FdBuffer::iterator::operator++() { return *this + 1; }
-
-FdBuffer::iterator
-FdBuffer::iterator::operator++(int) { return *this + 1; }
-
-bool
-FdBuffer::iterator::operator==(iterator other) const
-{
-    return mIndex == other.mIndex && mOffset == other.mOffset;
-}
-
-bool
-FdBuffer::iterator::operator!=(iterator other) const { return !(*this == other); }
-
-int
-FdBuffer::iterator::operator-(iterator other) const
-{
-    return (int)bytesRead() - (int)other.bytesRead();
-}
-
-FdBuffer::iterator::reference
-FdBuffer::iterator::operator*() const
-{
-    return mFdBuffer.mBuffers[mIndex][mOffset];
-}
-
-FdBuffer::iterator
-FdBuffer::iterator::snapshot() const
-{
-    return FdBuffer::iterator(mFdBuffer, mIndex, mOffset);
-}
-
-size_t
-FdBuffer::iterator::bytesRead() const
-{
-    return mIndex * BUFFER_SIZE + mOffset;
-}
-
-bool
-FdBuffer::iterator::outOfBound() const
-{
-    return bytesRead() > mFdBuffer.size();
+    return mBuffer.begin();
 }
diff --git a/cmds/incidentd/src/FdBuffer.h b/cmds/incidentd/src/FdBuffer.h
index dfe39c6..8857ae7 100644
--- a/cmds/incidentd/src/FdBuffer.h
+++ b/cmds/incidentd/src/FdBuffer.h
@@ -17,11 +17,11 @@
 #ifndef FD_BUFFER_H
 #define FD_BUFFER_H
 
+#include <android/util/EncodedBuffer.h>
 #include <utils/Errors.h>
 
-#include <vector>
-
 using namespace android;
+using namespace android::util;
 using namespace std;
 
 /**
@@ -71,52 +71,19 @@
     size_t size() const;
 
     /**
-     * Flush all the data to given file descriptor;
-     */
-    status_t flush(int fd) const;
-
-    /**
      * How long the read took in milliseconds.
      */
     int64_t durationMs() const { return mFinishTime - mStartTime; }
 
     /**
-     * Read data stored in FdBuffer
+     * Reader API for data stored in FdBuffer
      */
-    class iterator;
-    friend class iterator;
-    class iterator : public std::iterator<std::random_access_iterator_tag, uint8_t> {
-    public:
-        iterator(const FdBuffer& buffer, ssize_t index, ssize_t offset);
-        iterator& operator=(iterator& other) const;
-        iterator& operator+(size_t offset);
-        iterator& operator+=(size_t offset);
-        iterator& operator++();
-        iterator operator++(int);
-        bool operator==(iterator other) const;
-        bool operator!=(iterator other) const;
-        int operator-(iterator other) const;
-        reference operator*() const;
-
-        // return the snapshot of the current iterator
-        iterator snapshot() const;
-        // how many bytes are read
-        size_t bytesRead() const;
-        // random access could make the iterator out of bound
-        bool outOfBound() const;
-    private:
-        const FdBuffer& mFdBuffer;
-        size_t mIndex;
-        size_t mOffset;
-    };
-    iterator begin() const;
-    iterator end() const;
+    EncodedBuffer::iterator data() const;
 
 private:
-    vector<uint8_t*> mBuffers;
+    EncodedBuffer mBuffer;
     int64_t mStartTime;
     int64_t mFinishTime;
-    ssize_t mCurrentWritten;
     bool mTimedOut;
     bool mTruncated;
 };
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
new file mode 100644
index 0000000..07a064cf
--- /dev/null
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -0,0 +1,168 @@
+/*
+ * 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 "PrivacyBuffer.h"
+#include "io_util.h"
+
+#include <android/util/protobuf.h>
+#include <deque>
+
+using namespace android::util;
+
+/**
+ * Write the field to buf based on the wire type, iterator will point to next field.
+ * If skip is set to true, no data will be written to buf. Return number of bytes written.
+ */
+static size_t
+write_field_or_skip(EncodedBuffer::iterator* iter, EncodedBuffer* buf, uint8_t wireType, bool skip)
+{
+    EncodedBuffer::Pointer snapshot = iter->rp()->copy();
+    size_t bytesToWrite = 0;
+    uint32_t varint = 0;
+    switch (wireType) {
+        case WIRE_TYPE_VARINT:
+            varint = iter->readRawVarint();
+            if(!skip) return buf->writeRawVarint(varint);
+            break;
+        case WIRE_TYPE_FIXED64:
+            bytesToWrite = 8;
+            break;
+        case WIRE_TYPE_LENGTH_DELIMITED:
+            bytesToWrite = iter->readRawVarint();
+            if(!skip) buf->writeRawVarint(bytesToWrite);
+            break;
+        case WIRE_TYPE_FIXED32:
+            bytesToWrite = 4;
+            break;
+    }
+    if (skip) {
+        iter->rp()->move(bytesToWrite);
+    } else {
+        for (size_t i=0; i<bytesToWrite; i++) {
+            *buf->writeBuffer() = iter->next();
+            buf->wp()->move();
+        }
+    }
+    return skip ? 0 : iter->rp()->pos() - snapshot.pos();
+}
+
+/**
+ * Strip next field based on its private policy and request spec, then stores data in buf.
+ * Return NO_ERROR if succeeds, otherwise BAD_VALUE is returned to indicate bad data in FdBuffer.
+ *
+ * The iterator must point to the head of a protobuf formatted field for successful operation.
+ * After exit with NO_ERROR, iterator points to the next protobuf field's head.
+ */
+static status_t
+stripField(EncodedBuffer::iterator* iter, EncodedBuffer* buf, const Privacy* parentPolicy, const PrivacySpec& spec)
+{
+    if (!iter->hasNext() || parentPolicy == NULL) return BAD_VALUE;
+    uint32_t varint = iter->readRawVarint();
+    uint8_t wireType = read_wire_type(varint);
+    uint32_t fieldId = read_field_id(varint);
+    const Privacy* policy = parentPolicy->lookup(fieldId);
+
+    if (policy == NULL || !policy->IsMessageType() || !policy->HasChildren()) {
+        bool skip = !spec.CheckPremission(policy);
+        size_t amt = buf->size();
+        if (!skip) amt += buf->writeHeader(fieldId, wireType);
+        amt += write_field_or_skip(iter, buf, wireType, skip); // point to head of next field
+        return buf->size() != amt ? BAD_VALUE : NO_ERROR;
+    }
+    // current field is message type and its sub-fields have extra privacy policies
+    deque<EncodedBuffer*> q;
+    uint32_t msgSize = iter->readRawVarint();
+    size_t finalSize = 0;
+    EncodedBuffer::Pointer start = iter->rp()->copy();
+    while (iter->rp()->pos() - start.pos() != msgSize) {
+        EncodedBuffer* v = new EncodedBuffer();
+        status_t err = stripField(iter, v, policy, spec);
+        if (err != NO_ERROR) return err;
+        if (v->size() == 0) continue;
+        q.push_back(v);
+        finalSize += v->size();
+    }
+
+    buf->writeHeader(fieldId, wireType);
+    buf->writeRawVarint(finalSize);
+    while (!q.empty()) {
+        EncodedBuffer* subField = q.front();
+        EncodedBuffer::iterator it = subField->begin();
+        while (it.hasNext()) {
+            *buf->writeBuffer() = it.next();
+            buf->wp()->move();
+        }
+        q.pop_front();
+        delete subField;
+    }
+    return NO_ERROR;
+}
+
+// ================================================================================
+PrivacyBuffer::PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator& data)
+        :mPolicy(policy),
+         mData(data),
+         mBuffer(0),
+         mSize(0)
+{
+}
+
+PrivacyBuffer::~PrivacyBuffer()
+{
+}
+
+status_t
+PrivacyBuffer::strip(const PrivacySpec& spec)
+{
+    // optimization when no strip happens
+    if (mPolicy == NULL || !mPolicy->HasChildren() || spec.RequireAll()) {
+        if (spec.CheckPremission(mPolicy)) mSize = mData.size();
+        return NO_ERROR;
+    }
+    while (mData.hasNext()) {
+        status_t err = stripField(&mData, &mBuffer, mPolicy, spec);
+        if (err != NO_ERROR) return err;
+    }
+    if (mData.bytesRead() != mData.size()) return BAD_VALUE;
+    mSize = mBuffer.size();
+    mData.rp()->rewind(); // rewind the read pointer back to beginning after the strip.
+    return NO_ERROR;
+}
+
+void
+PrivacyBuffer::clear()
+{
+    mSize = 0;
+    mBuffer.wp()->rewind();
+}
+
+size_t
+PrivacyBuffer::size() const { return mSize; }
+
+status_t
+PrivacyBuffer::flush(int fd)
+{
+    status_t err = NO_ERROR;
+    EncodedBuffer::iterator iter = size() == mData.size() ? mData : mBuffer.begin();
+    while (iter.readBuffer() != NULL) {
+        err = write_all(fd, iter.readBuffer(), iter.currentToRead());
+        iter.rp()->move(iter.currentToRead());
+        if (err != NO_ERROR) return err;
+    }
+    return NO_ERROR;
+}
diff --git a/cmds/incidentd/src/EncodedBuffer.h b/cmds/incidentd/src/PrivacyBuffer.h
similarity index 69%
rename from cmds/incidentd/src/EncodedBuffer.h
rename to cmds/incidentd/src/PrivacyBuffer.h
index ea8603a..720b38e 100644
--- a/cmds/incidentd/src/EncodedBuffer.h
+++ b/cmds/incidentd/src/PrivacyBuffer.h
@@ -14,25 +14,27 @@
  * limitations under the License.
  */
 
-#ifndef ENCODED_BUFFER_H
-#define ENCODED_BUFFER_H
+#ifndef PRIVACY_BUFFER_H
+#define PRIVACY_BUFFER_H
 
-#include "FdBuffer.h"
 #include "Privacy.h"
 
+#include <android/util/EncodedBuffer.h>
 #include <stdint.h>
-#include <vector>
+#include <utils/Errors.h>
+
+using namespace android;
+using namespace android::util;
 
 /**
- * EncodedBuffer is constructed from FdBuffer which holds original protobuf formatted data and
- * its privacy policy in its tagged proto message. The class strips PII-sensitive fields
- * based on the request and holds stripped data in its buffer for output.
+ * PrivacyBuffer holds the original protobuf data and strips PII-sensitive fields
+ * based on the request and holds stripped data in its own buffer for output.
  */
-class EncodedBuffer
+class PrivacyBuffer
 {
 public:
-    EncodedBuffer(const FdBuffer& buffer, const Privacy* policy);
-    ~EncodedBuffer();
+    PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator& data);
+    ~PrivacyBuffer();
 
     /**
      * Strip based on the request and hold data in its own buffer. Return NO_ERROR if strip succeeds.
@@ -55,10 +57,11 @@
     status_t flush(int fd);
 
 private:
-    const FdBuffer& mFdBuffer;
     const Privacy* mPolicy;
-    vector<vector<uint8_t>> mBuffers;
+    EncodedBuffer::iterator& mData;
+
+    EncodedBuffer mBuffer;
     size_t mSize;
 };
 
-#endif // ENCODED_BUFFER_H
\ No newline at end of file
+#endif // PRIVACY_BUFFER_H
\ No newline at end of file
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 166fef0..892bcca 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -16,15 +16,15 @@
 
 #define LOG_TAG "incidentd"
 
-#include "EncodedBuffer.h"
 #include "FdBuffer.h"
 #include "Privacy.h"
+#include "PrivacyBuffer.h"
 #include "Section.h"
 
 #include "io_util.h"
-#include "protobuf.h"
 #include "section_list.h"
 
+#include <android/util/protobuf.h>
 #include <private/android_filesystem_config.h>
 #include <binder/IServiceManager.h>
 #include <map>
@@ -32,8 +32,13 @@
 #include <wait.h>
 #include <unistd.h>
 
+using namespace android::util;
 using namespace std;
 
+// special section ids
+const int FIELD_ID_INCIDENT_HEADER = 1;
+
+// incident section parameters
 const int   WAIT_MAX = 5;
 const struct timespec WAIT_INTERVAL_NS = {0, 200 * 1000 * 1000};
 const char* INCIDENT_HELPER = "/system/bin/incident_helper";
@@ -127,7 +132,8 @@
 write_report_requests(const int id, const FdBuffer& buffer, ReportRequestSet* requests)
 {
     status_t err = -EBADF;
-    EncodedBuffer encodedBuffer(buffer, get_privacy_of_section(id));
+    EncodedBuffer::iterator data = buffer.data();
+    PrivacyBuffer privacyBuffer(get_privacy_of_section(id), data);
     int writeable = 0;
 
     // The streaming ones, group requests by spec in order to save unnecessary strip operations
@@ -143,34 +149,34 @@
 
     for (map<PrivacySpec, vector<sp<ReportRequest>>>::iterator mit = requestsBySpec.begin(); mit != requestsBySpec.end(); mit++) {
         PrivacySpec spec = mit->first;
-        err = encodedBuffer.strip(spec);
-        if (err != NO_ERROR) return err; // it means the encodedBuffer data is corrupted.
-        if (encodedBuffer.size() == 0) continue;
+        err = privacyBuffer.strip(spec);
+        if (err != NO_ERROR) return err; // it means the privacyBuffer data is corrupted.
+        if (privacyBuffer.size() == 0) continue;
 
         for (vector<sp<ReportRequest>>::iterator it = mit->second.begin(); it != mit->second.end(); it++) {
             sp<ReportRequest> request = *it;
-            err = write_section_header(request->fd, id, encodedBuffer.size());
+            err = write_section_header(request->fd, id, privacyBuffer.size());
             if (err != NO_ERROR) { request->err = err; continue; }
-            err = encodedBuffer.flush(request->fd);
+            err = privacyBuffer.flush(request->fd);
             if (err != NO_ERROR) { request->err = err; continue; }
             writeable++;
-            ALOGD("Section %d flushed %zu bytes to fd %d with spec %d", id, encodedBuffer.size(), request->fd, spec.dest);
+            ALOGD("Section %d flushed %zu bytes to fd %d with spec %d", id, privacyBuffer.size(), request->fd, spec.dest);
         }
-        encodedBuffer.clear();
+        privacyBuffer.clear();
     }
 
     // The dropbox file
     if (requests->mainFd() >= 0) {
-        err = encodedBuffer.strip(get_default_dropbox_spec());
+        err = privacyBuffer.strip(get_default_dropbox_spec());
         if (err != NO_ERROR) return err; // the buffer data is corrupted.
-        if (encodedBuffer.size() == 0) goto DONE;
+        if (privacyBuffer.size() == 0) goto DONE;
 
-        err = write_section_header(requests->mainFd(), id, encodedBuffer.size());
+        err = write_section_header(requests->mainFd(), id, privacyBuffer.size());
         if (err != NO_ERROR) { requests->setMainFd(-1); goto DONE; }
-        err = encodedBuffer.flush(requests->mainFd());
+        err = privacyBuffer.flush(requests->mainFd());
         if (err != NO_ERROR) { requests->setMainFd(-1); goto DONE; }
         writeable++;
-        ALOGD("Section %d flushed %zu bytes to dropbox %d", id, encodedBuffer.size(), requests->mainFd());
+        ALOGD("Section %d flushed %zu bytes to dropbox %d", id, privacyBuffer.size(), requests->mainFd());
     }
 
 DONE:
diff --git a/cmds/incidentd/src/protobuf.cpp b/cmds/incidentd/src/protobuf.cpp
deleted file mode 100644
index 4fffec1..0000000
--- a/cmds/incidentd/src/protobuf.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2016 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 "protobuf.h"
-
-uint8_t read_wire_type(uint32_t varint)
-{
-    return (uint8_t) (varint & 0x07);
-}
-
-uint32_t read_field_id(uint32_t varint)
-{
-    return varint >> 3;
-}
-
-uint8_t*
-write_raw_varint(uint8_t* buf, uint32_t val)
-{
-    uint8_t* p = buf;
-    while (true) {
-        if ((val & ~0x7F) == 0) {
-            *p++ = (uint8_t)val;
-            return p;
-        } else {
-            *p++ = (uint8_t)((val & 0x7F) | 0x80);
-            val >>= 7;
-        }
-    }
-}
-
-uint8_t*
-write_length_delimited_tag_header(uint8_t* buf, uint32_t fieldId, size_t size)
-{
-    buf = write_raw_varint(buf, (fieldId << 3) | 2);
-    buf = write_raw_varint(buf, size);
-    return buf;
-}
-
-size_t
-write_raw_varint(vector<uint8_t>* buf, uint32_t val)
-{
-    size_t size = 0;
-    while (true) {
-        size++;
-        if ((val & ~0x7F) == 0) {
-            buf->push_back((uint8_t) val);
-            return size;
-        } else {
-            buf->push_back((uint8_t)((val & 0x7F) | 0x80));
-            val >>= 7;
-        }
-    }
-}
-
-size_t
-write_header(vector<uint8_t>* buf, uint32_t fieldId, uint8_t wireType)
-{
-    return write_raw_varint(buf, (fieldId << 3) | wireType);
-}
\ No newline at end of file
diff --git a/cmds/incidentd/src/protobuf.h b/cmds/incidentd/src/protobuf.h
deleted file mode 100644
index 263c864..0000000
--- a/cmds/incidentd/src/protobuf.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2016 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 PROTOBUF_H
-#define PROTOBUF_H
-
-#include <stdint.h>
-#include <vector>
-
-using namespace std;
-
-const uint8_t WIRE_TYPE_VARINT = 0;
-const uint8_t WIRE_TYPE_FIXED64 = 1;
-const uint8_t WIRE_TYPE_LENGTH_DELIMITED = 2;
-const uint8_t WIRE_TYPE_FIXED32 = 5;
-
-/**
- * Read the wire type from varint, it is the smallest 3 bits.
- */
-uint8_t read_wire_type(uint32_t varint);
-
-/**
- * read field id from varint, it is varint >> 3;
- */
-uint32_t read_field_id(uint32_t varint);
-
-/**
- * Write a varint into the buffer. Return the next position to write at.
- * There must be 10 bytes in the buffer. The same as
- * EncodedBuffer.writeRawVarint32
- */
-uint8_t* write_raw_varint(uint8_t* buf, uint32_t val);
-
-/**
- * Write a protobuf WIRE_TYPE_LENGTH_DELIMITED header. Return the next position
- * to write at. There must be 20 bytes in the buffer.
- */
-uint8_t* write_length_delimited_tag_header(uint8_t* buf, uint32_t fieldId, size_t size);
-
-/**
- * Write a varint into a vector. Return the size of the varint.
- */
-size_t write_raw_varint(vector<uint8_t>* buf, uint32_t val);
-
-/**
- * Write a protobuf header. Return the size of the header.
- */
-size_t write_header(vector<uint8_t>* buf, uint32_t fieldId, uint8_t wireType);
-
-enum {
-    // IncidentProto.header
-    FIELD_ID_INCIDENT_HEADER = 1
-};
-
-#endif  // PROTOBUF_H