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