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
This commit is contained in:
Ruchir Rastogi
2020-04-04 15:30:11 -07:00
parent 288c434f34
commit ffa34f05cf
10 changed files with 75 additions and 110 deletions

View File

@@ -120,9 +120,9 @@ bool isAttributionUidField(const FieldValue& value) {
}
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 @@ bool isAttributionUidField(const Field& field, const Value& value) {
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) {

View File

@@ -367,7 +367,8 @@ public:
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 @@ public:
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 @@ public:
// 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 @@ private:
}
// 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 @@ int getUidIfExists(const FieldValue& value);
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);

View File

@@ -138,13 +138,6 @@ void StatsLogProcessor::onPeriodicAlarmFired(
}
}
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 @@ void StatsLogProcessor::mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event
}
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);
}
}
}

View File

@@ -49,10 +49,14 @@ using namespace std;
*/
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 @@ void mapAndMergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const
}
}
} 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());
}
}
}

View File

@@ -240,14 +240,20 @@ void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last,
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) {

View File

@@ -213,6 +213,7 @@ private:
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

View File

@@ -81,18 +81,17 @@ bool combinationMatch(const vector<int>& children, const LogicalOperation& opera
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 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
}
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 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
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 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
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;
}
}

View File

@@ -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 @@ void makeStringLogEvent(LogEvent* logEvent, const int32_t atomId, const int64_t
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 @@ TEST(AtomMatcherTest, TestUidFieldMatcher) {
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));
}

View File

@@ -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 @@ int hostNonAdditiveData = 22;
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 @@ std::shared_ptr<LogEvent> makeUidLogEvent(uint64_t timestampNs, int uid, int dat
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_IS_UID, true);
AStatsEvent_writeInt32(statsEvent, data1);
AStatsEvent_writeInt32(statsEvent, data2);

View File

@@ -42,7 +42,6 @@ static void write_atoms_info_header_body(FILE* out, const Atoms& atoms) {
fprintf(out,
" const static std::set<int> "
"kTruncatingTimestampAtomBlackList;\n");
fprintf(out, " const static std::map<int, int> kAtomsWithUidField;\n");
fprintf(out, " const static std::set<int> kAtomsWithAttributionChain;\n");
fprintf(out,
" const static std::map<int, StateAtomFieldOptions> "
@@ -101,28 +100,6 @@ static void write_atoms_info_cpp_body(FILE* out, const Atoms& atoms) {
fprintf(out, "};\n");
fprintf(out, "\n");
fprintf(out, "static std::map<int, int> getAtomUidField() {\n");
fprintf(out, " std::map<int, int> uidField;\n");
for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
atomIt++) {
if ((*atomIt)->uidField == 0) {
continue;
}
fprintf(out,
"\n // Adding uid field for atom "
"(%d)%s\n",
(*atomIt)->code, (*atomIt)->name.c_str());
fprintf(out, " uidField[%d /* %s */] = %d;\n", (*atomIt)->code,
make_constant_name((*atomIt)->name).c_str(), (*atomIt)->uidField);
}
fprintf(out, " return uidField;\n");
fprintf(out, "};\n");
fprintf(out,
"const std::map<int, int> AtomsInfo::kAtomsWithUidField = "
"getAtomUidField();\n");
fprintf(out,
"static std::map<int, StateAtomFieldOptions> "
"getStateAtomFieldOptions() {\n");