summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/statsd/src/external/StatsCallbackPuller.cpp6
-rw-r--r--cmds/statsd/src/logd/LogEvent.cpp27
-rw-r--r--cmds/statsd/src/logd/LogEvent.h49
-rwxr-xr-xcmds/statsd/src/socket/StatsSocketListener.cpp5
-rw-r--r--cmds/statsd/tests/LogEvent_test.cpp25
-rw-r--r--cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp296
-rw-r--r--cmds/statsd/tests/external/StatsCallbackPuller_test.cpp1
-rw-r--r--cmds/statsd/tests/statsd_test_util.cpp1
8 files changed, 210 insertions, 200 deletions
diff --git a/cmds/statsd/src/external/StatsCallbackPuller.cpp b/cmds/statsd/src/external/StatsCallbackPuller.cpp
index 0edf40b69087..933f48d1714b 100644
--- a/cmds/statsd/src/external/StatsCallbackPuller.cpp
+++ b/cmds/statsd/src/external/StatsCallbackPuller.cpp
@@ -66,10 +66,8 @@ bool StatsCallbackPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
{
lock_guard<mutex> lk(*cv_mutex);
for (const StatsEventParcel& parcel: output) {
- uint8_t* buf = reinterpret_cast<uint8_t*>(
- const_cast<int8_t*>(parcel.buffer.data()));
- shared_ptr<LogEvent> event = make_shared<LogEvent>(
- buf, parcel.buffer.size(), /*uid=*/-1, /*pid=*/-1);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(/*uid=*/-1, /*pid=*/-1);
+ event->parseBuffer((uint8_t*)parcel.buffer.data(), parcel.buffer.size());
sharedData->push_back(event);
}
*pullSuccess = success;
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 3e46d131a813..974e203cd612 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -65,18 +65,6 @@ using std::vector;
#define ATTRIBUTION_CHAIN_TYPE 0x09
#define ERROR_TYPE 0x0F
-// Msg is expected to begin at the start of the serialized atom -- it should not
-// include the android_log_header_t or the StatsEventTag.
-LogEvent::LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid)
- : mBuf(msg),
- mRemainingLen(len),
- mLogdTimestampNs(time(nullptr)),
- mLogUid(uid),
- mLogPid(pid)
-{
- initNew();
-}
-
LogEvent::LogEvent(const LogEvent& event) {
mTagId = event.mTagId;
mLogUid = event.mLogUid;
@@ -86,6 +74,12 @@ LogEvent::LogEvent(const LogEvent& event) {
mValues = event.mValues;
}
+LogEvent::LogEvent(int32_t uid, int32_t pid)
+ : mLogdTimestampNs(time(nullptr)),
+ mLogUid(uid),
+ mLogPid(pid) {
+}
+
LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) {
mLogdTimestampNs = wallClockTimestampNs;
mElapsedTimestampNs = elapsedTimestampNs;
@@ -189,9 +183,6 @@ LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
}
-LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) : LogEvent(tagId, timestampNs, timestampNs) {
-}
-
LogEvent::LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid) {
mLogdTimestampNs = timestampNs;
mTagId = tagId;
@@ -467,7 +458,10 @@ void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last) {
// This parsing logic is tied to the encoding scheme used in StatsEvent.java and
// stats_event.c
-void LogEvent::initNew() {
+bool LogEvent::parseBuffer(uint8_t* buf, size_t len) {
+ mBuf = buf;
+ mRemainingLen = (uint32_t)len;
+
int32_t pos[] = {1, 1, 1};
bool last[] = {false, false, false};
@@ -529,6 +523,7 @@ void LogEvent::initNew() {
if (mRemainingLen != 0) mValid = false;
mBuf = nullptr;
+ return mValid;
}
uint8_t LogEvent::getTypeId(uint8_t typeInfo) {
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index e167e6721d01..3940aa8e1243 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -20,7 +20,6 @@
#include <android/util/ProtoOutputStream.h>
#include <private/android_logger.h>
-#include <stats_event.h>
#include <string>
#include <vector>
@@ -61,14 +60,32 @@ struct InstallTrainInfo {
};
/**
- * Wrapper for the log_msg structure.
+ * This class decodes the structured, serialized encoding of an atom into a
+ * vector of FieldValues.
*/
class LogEvent {
public:
/**
- * Read a LogEvent from the socket
+ * \param uid user id of the logging caller
+ * \param pid process id of the logging caller
*/
- explicit LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid);
+ explicit LogEvent(int32_t uid, int32_t pid);
+
+ /**
+ * Parses the atomId, timestamp, and vector of values from a buffer
+ * containing the StatsEvent/AStatsEvent encoding of an atom.
+ *
+ * \param buf a buffer that begins at the start of the serialized atom (it
+ * should not include the android_log_header_t or the StatsEventTag)
+ * \param len size of the buffer
+ *
+ * \return success of the initialization
+ */
+ bool parseBuffer(uint8_t* buf, size_t len);
+
+ // TODO(b/149590301): delete unused functions below once LogEvent uses the
+ // new socket schema within test code. Really we would like the only entry
+ // points into LogEvent to be the above constructor and parseBuffer functions.
/**
* Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
@@ -76,9 +93,6 @@ public:
explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs);
// For testing. The timestamp is used as both elapsed real time and logd timestamp.
- explicit LogEvent(int32_t tagId, int64_t timestampNs);
-
- // For testing. The timestamp is used as both elapsed real time and logd timestamp.
explicit LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid);
/**
@@ -192,10 +206,6 @@ public:
return &mValues;
}
- bool isValid() {
- return mValid;
- }
-
inline LogEvent makeCopy() {
return LogEvent(*this);
}
@@ -222,12 +232,6 @@ private:
*/
LogEvent(const LogEvent&);
-
- /**
- * Parsing function for new encoding scheme.
- */
- void initNew();
-
void parseInt32(int32_t* pos, int32_t depth, bool* last);
void parseInt64(int32_t* pos, int32_t depth, bool* last);
void parseString(int32_t* pos, int32_t depth, bool* last);
@@ -238,13 +242,14 @@ private:
void parseAttributionChain(int32_t* pos, int32_t depth, bool* last);
/**
- * mBuf is a pointer to the current location in the buffer being parsed.
- * Because the buffer lives on the StatsSocketListener stack, this pointer
- * is only valid during the LogEvent constructor. It will be set to null at
- * the end of initNew.
+ * The below three variables are only valid during the execution of
+ * parseBuffer. There are no guarantees about the state of these variables
+ * before/after.
+ *
+ * TODO (b/150312423): These shouldn't be member variables. We should pass
+ * them around as parameters.
*/
uint8_t* mBuf;
-
uint32_t mRemainingLen; // number of valid bytes left in the buffer being parsed
bool mValid = true; // stores whether the event we received from the socket is valid
diff --git a/cmds/statsd/src/socket/StatsSocketListener.cpp b/cmds/statsd/src/socket/StatsSocketListener.cpp
index 8f0f480cb862..b877cc9c352f 100755
--- a/cmds/statsd/src/socket/StatsSocketListener.cpp
+++ b/cmds/statsd/src/socket/StatsSocketListener.cpp
@@ -126,7 +126,10 @@ bool StatsSocketListener::onDataAvailable(SocketClient* cli) {
uint32_t pid = cred->pid;
int64_t oldestTimestamp;
- if (!mQueue->push(std::make_unique<LogEvent>(msg, len, uid, pid), &oldestTimestamp)) {
+ std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(uid, pid);
+ logEvent->parseBuffer(msg, len);
+
+ if (!mQueue->push(std::move(logEvent), &oldestTimestamp)) {
StatsdStats::getInstance().noteEventQueueOverflow(oldestTimestamp);
}
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index 7542faf25123..7458cbf9e9a1 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -54,8 +54,9 @@ TEST(LogEventTest, TestPrimitiveParsing) {
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(event, &size);
- LogEvent logEvent(buf, size, /*uid=*/ 1000, /*pid=*/ 1001);
- EXPECT_TRUE(logEvent.isValid());
+ LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+
EXPECT_EQ(100, logEvent.GetTagId());
EXPECT_EQ(1000, logEvent.GetUid());
EXPECT_EQ(1001, logEvent.GetPid());
@@ -102,8 +103,9 @@ TEST(LogEventTest, TestStringAndByteArrayParsing) {
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(event, &size);
- LogEvent logEvent(buf, size, /*uid=*/ 1000, /*pid=*/ 1001);
- EXPECT_TRUE(logEvent.isValid());
+ LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+
EXPECT_EQ(100, logEvent.GetTagId());
EXPECT_EQ(1000, logEvent.GetUid());
EXPECT_EQ(1001, logEvent.GetPid());
@@ -137,8 +139,9 @@ TEST(LogEventTest, TestEmptyString) {
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(event, &size);
- LogEvent logEvent(buf, size, /*uid=*/ 1000, /*pid=*/ 1001);
- EXPECT_TRUE(logEvent.isValid());
+ LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+
EXPECT_EQ(100, logEvent.GetTagId());
EXPECT_EQ(1000, logEvent.GetUid());
EXPECT_EQ(1001, logEvent.GetPid());
@@ -165,8 +168,9 @@ TEST(LogEventTest, TestByteArrayWithNullCharacter) {
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(event, &size);
- LogEvent logEvent(buf, size, /*uid=*/ 1000, /*pid=*/ 1001);
- EXPECT_TRUE(logEvent.isValid());
+ LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+
EXPECT_EQ(100, logEvent.GetTagId());
EXPECT_EQ(1000, logEvent.GetUid());
EXPECT_EQ(1001, logEvent.GetPid());
@@ -200,8 +204,9 @@ TEST(LogEventTest, TestAttributionChain) {
size_t size;
uint8_t* buf = AStatsEvent_getBuffer(event, &size);
- LogEvent logEvent(buf, size, /*uid=*/ 1000, /*pid=*/ 1001);
- EXPECT_TRUE(logEvent.isValid());
+ LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+
EXPECT_EQ(100, logEvent.GetTagId());
EXPECT_EQ(1000, logEvent.GetUid());
EXPECT_EQ(1001, logEvent.GetPid());
diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
index 36094b217303..8701e1790a69 100644
--- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
@@ -13,6 +13,7 @@
// limitations under the License.
#include "src/condition/SimpleConditionTracker.h"
+#include "stats_event.h"
#include "tests/statsd_test_util.h"
#include <gmock/gmock.h>
@@ -31,6 +32,8 @@ namespace android {
namespace os {
namespace statsd {
+namespace {
+
const ConfigKey kConfigKey(0, 12345);
const int ATTRIBUTION_NODE_FIELD_ID = 1;
@@ -57,24 +60,33 @@ SimplePredicate getWakeLockHeldCondition(bool countNesting, bool defaultFalse,
return simplePredicate;
}
-void writeAttributionNodesToEvent(LogEvent* event, const std::vector<int> &uids) {
- std::vector<AttributionNodeInternal> nodes;
- for (size_t i = 0; i < uids.size(); ++i) {
- AttributionNodeInternal node;
- node.set_uid(uids[i]);
- nodes.push_back(node);
+void makeWakeLockEvent(LogEvent* logEvent, uint32_t atomId, uint64_t timestamp,
+ const vector<int>& uids, const string& wl, int acquire) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, atomId);
+ AStatsEvent_overwriteTimestamp(statsEvent, timestamp);
+
+ vector<std::string> tags(uids.size()); // vector of empty strings
+ vector<const char*> cTags(uids.size());
+ for (int i = 0; i < cTags.size(); i++) {
+ cTags[i] = tags[i].c_str();
}
- event->write(nodes); // attribution chain.
+ AStatsEvent_writeAttributionChain(statsEvent, reinterpret_cast<const uint32_t*>(uids.data()),
+ cTags.data(), uids.size());
+
+ AStatsEvent_writeString(statsEvent, wl.c_str());
+ AStatsEvent_writeInt32(statsEvent, acquire);
+ AStatsEvent_build(statsEvent);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ logEvent->parseBuffer(buf, size);
+
+ AStatsEvent_release(statsEvent);
}
-// TODO(b/149590301): Update this helper to use new socket schema.
-//void makeWakeLockEvent(
-// LogEvent* event, const std::vector<int> &uids, const string& wl, int acquire) {
-// writeAttributionNodesToEvent(event, uids);
-// event->write(wl);
-// event->write(acquire);
-// event->init();
-//}
+} // anonymous namespace
+
std::map<int64_t, HashableDimensionKey> getWakeLockQueryKey(
const Position position,
@@ -265,138 +277,128 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) {
EXPECT_TRUE(changedCache[0]);
}
-// TODO(b/149590301): Update these tests to use new socket schema.
-//TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
-// std::vector<sp<ConditionTracker>> allConditions;
-// for (Position position :
-// { Position::FIRST, Position::LAST}) {
-//
-// SimplePredicate simplePredicate = getWakeLockHeldCondition(
-// true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
-// position);
-// string conditionName = "WL_HELD_BY_UID2";
-//
-// unordered_map<int64_t, int> trackerNameIndexMap;
-// trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
-// trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
-// trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
-//
-// SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
-// 0 /*condition tracker index*/, simplePredicate,
-// trackerNameIndexMap);
-//
-// std::vector<int> uids = {111, 222, 333};
-//
-// LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
-// makeWakeLockEvent(&event, uids, "wl1", 1);
-//
-// // one matched start
-// vector<MatchingState> matcherState;
-// matcherState.push_back(MatchingState::kMatched);
-// matcherState.push_back(MatchingState::kNotMatched);
-// matcherState.push_back(MatchingState::kNotMatched);
-// vector<sp<ConditionTracker>> allPredicates;
-// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
-// vector<bool> changedCache(1, false);
-//
-// conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
-// changedCache);
-//
-// if (position == Position::FIRST ||
-// position == Position::LAST) {
-// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
-// } else {
-// EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
-// }
-// EXPECT_TRUE(changedCache[0]);
-// if (position == Position::FIRST ||
-// position == Position::LAST) {
-// EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
-// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-// } else {
-// EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), uids.size());
-// }
-//
-// // Now test query
-// const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
-// conditionCache[0] = ConditionState::kNotEvaluated;
-//
-// conditionTracker.isConditionMet(queryKey, allPredicates,
-// false,
-// conditionCache);
-// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
-//
-// // another wake lock acquired by this uid
-// LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
-// makeWakeLockEvent(&event2, uids, "wl2", 1);
-// matcherState.clear();
-// matcherState.push_back(MatchingState::kMatched);
-// matcherState.push_back(MatchingState::kNotMatched);
-// conditionCache[0] = ConditionState::kNotEvaluated;
-// changedCache[0] = false;
-// conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
-// changedCache);
-// EXPECT_FALSE(changedCache[0]);
-// if (position == Position::FIRST ||
-// position == Position::LAST) {
-// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
-// } else {
-// EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
-// }
-// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
-// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-//
-//
-// // wake lock 1 release
-// LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
-// makeWakeLockEvent(&event3, uids, "wl1", 0); // now release it.
-// matcherState.clear();
-// matcherState.push_back(MatchingState::kNotMatched);
-// matcherState.push_back(MatchingState::kMatched);
-// conditionCache[0] = ConditionState::kNotEvaluated;
-// changedCache[0] = false;
-// conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
-// changedCache);
-// // nothing changes, because wake lock 2 is still held for this uid
-// EXPECT_FALSE(changedCache[0]);
-// if (position == Position::FIRST ||
-// position == Position::LAST) {
-// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
-// } else {
-// EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
-// }
-// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
-// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-//
-// LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
-// makeWakeLockEvent(&event4, uids, "wl2", 0); // now release it.
-// matcherState.clear();
-// matcherState.push_back(MatchingState::kNotMatched);
-// matcherState.push_back(MatchingState::kMatched);
-// conditionCache[0] = ConditionState::kNotEvaluated;
-// changedCache[0] = false;
-// conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
-// changedCache);
-// EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
-// EXPECT_TRUE(changedCache[0]);
-// if (position == Position::FIRST ||
-// position == Position::LAST) {
-// EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
-// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
-// } else {
-// EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), uids.size());
-// }
-//
-// // query again
-// conditionCache[0] = ConditionState::kNotEvaluated;
-// conditionTracker.isConditionMet(queryKey, allPredicates,
-// false,
-// conditionCache);
-// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
-// }
-//
-//}
-//
+TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
+ std::vector<sp<ConditionTracker>> allConditions;
+ for (Position position : {Position::FIRST, Position::LAST}) {
+ SimplePredicate simplePredicate = getWakeLockHeldCondition(
+ true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
+ position);
+ string conditionName = "WL_HELD_BY_UID2";
+
+ unordered_map<int64_t, int> trackerNameIndexMap;
+ trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
+ trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
+ trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
+
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+ 0 /*condition tracker index*/, simplePredicate,
+ trackerNameIndexMap);
+
+ std::vector<int> uids = {111, 222, 333};
+
+ LogEvent event(/*uid=*/-1, /*pid=*/-1);
+ makeWakeLockEvent(&event, /*atomId=*/ 1, /*timestamp=*/ 0, uids, "wl1", /*acquire=*/ 1);
+
+ // one matched start
+ vector<MatchingState> matcherState;
+ matcherState.push_back(MatchingState::kMatched);
+ matcherState.push_back(MatchingState::kNotMatched);
+ matcherState.push_back(MatchingState::kNotMatched);
+ vector<sp<ConditionTracker>> allPredicates;
+ vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
+ vector<bool> changedCache(1, false);
+
+ conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
+ changedCache);
+
+ if (position == Position::FIRST || position == Position::LAST) {
+ EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+ } else {
+ EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+ }
+ EXPECT_TRUE(changedCache[0]);
+ if (position == Position::FIRST || position == Position::LAST) {
+ EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
+ EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+ } else {
+ EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(),
+ uids.size());
+ }
+
+ // Now test query
+ const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
+ conditionCache[0] = ConditionState::kNotEvaluated;
+
+ conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
+ EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
+
+ // another wake lock acquired by this uid
+ LogEvent event2(/*uid=*/-1, /*pid=*/-1);
+ makeWakeLockEvent(&event2, /*atomId=*/ 1, /*timestamp=*/ 0, uids, "wl2", /*acquire=*/ 1);
+ matcherState.clear();
+ matcherState.push_back(MatchingState::kMatched);
+ matcherState.push_back(MatchingState::kNotMatched);
+ conditionCache[0] = ConditionState::kNotEvaluated;
+ changedCache[0] = false;
+ conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
+ changedCache);
+ EXPECT_FALSE(changedCache[0]);
+ if (position == Position::FIRST || position == Position::LAST) {
+ EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+ } else {
+ EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+ }
+ EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+ EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+
+
+ // wake lock 1 release
+ LogEvent event3(/*uid=*/-1, /*pid=*/-1);
+ makeWakeLockEvent(&event3, /*atomId=*/1, /*timestamp=*/0, uids, "wl1", /*acquire=*/0);
+ matcherState.clear();
+ matcherState.push_back(MatchingState::kNotMatched);
+ matcherState.push_back(MatchingState::kMatched);
+ conditionCache[0] = ConditionState::kNotEvaluated;
+ changedCache[0] = false;
+ conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
+ changedCache);
+ // nothing changes, because wake lock 2 is still held for this uid
+ EXPECT_FALSE(changedCache[0]);
+ if (position == Position::FIRST || position == Position::LAST) {
+ EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+ } else {
+ EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+ }
+ EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+ EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+
+ LogEvent event4(/*uid=*/-1, /*pid=*/-1);
+ makeWakeLockEvent(&event, /*atomId=*/1, /*timestamp=*/ 0, uids, "wl2", /*acquire=*/0);
+ matcherState.clear();
+ matcherState.push_back(MatchingState::kNotMatched);
+ matcherState.push_back(MatchingState::kMatched);
+ conditionCache[0] = ConditionState::kNotEvaluated;
+ changedCache[0] = false;
+ conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
+ changedCache);
+ EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+ EXPECT_TRUE(changedCache[0]);
+ if (position == Position::FIRST || position == Position::LAST) {
+ EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
+ EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+ } else {
+ EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(),
+ uids.size());
+ }
+
+ // query again
+ conditionCache[0] = ConditionState::kNotEvaluated;
+ conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
+ EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
+ }
+
+}
+
//TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
// std::vector<sp<ConditionTracker>> allConditions;
//
diff --git a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
index e416b4c0e29b..1ff66218f22c 100644
--- a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
+++ b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
@@ -28,6 +28,7 @@
#include "../metrics/metrics_test_helper.h"
#include "src/stats_log_util.h"
+#include "stats_event.h"
#include "tests/statsd_test_util.h"
#ifdef __ANDROID__
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 2bfce9b07eb5..d416f1395727 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -15,6 +15,7 @@
#include "statsd_test_util.h"
#include <aidl/android/util/StatsEventParcel.h>
+#include "stats_event.h"
using aidl::android::util::StatsEventParcel;
using std::shared_ptr;