Map isolated uid to host uid when processing log event in statsD.

Test: added test case for isolated uid in Attribution e2e test.
Change-Id: I63d16ebee3e611b1ef0c910e5154cf27766cb330
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index a9e0f23..1cfec32 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -25,6 +25,8 @@
 #include "guardrail/StatsdStats.h"
 #include "metrics/CountMetricProducer.h"
 #include "external/StatsPullerManager.h"
+#include "dimension.h"
+#include "field_util.h"
 #include "stats_util.h"
 #include "storage/StorageManager.h"
 
@@ -88,30 +90,56 @@
     }
 }
 
-// TODO: what if statsd service restarts? How do we know what logs are already processed before?
-void StatsLogProcessor::OnLogEvent(const LogEvent& msg) {
-    std::lock_guard<std::mutex> lock(mMetricsMutex);
-
-    StatsdStats::getInstance().noteAtomLogged(msg.GetTagId(), msg.GetTimestampNs() / NS_PER_SEC);
-    // pass the event to metrics managers.
-    for (auto& pair : mMetricsManagers) {
-        pair.second->onLogEvent(msg);
-        flushIfNecessaryLocked(msg.GetTimestampNs(), pair.first, *(pair.second));
+void StatsLogProcessor::mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const {
+    std::vector<Field> uidFields;
+    findFields(
+        event->getFieldValueMap(),
+        buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY),
+        &uidFields);
+    for (size_t i = 0; i < uidFields.size(); ++i) {
+        DimensionsValue* value = event->findFieldValueOrNull(uidFields[i]);
+        if (value != nullptr && value->value_case() == DimensionsValue::ValueCase::kValueInt) {
+            const int uid = mUidMap->getHostUidOrSelf(value->value_int());
+            value->set_value_int(uid);
+        }
     }
+}
+
+void StatsLogProcessor::onIsolatedUidChangedEventLocked(const LogEvent& event) {
+    status_t err = NO_ERROR, err2 = NO_ERROR, err3 = NO_ERROR;
+    bool is_create = event.GetBool(3, &err);
+    auto parent_uid = int(event.GetLong(1, &err2));
+    auto isolated_uid = int(event.GetLong(2, &err3));
+    if (err == NO_ERROR && err2 == NO_ERROR && err3 == NO_ERROR) {
+        if (is_create) {
+            mUidMap->assignIsolatedUid(isolated_uid, parent_uid);
+        } else {
+            mUidMap->removeIsolatedUid(isolated_uid, parent_uid);
+        }
+    } else {
+        ALOGE("Failed to parse uid in the isolated uid change event.");
+    }
+}
+
+// TODO: what if statsd service restarts? How do we know what logs are already processed before?
+void StatsLogProcessor::OnLogEvent(LogEvent* event) {
+    std::lock_guard<std::mutex> lock(mMetricsMutex);
+    StatsdStats::getInstance().noteAtomLogged(
+        event->GetTagId(), event->GetTimestampNs() / NS_PER_SEC);
+
     // Hard-coded logic to update the isolated uid's in the uid-map.
     // The field numbers need to be currently updated by hand with atoms.proto
-    if (msg.GetTagId() == android::util::ISOLATED_UID_CHANGED) {
-        status_t err = NO_ERROR, err2 = NO_ERROR, err3 = NO_ERROR;
-        bool is_create = msg.GetBool(3, &err);
-        auto parent_uid = int(msg.GetLong(1, &err2));
-        auto isolated_uid = int(msg.GetLong(2, &err3));
-        if (err == NO_ERROR && err2 == NO_ERROR && err3 == NO_ERROR) {
-            if (is_create) {
-                mUidMap->assignIsolatedUid(isolated_uid, parent_uid);
-            } else {
-                mUidMap->removeIsolatedUid(isolated_uid, parent_uid);
-            }
-        }
+    if (event->GetTagId() == android::util::ISOLATED_UID_CHANGED) {
+        onIsolatedUidChangedEventLocked(*event);
+    } else {
+        // Map the isolated uid to host uid if necessary.
+        mapIsolatedUidToHostUidIfNecessaryLocked(event);
+    }
+
+    // pass the event to metrics managers.
+    for (auto& pair : mMetricsManagers) {
+        pair.second->onLogEvent(*event);
+        flushIfNecessaryLocked(event->GetTimestampNs(), pair.first, *(pair.second));
     }
 }
 
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index adc9161..09e10a1 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -38,7 +38,7 @@
                       const std::function<void(const ConfigKey&)>& sendBroadcast);
     virtual ~StatsLogProcessor();
 
-    void OnLogEvent(const LogEvent& event);
+    void OnLogEvent(LogEvent* event);
 
     void OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config);
     void OnConfigRemoved(const ConfigKey& key);
@@ -46,7 +46,8 @@
     size_t GetMetricsSize(const ConfigKey& key) const;
 
     void onDumpReport(const ConfigKey& key, vector<uint8_t>* outData);
-    void onDumpReport(const ConfigKey& key, const uint64_t& dumpTimeStampNs, ConfigMetricsReportList* report);
+    void onDumpReport(const ConfigKey& key, const uint64_t& dumpTimeStampNs,
+                      ConfigMetricsReportList* report);
 
     /* Tells MetricsManager that the alarms in anomalySet have fired. Modifies anomalySet. */
     void onAnomalyAlarmFired(
@@ -79,6 +80,12 @@
     void flushIfNecessaryLocked(uint64_t timestampNs, const ConfigKey& key,
                                 MetricsManager& metricsManager);
 
+    // Maps the isolated uid in the log event to host uid if the log event contains uid fields.
+    void mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const;
+
+    // Handler over the isolated uid change event.
+    void onIsolatedUidChangedEventLocked(const LogEvent& event);
+
     // Function used to send a broadcast so that receiver for the config key can call getData
     // to retrieve the stored data.
     std::function<void(const ConfigKey& key)> mSendBroadcast;
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 45f1ea1..0ed1c1f 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -695,7 +695,7 @@
     mConfigManager->Startup();
 }
 
-void StatsService::OnLogEvent(const LogEvent& event) {
+void StatsService::OnLogEvent(LogEvent* event) {
     mProcessor->OnLogEvent(event);
 }
 
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index c0424f3..8d29970 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -72,7 +72,7 @@
     /**
      * Called by LogReader when there's a log event to process.
      */
-    virtual void OnLogEvent(const LogEvent& event);
+    virtual void OnLogEvent(LogEvent* event);
 
     /**
      * Binder call for clients to request data for this configuration key.
diff --git a/cmds/statsd/src/dimension.cpp b/cmds/statsd/src/dimension.cpp
index 45b3586..09499b6 100644
--- a/cmds/statsd/src/dimension.cpp
+++ b/cmds/statsd/src/dimension.cpp
@@ -19,7 +19,6 @@
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "frameworks/base/cmds/statsd/src/statsd_internal.pb.h"
 #include "dimension.h"
-#include "field_util.h"
 
 
 namespace android {
@@ -220,33 +219,35 @@
 constexpr int UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 1;
 constexpr int TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 2;
 
-void buildAttributionUidFieldMatcher(const int tagId, const Position position,
-                                     FieldMatcher *matcher) {
-    matcher->set_field(tagId);
-    matcher->add_child()->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
-    FieldMatcher* child = matcher->mutable_child(0)->add_child();
-    child->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
-}
-
-void buildAttributionTagFieldMatcher(const int tagId, const Position position,
-                                     FieldMatcher *matcher) {
-    matcher->set_field(tagId);
-    FieldMatcher* child = matcher->add_child();
+FieldMatcher buildAttributionUidFieldMatcher(const int tagId, const Position position) {
+    FieldMatcher matcher;
+    matcher.set_field(tagId);
+    auto child = matcher.add_child();
     child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
     child->set_position(position);
-    child = child->add_child();
-    child->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+    child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+    return matcher;
 }
 
-void buildAttributionFieldMatcher(const int tagId, const Position position,
-                                  FieldMatcher *matcher) {
-    matcher->set_field(tagId);
-    FieldMatcher* child = matcher->add_child();
+FieldMatcher buildAttributionTagFieldMatcher(const int tagId, const Position position) {
+    FieldMatcher matcher;
+    matcher.set_field(tagId);
+    FieldMatcher* child = matcher.add_child();
     child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
     child->set_position(position);
-    child = child->add_child();
-    child->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
-    child->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+    child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+    return matcher;
+}
+
+FieldMatcher buildAttributionFieldMatcher(const int tagId, const Position position) {
+    FieldMatcher matcher;
+    matcher.set_field(tagId);
+    FieldMatcher* child = matcher.add_child();
+    child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
+    child->set_position(position);
+    child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+    child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
+    return matcher;
 }
 
 void DimensionsValueToString(const DimensionsValue& value, std::string *flattened) {
diff --git a/cmds/statsd/src/dimension.h b/cmds/statsd/src/dimension.h
index 5bb64a9..845c138 100644
--- a/cmds/statsd/src/dimension.h
+++ b/cmds/statsd/src/dimension.h
@@ -27,7 +27,6 @@
 namespace os {
 namespace statsd {
 
-
 // Returns the leaf node from the DimensionsValue proto. It assume that the input has only one
 // leaf node at most.
 const DimensionsValue* getSingleLeafValue(const DimensionsValue* value);
diff --git a/cmds/statsd/src/field_util.cpp b/cmds/statsd/src/field_util.cpp
index d10e167..4ff4f74 100644
--- a/cmds/statsd/src/field_util.cpp
+++ b/cmds/statsd/src/field_util.cpp
@@ -184,6 +184,7 @@
     }
 }
 
+namespace {
 void findFields(
        const FieldValueMap& fieldValueMap,
        const FieldMatcher& matcher,
@@ -287,9 +288,18 @@
     }
 }
 
+}  // namespace
+
+void findFields(
+       const FieldValueMap& fieldValueMap,
+       const FieldMatcher& matcher,
+       std::vector<Field>* rootFields) {
+    return findFields(fieldValueMap, matcher, buildSimpleAtomField(matcher.field()), rootFields);
+}
+
 void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap) {
     std::vector<Field> rootFields;
-    findFields(*fieldValueMap, matcher, buildSimpleAtomField(matcher.field()), &rootFields);
+    findFields(*fieldValueMap, matcher, &rootFields);
     std::set<Field, FieldCmp> rootFieldSet(rootFields.begin(), rootFields.end());
     auto it = fieldValueMap->begin();
     while (it != fieldValueMap->end()) {
@@ -313,6 +323,11 @@
     return true;
 }
 
+bool IsAttributionUidField(const Field& field) {
+    return field.child_size() == 1 && field.child(0).field() == 1
+        && field.child(0).child_size() == 1 && field.child(0).child(0).field() == 1;
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/field_util.h b/cmds/statsd/src/field_util.h
index 3e7d54c..a4dfddd 100644
--- a/cmds/statsd/src/field_util.h
+++ b/cmds/statsd/src/field_util.h
@@ -85,6 +85,9 @@
 // Filter out the fields not in the field matcher.
 void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap);
 
+// Returns if the field is attribution node uid field.
+bool IsAttributionUidField(const Field& field);
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 49a6e33..6782f3f 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -397,6 +397,14 @@
     return dimensionsValue;
 }
 
+DimensionsValue* LogEvent::findFieldValueOrNull(const Field& field) {
+    auto it = mFieldValueMap.find(field);
+    if (it == mFieldValueMap.end()) {
+        return nullptr;
+    }
+    return &it->second;
+}
+
 string LogEvent::ToString() const {
     ostringstream result;
     result << "{ " << mTimestampNs << " (" << mTagId << ")";
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 8f3dedf..fdfa32e 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -132,6 +132,11 @@
         return mFieldValueMap.size();
     }
 
+    /**
+     * Returns the mutable DimensionsValue proto for the specific the field.
+     */
+    DimensionsValue* findFieldValueOrNull(const Field& field);
+
     inline const FieldValueMap& getFieldValueMap() const { return mFieldValueMap; }
 
 private:
diff --git a/cmds/statsd/src/logd/LogListener.h b/cmds/statsd/src/logd/LogListener.h
index 9641226..69ca571 100644
--- a/cmds/statsd/src/logd/LogListener.h
+++ b/cmds/statsd/src/logd/LogListener.h
@@ -33,7 +33,7 @@
     LogListener();
     virtual ~LogListener();
 
-    virtual void OnLogEvent(const LogEvent& msg) = 0;
+    virtual void OnLogEvent(LogEvent* msg) = 0;
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/logd/LogReader.cpp b/cmds/statsd/src/logd/LogReader.cpp
index c441a5e..7636268 100644
--- a/cmds/statsd/src/logd/LogReader.cpp
+++ b/cmds/statsd/src/logd/LogReader.cpp
@@ -110,7 +110,7 @@
             LogEvent event(msg);
 
             // Call the listener
-            mListener->OnLogEvent(event);
+            mListener->OnLogEvent(&event);
         }
     }
 
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index 46d9b92..48f62e7 100644
--- a/cmds/statsd/src/matchers/matcher_util.cpp
+++ b/cmds/statsd/src/matchers/matcher_util.cpp
@@ -93,11 +93,6 @@
     return matched;
 }
 
-bool IsAttributionUidField(const Field& field) {
-    return field.child_size() == 1 && field.child(0).field() == 1
-        && field.child(0).child_size() == 1 && field.child(0).child(0).field() == 1;
-}
-
 bool matchesNonRepeatedField(
        const UidMap& uidMap,
        const FieldValueMap& fieldMap,
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 517d21d..b0c3197 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -269,7 +269,7 @@
     }
 }
 
-int UidMap::getParentUidOrSelf(int uid) {
+int UidMap::getHostUidOrSelf(int uid) const {
     lock_guard<mutex> lock(mIsolatedMutex);
 
     auto it = mIsolatedUidMap.find(uid);
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 07e13e0..4e37977 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -90,8 +90,8 @@
     void assignIsolatedUid(int isolatedUid, int parentUid);
     void removeIsolatedUid(int isolatedUid, int parentUid);
 
-    // Returns the parent uid if it exists. Otherwise, returns the same uid that was passed-in.
-    int getParentUidOrSelf(int uid);
+    // Returns the host uid if it exists. Otherwise, returns the same uid that was passed-in.
+    int getHostUidOrSelf(int uid) const;
 
     // Gets the output. If every config key has received the output, then the output is cleared.
     UidMapping getOutput(const ConfigKey& key);