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;
                     }
                 }