Slice by state in CountMetricProducer

- When a log event is matched to the "what" atom of a metric,
MetricProducer parses the event for state primary key(s) and queries
StateTracker for the correct state values
- CountMetricProducer writes state information to the dump report proto
- Added e2e CountMetric tests that push events to StatsLogProcessor and
check that the resulting dump report is correct

Test: bit statsd_test:*
Bug: 136566566
Bug: 142124705
Change-Id: I9ca5b097151c0c73a617f3b16c8c3584b068cd82
diff --git a/cmds/statsd/src/state/StateTracker.cpp b/cmds/statsd/src/state/StateTracker.cpp
index 323fc0e..e6f6122 100644
--- a/cmds/statsd/src/state/StateTracker.cpp
+++ b/cmds/statsd/src/state/StateTracker.cpp
@@ -25,10 +25,8 @@
 namespace os {
 namespace statsd {
 
-StateTracker::StateTracker(const int atomId,
-                           const util::StateAtomFieldOptions& stateAtomInfo)
-  : mAtomId(atomId),
-    mStateField(getSimpleMatcher(atomId, stateAtomInfo.exclusiveField)) {
+StateTracker::StateTracker(const int32_t atomId, const util::StateAtomFieldOptions& stateAtomInfo)
+    : mAtomId(atomId), mStateField(getSimpleMatcher(atomId, stateAtomInfo.exclusiveField)) {
     // create matcher for each primary field
     // TODO(tsaichristine): b/142108433 handle when primary field is first uid in chain
     for (const auto& primary : stateAtomInfo.primaryFields) {
@@ -55,24 +53,26 @@
     }
 
     // parse event for state value
-    Value state;
-    int32_t stateValue;
-    if (!filterValues(mStateField, event.getValues(), &state) || state.getType() != INT) {
-        ALOGE("StateTracker error extracting state from log event. Type: %d", state.getType());
+    FieldValue stateValue;
+    int32_t state;
+    if (!filterValues(mStateField, event.getValues(), &stateValue) ||
+        stateValue.mValue.getType() != INT) {
+        ALOGE("StateTracker error extracting state from log event. Type: %d",
+              stateValue.mValue.getType());
         handlePartialReset(primaryKey);
         return;
     }
-    stateValue = state.int_value;
+    state = stateValue.mValue.int_value;
 
-    if (stateValue == mResetState) {
-        VLOG("StateTracker Reset state: %s", state.toString().c_str());
+    if (state == mResetState) {
+        VLOG("StateTracker Reset state: %s", stateValue.mValue.toString().c_str());
         handleReset();
     }
 
     // track and update state
     int32_t oldState = 0;
     int32_t newState = 0;
-    updateState(primaryKey, stateValue, &oldState, &newState);
+    updateState(primaryKey, state, &oldState, &newState);
 
     // notify all listeners if state has changed
     if (oldState != newState) {
@@ -96,18 +96,27 @@
     mListeners.erase(listener);
 }
 
-int StateTracker::getStateValue(const HashableDimensionKey& queryKey) const {
+bool StateTracker::getStateValue(const HashableDimensionKey& queryKey, FieldValue* output) const {
+    output->mField = mStateField.mMatcher;
+
+    // Check that the query key has the correct number of primary fields.
     if (queryKey.getValues().size() == mPrimaryFields.size()) {
         auto it = mStateMap.find(queryKey);
         if (it != mStateMap.end()) {
-            return it->second.state;
+            output->mValue = it->second.state;
+            return true;
         }
     } else if (queryKey.getValues().size() > mPrimaryFields.size()) {
         ALOGE("StateTracker query key size > primary key size is illegal");
     } else {
         ALOGE("StateTracker query key size < primary key size is not supported");
     }
-    return mDefaultState;
+
+    // Set the state value to unknown if:
+    // - query key size is incorrect
+    // - query key is not found in state map
+    output->mValue = StateTracker::kStateUnknown;
+    return false;
 }
 
 void StateTracker::handleReset() {