Remove kAtomsWithUidField from atoms_info

Instead of using the map from atoms_info, we now receive uid information
in the form of StatsEvent annotations. The isUid annotation is exposed
from both LogEvent and FieldValue.

Test: bit statsd_test:*
Test: atest GtsStatsdHostTestCases
Bug: 150414601
Change-Id: Iebbe4ce5668de1ab91485daa1be9197cde6e8309
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index 4385964..cfc1de4 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -120,9 +120,9 @@
 }
 
 int32_t getUidIfExists(const FieldValue& value) {
-    // the field is uid field if the field is the uid field in attribution node or marked as
-    // is_uid in atoms.proto
-    bool isUid = isAttributionUidField(value) || isUidField(value.mField, value.mValue);
+    // the field is uid field if the field is the uid field in attribution node
+    // or annotated as such in the atom
+    bool isUid = isAttributionUidField(value) || isUidField(value);
     return isUid ? value.mValue.int_value : -1;
 }
 
@@ -134,16 +134,8 @@
     return false;
 }
 
-bool isUidField(const Field& field, const Value& value) {
-    auto it = android::util::AtomsInfo::kAtomsWithUidField.find(field.getTag());
-
-    if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) {
-        int uidField = it->second;  // uidField is the field number in proto
-        return field.getDepth() == 0 && field.getPosAtDepth(0) == uidField &&
-               value.getType() == INT;
-    }
-
-    return false;
+bool isUidField(const FieldValue& fieldValue) {
+    return fieldValue.mAnnotations.isUidField();
 }
 
 Value::Value(const Value& from) {
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index 3536e5a..92e09ea 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -367,7 +367,8 @@
     enum {
         NESTED_POS = 0x0,
         PRIMARY_POS = 0x1,
-        EXCLUSIVE_POS = 0x2
+        EXCLUSIVE_POS = 0x2,
+        UID_POS = 0x3
     };
 
     inline void setNested(bool nested) { setBitmaskAtPos(NESTED_POS, nested); }
@@ -376,6 +377,8 @@
 
     inline void setExclusiveState(bool exclusive) { setBitmaskAtPos(EXCLUSIVE_POS, exclusive); }
 
+    inline void setUidField(bool isUid) { setBitmaskAtPos(UID_POS, isUid); }
+
     inline void setResetState(int resetState) { mResetState = resetState; }
 
     // Default value = false
@@ -387,6 +390,9 @@
     // Default value = false
     inline bool isExclusiveState() const { return getValueFromBitmask(EXCLUSIVE_POS); }
 
+    // Default value = false
+    inline bool isUidField() const { return getValueFromBitmask(UID_POS); }
+
     // If a reset state is not sent in the StatsEvent, returns -1. Note that a
     // reset satate is only sent if and only if a reset should be triggered.
     inline int getResetState() const { return mResetState; }
@@ -402,7 +408,7 @@
     }
 
     // This is a bitmask over all annotations stored in boolean form. Because
-    // there are only 3 booleans, just one byte is required.
+    // there are only 4 booleans, just one byte is required.
     uint8_t mBooleanBitmask = 0;
 
     int mResetState = -1;
@@ -449,7 +455,7 @@
 void translateFieldMatcher(const FieldMatcher& matcher, std::vector<Matcher>* output);
 
 bool isAttributionUidField(const Field& field, const Value& value);
-bool isUidField(const Field& field, const Value& value);
+bool isUidField(const FieldValue& fieldValue);
 
 bool equalDimensions(const std::vector<Matcher>& dimension_a,
                      const std::vector<Matcher>& dimension_b);
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 982a63e..325cbc7 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -138,13 +138,6 @@
     }
 }
 
-void updateUid(Value* value, int hostUid) {
-    int uid = value->int_value;
-    if (uid != hostUid) {
-        value->setInt(hostUid);
-    }
-}
-
 void StatsLogProcessor::mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const {
     if (android::util::AtomsInfo::kAtomsWithAttributionChain.find(event->GetTagId()) !=
         android::util::AtomsInfo::kAtomsWithAttributionChain.end()) {
@@ -154,22 +147,15 @@
             }
             if (isAttributionUidField(value)) {
                 const int hostUid = mUidMap->getHostUidOrSelf(value.mValue.int_value);
-                updateUid(&value.mValue, hostUid);
+                value.mValue.setInt(hostUid);
             }
         }
     } else {
-        auto it = android::util::AtomsInfo::kAtomsWithUidField.find(event->GetTagId());
-        if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) {
-            int uidField = it->second;  // uidField is the field number in proto,
-                                        // starting from 1
-            if (uidField > 0 && (int)event->getValues().size() >= uidField &&
-                (event->getValues())[uidField - 1].mValue.getType() == INT) {
-                Value& value = (*event->getMutableValues())[uidField - 1].mValue;
-                const int hostUid = mUidMap->getHostUidOrSelf(value.int_value);
-                updateUid(&value, hostUid);
-            } else {
-                ALOGE("Malformed log, uid not found. %s", event->ToString().c_str());
-            }
+        int uidFieldIndex = event->getUidFieldIndex();
+        if (uidFieldIndex != -1) {
+           Value& value = (*event->getMutableValues())[uidFieldIndex].mValue;
+           const int hostUid = mUidMap->getHostUidOrSelf(value.int_value);
+           value.setInt(hostUid);
         }
     }
 }
diff --git a/cmds/statsd/src/external/puller_util.cpp b/cmds/statsd/src/external/puller_util.cpp
index aee7256..90247cf 100644
--- a/cmds/statsd/src/external/puller_util.cpp
+++ b/cmds/statsd/src/external/puller_util.cpp
@@ -49,10 +49,14 @@
  */
 void mapAndMergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap,
                                       int tagId, const vector<int>& additiveFieldsVec) {
-    if ((android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) ==
-         android::util::AtomsInfo::kAtomsWithAttributionChain.end()) &&
-        (android::util::AtomsInfo::kAtomsWithUidField.find(tagId) ==
-         android::util::AtomsInfo::kAtomsWithUidField.end())) {
+    bool hasAttributionChain = (android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) !=
+                                android::util::AtomsInfo::kAtomsWithAttributionChain.end());
+    // To check if any LogEvent has a uid field, we can just check the first
+    // LogEvent because all atoms with this tagId should have the uid
+    // annotation.
+    bool hasUidField = (data[0]->getUidFieldIndex() != -1);
+
+    if (!hasAttributionChain && !hasUidField) {
         VLOG("No uid or attribution chain to merge, atom %d", tagId);
         return;
     }
@@ -75,19 +79,13 @@
                 }
             }
         } else {
-            auto it = android::util::AtomsInfo::kAtomsWithUidField.find(tagId);
-            if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) {
-                int uidField = it->second;  // uidField is the field number in proto,
-                // starting from 1
-                if (uidField > 0 && (int)event->getValues().size() >= uidField &&
-                    (event->getValues())[uidField - 1].mValue.getType() == INT) {
-                    Value& value = (*event->getMutableValues())[uidField - 1].mValue;
-                    const int hostUid = uidMap->getHostUidOrSelf(value.int_value);
-                    value.setInt(hostUid);
-                } else {
-                    ALOGE("Malformed log, uid not found. %s", event->ToString().c_str());
-                    return;
-                }
+            int uidFieldIndex = event->getUidFieldIndex();
+            if (uidFieldIndex != -1) {
+                Value& value = (*event->getMutableValues())[uidFieldIndex].mValue;
+                const int hostUid = uidMap->getHostUidOrSelf(value.int_value);
+                value.setInt(hostUid);
+            } else {
+                ALOGE("Malformed log, uid not found. %s", event->ToString().c_str());
             }
         }
     }
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 96bf04f..8b6a864 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -240,14 +240,20 @@
     last[1] = last[2] = false;
 }
 
+// Assumes that mValues is not empty
+bool LogEvent::checkPreviousValueType(Type expected) {
+    return mValues[mValues.size() - 1].mValue.getType() == expected;
+}
+
 void LogEvent::parseIsUidAnnotation(uint8_t annotationType) {
-    if (mValues.empty() || annotationType != BOOL_TYPE) {
+    if (mValues.empty() || !checkPreviousValueType(INT) || annotationType != BOOL_TYPE) {
         mValid = false;
         return;
     }
 
     bool isUid = readNextValue<uint8_t>();
     if (isUid) mUidFieldIndex = mValues.size() - 1;
+    mValues[mValues.size() - 1].mAnnotations.setUidField(isUid);
 }
 
 void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) {
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 9e21c77..4eeb7d6 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -213,6 +213,7 @@
     void parseExclusiveStateAnnotation(uint8_t annotationType);
     void parseTriggerStateResetAnnotation(uint8_t annotationType);
     void parseStateNestedAnnotation(uint8_t annotationType);
+    bool checkPreviousValueType(Type expected);
 
     /**
      * The below three variables are only valid during the execution of
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index 1f8bbd7..2b4c6a3 100644
--- a/cmds/statsd/src/matchers/matcher_util.cpp
+++ b/cmds/statsd/src/matchers/matcher_util.cpp
@@ -81,18 +81,17 @@
     return matched;
 }
 
-bool tryMatchString(const UidMap& uidMap, const Field& field, const Value& value,
-                    const string& str_match) {
-    if (isAttributionUidField(field, value) || isUidField(field, value)) {
-        int uid = value.int_value;
+bool tryMatchString(const UidMap& uidMap, const FieldValue& fieldValue, const string& str_match) {
+    if (isAttributionUidField(fieldValue) || isUidField(fieldValue)) {
+        int uid = fieldValue.mValue.int_value;
         auto aidIt = UidMap::sAidToUidMapping.find(str_match);
         if (aidIt != UidMap::sAidToUidMapping.end()) {
             return ((int)aidIt->second) == uid;
         }
         std::set<string> packageNames = uidMap.getAppNamesFromUid(uid, true /* normalize*/);
         return packageNames.find(str_match) != packageNames.end();
-    } else if (value.getType() == STRING) {
-        return value.str_value == str_match;
+    } else if (fieldValue.mValue.getType() == STRING) {
+        return fieldValue.mValue.str_value == str_match;
     }
     return false;
 }
@@ -228,8 +227,7 @@
         }
         case FieldValueMatcher::ValueMatcherCase::kEqString: {
             for (int i = start; i < end; i++) {
-                if (tryMatchString(uidMap, values[i].mField, values[i].mValue,
-                                   matcher.eq_string())) {
+                if (tryMatchString(uidMap, values[i], matcher.eq_string())) {
                     return true;
                 }
             }
@@ -240,7 +238,7 @@
             for (int i = start; i < end; i++) {
                 bool notEqAll = true;
                 for (const auto& str : str_list.str_value()) {
-                    if (tryMatchString(uidMap, values[i].mField, values[i].mValue, str)) {
+                    if (tryMatchString(uidMap, values[i], str)) {
                         notEqAll = false;
                         break;
                     }
@@ -255,7 +253,7 @@
             const auto& str_list = matcher.eq_any_string();
             for (int i = start; i < end; i++) {
                 for (const auto& str : str_list.str_value()) {
-                    if (tryMatchString(uidMap, values[i].mField, values[i].mValue, str)) {
+                    if (tryMatchString(uidMap, values[i], str)) {
                         return true;
                     }
                 }
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index 9cdf582..26423d4 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -18,6 +18,7 @@
 #include <log/logprint.h>
 #include <stdio.h>
 
+#include "annotations.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "matchers/matcher_util.h"
 #include "stats_event.h"
@@ -73,14 +74,13 @@
     parseStatsEventToLogEvent(statsEvent, logEvent);
 }
 
-void makeIntStringLogEvent(LogEvent* logEvent, const int32_t atomId, const int64_t timestamp,
-                           const int32_t value, const string& name) {
+void makeIntWithBoolAnnotationLogEvent(LogEvent* logEvent, const int32_t atomId,
+                                       const int32_t field, const uint8_t annotationId,
+                                       const bool annotationValue) {
     AStatsEvent* statsEvent = AStatsEvent_obtain();
     AStatsEvent_setAtomId(statsEvent, atomId);
-    AStatsEvent_overwriteTimestamp(statsEvent, timestamp);
-
-    AStatsEvent_writeInt32(statsEvent, value);
-    AStatsEvent_writeString(statsEvent, name.c_str());
+    AStatsEvent_writeInt32(statsEvent, field);
+    AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue);
 
     parseStatsEventToLogEvent(statsEvent, logEvent);
 }
@@ -376,21 +376,20 @@
     simpleMatcher->add_field_value_matcher()->set_field(1);
     simpleMatcher->mutable_field_value_matcher(0)->set_eq_string("pkg0");
 
-    // Set up the event
+    // Make event without is_uid annotation.
     LogEvent event1(/*uid=*/0, /*pid=*/0);
     makeIntLogEvent(&event1, TAG_ID, 0, 1111);
-
-    LogEvent event2(/*uid=*/0, /*pid=*/0);
-    makeIntStringLogEvent(&event2, TAG_ID_2, 0, 1111, "some value");
-
-    // Tag not in kAtomsWithUidField
     EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1));
 
-    // Tag found in kAtomsWithUidField and has matching uid
+    // Make event with is_uid annotation.
+    LogEvent event2(/*uid=*/0, /*pid=*/0);
+    makeIntWithBoolAnnotationLogEvent(&event2, TAG_ID_2, 1111, ANNOTATION_ID_IS_UID, true);
+
+    // Event has is_uid annotation, so mapping from uid to package name occurs.
     simpleMatcher->set_atom_id(TAG_ID_2);
     EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2));
 
-    // Tag found in kAtomsWithUidField but has non-matching uid
+    // Event has is_uid annotation, but uid maps to different package name.
     simpleMatcher->mutable_field_value_matcher(0)->set_eq_string("Pkg2");
     EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2));
 }
diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp
index 3e1cc5e..c2cfb37 100644
--- a/cmds/statsd/tests/external/puller_util_test.cpp
+++ b/cmds/statsd/tests/external/puller_util_test.cpp
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "../metrics/metrics_test_helper.h"
+#include "annotations.h"
 #include "stats_event.h"
 #include "statslog_statsdtest.h"
 #include "tests/statsd_test_util.h"
@@ -53,15 +54,15 @@
 
 void extractIntoVector(vector<shared_ptr<LogEvent>> events,
                       vector<vector<int>>& ret) {
-  ret.clear();
-  status_t err;
-  for (const auto& event : events) {
-    vector<int> vec;
-    vec.push_back(event->GetInt(1, &err));
-    vec.push_back(event->GetInt(2, &err));
-    vec.push_back(event->GetInt(3, &err));
-    ret.push_back(vec);
-  }
+    ret.clear();
+    status_t err;
+    for (const auto& event : events) {
+        vector<int> vec;
+        vec.push_back(event->GetInt(1, &err));
+        vec.push_back(event->GetInt(2, &err));
+        vec.push_back(event->GetInt(3, &err));
+        ret.push_back(vec);
+    }
 }
 
 std::shared_ptr<LogEvent> makeUidLogEvent(uint64_t timestampNs, int uid, int data1, int data2) {
@@ -70,6 +71,7 @@
     AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
 
     AStatsEvent_writeInt32(statsEvent, uid);
+    AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_IS_UID, true);
     AStatsEvent_writeInt32(statsEvent, data1);
     AStatsEvent_writeInt32(statsEvent, data2);