Fix recovery of stats data from previous input while using
ProtoOutputStream
- Specify the length of message to avoid libprotoutil from thinking that
we are trying to write bool
- We only attach the previous dump file to the upload file where config
key matches
- Store ConfigMetricsReport (instead of ConfigMetricsReportList) onto
disk
- Stop use stack after scope in StorageManager
- Migrate UidMap to use ProtoOutputStream and renaming variables to
prevent confusion
Bug: 74021554
Bug: 75968524
Test: manual test, statsd_test, CTS tests
Change-Id: Iedf52633d7f5b985f5a934a3fb5a0c3c3b2e7fd1
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 652ec9d..4a1e3d6 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -231,14 +231,13 @@
}
}
+/*
+ * onDumpReport dumps serialized ConfigMetricsReportList into outData.
+ */
void StatsLogProcessor::onDumpReport(const ConfigKey& key, const uint64_t dumpTimeStampNs,
vector<uint8_t>* outData) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
- onDumpReportLocked(key, dumpTimeStampNs, outData);
-}
-void StatsLogProcessor::onDumpReportLocked(const ConfigKey& key, const uint64_t dumpTimeStampNs,
- vector<uint8_t>* outData) {
auto it = mMetricsManagers.find(key);
if (it == mMetricsManagers.end()) {
ALOGW("Config source %s does not exist", key.ToString().c_str());
@@ -261,35 +260,14 @@
// Start of ConfigMetricsReport (reports).
uint64_t reportsToken =
proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
-
- int64_t lastReportTimeNs = it->second->getLastReportTimeNs();
- int64_t lastReportWallClockNs = it->second->getLastReportWallClockNs();
-
- // First, fill in ConfigMetricsReport using current data on memory, which
- // starts from filling in StatsLogReport's.
- it->second->onDumpReport(dumpTimeStampNs, &proto);
-
- // Fill in UidMap.
- vector<uint8_t> uidMap;
- mUidMap->getOutput(key, &uidMap);
- proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP, uidMap.data());
-
- // Fill in the timestamps.
- proto.write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_ELAPSED_NANOS,
- (long long)lastReportTimeNs);
- proto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS,
- (long long)dumpTimeStampNs);
- proto.write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_WALL_CLOCK_NANOS,
- (long long)lastReportWallClockNs);
- proto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS,
- (long long)getWallClockNs());
-
- // End of ConfigMetricsReport (reports).
+ onConfigMetricsReportLocked(key, dumpTimeStampNs, &proto);
proto.end(reportsToken);
+ // End of ConfigMetricsReport (reports).
+
// Then, check stats-data directory to see there's any file containing
// ConfigMetricsReport from previous shutdowns to concatenate to reports.
- StorageManager::appendConfigMetricsReport(proto);
+ StorageManager::appendConfigMetricsReport(key, &proto);
if (outData != nullptr) {
outData->clear();
@@ -307,6 +285,40 @@
StatsdStats::getInstance().noteMetricsReportSent(key);
}
+/*
+ * onConfigMetricsReportLocked dumps serialized ConfigMetricsReport into outData.
+ */
+void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key,
+ const uint64_t dumpTimeStampNs,
+ ProtoOutputStream* proto) {
+ // We already checked whether key exists in mMetricsManagers in
+ // WriteDataToDisk.
+ auto it = mMetricsManagers.find(key);
+ int64_t lastReportTimeNs = it->second->getLastReportTimeNs();
+ int64_t lastReportWallClockNs = it->second->getLastReportWallClockNs();
+
+ // First, fill in ConfigMetricsReport using current data on memory, which
+ // starts from filling in StatsLogReport's.
+ it->second->onDumpReport(dumpTimeStampNs, proto);
+
+ // Fill in UidMap.
+ uint64_t uidMapToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP);
+ mUidMap->appendUidMap(key, proto);
+ proto->end(uidMapToken);
+
+ // Fill in the timestamps.
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_ELAPSED_NANOS,
+ (long long)lastReportTimeNs);
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS,
+ (long long)dumpTimeStampNs);
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_WALL_CLOCK_NANOS,
+ (long long)lastReportWallClockNs);
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS,
+ (long long)getWallClockNs());
+
+
+}
+
void StatsLogProcessor::OnConfigRemoved(const ConfigKey& key) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
auto it = mMetricsManagers.find(key);
@@ -360,11 +372,17 @@
std::lock_guard<std::mutex> lock(mMetricsMutex);
for (auto& pair : mMetricsManagers) {
const ConfigKey& key = pair.first;
- vector<uint8_t> data;
- onDumpReportLocked(key, getElapsedRealtimeNs(), &data);
+ ProtoOutputStream proto;
+ onConfigMetricsReportLocked(key, getElapsedRealtimeNs(), &proto);
string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
(long)getWallClockSec(), key.GetUid(), (long long)key.GetId());
- StorageManager::writeFile(file_name.c_str(), &data[0], data.size());
+ android::base::unique_fd fd(open(file_name.c_str(),
+ O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
+ if (fd == -1) {
+ VLOG("Attempt to write %s but failed", file_name.c_str());
+ return;
+ }
+ proto.flush(fd.get());
}
}
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 8b42146..1be4dc5 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -86,8 +86,8 @@
sp<AlarmMonitor> mPeriodicAlarmMonitor;
- void onDumpReportLocked(const ConfigKey& key, const uint64_t dumpTimeNs,
- vector<uint8_t>* outData);
+ void onConfigMetricsReportLocked(const ConfigKey& key, const uint64_t dumpTimeStampNs,
+ util::ProtoOutputStream* proto);
/* Check if we should send a broadcast if approaching memory limits and if we're over, we
* actually delete the data. */
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index efbe96e..3d07c44 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -331,25 +331,25 @@
return mBytesUsed;
}
-void UidMap::getOutput(const ConfigKey& key, vector<uint8_t>* outData) {
- getOutput(getElapsedRealtimeNs(), key, outData);
+void UidMap::appendUidMap(const ConfigKey& key, ProtoOutputStream* proto) {
+ appendUidMap(getElapsedRealtimeNs(), key, proto);
}
-void UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key, vector<uint8_t>* outData) {
+void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
+ ProtoOutputStream* proto) {
lock_guard<mutex> lock(mMutex); // Lock for updates
- ProtoOutputStream proto;
for (const ChangeRecord& record : mChanges) {
if (record.timestampNs > mLastUpdatePerConfigKey[key]) {
uint64_t changesToken =
- proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_CHANGES);
- proto.write(FIELD_TYPE_BOOL | FIELD_ID_CHANGE_DELETION, (bool)record.deletion);
- proto.write(FIELD_TYPE_INT64 | FIELD_ID_CHANGE_TIMESTAMP,
- (long long)record.timestampNs);
- proto.write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PACKAGE, record.package);
- proto.write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_UID, (int)record.uid);
- proto.write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_VERSION, (int)record.version);
- proto.end(changesToken);
+ proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_CHANGES);
+ proto->write(FIELD_TYPE_BOOL | FIELD_ID_CHANGE_DELETION, (bool)record.deletion);
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_CHANGE_TIMESTAMP,
+ (long long)record.timestampNs);
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PACKAGE, record.package);
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_UID, (int)record.uid);
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_VERSION, (int)record.version);
+ proto->end(changesToken);
}
}
@@ -360,13 +360,13 @@
if ((count == mSnapshots.size() - 1 && !atLeastOneSnapshot) ||
record.timestampNs > mLastUpdatePerConfigKey[key]) {
uint64_t snapshotsToken =
- proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SNAPSHOTS);
+ proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SNAPSHOTS);
atLeastOneSnapshot = true;
count++;
- proto.write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP,
- (long long)record.timestampNs);
- proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_SNAPSHOT_PACKAGE_INFO, record.bytes.data());
- proto.end(snapshotsToken);
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP,
+ (long long)record.timestampNs);
+ proto->write(FIELD_TYPE_MESSAGE | FIELD_ID_SNAPSHOT_PACKAGE_INFO, record.bytes.data());
+ proto->end(snapshotsToken);
}
}
@@ -395,47 +395,36 @@
// Produce another snapshot. This results in extra data being uploaded but
// helps ensure we can re-construct the UID->app name, versionCode mapping
// in server.
- ProtoOutputStream proto;
- uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
- FIELD_ID_SNAPSHOT_PACKAGE_INFO);
+ ProtoOutputStream snapshotProto;
+ uint64_t token = snapshotProto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+ FIELD_ID_SNAPSHOT_PACKAGE_INFO);
for (const auto& it : mMap) {
- proto.write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME,
- it.second.packageName);
- proto.write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
- (int)it.second.versionCode);
- proto.write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, (int)it.first);
+ snapshotProto.write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME,
+ it.second.packageName);
+ snapshotProto.write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
+ (int)it.second.versionCode);
+ snapshotProto.write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID,
+ (int)it.first);
}
- proto.end(token);
+ snapshotProto.end(token);
// Copy ProtoOutputStream output to
- auto iter = proto.data();
- vector<char> outData(proto.size());
+ auto iter = snapshotProto.data();
+ vector<char> snapshotData(snapshotProto.size());
size_t pos = 0;
while (iter.readBuffer() != NULL) {
size_t toRead = iter.currentToRead();
- std::memcpy(&(outData[pos]), iter.readBuffer(), toRead);
+ std::memcpy(&(snapshotData[pos]), iter.readBuffer(), toRead);
pos += toRead;
iter.rp()->move(toRead);
}
- mSnapshots.emplace_back(timestamp, outData);
- mBytesUsed += kBytesTimestampField + outData.size();
+ mSnapshots.emplace_back(timestamp, snapshotData);
+ mBytesUsed += kBytesTimestampField + snapshotData.size();
}
}
StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
StatsdStats::getInstance().setUidMapChanges(mChanges.size());
StatsdStats::getInstance().setUidMapSnapshots(mSnapshots.size());
- if (outData != nullptr) {
- outData->clear();
- outData->resize(proto.size());
- size_t pos = 0;
- auto iter = proto.data();
- while (iter.readBuffer() != NULL) {
- size_t toRead = iter.currentToRead();
- std::memcpy(&((*outData)[pos]), iter.readBuffer(), toRead);
- pos += toRead;
- iter.rp()->move(toRead);
- }
- }
}
void UidMap::printUidMap(FILE* out) const {
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index b0181f7..9dc73f4 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -19,6 +19,7 @@
#include "config/ConfigKey.h"
#include "config/ConfigListener.h"
#include "packages/PackageInfoListener.h"
+#include "stats_util.h"
#include <binder/IResultReceiver.h>
#include <binder/IShellCallback.h>
@@ -32,8 +33,11 @@
#include <string>
#include <unordered_map>
+using namespace android;
using namespace std;
+using android::util::ProtoOutputStream;
+
namespace android {
namespace os {
namespace statsd {
@@ -45,8 +49,8 @@
AppData(const string& a, const int64_t v) : packageName(a), versionCode(v){};
};
-// When calling getOutput, we retrieve all the ChangeRecords since the last
-// timestamp we called getOutput for this configuration key.
+// When calling appendUidMap, we retrieve all the ChangeRecords since the last
+// timestamp we called appendUidMap for this configuration key.
struct ChangeRecord {
const bool deletion;
const int64_t timestampNs;
@@ -70,8 +74,8 @@
// less because of varint encoding).
const unsigned int kBytesTimestampField = 10;
-// When calling getOutput, we retrieve all the snapshots since the last
-// timestamp we called getOutput for this configuration key.
+// When calling appendUidMap, we retrieve all the snapshots since the last
+// timestamp we called appendUidMap for this configuration key.
struct SnapshotRecord {
const int64_t timestampNs;
@@ -135,7 +139,7 @@
// Gets all snapshots and changes that have occurred since the last output.
// If every config key has received a change or snapshot record, then this
// record is deleted.
- void getOutput(const ConfigKey& key, vector<uint8_t>* outData);
+ void appendUidMap(const ConfigKey& key, util::ProtoOutputStream* proto);
// Forces the output to be cleared. We still generate a snapshot based on the current state.
// This results in extra data uploaded but helps us reconstruct the uid mapping on the server
@@ -158,7 +162,8 @@
const int64_t& versionCode);
void removeApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid);
- void getOutput(const int64_t& timestamp, const ConfigKey& key, vector<uint8_t>* outData);
+ void appendUidMap(const int64_t& timestamp, const ConfigKey& key,
+ util::ProtoOutputStream* proto);
void getListenerListCopyLocked(std::vector<wp<PackageInfoListener>>* output);
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index cd41f53..3d8aa47 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -160,38 +160,46 @@
}
}
-void StorageManager::appendConfigMetricsReport(ProtoOutputStream& proto) {
+void StorageManager::appendConfigMetricsReport(const ConfigKey& key, ProtoOutputStream* proto) {
unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_DATA_DIR), closedir);
if (dir == NULL) {
VLOG("Path %s does not exist", STATS_DATA_DIR);
return;
}
+ const char* suffix =
+ StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId()).c_str();
+
dirent* de;
while ((de = readdir(dir.get()))) {
char* name = de->d_name;
if (name[0] == '.') continue;
- VLOG("file %s", name);
- int64_t result[3];
- parseFileName(name, result);
- if (result[0] == -1) continue;
- int64_t timestamp = result[0];
- int64_t uid = result[1];
- int64_t configID = result[2];
- string file_name = getFilePath(STATS_DATA_DIR, timestamp, uid, configID);
- int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
- if (fd != -1) {
- string content;
- if (android::base::ReadFdToString(fd, &content)) {
- proto.write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS,
- content.c_str());
+ size_t nameLen = strlen(name);
+ size_t suffixLen = strlen(suffix);
+ if (suffixLen <= nameLen &&
+ strncmp(name + nameLen - suffixLen, suffix, suffixLen) == 0) {
+ int64_t result[3];
+ parseFileName(name, result);
+ if (result[0] == -1) continue;
+ int64_t timestamp = result[0];
+ int64_t uid = result[1];
+ int64_t configID = result[2];
+
+ string file_name = getFilePath(STATS_DATA_DIR, timestamp, uid, configID);
+ int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
+ if (fd != -1) {
+ string content;
+ if (android::base::ReadFdToString(fd, &content)) {
+ proto->write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS,
+ content.c_str(), content.size());
+ }
+ close(fd);
}
- close(fd);
- }
- // Remove file from disk after reading.
- remove(file_name.c_str());
+ // Remove file from disk after reading.
+ remove(file_name.c_str());
+ }
}
}
@@ -275,9 +283,11 @@
if (android::base::ReadFdToString(fd, &content)) {
vector<uint8_t> vec(content.begin(), content.end());
if (vec == config) {
+ close(fd);
return true;
}
}
+ close(fd);
}
}
}
diff --git a/cmds/statsd/src/storage/StorageManager.h b/cmds/statsd/src/storage/StorageManager.h
index 4b75628..fb7b085 100644
--- a/cmds/statsd/src/storage/StorageManager.h
+++ b/cmds/statsd/src/storage/StorageManager.h
@@ -66,7 +66,7 @@
* Appends ConfigMetricsReport found on disk to the specific proto and
* delete it.
*/
- static void appendConfigMetricsReport(ProtoOutputStream& proto);
+ static void appendConfigMetricsReport(const ConfigKey& key, ProtoOutputStream* proto);
/**
* Call to load the saved configs from disk.
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index ee7d770..c9492eb 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -20,6 +20,7 @@
#include "statslog.h"
#include "statsd_test_util.h"
+#include <android/util/ProtoOutputStream.h>
#include <gtest/gtest.h>
#include <stdio.h>
@@ -30,6 +31,8 @@
namespace os {
namespace statsd {
+using android::util::ProtoOutputStream;
+
#ifdef __ANDROID__
const string kApp1 = "app1.sharing.1";
const string kApp2 = "app2.sharing.1";
@@ -156,6 +159,20 @@
EXPECT_TRUE(name_set.find("new_app1_name") != name_set.end());
}
+static void protoOutputStreamToUidMapping(ProtoOutputStream* proto, UidMapping* results) {
+ vector<uint8_t> bytes;
+ bytes.resize(proto->size());
+ size_t pos = 0;
+ auto iter = proto->data();
+ while (iter.readBuffer() != NULL) {
+ size_t toRead = iter.currentToRead();
+ std::memcpy(&((bytes)[pos]), iter.readBuffer(), toRead);
+ pos += toRead;
+ iter.rp()->move(toRead);
+ }
+ results->ParseFromArray(bytes.data(), bytes.size());
+}
+
TEST(UidMapTest, TestClearingOutput) {
UidMap m;
@@ -176,26 +193,26 @@
m.updateMap(1, uids, versions, apps);
EXPECT_EQ(1U, m.mSnapshots.size());
- vector<uint8_t> bytes;
- m.getOutput(2, config1, &bytes);
+ ProtoOutputStream proto;
+ m.appendUidMap(2, config1, &proto);
UidMapping results;
- results.ParseFromArray(bytes.data(), bytes.size());
+ protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
// It should be cleared now
EXPECT_EQ(1U, m.mSnapshots.size());
- bytes.clear();
- m.getOutput(2, config1, &bytes);
- results.ParseFromArray(bytes.data(), bytes.size());
+ proto.clear();
+ m.appendUidMap(2, config1, &proto);
+ protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
// Now add another configuration.
m.OnConfigUpdated(config2);
m.updateApp(5, String16(kApp1.c_str()), 1000, 40);
EXPECT_EQ(1U, m.mChanges.size());
- bytes.clear();
- m.getOutput(6, config1, &bytes);
- results.ParseFromArray(bytes.data(), bytes.size());
+ proto.clear();
+ m.appendUidMap(6, config1, &proto);
+ protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ(1, results.changes_size());
EXPECT_EQ(1U, m.mChanges.size());
@@ -205,16 +222,16 @@
EXPECT_EQ(2U, m.mChanges.size());
// We still can't remove anything.
- bytes.clear();
- m.getOutput(8, config1, &bytes);
- results.ParseFromArray(bytes.data(), bytes.size());
+ proto.clear();
+ m.appendUidMap(8, config1, &proto);
+ protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ(1, results.changes_size());
EXPECT_EQ(2U, m.mChanges.size());
- bytes.clear();
- m.getOutput(9, config2, &bytes);
- results.ParseFromArray(bytes.data(), bytes.size());
+ proto.clear();
+ m.appendUidMap(9, config2, &proto);
+ protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ(2, results.changes_size());
// At this point both should be cleared.
@@ -242,11 +259,12 @@
m.updateApp(3, String16(kApp1.c_str()), 1000, 40);
EXPECT_TRUE(m.mBytesUsed > snapshot_bytes);
+ ProtoOutputStream proto;
vector<uint8_t> bytes;
- m.getOutput(2, config1, &bytes);
+ m.appendUidMap(2, config1, &proto);
size_t prevBytes = m.mBytesUsed;
- m.getOutput(4, config1, &bytes);
+ m.appendUidMap(4, config1, &proto);
EXPECT_TRUE(m.mBytesUsed < prevBytes);
}
@@ -286,4 +304,4 @@
} // namespace statsd
} // namespace os
-} // namespace android
\ No newline at end of file
+} // namespace android