Adds guardrail for memory usage for statsd uid map.

Checks if current memory usage of uid map is above a configured limit
and if so, we start deleting snapshots. If there are no more
snapshots, we begin deleting two of the deltas. Also records stats
in the guardrail StatsdStats. Also fixes an edge case where a config
is added after the snapshots are added. We request a snapshot of all
installed uid's at that moment. Finally, adds the uid map memory size
when determining if we should send a broadcast to trigger collection.

Test: Added unit-tests and check they pass on marlin.
Change-Id: Id5d86378bd1efe12a06b409164c777c0c6f4e3ab
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 2bd3612..2957457 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -45,6 +45,7 @@
 const int FIELD_ID_CONDITION_STATS = 5;
 const int FIELD_ID_METRIC_STATS = 6;
 const int FIELD_ID_ATOM_STATS = 7;
+const int FIELD_ID_UIDMAP_STATS = 8;
 
 const int FIELD_ID_MATCHER_STATS_NAME = 1;
 const int FIELD_ID_MATCHER_STATS_COUNT = 2;
@@ -173,6 +174,27 @@
     it->second.add_dump_report_time_sec(timeSec);
 }
 
+void StatsdStats::noteUidMapDropped(int snapshots, int deltas) {
+    lock_guard<std::mutex> lock(mLock);
+    mUidMapStats.set_dropped_snapshots(mUidMapStats.dropped_snapshots() + snapshots);
+    mUidMapStats.set_dropped_changes(mUidMapStats.dropped_changes() + deltas);
+}
+
+void StatsdStats::setUidMapSnapshots(int snapshots) {
+    lock_guard<std::mutex> lock(mLock);
+    mUidMapStats.set_snapshots(snapshots);
+}
+
+void StatsdStats::setUidMapChanges(int changes) {
+    lock_guard<std::mutex> lock(mLock);
+    mUidMapStats.set_changes(changes);
+}
+
+void StatsdStats::setCurrentUidMapMemory(int bytes) {
+    lock_guard<std::mutex> lock(mLock);
+    mUidMapStats.set_bytes_used(bytes);
+}
+
 void StatsdStats::noteConditionDimensionSize(const ConfigKey& key, const string& name, int size) {
     lock_guard<std::mutex> lock(mLock);
     // if name doesn't exist before, it will create the key with count 0.
@@ -364,6 +386,15 @@
         }
     }
 
+    const int numBytes = mUidMapStats.ByteSize();
+    vector<char> buffer(numBytes);
+    mUidMapStats.SerializeToArray(&buffer[0], numBytes);
+    proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UIDMAP_STATS, &buffer[0], buffer.size());
+    VLOG("UID map stats: bytes=%d, snapshots=%d, changes=%d, snapshots lost=%d, changes "
+         "lost=%d",
+         mUidMapStats.bytes_used(), mUidMapStats.snapshots(), mUidMapStats.changes(),
+         mUidMapStats.dropped_snapshots(), mUidMapStats.dropped_changes());
+
     output->clear();
     size_t bufferSize = proto.size();
     output->resize(bufferSize);