Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b1140ee authored by Yao Chen's avatar Yao Chen
Browse files

Add the option to match a whitelist of strings in FieldValueMatcher.

+ This is useful when we want to build Anomaly detection on wakelocks, but want to whitelist
wakelocks held by some apps that are whitelisted. It reduces the number of matchers needed
in such a config.

+ Also added the ability to match an AID by string name.

Bug: 73897465
Test: unit tests added.
Change-Id: I19315ae4d7d27fc467655d3a29866049cd8c9a2b
parent 3f8237f3
Loading
Loading
Loading
Loading
+48 −7
Original line number Diff line number Diff line
@@ -87,6 +87,10 @@ bool tryMatchString(const UidMap& uidMap, const Field& field, const Value& value
                    const string& str_match) {
    if (isAttributionUidField(field, value)) {
        int uid = value.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) {
@@ -207,6 +211,9 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
            }
            return false;
        }
        // Finally, we get to the point of real value matching.
        // If the field matcher ends with ANY, then we have [start, end) range > 1.
        // In the following, we should return true, when ANY of the values matches.
        case FieldValueMatcher::ValueMatcherCase::kEqBool: {
            for (int i = start; i < end; i++) {
                if ((values[i].mValue.getType() == INT &&
@@ -225,9 +232,36 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
                    return true;
                }
            }
            return false;
        }
        case FieldValueMatcher::ValueMatcherCase::kNeqAllString: {
            const auto& str_list = matcher.neq_all_string();
            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)) {
                        notEqAll = false;
                        break;
                    }
                }
                if (notEqAll) {
                    return true;
                }
            }
            return false;
        }
        case FieldValueMatcher::ValueMatcherCase::kEqAnyString: {
            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)) {
                        return true;
                    }
                }
            }
            return false;
        case FieldValueMatcher::ValueMatcherCase::kEqInt:
        }
        case FieldValueMatcher::ValueMatcherCase::kEqInt: {
            for (int i = start; i < end; i++) {
                if (values[i].mValue.getType() == INT &&
                    (matcher.eq_int() == values[i].mValue.int_value)) {
@@ -240,7 +274,8 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
                }
            }
            return false;
        case FieldValueMatcher::ValueMatcherCase::kLtInt:
        }
        case FieldValueMatcher::ValueMatcherCase::kLtInt: {
            for (int i = start; i < end; i++) {
                if (values[i].mValue.getType() == INT &&
                    (values[i].mValue.int_value < matcher.lt_int())) {
@@ -253,7 +288,8 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
                }
            }
            return false;
        case FieldValueMatcher::ValueMatcherCase::kGtInt:
        }
        case FieldValueMatcher::ValueMatcherCase::kGtInt: {
            for (int i = start; i < end; i++) {
                if (values[i].mValue.getType() == INT &&
                    (values[i].mValue.int_value > matcher.gt_int())) {
@@ -266,7 +302,8 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
                }
            }
            return false;
        case FieldValueMatcher::ValueMatcherCase::kLtFloat:
        }
        case FieldValueMatcher::ValueMatcherCase::kLtFloat: {
            for (int i = start; i < end; i++) {
                if (values[i].mValue.getType() == FLOAT &&
                    (values[i].mValue.float_value < matcher.lt_float())) {
@@ -274,7 +311,8 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
                }
            }
            return false;
        case FieldValueMatcher::ValueMatcherCase::kGtFloat:
        }
        case FieldValueMatcher::ValueMatcherCase::kGtFloat: {
            for (int i = start; i < end; i++) {
                if (values[i].mValue.getType() == FLOAT &&
                    (values[i].mValue.float_value > matcher.gt_float())) {
@@ -282,7 +320,8 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
                }
            }
            return false;
        case FieldValueMatcher::ValueMatcherCase::kLteInt:
        }
        case FieldValueMatcher::ValueMatcherCase::kLteInt: {
            for (int i = start; i < end; i++) {
                if (values[i].mValue.getType() == INT &&
                    (values[i].mValue.int_value <= matcher.lte_int())) {
@@ -295,7 +334,8 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
                }
            }
            return false;
        case FieldValueMatcher::ValueMatcherCase::kGteInt:
        }
        case FieldValueMatcher::ValueMatcherCase::kGteInt: {
            for (int i = start; i < end; i++) {
                if (values[i].mValue.getType() == INT &&
                    (values[i].mValue.int_value >= matcher.gte_int())) {
@@ -308,6 +348,7 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
                }
            }
            return false;
        }
        default:
            return false;
    }
+7 −0
Original line number Diff line number Diff line
@@ -74,6 +74,9 @@ message FieldValueMatcher {
    int64 gte_int = 11;

    MessageMatcher matches_tuple = 12;

    StringListMatcher eq_any_string = 13;
    StringListMatcher neq_all_string = 14;
  }
}

@@ -81,6 +84,10 @@ message MessageMatcher {
  repeated FieldValueMatcher field_value_matcher = 1;
}

message StringListMatcher {
    repeated string str_value = 1;
}

enum LogicalOperation {
  LOGICAL_OPERATION_UNSPECIFIED = 0;
  AND = 1;
+153 −0
Original line number Diff line number Diff line
@@ -294,6 +294,159 @@ TEST(AtomMatcherTest, TestAttributionMatcher) {
    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
}

TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
    UidMap uidMap;
    uidMap.updateMap(
            {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
            {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);

    AttributionNodeInternal attribution_node1;
    attribution_node1.set_uid(1111);
    attribution_node1.set_tag("location1");

    AttributionNodeInternal attribution_node2;
    attribution_node2.set_uid(2222);
    attribution_node2.set_tag("location2");

    AttributionNodeInternal attribution_node3;
    attribution_node3.set_uid(3333);
    attribution_node3.set_tag("location3");

    AttributionNodeInternal attribution_node4;
    attribution_node4.set_uid(1066);
    attribution_node4.set_tag("location3");
    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
                                                              attribution_node3, attribution_node4};

    // Set up the event
    LogEvent event(TAG_ID, 0);
    event.write(attribution_nodes);
    event.write("some value");
    // Convert to a LogEvent
    event.init();

    // Set up the matcher
    AtomMatcher matcher;
    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
    simpleMatcher->set_atom_id(TAG_ID);

    // Match first node.
    auto attributionMatcher = simpleMatcher->add_field_value_matcher();
    attributionMatcher->set_field(FIELD_ID_1);
    attributionMatcher->set_position(Position::FIRST);
    attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
            ATTRIBUTION_UID_FIELD_ID);
    auto neqStringList = attributionMatcher->mutable_matches_tuple()
                                 ->mutable_field_value_matcher(0)
                                 ->mutable_neq_all_string();
    neqStringList->add_str_value("pkg2");
    neqStringList->add_str_value("pkg3");

    auto fieldMatcher = simpleMatcher->add_field_value_matcher();
    fieldMatcher->set_field(FIELD_ID_2);
    fieldMatcher->set_eq_string("some value");

    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));

    neqStringList->Clear();
    neqStringList->add_str_value("pkg1");
    neqStringList->add_str_value("pkg3");
    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));

    attributionMatcher->set_position(Position::ANY);
    neqStringList->Clear();
    neqStringList->add_str_value("maps.com");
    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));

    neqStringList->Clear();
    neqStringList->add_str_value("PkG3");
    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));

    attributionMatcher->set_position(Position::LAST);
    neqStringList->Clear();
    neqStringList->add_str_value("AID_STATSD");
    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
}

TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
    UidMap uidMap;
    uidMap.updateMap(
            {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
            {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);

    AttributionNodeInternal attribution_node1;
    attribution_node1.set_uid(1067);
    attribution_node1.set_tag("location1");

    AttributionNodeInternal attribution_node2;
    attribution_node2.set_uid(2222);
    attribution_node2.set_tag("location2");

    AttributionNodeInternal attribution_node3;
    attribution_node3.set_uid(3333);
    attribution_node3.set_tag("location3");

    AttributionNodeInternal attribution_node4;
    attribution_node4.set_uid(1066);
    attribution_node4.set_tag("location3");
    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
                                                              attribution_node3, attribution_node4};

    // Set up the event
    LogEvent event(TAG_ID, 0);
    event.write(attribution_nodes);
    event.write("some value");
    // Convert to a LogEvent
    event.init();

    // Set up the matcher
    AtomMatcher matcher;
    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
    simpleMatcher->set_atom_id(TAG_ID);

    // Match first node.
    auto attributionMatcher = simpleMatcher->add_field_value_matcher();
    attributionMatcher->set_field(FIELD_ID_1);
    attributionMatcher->set_position(Position::FIRST);
    attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
            ATTRIBUTION_UID_FIELD_ID);
    auto eqStringList = attributionMatcher->mutable_matches_tuple()
                                ->mutable_field_value_matcher(0)
                                ->mutable_eq_any_string();
    eqStringList->add_str_value("AID_ROOT");
    eqStringList->add_str_value("AID_INCIDENTD");

    auto fieldMatcher = simpleMatcher->add_field_value_matcher();
    fieldMatcher->set_field(FIELD_ID_2);
    fieldMatcher->set_eq_string("some value");

    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));

    attributionMatcher->set_position(Position::ANY);
    eqStringList->Clear();
    eqStringList->add_str_value("AID_STATSD");
    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));

    eqStringList->Clear();
    eqStringList->add_str_value("pkg1");
    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));

    auto normalStringField = fieldMatcher->mutable_eq_any_string();
    normalStringField->add_str_value("some value123");
    normalStringField->add_str_value("some value");
    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));

    normalStringField->Clear();
    normalStringField->add_str_value("AID_STATSD");
    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));

    eqStringList->Clear();
    eqStringList->add_str_value("maps.com");
    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
}

TEST(AtomMatcherTest, TestBoolMatcher) {
    UidMap uidMap;
    // Set up the matcher