summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/statsd/src/condition/CombinationConditionTracker.cpp48
-rw-r--r--cmds/statsd/src/condition/CombinationConditionTracker.h10
-rw-r--r--cmds/statsd/src/condition/ConditionTracker.h41
-rw-r--r--cmds/statsd/src/condition/SimpleConditionTracker.cpp98
-rw-r--r--cmds/statsd/src/condition/SimpleConditionTracker.h19
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp13
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.h5
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp247
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.h90
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp55
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h14
-rw-r--r--cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp18
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp486
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp132
14 files changed, 1121 insertions, 155 deletions
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
index 3b65f8225ee9..4574b2e34547 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
@@ -25,8 +25,9 @@ namespace statsd {
using std::unordered_map;
using std::vector;
-CombinationConditionTracker::CombinationConditionTracker(const int64_t& id, const int index)
- : ConditionTracker(id, index) {
+CombinationConditionTracker::CombinationConditionTracker(const int64_t& id, const int index,
+ const uint64_t protoHash)
+ : ConditionTracker(id, index, protoHash) {
VLOG("creating CombinationConditionTracker %lld", (long long)mConditionId);
}
@@ -122,6 +123,49 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
return true;
}
+bool CombinationConditionTracker::onConfigUpdated(
+ const vector<Predicate>& allConditionProtos, const int index,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& conditionTrackerMap) {
+ ConditionTracker::onConfigUpdated(allConditionProtos, index, allConditionTrackers,
+ atomMatchingTrackerMap, conditionTrackerMap);
+ mTrackerIndex.clear();
+ mChildren.clear();
+ mUnSlicedChildren.clear();
+ mSlicedChildren.clear();
+ Predicate_Combination combinationCondition = allConditionProtos[mIndex].combination();
+
+ for (const int64_t child : combinationCondition.predicate()) {
+ const auto& it = conditionTrackerMap.find(child);
+
+ if (it == conditionTrackerMap.end()) {
+ ALOGW("Predicate %lld not found in the config", (long long)child);
+ return false;
+ }
+
+ int childIndex = it->second;
+ const sp<ConditionTracker>& childTracker = allConditionTrackers[childIndex];
+
+ // Ensures that the child's tracker indices are updated.
+ if (!childTracker->onConfigUpdated(allConditionProtos, childIndex, allConditionTrackers,
+ atomMatchingTrackerMap, conditionTrackerMap)) {
+ ALOGW("Child update failed %lld ", (long long)child);
+ return false;
+ }
+
+ if (allConditionTrackers[childIndex]->isSliced()) {
+ mSlicedChildren.push_back(childIndex);
+ } else {
+ mUnSlicedChildren.push_back(childIndex);
+ }
+ mChildren.push_back(childIndex);
+ mTrackerIndex.insert(childTracker->getAtomMatchingTrackerIndex().begin(),
+ childTracker->getAtomMatchingTrackerIndex().end());
+ }
+ return true;
+}
+
void CombinationConditionTracker::isConditionMet(
const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
const bool isPartialLink,
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.h b/cmds/statsd/src/condition/CombinationConditionTracker.h
index a7fac3deaabe..672d61c82268 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.h
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.h
@@ -24,9 +24,9 @@ namespace android {
namespace os {
namespace statsd {
-class CombinationConditionTracker : public virtual ConditionTracker {
+class CombinationConditionTracker : public ConditionTracker {
public:
- CombinationConditionTracker(const int64_t& id, const int index);
+ CombinationConditionTracker(const int64_t& id, const int index, const uint64_t protoHash);
~CombinationConditionTracker();
@@ -35,6 +35,11 @@ public:
const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
std::vector<ConditionState>& conditionCache) override;
+ bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap) override;
+
void evaluateCondition(const LogEvent& event,
const std::vector<MatchingState>& eventMatcherValues,
const std::vector<sp<ConditionTracker>>& mAllConditions,
@@ -102,6 +107,7 @@ private:
std::vector<int> mSlicedChildren;
std::vector<int> mUnSlicedChildren;
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h
index 4e1253506be7..3bf4e636be89 100644
--- a/cmds/statsd/src/condition/ConditionTracker.h
+++ b/cmds/statsd/src/condition/ConditionTracker.h
@@ -31,18 +31,17 @@ namespace statsd {
class ConditionTracker : public virtual RefBase {
public:
- ConditionTracker(const int64_t& id, const int index)
+ ConditionTracker(const int64_t& id, const int index, const uint64_t protoHash)
: mConditionId(id),
mIndex(index),
mInitialized(false),
mTrackerIndex(),
mUnSlicedPartCondition(ConditionState::kUnknown),
- mSliced(false){};
+ mSliced(false),
+ mProtoHash(protoHash){};
virtual ~ConditionTracker(){};
- inline const int64_t& getId() { return mConditionId; }
-
// Initialize this ConditionTracker. This initialization is done recursively (DFS). It can also
// be done in the constructor, but we do it separately because (1) easy to return a bool to
// indicate whether the initialization is successful. (2) makes unit test easier.
@@ -50,7 +49,7 @@ public:
// fill the condition cache with the current condition.
// allConditionConfig: the list of all Predicate config from statsd_config.
// allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
- // need to call init() on children conditions)
+ // need to call init() on child conditions)
// conditionIdIndexMap: the mapping from condition id to its index.
// stack: a bit map to keep track which nodes have been visited on the stack in the recursion.
// conditionCache: tracks initial conditions of all ConditionTrackers. returns the
@@ -60,6 +59,26 @@ public:
const std::unordered_map<int64_t, int>& conditionIdIndexMap,
std::vector<bool>& stack, std::vector<ConditionState>& conditionCache) = 0;
+ // Update appropriate state on config updates. Primarily, all indices need to be updated.
+ // This predicate and all of its children are guaranteed to be preserved across the update.
+ // This function is recursive and will call onConfigUpdated on child conditions. It does not
+ // manage cycle detection since all preserved conditions should not have any cycles.
+ //
+ // allConditionProtos: the new predicates.
+ // index: the new index of this tracker in allConditionProtos and allConditionTrackers.
+ // allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
+ // need to call onConfigUpdated() on child conditions)
+ // [atomMatchingTrackerMap]: map of atom matcher id to index after the config update
+ // [conditionTrackerMap]: map of condition tracker id to index after the config update.
+ // returns whether or not the update is successful
+ virtual bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap) {
+ mIndex = index;
+ return true;
+ }
+
// evaluate current condition given the new event.
// event: the new log event
// eventMatcherValues: the results of the AtomMatchingTrackers. AtomMatchingTrackers always
@@ -112,6 +131,10 @@ public:
return mConditionId;
}
+ inline uint64_t getProtoHash() const {
+ return mProtoHash;
+ }
+
virtual void getTrueSlicedDimensions(
const std::vector<sp<ConditionTracker>>& allConditions,
std::set<HashableDimensionKey>* dimensions) const = 0;
@@ -133,7 +156,7 @@ protected:
const int64_t mConditionId;
// the index of this condition in the manager's condition list.
- const int mIndex;
+ int mIndex;
// if it's properly initialized.
bool mInitialized;
@@ -151,6 +174,12 @@ protected:
ConditionState mUnSlicedPartCondition;
bool mSliced;
+
+ // Hash of the Predicate's proto bytes from StatsdConfig.
+ // Used to determine if the definition of this condition has changed across a config update.
+ const uint64_t mProtoHash;
+
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index f45759b6a77e..1dcc8f96131a 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -27,54 +27,21 @@ namespace statsd {
using std::unordered_map;
SimpleConditionTracker::SimpleConditionTracker(
- const ConfigKey& key, const int64_t& id, const int index,
+ const ConfigKey& key, const int64_t& id, const uint64_t protoHash, const int index,
const SimplePredicate& simplePredicate,
- const unordered_map<int64_t, int>& trackerNameIndexMap)
- : ConditionTracker(id, index), mConfigKey(key), mContainANYPositionInInternalDimensions(false) {
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap)
+ : ConditionTracker(id, index, protoHash),
+ mConfigKey(key),
+ mContainANYPositionInInternalDimensions(false) {
VLOG("creating SimpleConditionTracker %lld", (long long)mConditionId);
mCountNesting = simplePredicate.count_nesting();
- if (simplePredicate.has_start()) {
- auto pair = trackerNameIndexMap.find(simplePredicate.start());
- if (pair == trackerNameIndexMap.end()) {
- ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
- return;
- }
- mStartLogMatcherIndex = pair->second;
- mTrackerIndex.insert(mStartLogMatcherIndex);
- } else {
- mStartLogMatcherIndex = -1;
- }
-
- if (simplePredicate.has_stop()) {
- auto pair = trackerNameIndexMap.find(simplePredicate.stop());
- if (pair == trackerNameIndexMap.end()) {
- ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop());
- return;
- }
- mStopLogMatcherIndex = pair->second;
- mTrackerIndex.insert(mStopLogMatcherIndex);
- } else {
- mStopLogMatcherIndex = -1;
- }
-
- if (simplePredicate.has_stop_all()) {
- auto pair = trackerNameIndexMap.find(simplePredicate.stop_all());
- if (pair == trackerNameIndexMap.end()) {
- ALOGW("Stop all matcher %lld found in the config", (long long)simplePredicate.stop_all());
- return;
- }
- mStopAllLogMatcherIndex = pair->second;
- mTrackerIndex.insert(mStopAllLogMatcherIndex);
- } else {
- mStopAllLogMatcherIndex = -1;
- }
+ setMatcherIndices(simplePredicate, atomMatchingTrackerMap);
if (simplePredicate.has_dimensions()) {
translateFieldMatcher(simplePredicate.dimensions(), &mOutputDimensions);
if (mOutputDimensions.size() > 0) {
mSliced = true;
- mDimensionTag = mOutputDimensions[0].mMatcher.getTag();
}
mContainANYPositionInInternalDimensions = HasPositionANY(simplePredicate.dimensions());
}
@@ -106,6 +73,59 @@ bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig,
return mInitialized;
}
+bool SimpleConditionTracker::onConfigUpdated(
+ const vector<Predicate>& allConditionProtos, const int index,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& conditionTrackerMap) {
+ ConditionTracker::onConfigUpdated(allConditionProtos, index, allConditionTrackers,
+ atomMatchingTrackerMap, conditionTrackerMap);
+ setMatcherIndices(allConditionProtos[index].simple_predicate(), atomMatchingTrackerMap);
+ return true;
+}
+
+void SimpleConditionTracker::setMatcherIndices(
+ const SimplePredicate& simplePredicate,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
+ mTrackerIndex.clear();
+ if (simplePredicate.has_start()) {
+ auto pair = atomMatchingTrackerMap.find(simplePredicate.start());
+ if (pair == atomMatchingTrackerMap.end()) {
+ ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
+ return;
+ }
+ mStartLogMatcherIndex = pair->second;
+ mTrackerIndex.insert(mStartLogMatcherIndex);
+ } else {
+ mStartLogMatcherIndex = -1;
+ }
+
+ if (simplePredicate.has_stop()) {
+ auto pair = atomMatchingTrackerMap.find(simplePredicate.stop());
+ if (pair == atomMatchingTrackerMap.end()) {
+ ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop());
+ return;
+ }
+ mStopLogMatcherIndex = pair->second;
+ mTrackerIndex.insert(mStopLogMatcherIndex);
+ } else {
+ mStopLogMatcherIndex = -1;
+ }
+
+ if (simplePredicate.has_stop_all()) {
+ auto pair = atomMatchingTrackerMap.find(simplePredicate.stop_all());
+ if (pair == atomMatchingTrackerMap.end()) {
+ ALOGW("Stop all matcher %lld found in the config",
+ (long long)simplePredicate.stop_all());
+ return;
+ }
+ mStopAllLogMatcherIndex = pair->second;
+ mTrackerIndex.insert(mStopAllLogMatcherIndex);
+ } else {
+ mStopAllLogMatcherIndex = -1;
+ }
+}
+
void SimpleConditionTracker::dumpState() {
VLOG("%lld DUMP:", (long long)mConditionId);
for (const auto& pair : mSlicedConditionState) {
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.h b/cmds/statsd/src/condition/SimpleConditionTracker.h
index 1a9e35e38207..7a8b40108448 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.h
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.h
@@ -27,11 +27,11 @@ namespace android {
namespace os {
namespace statsd {
-class SimpleConditionTracker : public virtual ConditionTracker {
+class SimpleConditionTracker : public ConditionTracker {
public:
- SimpleConditionTracker(const ConfigKey& key, const int64_t& id, const int index,
- const SimplePredicate& simplePredicate,
- const std::unordered_map<int64_t, int>& trackerNameIndexMap);
+ SimpleConditionTracker(const ConfigKey& key, const int64_t& id, const uint64_t protoHash,
+ const int index, const SimplePredicate& simplePredicate,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap);
~SimpleConditionTracker();
@@ -40,6 +40,11 @@ public:
const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
std::vector<ConditionState>& conditionCache) override;
+ bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap) override;
+
void evaluateCondition(const LogEvent& event,
const std::vector<MatchingState>& eventMatcherValues,
const std::vector<sp<ConditionTracker>>& mAllConditions,
@@ -112,10 +117,11 @@ private:
std::set<HashableDimensionKey> mLastChangedToTrueDimensions;
std::set<HashableDimensionKey> mLastChangedToFalseDimensions;
- int mDimensionTag;
-
std::map<HashableDimensionKey, int> mSlicedConditionState;
+ void setMatcherIndices(const SimplePredicate& predicate,
+ const std::unordered_map<int64_t, int>& logTrackerMap);
+
void handleStopAll(std::vector<ConditionState>& conditionCache,
std::vector<bool>& changedCache);
@@ -129,6 +135,7 @@ private:
FRIEND_TEST(SimpleConditionTrackerTest, TestSlicedCondition);
FRIEND_TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim);
FRIEND_TEST(SimpleConditionTrackerTest, TestStopAll);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 5a520326116a..a0c701ea4229 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -80,7 +80,7 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
mConfigValid = initStatsdConfig(
key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
- mAllConditionTrackers, mAllMetricProducers, mAllAnomalyTrackers,
+ mAllConditionTrackers, mConditionTrackerMap, mAllMetricProducers, mAllAnomalyTrackers,
mAllPeriodicAlarmTrackers, mConditionToMetricMap, mTrackerToMetricMap,
mTrackerToConditionMap, mActivationAtomTrackerToMetricMap,
mDeactivationAtomTrackerToMetricMap, mAlertTrackerMap, mMetricIndexesWithActivation,
@@ -204,13 +204,20 @@ bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t time
const sp<AlarmMonitor>& periodicAlarmMonitor) {
vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ unordered_map<int64_t, int> newConditionTrackerMap;
mTagIds.clear();
+ mTrackerToConditionMap.clear();
mConfigValid = updateStatsdConfig(
mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseNs, currentTimeNs, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap, mTagIds,
- newAtomMatchingTrackers, newAtomMatchingTrackerMap);
+ timeBaseNs, currentTimeNs, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
+ mAllConditionTrackers, mConditionTrackerMap, mTagIds, newAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, newConditionTrackers, newConditionTrackerMap,
+ mTrackerToConditionMap);
mAllAtomMatchingTrackers = newAtomMatchingTrackers;
mAtomMatchingTrackerMap = newAtomMatchingTrackerMap;
+ mAllConditionTrackers = newConditionTrackers;
+ mConditionTrackerMap = newConditionTrackerMap;
return mConfigValid;
}
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 6f4b2d7e9fa4..bd0c8161a884 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -242,9 +242,12 @@ private:
// To make updating configs faster, we map the id of a AtomMatchingTracker, MetricProducer, and
// ConditionTracker to its index in the corresponding vector.
- // Maps the id of an atom matcher to its index in mAllAtomMatchingTrackers.
+ // Maps the id of an atom matching tracker to its index in mAllAtomMatchingTrackers.
std::unordered_map<int64_t, int> mAtomMatchingTrackerMap;
+ // Maps the id of a condition tracker to its index in mAllConditionTrackers.
+ std::unordered_map<int64_t, int> mConditionTrackerMap;
+
// To make the log processing more efficient, we want to do as much filtering as possible
// before we go into individual trackers and conditions to match.
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index 0983dc0b2c83..bd60b6bfcb8e 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -15,6 +15,7 @@
*/
#define DEBUG false // STOPSHIP if true
+#include "Log.h"
#include "config_update_utils.h"
@@ -44,7 +45,7 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI
// Check if new matcher.
const auto& oldAtomMatchingTrackerIt = oldAtomMatchingTrackerMap.find(id);
if (oldAtomMatchingTrackerIt == oldAtomMatchingTrackerMap.end()) {
- matchersToUpdate[matcherIdx] = UPDATE_REPLACE;
+ matchersToUpdate[matcherIdx] = UPDATE_NEW;
return true;
}
@@ -103,11 +104,13 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI
return true;
}
-bool updateAtomTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- set<int>& allTagIds, unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers) {
+bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ set<int>& allTagIds,
+ unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ set<int64_t>& replacedMatchers) {
const int atomMatcherCount = config.atom_matcher_size();
vector<AtomMatcher> matcherProtos;
@@ -157,7 +160,10 @@ bool updateAtomTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
newAtomMatchingTrackers.push_back(tracker);
break;
}
- case UPDATE_REPLACE: {
+ case UPDATE_REPLACE:
+ replacedMatchers.insert(id);
+ [[fallthrough]]; // Intentionally fallthrough to create the new matcher.
+ case UPDATE_NEW: {
sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, i, uidMap);
if (tracker == nullptr) {
return false;
@@ -187,6 +193,207 @@ bool updateAtomTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
return true;
}
+// Recursive function to determine if a condition needs to be updated. Populates conditionsToUpdate.
+// Returns whether the function was successful or not.
+bool determineConditionUpdateStatus(const StatsdConfig& config, const int conditionIdx,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const unordered_map<int64_t, int>& newConditionTrackerMap,
+ const set<int64_t>& replacedMatchers,
+ vector<UpdateStatus>& conditionsToUpdate,
+ vector<bool>& cycleTracker) {
+ // Have already examined this condition.
+ if (conditionsToUpdate[conditionIdx] != UPDATE_UNKNOWN) {
+ return true;
+ }
+
+ const Predicate& predicate = config.predicate(conditionIdx);
+ int64_t id = predicate.id();
+ // Check if new condition.
+ const auto& oldConditionTrackerIt = oldConditionTrackerMap.find(id);
+ if (oldConditionTrackerIt == oldConditionTrackerMap.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_NEW;
+ return true;
+ }
+
+ // This is an existing condition. Check if it has changed.
+ string serializedCondition;
+ if (!predicate.SerializeToString(&serializedCondition)) {
+ ALOGE("Unable to serialize matcher %lld", (long long)id);
+ return false;
+ }
+ uint64_t newProtoHash = Hash64(serializedCondition);
+ if (newProtoHash != oldConditionTrackers[oldConditionTrackerIt->second]->getProtoHash()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+
+ switch (predicate.contents_case()) {
+ case Predicate::ContentsCase::kSimplePredicate: {
+ // Need to check if any of the underlying matchers changed.
+ const SimplePredicate& simplePredicate = predicate.simple_predicate();
+ if (simplePredicate.has_start()) {
+ if (replacedMatchers.find(simplePredicate.start()) != replacedMatchers.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+ }
+ if (simplePredicate.has_stop()) {
+ if (replacedMatchers.find(simplePredicate.stop()) != replacedMatchers.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+ }
+ if (simplePredicate.has_stop_all()) {
+ if (replacedMatchers.find(simplePredicate.stop_all()) != replacedMatchers.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+ }
+ conditionsToUpdate[conditionIdx] = UPDATE_PRESERVE;
+ return true;
+ }
+ case Predicate::ContentsCase::kCombination: {
+ // Need to recurse on the children to see if any of the child predicates changed.
+ cycleTracker[conditionIdx] = true;
+ UpdateStatus status = UPDATE_PRESERVE;
+ for (const int64_t childPredicateId : predicate.combination().predicate()) {
+ const auto& childIt = newConditionTrackerMap.find(childPredicateId);
+ if (childIt == newConditionTrackerMap.end()) {
+ ALOGW("Predicate %lld not found in the config", (long long)childPredicateId);
+ return false;
+ }
+ const int childIdx = childIt->second;
+ if (cycleTracker[childIdx]) {
+ ALOGE("Cycle detected in predicate config");
+ return false;
+ }
+ if (!determineConditionUpdateStatus(config, childIdx, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate,
+ cycleTracker)) {
+ return false;
+ }
+
+ if (conditionsToUpdate[childIdx] == UPDATE_REPLACE) {
+ status = UPDATE_REPLACE;
+ break;
+ }
+ }
+ conditionsToUpdate[conditionIdx] = status;
+ cycleTracker[conditionIdx] = false;
+ return true;
+ }
+ default: {
+ ALOGE("Predicate \"%lld\" malformed", (long long)id);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const set<int64_t>& replacedMatchers,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ unordered_map<int64_t, int>& newConditionTrackerMap,
+ vector<sp<ConditionTracker>>& newConditionTrackers,
+ unordered_map<int, vector<int>>& trackerToConditionMap,
+ vector<ConditionState>& conditionCache, set<int64_t>& replacedConditions) {
+ vector<Predicate> conditionProtos;
+ const int conditionTrackerCount = config.predicate_size();
+ conditionProtos.reserve(conditionTrackerCount);
+ newConditionTrackers.reserve(conditionTrackerCount);
+ conditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated);
+
+ for (int i = 0; i < conditionTrackerCount; i++) {
+ const Predicate& condition = config.predicate(i);
+ if (newConditionTrackerMap.find(condition.id()) != newConditionTrackerMap.end()) {
+ ALOGE("Duplicate Predicate found!");
+ return false;
+ }
+ newConditionTrackerMap[condition.id()] = i;
+ conditionProtos.push_back(condition);
+ }
+
+ vector<UpdateStatus> conditionsToUpdate(conditionTrackerCount, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(conditionTrackerCount, false);
+ for (int i = 0; i < conditionTrackerCount; i++) {
+ if (!determineConditionUpdateStatus(config, i, oldConditionTrackerMap, oldConditionTrackers,
+ newConditionTrackerMap, replacedMatchers,
+ conditionsToUpdate, cycleTracker)) {
+ return false;
+ }
+ }
+
+ // Update status has been determined for all conditions. Now perform the update.
+ set<int> preservedConditions;
+ for (int i = 0; i < conditionTrackerCount; i++) {
+ const Predicate& predicate = config.predicate(i);
+ const int64_t id = predicate.id();
+ switch (conditionsToUpdate[i]) {
+ case UPDATE_PRESERVE: {
+ preservedConditions.insert(i);
+ const auto& oldConditionTrackerIt = oldConditionTrackerMap.find(id);
+ if (oldConditionTrackerIt == oldConditionTrackerMap.end()) {
+ ALOGE("Could not find Predicate %lld in the previous config, but expected it "
+ "to be there",
+ (long long)id);
+ return false;
+ }
+ const int oldIndex = oldConditionTrackerIt->second;
+ newConditionTrackers.push_back(oldConditionTrackers[oldIndex]);
+ break;
+ }
+ case UPDATE_REPLACE:
+ replacedConditions.insert(id);
+ [[fallthrough]]; // Intentionally fallthrough to create the new condition tracker.
+ case UPDATE_NEW: {
+ sp<ConditionTracker> tracker =
+ createConditionTracker(key, predicate, i, atomMatchingTrackerMap);
+ if (tracker == nullptr) {
+ return false;
+ }
+ newConditionTrackers.push_back(tracker);
+ break;
+ }
+ default: {
+ ALOGE("Condition \"%lld\" update state is unknown. This should never happen",
+ (long long)id);
+ return false;
+ }
+ }
+ }
+
+ // Update indices of preserved predicates.
+ for (const int conditionIndex : preservedConditions) {
+ if (!newConditionTrackers[conditionIndex]->onConfigUpdated(
+ conditionProtos, conditionIndex, newConditionTrackers, atomMatchingTrackerMap,
+ newConditionTrackerMap)) {
+ ALOGE("Failed to update condition %lld",
+ (long long)newConditionTrackers[conditionIndex]->getConditionId());
+ return false;
+ }
+ }
+
+ std::fill(cycleTracker.begin(), cycleTracker.end(), false);
+ for (int conditionIndex = 0; conditionIndex < conditionTrackerCount; conditionIndex++) {
+ const sp<ConditionTracker>& conditionTracker = newConditionTrackers[conditionIndex];
+ // Calling init on preserved conditions is OK. It is needed to fill the condition cache.
+ if (!conditionTracker->init(conditionProtos, newConditionTrackers, newConditionTrackerMap,
+ cycleTracker, conditionCache)) {
+ return false;
+ }
+ for (const int trackerIndex : conditionTracker->getAtomMatchingTrackerIndex()) {
+ vector<int>& conditionList = trackerToConditionMap[trackerIndex];
+ conditionList.push_back(conditionIndex);
+ }
+ }
+ return true;
+}
+
bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
const sp<StatsPullerManager>& pullerManager,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
@@ -194,14 +401,34 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
const int64_t currentTimeNs,
const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
set<int>& allTagIds,
vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
- unordered_map<int64_t, int>& newAtomMatchingTrackerMap) {
- if (!updateAtomTrackers(config, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers,
- allTagIds, newAtomMatchingTrackerMap, newAtomMatchingTrackers)) {
+ unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ vector<sp<ConditionTracker>>& newConditionTrackers,
+ unordered_map<int64_t, int>& newConditionTrackerMap,
+ unordered_map<int, vector<int>>& trackerToConditionMap) {
+ set<int64_t> replacedMatchers;
+ set<int64_t> replacedConditions;
+ vector<ConditionState> conditionCache;
+
+ if (!updateAtomMatchingTrackers(config, uidMap, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, allTagIds, newAtomMatchingTrackerMap,
+ newAtomMatchingTrackers, replacedMatchers)) {
ALOGE("updateAtomMatchingTrackers failed");
return false;
}
+ VLOG("updateAtomMatchingTrackers succeeded");
+
+ if (!updateConditions(key, config, newAtomMatchingTrackerMap, replacedMatchers,
+ oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap,
+ newConditionTrackers, trackerToConditionMap, conditionCache,
+ replacedConditions)) {
+ ALOGE("updateConditions failed");
+ return false;
+ }
+ VLOG("updateConditions succeeded");
return true;
}
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
index ae7b2162e034..7ba684a65e88 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
@@ -19,6 +19,7 @@
#include <vector>
#include "anomaly/AlarmMonitor.h"
+#include "condition/ConditionTracker.h"
#include "external/StatsPullerManager.h"
#include "matchers/AtomMatchingTracker.h"
@@ -31,30 +32,33 @@ namespace statsd {
// All other functions are intermediate steps, created to make unit testing easier.
// Possible update states for a component. PRESERVE means we should keep the existing one.
-// REPLACE means we should create a new one, either because it didn't exist or it changed.
+// REPLACE means we should create a new one because the existing one changed
+// NEW means we should create a new one because one does not currently exist.
enum UpdateStatus {
UPDATE_UNKNOWN = 0,
UPDATE_PRESERVE = 1,
UPDATE_REPLACE = 2,
+ UPDATE_NEW = 3,
};
// Recursive function to determine if a matcher needs to be updated.
// input:
// [config]: the input StatsdConfig
// [matcherIdx]: the index of the current matcher to be updated
-// [newAtomMatchingTrackerMap]: matcher id to index mapping in the input StatsdConfig
// [oldAtomMatchingTrackerMap]: matcher id to index mapping in the existing MetricsManager
// [oldAtomMatchingTrackers]: stores the existing AtomMatchingTrackers
+// [newAtomMatchingTrackerMap]: matcher id to index mapping in the input StatsdConfig
// output:
// [matchersToUpdate]: vector of the update status of each matcher. The matcherIdx index will
// be updated from UPDATE_UNKNOWN after this call.
// [cycleTracker]: intermediate param used during recursion.
-bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherIdx,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- vector<UpdateStatus>& matchersToUpdate,
- vector<bool>& cycleTracker);
+// Returns whether the function was successful or not.
+bool determineMatcherUpdateStatus(
+ const StatsdConfig& config, const int matcherIdx,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<UpdateStatus>& matchersToUpdate, std::vector<bool>& cycleTracker);
// Updates the AtomMatchingTrackers.
// input:
@@ -64,12 +68,61 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI
// output:
// [allTagIds]: contains the set of all interesting tag ids to this config.
// [newAtomMatchingTrackerMap]: new matcher id to index mapping
-// [newAtomMatchers]: stores the new AtomMatchingTrackers
-bool updateAtomTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- set<int>& allTagIds, unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers);
+// [newAtomMatchingTrackers]: stores the new AtomMatchingTrackers
+// [replacedMatchers]: set of matcher ids that changed and have been replaced
+bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ std::set<int>& allTagIds,
+ std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ std::set<int64_t>& replacedMatchers);
+
+// Recursive function to determine if a condition needs to be updated.
+// input:
+// [config]: the input StatsdConfig
+// [conditionIdx]: the index of the current condition to be updated
+// [oldConditionTrackerMap]: condition id to index mapping in the existing MetricsManager
+// [oldConditionTrackers]: stores the existing ConditionTrackers
+// [newConditionTrackerMap]: condition id to index mapping in the input StatsdConfig
+// [replacedMatchers]: set of replaced matcher ids. conditions using these matchers must be replaced
+// output:
+// [conditionsToUpdate]: vector of the update status of each condition. The conditionIdx index will
+// be updated from UPDATE_UNKNOWN after this call.
+// [cycleTracker]: intermediate param used during recursion.
+// Returns whether the function was successful or not.
+bool determineConditionUpdateStatus(const StatsdConfig& config, const int conditionIdx,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ const std::set<int64_t>& replacedMatchers,
+ std::vector<UpdateStatus>& conditionsToUpdate,
+ std::vector<bool>& cycleTracker);
+
+// Updates ConditionTrackers
+// input:
+// [config]: the input config
+// [atomMatchingTrackerMap]: AtomMatchingTracker name to index mapping from previous step.
+// [replacedMatchers]: ids of replaced matchers. conditions depending on these must also be replaced
+// [oldConditionTrackerMap]: existing matcher id to index mapping
+// [oldConditionTrackers]: stores the existing ConditionTrackers
+// output:
+// [newConditionTrackerMap]: new condition id to index mapping
+// [newConditionTrackers]: stores the sp to all the ConditionTrackers
+// [trackerToConditionMap]: contains the mapping from the index of an atom matcher
+// to indices of condition trackers that use the matcher
+// [conditionCache]: stores the current conditions for each ConditionTracker
+// [replacedConditions]: set of matcher ids that have changed and have been replaced
+bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::set<int64_t>& replacedMatchers,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ std::vector<sp<ConditionTracker>>& newConditionTrackers,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
+ std::vector<ConditionState>& conditionCache,
+ std::set<int64_t>& replacedConditions);
// Updates the existing MetricsManager from a new StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
@@ -79,10 +132,15 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
const int64_t currentTimeNs,
const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
std::set<int>& allTagIds,
std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
- unordered_map<int64_t, int>& newAtomMatchingTrackerMap);
+ std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<sp<ConditionTracker>>& newConditionTrackers,
+ std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index e40fbdb250f1..2e3e43413d54 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -74,16 +74,37 @@ sp<AtomMatchingTracker> createAtomMatchingTracker(const AtomMatcher& logMatcher,
case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
return new SimpleAtomMatchingTracker(logMatcher.id(), index, protoHash,
logMatcher.simple_atom_matcher(), uidMap);
- break;
case AtomMatcher::ContentsCase::kCombination:
return new CombinationAtomMatchingTracker(logMatcher.id(), index, protoHash);
- break;
default:
ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
return nullptr;
}
}
+sp<ConditionTracker> createConditionTracker(
+ const ConfigKey& key, const Predicate& predicate, const int index,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
+ string serializedPredicate;
+ if (!predicate.SerializeToString(&serializedPredicate)) {
+ ALOGE("Unable to serialize predicate %lld", (long long)predicate.id());
+ return nullptr;
+ }
+ uint64_t protoHash = Hash64(serializedPredicate);
+ switch (predicate.contents_case()) {
+ case Predicate::ContentsCase::kSimplePredicate: {
+ return new SimpleConditionTracker(key, predicate.id(), protoHash, index,
+ predicate.simple_predicate(), atomMatchingTrackerMap);
+ }
+ case Predicate::ContentsCase::kCombination: {
+ return new CombinationConditionTracker(predicate.id(), index, protoHash);
+ }
+ default:
+ ALOGE("Predicate \"%lld\" malformed", (long long)predicate.id());
+ return nullptr;
+ }
+}
+
bool handleMetricWithAtomMatchingTrackers(
const int64_t what, const int metricIndex, const bool usedForDimension,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -266,8 +287,7 @@ bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidM
for (int i = 0; i < atomMatcherCount; i++) {
const AtomMatcher& logMatcher = config.atom_matcher(i);
- int index = allAtomMatchingTrackers.size();
- sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(logMatcher, index, uidMap);
+ sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(logMatcher, i, uidMap);
if (tracker == nullptr) {
return false;
}
@@ -276,7 +296,7 @@ bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidM
ALOGE("Duplicate AtomMatcher found!");
return false;
}
- atomMatchingTrackerMap[logMatcher.id()] = index;
+ atomMatchingTrackerMap[logMatcher.id()] = i;
matcherConfigs.push_back(logMatcher);
}
@@ -307,28 +327,17 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
for (int i = 0; i < conditionTrackerCount; i++) {
const Predicate& condition = config.predicate(i);
- int index = allConditionTrackers.size();
- switch (condition.contents_case()) {
- case Predicate::ContentsCase::kSimplePredicate: {
- allConditionTrackers.push_back(new SimpleConditionTracker(
- key, condition.id(), index, condition.simple_predicate(),
- atomMatchingTrackerMap));
- break;
- }
- case Predicate::ContentsCase::kCombination: {
- allConditionTrackers.push_back(
- new CombinationConditionTracker(condition.id(), index));
- break;
- }
- default:
- ALOGE("Predicate \"%lld\" malformed", (long long)condition.id());
- return false;
+ sp<ConditionTracker> tracker =
+ createConditionTracker(key, condition, i, atomMatchingTrackerMap);
+ if (tracker == nullptr) {
+ return false;
}
+ allConditionTrackers.push_back(tracker);
if (conditionTrackerMap.find(condition.id()) != conditionTrackerMap.end()) {
ALOGE("Duplicate Predicate found!");
return false;
}
- conditionTrackerMap[condition.id()] = index;
+ conditionTrackerMap[condition.id()] = i;
conditionConfigs.push_back(condition);
}
@@ -934,6 +943,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
unordered_map<int64_t, int>& atomMatchingTrackerMap,
vector<sp<ConditionTracker>>& allConditionTrackers,
+ unordered_map<int64_t, int>& conditionTrackerMap,
vector<sp<MetricProducer>>& allMetricProducers,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
@@ -944,7 +954,6 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
unordered_map<int64_t, int>& alertTrackerMap,
vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds) {
- unordered_map<int64_t, int> conditionTrackerMap;
vector<ConditionState> initialConditionCache;
unordered_map<int64_t, int> metricProducerMap;
unordered_map<int64_t, int> stateAtomIdMap;
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index 4cfd1b0465ea..6eabcf4971d3 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -42,6 +42,17 @@ namespace statsd {
sp<AtomMatchingTracker> createAtomMatchingTracker(const AtomMatcher& logMatcher, const int index,
const sp<UidMap>& uidMap);
+// Create a ConditionTracker.
+// input:
+// [predicate]: the input Predicate from the StatsdConfig
+// [index]: the index of the condition tracker
+// [atomMatchingTrackerMap]: map of atom matcher id to its index in allAtomMatchingTrackers
+// output:
+// new ConditionTracker, or null if the tracker is unable to be created
+sp<ConditionTracker> createConditionTracker(
+ const ConfigKey& key, const Predicate& predicate, const int index,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap);
+
// Helper functions for MetricsManager to initialize from StatsdConfig.
// *Note*: only initStatsdConfig() should be called from outside.
// All other functions are intermediate
@@ -77,7 +88,6 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
std::unordered_map<int64_t, int>& conditionTrackerMap,
std::vector<sp<ConditionTracker>>& allConditionTrackers,
std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
- std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
std::vector<ConditionState>& initialConditionCache);
// Initialize State maps using State protos in the config. These maps will
@@ -111,7 +121,6 @@ bool initMetrics(
const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
const std::unordered_map<int64_t, int>& conditionTrackerMap,
- const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& stateAtomIdMap,
const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
@@ -135,6 +144,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ std::unordered_map<int64_t, int>& conditionTrackerMap,
std::vector<sp<MetricProducer>>& allMetricProducers,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
index 07b5311b1207..8998b5f98df5 100644
--- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
@@ -39,6 +39,7 @@ const ConfigKey kConfigKey(0, 12345);
const int ATTRIBUTION_NODE_FIELD_ID = 1;
const int ATTRIBUTION_UID_FIELD_ID = 1;
const int TAG_ID = 1;
+const uint64_t protoHash = 0x123456789;
SimplePredicate getWakeLockHeldCondition(bool countNesting, bool defaultFalse,
bool outputSlicedUid, Position position) {
@@ -123,7 +124,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueFalse) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
0 /*tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -177,7 +178,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueUnknown) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
0 /*tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -231,8 +232,9 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedCondition) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), 0 /*tracker index*/,
- simplePredicate, trackerNameIndexMap);
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
+ 0 /*tracker index*/, simplePredicate,
+ trackerNameIndexMap);
EXPECT_FALSE(conditionTracker.isSliced());
// This event is not accessed in this test besides dimensions which is why this is okay.
@@ -317,7 +319,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
EXPECT_FALSE(conditionTracker.isSliced());
@@ -392,7 +394,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -514,7 +516,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -610,7 +612,7 @@ TEST(SimpleConditionTrackerTest, TestStopAll) {
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
index 8c698eb15d8d..890884bc5d83 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -14,6 +14,7 @@
#include "src/metrics/parsing_utils/config_update_utils.h"
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
#include <stdio.h>
@@ -23,6 +24,8 @@
#include <vector>
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "src/condition/CombinationConditionTracker.h"
+#include "src/condition/SimpleConditionTracker.h"
#include "src/matchers/CombinationAtomMatchingTracker.h"
#include "src/metrics/parsing_utils/metrics_manager_util.h"
#include "tests/statsd_test_util.h"
@@ -53,6 +56,7 @@ set<int> allTagIds;
vector<sp<AtomMatchingTracker>> oldAtomMatchingTrackers;
unordered_map<int64_t, int> oldAtomMatchingTrackerMap;
vector<sp<ConditionTracker>> oldConditionTrackers;
+unordered_map<int64_t, int> oldConditionTrackerMap;
vector<sp<MetricProducer>> oldMetricProducers;
std::vector<sp<AnomalyTracker>> oldAnomalyTrackers;
std::vector<sp<AlarmTracker>> oldAlarmTrackers;
@@ -75,6 +79,7 @@ public:
oldAtomMatchingTrackers.clear();
oldAtomMatchingTrackerMap.clear();
oldConditionTrackers.clear();
+ oldConditionTrackerMap.clear();
oldMetricProducers.clear();
oldAnomalyTrackers.clear();
oldAlarmTrackers.clear();
@@ -93,8 +98,8 @@ bool initConfig(const StatsdConfig& config) {
return initStatsdConfig(
key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, timeBaseNs, allTagIds, oldAtomMatchingTrackers, oldAtomMatchingTrackerMap,
- oldConditionTrackers, oldMetricProducers, oldAnomalyTrackers, oldAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ oldConditionTrackers, oldConditionTrackerMap, oldMetricProducers, oldAnomalyTrackers,
+ oldAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds);
}
@@ -144,6 +149,30 @@ TEST_F(ConfigUpdateTest, TestSimpleMatcherReplace) {
EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE);
}
+TEST_F(ConfigUpdateTest, TestSimpleMatcherNew) {
+ StatsdConfig config;
+ AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10);
+ *config.add_atom_matcher() = matcher;
+
+ EXPECT_TRUE(initConfig(config));
+
+ StatsdConfig newConfig;
+ // Different id, so should be a new matcher.
+ AtomMatcher newMatcher = CreateSimpleAtomMatcher("DIFFERENT_NAME", /*atom=*/10);
+ int64_t matcherId = newMatcher.id();
+ EXPECT_NE(matcherId, matcher.id());
+ *newConfig.add_atom_matcher() = newMatcher;
+
+ vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ newAtomMatchingTrackerMap[matcherId] = 0;
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_NEW);
+}
+
TEST_F(ConfigUpdateTest, TestCombinationMatcherPreserve) {
StatsdConfig config;
AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
@@ -338,9 +367,10 @@ TEST_F(ConfigUpdateTest, TestUpdateMatchers) {
set<int> newTagIds;
unordered_map<int64_t, int> newAtomMatchingTrackerMap;
vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
- EXPECT_TRUE(updateAtomTrackers(newConfig, uidMap, oldAtomMatchingTrackerMap,
- oldAtomMatchingTrackers, newTagIds, newAtomMatchingTrackerMap,
- newAtomMatchingTrackers));
+ set<int64_t> replacedMatchers;
+ EXPECT_TRUE(updateAtomMatchingTrackers(
+ newConfig, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, newTagIds,
+ newAtomMatchingTrackerMap, newAtomMatchingTrackers, replacedMatchers));
ASSERT_EQ(newTagIds.size(), 3);
EXPECT_EQ(newTagIds.count(10), 1);
@@ -405,8 +435,454 @@ TEST_F(ConfigUpdateTest, TestUpdateMatchers) {
EXPECT_EQ(childMatchers->size(), 2);
EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 1), childMatchers->end());
EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 4), childMatchers->end());
+
+ // Expect replacedMatchers to have simple2 and combination2
+ ASSERT_EQ(replacedMatchers.size(), 2);
+ EXPECT_NE(replacedMatchers.find(simple2Id), replacedMatchers.end());
+ EXPECT_NE(replacedMatchers.find(combination2Id), replacedMatchers.end());
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleConditionPreserve) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ newConditionTrackerMap[predicate.id()] = 0;
+ EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleConditionReplace) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Modify the predicate.
+ config.mutable_predicate(0)->mutable_simple_predicate()->set_count_nesting(true);
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ newConditionTrackerMap[predicate.id()] = 0;
+ EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleConditionDepsChange) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ int64_t startMatcherId = startMatcher.id();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Start matcher was replaced.
+ set<int64_t> replacedMatchers;
+ replacedMatchers.insert(startMatcherId);
+
+ vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ newConditionTrackerMap[predicate.id()] = 0;
+ EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationConditionPreserve) {
+ StatsdConfig config;
+ AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ *config.add_predicate() = simple1;
+ Predicate simple2 = CreateScreenIsOffPredicate();
+ *config.add_predicate() = simple2;
+
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ Predicate_Combination* combinationInternal = combination1.mutable_combination();
+ combinationInternal->set_operation(LogicalOperation::NAND);
+ combinationInternal->add_predicate(simple1.id());
+ combinationInternal->add_predicate(simple2.id());
+ *config.add_predicate() = combination1;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Same predicates, different order
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ *newConfig.add_predicate() = combination1;
+ newConditionTrackerMap[combination1.id()] = 0;
+ *newConfig.add_predicate() = simple2;
+ newConditionTrackerMap[simple2.id()] = 1;
+ *newConfig.add_predicate() = simple1;
+ newConditionTrackerMap[simple1.id()] = 2;
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. It should recurse the two child predicates and preserve all 3.
+ EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_PRESERVE);
+ EXPECT_EQ(conditionsToUpdate[1], UPDATE_PRESERVE);
+ EXPECT_EQ(conditionsToUpdate[2], UPDATE_PRESERVE);
}
+TEST_F(ConfigUpdateTest, TestCombinationConditionReplace) {
+ StatsdConfig config;
+ AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ *config.add_predicate() = simple1;
+ Predicate simple2 = CreateScreenIsOffPredicate();
+ *config.add_predicate() = simple2;
+
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ Predicate_Combination* combinationInternal = combination1.mutable_combination();
+ combinationInternal->set_operation(LogicalOperation::NAND);
+ combinationInternal->add_predicate(simple1.id());
+ combinationInternal->add_predicate(simple2.id());
+ *config.add_predicate() = combination1;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Changing the logical operation changes the predicate definition, so it should be replaced.
+ combination1.mutable_combination()->set_operation(LogicalOperation::OR);
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ *newConfig.add_predicate() = combination1;
+ newConditionTrackerMap[combination1.id()] = 0;
+ *newConfig.add_predicate() = simple2;
+ newConditionTrackerMap[simple2.id()] = 1;
+ *newConfig.add_predicate() = simple1;
+ newConditionTrackerMap[simple1.id()] = 2;
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. The simple conditions should not be evaluated.
+ EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+ EXPECT_EQ(conditionsToUpdate[1], UPDATE_UNKNOWN);
+ EXPECT_EQ(conditionsToUpdate[2], UPDATE_UNKNOWN);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationConditionDepsChange) {
+ StatsdConfig config;
+ AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ *config.add_predicate() = simple1;
+ Predicate simple2 = CreateScreenIsOffPredicate();
+ *config.add_predicate() = simple2;
+
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ Predicate_Combination* combinationInternal = combination1.mutable_combination();
+ combinationInternal->set_operation(LogicalOperation::NAND);
+ combinationInternal->add_predicate(simple1.id());
+ combinationInternal->add_predicate(simple2.id());
+ *config.add_predicate() = combination1;
+
+ EXPECT_TRUE(initConfig(config));
+
+ simple2.mutable_simple_predicate()->set_count_nesting(false);
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ *newConfig.add_predicate() = combination1;
+ newConditionTrackerMap[combination1.id()] = 0;
+ *newConfig.add_predicate() = simple2;
+ newConditionTrackerMap[simple2.id()] = 1;
+ *newConfig.add_predicate() = simple1;
+ newConditionTrackerMap[simple1.id()] = 2;
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. Simple2 and combination1 must be evaluated.
+ EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+ EXPECT_EQ(conditionsToUpdate[1], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateConditions) {
+ StatsdConfig config;
+
+ // Add atom matchers. These are mostly needed for initStatsdConfig
+ AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher();
+ int64_t matcher2Id = matcher2.id();
+ *config.add_atom_matcher() = matcher2;
+
+ AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher();
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ AtomMatcher matcher4 = CreateFinishScheduledJobAtomMatcher();
+ int64_t matcher4Id = matcher4.id();
+ *config.add_atom_matcher() = matcher4;
+
+ AtomMatcher matcher5 = CreateBatterySaverModeStartAtomMatcher();
+ int64_t matcher5Id = matcher5.id();
+ *config.add_atom_matcher() = matcher5;
+
+ AtomMatcher matcher6 = CreateBatterySaverModeStopAtomMatcher();
+ int64_t matcher6Id = matcher6.id();
+ *config.add_atom_matcher() = matcher6;
+
+ // Add the predicates.
+ // Will be preserved.
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ int64_t simple1Id = simple1.id();
+ *config.add_predicate() = simple1;
+
+ // Will be preserved.
+ Predicate simple2 = CreateScheduledJobPredicate();
+ int64_t simple2Id = simple2.id();
+ *config.add_predicate() = simple2;
+
+ // Will be replaced.
+ Predicate simple3 = CreateBatterySaverModePredicate();
+ int64_t simple3Id = simple3.id();
+ *config.add_predicate() = simple3;
+
+ // Will be preserved
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ combination1.mutable_combination()->set_operation(LogicalOperation::AND);
+ combination1.mutable_combination()->add_predicate(simple1Id);
+ combination1.mutable_combination()->add_predicate(simple2Id);
+ int64_t combination1Id = combination1.id();
+ *config.add_predicate() = combination1;
+
+ // Will be replaced since simple3 will be replaced.
+ Predicate combination2;
+ combination2.set_id(StringToId("COMBINATION2"));
+ combination2.mutable_combination()->set_operation(LogicalOperation::OR);
+ combination2.mutable_combination()->add_predicate(simple1Id);
+ combination2.mutable_combination()->add_predicate(simple3Id);
+ int64_t combination2Id = combination2.id();
+ *config.add_predicate() = combination2;
+
+ // Will be removed.
+ Predicate combination3;
+ combination3.set_id(StringToId("COMBINATION3"));
+ combination3.mutable_combination()->set_operation(LogicalOperation::NOT);
+ combination3.mutable_combination()->add_predicate(simple2Id);
+ int64_t combination3Id = combination3.id();
+ *config.add_predicate() = combination3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Mark marcher 5 as replaced. Causes simple3, and therefore combination2 to be replaced.
+ set<int64_t> replacedMatchers;
+ replacedMatchers.insert(matcher6Id);
+
+ // Change the condition of simple1 to true.
+ ASSERT_EQ(oldConditionTrackers[0]->getConditionId(), simple1Id);
+ LogEvent event(/*uid=*/0, /*pid=*/0); // Empty event is fine since there are no dimensions.
+ // Mark the stop matcher as matched, condition should be false.
+ vector<MatchingState> eventMatcherValues(6, MatchingState::kNotMatched);
+ eventMatcherValues[1] = MatchingState::kMatched;
+ vector<ConditionState> tmpConditionCache(6, ConditionState::kNotEvaluated);
+ vector<bool> conditionChangeCache(6, false);
+ oldConditionTrackers[0]->evaluateCondition(event, eventMatcherValues, oldConditionTrackers,
+ tmpConditionCache, conditionChangeCache);
+ EXPECT_EQ(tmpConditionCache[0], ConditionState::kFalse);
+ EXPECT_EQ(conditionChangeCache[0], true);
+
+ // New combination matcher. Should have an initial condition of true since it is NOT(simple1).
+ Predicate combination4;
+ combination4.set_id(StringToId("COMBINATION4"));
+ combination4.mutable_combination()->set_operation(LogicalOperation::NOT);
+ combination4.mutable_combination()->add_predicate(simple1Id);
+ int64_t combination4Id = combination4.id();
+ *config.add_predicate() = combination4;
+
+ // Map the matchers in reverse order to force the indices to change.
+ std::unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ const int matcher6Index = 0;
+ newAtomMatchingTrackerMap[matcher6Id] = 0;
+ const int matcher5Index = 1;
+ newAtomMatchingTrackerMap[matcher5Id] = 1;
+ const int matcher4Index = 2;
+ newAtomMatchingTrackerMap[matcher4Id] = 2;
+ const int matcher3Index = 3;
+ newAtomMatchingTrackerMap[matcher3Id] = 3;
+ const int matcher2Index = 4;
+ newAtomMatchingTrackerMap[matcher2Id] = 4;
+ const int matcher1Index = 5;
+ newAtomMatchingTrackerMap[matcher1Id] = 5;
+
+ StatsdConfig newConfig;
+ *newConfig.add_predicate() = simple3;
+ const int simple3Index = 0;
+ *newConfig.add_predicate() = combination2;
+ const int combination2Index = 1;
+ *newConfig.add_predicate() = combination4;
+ const int combination4Index = 2;
+ *newConfig.add_predicate() = simple2;
+ const int simple2Index = 3;
+ *newConfig.add_predicate() = combination1;
+ const int combination1Index = 4;
+ *newConfig.add_predicate() = simple1;
+ const int simple1Index = 5;
+
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ unordered_map<int, vector<int>> trackerToConditionMap;
+ std::vector<ConditionState> conditionCache;
+ std::set<int64_t> replacedConditions;
+ EXPECT_TRUE(updateConditions(key, newConfig, newAtomMatchingTrackerMap, replacedMatchers,
+ oldConditionTrackerMap, oldConditionTrackers,
+ newConditionTrackerMap, newConditionTrackers,
+ trackerToConditionMap, conditionCache, replacedConditions));
+
+ unordered_map<int64_t, int> expectedConditionTrackerMap = {
+ {simple1Id, simple1Index}, {simple2Id, simple2Index},
+ {simple3Id, simple3Index}, {combination1Id, combination1Index},
+ {combination2Id, combination2Index}, {combination4Id, combination4Index},
+ };
+ EXPECT_THAT(newConditionTrackerMap, ContainerEq(expectedConditionTrackerMap));
+
+ ASSERT_EQ(newConditionTrackers.size(), 6);
+ // Make sure all conditions are initialized:
+ for (const sp<ConditionTracker>& tracker : newConditionTrackers) {
+ EXPECT_TRUE(tracker->mInitialized);
+ }
+
+ // Make sure preserved conditions are the same.
+ EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(simple1Id)],
+ newConditionTrackers[newConditionTrackerMap.at(simple1Id)]);
+ EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(simple2Id)],
+ newConditionTrackers[newConditionTrackerMap.at(simple2Id)]);
+ EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(combination1Id)],
+ newConditionTrackers[newConditionTrackerMap.at(combination1Id)]);
+
+ // Make sure replaced conditions are different and included in replacedConditions.
+ EXPECT_NE(oldConditionTrackers[oldConditionTrackerMap.at(simple3Id)],
+ newConditionTrackers[newConditionTrackerMap.at(simple3Id)]);
+ EXPECT_NE(oldConditionTrackers[oldConditionTrackerMap.at(combination2Id)],
+ newConditionTrackers[newConditionTrackerMap.at(combination2Id)]);
+ EXPECT_THAT(replacedConditions, ContainerEq(set({simple3Id, combination2Id})));
+
+ // Verify the trackerToConditionMap
+ ASSERT_EQ(trackerToConditionMap.size(), 6);
+ const vector<int>& matcher1Conditions = trackerToConditionMap[matcher1Index];
+ EXPECT_THAT(matcher1Conditions, UnorderedElementsAre(simple1Index, combination1Index,
+ combination2Index, combination4Index));
+ const vector<int>& matcher2Conditions = trackerToConditionMap[matcher2Index];
+ EXPECT_THAT(matcher2Conditions, UnorderedElementsAre(simple1Index, combination1Index,
+ combination2Index, combination4Index));
+ const vector<int>& matcher3Conditions = trackerToConditionMap[matcher3Index];
+ EXPECT_THAT(matcher3Conditions, UnorderedElementsAre(simple2Index, combination1Index));
+ const vector<int>& matcher4Conditions = trackerToConditionMap[matcher4Index];
+ EXPECT_THAT(matcher4Conditions, UnorderedElementsAre(simple2Index, combination1Index));
+ const vector<int>& matcher5Conditions = trackerToConditionMap[matcher5Index];
+ EXPECT_THAT(matcher5Conditions, UnorderedElementsAre(simple3Index, combination2Index));
+ const vector<int>& matcher6Conditions = trackerToConditionMap[matcher6Index];
+ EXPECT_THAT(matcher6Conditions, UnorderedElementsAre(simple3Index, combination2Index));
+
+ // Verify the conditionCache. Specifically, simple1 is false and combination4 is true.
+ ASSERT_EQ(conditionCache.size(), 6);
+ EXPECT_EQ(conditionCache[simple1Index], ConditionState::kFalse);
+ EXPECT_EQ(conditionCache[simple2Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[simple3Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[combination1Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[combination2Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[combination4Index], ConditionState::kTrue);
+
+ // Verify tracker indices/ids are correct.
+ EXPECT_EQ(newConditionTrackers[simple1Index]->getConditionId(), simple1Id);
+ EXPECT_EQ(newConditionTrackers[simple1Index]->mIndex, simple1Index);
+ EXPECT_TRUE(newConditionTrackers[simple1Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[simple2Index]->getConditionId(), simple2Id);
+ EXPECT_EQ(newConditionTrackers[simple2Index]->mIndex, simple2Index);
+ EXPECT_TRUE(newConditionTrackers[simple2Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[simple3Index]->getConditionId(), simple3Id);
+ EXPECT_EQ(newConditionTrackers[simple3Index]->mIndex, simple3Index);
+ EXPECT_TRUE(newConditionTrackers[simple3Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[combination1Index]->getConditionId(), combination1Id);
+ EXPECT_EQ(newConditionTrackers[combination1Index]->mIndex, combination1Index);
+ EXPECT_FALSE(newConditionTrackers[combination1Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[combination2Index]->getConditionId(), combination2Id);
+ EXPECT_EQ(newConditionTrackers[combination2Index]->mIndex, combination2Index);
+ EXPECT_FALSE(newConditionTrackers[combination2Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[combination4Index]->getConditionId(), combination4Id);
+ EXPECT_EQ(newConditionTrackers[combination4Index]->mIndex, combination4Index);
+ EXPECT_FALSE(newConditionTrackers[combination4Index]->IsSimpleCondition());
+
+ // Verify preserved trackers have indices updated.
+ SimpleConditionTracker* simpleTracker1 =
+ static_cast<SimpleConditionTracker*>(newConditionTrackers[simple1Index].get());
+ EXPECT_EQ(simpleTracker1->mStartLogMatcherIndex, matcher1Index);
+ EXPECT_EQ(simpleTracker1->mStopLogMatcherIndex, matcher2Index);
+ EXPECT_EQ(simpleTracker1->mStopAllLogMatcherIndex, -1);
+
+ SimpleConditionTracker* simpleTracker2 =
+ static_cast<SimpleConditionTracker*>(newConditionTrackers[simple2Index].get());
+ EXPECT_EQ(simpleTracker2->mStartLogMatcherIndex, matcher3Index);
+ EXPECT_EQ(simpleTracker2->mStopLogMatcherIndex, matcher4Index);
+ EXPECT_EQ(simpleTracker2->mStopAllLogMatcherIndex, -1);
+
+ CombinationConditionTracker* combinationTracker1 = static_cast<CombinationConditionTracker*>(
+ newConditionTrackers[combination1Index].get());
+ EXPECT_THAT(combinationTracker1->mChildren, UnorderedElementsAre(simple1Index, simple2Index));
+ EXPECT_THAT(combinationTracker1->mUnSlicedChildren,
+ UnorderedElementsAre(simple1Index, simple2Index));
+ EXPECT_THAT(combinationTracker1->mSlicedChildren, IsEmpty());
+}
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
index d6db4c12ae4d..e6583c9686ec 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
@@ -384,8 +384,9 @@ TEST(MetricsManagerTest, TestInitialConditions) {
StatsdConfig config = buildConfigWithDifferentPredicates();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -400,9 +401,9 @@ TEST(MetricsManagerTest, TestInitialConditions) {
EXPECT_TRUE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
ASSERT_EQ(4u, allMetricProducers.size());
@@ -433,8 +434,9 @@ TEST(MetricsManagerTest, TestGoodConfig) {
StatsdConfig config = buildGoodConfig();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -449,9 +451,9 @@ TEST(MetricsManagerTest, TestGoodConfig) {
EXPECT_TRUE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
ASSERT_EQ(1u, allMetricProducers.size());
@@ -470,8 +472,9 @@ TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
StatsdConfig config = buildDimensionMetricsWithMultiTags();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -486,9 +489,9 @@ TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -501,8 +504,9 @@ TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
StatsdConfig config = buildCircleMatchers();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -517,9 +521,9 @@ TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -532,8 +536,9 @@ TEST(MetricsManagerTest, TestMissingMatchers) {
StatsdConfig config = buildMissingMatchers();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -547,9 +552,9 @@ TEST(MetricsManagerTest, TestMissingMatchers) {
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -562,8 +567,9 @@ TEST(MetricsManagerTest, TestMissingPredicate) {
StatsdConfig config = buildMissingPredicate();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -577,9 +583,9 @@ TEST(MetricsManagerTest, TestMissingPredicate) {
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -592,8 +598,9 @@ TEST(MetricsManagerTest, TestCirclePredicateDependency) {
StatsdConfig config = buildCirclePredicates();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -608,9 +615,9 @@ TEST(MetricsManagerTest, TestCirclePredicateDependency) {
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -623,8 +630,9 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
StatsdConfig config = buildAlertWithUnknownMetric();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -639,9 +647,9 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -649,6 +657,7 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerInvalidMatcher) {
sp<UidMap> uidMap = new UidMap();
AtomMatcher matcher;
+ // Matcher has no contents_case (simple/combination), so it is invalid.
matcher.set_id(21);
EXPECT_EQ(createAtomMatchingTracker(matcher, 0, uidMap), nullptr);
}
@@ -699,6 +708,65 @@ TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerCombination) {
ASSERT_EQ(atomIds.size(), 0);
}
+TEST(MetricsManagerTest, TestCreateConditionTrackerInvalid) {
+ const ConfigKey key(123, 456);
+ // Predicate has no contents_case (simple/combination), so it is invalid.
+ Predicate predicate;
+ predicate.set_id(21);
+ unordered_map<int64_t, int> atomTrackerMap;
+ EXPECT_EQ(createConditionTracker(key, predicate, 0, atomTrackerMap), nullptr);
+}
+
+TEST(MetricsManagerTest, TestCreateConditionTrackerSimple) {
+ int index = 1;
+ int64_t id = 987;
+ const ConfigKey key(123, 456);
+
+ int startMatcherIndex = 2, stopMatcherIndex = 0, stopAllMatcherIndex = 1;
+ int64_t startMatcherId = 246, stopMatcherId = 153, stopAllMatcherId = 975;
+
+ Predicate predicate;
+ predicate.set_id(id);
+ SimplePredicate* simplePredicate = predicate.mutable_simple_predicate();
+ simplePredicate->set_start(startMatcherId);
+ simplePredicate->set_stop(stopMatcherId);
+ simplePredicate->set_stop_all(stopAllMatcherId);
+
+ unordered_map<int64_t, int> atomTrackerMap;
+ atomTrackerMap[startMatcherId] = startMatcherIndex;
+ atomTrackerMap[stopMatcherId] = stopMatcherIndex;
+ atomTrackerMap[stopAllMatcherId] = stopAllMatcherIndex;
+
+ sp<ConditionTracker> tracker = createConditionTracker(key, predicate, index, atomTrackerMap);
+ EXPECT_EQ(tracker->getConditionId(), id);
+ EXPECT_EQ(tracker->isSliced(), false);
+ EXPECT_TRUE(tracker->IsSimpleCondition());
+ const set<int>& interestedMatchers = tracker->getAtomMatchingTrackerIndex();
+ ASSERT_EQ(interestedMatchers.size(), 3);
+ ASSERT_EQ(interestedMatchers.count(startMatcherIndex), 1);
+ ASSERT_EQ(interestedMatchers.count(stopMatcherIndex), 1);
+ ASSERT_EQ(interestedMatchers.count(stopAllMatcherIndex), 1);
+}
+
+TEST(MetricsManagerTest, TestCreateConditionTrackerCombination) {
+ int index = 1;
+ int64_t id = 987;
+ const ConfigKey key(123, 456);
+
+ Predicate predicate;
+ predicate.set_id(id);
+ Predicate_Combination* combinationPredicate = predicate.mutable_combination();
+ combinationPredicate->set_operation(LogicalOperation::AND);
+ combinationPredicate->add_predicate(888);
+ combinationPredicate->add_predicate(777);
+
+ // Combination conditions must be initialized to set most state.
+ unordered_map<int64_t, int> atomTrackerMap;
+ sp<ConditionTracker> tracker = createConditionTracker(key, predicate, index, atomTrackerMap);
+ EXPECT_EQ(tracker->getConditionId(), id);
+ EXPECT_FALSE(tracker->IsSimpleCondition());
+}
+
} // namespace statsd
} // namespace os
} // namespace android