From 5088e72c530802afd8a8dcb3cc0023e79670c90e Mon Sep 17 00:00:00 2001 From: tsaichristine Date: Thu, 28 May 2020 10:06:41 -0700 Subject: [PATCH] Populate initial base info with unknown state values Set the current state key to a HashableDimensionKey with -1 (kStateUnknown) for each sliced state atom. Previously, the current state key was being set to the DEFAULT_DIMENSION_KEY which is an empty HashableDimensionKey. Bug: 155487198 Test: make statsd_test && adb sync data && adb shell data/nativetest/statsd_test/statsd_test Change-Id: Icaa187ecae599407695d86eec6104d210aa98714 --- cmds/statsd/src/metrics/MetricProducer.cpp | 11 + cmds/statsd/src/metrics/MetricProducer.h | 4 + .../src/metrics/ValueMetricProducer.cpp | 10 +- .../metrics/ValueMetricProducer_test.cpp | 371 ++++++++++++++---- 4 files changed, 312 insertions(+), 84 deletions(-) diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index 2518d85eb6a1d..bb4f03e81e2e2 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -293,6 +293,17 @@ void MetricProducer::mapStateValue(const int32_t atomId, FieldValue* value) { } } +HashableDimensionKey MetricProducer::getUnknownStateKey() { + HashableDimensionKey stateKey; + for (auto atom : mSlicedStateAtoms) { + FieldValue fieldValue; + fieldValue.mField.setTag(atom); + fieldValue.mValue.setInt(StateTracker::kStateUnknown); + stateKey.addValue(fieldValue); + } + return stateKey; +} + DropEvent MetricProducer::buildDropEvent(const int64_t dropTimeNs, const BucketDropReason reason) { DropEvent event; event.reason = reason; diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h index e86fdf06e8363..fe84739ebad9a 100644 --- a/cmds/statsd/src/metrics/MetricProducer.h +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -384,6 +384,10 @@ protected: // If no state map exists, keep the original state value. void mapStateValue(const int32_t atomId, FieldValue* value); + // Returns a HashableDimensionKey with unknown state value for each state + // atom. + HashableDimensionKey getUnknownStateKey(); + DropEvent buildDropEvent(const int64_t dropTimeNs, const BucketDropReason reason); // Returns true if the number of drop events in the current bucket has diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index f03ce4550bc45..130e6f2f18b3f 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -767,22 +767,24 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked( bool shouldSkipForPulledMetric = mIsPulled && !mUseDiff && mCondition != ConditionState::kTrue; if (shouldSkipForPushMetric || shouldSkipForPulledMetric) { - VLOG("ValueMetric skip event because condition is false"); + VLOG("ValueMetric skip event because condition is false and we are not using diff (for " + "pulled metric)"); return; } if (hitGuardRailLocked(eventKey)) { return; } + vector& baseInfos = mCurrentBaseInfo[whatKey]; if (baseInfos.size() < mFieldMatchers.size()) { VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size()); baseInfos.resize(mFieldMatchers.size()); } - for (auto baseInfo : baseInfos) { + for (BaseInfo& baseInfo : baseInfos) { if (!baseInfo.hasCurrentState) { - baseInfo.currentState = DEFAULT_DIMENSION_KEY; + baseInfo.currentState = getUnknownStateKey(); baseInfo.hasCurrentState = true; } } @@ -1033,7 +1035,7 @@ void ValueMetricProducer::initCurrentSlicedBucket(int64_t nextBucketStartTimeNs) } else { it++; } - // TODO: remove mCurrentBaseInfo entries when obsolete + // TODO(b/157655103): remove mCurrentBaseInfo entries when obsolete } mCurrentBucketIsInvalid = false; diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index 474aa22348377..5f38300944d42 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -3765,6 +3765,7 @@ TEST(ValueMetricProducerTest, TestSlicedState) { sp valueProducer = ValueMetricProducerTestHelper::createValueProducerWithState( pullerManager, metric, {util::SCREEN_STATE_CHANGED}, {}); + EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size()); // Set up StateManager and check that StateTrackers are initialized. StateManager::getInstance().clear(); @@ -3777,10 +3778,18 @@ TEST(ValueMetricProducerTest, TestSlicedState) { // Base for dimension key {} auto it = valueProducer->mCurrentSlicedBucket.begin(); auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(3, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for dimension, state key {{}, kStateUnknown} - EXPECT_EQ(false, it->second[0].hasValue); + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Bucket status after screen state change kStateUnknown->ON. auto screenEvent = CreateScreenStateChangedEvent( @@ -3790,10 +3799,18 @@ TEST(ValueMetricProducerTest, TestSlicedState) { // Base for dimension key {} it = valueProducer->mCurrentSlicedBucket.begin(); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(5, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for dimension, state key {{}, kStateUnknown} - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(2, it->second[0].value.long_value); // Bucket status after screen state change ON->OFF. @@ -3804,16 +3821,25 @@ TEST(ValueMetricProducerTest, TestSlicedState) { // Base for dimension key {} it = valueProducer->mCurrentSlicedBucket.begin(); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(9, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for dimension, state key {{}, ON} + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(4, it->second[0].value.long_value); // Value for dimension, state key {{}, kStateUnknown} it++; - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(2, it->second[0].value.long_value); // Bucket status after screen state change OFF->ON. @@ -3824,22 +3850,34 @@ TEST(ValueMetricProducerTest, TestSlicedState) { // Base for dimension key {} it = valueProducer->mCurrentSlicedBucket.begin(); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(21, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for dimension, state key {{}, OFF} + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(12, it->second[0].value.long_value); // Value for dimension, state key {{}, ON} it++; + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(4, it->second[0].value.long_value); // Value for dimension, state key {{}, kStateUnknown} it++; - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(2, it->second[0].value.long_value); // Start dump report and check output. @@ -3855,6 +3893,9 @@ TEST(ValueMetricProducerTest, TestSlicedState) { auto data = report.value_metrics().data(0); ASSERT_EQ(1, data.bucket_info_size()); EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long()); + EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id()); + EXPECT_TRUE(data.slice_by_state(0).has_value()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value()); data = report.value_metrics().data(1); ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size()); @@ -3948,10 +3989,18 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) { // Base for dimension key {} auto it = valueProducer->mCurrentSlicedBucket.begin(); auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(3, itBase->second[0].base.long_value); - // Value for dimension, state key {{}, {}} - EXPECT_EQ(false, it->second[0].hasValue); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + itBase->second[0].currentState.getValues()[0].mValue.int_value); + // Value for dimension, state key {{}, {kStateUnknown}} + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Bucket status after screen state change kStateUnknown->ON. auto screenEvent = CreateScreenStateChangedEvent( @@ -3961,10 +4010,18 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) { // Base for dimension key {} it = valueProducer->mCurrentSlicedBucket.begin(); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(5, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(screenOnGroup.group_id(), + itBase->second[0].currentState.getValues()[0].mValue.long_value); // Value for dimension, state key {{}, kStateUnknown} - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(2, it->second[0].value.long_value); // Bucket status after screen state change ON->VR. @@ -3976,10 +4033,18 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) { // Base for dimension key {} it = valueProducer->mCurrentSlicedBucket.begin(); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(5, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(screenOnGroup.group_id(), + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for dimension, state key {{}, kStateUnknown} - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(2, it->second[0].value.long_value); // Bucket status after screen state change VR->ON. @@ -3987,14 +4052,22 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) { screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 12, android::view::DisplayStateEnum::DISPLAY_STATE_ON); StateManager::getInstance().onLogEvent(*screenEvent); - EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); + ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); // Base for dimension key {} it = valueProducer->mCurrentSlicedBucket.begin(); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(5, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(screenOnGroup.group_id(), + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for dimension, state key {{}, kStateUnknown} - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(2, it->second[0].value.long_value); // Bucket status after screen state change VR->OFF. @@ -4005,16 +4078,26 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) { // Base for dimension key {} it = valueProducer->mCurrentSlicedBucket.begin(); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(21, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(screenOffGroup.group_id(), + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for dimension, state key {{}, ON GROUP} + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); EXPECT_EQ(screenOnGroup.group_id(), it->first.getStateValuesKey().getValues()[0].mValue.long_value); - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(16, it->second[0].value.long_value); // Value for dimension, state key {{}, kStateUnknown} it++; - EXPECT_EQ(true, it->second[0].hasValue); + EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(2, it->second[0].value.long_value); // Start dump report and check output. @@ -4030,6 +4113,9 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) { auto data = report.value_metrics().data(0); ASSERT_EQ(1, data.bucket_info_size()); EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long()); + EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id()); + EXPECT_TRUE(data.slice_by_state(0).has_value()); + EXPECT_EQ(-1 /*StateTracker::kStateUnknown*/, data.slice_by_state(0).value()); data = report.value_metrics().data(1); ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size()); @@ -4154,23 +4240,36 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size()); // Base for dimension key {uid 1}. auto it = valueProducer->mCurrentSlicedBucket.begin(); - EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(3, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for dimension, state key {{uid 1}, kStateUnknown} - // TODO(tsaichristine): test equality of state values key - // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(false, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Base for dimension key {uid 2} it++; - EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(7, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for dimension, state key {{uid 2}, kStateUnknown} - // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(false, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Bucket status after uid 1 process state change kStateUnknown -> Foreground. auto uidProcessEvent = CreateUidProcessStateChangedEvent( @@ -4179,25 +4278,37 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size()); // Base for dimension key {uid 1}. it = valueProducer->mCurrentSlicedBucket.begin(); - EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(6, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for key {uid 1, kStateUnknown}. - // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(true, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(3, it->second[0].value.long_value); // Base for dimension key {uid 2} it++; - EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(7, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for key {uid 2, kStateUnknown} - EXPECT_EQ(false, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Bucket status after uid 2 process state change kStateUnknown -> Background. uidProcessEvent = CreateUidProcessStateChangedEvent( @@ -4206,23 +4317,36 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size()); // Base for dimension key {uid 1}. it = valueProducer->mCurrentSlicedBucket.begin(); - EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(6, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for key {uid 1, kStateUnknown}. - EXPECT_EQ(true, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(3, it->second[0].value.long_value); // Base for dimension key {uid 2} it++; - EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(9, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for key {uid 2, kStateUnknown} - // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(true, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(2, it->second[0].value.long_value); // Pull at end of first bucket. @@ -4240,33 +4364,54 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { it = valueProducer->mCurrentSlicedBucket.begin(); EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(15, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for key {uid 2, BACKGROUND}. + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); - EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(false, it->second[0].hasValue); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Base for dimension key {uid 1} it++; - EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(10, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for key {uid 1, kStateUnknown} - ASSERT_EQ(0, it->first.getStateValuesKey().getValues().size()); - // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(false, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* kStateTracker::kUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Value for key {uid 1, FOREGROUND} it++; + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); - EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(false, it->second[0].hasValue); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Value for key {uid 2, kStateUnknown} it++; - EXPECT_EQ(false, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* kStateTracker::kUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Bucket status after uid 1 process state change from Foreground -> Background. uidProcessEvent = CreateUidProcessStateChangedEvent( @@ -4278,29 +4423,53 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size()); // Base for dimension key {uid 2}. it = valueProducer->mCurrentSlicedBucket.begin(); - EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(15, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for key {uid 2, BACKGROUND}. - EXPECT_EQ(false, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Base for dimension key {uid 1} it++; - EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(13, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, + itBase->second[0].currentState.getValues()[0].mValue.int_value); // Value for key {uid 1, kStateUnknown} - EXPECT_EQ(false, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Value for key {uid 1, FOREGROUND} it++; + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); - EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(true, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(3, it->second[0].value.long_value); // Value for key {uid 2, kStateUnknown} it++; - EXPECT_EQ(false, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Bucket status after uid 1 process state change Background->Foreground. uidProcessEvent = CreateUidProcessStateChangedEvent( @@ -4311,30 +4480,66 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size()); // Base for dimension key {uid 2} it = valueProducer->mCurrentSlicedBucket.begin(); - EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); - EXPECT_EQ(true, itBase->second[0].hasBase); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(15, itBase->second[0].base.long_value); - EXPECT_EQ(false, it->second[0].hasValue); - - it++; - EXPECT_EQ(false, it->second[0].hasValue); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, + itBase->second[0].currentState.getValues()[0].mValue.int_value); + // Value for key {uid 2, BACKGROUND} + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); // Base for dimension key {uid 1} it++; - EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat()); + EXPECT_TRUE(itBase->second[0].hasBase); EXPECT_EQ(17, itBase->second[0].base.long_value); + EXPECT_TRUE(itBase->second[0].hasCurrentState); + ASSERT_EQ(1, itBase->second[0].currentState.getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, + itBase->second[0].currentState.getValues()[0].mValue.int_value); + // Value for key {uid 1, kStateUnknown} + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_FALSE(it->second[0].hasValue); + // Value for key {uid 1, BACKGROUND} - EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(true, it->second[0].hasValue); + it++; + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(4, it->second[0].value.long_value); + // Value for key {uid 1, FOREGROUND} it++; - EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value); - EXPECT_EQ(true, it->second[0].hasValue); + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + EXPECT_TRUE(it->second[0].hasValue); EXPECT_EQ(3, it->second[0].value.long_value); + // Value for key {uid 2, kStateUnknown} + it++; + ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size()); + EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); + ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size()); + EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, + it->first.getStateValuesKey().getValues()[0].mValue.int_value); + // Start dump report and check output. ProtoOutputStream output; std::set strSet; @@ -4356,6 +4561,9 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { data = report.value_metrics().data(1); ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size()); EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long()); + EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id()); + EXPECT_TRUE(data.slice_by_state(0).has_value()); + EXPECT_EQ(-1 /*StateTracker::kStateUnknown*/, data.slice_by_state(0).value()); data = report.value_metrics().data(2); EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id()); @@ -4369,6 +4577,9 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) { data = report.value_metrics().data(3); ASSERT_EQ(1, report.value_metrics().data(3).bucket_info_size()); EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long()); + EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id()); + EXPECT_TRUE(data.slice_by_state(0).has_value()); + EXPECT_EQ(-1 /*StateTracker::kStateUnknown*/, data.slice_by_state(0).value()); data = report.value_metrics().data(4); EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());