1 // Copyright (C) 2017 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/metrics/ValueMetricProducer.h"
16 
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <math.h>
20 #include <stdio.h>
21 
22 #include <vector>
23 
24 #include "metrics_test_helper.h"
25 #include "src/matchers/SimpleAtomMatchingTracker.h"
26 #include "src/metrics/MetricProducer.h"
27 #include "src/stats_log_util.h"
28 #include "tests/statsd_test_util.h"
29 
30 using namespace testing;
31 using android::sp;
32 using std::make_shared;
33 using std::set;
34 using std::shared_ptr;
35 using std::unordered_map;
36 using std::vector;
37 
38 #ifdef __ANDROID__
39 
40 namespace android {
41 namespace os {
42 namespace statsd {
43 
44 namespace {
45 
46 const ConfigKey kConfigKey(0, 12345);
47 const int tagId = 1;
48 const int64_t metricId = 123;
49 const uint64_t protoHash = 0x1234567890;
50 const int logEventMatcherIndex = 0;
51 const int64_t bucketStartTimeNs = 10000000000;
52 const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
53 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
54 const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
55 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
56 const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs;
57 const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
58 double epsilon = 0.001;
59 
assertPastBucketValuesSingleKey(const std::unordered_map<MetricDimensionKey,std::vector<PastValueBucket>> & mPastBuckets,const std::initializer_list<int> & expectedValuesList,const std::initializer_list<int64_t> & expectedDurationNsList,const std::initializer_list<int64_t> & expectedStartTimeNsList,const std::initializer_list<int64_t> & expectedEndTimeNsList)60 static void assertPastBucketValuesSingleKey(
61         const std::unordered_map<MetricDimensionKey, std::vector<PastValueBucket>>& mPastBuckets,
62         const std::initializer_list<int>& expectedValuesList,
63         const std::initializer_list<int64_t>& expectedDurationNsList,
64         const std::initializer_list<int64_t>& expectedStartTimeNsList,
65         const std::initializer_list<int64_t>& expectedEndTimeNsList) {
66     vector<int> expectedValues(expectedValuesList);
67     vector<int64_t> expectedDurationNs(expectedDurationNsList);
68     vector<int64_t> expectedStartTimeNs(expectedStartTimeNsList);
69     vector<int64_t> expectedEndTimeNs(expectedEndTimeNsList);
70 
71     ASSERT_EQ(expectedValues.size(), expectedDurationNs.size());
72     ASSERT_EQ(expectedValues.size(), expectedStartTimeNs.size());
73     ASSERT_EQ(expectedValues.size(), expectedEndTimeNs.size());
74 
75     if (expectedValues.size() == 0) {
76         ASSERT_EQ(0, mPastBuckets.size());
77         return;
78     }
79 
80     ASSERT_EQ(1, mPastBuckets.size());
81     ASSERT_EQ(expectedValues.size(), mPastBuckets.begin()->second.size());
82 
83     const vector<PastValueBucket>& buckets = mPastBuckets.begin()->second;
84     for (int i = 0; i < expectedValues.size(); i++) {
85         EXPECT_EQ(expectedValues[i], buckets[i].values[0].long_value)
86                 << "Values differ at index " << i;
87         EXPECT_EQ(expectedDurationNs[i], buckets[i].mConditionTrueNs)
88                 << "Condition duration value differ at index " << i;
89         EXPECT_EQ(expectedStartTimeNs[i], buckets[i].mBucketStartNs)
90                 << "Start time differs at index " << i;
91         EXPECT_EQ(expectedEndTimeNs[i], buckets[i].mBucketEndNs)
92                 << "End time differs at index " << i;
93     }
94 }
95 
assertConditionTimer(const ConditionTimer & conditionTimer,bool condition,int64_t timerNs,int64_t lastConditionTrueTimestampNs)96 static void assertConditionTimer(const ConditionTimer& conditionTimer, bool condition,
97                                  int64_t timerNs, int64_t lastConditionTrueTimestampNs) {
98     EXPECT_EQ(condition, conditionTimer.mCondition);
99     EXPECT_EQ(timerNs, conditionTimer.mTimerNs);
100     EXPECT_EQ(lastConditionTrueTimestampNs, conditionTimer.mLastConditionChangeTimestampNs);
101 }
102 
103 }  // anonymous namespace
104 
105 class ValueMetricProducerTestHelper {
106 public:
createValueProducerNoConditions(sp<MockStatsPullerManager> & pullerManager,ValueMetric & metric)107     static sp<ValueMetricProducer> createValueProducerNoConditions(
108             sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
109         sp<EventMatcherWizard> eventMatcherWizard =
110                 createEventMatcherWizard(tagId, logEventMatcherIndex);
111         sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
112         EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
113                 .WillOnce(Return());
114         EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
115                 .WillRepeatedly(Return());
116 
117         sp<ValueMetricProducer> valueProducer =
118                 new ValueMetricProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
119                                         wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
120                                         tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
121         valueProducer->prepareFirstBucket();
122         return valueProducer;
123     }
124 
createValueProducerWithCondition(sp<MockStatsPullerManager> & pullerManager,ValueMetric & metric,ConditionState conditionAfterFirstBucketPrepared)125     static sp<ValueMetricProducer> createValueProducerWithCondition(
126             sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
127             ConditionState conditionAfterFirstBucketPrepared) {
128         sp<EventMatcherWizard> eventMatcherWizard =
129                 createEventMatcherWizard(tagId, logEventMatcherIndex);
130         sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
131         EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
132                 .WillOnce(Return());
133         EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
134                 .WillRepeatedly(Return());
135 
136         sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
137                 kConfigKey, metric, 0 /*condition index*/, {ConditionState::kUnknown}, wizard,
138                 protoHash, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
139                 bucketStartTimeNs, pullerManager);
140         valueProducer->prepareFirstBucket();
141         valueProducer->mCondition = conditionAfterFirstBucketPrepared;
142         return valueProducer;
143     }
144 
createValueProducerWithState(sp<MockStatsPullerManager> & pullerManager,ValueMetric & metric,vector<int32_t> slicedStateAtoms,unordered_map<int,unordered_map<int,int64_t>> stateGroupMap)145     static sp<ValueMetricProducer> createValueProducerWithState(
146             sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
147             vector<int32_t> slicedStateAtoms,
148             unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
149         sp<EventMatcherWizard> eventMatcherWizard =
150                 createEventMatcherWizard(tagId, logEventMatcherIndex);
151         sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
152         EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
153                 .WillOnce(Return());
154         EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
155                 .WillRepeatedly(Return());
156 
157         sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
158                 kConfigKey, metric, -1 /* no condition */, {}, wizard, protoHash,
159                 logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
160                 bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms, stateGroupMap);
161         valueProducer->prepareFirstBucket();
162         return valueProducer;
163     }
164 
createValueProducerWithConditionAndState(sp<MockStatsPullerManager> & pullerManager,ValueMetric & metric,vector<int32_t> slicedStateAtoms,unordered_map<int,unordered_map<int,int64_t>> stateGroupMap,ConditionState conditionAfterFirstBucketPrepared)165     static sp<ValueMetricProducer> createValueProducerWithConditionAndState(
166             sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
167             vector<int32_t> slicedStateAtoms,
168             unordered_map<int, unordered_map<int, int64_t>> stateGroupMap,
169             ConditionState conditionAfterFirstBucketPrepared) {
170         sp<EventMatcherWizard> eventMatcherWizard =
171                 createEventMatcherWizard(tagId, logEventMatcherIndex);
172         sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
173         EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
174                 .WillOnce(Return());
175         EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
176                 .WillRepeatedly(Return());
177 
178         sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
179                 kConfigKey, metric, 0 /* condition tracker index */, {ConditionState::kUnknown},
180                 wizard, protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
181                 bucketStartTimeNs, bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms,
182                 stateGroupMap);
183         valueProducer->prepareFirstBucket();
184         valueProducer->mCondition = conditionAfterFirstBucketPrepared;
185         return valueProducer;
186     }
187 
createMetric()188     static ValueMetric createMetric() {
189         ValueMetric metric;
190         metric.set_id(metricId);
191         metric.set_bucket(ONE_MINUTE);
192         metric.mutable_value_field()->set_field(tagId);
193         metric.mutable_value_field()->add_child()->set_field(2);
194         metric.set_max_pull_delay_sec(INT_MAX);
195         return metric;
196     }
197 
createMetricWithCondition()198     static ValueMetric createMetricWithCondition() {
199         ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
200         metric.set_condition(StringToId("SCREEN_ON"));
201         return metric;
202     }
203 
createMetricWithState(string state)204     static ValueMetric createMetricWithState(string state) {
205         ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
206         metric.add_slice_by_state(StringToId(state));
207         return metric;
208     }
209 
createMetricWithConditionAndState(string state)210     static ValueMetric createMetricWithConditionAndState(string state) {
211         ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
212         metric.set_condition(StringToId("SCREEN_ON"));
213         metric.add_slice_by_state(StringToId(state));
214         return metric;
215     }
216 };
217 
218 // Setup for parameterized tests.
219 class ValueMetricProducerTest_PartialBucket : public TestWithParam<BucketSplitEvent> {};
220 
221 INSTANTIATE_TEST_SUITE_P(ValueMetricProducerTest_PartialBucket,
222                          ValueMetricProducerTest_PartialBucket,
223                          testing::Values(APP_UPGRADE, BOOT_COMPLETE));
224 
225 /*
226  * Tests that the first bucket works correctly
227  */
TEST(ValueMetricProducerTest,TestCalcPreviousBucketEndTime)228 TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
229     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
230 
231     int64_t startTimeBase = 11;
232     sp<EventMatcherWizard> eventMatcherWizard =
233             createEventMatcherWizard(tagId, logEventMatcherIndex);
234     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
235     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
236 
237     // statsd started long ago.
238     // The metric starts in the middle of the bucket
239     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
240                                       wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
241                                       -1, startTimeBase, 22, pullerManager);
242     valueProducer.prepareFirstBucket();
243 
244     EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
245     EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
246     EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
247               valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
248     EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
249               valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
250 }
251 
252 /*
253  * Tests that the first bucket works correctly
254  */
TEST(ValueMetricProducerTest,TestFirstBucket)255 TEST(ValueMetricProducerTest, TestFirstBucket) {
256     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
257 
258     sp<EventMatcherWizard> eventMatcherWizard =
259             createEventMatcherWizard(tagId, logEventMatcherIndex);
260     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
261     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
262 
263     // statsd started long ago.
264     // The metric starts in the middle of the bucket
265     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
266                                       wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
267                                       -1, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
268     valueProducer.prepareFirstBucket();
269 
270     EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
271     EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
272     EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
273 }
274 
275 /*
276  * Tests pulled atoms with no conditions
277  */
TEST(ValueMetricProducerTest,TestPulledEventsNoCondition)278 TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
279     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
280     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
281     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
282             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
283                                 vector<std::shared_ptr<LogEvent>>* data) {
284                 data->clear();
285                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
286                 return true;
287             }));
288 
289     sp<ValueMetricProducer> valueProducer =
290             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
291 
292     vector<shared_ptr<LogEvent>> allData;
293     allData.clear();
294     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
295 
296     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
297     // has one slice
298     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
299     ValueMetricProducer::Interval curInterval =
300             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
301     ValueMetricProducer::BaseInfo curBaseInfo =
302             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
303 
304     EXPECT_EQ(true, curBaseInfo.hasBase);
305     EXPECT_EQ(11, curBaseInfo.base.long_value);
306     EXPECT_EQ(false, curInterval.hasValue);
307     EXPECT_EQ(8, curInterval.value.long_value);
308     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
309     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
310     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
311 
312     allData.clear();
313     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
314     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
315     // has one slice
316     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
317     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
318     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
319 
320     EXPECT_EQ(true, curBaseInfo.hasBase);
321     EXPECT_EQ(23, curBaseInfo.base.long_value);
322     EXPECT_EQ(false, curInterval.hasValue);
323     EXPECT_EQ(12, curInterval.value.long_value);
324     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
325     ASSERT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
326     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
327     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
328     EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
329     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
330 
331     allData.clear();
332     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
333     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
334     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
335     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
336     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
337 
338     EXPECT_EQ(true, curBaseInfo.hasBase);
339     EXPECT_EQ(36, curBaseInfo.base.long_value);
340     EXPECT_EQ(false, curInterval.hasValue);
341     EXPECT_EQ(13, curInterval.value.long_value);
342     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
343     ASSERT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
344     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
345     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
346     EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
347     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
348     EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
349     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs);
350 }
351 
TEST_P(ValueMetricProducerTest_PartialBucket,TestPartialBucketCreated)352 TEST_P(ValueMetricProducerTest_PartialBucket, TestPartialBucketCreated) {
353     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
354     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
355     int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2;
356     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
357             // Initialize bucket.
358             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
359                                 vector<std::shared_ptr<LogEvent>>* data) {
360                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
361                 data->clear();
362                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
363                 return true;
364             }))
365             // Partial bucket.
366             .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
367                                                         const int64_t eventTimeNs,
368                                                         vector<std::shared_ptr<LogEvent>>* data) {
369                 EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
370                 data->clear();
371                 data->push_back(
372                         CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs + 8, 5));
373                 return true;
374             }));
375 
376     sp<ValueMetricProducer> valueProducer =
377             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
378 
379     // First bucket ends.
380     vector<shared_ptr<LogEvent>> allData;
381     allData.clear();
382     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 2));
383     valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
384 
385     // Partial buckets created in 2nd bucket.
386     switch (GetParam()) {
387         case APP_UPGRADE:
388             valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
389             break;
390         case BOOT_COMPLETE:
391             valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
392             break;
393     }
394     EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mCurrentBucketStartTimeNs);
395     EXPECT_EQ(1, valueProducer->getCurrentBucketNum());
396 
397     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1, 3},
398                                     {bucketSizeNs, partialBucketSplitTimeNs - bucket2StartTimeNs},
399                                     {bucketStartTimeNs, bucket2StartTimeNs},
400                                     {bucket2StartTimeNs, partialBucketSplitTimeNs});
401 }
402 
403 /*
404  * Tests pulled atoms with filtering
405  */
TEST(ValueMetricProducerTest,TestPulledEventsWithFiltering)406 TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
407     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
408 
409     FieldValueMatcher fvm;
410     fvm.set_field(1);
411     fvm.set_eq_int(3);
412     sp<EventMatcherWizard> eventMatcherWizard =
413             createEventMatcherWizard(tagId, logEventMatcherIndex, {fvm});
414     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
415     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
416     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
417     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
418     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
419             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
420                                 vector<std::shared_ptr<LogEvent>>* data) {
421                 data->clear();
422                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
423                 return true;
424             }));
425 
426     sp<ValueMetricProducer> valueProducer =
427             new ValueMetricProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, wizard,
428                                     protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
429                                     bucketStartTimeNs, bucketStartTimeNs, pullerManager);
430     valueProducer->prepareFirstBucket();
431 
432     vector<shared_ptr<LogEvent>> allData;
433     allData.clear();
434     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 3, 11));
435 
436     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
437     // has one slice
438     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
439     ValueMetricProducer::Interval curInterval =
440             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
441     ValueMetricProducer::BaseInfo curBaseInfo =
442             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
443 
444     EXPECT_EQ(true, curBaseInfo.hasBase);
445     EXPECT_EQ(11, curBaseInfo.base.long_value);
446     EXPECT_EQ(false, curInterval.hasValue);
447     EXPECT_EQ(8, curInterval.value.long_value);
448     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
449     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
450     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
451 
452     allData.clear();
453     allData.push_back(CreateTwoValueLogEvent(tagId, bucket3StartTimeNs + 1, 4, 23));
454     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
455     // No new data seen, so data has been cleared.
456     ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
457 
458     EXPECT_EQ(true, curBaseInfo.hasBase);
459     EXPECT_EQ(11, curBaseInfo.base.long_value);
460     EXPECT_EQ(false, curInterval.hasValue);
461     EXPECT_EQ(8, curInterval.value.long_value);
462     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
463     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
464     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
465 
466     allData.clear();
467     allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 3, 36));
468     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
469     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
470     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
471     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
472 
473     // the base was reset
474     EXPECT_EQ(true, curBaseInfo.hasBase);
475     EXPECT_EQ(36, curBaseInfo.base.long_value);
476     EXPECT_EQ(false, curInterval.hasValue);
477     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
478     ASSERT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
479     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
480     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
481 }
482 
483 /*
484  * Tests pulled atoms with no conditions and take absolute value after reset
485  */
TEST(ValueMetricProducerTest,TestPulledEventsTakeAbsoluteValueOnReset)486 TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
487     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
488     metric.set_use_absolute_value_on_reset(true);
489 
490     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
491     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
492             .WillOnce(Return(true));
493     sp<ValueMetricProducer> valueProducer =
494             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
495 
496     vector<shared_ptr<LogEvent>> allData;
497     allData.clear();
498     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
499 
500     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
501     // has one slice
502     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
503     ValueMetricProducer::Interval curInterval =
504             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
505     ValueMetricProducer::BaseInfo curBaseInfo =
506             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
507 
508     EXPECT_EQ(true, curBaseInfo.hasBase);
509     EXPECT_EQ(11, curBaseInfo.base.long_value);
510     EXPECT_EQ(false, curInterval.hasValue);
511     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
512 
513     allData.clear();
514     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
515     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
516     // has one slice
517     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
518     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
519     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
520     EXPECT_EQ(true, curBaseInfo.hasBase);
521     EXPECT_EQ(10, curBaseInfo.base.long_value);
522     EXPECT_EQ(false, curInterval.hasValue);
523     EXPECT_EQ(10, curInterval.value.long_value);
524     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
525     EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
526     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
527 
528     allData.clear();
529     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
530     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
531     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
532     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
533     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
534     EXPECT_EQ(true, curBaseInfo.hasBase);
535     EXPECT_EQ(36, curBaseInfo.base.long_value);
536     EXPECT_EQ(false, curInterval.hasValue);
537     EXPECT_EQ(26, curInterval.value.long_value);
538     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
539     ASSERT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
540     EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
541     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
542     EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
543     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
544 }
545 
546 /*
547  * Tests pulled atoms with no conditions and take zero value after reset
548  */
TEST(ValueMetricProducerTest,TestPulledEventsTakeZeroOnReset)549 TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
550     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
551     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
552     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
553             .WillOnce(Return(false));
554     sp<ValueMetricProducer> valueProducer =
555             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
556 
557     vector<shared_ptr<LogEvent>> allData;
558     allData.clear();
559     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
560 
561     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
562     // has one slice
563     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
564     ValueMetricProducer::Interval curInterval =
565             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
566     ValueMetricProducer::BaseInfo curBaseInfo =
567             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
568 
569     EXPECT_EQ(true, curBaseInfo.hasBase);
570     EXPECT_EQ(11, curBaseInfo.base.long_value);
571     EXPECT_EQ(false, curInterval.hasValue);
572     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
573 
574     allData.clear();
575     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
576     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
577     // has one slice
578     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
579     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
580     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
581     EXPECT_EQ(true, curBaseInfo.hasBase);
582     EXPECT_EQ(10, curBaseInfo.base.long_value);
583     EXPECT_EQ(false, curInterval.hasValue);
584     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
585 
586     allData.clear();
587     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
588     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
589     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
590     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
591     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
592     EXPECT_EQ(true, curBaseInfo.hasBase);
593     EXPECT_EQ(36, curBaseInfo.base.long_value);
594     EXPECT_EQ(false, curInterval.hasValue);
595     EXPECT_EQ(26, curInterval.value.long_value);
596     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
597     EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
598     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
599 }
600 
601 /*
602  * Test pulled event with non sliced condition.
603  */
TEST(ValueMetricProducerTest,TestEventsWithNonSlicedCondition)604 TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
605     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
606 
607     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
608 
609     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
610             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
611                                 vector<std::shared_ptr<LogEvent>>* data) {
612                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);  // First condition change.
613                 data->clear();
614                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
615                 return true;
616             }))
617             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
618                                 vector<std::shared_ptr<LogEvent>>* data) {
619                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1);  // Second condition change.
620                 data->clear();
621                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 130));
622                 return true;
623             }))
624             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
625                                 vector<std::shared_ptr<LogEvent>>* data) {
626                 EXPECT_EQ(eventTimeNs, bucket3StartTimeNs + 1);  // Third condition change.
627                 data->clear();
628                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 180));
629                 return true;
630             }));
631 
632     sp<ValueMetricProducer> valueProducer =
633             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
634                                                                             ConditionState::kFalse);
635 
636     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
637 
638     // has one slice
639     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
640     ValueMetricProducer::Interval curInterval =
641             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
642     ValueMetricProducer::BaseInfo curBaseInfo =
643             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
644     // startUpdated:false sum:0 start:100
645     EXPECT_EQ(true, curBaseInfo.hasBase);
646     EXPECT_EQ(100, curBaseInfo.base.long_value);
647     EXPECT_EQ(false, curInterval.hasValue);
648     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
649 
650     vector<shared_ptr<LogEvent>> allData;
651     allData.clear();
652     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
653     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
654     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8},
655                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
656 
657     // has one slice
658     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
659     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
660     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
661     EXPECT_EQ(true, curBaseInfo.hasBase);
662     EXPECT_EQ(110, curBaseInfo.base.long_value);
663     EXPECT_EQ(false, curInterval.hasValue);
664     EXPECT_EQ(10, curInterval.value.long_value);
665 
666     valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
667     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8},
668                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
669 
670     // has one slice
671     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
672     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
673     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
674     EXPECT_EQ(true, curInterval.hasValue);
675     EXPECT_EQ(20, curInterval.value.long_value);
676     EXPECT_EQ(false, curBaseInfo.hasBase);
677 
678     valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
679     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1},
680                                     {bucketStartTimeNs, bucket2StartTimeNs},
681                                     {bucket2StartTimeNs, bucket3StartTimeNs});
682 }
683 
TEST_P(ValueMetricProducerTest_PartialBucket,TestPushedEvents)684 TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) {
685     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
686 
687     sp<EventMatcherWizard> eventMatcherWizard =
688             createEventMatcherWizard(tagId, logEventMatcherIndex);
689     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
690     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
691 
692     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
693                                       logEventMatcherIndex, eventMatcherWizard, -1,
694                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
695     valueProducer.prepareFirstBucket();
696 
697     LogEvent event1(/*uid=*/0, /*pid=*/0);
698     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
699     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
700     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
701 
702     int64_t partialBucketSplitTimeNs = bucketStartTimeNs + 150;
703     switch (GetParam()) {
704         case APP_UPGRADE:
705             valueProducer.notifyAppUpgrade(partialBucketSplitTimeNs);
706             break;
707         case BOOT_COMPLETE:
708             valueProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
709             break;
710     }
711     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10},
712                                     {partialBucketSplitTimeNs - bucketStartTimeNs},
713                                     {bucketStartTimeNs}, {partialBucketSplitTimeNs});
714     EXPECT_EQ(partialBucketSplitTimeNs, valueProducer.mCurrentBucketStartTimeNs);
715     EXPECT_EQ(0, valueProducer.getCurrentBucketNum());
716 
717     // Event arrives after the bucket split.
718     LogEvent event2(/*uid=*/0, /*pid=*/0);
719     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 59 * NS_PER_SEC, 20);
720     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
721 
722     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10},
723                                     {partialBucketSplitTimeNs - bucketStartTimeNs},
724                                     {bucketStartTimeNs}, {partialBucketSplitTimeNs});
725     EXPECT_EQ(partialBucketSplitTimeNs, valueProducer.mCurrentBucketStartTimeNs);
726     EXPECT_EQ(0, valueProducer.getCurrentBucketNum());
727 
728     // Next value should create a new bucket.
729     LogEvent event3(/*uid=*/0, /*pid=*/0);
730     CreateRepeatedValueLogEvent(&event3, tagId, bucket2StartTimeNs + 5 * NS_PER_SEC, 10);
731     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
732     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10, 20},
733                                     {partialBucketSplitTimeNs - bucketStartTimeNs,
734                                      bucket2StartTimeNs - partialBucketSplitTimeNs},
735                                     {bucketStartTimeNs, partialBucketSplitTimeNs},
736                                     {partialBucketSplitTimeNs, bucket2StartTimeNs});
737     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
738     EXPECT_EQ(1, valueProducer.getCurrentBucketNum());
739 }
740 
TEST_P(ValueMetricProducerTest_PartialBucket,TestPulledValue)741 TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValue) {
742     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
743 
744     sp<EventMatcherWizard> eventMatcherWizard =
745             createEventMatcherWizard(tagId, logEventMatcherIndex);
746     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
747     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
748     int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 150;
749     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
750     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
751     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
752             .WillOnce(Return(true))
753             .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
754                                                         const int64_t eventTimeNs,
755                                                         vector<std::shared_ptr<LogEvent>>* data) {
756                 EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
757                 data->clear();
758                 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 120));
759                 return true;
760             }));
761 
762     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
763                                       logEventMatcherIndex, eventMatcherWizard, tagId,
764                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
765     valueProducer.prepareFirstBucket();
766 
767     vector<shared_ptr<LogEvent>> allData;
768     allData.clear();
769     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
770 
771     valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
772     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
773 
774     switch (GetParam()) {
775         case APP_UPGRADE:
776             valueProducer.notifyAppUpgrade(partialBucketSplitTimeNs);
777             break;
778         case BOOT_COMPLETE:
779             valueProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
780             break;
781     }
782     EXPECT_EQ(partialBucketSplitTimeNs, valueProducer.mCurrentBucketStartTimeNs);
783     EXPECT_EQ(1, valueProducer.getCurrentBucketNum());
784     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150}, {bucket2StartTimeNs},
785                                     {partialBucketSplitTimeNs});
786 
787     allData.clear();
788     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 150));
789     valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
790     EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
791     EXPECT_EQ(2, valueProducer.getCurrentBucketNum());
792     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30}, {150, bucketSizeNs - 150},
793                                     {bucket2StartTimeNs, partialBucketSplitTimeNs},
794                                     {partialBucketSplitTimeNs, bucket3StartTimeNs});
795 }
796 
TEST(ValueMetricProducerTest,TestPulledWithAppUpgradeDisabled)797 TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
798     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
799     metric.set_split_bucket_for_app_upgrade(false);
800 
801     sp<EventMatcherWizard> eventMatcherWizard =
802             createEventMatcherWizard(tagId, logEventMatcherIndex);
803     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
804     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
805     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
806     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
807     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
808             .WillOnce(Return(true));
809 
810     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
811                                       logEventMatcherIndex, eventMatcherWizard, tagId,
812                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
813     valueProducer.prepareFirstBucket();
814 
815     vector<shared_ptr<LogEvent>> allData;
816     allData.clear();
817     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
818 
819     valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
820     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
821 
822     valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150);
823     ASSERT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
824     EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
825 }
826 
TEST_P(ValueMetricProducerTest_PartialBucket,TestPulledValueWhileConditionFalse)827 TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse) {
828     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
829 
830     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
831     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
832             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
833                                 vector<std::shared_ptr<LogEvent>>* data) {
834                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1);  // Condition change to true time.
835                 data->clear();
836                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
837                 return true;
838             }))
839             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
840                                 vector<std::shared_ptr<LogEvent>>* data) {
841                 EXPECT_EQ(eventTimeNs,
842                           bucket2StartTimeNs - 100);  // Condition change to false time.
843                 data->clear();
844                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 120));
845                 return true;
846             }));
847     sp<ValueMetricProducer> valueProducer =
848             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
849                                                                             ConditionState::kFalse);
850 
851     valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
852 
853     valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
854     EXPECT_FALSE(valueProducer->mCondition);
855 
856     int64_t partialBucketSplitTimeNs = bucket2StartTimeNs - 50;
857     switch (GetParam()) {
858         case APP_UPGRADE:
859             valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
860             break;
861         case BOOT_COMPLETE:
862             valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
863             break;
864     }
865     // Expect one full buckets already done and starting a partial bucket.
866     EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mCurrentBucketStartTimeNs);
867     EXPECT_EQ(0, valueProducer->getCurrentBucketNum());
868     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20},
869                                     {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)},
870                                     {bucketStartTimeNs}, {partialBucketSplitTimeNs});
871     EXPECT_FALSE(valueProducer->mCondition);
872 }
873 
TEST(ValueMetricProducerTest,TestPushedEventsWithoutCondition)874 TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
875     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
876 
877     sp<EventMatcherWizard> eventMatcherWizard =
878             createEventMatcherWizard(tagId, logEventMatcherIndex);
879     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
880     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
881 
882     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
883                                       logEventMatcherIndex, eventMatcherWizard, -1,
884                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
885     valueProducer.prepareFirstBucket();
886 
887     LogEvent event1(/*uid=*/0, /*pid=*/0);
888     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
889 
890     LogEvent event2(/*uid=*/0, /*pid=*/0);
891     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
892 
893     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
894     // has one slice
895     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
896     ValueMetricProducer::Interval curInterval =
897             valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
898     ValueMetricProducer::BaseInfo curBaseInfo =
899             valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
900     EXPECT_EQ(10, curInterval.value.long_value);
901     EXPECT_EQ(true, curInterval.hasValue);
902 
903     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
904 
905     // has one slice
906     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
907     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
908     EXPECT_EQ(30, curInterval.value.long_value);
909 
910     valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
911     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs},
912                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
913 }
914 
TEST(ValueMetricProducerTest,TestPushedEventsWithCondition)915 TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
916     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
917 
918     sp<EventMatcherWizard> eventMatcherWizard =
919             createEventMatcherWizard(tagId, logEventMatcherIndex);
920     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
921     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
922 
923     ValueMetricProducer valueProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard,
924                                       protoHash, logEventMatcherIndex, eventMatcherWizard, -1,
925                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
926     valueProducer.prepareFirstBucket();
927     valueProducer.mCondition = ConditionState::kFalse;
928 
929     LogEvent event1(/*uid=*/0, /*pid=*/0);
930     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
931     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
932     // has 1 slice
933     ASSERT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
934 
935     valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
936 
937     LogEvent event2(/*uid=*/0, /*pid=*/0);
938     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
939     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
940 
941     // has one slice
942     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
943     ValueMetricProducer::Interval curInterval =
944             valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
945     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
946     EXPECT_EQ(20, curInterval.value.long_value);
947 
948     LogEvent event3(/*uid=*/0, /*pid=*/0);
949     CreateRepeatedValueLogEvent(&event3, tagId, bucketStartTimeNs + 30, 30);
950     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
951 
952     // has one slice
953     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
954     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
955     EXPECT_EQ(50, curInterval.value.long_value);
956 
957     valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
958 
959     LogEvent event4(/*uid=*/0, /*pid=*/0);
960     CreateRepeatedValueLogEvent(&event4, tagId, bucketStartTimeNs + 40, 40);
961     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
962 
963     // has one slice
964     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
965     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
966     EXPECT_EQ(50, curInterval.value.long_value);
967 
968     valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
969     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20}, {bucketStartTimeNs},
970                                     {bucket2StartTimeNs});
971 }
972 
TEST(ValueMetricProducerTest,TestAnomalyDetection)973 TEST(ValueMetricProducerTest, TestAnomalyDetection) {
974     sp<AlarmMonitor> alarmMonitor;
975     Alert alert;
976     alert.set_id(101);
977     alert.set_metric_id(metricId);
978     alert.set_trigger_if_sum_gt(130);
979     alert.set_num_buckets(2);
980     const int32_t refPeriodSec = 3;
981     alert.set_refractory_period_secs(refPeriodSec);
982 
983     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
984 
985     sp<EventMatcherWizard> eventMatcherWizard =
986             createEventMatcherWizard(tagId, logEventMatcherIndex);
987     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
988     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
989 
990     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
991                                       wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
992                                       -1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs,
993                                       pullerManager);
994     valueProducer.prepareFirstBucket();
995 
996     sp<AnomalyTracker> anomalyTracker =
997             valueProducer.addAnomalyTracker(alert, alarmMonitor, UPDATE_NEW, bucketStartTimeNs);
998 
999     LogEvent event1(/*uid=*/0, /*pid=*/0);
1000     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 1 * NS_PER_SEC, 10);
1001 
1002     LogEvent event2(/*uid=*/0, /*pid=*/0);
1003     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 2 + NS_PER_SEC, 20);
1004 
1005     LogEvent event3(/*uid=*/0, /*pid=*/0);
1006     CreateRepeatedValueLogEvent(&event3, tagId,
1007                                 bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, 130);
1008 
1009     LogEvent event4(/*uid=*/0, /*pid=*/0);
1010     CreateRepeatedValueLogEvent(&event4, tagId,
1011                                 bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC, 1);
1012 
1013     LogEvent event5(/*uid=*/0, /*pid=*/0);
1014     CreateRepeatedValueLogEvent(&event5, tagId,
1015                                 bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC, 150);
1016 
1017     LogEvent event6(/*uid=*/0, /*pid=*/0);
1018     CreateRepeatedValueLogEvent(&event6, tagId,
1019                                 bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC, 160);
1020 
1021     // Two events in bucket #0.
1022     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1023     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1024     // Value sum == 30 <= 130.
1025     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
1026 
1027     // One event in bucket #2. No alarm as bucket #0 is trashed out.
1028     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
1029     // Value sum == 130 <= 130.
1030     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
1031 
1032     // Three events in bucket #3.
1033     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
1034     // Anomaly at event 4 since Value sum == 131 > 130!
1035     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1036               std::ceil(1.0 * event4.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1037     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
1038     // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
1039     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1040               std::ceil(1.0 * event4.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1041 
1042     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
1043     // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
1044     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
1045               std::ceil(1.0 * event6.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
1046 }
1047 
TEST(ValueMetricProducerTest,TestAnomalyDetectionMultipleBucketsSkipped)1048 TEST(ValueMetricProducerTest, TestAnomalyDetectionMultipleBucketsSkipped) {
1049     sp<AlarmMonitor> alarmMonitor;
1050     Alert alert;
1051     alert.set_id(101);
1052     alert.set_metric_id(metricId);
1053     alert.set_trigger_if_sum_gt(100);
1054     alert.set_num_buckets(1);
1055     const int32_t refPeriodSec = 3;
1056     alert.set_refractory_period_secs(refPeriodSec);
1057 
1058     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1059 
1060     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1061     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1062             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1063                                 vector<std::shared_ptr<LogEvent>>* data) {
1064                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1);  // Condition change to true time.
1065                 data->clear();
1066                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 0));
1067                 return true;
1068             }))
1069             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1070                                 vector<std::shared_ptr<LogEvent>>* data) {
1071                 EXPECT_EQ(eventTimeNs,
1072                           bucket3StartTimeNs + 100);  // Condition changed to false time.
1073                 data->clear();
1074                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 100, 120));
1075                 return true;
1076             }));
1077     sp<ValueMetricProducer> valueProducer =
1078             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
1079                                                                             ConditionState::kFalse);
1080     sp<AnomalyTracker> anomalyTracker =
1081             valueProducer->addAnomalyTracker(alert, alarmMonitor, UPDATE_NEW, bucketStartTimeNs);
1082 
1083     valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
1084 
1085     // multiple buckets should be skipped here.
1086     valueProducer->onConditionChanged(false, bucket3StartTimeNs + 100);
1087 
1088     // No alert is fired when multiple buckets are skipped.
1089     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
1090 }
1091 
1092 // Test value metric no condition, the pull on bucket boundary come in time and too late
TEST(ValueMetricProducerTest,TestBucketBoundaryNoCondition)1093 TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
1094     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1095     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1096     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
1097             .WillOnce(Return(true));
1098     sp<ValueMetricProducer> valueProducer =
1099             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1100 
1101     vector<shared_ptr<LogEvent>> allData;
1102     // pull 1
1103     allData.clear();
1104     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
1105 
1106     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1107     // has one slice
1108     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1109     ValueMetricProducer::Interval curInterval =
1110             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1111     ValueMetricProducer::BaseInfo curBaseInfo =
1112             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1113 
1114     // startUpdated:true sum:0 start:11
1115     EXPECT_EQ(true, curBaseInfo.hasBase);
1116     EXPECT_EQ(11, curBaseInfo.base.long_value);
1117     EXPECT_EQ(false, curInterval.hasValue);
1118     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1119 
1120     // pull 2 at correct time
1121     allData.clear();
1122     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
1123     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
1124     // has one slice
1125     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1126     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1127     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1128     // tartUpdated:false sum:12
1129     EXPECT_EQ(true, curBaseInfo.hasBase);
1130     EXPECT_EQ(23, curBaseInfo.base.long_value);
1131     EXPECT_EQ(false, curInterval.hasValue);
1132     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs},
1133                                     {bucket2StartTimeNs}, {bucket3StartTimeNs});
1134 
1135     // pull 3 come late.
1136     // The previous bucket gets closed with error. (Has start value 23, no ending)
1137     // Another bucket gets closed with error. (No start, but ending with 36)
1138     // The new bucket is back to normal.
1139     allData.clear();
1140     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket6StartTimeNs + 1, 36));
1141     valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
1142     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1143     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1144     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1145     // startUpdated:false sum:12
1146     EXPECT_EQ(true, curBaseInfo.hasBase);
1147     EXPECT_EQ(36, curBaseInfo.base.long_value);
1148     EXPECT_EQ(false, curInterval.hasValue);
1149     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs},
1150                                     {bucket2StartTimeNs}, {bucket3StartTimeNs});
1151     // The 1st bucket is dropped because of no data
1152     // The 3rd bucket is dropped due to multiple buckets being skipped.
1153     ASSERT_EQ(2, valueProducer->mSkippedBuckets.size());
1154 
1155     EXPECT_EQ(bucketStartTimeNs, valueProducer->mSkippedBuckets[0].bucketStartTimeNs);
1156     EXPECT_EQ(bucket2StartTimeNs, valueProducer->mSkippedBuckets[0].bucketEndTimeNs);
1157     ASSERT_EQ(1, valueProducer->mSkippedBuckets[0].dropEvents.size());
1158     EXPECT_EQ(NO_DATA, valueProducer->mSkippedBuckets[0].dropEvents[0].reason);
1159     EXPECT_EQ(bucket2StartTimeNs, valueProducer->mSkippedBuckets[0].dropEvents[0].dropTimeNs);
1160 
1161     EXPECT_EQ(bucket3StartTimeNs, valueProducer->mSkippedBuckets[1].bucketStartTimeNs);
1162     EXPECT_EQ(bucket6StartTimeNs, valueProducer->mSkippedBuckets[1].bucketEndTimeNs);
1163     ASSERT_EQ(1, valueProducer->mSkippedBuckets[1].dropEvents.size());
1164     EXPECT_EQ(MULTIPLE_BUCKETS_SKIPPED, valueProducer->mSkippedBuckets[1].dropEvents[0].reason);
1165     EXPECT_EQ(bucket6StartTimeNs, valueProducer->mSkippedBuckets[1].dropEvents[0].dropTimeNs);
1166 }
1167 
1168 /*
1169  * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
1170  * was delivered late.
1171  */
TEST(ValueMetricProducerTest,TestBucketBoundaryWithCondition)1172 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
1173     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1174 
1175     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1176     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1177             // condition becomes true
1178             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1179                                 vector<std::shared_ptr<LogEvent>>* data) {
1180                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);  // First condition change.
1181                 data->clear();
1182                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1183                 return true;
1184             }))
1185             // condition becomes false
1186             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1187                                 vector<std::shared_ptr<LogEvent>>* data) {
1188                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1);  // Second condition change.
1189                 data->clear();
1190                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
1191                 return true;
1192             }));
1193     sp<ValueMetricProducer> valueProducer =
1194             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
1195                                                                             ConditionState::kFalse);
1196 
1197     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1198 
1199     // has one slice
1200     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1201     ValueMetricProducer::Interval curInterval =
1202             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1203     ValueMetricProducer::BaseInfo curBaseInfo =
1204             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1205     EXPECT_EQ(true, curBaseInfo.hasBase);
1206     EXPECT_EQ(100, curBaseInfo.base.long_value);
1207     EXPECT_EQ(false, curInterval.hasValue);
1208     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1209 
1210     // pull on bucket boundary come late, condition change happens before it
1211     valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
1212     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1213     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1214     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1215                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1216     EXPECT_EQ(false, curBaseInfo.hasBase);
1217 
1218     // Now the alarm is delivered.
1219     // since the condition turned to off before this pull finish, it has no effect
1220     vector<shared_ptr<LogEvent>> allData;
1221     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 110));
1222     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1223 
1224     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1225                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1226     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1227     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1228     EXPECT_EQ(false, curBaseInfo.hasBase);
1229     EXPECT_EQ(false, curInterval.hasValue);
1230 }
1231 
1232 /*
1233  * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
1234  * change to false, and then true again. This is due to alarm delivered late.
1235  */
TEST(ValueMetricProducerTest,TestBucketBoundaryWithCondition2)1236 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
1237     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1238 
1239     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1240     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1241             // condition becomes true
1242             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1243                                 vector<std::shared_ptr<LogEvent>>* data) {
1244                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
1245                 data->clear();
1246                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1247                 return true;
1248             }))
1249             // condition becomes false
1250             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1251                                 vector<std::shared_ptr<LogEvent>>* data) {
1252                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1);
1253                 data->clear();
1254                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
1255                 return true;
1256             }))
1257             // condition becomes true again
1258             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1259                                 vector<std::shared_ptr<LogEvent>>* data) {
1260                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 25);
1261                 data->clear();
1262                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 25, 130));
1263                 return true;
1264             }));
1265 
1266     sp<ValueMetricProducer> valueProducer =
1267             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
1268                                                                             ConditionState::kFalse);
1269 
1270     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1271 
1272     // has one slice
1273     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1274     ValueMetricProducer::Interval curInterval =
1275             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1276     ValueMetricProducer::BaseInfo curBaseInfo =
1277             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1278     // startUpdated:false sum:0 start:100
1279     EXPECT_EQ(true, curBaseInfo.hasBase);
1280     EXPECT_EQ(100, curBaseInfo.base.long_value);
1281     EXPECT_EQ(false, curInterval.hasValue);
1282     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1283 
1284     // pull on bucket boundary come late, condition change happens before it
1285     valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
1286     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1287                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1288     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1289     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1290     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1291     EXPECT_EQ(false, curBaseInfo.hasBase);
1292     EXPECT_EQ(false, curInterval.hasValue);
1293 
1294     // condition changed to true again, before the pull alarm is delivered
1295     valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
1296     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1297                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1298     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1299     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1300     EXPECT_EQ(true, curBaseInfo.hasBase);
1301     EXPECT_EQ(130, curBaseInfo.base.long_value);
1302     EXPECT_EQ(false, curInterval.hasValue);
1303 
1304     // Now the alarm is delivered, but it is considered late, the data will be used
1305     // for the new bucket since it was just pulled.
1306     vector<shared_ptr<LogEvent>> allData;
1307     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 50, 140));
1308     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
1309 
1310     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1311     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1312     EXPECT_EQ(true, curBaseInfo.hasBase);
1313     EXPECT_EQ(140, curBaseInfo.base.long_value);
1314     EXPECT_EQ(true, curInterval.hasValue);
1315     EXPECT_EQ(10, curInterval.value.long_value);
1316     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
1317                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1318 
1319     allData.clear();
1320     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 160));
1321     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
1322     assertPastBucketValuesSingleKey(
1323             valueProducer->mPastBuckets, {20, 30}, {bucketSizeNs - 8, bucketSizeNs - 24},
1324             {bucketStartTimeNs, bucket2StartTimeNs}, {bucket2StartTimeNs, bucket3StartTimeNs});
1325 }
1326 
TEST(ValueMetricProducerTest,TestPushedAggregateMin)1327 TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
1328     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1329     metric.set_aggregation_type(ValueMetric::MIN);
1330 
1331     sp<EventMatcherWizard> eventMatcherWizard =
1332             createEventMatcherWizard(tagId, logEventMatcherIndex);
1333     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1334     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1335 
1336     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1337                                       logEventMatcherIndex, eventMatcherWizard, -1,
1338                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1339     valueProducer.prepareFirstBucket();
1340 
1341     LogEvent event1(/*uid=*/0, /*pid=*/0);
1342     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
1343 
1344     LogEvent event2(/*uid=*/0, /*pid=*/0);
1345     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
1346 
1347     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1348     // has one slice
1349     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1350     ValueMetricProducer::Interval curInterval =
1351             valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1352     EXPECT_EQ(10, curInterval.value.long_value);
1353     EXPECT_EQ(true, curInterval.hasValue);
1354 
1355     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1356 
1357     // has one slice
1358     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1359     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1360     EXPECT_EQ(10, curInterval.value.long_value);
1361 
1362     valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1363     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs},
1364                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1365 }
1366 
TEST(ValueMetricProducerTest,TestPushedAggregateMax)1367 TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
1368     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1369     metric.set_aggregation_type(ValueMetric::MAX);
1370 
1371     sp<EventMatcherWizard> eventMatcherWizard =
1372             createEventMatcherWizard(tagId, logEventMatcherIndex);
1373     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1374     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1375 
1376     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1377                                       logEventMatcherIndex, eventMatcherWizard, -1,
1378                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1379     valueProducer.prepareFirstBucket();
1380 
1381     LogEvent event1(/*uid=*/0, /*pid=*/0);
1382     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
1383     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1384 
1385     // has one slice
1386     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1387     ValueMetricProducer::Interval curInterval =
1388             valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1389     EXPECT_EQ(10, curInterval.value.long_value);
1390     EXPECT_EQ(true, curInterval.hasValue);
1391 
1392     LogEvent event2(/*uid=*/0, /*pid=*/0);
1393     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 20);
1394     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1395 
1396     // has one slice
1397     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1398     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1399     EXPECT_EQ(20, curInterval.value.long_value);
1400 
1401     valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1402     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {bucketSizeNs},
1403                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1404 }
1405 
TEST(ValueMetricProducerTest,TestPushedAggregateAvg)1406 TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
1407     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1408     metric.set_aggregation_type(ValueMetric::AVG);
1409 
1410     sp<EventMatcherWizard> eventMatcherWizard =
1411             createEventMatcherWizard(tagId, logEventMatcherIndex);
1412     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1413     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1414 
1415     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1416                                       logEventMatcherIndex, eventMatcherWizard, -1,
1417                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1418     valueProducer.prepareFirstBucket();
1419 
1420     LogEvent event1(/*uid=*/0, /*pid=*/0);
1421     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
1422 
1423     LogEvent event2(/*uid=*/0, /*pid=*/0);
1424     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 15);
1425     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1426     // has one slice
1427     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1428     ValueMetricProducer::Interval curInterval;
1429     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1430     EXPECT_EQ(10, curInterval.value.long_value);
1431     EXPECT_EQ(true, curInterval.hasValue);
1432     EXPECT_EQ(1, curInterval.sampleSize);
1433 
1434     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1435 
1436     // has one slice
1437     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1438     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1439     EXPECT_EQ(25, curInterval.value.long_value);
1440     EXPECT_EQ(2, curInterval.sampleSize);
1441 
1442     valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1443     ASSERT_EQ(1UL, valueProducer.mPastBuckets.size());
1444     ASSERT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
1445 
1446     EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
1447                          12.5) < epsilon);
1448 }
1449 
TEST(ValueMetricProducerTest,TestPushedAggregateSum)1450 TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
1451     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1452     metric.set_aggregation_type(ValueMetric::SUM);
1453 
1454     sp<EventMatcherWizard> eventMatcherWizard =
1455             createEventMatcherWizard(tagId, logEventMatcherIndex);
1456     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1457     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1458 
1459     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1460                                       logEventMatcherIndex, eventMatcherWizard, -1,
1461                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1462     valueProducer.prepareFirstBucket();
1463 
1464     LogEvent event1(/*uid=*/0, /*pid=*/0);
1465     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
1466 
1467     LogEvent event2(/*uid=*/0, /*pid=*/0);
1468     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 15);
1469     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1470     // has one slice
1471     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1472     ValueMetricProducer::Interval curInterval =
1473             valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1474     EXPECT_EQ(10, curInterval.value.long_value);
1475     EXPECT_EQ(true, curInterval.hasValue);
1476 
1477     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1478 
1479     // has one slice
1480     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1481     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1482     EXPECT_EQ(25, curInterval.value.long_value);
1483 
1484     valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
1485     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs},
1486                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1487 }
1488 
TEST(ValueMetricProducerTest,TestSkipZeroDiffOutput)1489 TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
1490     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1491     metric.set_aggregation_type(ValueMetric::MIN);
1492     metric.set_use_diff(true);
1493 
1494     sp<EventMatcherWizard> eventMatcherWizard =
1495             createEventMatcherWizard(tagId, logEventMatcherIndex);
1496     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1497     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1498 
1499     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1500                                       logEventMatcherIndex, eventMatcherWizard, -1,
1501                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1502     valueProducer.prepareFirstBucket();
1503 
1504     LogEvent event1(/*uid=*/0, /*pid=*/0);
1505     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
1506     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1507 
1508     // has one slice
1509     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1510     ValueMetricProducer::Interval curInterval =
1511             valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1512     ValueMetricProducer::BaseInfo curBaseInfo =
1513             valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1514     EXPECT_EQ(true, curBaseInfo.hasBase);
1515     EXPECT_EQ(10, curBaseInfo.base.long_value);
1516     EXPECT_EQ(false, curInterval.hasValue);
1517 
1518     LogEvent event2(/*uid=*/0, /*pid=*/0);
1519     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 15, 15);
1520     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1521 
1522     // has one slice
1523     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1524     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1525     EXPECT_EQ(true, curInterval.hasValue);
1526     EXPECT_EQ(5, curInterval.value.long_value);
1527 
1528     // no change in data.
1529     LogEvent event3(/*uid=*/0, /*pid=*/0);
1530     CreateRepeatedValueLogEvent(&event3, tagId, bucket2StartTimeNs + 10, 15);
1531     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
1532 
1533     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1534     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1535     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1536     EXPECT_EQ(true, curBaseInfo.hasBase);
1537     EXPECT_EQ(15, curBaseInfo.base.long_value);
1538     EXPECT_EQ(true, curInterval.hasValue);
1539     EXPECT_EQ(0, curInterval.value.long_value);
1540 
1541     LogEvent event4(/*uid=*/0, /*pid=*/0);
1542     CreateRepeatedValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 15);
1543     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
1544     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1545     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1546     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1547     EXPECT_EQ(true, curBaseInfo.hasBase);
1548     EXPECT_EQ(15, curBaseInfo.base.long_value);
1549     EXPECT_EQ(true, curInterval.hasValue);
1550     EXPECT_EQ(0, curInterval.value.long_value);
1551 
1552     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1553     assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs},
1554                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1555 }
1556 
TEST(ValueMetricProducerTest,TestSkipZeroDiffOutputMultiValue)1557 TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
1558     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1559     metric.mutable_value_field()->add_child()->set_field(3);
1560     metric.set_aggregation_type(ValueMetric::MIN);
1561     metric.set_use_diff(true);
1562 
1563     sp<EventMatcherWizard> eventMatcherWizard =
1564             createEventMatcherWizard(tagId, logEventMatcherIndex);
1565     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
1566     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1567 
1568     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
1569                                       logEventMatcherIndex, eventMatcherWizard, -1,
1570                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
1571     valueProducer.prepareFirstBucket();
1572 
1573     LogEvent event1(/*uid=*/0, /*pid=*/0);
1574     CreateThreeValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10, 20);
1575 
1576     LogEvent event2(/*uid=*/0, /*pid=*/0);
1577     CreateThreeValueLogEvent(&event2, tagId, bucketStartTimeNs + 15, 1, 15, 22);
1578 
1579     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
1580     // has one slice
1581     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1582     ValueMetricProducer::Interval curInterval =
1583             valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1584     ValueMetricProducer::BaseInfo curBaseInfo =
1585             valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1586     EXPECT_EQ(true, curBaseInfo.hasBase);
1587     EXPECT_EQ(10, curBaseInfo.base.long_value);
1588     EXPECT_EQ(false, curInterval.hasValue);
1589     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
1590     EXPECT_EQ(true, curBaseInfo.hasBase);
1591     EXPECT_EQ(20, curBaseInfo.base.long_value);
1592     EXPECT_EQ(false, curInterval.hasValue);
1593 
1594     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
1595 
1596     // has one slice
1597     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1598     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1599     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1600     EXPECT_EQ(true, curInterval.hasValue);
1601     EXPECT_EQ(5, curInterval.value.long_value);
1602     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
1603     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
1604     EXPECT_EQ(true, curInterval.hasValue);
1605     EXPECT_EQ(2, curInterval.value.long_value);
1606 
1607     // no change in first value field
1608     LogEvent event3(/*uid=*/0, /*pid=*/0);
1609     CreateThreeValueLogEvent(&event3, tagId, bucket2StartTimeNs + 10, 1, 15, 25);
1610 
1611     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
1612     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1613     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1614     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1615 
1616     EXPECT_EQ(true, curBaseInfo.hasBase);
1617     EXPECT_EQ(15, curBaseInfo.base.long_value);
1618     EXPECT_EQ(true, curInterval.hasValue);
1619     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
1620     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
1621     EXPECT_EQ(true, curBaseInfo.hasBase);
1622     EXPECT_EQ(25, curBaseInfo.base.long_value);
1623     EXPECT_EQ(true, curInterval.hasValue);
1624 
1625     LogEvent event4(/*uid=*/0, /*pid=*/0);
1626     CreateThreeValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 1, 15, 29);
1627 
1628     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
1629     ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
1630     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[0];
1631     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[0];
1632     EXPECT_EQ(true, curBaseInfo.hasBase);
1633     EXPECT_EQ(15, curBaseInfo.base.long_value);
1634     EXPECT_EQ(true, curInterval.hasValue);
1635     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second.intervals[1];
1636     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second.baseInfos[1];
1637     EXPECT_EQ(true, curBaseInfo.hasBase);
1638     EXPECT_EQ(29, curBaseInfo.base.long_value);
1639     EXPECT_EQ(true, curInterval.hasValue);
1640 
1641     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
1642 
1643     ASSERT_EQ(1UL, valueProducer.mPastBuckets.size());
1644     ASSERT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
1645     ASSERT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
1646     ASSERT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
1647 
1648     EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
1649     EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
1650     EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]);
1651     EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value);
1652     EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]);
1653 
1654     EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs);
1655     EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
1656     EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]);
1657 }
1658 
1659 /*
1660  * Tests zero default base.
1661  */
TEST(ValueMetricProducerTest,TestUseZeroDefaultBase)1662 TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
1663     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1664     metric.mutable_dimensions_in_what()->set_field(tagId);
1665     metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1666     metric.set_use_zero_default_base(true);
1667 
1668     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1669     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
1670             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
1671                                 vector<std::shared_ptr<LogEvent>>* data) {
1672                 data->clear();
1673                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
1674                 return true;
1675             }));
1676 
1677     sp<ValueMetricProducer> valueProducer =
1678             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1679 
1680     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1681     auto iter = valueProducer->mCurrentSlicedBucket.begin();
1682     auto& interval1 = iter->second.intervals[0];
1683     auto iterBase = valueProducer->mCurrentBaseInfo.begin();
1684     auto& baseInfo1 = iterBase->second.baseInfos[0];
1685     EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1686     EXPECT_EQ(true, baseInfo1.hasBase);
1687     EXPECT_EQ(3, baseInfo1.base.long_value);
1688     EXPECT_EQ(false, interval1.hasValue);
1689     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1690     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1691     vector<shared_ptr<LogEvent>> allData;
1692 
1693     allData.clear();
1694     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
1695     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
1696 
1697     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1698     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1699     EXPECT_EQ(true, baseInfo1.hasBase);
1700     EXPECT_EQ(11, baseInfo1.base.long_value);
1701     EXPECT_EQ(false, interval1.hasValue);
1702     EXPECT_EQ(8, interval1.value.long_value);
1703 
1704     auto it = valueProducer->mCurrentSlicedBucket.begin();
1705     for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
1706         if (it != iter) {
1707             break;
1708         }
1709     }
1710     auto itBase = valueProducer->mCurrentBaseInfo.begin();
1711     for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
1712         if (itBase != iterBase) {
1713             break;
1714         }
1715     }
1716     EXPECT_TRUE(it != iter);
1717     EXPECT_TRUE(itBase != iterBase);
1718     auto& interval2 = it->second.intervals[0];
1719     auto& baseInfo2 = itBase->second.baseInfos[0];
1720     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1721     EXPECT_EQ(true, baseInfo2.hasBase);
1722     EXPECT_EQ(4, baseInfo2.base.long_value);
1723     EXPECT_EQ(false, interval2.hasValue);
1724     EXPECT_EQ(4, interval2.value.long_value);
1725 
1726     ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1727     auto iterator = valueProducer->mPastBuckets.begin();
1728     EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1729     EXPECT_EQ(8, iterator->second[0].values[0].long_value);
1730     iterator++;
1731     EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1732     EXPECT_EQ(4, iterator->second[0].values[0].long_value);
1733 }
1734 
1735 /*
1736  * Tests using zero default base with failed pull.
1737  */
TEST(ValueMetricProducerTest,TestUseZeroDefaultBaseWithPullFailures)1738 TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
1739     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1740     metric.mutable_dimensions_in_what()->set_field(tagId);
1741     metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1742     metric.set_use_zero_default_base(true);
1743 
1744     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1745     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
1746             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
1747                                 vector<std::shared_ptr<LogEvent>>* data) {
1748                 data->clear();
1749                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
1750                 return true;
1751             }));
1752 
1753     sp<ValueMetricProducer> valueProducer =
1754             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1755 
1756     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1757     const auto& it = valueProducer->mCurrentSlicedBucket.begin();
1758     ValueMetricProducer::Interval& interval1 = it->second.intervals[0];
1759     ValueMetricProducer::BaseInfo& baseInfo1 =
1760             valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())
1761                     ->second.baseInfos[0];
1762     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1763     EXPECT_EQ(true, baseInfo1.hasBase);
1764     EXPECT_EQ(3, baseInfo1.base.long_value);
1765     EXPECT_EQ(false, interval1.hasValue);
1766     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1767     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1768     vector<shared_ptr<LogEvent>> allData;
1769 
1770     allData.clear();
1771     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
1772     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
1773 
1774     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1775     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1776     EXPECT_EQ(true, baseInfo1.hasBase);
1777     EXPECT_EQ(11, baseInfo1.base.long_value);
1778     EXPECT_EQ(false, interval1.hasValue);
1779     EXPECT_EQ(8, interval1.value.long_value);
1780 
1781     auto it2 = valueProducer->mCurrentSlicedBucket.begin();
1782     for (; it2 != valueProducer->mCurrentSlicedBucket.end(); it2++) {
1783         if (it2 != it) {
1784             break;
1785         }
1786     }
1787     EXPECT_TRUE(it2 != it);
1788     ValueMetricProducer::Interval& interval2 = it2->second.intervals[0];
1789     ValueMetricProducer::BaseInfo& baseInfo2 =
1790             valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())
1791                     ->second.baseInfos[0];
1792     EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1793     EXPECT_EQ(true, baseInfo2.hasBase);
1794     EXPECT_EQ(4, baseInfo2.base.long_value);
1795     EXPECT_EQ(false, interval2.hasValue);
1796     EXPECT_EQ(4, interval2.value.long_value);
1797     ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1798 
1799     // next pull somehow did not happen, skip to end of bucket 3
1800     allData.clear();
1801     allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 2, 5));
1802     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
1803 
1804     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1805     EXPECT_EQ(true, baseInfo2.hasBase);
1806     EXPECT_EQ(5, baseInfo2.base.long_value);
1807     EXPECT_EQ(false, interval2.hasValue);
1808     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1809     ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1810 
1811     allData.clear();
1812     allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 13));
1813     allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 1, 5));
1814     valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
1815 
1816     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1817     // Get new references now that entries have been deleted from the map
1818     const auto& it3 = valueProducer->mCurrentSlicedBucket.begin();
1819     const auto& it4 = std::next(valueProducer->mCurrentSlicedBucket.begin());
1820     ASSERT_EQ(it3->second.intervals.size(), 1);
1821     ASSERT_EQ(it4->second.intervals.size(), 1);
1822     ValueMetricProducer::Interval& interval3 = it3->second.intervals[0];
1823     ValueMetricProducer::Interval& interval4 = it4->second.intervals[0];
1824     ValueMetricProducer::BaseInfo& baseInfo3 =
1825             valueProducer->mCurrentBaseInfo.find(it3->first.getDimensionKeyInWhat())
1826                     ->second.baseInfos[0];
1827     ValueMetricProducer::BaseInfo& baseInfo4 =
1828             valueProducer->mCurrentBaseInfo.find(it4->first.getDimensionKeyInWhat())
1829                     ->second.baseInfos[0];
1830 
1831     EXPECT_EQ(true, baseInfo3.hasBase);
1832     EXPECT_EQ(5, baseInfo3.base.long_value);
1833     EXPECT_EQ(false, interval3.hasValue);
1834     EXPECT_EQ(5, interval3.value.long_value);
1835     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
1836 
1837     EXPECT_EQ(true, baseInfo4.hasBase);
1838     EXPECT_EQ(13, baseInfo4.base.long_value);
1839     EXPECT_EQ(false, interval4.hasValue);
1840     EXPECT_EQ(8, interval4.value.long_value);
1841 
1842     ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1843 }
1844 
1845 /*
1846  * Tests trim unused dimension key if no new data is seen in an entire bucket.
1847  */
TEST(ValueMetricProducerTest,TestTrimUnusedDimensionKey)1848 TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
1849     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
1850     metric.mutable_dimensions_in_what()->set_field(tagId);
1851     metric.mutable_dimensions_in_what()->add_child()->set_field(1);
1852 
1853     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1854     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
1855             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
1856                                 vector<std::shared_ptr<LogEvent>>* data) {
1857                 data->clear();
1858                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
1859                 return true;
1860             }));
1861 
1862     sp<ValueMetricProducer> valueProducer =
1863             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
1864 
1865     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1866     auto iter = valueProducer->mCurrentSlicedBucket.begin();
1867     auto& interval1 = iter->second.intervals[0];
1868     auto iterBase = valueProducer->mCurrentBaseInfo.begin();
1869     auto& baseInfo1 = iterBase->second.baseInfos[0];
1870     EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1871     EXPECT_EQ(true, baseInfo1.hasBase);
1872     EXPECT_EQ(3, baseInfo1.base.long_value);
1873     EXPECT_EQ(false, interval1.hasValue);
1874     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
1875 
1876     vector<shared_ptr<LogEvent>> allData;
1877     allData.clear();
1878     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
1879     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
1880     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
1881 
1882     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
1883     EXPECT_EQ(true, baseInfo1.hasBase);
1884     EXPECT_EQ(11, baseInfo1.base.long_value);
1885     EXPECT_EQ(false, interval1.hasValue);
1886     EXPECT_EQ(8, interval1.value.long_value);
1887     EXPECT_FALSE(interval1.seenNewData);
1888     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs},
1889                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1890 
1891     auto it = valueProducer->mCurrentSlicedBucket.begin();
1892     for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
1893         if (it != iter) {
1894             break;
1895         }
1896     }
1897     auto itBase = valueProducer->mCurrentBaseInfo.begin();
1898     for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
1899         if (itBase != iterBase) {
1900             break;
1901         }
1902     }
1903     EXPECT_TRUE(it != iter);
1904     EXPECT_TRUE(itBase != iterBase);
1905     auto interval2 = it->second.intervals[0];
1906     auto baseInfo2 = itBase->second.baseInfos[0];
1907     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1908     EXPECT_EQ(true, baseInfo2.hasBase);
1909     EXPECT_EQ(4, baseInfo2.base.long_value);
1910     EXPECT_EQ(false, interval2.hasValue);
1911     EXPECT_FALSE(interval2.seenNewData);
1912 
1913     // next pull somehow did not happen, skip to end of bucket 3
1914     allData.clear();
1915     allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 2, 5));
1916     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
1917     // Only one interval left. One was trimmed.
1918     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1919     interval2 = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1920     baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1921     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
1922     EXPECT_EQ(true, baseInfo2.hasBase);
1923     EXPECT_EQ(5, baseInfo2.base.long_value);
1924     EXPECT_EQ(false, interval2.hasValue);
1925     EXPECT_FALSE(interval2.seenNewData);
1926     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs},
1927                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
1928 
1929     allData.clear();
1930     allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 14));
1931     valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
1932 
1933     interval2 = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1934     baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1935     EXPECT_EQ(true, baseInfo2.hasBase);
1936     EXPECT_EQ(14, baseInfo2.base.long_value);
1937     EXPECT_EQ(false, interval2.hasValue);
1938     EXPECT_FALSE(interval2.seenNewData);
1939     ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
1940     auto iterator = valueProducer->mPastBuckets.begin();
1941     EXPECT_EQ(bucket4StartTimeNs, iterator->second[0].mBucketStartNs);
1942     EXPECT_EQ(bucket5StartTimeNs, iterator->second[0].mBucketEndNs);
1943     EXPECT_EQ(9, iterator->second[0].values[0].long_value);
1944     EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1945     iterator++;
1946     EXPECT_EQ(bucketStartTimeNs, iterator->second[0].mBucketStartNs);
1947     EXPECT_EQ(bucket2StartTimeNs, iterator->second[0].mBucketEndNs);
1948     EXPECT_EQ(8, iterator->second[0].values[0].long_value);
1949     EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
1950 }
1951 
TEST(ValueMetricProducerTest,TestResetBaseOnPullFailAfterConditionChange_EndOfBucket)1952 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
1953     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1954 
1955     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1956     // Used by onConditionChanged.
1957     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _))
1958             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
1959                                 vector<std::shared_ptr<LogEvent>>* data) {
1960                 data->clear();
1961                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1962                 return true;
1963             }));
1964 
1965     sp<ValueMetricProducer> valueProducer =
1966             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
1967                                                                             ConditionState::kFalse);
1968 
1969     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
1970     // has one slice
1971     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1972     ValueMetricProducer::Interval& curInterval =
1973             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
1974     ValueMetricProducer::BaseInfo& curBaseInfo =
1975             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
1976     EXPECT_EQ(true, curBaseInfo.hasBase);
1977     EXPECT_EQ(100, curBaseInfo.base.long_value);
1978     EXPECT_EQ(false, curInterval.hasValue);
1979 
1980     vector<shared_ptr<LogEvent>> allData;
1981     valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
1982     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
1983     EXPECT_EQ(false, curBaseInfo.hasBase);
1984     EXPECT_EQ(false, curInterval.hasValue);
1985     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
1986 }
1987 
TEST(ValueMetricProducerTest,TestResetBaseOnPullFailAfterConditionChange)1988 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
1989     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
1990 
1991     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
1992     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
1993             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
1994                                 vector<std::shared_ptr<LogEvent>>* data) {
1995                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);  // Condition change to true.
1996                 data->clear();
1997                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
1998                 return true;
1999             }))
2000             .WillOnce(Return(false));
2001 
2002     sp<ValueMetricProducer> valueProducer =
2003             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2004                                                                             ConditionState::kFalse);
2005 
2006     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
2007 
2008     // has one slice
2009     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2010     ValueMetricProducer::Interval& curInterval =
2011             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2012     ValueMetricProducer::BaseInfo& curBaseInfo =
2013             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2014     EXPECT_EQ(true, curBaseInfo.hasBase);
2015     EXPECT_EQ(100, curBaseInfo.base.long_value);
2016     EXPECT_EQ(false, curInterval.hasValue);
2017     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
2018 
2019     valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
2020 
2021     // has one slice
2022     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2023     EXPECT_EQ(false, curInterval.hasValue);
2024     EXPECT_EQ(false, curBaseInfo.hasBase);
2025     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2026 }
2027 
TEST(ValueMetricProducerTest,TestResetBaseOnPullFailBeforeConditionChange)2028 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
2029     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2030 
2031     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2032     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2033             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2034                                 vector<std::shared_ptr<LogEvent>>* data) {
2035                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
2036                 data->clear();
2037                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50));
2038                 return false;
2039             }))
2040             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2041                                 vector<std::shared_ptr<LogEvent>>* data) {
2042                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1);  // Condition change to false.
2043                 data->clear();
2044                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
2045                 return true;
2046             }));
2047 
2048     sp<ValueMetricProducer> valueProducer =
2049             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2050                                                                             ConditionState::kFalse);
2051 
2052     // Don't directly set mCondition; the real code never does that. Go through regular code path
2053     // to avoid unexpected behaviors.
2054     // valueProducer->mCondition = ConditionState::kTrue;
2055     valueProducer->onConditionChanged(true, bucketStartTimeNs);
2056 
2057     ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2058 
2059     valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
2060     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2061     ValueMetricProducer::Interval& curInterval =
2062             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2063     ValueMetricProducer::BaseInfo curBaseInfo =
2064             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2065     EXPECT_EQ(false, curBaseInfo.hasBase);
2066     EXPECT_EQ(false, curInterval.hasValue);
2067     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2068 }
2069 
TEST(ValueMetricProducerTest,TestResetBaseOnPullDelayExceeded)2070 TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
2071     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2072     metric.set_condition(StringToId("SCREEN_ON"));
2073     metric.set_max_pull_delay_sec(0);
2074 
2075     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2076     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _))
2077             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2078                                 vector<std::shared_ptr<LogEvent>>* data) {
2079                 data->clear();
2080                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 120));
2081                 return true;
2082             }));
2083 
2084     sp<ValueMetricProducer> valueProducer =
2085             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2086                                                                             ConditionState::kFalse);
2087 
2088     // Max delay is set to 0 so pull will exceed max delay.
2089     valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
2090     ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2091 }
2092 
TEST(ValueMetricProducerTest,TestResetBaseOnPullTooLate)2093 TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
2094     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2095 
2096     sp<EventMatcherWizard> eventMatcherWizard =
2097             createEventMatcherWizard(tagId, logEventMatcherIndex);
2098     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2099     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2100     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
2101     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
2102 
2103     ValueMetricProducer valueProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard,
2104                                       protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
2105                                       bucket2StartTimeNs, bucket2StartTimeNs, pullerManager);
2106     valueProducer.prepareFirstBucket();
2107     valueProducer.mCondition = ConditionState::kFalse;
2108 
2109     // Event should be skipped since it is from previous bucket.
2110     // Pull should not be called.
2111     valueProducer.onConditionChanged(true, bucketStartTimeNs);
2112     ASSERT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
2113 }
2114 
TEST(ValueMetricProducerTest,TestBaseSetOnConditionChange)2115 TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
2116     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2117 
2118     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2119     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _))
2120             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2121                                 vector<std::shared_ptr<LogEvent>>* data) {
2122                 data->clear();
2123                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
2124                 return true;
2125             }));
2126 
2127     sp<ValueMetricProducer> valueProducer =
2128             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2129                                                                             ConditionState::kFalse);
2130     valueProducer->mHasGlobalBase = false;
2131 
2132     valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
2133     valueProducer->mHasGlobalBase = true;
2134     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2135     ValueMetricProducer::Interval& curInterval =
2136             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2137     ValueMetricProducer::BaseInfo curBaseInfo =
2138             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2139     EXPECT_EQ(true, curBaseInfo.hasBase);
2140     EXPECT_EQ(100, curBaseInfo.base.long_value);
2141     EXPECT_EQ(false, curInterval.hasValue);
2142     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2143 }
2144 
2145 /*
2146  * Tests that a bucket is marked invalid when a condition change pull fails.
2147  */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenOneConditionFailed)2148 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed) {
2149     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2150 
2151     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2152     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2153             // First onConditionChanged
2154             .WillOnce(Return(false))
2155             // Second onConditionChanged
2156             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2157                                 vector<std::shared_ptr<LogEvent>>* data) {
2158                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
2159                 data->clear();
2160                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
2161                 return true;
2162             }));
2163 
2164     sp<ValueMetricProducer> valueProducer =
2165             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2166                                                                             ConditionState::kTrue);
2167 
2168     // Bucket start.
2169     vector<shared_ptr<LogEvent>> allData;
2170     allData.clear();
2171     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
2172     valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
2173 
2174     // This will fail and should invalidate the whole bucket since we do not have all the data
2175     // needed to compute the metric value when the screen was on.
2176     valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2177     valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2178 
2179     // Bucket end.
2180     allData.clear();
2181     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
2182     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2183 
2184     valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2185 
2186     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
2187     // Contains base from last pull which was successful.
2188     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2189     ValueMetricProducer::Interval& curInterval =
2190             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2191     ValueMetricProducer::BaseInfo curBaseInfo =
2192             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2193     EXPECT_EQ(true, curBaseInfo.hasBase);
2194     EXPECT_EQ(140, curBaseInfo.base.long_value);
2195     EXPECT_EQ(false, curInterval.hasValue);
2196     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2197 
2198     // Check dump report.
2199     ProtoOutputStream output;
2200     std::set<string> strSet;
2201     valueProducer->onDumpReport(bucket2StartTimeNs + 10, false /* include partial bucket */, true,
2202                                 FAST /* dumpLatency */, &strSet, &output);
2203 
2204     StatsLogReport report = outputStreamToProto(&output);
2205     EXPECT_TRUE(report.has_value_metrics());
2206     ASSERT_EQ(0, report.value_metrics().data_size());
2207     ASSERT_EQ(1, report.value_metrics().skipped_size());
2208 
2209     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2210               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2211     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2212               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
2213     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
2214 
2215     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2216     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
2217     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
2218 }
2219 
2220 /*
2221  * Tests that a bucket is marked invalid when the guardrail is hit.
2222  */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenGuardRailHit)2223 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
2224     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2225     metric.mutable_dimensions_in_what()->set_field(tagId);
2226     metric.mutable_dimensions_in_what()->add_child()->set_field(1);
2227     metric.set_condition(StringToId("SCREEN_ON"));
2228 
2229     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2230     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 2, _))
2231             // First onConditionChanged
2232             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2233                                 vector<std::shared_ptr<LogEvent>>* data) {
2234                 for (int i = 0; i < 2000; i++) {
2235                     data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
2236                 }
2237                 return true;
2238             }));
2239 
2240     sp<ValueMetricProducer> valueProducer =
2241             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2242                                                                             ConditionState::kFalse);
2243 
2244     valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
2245     EXPECT_EQ(true, valueProducer->mCurrentBucketIsSkipped);
2246     ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2247     ASSERT_EQ(0UL, valueProducer->mSkippedBuckets.size());
2248 
2249     // Bucket 2 start.
2250     vector<shared_ptr<LogEvent>> allData;
2251     allData.clear();
2252     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 10));
2253     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2254 
2255     // First bucket added to mSkippedBuckets after flush.
2256     ASSERT_EQ(1UL, valueProducer->mSkippedBuckets.size());
2257 
2258     // Check dump report.
2259     ProtoOutputStream output;
2260     std::set<string> strSet;
2261     valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
2262                                 true, FAST /* dumpLatency */, &strSet, &output);
2263 
2264     StatsLogReport report = outputStreamToProto(&output);
2265     EXPECT_TRUE(report.has_value_metrics());
2266     ASSERT_EQ(0, report.value_metrics().data_size());
2267     ASSERT_EQ(1, report.value_metrics().skipped_size());
2268 
2269     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2270               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2271     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2272               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
2273     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
2274 
2275     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2276     EXPECT_EQ(BucketDropReason::DIMENSION_GUARDRAIL_REACHED, dropEvent.drop_reason());
2277     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
2278 }
2279 
2280 /*
2281  * Tests that a bucket is marked invalid when the bucket's initial pull fails.
2282  */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenInitialPullFailed)2283 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) {
2284     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2285 
2286     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2287     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2288             // First onConditionChanged
2289             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2290                                 vector<std::shared_ptr<LogEvent>>* data) {
2291                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 2);
2292                 data->clear();
2293                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
2294                 return true;
2295             }))
2296             // Second onConditionChanged
2297             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2298                                 vector<std::shared_ptr<LogEvent>>* data) {
2299                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
2300                 data->clear();
2301                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
2302                 return true;
2303             }));
2304 
2305     sp<ValueMetricProducer> valueProducer =
2306             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2307                                                                             ConditionState::kTrue);
2308 
2309     // Bucket start.
2310     vector<shared_ptr<LogEvent>> allData;
2311     allData.clear();
2312     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
2313     valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
2314 
2315     valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2316     valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2317 
2318     // Bucket end.
2319     allData.clear();
2320     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
2321     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2322 
2323     valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2324 
2325     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
2326     // Contains base from last pull which was successful.
2327     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2328     ValueMetricProducer::Interval& curInterval =
2329             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2330     ValueMetricProducer::BaseInfo curBaseInfo =
2331             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2332     EXPECT_EQ(true, curBaseInfo.hasBase);
2333     EXPECT_EQ(140, curBaseInfo.base.long_value);
2334     EXPECT_EQ(false, curInterval.hasValue);
2335     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2336 
2337     // Check dump report.
2338     ProtoOutputStream output;
2339     std::set<string> strSet;
2340     valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
2341                                 true, FAST /* dumpLatency */, &strSet, &output);
2342 
2343     StatsLogReport report = outputStreamToProto(&output);
2344     EXPECT_TRUE(report.has_value_metrics());
2345     ASSERT_EQ(0, report.value_metrics().data_size());
2346     ASSERT_EQ(1, report.value_metrics().skipped_size());
2347 
2348     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2349               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2350     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2351               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
2352     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
2353 
2354     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2355     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
2356     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
2357 }
2358 
2359 /*
2360  * Tests that a bucket is marked invalid when the bucket's final pull fails
2361  * (i.e. failed pull on bucket boundary).
2362  */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenLastPullFailed)2363 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
2364     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2365 
2366     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2367     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2368             // First onConditionChanged
2369             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2370                                 vector<std::shared_ptr<LogEvent>>* data) {
2371                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 2);
2372                 data->clear();
2373                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
2374                 return true;
2375             }))
2376             // Second onConditionChanged
2377             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2378                                 vector<std::shared_ptr<LogEvent>>* data) {
2379                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
2380                 data->clear();
2381                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
2382                 return true;
2383             }));
2384 
2385     sp<ValueMetricProducer> valueProducer =
2386             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2387                                                                             ConditionState::kTrue);
2388 
2389     // Bucket start.
2390     vector<shared_ptr<LogEvent>> allData;
2391     allData.clear();
2392     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
2393     valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
2394 
2395     valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
2396     valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
2397 
2398     // Bucket end.
2399     allData.clear();
2400     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
2401     valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
2402 
2403     valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
2404 
2405     ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
2406     // Last pull failed so base has been reset.
2407     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2408     ValueMetricProducer::Interval& curInterval =
2409             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2410     ValueMetricProducer::BaseInfo curBaseInfo =
2411             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2412     EXPECT_EQ(false, curBaseInfo.hasBase);
2413     EXPECT_EQ(false, curInterval.hasValue);
2414     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2415 
2416     // Check dump report.
2417     ProtoOutputStream output;
2418     std::set<string> strSet;
2419     valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
2420                                 true, FAST /* dumpLatency */, &strSet, &output);
2421 
2422     StatsLogReport report = outputStreamToProto(&output);
2423     EXPECT_TRUE(report.has_value_metrics());
2424     ASSERT_EQ(0, report.value_metrics().data_size());
2425     ASSERT_EQ(1, report.value_metrics().skipped_size());
2426 
2427     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
2428               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
2429     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
2430               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
2431     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
2432 
2433     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
2434     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
2435     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
2436 }
2437 
TEST(ValueMetricProducerTest,TestEmptyDataResetsBase_onDataPulled)2438 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
2439     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2440     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2441     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
2442             // Start bucket.
2443             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2444                                 vector<std::shared_ptr<LogEvent>>* data) {
2445                 data->clear();
2446                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
2447                 return true;
2448             }));
2449 
2450     sp<ValueMetricProducer> valueProducer =
2451             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2452 
2453     // Bucket 2 start.
2454     vector<shared_ptr<LogEvent>> allData;
2455     allData.clear();
2456     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
2457     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2458     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2459     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
2460 
2461     // Bucket 3 empty.
2462     allData.clear();
2463     allData.push_back(CreateNoValuesLogEvent(tagId, bucket3StartTimeNs + 1));
2464     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
2465     // Data has been trimmed.
2466     ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2467     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
2468 }
2469 
TEST(ValueMetricProducerTest,TestEmptyDataResetsBase_onConditionChanged)2470 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
2471     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2472 
2473     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2474     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2475             // First onConditionChanged
2476             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2477                                 vector<std::shared_ptr<LogEvent>>* data) {
2478                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
2479                 data->clear();
2480                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
2481                 return true;
2482             }))
2483             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2484                                 vector<std::shared_ptr<LogEvent>>* data) {
2485                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
2486                 data->clear();
2487                 return true;
2488             }));
2489 
2490     sp<ValueMetricProducer> valueProducer =
2491             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2492                                                                             ConditionState::kFalse);
2493 
2494     valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
2495     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2496     ValueMetricProducer::Interval& curInterval =
2497             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2498     ValueMetricProducer::BaseInfo curBaseInfo =
2499             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2500     EXPECT_EQ(true, curBaseInfo.hasBase);
2501     EXPECT_EQ(false, curInterval.hasValue);
2502     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2503 
2504     // Empty pull.
2505     valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
2506     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2507     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2508     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2509     EXPECT_EQ(false, curBaseInfo.hasBase);
2510     EXPECT_EQ(false, curInterval.hasValue);
2511     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
2512 }
2513 
TEST(ValueMetricProducerTest,TestEmptyDataResetsBase_onBucketBoundary)2514 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
2515     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2516 
2517     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2518     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2519             // First onConditionChanged
2520             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2521                                 vector<std::shared_ptr<LogEvent>>* data) {
2522                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
2523                 data->clear();
2524                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2525                 return true;
2526             }))
2527             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2528                                 vector<std::shared_ptr<LogEvent>>* data) {
2529                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 11);
2530                 data->clear();
2531                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
2532                 return true;
2533             }))
2534             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2535                                 vector<std::shared_ptr<LogEvent>>* data) {
2536                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 12);
2537                 data->clear();
2538                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
2539                 return true;
2540             }));
2541 
2542     sp<ValueMetricProducer> valueProducer =
2543             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2544                                                                             ConditionState::kFalse);
2545 
2546     valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
2547     valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
2548     valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
2549     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2550     ValueMetricProducer::Interval& curInterval =
2551             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2552     ValueMetricProducer::BaseInfo curBaseInfo =
2553             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2554     EXPECT_EQ(true, curBaseInfo.hasBase);
2555     EXPECT_EQ(true, curInterval.hasValue);
2556     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2557 
2558     // End of bucket
2559     vector<shared_ptr<LogEvent>> allData;
2560     allData.clear();
2561     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2562     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2563     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2564     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2565     // Data is empty, base should be reset.
2566     EXPECT_EQ(false, curBaseInfo.hasBase);
2567     EXPECT_EQ(5, curBaseInfo.base.long_value);
2568     EXPECT_EQ(false, curInterval.hasValue);
2569     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2570 
2571     ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
2572     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1},
2573                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
2574 }
2575 
TEST(ValueMetricProducerTest,TestPartialResetOnBucketBoundaries)2576 TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
2577     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2578     metric.mutable_dimensions_in_what()->set_field(tagId);
2579     metric.mutable_dimensions_in_what()->add_child()->set_field(1);
2580     metric.set_condition(StringToId("SCREEN_ON"));
2581 
2582     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2583     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _))
2584             // First onConditionChanged
2585             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2586                                 vector<std::shared_ptr<LogEvent>>* data) {
2587                 data->clear();
2588                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2589                 return true;
2590             }));
2591 
2592     sp<ValueMetricProducer> valueProducer =
2593             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2594                                                                             ConditionState::kFalse);
2595 
2596     valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
2597     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2598 
2599     // End of bucket
2600     vector<shared_ptr<LogEvent>> allData;
2601     allData.clear();
2602     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 2));
2603     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2604 
2605     // Key 1 should be reset since in not present in the most pull.
2606     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
2607     auto iterator = valueProducer->mCurrentSlicedBucket.begin();
2608     auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
2609     EXPECT_EQ(true, baseInfoIter->second.baseInfos[0].hasBase);
2610     EXPECT_EQ(2, baseInfoIter->second.baseInfos[0].base.long_value);
2611     EXPECT_EQ(false, iterator->second.intervals[0].hasValue);
2612     iterator++;
2613     baseInfoIter++;
2614     EXPECT_EQ(false, baseInfoIter->second.baseInfos[0].hasBase);
2615     EXPECT_EQ(1, baseInfoIter->second.baseInfos[0].base.long_value);
2616     EXPECT_EQ(false, iterator->second.intervals[0].hasValue);
2617 
2618     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
2619 }
2620 
TEST_P(ValueMetricProducerTest_PartialBucket,TestFullBucketResetWhenLastBucketInvalid)2621 TEST_P(ValueMetricProducerTest_PartialBucket, TestFullBucketResetWhenLastBucketInvalid) {
2622     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2623 
2624     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2625     int64_t partialBucketSplitTimeNs = bucketStartTimeNs + bucketSizeNs / 2;
2626     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2627             // Initialization.
2628             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2629                                 vector<std::shared_ptr<LogEvent>>* data) {
2630                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
2631                 data->clear();
2632                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2633                 return true;
2634             }))
2635             // notifyAppUpgrade.
2636             .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
2637                                                         const int64_t eventTimeNs,
2638                                                         vector<std::shared_ptr<LogEvent>>* data) {
2639                 EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
2640                 data->clear();
2641                 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10));
2642                 return true;
2643             }));
2644     sp<ValueMetricProducer> valueProducer =
2645             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2646     ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
2647 
2648     switch (GetParam()) {
2649         case APP_UPGRADE:
2650             valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
2651             break;
2652         case BOOT_COMPLETE:
2653             valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
2654             break;
2655     }
2656     EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mCurrentBucketStartTimeNs);
2657     EXPECT_EQ(0, valueProducer->getCurrentBucketNum());
2658     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9},
2659                                     {partialBucketSplitTimeNs - bucketStartTimeNs},
2660                                     {bucketStartTimeNs}, {partialBucketSplitTimeNs});
2661     ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
2662 
2663     vector<shared_ptr<LogEvent>> allData;
2664     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 4));
2665     // Pull fails and arrives late.
2666     valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
2667     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9},
2668                                     {partialBucketSplitTimeNs - bucketStartTimeNs},
2669                                     {bucketStartTimeNs}, {partialBucketSplitTimeNs});
2670     ASSERT_EQ(1, valueProducer->mSkippedBuckets.size());
2671     ASSERT_EQ(2, valueProducer->mSkippedBuckets[0].dropEvents.size());
2672     EXPECT_EQ(PULL_FAILED, valueProducer->mSkippedBuckets[0].dropEvents[0].reason);
2673     EXPECT_EQ(MULTIPLE_BUCKETS_SKIPPED, valueProducer->mSkippedBuckets[0].dropEvents[1].reason);
2674     EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mSkippedBuckets[0].bucketStartTimeNs);
2675     EXPECT_EQ(bucket3StartTimeNs, valueProducer->mSkippedBuckets[0].bucketEndTimeNs);
2676     ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
2677 }
2678 
TEST(ValueMetricProducerTest,TestBucketBoundariesOnConditionChange)2679 TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
2680     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2681     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2682     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2683             // Second onConditionChanged.
2684             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2685                                 vector<std::shared_ptr<LogEvent>>* data) {
2686                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
2687                 data->clear();
2688                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
2689                 return true;
2690             }))
2691             // Third onConditionChanged.
2692             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2693                                 vector<std::shared_ptr<LogEvent>>* data) {
2694                 EXPECT_EQ(eventTimeNs, bucket3StartTimeNs + 10);
2695                 data->clear();
2696                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 10, 7));
2697                 return true;
2698             }));
2699 
2700     sp<ValueMetricProducer> valueProducer =
2701             ValueMetricProducerTestHelper::createValueProducerWithCondition(
2702                     pullerManager, metric, ConditionState::kUnknown);
2703 
2704     valueProducer->onConditionChanged(false, bucketStartTimeNs);
2705     ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2706 
2707     // End of first bucket
2708     vector<shared_ptr<LogEvent>> allData;
2709     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 4));
2710     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
2711     ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
2712 
2713     valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2714     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2715     auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2716     auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2717     EXPECT_EQ(true, curBaseInfo.hasBase);
2718     EXPECT_EQ(5, curBaseInfo.base.long_value);
2719     EXPECT_EQ(false, curInterval.hasValue);
2720 
2721     valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
2722 
2723     // Bucket should have been completed.
2724     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10},
2725                                     {bucket2StartTimeNs}, {bucket3StartTimeNs});
2726 }
2727 
TEST(ValueMetricProducerTest,TestLateOnDataPulledWithoutDiff)2728 TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
2729     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2730     metric.set_use_diff(false);
2731 
2732     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2733     sp<ValueMetricProducer> valueProducer =
2734             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2735 
2736     vector<shared_ptr<LogEvent>> allData;
2737     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
2738     valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
2739 
2740     allData.clear();
2741     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
2742     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2743 
2744     // Bucket should have been completed.
2745     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs},
2746                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
2747 }
2748 
TEST(ValueMetricProducerTest,TestLateOnDataPulledWithDiff)2749 TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
2750     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2751 
2752     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2753     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
2754             // Initialization.
2755             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2756                                 vector<std::shared_ptr<LogEvent>>* data) {
2757                 data->clear();
2758                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2759                 return true;
2760             }));
2761 
2762     sp<ValueMetricProducer> valueProducer =
2763             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2764 
2765     vector<shared_ptr<LogEvent>> allData;
2766     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
2767     valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
2768 
2769     allData.clear();
2770     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
2771     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2772 
2773     // Bucket should have been completed.
2774     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs},
2775                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
2776 }
2777 
TEST_P(ValueMetricProducerTest_PartialBucket,TestBucketBoundariesOnPartialBucket)2778 TEST_P(ValueMetricProducerTest_PartialBucket, TestBucketBoundariesOnPartialBucket) {
2779     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2780 
2781     int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2;
2782     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2783     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2784             // Initialization.
2785             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2786                                 vector<std::shared_ptr<LogEvent>>* data) {
2787                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
2788                 data->clear();
2789                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2790                 return true;
2791             }))
2792             // notifyAppUpgrade.
2793             .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
2794                                                         const int64_t eventTimeNs,
2795                                                         vector<std::shared_ptr<LogEvent>>* data) {
2796                 EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
2797                 data->clear();
2798                 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10));
2799                 return true;
2800             }));
2801 
2802     sp<ValueMetricProducer> valueProducer =
2803             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
2804 
2805     switch (GetParam()) {
2806         case APP_UPGRADE:
2807             valueProducer->notifyAppUpgrade(partialBucketSplitTimeNs);
2808             break;
2809         case BOOT_COMPLETE:
2810             valueProducer->onStatsdInitCompleted(partialBucketSplitTimeNs);
2811             break;
2812     }
2813 
2814     // Bucket should have been completed.
2815     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs},
2816                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
2817 }
2818 
TEST(ValueMetricProducerTest,TestDataIsNotUpdatedWhenNoConditionChanged)2819 TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
2820     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2821 
2822     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2823     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2824             // First on condition changed.
2825             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2826                                 vector<std::shared_ptr<LogEvent>>* data) {
2827                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
2828                 data->clear();
2829                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2830                 return true;
2831             }))
2832             // Second on condition changed.
2833             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2834                                 vector<std::shared_ptr<LogEvent>>* data) {
2835                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
2836                 data->clear();
2837                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
2838                 return true;
2839             }));
2840 
2841     sp<ValueMetricProducer> valueProducer =
2842             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2843                                                                             ConditionState::kFalse);
2844 
2845     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
2846     valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
2847     valueProducer->onConditionChanged(false, bucketStartTimeNs + 12);
2848 
2849     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
2850     auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
2851     auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
2852     EXPECT_EQ(true, curInterval.hasValue);
2853     EXPECT_EQ(2, curInterval.value.long_value);
2854 
2855     vector<shared_ptr<LogEvent>> allData;
2856     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 10));
2857     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
2858 
2859     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2}, {bucketStartTimeNs},
2860                                     {bucket2StartTimeNs});
2861 }
2862 
2863 // TODO: b/145705635 fix or delete this test
TEST(ValueMetricProducerTest,TestBucketInvalidIfGlobalBaseIsNotSet)2864 TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
2865     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
2866 
2867     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2868     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
2869             // First condition change.
2870             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2871                                 vector<std::shared_ptr<LogEvent>>* data) {
2872                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
2873                 data->clear();
2874                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
2875                 return true;
2876             }))
2877             // 2nd condition change.
2878             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2879                                 vector<std::shared_ptr<LogEvent>>* data) {
2880                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 8);
2881                 data->clear();
2882                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
2883                 return true;
2884             }))
2885             // 3rd condition change.
2886             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
2887                                 vector<std::shared_ptr<LogEvent>>* data) {
2888                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
2889                 data->clear();
2890                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
2891                 return true;
2892             }));
2893 
2894     sp<ValueMetricProducer> valueProducer =
2895             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
2896                                                                             ConditionState::kFalse);
2897     valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2898 
2899     vector<shared_ptr<LogEvent>> allData;
2900     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 3, 10));
2901     valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
2902 
2903     allData.clear();
2904     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
2905     valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
2906 
2907     valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
2908     valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
2909 
2910     allData.clear();
2911     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 30));
2912     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2913 
2914     // There was not global base available so all buckets are invalid.
2915     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {});
2916 }
2917 
TEST(ValueMetricProducerTest,TestPullNeededFastDump)2918 TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
2919     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2920 
2921     sp<EventMatcherWizard> eventMatcherWizard =
2922             createEventMatcherWizard(tagId, logEventMatcherIndex);
2923     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2924     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2925     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
2926     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
2927 
2928     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
2929             // Initial pull.
2930             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2931                                 vector<std::shared_ptr<LogEvent>>* data) {
2932                 data->clear();
2933                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
2934                 return true;
2935             }));
2936 
2937     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
2938                                       logEventMatcherIndex, eventMatcherWizard, tagId,
2939                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
2940     valueProducer.prepareFirstBucket();
2941 
2942     ProtoOutputStream output;
2943     std::set<string> strSet;
2944     valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
2945                                FAST, &strSet, &output);
2946 
2947     StatsLogReport report = outputStreamToProto(&output);
2948     // Bucket is invalid since we did not pull when dump report was called.
2949     ASSERT_EQ(0, report.value_metrics().data_size());
2950 }
2951 
TEST(ValueMetricProducerTest,TestFastDumpWithoutCurrentBucket)2952 TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
2953     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2954 
2955     sp<EventMatcherWizard> eventMatcherWizard =
2956             createEventMatcherWizard(tagId, logEventMatcherIndex);
2957     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2958     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2959     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
2960     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
2961 
2962     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
2963             // Initial pull.
2964             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
2965                                 vector<std::shared_ptr<LogEvent>>* data) {
2966                 data->clear();
2967                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
2968                 return true;
2969             }));
2970 
2971     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
2972                                       logEventMatcherIndex, eventMatcherWizard, tagId,
2973                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
2974     valueProducer.prepareFirstBucket();
2975 
2976     vector<shared_ptr<LogEvent>> allData;
2977     allData.clear();
2978     allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, tagId, 2, 2));
2979     valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
2980 
2981     ProtoOutputStream output;
2982     std::set<string> strSet;
2983     valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
2984                                &strSet, &output);
2985 
2986     StatsLogReport report = outputStreamToProto(&output);
2987     // Previous bucket is part of the report.
2988     ASSERT_EQ(1, report.value_metrics().data_size());
2989     EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
2990 }
2991 
TEST(ValueMetricProducerTest,TestPullNeededNoTimeConstraints)2992 TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
2993     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
2994 
2995     sp<EventMatcherWizard> eventMatcherWizard =
2996             createEventMatcherWizard(tagId, logEventMatcherIndex);
2997     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
2998     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
2999     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
3000     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
3001 
3002     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3003             // Initial pull.
3004             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3005                                 vector<std::shared_ptr<LogEvent>>* data) {
3006                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
3007                 data->clear();
3008                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
3009                 return true;
3010             }))
3011             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3012                                 vector<std::shared_ptr<LogEvent>>* data) {
3013                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
3014                 data->clear();
3015                 data->push_back(
3016                         CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10, tagId, 3, 3));
3017                 return true;
3018             }));
3019 
3020     ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
3021                                       logEventMatcherIndex, eventMatcherWizard, tagId,
3022                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
3023     valueProducer.prepareFirstBucket();
3024 
3025     ProtoOutputStream output;
3026     std::set<string> strSet;
3027     valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
3028                                NO_TIME_CONSTRAINTS, &strSet, &output);
3029 
3030     StatsLogReport report = outputStreamToProto(&output);
3031     ASSERT_EQ(1, report.value_metrics().data_size());
3032     ASSERT_EQ(1, report.value_metrics().data(0).bucket_info_size());
3033     EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
3034 }
3035 
TEST(ValueMetricProducerTest,TestPulledData_noDiff_withoutCondition)3036 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
3037     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
3038     metric.set_use_diff(false);
3039 
3040     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3041     sp<ValueMetricProducer> valueProducer =
3042             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
3043 
3044     vector<shared_ptr<LogEvent>> allData;
3045     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 10));
3046     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
3047 
3048     // Bucket should have been completed.
3049     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs},
3050                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
3051 }
3052 
TEST(ValueMetricProducerTest,TestPulledData_noDiff_withMultipleConditionChanges)3053 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) {
3054     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3055     metric.set_use_diff(false);
3056 
3057     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3058     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3059             // condition becomes true
3060             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3061                                 vector<std::shared_ptr<LogEvent>>* data) {
3062                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
3063                 data->clear();
3064                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
3065                 return true;
3066             }))
3067             // condition becomes false
3068             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3069                                 vector<std::shared_ptr<LogEvent>>* data) {
3070                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
3071                 data->clear();
3072                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 20));
3073                 return true;
3074             }));
3075     sp<ValueMetricProducer> valueProducer =
3076             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3077                                                                             ConditionState::kFalse);
3078 
3079     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3080     valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
3081     // has one slice
3082     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
3083     ValueMetricProducer::Interval curInterval =
3084             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
3085     ValueMetricProducer::BaseInfo curBaseInfo =
3086             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
3087     EXPECT_EQ(false, curBaseInfo.hasBase);
3088     EXPECT_EQ(true, curInterval.hasValue);
3089     EXPECT_EQ(20, curInterval.value.long_value);
3090 
3091     // Now the alarm is delivered. Condition is off though.
3092     vector<shared_ptr<LogEvent>> allData;
3093     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 110));
3094     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3095 
3096     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8},
3097                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
3098     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
3099     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
3100     EXPECT_EQ(false, curBaseInfo.hasBase);
3101     EXPECT_EQ(false, curInterval.hasValue);
3102 }
3103 
TEST(ValueMetricProducerTest,TestPulledData_noDiff_bucketBoundaryTrue)3104 TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
3105     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3106     metric.set_use_diff(false);
3107 
3108     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3109     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _))
3110             // condition becomes true
3111             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
3112                                 vector<std::shared_ptr<LogEvent>>* data) {
3113                 data->clear();
3114                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
3115                 return true;
3116             }));
3117     sp<ValueMetricProducer> valueProducer =
3118             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3119                                                                             ConditionState::kFalse);
3120 
3121     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3122 
3123     // Now the alarm is delivered. Condition is off though.
3124     vector<shared_ptr<LogEvent>> allData;
3125     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
3126     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3127 
3128     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8},
3129                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
3130     ValueMetricProducer::Interval curInterval =
3131             valueProducer->mCurrentSlicedBucket.begin()->second.intervals[0];
3132     ValueMetricProducer::BaseInfo curBaseInfo =
3133             valueProducer->mCurrentBaseInfo.begin()->second.baseInfos[0];
3134     EXPECT_EQ(false, curBaseInfo.hasBase);
3135     EXPECT_EQ(false, curInterval.hasValue);
3136 }
3137 
TEST(ValueMetricProducerTest,TestPulledData_noDiff_bucketBoundaryFalse)3138 TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) {
3139     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3140     metric.set_use_diff(false);
3141 
3142     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3143     sp<ValueMetricProducer> valueProducer =
3144             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3145                                                                             ConditionState::kFalse);
3146 
3147     // Now the alarm is delivered. Condition is off though.
3148     vector<shared_ptr<LogEvent>> allData;
3149     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
3150     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3151 
3152     // Condition was always false.
3153     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {});
3154 }
3155 
TEST(ValueMetricProducerTest,TestPulledData_noDiff_withFailure)3156 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
3157     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3158     metric.set_use_diff(false);
3159 
3160     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3161     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3162             // condition becomes true
3163             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3164                                 vector<std::shared_ptr<LogEvent>>* data) {
3165                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
3166                 data->clear();
3167                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
3168                 return true;
3169             }))
3170             .WillOnce(Return(false));
3171     sp<ValueMetricProducer> valueProducer =
3172             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3173                                                                             ConditionState::kFalse);
3174 
3175     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
3176     valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
3177 
3178     // Now the alarm is delivered. Condition is off though.
3179     vector<shared_ptr<LogEvent>> allData;
3180     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
3181     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3182 
3183     // No buckets, we had a failure.
3184     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {});
3185 }
3186 
3187 /*
3188  * Test that DUMP_REPORT_REQUESTED dump reason is logged.
3189  *
3190  * For the bucket to be marked invalid during a dump report requested,
3191  * three things must be true:
3192  * - we want to include the current partial bucket
3193  * - we need a pull (metric is pulled and condition is true)
3194  * - the dump latency must be FAST
3195  */
3196 
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenDumpReportRequested)3197 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequested) {
3198     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3199 
3200     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3201     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 20, _))
3202             // Condition change to true.
3203             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
3204                                 vector<std::shared_ptr<LogEvent>>* data) {
3205                 data->clear();
3206                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 10));
3207                 return true;
3208             }));
3209 
3210     sp<ValueMetricProducer> valueProducer =
3211             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3212                                                                             ConditionState::kFalse);
3213 
3214     // Condition change event.
3215     valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
3216 
3217     // Check dump report.
3218     ProtoOutputStream output;
3219     std::set<string> strSet;
3220     valueProducer->onDumpReport(bucketStartTimeNs + 40, true /* include recent buckets */, true,
3221                                 FAST /* dumpLatency */, &strSet, &output);
3222 
3223     StatsLogReport report = outputStreamToProto(&output);
3224     EXPECT_TRUE(report.has_value_metrics());
3225     ASSERT_EQ(0, report.value_metrics().data_size());
3226     ASSERT_EQ(1, report.value_metrics().skipped_size());
3227 
3228     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3229               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3230     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40),
3231               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3232     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3233 
3234     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3235     EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
3236     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40), dropEvent.drop_time_millis());
3237 }
3238 
3239 /*
3240  * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late condition
3241  * change event (i.e. the condition change occurs in the wrong bucket).
3242  */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenConditionEventWrongBucket)3243 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWrongBucket) {
3244     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3245 
3246     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3247     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 50, _))
3248             // Condition change to true.
3249             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
3250                                 vector<std::shared_ptr<LogEvent>>* data) {
3251                 data->clear();
3252                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3253                 return true;
3254             }));
3255 
3256     sp<ValueMetricProducer> valueProducer =
3257             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3258                                                                             ConditionState::kFalse);
3259 
3260     // Condition change event.
3261     valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3262 
3263     // Bucket boundary pull.
3264     vector<shared_ptr<LogEvent>> allData;
3265     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 15));
3266     valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
3267 
3268     // Late condition change event.
3269     valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
3270 
3271     // Check dump report.
3272     ProtoOutputStream output;
3273     std::set<string> strSet;
3274     valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
3275                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3276 
3277     StatsLogReport report = outputStreamToProto(&output);
3278     EXPECT_TRUE(report.has_value_metrics());
3279     ASSERT_EQ(1, report.value_metrics().data_size());
3280     ASSERT_EQ(1, report.value_metrics().skipped_size());
3281 
3282     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3283               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3284     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
3285               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3286     ASSERT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
3287 
3288     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3289     EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
3290     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
3291 
3292     dropEvent = report.value_metrics().skipped(0).drop_event(1);
3293     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3294     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100), dropEvent.drop_time_millis());
3295 }
3296 
3297 /*
3298  * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late accumulate
3299  * event (i.e. the accumulate events call occurs in the wrong bucket).
3300  */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenAccumulateEventWrongBucket)3301 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWrongBucket) {
3302     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3303 
3304     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3305     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3306             // Condition change to true.
3307             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3308                                 vector<std::shared_ptr<LogEvent>>* data) {
3309                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
3310                 data->clear();
3311                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3312                 return true;
3313             }))
3314             // Dump report requested.
3315             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3316                                 vector<std::shared_ptr<LogEvent>>* data) {
3317                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 100);
3318                 data->clear();
3319                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 100, 15));
3320                 return true;
3321             }));
3322 
3323     sp<ValueMetricProducer> valueProducer =
3324             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3325                                                                             ConditionState::kFalse);
3326 
3327     // Condition change event.
3328     valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3329 
3330     // Bucket boundary pull.
3331     vector<shared_ptr<LogEvent>> allData;
3332     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 15));
3333     valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
3334 
3335     allData.clear();
3336     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 20));
3337 
3338     // Late accumulateEvents event.
3339     valueProducer->accumulateEvents(allData, bucket2StartTimeNs - 100, bucket2StartTimeNs - 100);
3340 
3341     // Check dump report.
3342     ProtoOutputStream output;
3343     std::set<string> strSet;
3344     valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
3345                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3346 
3347     StatsLogReport report = outputStreamToProto(&output);
3348     EXPECT_TRUE(report.has_value_metrics());
3349     ASSERT_EQ(1, report.value_metrics().data_size());
3350     ASSERT_EQ(1, report.value_metrics().skipped_size());
3351 
3352     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3353               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3354     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
3355               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3356     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3357 
3358     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3359     EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
3360     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
3361 }
3362 
3363 /*
3364  * Test that CONDITION_UNKNOWN dump reason is logged due to an unknown condition
3365  * when a metric is initialized.
3366  */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenConditionUnknown)3367 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) {
3368     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3369 
3370     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3371     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3372             // Condition change to true.
3373             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3374                                 vector<std::shared_ptr<LogEvent>>* data) {
3375                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
3376                 data->clear();
3377                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3378                 return true;
3379             }))
3380             // Dump report requested.
3381             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3382                                 vector<std::shared_ptr<LogEvent>>* data) {
3383                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10000);
3384                 data->clear();
3385                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 100, 15));
3386                 return true;
3387             }));
3388 
3389     sp<ValueMetricProducer> valueProducer =
3390             ValueMetricProducerTestHelper::createValueProducerWithCondition(
3391                     pullerManager, metric, ConditionState::kUnknown);
3392 
3393     // Condition change event.
3394     valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3395 
3396     // Check dump report.
3397     ProtoOutputStream output;
3398     std::set<string> strSet;
3399     int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
3400     valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3401                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3402 
3403     StatsLogReport report = outputStreamToProto(&output);
3404     EXPECT_TRUE(report.has_value_metrics());
3405     ASSERT_EQ(0, report.value_metrics().data_size());
3406     ASSERT_EQ(1, report.value_metrics().skipped_size());
3407 
3408     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3409               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3410     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3411               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3412     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3413 
3414     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3415     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3416     EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3417 }
3418 
3419 /*
3420  * Test that PULL_FAILED dump reason is logged due to a pull failure in
3421  * #pullAndMatchEventsLocked.
3422  */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenPullFailed)3423 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
3424     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3425 
3426     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3427     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3428             // Condition change to true.
3429             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3430                                 vector<std::shared_ptr<LogEvent>>* data) {
3431                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
3432                 data->clear();
3433                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
3434                 return true;
3435             }))
3436             // Dump report requested, pull fails.
3437             .WillOnce(Return(false));
3438 
3439     sp<ValueMetricProducer> valueProducer =
3440             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3441                                                                             ConditionState::kFalse);
3442 
3443     // Condition change event.
3444     valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3445 
3446     // Check dump report.
3447     ProtoOutputStream output;
3448     std::set<string> strSet;
3449     int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
3450     valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3451                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3452 
3453     StatsLogReport report = outputStreamToProto(&output);
3454     EXPECT_TRUE(report.has_value_metrics());
3455     ASSERT_EQ(0, report.value_metrics().data_size());
3456     ASSERT_EQ(1, report.value_metrics().skipped_size());
3457 
3458     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3459               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3460     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3461               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3462     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3463 
3464     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3465     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3466     EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3467 }
3468 
3469 /*
3470  * Test that MULTIPLE_BUCKETS_SKIPPED dump reason is logged when a log event
3471  * skips over more than one bucket.
3472  */
TEST(ValueMetricProducerTest_BucketDrop,TestInvalidBucketWhenMultipleBucketsSkipped)3473 TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSkipped) {
3474     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3475 
3476     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3477     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3478             // Condition change to true.
3479             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3480                                 vector<std::shared_ptr<LogEvent>>* data) {
3481                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
3482                 data->clear();
3483                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3484                 return true;
3485             }))
3486             // Dump report requested.
3487             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3488                                 vector<std::shared_ptr<LogEvent>>* data) {
3489                 EXPECT_EQ(eventTimeNs, bucket4StartTimeNs + 10);
3490                 data->clear();
3491                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1000, 15));
3492                 return true;
3493             }));
3494 
3495     sp<ValueMetricProducer> valueProducer =
3496             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3497                                                                             ConditionState::kFalse);
3498 
3499     // Condition change event.
3500     valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3501 
3502     // Condition change event that skips forward by three buckets.
3503     valueProducer->onConditionChanged(false, bucket4StartTimeNs + 10);
3504 
3505     int64_t dumpTimeNs = bucket4StartTimeNs + 1000;
3506 
3507     // Check dump report.
3508     ProtoOutputStream output;
3509     std::set<string> strSet;
3510     valueProducer->onDumpReport(dumpTimeNs, true /* include current buckets */, true,
3511                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3512 
3513     StatsLogReport report = outputStreamToProto(&output);
3514     EXPECT_TRUE(report.has_value_metrics());
3515     ASSERT_EQ(0, report.value_metrics().data_size());
3516     ASSERT_EQ(2, report.value_metrics().skipped_size());
3517 
3518     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3519               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3520     EXPECT_EQ(NanoToMillis(bucket4StartTimeNs),
3521               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3522     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3523 
3524     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3525     EXPECT_EQ(BucketDropReason::MULTIPLE_BUCKETS_SKIPPED, dropEvent.drop_reason());
3526     EXPECT_EQ(NanoToMillis(bucket4StartTimeNs + 10), dropEvent.drop_time_millis());
3527 
3528     // This bucket is skipped because a dumpReport with include current buckets is called.
3529     // This creates a new bucket from bucket4StartTimeNs to dumpTimeNs in which we have no data
3530     // since the condition is false for the entire bucket interval.
3531     EXPECT_EQ(NanoToMillis(bucket4StartTimeNs),
3532               report.value_metrics().skipped(1).start_bucket_elapsed_millis());
3533     EXPECT_EQ(NanoToMillis(dumpTimeNs),
3534               report.value_metrics().skipped(1).end_bucket_elapsed_millis());
3535     ASSERT_EQ(1, report.value_metrics().skipped(1).drop_event_size());
3536 
3537     dropEvent = report.value_metrics().skipped(1).drop_event(0);
3538     EXPECT_EQ(BucketDropReason::NO_DATA, dropEvent.drop_reason());
3539     EXPECT_EQ(NanoToMillis(dumpTimeNs), dropEvent.drop_time_millis());
3540 }
3541 
3542 /*
3543  * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
3544  * is smaller than the "min_bucket_size_nanos" specified in the metric config.
3545  */
TEST(ValueMetricProducerTest_BucketDrop,TestBucketDropWhenBucketTooSmall)3546 TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
3547     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3548     metric.set_min_bucket_size_nanos(10000000000);  // 10 seconds
3549 
3550     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3551     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3552             // Condition change to true.
3553             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3554                                 vector<std::shared_ptr<LogEvent>>* data) {
3555                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
3556                 data->clear();
3557                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3558                 return true;
3559             }))
3560             // Dump report requested.
3561             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3562                                 vector<std::shared_ptr<LogEvent>>* data) {
3563                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 9000000);
3564                 data->clear();
3565                 data->push_back(
3566                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 9000000, 15));
3567                 return true;
3568             }));
3569 
3570     sp<ValueMetricProducer> valueProducer =
3571             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3572                                                                             ConditionState::kFalse);
3573 
3574     // Condition change event.
3575     valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3576 
3577     // Check dump report.
3578     ProtoOutputStream output;
3579     std::set<string> strSet;
3580     int64_t dumpReportTimeNs = bucketStartTimeNs + 9000000;
3581     valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3582                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3583 
3584     StatsLogReport report = outputStreamToProto(&output);
3585     EXPECT_TRUE(report.has_value_metrics());
3586     ASSERT_EQ(0, report.value_metrics().data_size());
3587     ASSERT_EQ(1, report.value_metrics().skipped_size());
3588 
3589     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3590               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3591     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3592               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3593     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3594 
3595     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3596     EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
3597     EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3598 }
3599 
3600 /*
3601  * Test that NO_DATA dump reason is logged when a flushed bucket contains no data.
3602  */
TEST(ValueMetricProducerTest_BucketDrop,TestBucketDropWhenDataUnavailable)3603 TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenDataUnavailable) {
3604     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3605 
3606     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3607 
3608     sp<ValueMetricProducer> valueProducer =
3609             ValueMetricProducerTestHelper::createValueProducerWithCondition(
3610                     pullerManager, metric, ConditionState::kFalse);
3611 
3612     // Check dump report.
3613     ProtoOutputStream output;
3614     std::set<string> strSet;
3615     int64_t dumpReportTimeNs = bucketStartTimeNs + 10000000000; // 10 seconds
3616     valueProducer->onDumpReport(dumpReportTimeNs, true /* include current bucket */, true,
3617                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3618 
3619     StatsLogReport report = outputStreamToProto(&output);
3620     EXPECT_TRUE(report.has_value_metrics());
3621     ASSERT_EQ(0, report.value_metrics().data_size());
3622     ASSERT_EQ(1, report.value_metrics().skipped_size());
3623 
3624     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3625               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3626     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3627               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3628     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3629 
3630     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3631     EXPECT_EQ(BucketDropReason::NO_DATA, dropEvent.drop_reason());
3632     EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3633 }
3634 
3635 /*
3636  * Test that all buckets are dropped due to condition unknown until the first onConditionChanged.
3637  */
TEST(ValueMetricProducerTest_BucketDrop,TestConditionUnknownMultipleBuckets)3638 TEST(ValueMetricProducerTest_BucketDrop, TestConditionUnknownMultipleBuckets) {
3639     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3640 
3641     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3642     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3643             // Condition change to true.
3644             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3645                                 vector<std::shared_ptr<LogEvent>>* data) {
3646                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10 * NS_PER_SEC);
3647                 data->clear();
3648                 data->push_back(CreateRepeatedValueLogEvent(
3649                         tagId, bucket2StartTimeNs + 10 * NS_PER_SEC, 10));
3650                 return true;
3651             }))
3652             // Dump report requested.
3653             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3654                                 vector<std::shared_ptr<LogEvent>>* data) {
3655                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 15 * NS_PER_SEC);
3656                 data->clear();
3657                 data->push_back(CreateRepeatedValueLogEvent(
3658                         tagId, bucket2StartTimeNs + 15 * NS_PER_SEC, 15));
3659                 return true;
3660             }));
3661 
3662     sp<ValueMetricProducer> valueProducer =
3663             ValueMetricProducerTestHelper::createValueProducerWithCondition(
3664                     pullerManager, metric, ConditionState::kUnknown);
3665 
3666     // Bucket should be dropped because of condition unknown.
3667     int64_t appUpgradeTimeNs = bucketStartTimeNs + 5 * NS_PER_SEC;
3668     valueProducer->notifyAppUpgrade(appUpgradeTimeNs);
3669 
3670     // Bucket also dropped due to condition unknown
3671     vector<shared_ptr<LogEvent>> allData;
3672     allData.clear();
3673     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 3));
3674     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
3675 
3676     // This bucket is also dropped due to condition unknown.
3677     int64_t conditionChangeTimeNs = bucket2StartTimeNs + 10 * NS_PER_SEC;
3678     valueProducer->onConditionChanged(true, conditionChangeTimeNs);
3679 
3680     // Check dump report.
3681     ProtoOutputStream output;
3682     std::set<string> strSet;
3683     int64_t dumpReportTimeNs = bucket2StartTimeNs + 15 * NS_PER_SEC; // 15 seconds
3684     valueProducer->onDumpReport(dumpReportTimeNs, true /* include current bucket */, true,
3685                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3686 
3687     StatsLogReport report = outputStreamToProto(&output);
3688     EXPECT_TRUE(report.has_value_metrics());
3689     ASSERT_EQ(0, report.value_metrics().data_size());
3690     ASSERT_EQ(3, report.value_metrics().skipped_size());
3691 
3692     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3693               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3694     EXPECT_EQ(NanoToMillis(appUpgradeTimeNs),
3695               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3696     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3697 
3698     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3699     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3700     EXPECT_EQ(NanoToMillis(appUpgradeTimeNs), dropEvent.drop_time_millis());
3701 
3702     EXPECT_EQ(NanoToMillis(appUpgradeTimeNs),
3703               report.value_metrics().skipped(1).start_bucket_elapsed_millis());
3704     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3705               report.value_metrics().skipped(1).end_bucket_elapsed_millis());
3706     ASSERT_EQ(1, report.value_metrics().skipped(1).drop_event_size());
3707 
3708     dropEvent = report.value_metrics().skipped(1).drop_event(0);
3709     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3710     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
3711 
3712     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3713               report.value_metrics().skipped(2).start_bucket_elapsed_millis());
3714     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3715               report.value_metrics().skipped(2).end_bucket_elapsed_millis());
3716     ASSERT_EQ(1, report.value_metrics().skipped(2).drop_event_size());
3717 
3718     dropEvent = report.value_metrics().skipped(2).drop_event(0);
3719     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3720     EXPECT_EQ(NanoToMillis(conditionChangeTimeNs), dropEvent.drop_time_millis());
3721 }
3722 
3723 /*
3724  * Test that a skipped bucket is logged when a forced bucket split occurs when the previous bucket
3725  * was not flushed in time.
3726  */
TEST(ValueMetricProducerTest_BucketDrop,TestBucketDropWhenForceBucketSplitBeforeBucketFlush)3727 TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenForceBucketSplitBeforeBucketFlush) {
3728     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3729 
3730     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3731     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3732             // Condition change to true.
3733             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3734                                 vector<std::shared_ptr<LogEvent>>* data) {
3735                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
3736                 data->clear();
3737                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3738                 return true;
3739             }))
3740             // App Update.
3741             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3742                                 vector<std::shared_ptr<LogEvent>>* data) {
3743                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1000);
3744                 data->clear();
3745                 data->push_back(
3746                         CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1000, 15));
3747                 return true;
3748             }));
3749 
3750     sp<ValueMetricProducer> valueProducer =
3751             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric,
3752                                                                             ConditionState::kFalse);
3753 
3754     // Condition changed event
3755     int64_t conditionChangeTimeNs = bucketStartTimeNs + 10;
3756     valueProducer->onConditionChanged(true, conditionChangeTimeNs);
3757 
3758     // App update event.
3759     int64_t appUpdateTimeNs = bucket2StartTimeNs + 1000;
3760     valueProducer->notifyAppUpgrade(appUpdateTimeNs);
3761 
3762     // Check dump report.
3763     ProtoOutputStream output;
3764     std::set<string> strSet;
3765     int64_t dumpReportTimeNs = bucket2StartTimeNs + 10000000000; // 10 seconds
3766     valueProducer->onDumpReport(dumpReportTimeNs, false /* include current buckets */, true,
3767                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
3768 
3769     StatsLogReport report = outputStreamToProto(&output);
3770     EXPECT_TRUE(report.has_value_metrics());
3771     ASSERT_EQ(1, report.value_metrics().data_size());
3772     ASSERT_EQ(1, report.value_metrics().skipped_size());
3773 
3774     ASSERT_EQ(1, report.value_metrics().data(0).bucket_info_size());
3775     auto data = report.value_metrics().data(0);
3776     ASSERT_EQ(0, data.bucket_info(0).bucket_num());
3777     EXPECT_EQ(5, data.bucket_info(0).values(0).value_long());
3778 
3779     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
3780               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3781     EXPECT_EQ(NanoToMillis(appUpdateTimeNs),
3782               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3783     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
3784 
3785     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3786     EXPECT_EQ(BucketDropReason::NO_DATA, dropEvent.drop_reason());
3787     EXPECT_EQ(NanoToMillis(appUpdateTimeNs), dropEvent.drop_time_millis());
3788 }
3789 
3790 /*
3791  * Test multiple bucket drop events in the same bucket.
3792  */
TEST(ValueMetricProducerTest_BucketDrop,TestMultipleBucketDropEvents)3793 TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
3794     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3795 
3796     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3797     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _))
3798             // Condition change to true.
3799             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
3800                                 vector<std::shared_ptr<LogEvent>>* data) {
3801                 data->clear();
3802                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
3803                 return true;
3804             }));
3805 
3806     sp<ValueMetricProducer> valueProducer =
3807             ValueMetricProducerTestHelper::createValueProducerWithCondition(
3808                     pullerManager, metric, ConditionState::kUnknown);
3809 
3810     // Condition change event.
3811     valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3812 
3813     // Check dump report.
3814     ProtoOutputStream output;
3815     std::set<string> strSet;
3816     int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
3817     valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
3818                                 FAST /* dumpLatency */, &strSet, &output);
3819 
3820     StatsLogReport report = outputStreamToProto(&output);
3821     EXPECT_TRUE(report.has_value_metrics());
3822     ASSERT_EQ(0, report.value_metrics().data_size());
3823     ASSERT_EQ(1, report.value_metrics().skipped_size());
3824 
3825     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3826               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3827     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3828               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3829     ASSERT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
3830 
3831     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3832     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3833     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
3834 
3835     dropEvent = report.value_metrics().skipped(0).drop_event(1);
3836     EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
3837     EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
3838 }
3839 
3840 /*
3841  * Test that the number of logged bucket drop events is capped at the maximum.
3842  * The maximum is currently 10 and is set in MetricProducer::maxDropEventsReached().
3843  */
TEST(ValueMetricProducerTest_BucketDrop,TestMaxBucketDropEvents)3844 TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
3845     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
3846 
3847     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3848     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3849             // First condition change event.
3850             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3851                                 vector<std::shared_ptr<LogEvent>>* data) {
3852                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
3853                 for (int i = 0; i < 2000; i++) {
3854                     data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
3855                 }
3856                 return true;
3857             }))
3858             .WillOnce(Return(false))
3859             .WillOnce(Return(false))
3860             .WillOnce(Return(false))
3861             .WillOnce(Return(false))
3862             .WillOnce(Return(false))
3863             .WillOnce(Return(false))
3864             .WillOnce(Return(false))
3865             .WillOnce(Return(false))
3866             .WillOnce(Return(false))
3867             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3868                                 vector<std::shared_ptr<LogEvent>>* data) {
3869                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 220);
3870                 data->clear();
3871                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 220, 10));
3872                 return true;
3873             }));
3874 
3875     sp<ValueMetricProducer> valueProducer =
3876             ValueMetricProducerTestHelper::createValueProducerWithCondition(
3877                     pullerManager, metric, ConditionState::kUnknown);
3878 
3879     // First condition change event causes guardrail to be reached.
3880     valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
3881 
3882     // 2-10 condition change events result in failed pulls.
3883     valueProducer->onConditionChanged(false, bucketStartTimeNs + 30);
3884     valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
3885     valueProducer->onConditionChanged(false, bucketStartTimeNs + 70);
3886     valueProducer->onConditionChanged(true, bucketStartTimeNs + 90);
3887     valueProducer->onConditionChanged(false, bucketStartTimeNs + 100);
3888     valueProducer->onConditionChanged(true, bucketStartTimeNs + 150);
3889     valueProducer->onConditionChanged(false, bucketStartTimeNs + 170);
3890     valueProducer->onConditionChanged(true, bucketStartTimeNs + 190);
3891     valueProducer->onConditionChanged(false, bucketStartTimeNs + 200);
3892 
3893     // Condition change event 11
3894     valueProducer->onConditionChanged(true, bucketStartTimeNs + 220);
3895 
3896     // Check dump report.
3897     ProtoOutputStream output;
3898     std::set<string> strSet;
3899     int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
3900     // Because we already have 10 dump events in the current bucket,
3901     // this case should not be added to the list of dump events.
3902     valueProducer->onDumpReport(bucketStartTimeNs + 1000, true /* include recent buckets */, true,
3903                                 FAST /* dumpLatency */, &strSet, &output);
3904 
3905     StatsLogReport report = outputStreamToProto(&output);
3906     EXPECT_TRUE(report.has_value_metrics());
3907     ASSERT_EQ(0, report.value_metrics().data_size());
3908     ASSERT_EQ(1, report.value_metrics().skipped_size());
3909 
3910     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
3911               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
3912     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
3913               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
3914     ASSERT_EQ(10, report.value_metrics().skipped(0).drop_event_size());
3915 
3916     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
3917     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
3918     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
3919 
3920     dropEvent = report.value_metrics().skipped(0).drop_event(1);
3921     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3922     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 30), dropEvent.drop_time_millis());
3923 
3924     dropEvent = report.value_metrics().skipped(0).drop_event(2);
3925     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3926     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 50), dropEvent.drop_time_millis());
3927 
3928     dropEvent = report.value_metrics().skipped(0).drop_event(3);
3929     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3930     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 70), dropEvent.drop_time_millis());
3931 
3932     dropEvent = report.value_metrics().skipped(0).drop_event(4);
3933     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3934     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 90), dropEvent.drop_time_millis());
3935 
3936     dropEvent = report.value_metrics().skipped(0).drop_event(5);
3937     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3938     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 100), dropEvent.drop_time_millis());
3939 
3940     dropEvent = report.value_metrics().skipped(0).drop_event(6);
3941     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3942     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 150), dropEvent.drop_time_millis());
3943 
3944     dropEvent = report.value_metrics().skipped(0).drop_event(7);
3945     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3946     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 170), dropEvent.drop_time_millis());
3947 
3948     dropEvent = report.value_metrics().skipped(0).drop_event(8);
3949     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3950     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 190), dropEvent.drop_time_millis());
3951 
3952     dropEvent = report.value_metrics().skipped(0).drop_event(9);
3953     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
3954     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 200), dropEvent.drop_time_millis());
3955 }
3956 
3957 /*
3958  * Test metric with a simple sliced state
3959  * - Increasing values
3960  * - Using diff
3961  * - Second field is value field
3962  */
TEST(ValueMetricProducerTest,TestSlicedState)3963 TEST(ValueMetricProducerTest, TestSlicedState) {
3964     // Set up ValueMetricProducer.
3965     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
3966     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
3967     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
3968             // ValueMetricProducer initialized.
3969             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3970                                 vector<std::shared_ptr<LogEvent>>* data) {
3971                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
3972                 data->clear();
3973                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
3974                 return true;
3975             }))
3976             // Screen state change to ON.
3977             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3978                                 vector<std::shared_ptr<LogEvent>>* data) {
3979                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 5 * NS_PER_SEC);
3980                 data->clear();
3981                 data->push_back(
3982                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5 * NS_PER_SEC, 5));
3983                 return true;
3984             }))
3985             // Screen state change to OFF.
3986             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3987                                 vector<std::shared_ptr<LogEvent>>* data) {
3988                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
3989                 data->clear();
3990                 data->push_back(
3991                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC, 9));
3992                 return true;
3993             }))
3994             // Screen state change to ON.
3995             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
3996                                 vector<std::shared_ptr<LogEvent>>* data) {
3997                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 15 * NS_PER_SEC);
3998                 data->clear();
3999                 data->push_back(CreateRepeatedValueLogEvent(
4000                         tagId, bucketStartTimeNs + 15 * NS_PER_SEC, 21));
4001                 return true;
4002             }))
4003             // Dump report requested.
4004             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4005                                 vector<std::shared_ptr<LogEvent>>* data) {
4006                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50 * NS_PER_SEC);
4007                 data->clear();
4008                 data->push_back(CreateRepeatedValueLogEvent(
4009                         tagId, bucketStartTimeNs + 50 * NS_PER_SEC, 30));
4010                 return true;
4011             }));
4012 
4013     StateManager::getInstance().clear();
4014     sp<ValueMetricProducer> valueProducer =
4015             ValueMetricProducerTestHelper::createValueProducerWithState(
4016                     pullerManager, metric, {util::SCREEN_STATE_CHANGED}, {});
4017     EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
4018 
4019     // Set up StateManager and check that StateTrackers are initialized.
4020     StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
4021     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
4022     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
4023 
4024     // Bucket status after metric initialized.
4025     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
4026     // Base for dimension key {}
4027     auto it = valueProducer->mCurrentSlicedBucket.begin();
4028     auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4029     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4030     EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
4031     EXPECT_TRUE(itBase->second.hasCurrentState);
4032     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4033     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4034               itBase->second.currentState.getValues()[0].mValue.int_value);
4035     // Value for dimension, state key {{}, kStateUnknown}
4036     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4037     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4038     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4039               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4040     EXPECT_FALSE(it->second.intervals[0].hasValue);
4041     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
4042 
4043     // Bucket status after screen state change kStateUnknown->ON.
4044     auto screenEvent = CreateScreenStateChangedEvent(
4045             bucketStartTimeNs + 5 * NS_PER_SEC, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
4046     StateManager::getInstance().onLogEvent(*screenEvent);
4047     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
4048     // Base for dimension key {}
4049     it = valueProducer->mCurrentSlicedBucket.begin();
4050     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4051     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4052     EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
4053     EXPECT_TRUE(itBase->second.hasCurrentState);
4054     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4055     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
4056               itBase->second.currentState.getValues()[0].mValue.int_value);
4057     // Value for dimension, state key {{}, ON}
4058     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4059     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4060     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
4061               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4062     EXPECT_EQ(0, it->second.intervals.size());
4063     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 5 * NS_PER_SEC);
4064     // Value for dimension, state key {{}, kStateUnknown}
4065     it++;
4066     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4067     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4068     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4069               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4070     EXPECT_TRUE(it->second.intervals[0].hasValue);
4071     EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4072     assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4073                          bucketStartTimeNs + 5 * NS_PER_SEC);
4074 
4075     // Bucket status after screen state change ON->OFF.
4076     screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
4077                                                 android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
4078     StateManager::getInstance().onLogEvent(*screenEvent);
4079     ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
4080     // Base for dimension key {}
4081     it = valueProducer->mCurrentSlicedBucket.begin();
4082     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4083     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4084     EXPECT_EQ(9, itBase->second.baseInfos[0].base.long_value);
4085     EXPECT_TRUE(itBase->second.hasCurrentState);
4086     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
4087               itBase->second.currentState.getValues()[0].mValue.int_value);
4088     // Value for dimension, state key {{}, OFF}
4089     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4090     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4091     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
4092               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4093     EXPECT_EQ(0, it->second.intervals.size());
4094     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
4095     // Value for dimension, state key {{}, ON}
4096     it++;
4097     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4098     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4099     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
4100               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4101     EXPECT_TRUE(it->second.intervals[0].hasValue);
4102     EXPECT_EQ(4, it->second.intervals[0].value.long_value);
4103     assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4104                          bucketStartTimeNs + 10 * NS_PER_SEC);
4105     // Value for dimension, state key {{}, kStateUnknown}
4106     it++;
4107     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4108     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4109     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4110               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4111     EXPECT_TRUE(it->second.intervals[0].hasValue);
4112     EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4113     assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4114                          bucketStartTimeNs + 5 * NS_PER_SEC);
4115 
4116     // Bucket status after screen state change OFF->ON.
4117     screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15 * NS_PER_SEC,
4118                                                 android::view::DisplayStateEnum::DISPLAY_STATE_ON);
4119     StateManager::getInstance().onLogEvent(*screenEvent);
4120     ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
4121     // Base for dimension key {}
4122     it = valueProducer->mCurrentSlicedBucket.begin();
4123     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4124     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4125     EXPECT_EQ(21, itBase->second.baseInfos[0].base.long_value);
4126     EXPECT_TRUE(itBase->second.hasCurrentState);
4127     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4128     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
4129               itBase->second.currentState.getValues()[0].mValue.int_value);
4130     // Value for dimension, state key {{}, OFF}
4131     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4132     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4133     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
4134               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4135     EXPECT_TRUE(it->second.intervals[0].hasValue);
4136     EXPECT_EQ(12, it->second.intervals[0].value.long_value);
4137     assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4138                          bucketStartTimeNs + 15 * NS_PER_SEC);
4139     // Value for dimension, state key {{}, ON}
4140     it++;
4141     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4142     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4143     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
4144               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4145     EXPECT_TRUE(it->second.intervals[0].hasValue);
4146     EXPECT_EQ(4, it->second.intervals[0].value.long_value);
4147     assertConditionTimer(it->second.conditionTimer, true, 5 * NS_PER_SEC,
4148                          bucketStartTimeNs + 15 * NS_PER_SEC);
4149     // Value for dimension, state key {{}, kStateUnknown}
4150     it++;
4151     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4152     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4153     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4154               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4155     EXPECT_TRUE(it->second.intervals[0].hasValue);
4156     EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4157     assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4158                          bucketStartTimeNs + 5 * NS_PER_SEC);
4159 
4160     // Start dump report and check output.
4161     ProtoOutputStream output;
4162     std::set<string> strSet;
4163     valueProducer->onDumpReport(bucketStartTimeNs + 50 * NS_PER_SEC,
4164                                 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
4165                                 &strSet, &output);
4166 
4167     StatsLogReport report = outputStreamToProto(&output);
4168     EXPECT_TRUE(report.has_value_metrics());
4169     ASSERT_EQ(3, report.value_metrics().data_size());
4170 
4171     // {{}, kStateUnknown}
4172     auto data = report.value_metrics().data(0);
4173     ASSERT_EQ(1, data.bucket_info_size());
4174     EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
4175     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4176     EXPECT_TRUE(data.slice_by_state(0).has_value());
4177     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
4178     EXPECT_EQ(5 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4179 
4180     // {{}, ON}
4181     data = report.value_metrics().data(1);
4182     ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
4183     EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
4184     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4185     EXPECT_TRUE(data.slice_by_state(0).has_value());
4186     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
4187     EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4188 
4189     // {{}, OFF}
4190     data = report.value_metrics().data(2);
4191     ASSERT_EQ(1, report.value_metrics().data(2).bucket_info_size());
4192     EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
4193     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4194     EXPECT_TRUE(data.slice_by_state(0).has_value());
4195     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
4196     EXPECT_EQ(5 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4197 }
4198 
4199 /*
4200  * Test metric with sliced state with map
4201  * - Increasing values
4202  * - Using diff
4203  * - Second field is value field
4204  */
TEST(ValueMetricProducerTest,TestSlicedStateWithMap)4205 TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
4206     // Set up ValueMetricProducer.
4207     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
4208     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
4209     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
4210             // ValueMetricProducer initialized.
4211             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4212                                 vector<std::shared_ptr<LogEvent>>* data) {
4213                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
4214                 data->clear();
4215                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
4216                 return true;
4217             }))
4218             // Screen state change to ON.
4219             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4220                                 vector<std::shared_ptr<LogEvent>>* data) {
4221                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 5 * NS_PER_SEC);
4222                 data->clear();
4223                 data->push_back(
4224                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5 * NS_PER_SEC, 5));
4225                 return true;
4226             }))
4227             // Screen state change to VR has no pull because it is in the same
4228             // state group as ON.
4229 
4230             // Screen state change to ON has no pull because it is in the same
4231             // state group as VR.
4232 
4233             // Screen state change to OFF.
4234             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4235                                 vector<std::shared_ptr<LogEvent>>* data) {
4236                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 15 * NS_PER_SEC);
4237                 data->clear();
4238                 data->push_back(CreateRepeatedValueLogEvent(
4239                         tagId, bucketStartTimeNs + 15 * NS_PER_SEC, 21));
4240                 return true;
4241             }))
4242             // Dump report requested.
4243             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4244                                 vector<std::shared_ptr<LogEvent>>* data) {
4245                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50 * NS_PER_SEC);
4246                 data->clear();
4247                 data->push_back(CreateRepeatedValueLogEvent(
4248                         tagId, bucketStartTimeNs + 50 * NS_PER_SEC, 30));
4249                 return true;
4250             }));
4251 
4252     const StateMap& stateMap =
4253             CreateScreenStateOnOffMap(/*screen on id=*/321, /*screen off id=*/123);
4254     const StateMap_StateGroup screenOnGroup = stateMap.group(0);
4255     const StateMap_StateGroup screenOffGroup = stateMap.group(1);
4256 
4257     unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
4258     for (auto group : stateMap.group()) {
4259         for (auto value : group.value()) {
4260             stateGroupMap[SCREEN_STATE_ATOM_ID][value] = group.group_id();
4261         }
4262     }
4263 
4264     StateManager::getInstance().clear();
4265     sp<ValueMetricProducer> valueProducer =
4266             ValueMetricProducerTestHelper::createValueProducerWithState(
4267                     pullerManager, metric, {util::SCREEN_STATE_CHANGED}, stateGroupMap);
4268 
4269     // Set up StateManager and check that StateTrackers are initialized.
4270     StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
4271     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
4272     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
4273 
4274     // Bucket status after metric initialized.
4275     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
4276     // Base for dimension key {}
4277     auto it = valueProducer->mCurrentSlicedBucket.begin();
4278     auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4279     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4280     EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
4281     EXPECT_TRUE(itBase->second.hasCurrentState);
4282     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4283     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4284               itBase->second.currentState.getValues()[0].mValue.int_value);
4285     // Value for dimension, state key {{}, {kStateUnknown}}
4286     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4287     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4288     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4289               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4290     EXPECT_FALSE(it->second.intervals[0].hasValue);
4291     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
4292 
4293     // Bucket status after screen state change kStateUnknown->ON.
4294     auto screenEvent = CreateScreenStateChangedEvent(
4295             bucketStartTimeNs + 5 * NS_PER_SEC, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
4296     StateManager::getInstance().onLogEvent(*screenEvent);
4297     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
4298     // Base for dimension key {}
4299     it = valueProducer->mCurrentSlicedBucket.begin();
4300     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4301     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4302     EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
4303     EXPECT_TRUE(itBase->second.hasCurrentState);
4304     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4305     EXPECT_EQ(screenOnGroup.group_id(),
4306               itBase->second.currentState.getValues()[0].mValue.long_value);
4307     // Value for dimension, state key {{}, ON GROUP}
4308     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4309     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4310     EXPECT_EQ(screenOnGroup.group_id(),
4311               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4312     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 5 * NS_PER_SEC);
4313     // Value for dimension, state key {{}, kStateUnknown}
4314     it++;
4315     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4316     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4317     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4318               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4319     EXPECT_TRUE(it->second.intervals[0].hasValue);
4320     EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4321     assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4322                          bucketStartTimeNs + 5 * NS_PER_SEC);
4323 
4324     // Bucket status after screen state change ON->VR.
4325     // Both ON and VR are in the same state group, so the base should not change.
4326     screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
4327                                                 android::view::DisplayStateEnum::DISPLAY_STATE_VR);
4328     StateManager::getInstance().onLogEvent(*screenEvent);
4329     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
4330     // Base for dimension key {}
4331     it = valueProducer->mCurrentSlicedBucket.begin();
4332     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4333     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4334     EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
4335     EXPECT_TRUE(itBase->second.hasCurrentState);
4336     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4337     EXPECT_EQ(screenOnGroup.group_id(),
4338               itBase->second.currentState.getValues()[0].mValue.int_value);
4339     // Value for dimension, state key {{}, ON GROUP}
4340     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4341     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4342     EXPECT_EQ(screenOnGroup.group_id(),
4343               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4344     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 5 * NS_PER_SEC);
4345     // Value for dimension, state key {{}, kStateUnknown}
4346     it++;
4347     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4348     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4349     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4350               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4351     EXPECT_TRUE(it->second.intervals[0].hasValue);
4352     EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4353     assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4354                          bucketStartTimeNs + 5 * NS_PER_SEC);
4355 
4356     // Bucket status after screen state change VR->ON.
4357     // Both ON and VR are in the same state group, so the base should not change.
4358     screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 12 * NS_PER_SEC,
4359                                                 android::view::DisplayStateEnum::DISPLAY_STATE_ON);
4360     StateManager::getInstance().onLogEvent(*screenEvent);
4361     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
4362     // Base for dimension key {}
4363     it = valueProducer->mCurrentSlicedBucket.begin();
4364     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4365     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4366     EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
4367     EXPECT_TRUE(itBase->second.hasCurrentState);
4368     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4369     EXPECT_EQ(screenOnGroup.group_id(),
4370               itBase->second.currentState.getValues()[0].mValue.int_value);
4371     // Value for dimension, state key {{}, ON GROUP}
4372     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4373     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4374     EXPECT_EQ(screenOnGroup.group_id(),
4375               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4376     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 5 * NS_PER_SEC);
4377     // Value for dimension, state key {{}, kStateUnknown}
4378     it++;
4379     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4380     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4381     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4382               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4383     EXPECT_TRUE(it->second.intervals[0].hasValue);
4384     EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4385     assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4386                          bucketStartTimeNs + 5 * NS_PER_SEC);
4387 
4388     // Bucket status after screen state change VR->OFF.
4389     screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15 * NS_PER_SEC,
4390                                                 android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
4391     StateManager::getInstance().onLogEvent(*screenEvent);
4392     ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
4393     // Base for dimension key {}
4394     it = valueProducer->mCurrentSlicedBucket.begin();
4395     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4396     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4397     EXPECT_EQ(21, itBase->second.baseInfos[0].base.long_value);
4398     EXPECT_TRUE(itBase->second.hasCurrentState);
4399     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4400     EXPECT_EQ(screenOffGroup.group_id(),
4401               itBase->second.currentState.getValues()[0].mValue.int_value);
4402     // Value for dimension, state key {{}, OFF GROUP}
4403     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4404     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4405     EXPECT_EQ(screenOffGroup.group_id(),
4406               it->first.getStateValuesKey().getValues()[0].mValue.long_value);
4407     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 15 * NS_PER_SEC);
4408     // Value for dimension, state key {{}, ON GROUP}
4409     it++;
4410     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4411     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4412     EXPECT_EQ(screenOnGroup.group_id(),
4413               it->first.getStateValuesKey().getValues()[0].mValue.long_value);
4414     EXPECT_TRUE(it->second.intervals[0].hasValue);
4415     EXPECT_EQ(16, it->second.intervals[0].value.long_value);
4416     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
4417                          bucketStartTimeNs + 15 * NS_PER_SEC);
4418     // Value for dimension, state key {{}, kStateUnknown}
4419     it++;
4420     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
4421     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4422     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4423               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4424     EXPECT_TRUE(it->second.intervals[0].hasValue);
4425     EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4426     assertConditionTimer(it->second.conditionTimer, false, 5 * NS_PER_SEC,
4427                          bucketStartTimeNs + 5 * NS_PER_SEC);
4428 
4429     // Start dump report and check output.
4430     ProtoOutputStream output;
4431     std::set<string> strSet;
4432     valueProducer->onDumpReport(bucketStartTimeNs + 50 * NS_PER_SEC,
4433                                 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
4434                                 &strSet, &output);
4435 
4436     StatsLogReport report = outputStreamToProto(&output);
4437     EXPECT_TRUE(report.has_value_metrics());
4438     ASSERT_EQ(3, report.value_metrics().data_size());
4439 
4440     // {{}, kStateUnknown}
4441     auto data = report.value_metrics().data(0);
4442     ASSERT_EQ(1, data.bucket_info_size());
4443     EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
4444     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4445     EXPECT_TRUE(data.slice_by_state(0).has_value());
4446     EXPECT_EQ(-1 /*StateTracker::kStateUnknown*/, data.slice_by_state(0).value());
4447     EXPECT_EQ(5 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4448 
4449     // {{}, ON GROUP}
4450     data = report.value_metrics().data(1);
4451     ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
4452     EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
4453     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4454     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
4455     EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
4456     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4457 
4458     // {{}, OFF GROUP}
4459     data = report.value_metrics().data(2);
4460     ASSERT_EQ(1, report.value_metrics().data(2).bucket_info_size());
4461     EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
4462     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4463     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
4464     EXPECT_EQ(screenOffGroup.group_id(), data.slice_by_state(0).group_id());
4465     EXPECT_EQ(35 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4466 }
4467 
4468 /*
4469  * Test metric that slices by state with a primary field and has dimensions
4470  * - Increasing values
4471  * - Using diff
4472  * - Second field is value field
4473  */
TEST(ValueMetricProducerTest,TestSlicedStateWithPrimaryField_WithDimensions)4474 TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
4475     // Set up ValueMetricProducer.
4476     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
4477     metric.mutable_dimensions_in_what()->set_field(tagId);
4478     metric.mutable_dimensions_in_what()->add_child()->set_field(1);
4479 
4480     MetricStateLink* stateLink = metric.add_state_link();
4481     stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
4482     auto fieldsInWhat = stateLink->mutable_fields_in_what();
4483     *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
4484     auto fieldsInState = stateLink->mutable_fields_in_state();
4485     *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
4486 
4487     /*
4488     NOTE: "1" denotes uid 1 and "2" denotes uid 2.
4489                     bucket # 1                            bucket # 2
4490     10     20     30     40     50     60     70     80     90    100    110    120 (seconds)
4491     |------------------------------------------|---------------------------------|--
4492 
4493                                                                                     (kStateUnknown)
4494     1
4495     |-------------|
4496           20
4497 
4498     2
4499     |----------------------------|
4500                  40
4501 
4502                                                                                     (FOREGROUND)
4503                   1                                                       1
4504                   |----------------------------|-------------|            |------|
4505                                40                     20                     10
4506 
4507 
4508                                                                                     (BACKGROUND)
4509                                                              1
4510                                                              |------------|
4511                                                                    20
4512                                  2
4513                                  |-------------|---------------------------------|
4514                                        20                      50
4515     */
4516     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
4517     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
4518             // ValueMetricProducer initialized.
4519             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4520                                 vector<std::shared_ptr<LogEvent>>* data) {
4521                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
4522                 data->clear();
4523                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 2 /*uid*/, 7));
4524                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1 /*uid*/, 3));
4525                 return true;
4526             }))
4527             // Uid 1 process state change from kStateUnknown -> Foreground
4528             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4529                                 vector<std::shared_ptr<LogEvent>>* data) {
4530                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20 * NS_PER_SEC);
4531                 data->clear();
4532                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC,
4533                                                        1 /*uid*/, 6));
4534 
4535                 // This event should be skipped.
4536                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC,
4537                                                        2 /*uid*/, 8));
4538                 return true;
4539             }))
4540             // Uid 2 process state change from kStateUnknown -> Background
4541             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4542                                 vector<std::shared_ptr<LogEvent>>* data) {
4543                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40 * NS_PER_SEC);
4544                 data->clear();
4545                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC,
4546                                                        2 /*uid*/, 9));
4547 
4548                 // This event should be skipped.
4549                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC,
4550                                                        1 /*uid*/, 12));
4551                 return true;
4552             }))
4553             // Uid 1 process state change from Foreground -> Background
4554             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4555                                 vector<std::shared_ptr<LogEvent>>* data) {
4556                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 20 * NS_PER_SEC);
4557                 data->clear();
4558                 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 20 * NS_PER_SEC,
4559                                                        1 /*uid*/, 13));
4560 
4561                 // This event should be skipped.
4562                 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 20 * NS_PER_SEC,
4563                                                        2 /*uid*/, 11));
4564                 return true;
4565             }))
4566             // Uid 1 process state change from Background -> Foreground
4567             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4568                                 vector<std::shared_ptr<LogEvent>>* data) {
4569                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 40 * NS_PER_SEC);
4570                 data->clear();
4571                 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 40 * NS_PER_SEC,
4572                                                        1 /*uid*/, 17));
4573 
4574                 // This event should be skipped.
4575                 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 40 * NS_PER_SEC,
4576                                                        2 /*uid */, 15));
4577                 return true;
4578             }))
4579             // Dump report pull.
4580             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
4581                                 vector<std::shared_ptr<LogEvent>>* data) {
4582                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 50 * NS_PER_SEC);
4583                 data->clear();
4584                 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 50 * NS_PER_SEC,
4585                                                        2 /*uid*/, 20));
4586                 data->push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 50 * NS_PER_SEC,
4587                                                        1 /*uid*/, 21));
4588                 return true;
4589             }));
4590 
4591     StateManager::getInstance().clear();
4592     sp<ValueMetricProducer> valueProducer =
4593             ValueMetricProducerTestHelper::createValueProducerWithState(
4594                     pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {});
4595 
4596     // Set up StateManager and check that StateTrackers are initialized.
4597     StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
4598     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
4599     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
4600 
4601     // Bucket status after metric initialized.
4602     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
4603     // Base for dimension key {uid 1}.
4604     auto it = valueProducer->mCurrentSlicedBucket.begin();
4605     auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4606     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4607     EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
4608     EXPECT_TRUE(itBase->second.hasCurrentState);
4609     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4610     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4611               itBase->second.currentState.getValues()[0].mValue.int_value);
4612     // Value for dimension, state key {{uid 1}, kStateUnknown}
4613     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4614     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4615     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4616     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4617               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4618     EXPECT_FALSE(it->second.intervals[0].hasValue);
4619     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
4620     // Base for dimension key {uid 2}
4621     it++;
4622     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4623     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4624     EXPECT_EQ(7, itBase->second.baseInfos[0].base.long_value);
4625     EXPECT_TRUE(itBase->second.hasCurrentState);
4626     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4627     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4628               itBase->second.currentState.getValues()[0].mValue.int_value);
4629     // Value for dimension, state key {{uid 2}, kStateUnknown}
4630     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4631     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4632     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4633     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4634               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4635     EXPECT_FALSE(it->second.intervals[0].hasValue);
4636     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
4637 
4638     // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
4639     auto uidProcessEvent =
4640             CreateUidProcessStateChangedEvent(bucketStartTimeNs + 20 * NS_PER_SEC, 1 /* uid */,
4641                                               android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
4642     StateManager::getInstance().onLogEvent(*uidProcessEvent);
4643     ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
4644     // Base for dimension key {uid 1}.
4645     it = valueProducer->mCurrentSlicedBucket.begin();
4646     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4647     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4648     EXPECT_EQ(6, itBase->second.baseInfos[0].base.long_value);
4649     EXPECT_TRUE(itBase->second.hasCurrentState);
4650     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4651     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4652               itBase->second.currentState.getValues()[0].mValue.int_value);
4653     // Value for key {uid 1, kStateUnknown}.
4654     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4655     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4656     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4657     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4658               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4659     EXPECT_TRUE(it->second.intervals[0].hasValue);
4660     EXPECT_EQ(3, it->second.intervals[0].value.long_value);
4661     assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
4662                          bucketStartTimeNs + 20 * NS_PER_SEC);
4663     // Value for key {uid 1, FOREGROUND}.
4664     it++;
4665     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4666     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4667     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4668     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4669               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4670     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
4671 
4672     // Base for dimension key {uid 2}.
4673     it++;
4674     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4675     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4676     EXPECT_EQ(7, itBase->second.baseInfos[0].base.long_value);
4677     EXPECT_TRUE(itBase->second.hasCurrentState);
4678     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4679     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4680               itBase->second.currentState.getValues()[0].mValue.int_value);
4681     // Value for key {uid 2, kStateUnknown}.
4682     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4683     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4684     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4685     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4686               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4687     EXPECT_FALSE(it->second.intervals[0].hasValue);
4688     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
4689 
4690     // Bucket status after uid 2 process state change kStateUnknown -> Background.
4691     uidProcessEvent =
4692             CreateUidProcessStateChangedEvent(bucketStartTimeNs + 40 * NS_PER_SEC, 2 /* uid */,
4693                                               android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
4694     StateManager::getInstance().onLogEvent(*uidProcessEvent);
4695     ASSERT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
4696     // Base for dimension key {uid 2}.
4697     it = valueProducer->mCurrentSlicedBucket.begin();
4698     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4699     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4700     EXPECT_EQ(9, itBase->second.baseInfos[0].base.long_value);
4701     EXPECT_TRUE(itBase->second.hasCurrentState);
4702     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4703     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4704               itBase->second.currentState.getValues()[0].mValue.int_value);
4705     // Value for key {uid 2, BACKGROUND}.
4706     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4707     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4708     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4709     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4710               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4711     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 40 * NS_PER_SEC);
4712 
4713     // Base for dimension key {uid 1}.
4714     it++;
4715     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4716     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4717     EXPECT_EQ(6, itBase->second.baseInfos[0].base.long_value);
4718     EXPECT_TRUE(itBase->second.hasCurrentState);
4719     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4720     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4721               itBase->second.currentState.getValues()[0].mValue.int_value);
4722     // Value for key {uid 1, kStateUnknown}.
4723     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4724     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4725     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4726     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4727               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4728     EXPECT_TRUE(it->second.intervals[0].hasValue);
4729     EXPECT_EQ(3, it->second.intervals[0].value.long_value);
4730     assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
4731                          bucketStartTimeNs + 20 * NS_PER_SEC);
4732 
4733     // Value for key {uid 1, FOREGROUND}.
4734     it++;
4735     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4736     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4737     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4738     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4739               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4740     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
4741 
4742     // Value for key {uid 2, kStateUnknown}
4743     it++;
4744     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4745     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4746     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4747     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4748               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4749     EXPECT_TRUE(it->second.intervals[0].hasValue);
4750     EXPECT_EQ(2, it->second.intervals[0].value.long_value);
4751     assertConditionTimer(it->second.conditionTimer, false, 40 * NS_PER_SEC,
4752                          bucketStartTimeNs + 40 * NS_PER_SEC);
4753 
4754     // Pull at end of first bucket.
4755     vector<shared_ptr<LogEvent>> allData;
4756     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 10));
4757     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs, 2 /*uid*/, 15));
4758     valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
4759 
4760     // Buckets flushed after end of first bucket.
4761     // None of the buckets should have a value.
4762     ASSERT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
4763     ASSERT_EQ(4UL, valueProducer->mPastBuckets.size());
4764     ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
4765     // Base for dimension key {uid 2}.
4766     it = valueProducer->mCurrentSlicedBucket.begin();
4767     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4768     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4769     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4770     EXPECT_EQ(15, itBase->second.baseInfos[0].base.long_value);
4771     EXPECT_TRUE(itBase->second.hasCurrentState);
4772     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4773     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4774               itBase->second.currentState.getValues()[0].mValue.int_value);
4775     // Value for key {uid 2, BACKGROUND}.
4776     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4777     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4778     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4779     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4780               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4781     EXPECT_FALSE(it->second.intervals[0].hasValue);
4782     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
4783     EXPECT_EQ(20 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
4784 
4785     // Base for dimension key {uid 1}
4786     it++;
4787     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4788     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4789     EXPECT_EQ(10, itBase->second.baseInfos[0].base.long_value);
4790     EXPECT_TRUE(itBase->second.hasCurrentState);
4791     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4792     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4793               itBase->second.currentState.getValues()[0].mValue.int_value);
4794     // Value for key {uid 1, kStateUnknown}
4795     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4796     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4797     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4798     EXPECT_EQ(-1 /* kStateTracker::kUnknown */,
4799               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4800     EXPECT_FALSE(it->second.intervals[0].hasValue);
4801     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
4802     EXPECT_EQ(20 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
4803 
4804     // Value for key {uid 1, FOREGROUND}
4805     it++;
4806     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4807     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4808     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4809     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4810               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4811     EXPECT_FALSE(it->second.intervals[0].hasValue);
4812     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
4813     EXPECT_EQ(40 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
4814 
4815     // Value for key {uid 2, kStateUnknown}
4816     it++;
4817     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4818     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4819     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4820     EXPECT_EQ(-1 /* kStateTracker::kUnknown */,
4821               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4822     EXPECT_FALSE(it->second.intervals[0].hasValue);
4823     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 40 * NS_PER_SEC);
4824     EXPECT_EQ(40 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
4825 
4826     // Bucket status after uid 1 process state change from Foreground -> Background.
4827     uidProcessEvent =
4828             CreateUidProcessStateChangedEvent(bucket2StartTimeNs + 20 * NS_PER_SEC, 1 /* uid */,
4829                                               android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
4830     StateManager::getInstance().onLogEvent(*uidProcessEvent);
4831 
4832     ASSERT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
4833     ASSERT_EQ(4UL, valueProducer->mPastBuckets.size());
4834     ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
4835     // Base for dimension key {uid 2}.
4836     it = valueProducer->mCurrentSlicedBucket.begin();
4837     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4838     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4839     EXPECT_EQ(15, itBase->second.baseInfos[0].base.long_value);
4840     EXPECT_TRUE(itBase->second.hasCurrentState);
4841     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4842     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4843               itBase->second.currentState.getValues()[0].mValue.int_value);
4844     // Value for key {uid 2, BACKGROUND}.
4845     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4846     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4847     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4848     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4849               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4850     EXPECT_FALSE(it->second.intervals[0].hasValue);
4851     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
4852 
4853     // Base for dimension key {uid 1}
4854     it++;
4855     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4856     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4857     EXPECT_EQ(13, itBase->second.baseInfos[0].base.long_value);
4858     EXPECT_TRUE(itBase->second.hasCurrentState);
4859     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4860     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4861               itBase->second.currentState.getValues()[0].mValue.int_value);
4862     // Value for key {uid 1, kStateUnknown}
4863     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4864     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4865     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4866     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4867               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4868     EXPECT_FALSE(it->second.intervals[0].hasValue);
4869     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
4870 
4871     // Value for key {uid 1, BACKGROUND}
4872     it++;
4873     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4874     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4875     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4876     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4877               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4878     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs + 20 * NS_PER_SEC);
4879 
4880     // Value for key {uid 1, FOREGROUND}
4881     it++;
4882     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4883     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4884     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4885     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4886               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4887     EXPECT_TRUE(it->second.intervals[0].hasValue);
4888     EXPECT_EQ(3, it->second.intervals[0].value.long_value);
4889     assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
4890                          bucket2StartTimeNs + 20 * NS_PER_SEC);
4891 
4892     // Value for key {uid 2, kStateUnknown}
4893     it++;
4894     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4895     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4896     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4897     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4898               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4899     EXPECT_FALSE(it->second.intervals[0].hasValue);
4900     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 40 * NS_PER_SEC);
4901 
4902     // Bucket status after uid 1 process state change Background->Foreground.
4903     uidProcessEvent =
4904             CreateUidProcessStateChangedEvent(bucket2StartTimeNs + 40 * NS_PER_SEC, 1 /* uid */,
4905                                               android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
4906     StateManager::getInstance().onLogEvent(*uidProcessEvent);
4907 
4908     ASSERT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
4909     ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
4910     // Base for dimension key {uid 2}
4911     it = valueProducer->mCurrentSlicedBucket.begin();
4912     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4913     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4914     EXPECT_EQ(15, itBase->second.baseInfos[0].base.long_value);
4915     EXPECT_TRUE(itBase->second.hasCurrentState);
4916     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4917     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4918               itBase->second.currentState.getValues()[0].mValue.int_value);
4919     // Value for key {uid 2, BACKGROUND}
4920     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4921     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4922     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4923     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4924               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4925     EXPECT_FALSE(it->second.intervals[0].hasValue);
4926     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
4927 
4928     // Base for dimension key {uid 1}
4929     it++;
4930     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
4931     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
4932     EXPECT_EQ(17, itBase->second.baseInfos[0].base.long_value);
4933     EXPECT_TRUE(itBase->second.hasCurrentState);
4934     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
4935     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4936               itBase->second.currentState.getValues()[0].mValue.int_value);
4937     // Value for key {uid 1, kStateUnknown}
4938     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4939     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4940     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4941     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4942               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4943     EXPECT_FALSE(it->second.intervals[0].hasValue);
4944     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
4945 
4946     // Value for key {uid 1, BACKGROUND}
4947     it++;
4948     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4949     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4950     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4951     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
4952               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4953     EXPECT_TRUE(it->second.intervals[0].hasValue);
4954     EXPECT_EQ(4, it->second.intervals[0].value.long_value);
4955     assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
4956                          bucket2StartTimeNs + 40 * NS_PER_SEC);
4957 
4958     // Value for key {uid 1, FOREGROUND}
4959     it++;
4960     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4961     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4962     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4963     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
4964               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4965     EXPECT_TRUE(it->second.intervals[0].hasValue);
4966     EXPECT_EQ(3, it->second.intervals[0].value.long_value);
4967     assertConditionTimer(it->second.conditionTimer, true, 20 * NS_PER_SEC,
4968                          bucket2StartTimeNs + 40 * NS_PER_SEC);
4969 
4970     // Value for key {uid 2, kStateUnknown}
4971     it++;
4972     ASSERT_EQ(1, it->first.getDimensionKeyInWhat().getValues().size());
4973     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
4974     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
4975     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
4976               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
4977     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 40 * NS_PER_SEC);
4978 
4979     // Start dump report and check output.
4980     ProtoOutputStream output;
4981     std::set<string> strSet;
4982     valueProducer->onDumpReport(bucket2StartTimeNs + 50 * NS_PER_SEC,
4983                                 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
4984                                 &strSet, &output);
4985 
4986     StatsLogReport report = outputStreamToProto(&output);
4987     EXPECT_TRUE(report.has_value_metrics());
4988     ASSERT_EQ(5, report.value_metrics().data_size());
4989 
4990     // {uid 1, BACKGROUND}
4991     auto data = report.value_metrics().data(0);
4992     ASSERT_EQ(1, data.bucket_info_size());
4993     EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
4994     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
4995     EXPECT_TRUE(data.slice_by_state(0).has_value());
4996     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
4997               data.slice_by_state(0).value());
4998     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
4999 
5000     // {uid 2, kStateUnknown}
5001     data = report.value_metrics().data(1);
5002     ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
5003     EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
5004     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
5005     EXPECT_TRUE(data.slice_by_state(0).has_value());
5006     EXPECT_EQ(-1 /*StateTracker::kStateUnknown*/, data.slice_by_state(0).value());
5007     EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5008 
5009     // {uid 1, FOREGROUND}
5010     data = report.value_metrics().data(2);
5011     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
5012     EXPECT_TRUE(data.slice_by_state(0).has_value());
5013     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
5014               data.slice_by_state(0).value());
5015     ASSERT_EQ(2, report.value_metrics().data(2).bucket_info_size());
5016     EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
5017     EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
5018     EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5019     EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
5020 
5021     // {uid 1, kStateUnknown}
5022     data = report.value_metrics().data(3);
5023     ASSERT_EQ(1, report.value_metrics().data(3).bucket_info_size());
5024     EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
5025     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
5026     EXPECT_TRUE(data.slice_by_state(0).has_value());
5027     EXPECT_EQ(-1 /*StateTracker::kStateUnknown*/, data.slice_by_state(0).value());
5028     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5029 
5030     // {uid 2, BACKGROUND}
5031     data = report.value_metrics().data(4);
5032     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
5033     EXPECT_TRUE(data.slice_by_state(0).has_value());
5034     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
5035               data.slice_by_state(0).value());
5036     ASSERT_EQ(2, report.value_metrics().data(4).bucket_info_size());
5037     EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
5038     EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
5039     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5040     EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
5041 }
5042 
5043 /*
5044  * Test slicing condition_true_nanos by state for metric that slices by state when data is not
5045  * present in pulled data during a state change.
5046  */
TEST(ValueMetricProducerTest,TestSlicedStateWithMissingDataInStateChange)5047 TEST(ValueMetricProducerTest, TestSlicedStateWithMissingDataInStateChange) {
5048     // Set up ValueMetricProducer.
5049     ValueMetric metric =
5050             ValueMetricProducerTestHelper::createMetricWithState("BATTERY_SAVER_MODE_STATE");
5051     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
5052     /*
5053     NOTE: "-" means that the data was not present in the pulled data.
5054 
5055                              bucket # 1
5056     10         20         30         40         50         60   (seconds)
5057     |-------------------------------------------------------|--
5058     x                                                           (kStateUnknown)
5059     |-----------|
5060          10
5061 
5062                 x                               x               (ON)
5063                 |---------------------|         |-----------|
5064                            20                        10
5065 
5066                                       -                         (OFF)
5067     */
5068     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
5069             // ValueMetricProducer initialized.
5070             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5071                                 vector<std::shared_ptr<LogEvent>>* data) {
5072                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
5073                 data->clear();
5074                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
5075                 return true;
5076             }))
5077             // Battery saver mode state changed to ON.
5078             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5079                                 vector<std::shared_ptr<LogEvent>>* data) {
5080                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
5081                 data->clear();
5082                 data->push_back(
5083                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC, 5));
5084                 return true;
5085             }))
5086             // Battery saver mode state changed to OFF but data for dimension key {} is not present
5087             // in the pulled data.
5088             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5089                                 vector<std::shared_ptr<LogEvent>>* data) {
5090                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 30 * NS_PER_SEC);
5091                 data->clear();
5092                 return true;
5093             }))
5094             // Battery saver mode state changed to ON.
5095             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5096                                 vector<std::shared_ptr<LogEvent>>* data) {
5097                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40 * NS_PER_SEC);
5098                 data->clear();
5099                 data->push_back(
5100                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC, 7));
5101                 return true;
5102             }))
5103             // Dump report pull.
5104             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5105                                 vector<std::shared_ptr<LogEvent>>* data) {
5106                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50 * NS_PER_SEC);
5107                 data->clear();
5108                 data->push_back(CreateRepeatedValueLogEvent(
5109                         tagId, bucketStartTimeNs + 50 * NS_PER_SEC, 15));
5110                 return true;
5111             }));
5112 
5113     StateManager::getInstance().clear();
5114     sp<ValueMetricProducer> valueProducer =
5115             ValueMetricProducerTestHelper::createValueProducerWithState(
5116                     pullerManager, metric, {util::BATTERY_SAVER_MODE_STATE_CHANGED}, {});
5117     EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
5118 
5119     // Set up StateManager and check that StateTrackers are initialized.
5120     StateManager::getInstance().registerListener(util::BATTERY_SAVER_MODE_STATE_CHANGED,
5121                                                  valueProducer);
5122     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
5123     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
5124                          util::BATTERY_SAVER_MODE_STATE_CHANGED));
5125 
5126     // Bucket status after metric initialized.
5127     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
5128     // Base for dimension key {}
5129     auto it = valueProducer->mCurrentSlicedBucket.begin();
5130     auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5131     EXPECT_TRUE(itBase->second.hasCurrentState);
5132     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5133     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5134               itBase->second.currentState.getValues()[0].mValue.int_value);
5135     // Value for dimension, state key {{}, kStateUnknown}
5136     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5137     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5138     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5139               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5140     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
5141 
5142     // Bucket status after battery saver mode ON event.
5143     unique_ptr<LogEvent> batterySaverOnEvent =
5144             CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 10 * NS_PER_SEC);
5145     StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5146 
5147     // Base for dimension key {}
5148 
5149     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5150     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5151     it = valueProducer->mCurrentSlicedBucket.begin();
5152     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5153     EXPECT_TRUE(itBase->second.hasCurrentState);
5154     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5155     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5156               itBase->second.currentState.getValues()[0].mValue.int_value);
5157     // Value for key {{}, ON}
5158     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5159     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5160     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5161               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5162     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5163 
5164     // Value for key {{}, -1}
5165     it++;
5166     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5167     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5168     EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5169               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5170     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5171                          bucketStartTimeNs + 10 * NS_PER_SEC);
5172 
5173     // Bucket status after battery saver mode OFF event which is not present
5174     // in the pulled data.
5175     unique_ptr<LogEvent> batterySaverOffEvent =
5176             CreateBatterySaverOffEvent(/*timestamp=*/bucketStartTimeNs + 30 * NS_PER_SEC);
5177     StateManager::getInstance().onLogEvent(*batterySaverOffEvent);
5178 
5179     // Base for dimension key {}
5180     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5181     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5182     it = valueProducer->mCurrentSlicedBucket.begin();
5183     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5184     EXPECT_FALSE(itBase->second.hasCurrentState);
5185     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5186     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5187               itBase->second.currentState.getValues()[0].mValue.int_value);
5188     // Value for key {{}, ON}
5189     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5190     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5191     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5192               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5193     assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
5194                          bucketStartTimeNs + 30 * NS_PER_SEC);
5195 
5196     // Value for key {{}, -1}
5197     it++;
5198     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5199     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5200     EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5201               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5202     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5203                          bucketStartTimeNs + 10 * NS_PER_SEC);
5204 
5205     // Bucket status after battery saver mode ON event.
5206     batterySaverOnEvent =
5207             CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 40 * NS_PER_SEC);
5208     StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5209 
5210     // Base for dimension key {}
5211     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5212     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5213     it = valueProducer->mCurrentSlicedBucket.begin();
5214     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5215     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5216     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5217               itBase->second.currentState.getValues()[0].mValue.int_value);
5218     // Value for key {{}, ON}
5219     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5220     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5221     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5222               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5223     assertConditionTimer(it->second.conditionTimer, true, 20 * NS_PER_SEC,
5224                          bucketStartTimeNs + 40 * NS_PER_SEC);
5225 
5226     // Value for key {{}, -1}
5227     it++;
5228     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5229     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5230     EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5231               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5232     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5233                          bucketStartTimeNs + 10 * NS_PER_SEC);
5234 
5235     // Start dump report and check output.
5236     ProtoOutputStream output;
5237     std::set<string> strSet;
5238     valueProducer->onDumpReport(bucketStartTimeNs + 50 * NS_PER_SEC,
5239                                 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
5240                                 &strSet, &output);
5241 
5242     StatsLogReport report = outputStreamToProto(&output);
5243     EXPECT_TRUE(report.has_value_metrics());
5244     ASSERT_EQ(2, report.value_metrics().data_size());
5245 
5246     // {{}, kStateUnknown}
5247     ValueMetricData data = report.value_metrics().data(0);
5248     EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5249     EXPECT_EQ(-1 /*StateTracker::kUnknown*/, data.slice_by_state(0).value());
5250     ASSERT_EQ(1, data.bucket_info_size());
5251     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5252 
5253     // {{}, ON}
5254     data = report.value_metrics().data(1);
5255     EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5256     EXPECT_EQ(BatterySaverModeStateChanged::ON, data.slice_by_state(0).value());
5257     ASSERT_EQ(1, data.bucket_info_size());
5258     EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5259 }
5260 
5261 /*
5262  * Test for metric that slices by state when data is not present in pulled data
5263  * during an event and then a flush occurs for the current bucket. With the new
5264  * condition timer behavior, a "new" MetricDimensionKey is inserted into
5265  * `mCurrentSlicedBucket` before intervals are closed/added to that new
5266  * MetricDimensionKey.
5267  */
TEST(ValueMetricProducerTest,TestSlicedStateWithMissingDataThenFlushBucket)5268 TEST(ValueMetricProducerTest, TestSlicedStateWithMissingDataThenFlushBucket) {
5269     // Set up ValueMetricProducer.
5270     ValueMetric metric =
5271             ValueMetricProducerTestHelper::createMetricWithState("BATTERY_SAVER_MODE_STATE");
5272     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
5273     /*
5274     NOTE: "-" means that the data was not present in the pulled data.
5275 
5276                              bucket # 1
5277     10         20         30         40         50         60   (seconds)
5278     |-------------------------------------------------------|--
5279     -                                                           (kStateUnknown)
5280 
5281                 -                                               (ON)
5282     */
5283     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
5284             // ValueMetricProducer initialized  but data for dimension key {} is not present
5285             // in the pulled data..
5286             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5287                                 vector<std::shared_ptr<LogEvent>>* data) {
5288                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
5289                 data->clear();
5290                 return true;
5291             }))
5292             // Battery saver mode state changed to ON but data for dimension key {} is not present
5293             // in the pulled data.
5294             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5295                                 vector<std::shared_ptr<LogEvent>>* data) {
5296                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
5297                 data->clear();
5298                 return true;
5299             }))
5300             // Dump report pull.
5301             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5302                                 vector<std::shared_ptr<LogEvent>>* data) {
5303                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50 * NS_PER_SEC);
5304                 data->clear();
5305                 data->push_back(CreateRepeatedValueLogEvent(
5306                         tagId, bucketStartTimeNs + 50 * NS_PER_SEC, 15));
5307                 return true;
5308             }));
5309 
5310     StateManager::getInstance().clear();
5311     sp<ValueMetricProducer> valueProducer =
5312             ValueMetricProducerTestHelper::createValueProducerWithState(
5313                     pullerManager, metric, {util::BATTERY_SAVER_MODE_STATE_CHANGED}, {});
5314     EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
5315 
5316     // Set up StateManager and check that StateTrackers are initialized.
5317     StateManager::getInstance().registerListener(util::BATTERY_SAVER_MODE_STATE_CHANGED,
5318                                                  valueProducer);
5319     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
5320     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
5321                          util::BATTERY_SAVER_MODE_STATE_CHANGED));
5322 
5323     // Bucket status after metric initialized.
5324     ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
5325     ASSERT_EQ(0UL, valueProducer->mCurrentBaseInfo.size());
5326 
5327     // Bucket status after battery saver mode ON event which is not present
5328     // in the pulled data.
5329     unique_ptr<LogEvent> batterySaverOnEvent =
5330             CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 10 * NS_PER_SEC);
5331     StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5332 
5333     ASSERT_EQ(0UL, valueProducer->mCurrentBaseInfo.size());
5334     ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
5335 
5336     // Start dump report and check output.
5337     ProtoOutputStream output;
5338     std::set<string> strSet;
5339     valueProducer->onDumpReport(bucketStartTimeNs + 50 * NS_PER_SEC,
5340                                 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
5341                                 &strSet, &output);
5342 
5343     StatsLogReport report = outputStreamToProto(&output);
5344     EXPECT_TRUE(report.has_value_metrics());
5345     ASSERT_EQ(0, report.value_metrics().data_size());
5346     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5347     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5348 }
5349 
TEST(ValueMetricProducerTest,TestSlicedStateWithNoPullOnBucketBoundary)5350 TEST(ValueMetricProducerTest, TestSlicedStateWithNoPullOnBucketBoundary) {
5351     // Set up ValueMetricProducer.
5352     ValueMetric metric =
5353             ValueMetricProducerTestHelper::createMetricWithState("BATTERY_SAVER_MODE_STATE");
5354     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
5355     /*
5356                  bucket # 1                         bucket # 2
5357     10    20    30    40    50    60    70    80   90   100   110   120  (seconds)
5358     |------------------------------------|---------------------------|--
5359     x                                                                    (kStateUnknown)
5360     |-----|
5361       10
5362           x                                              x               (ON)
5363           |-----|                                        |-----------|
5364              10                                               20
5365                 x                                                        (OFF)
5366                 |------------------------|
5367                           40
5368     */
5369     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
5370             // ValueMetricProducer initialized.
5371             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5372                                 vector<std::shared_ptr<LogEvent>>* data) {
5373                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
5374                 data->clear();
5375                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
5376                 return true;
5377             }))
5378             // Battery saver mode state changed to ON.
5379             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5380                                 vector<std::shared_ptr<LogEvent>>* data) {
5381                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
5382                 data->clear();
5383                 data->push_back(
5384                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC, 5));
5385                 return true;
5386             }))
5387             // Battery saver mode state changed to OFF.
5388             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5389                                 vector<std::shared_ptr<LogEvent>>* data) {
5390                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20 * NS_PER_SEC);
5391                 data->clear();
5392                 data->push_back(
5393                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC, 7));
5394                 return true;
5395             }))
5396             // Battery saver mode state changed to ON.
5397             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5398                                 vector<std::shared_ptr<LogEvent>>* data) {
5399                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 30 * NS_PER_SEC);
5400                 data->clear();
5401                 data->push_back(CreateRepeatedValueLogEvent(
5402                         tagId, bucket2StartTimeNs + 30 * NS_PER_SEC, 10));
5403                 return true;
5404             }))
5405             // Dump report pull.
5406             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5407                                 vector<std::shared_ptr<LogEvent>>* data) {
5408                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 50 * NS_PER_SEC);
5409                 data->clear();
5410                 data->push_back(CreateRepeatedValueLogEvent(
5411                         tagId, bucket2StartTimeNs + 50 * NS_PER_SEC, 15));
5412                 return true;
5413             }));
5414 
5415     StateManager::getInstance().clear();
5416     sp<ValueMetricProducer> valueProducer =
5417             ValueMetricProducerTestHelper::createValueProducerWithState(
5418                     pullerManager, metric, {util::BATTERY_SAVER_MODE_STATE_CHANGED}, {});
5419     EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
5420 
5421     // Set up StateManager and check that StateTrackers are initialized.
5422     StateManager::getInstance().registerListener(util::BATTERY_SAVER_MODE_STATE_CHANGED,
5423                                                  valueProducer);
5424     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
5425     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
5426                          util::BATTERY_SAVER_MODE_STATE_CHANGED));
5427 
5428     // Bucket status after metric initialized.
5429     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
5430     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5431     auto it = valueProducer->mCurrentSlicedBucket.begin();
5432     auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5433     EXPECT_TRUE(itBase->second.hasCurrentState);
5434     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5435     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5436               itBase->second.currentState.getValues()[0].mValue.int_value);
5437     // Value for dimension, state key {{}, kStateUnknown}
5438     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5439     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5440     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5441               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5442     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs);
5443 
5444     // Bucket status after battery saver mode ON event.
5445     unique_ptr<LogEvent> batterySaverOnEvent =
5446             CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 10 * NS_PER_SEC);
5447     StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5448 
5449     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5450     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5451     it = valueProducer->mCurrentSlicedBucket.begin();
5452     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5453     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5454     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5455               itBase->second.currentState.getValues()[0].mValue.int_value);
5456     // Value for key {{}, ON}
5457     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5458     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5459     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5460               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5461     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5462 
5463     // Value for key {{}, -1}
5464     it++;
5465     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5466     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5467     EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5468               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5469     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5470                          bucketStartTimeNs + 10 * NS_PER_SEC);
5471 
5472     // Bucket status after battery saver mode OFF event.
5473     unique_ptr<LogEvent> batterySaverOffEvent =
5474             CreateBatterySaverOffEvent(/*timestamp=*/bucketStartTimeNs + 20 * NS_PER_SEC);
5475     StateManager::getInstance().onLogEvent(*batterySaverOffEvent);
5476 
5477     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5478     ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
5479     it = valueProducer->mCurrentSlicedBucket.begin();
5480     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5481     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5482     EXPECT_EQ(BatterySaverModeStateChanged::OFF,
5483               itBase->second.currentState.getValues()[0].mValue.int_value);
5484     // Value for key {{}, OFF}
5485     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5486     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5487     EXPECT_EQ(BatterySaverModeStateChanged::OFF,
5488               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5489     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
5490 
5491     // Value for key {{}, ON}
5492     it++;
5493     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5494     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5495     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5496               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5497     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5498                          bucketStartTimeNs + 20 * NS_PER_SEC);
5499 
5500     // Value for key {{}, -1}
5501     it++;
5502     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5503     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5504     EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5505               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5506     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
5507                          bucketStartTimeNs + 10 * NS_PER_SEC);
5508 
5509     // Bucket status after battery saver mode ON event.
5510     batterySaverOnEvent =
5511             CreateBatterySaverOnEvent(/*timestamp=*/bucket2StartTimeNs + 30 * NS_PER_SEC);
5512     StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5513 
5514     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5515     ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
5516     it = valueProducer->mCurrentSlicedBucket.begin();
5517     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5518     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5519     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5520               itBase->second.currentState.getValues()[0].mValue.int_value);
5521     // Value for key {{}, OFF}
5522     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5523     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5524     EXPECT_EQ(BatterySaverModeStateChanged::OFF,
5525               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5526     assertConditionTimer(it->second.conditionTimer, false, 30 * NS_PER_SEC,
5527                          bucket2StartTimeNs + 30 * NS_PER_SEC);
5528 
5529     // Value for key {{}, ON}
5530     it++;
5531     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5532     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5533     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5534               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5535     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs + 30 * NS_PER_SEC);
5536 
5537     // Value for key {{}, -1}
5538     it++;
5539     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5540     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5541     EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5542               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5543     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5544 
5545     // Start dump report and check output.
5546     ProtoOutputStream output;
5547     std::set<string> strSet;
5548     valueProducer->onDumpReport(bucket2StartTimeNs + 50 * NS_PER_SEC,
5549                                 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
5550                                 &strSet, &output);
5551 
5552     StatsLogReport report = outputStreamToProto(&output);
5553     EXPECT_TRUE(report.has_value_metrics());
5554     ASSERT_EQ(3, report.value_metrics().data_size());
5555 
5556     // {{}, kStateUnknown}
5557     ValueMetricData data = report.value_metrics().data(0);
5558     EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5559     EXPECT_EQ(-1 /*StateTracker::kUnknown*/, data.slice_by_state(0).value());
5560     ASSERT_EQ(1, data.bucket_info_size());
5561     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5562 
5563     // {{}, ON}
5564     data = report.value_metrics().data(1);
5565     EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5566     EXPECT_EQ(BatterySaverModeStateChanged::ON, data.slice_by_state(0).value());
5567     ASSERT_EQ(2, data.bucket_info_size());
5568     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5569     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
5570 
5571     // {{}, OFF}
5572     data = report.value_metrics().data(2);
5573     EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5574     EXPECT_EQ(BatterySaverModeStateChanged::OFF, data.slice_by_state(0).value());
5575     ASSERT_EQ(1, data.bucket_info_size());
5576     EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5577 }
5578 
5579 /*
5580  * Test slicing condition_true_nanos by state for metric that slices by state when data is not
5581  * present in pulled data during a condition change.
5582  */
TEST(ValueMetricProducerTest,TestSlicedStateWithDataMissingInConditionChange)5583 TEST(ValueMetricProducerTest, TestSlicedStateWithDataMissingInConditionChange) {
5584     // Set up ValueMetricProducer.
5585     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithConditionAndState(
5586             "BATTERY_SAVER_MODE_STATE");
5587     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
5588     /*
5589     NOTE: "-" means that the data was not present in the pulled data.
5590 
5591                              bucket # 1
5592     10         20         30         40         50         60   (seconds)
5593     |-------------------------------------------------------|--
5594 
5595     T                                 F         T               (Condition)
5596                x                                                (ON)
5597                |----------------------|         -
5598                          20
5599     */
5600     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
5601             // Battery saver mode state changed to ON.
5602             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5603                                 vector<std::shared_ptr<LogEvent>>* data) {
5604                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
5605                 data->clear();
5606                 data->push_back(
5607                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC, 3));
5608                 return true;
5609             }))
5610             // Condition changed to false.
5611             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5612                                 vector<std::shared_ptr<LogEvent>>* data) {
5613                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 30 * NS_PER_SEC);
5614                 data->clear();
5615                 data->push_back(
5616                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30 * NS_PER_SEC, 5));
5617                 return true;
5618             }))
5619             // Condition changed to true but data for dimension key {} is not present in the
5620             // pulled data.
5621             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5622                                 vector<std::shared_ptr<LogEvent>>* data) {
5623                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40 * NS_PER_SEC);
5624                 data->clear();
5625                 return true;
5626             }))
5627             // Dump report pull.
5628             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5629                                 vector<std::shared_ptr<LogEvent>>* data) {
5630                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50 * NS_PER_SEC);
5631                 data->clear();
5632                 data->push_back(CreateRepeatedValueLogEvent(
5633                         tagId, bucketStartTimeNs + 50 * NS_PER_SEC, 20));
5634                 return true;
5635             }));
5636 
5637     StateManager::getInstance().clear();
5638     sp<ValueMetricProducer> valueProducer =
5639             ValueMetricProducerTestHelper::createValueProducerWithConditionAndState(
5640                     pullerManager, metric, {util::BATTERY_SAVER_MODE_STATE_CHANGED}, {},
5641                     ConditionState::kTrue);
5642     EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
5643 
5644     // Set up StateManager and check that StateTrackers are initialized.
5645     StateManager::getInstance().registerListener(util::BATTERY_SAVER_MODE_STATE_CHANGED,
5646                                                  valueProducer);
5647     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
5648     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
5649                          util::BATTERY_SAVER_MODE_STATE_CHANGED));
5650 
5651     // Bucket status after battery saver mode ON event.
5652     unique_ptr<LogEvent> batterySaverOnEvent =
5653             CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 10 * NS_PER_SEC);
5654     StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
5655     // Base for dimension key {}
5656     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5657     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5658     auto it = valueProducer->mCurrentSlicedBucket.begin();
5659     auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5660     EXPECT_TRUE(itBase->second.hasCurrentState);
5661     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5662     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5663               itBase->second.currentState.getValues()[0].mValue.int_value);
5664     // Value for key {{}, ON}
5665     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5666     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5667     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5668               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5669     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5670 
5671     // Value for key {{}, -1}
5672     it++;
5673     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5674     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5675     EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5676               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5677     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
5678 
5679     // Bucket status after condition change to false.
5680     valueProducer->onConditionChanged(false, bucketStartTimeNs + 30 * NS_PER_SEC);
5681     // Base for dimension key {}
5682     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5683     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5684     it = valueProducer->mCurrentSlicedBucket.begin();
5685     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5686     EXPECT_TRUE(itBase->second.hasCurrentState);
5687     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5688     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5689               itBase->second.currentState.getValues()[0].mValue.int_value);
5690     // Value for key {{}, ON}
5691     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5692     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5693     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5694               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5695     assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
5696                          bucketStartTimeNs + 30 * NS_PER_SEC);
5697 
5698     // Value for key {{}, -1}
5699     it++;
5700     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5701     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5702     EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5703               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5704     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
5705 
5706     // Bucket status after condition change to true.
5707     valueProducer->onConditionChanged(true, bucketStartTimeNs + 40 * NS_PER_SEC);
5708     // Base for dimension key {}
5709     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
5710     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
5711     it = valueProducer->mCurrentSlicedBucket.begin();
5712     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5713     EXPECT_FALSE(itBase->second.hasCurrentState);
5714     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5715     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5716               itBase->second.currentState.getValues()[0].mValue.int_value);
5717     // Value for key {{}, ON}
5718     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5719     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5720     EXPECT_EQ(BatterySaverModeStateChanged::ON,
5721               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5722     assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
5723                          bucketStartTimeNs + 30 * NS_PER_SEC);
5724 
5725     // Value for key {{}, -1}
5726     it++;
5727     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
5728     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5729     EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
5730               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5731     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
5732 
5733     // Start dump report and check output.
5734     ProtoOutputStream output;
5735     std::set<string> strSet;
5736     valueProducer->onDumpReport(bucketStartTimeNs + 50 * NS_PER_SEC,
5737                                 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
5738                                 &strSet, &output);
5739 
5740     StatsLogReport report = outputStreamToProto(&output);
5741     EXPECT_TRUE(report.has_value_metrics());
5742     ASSERT_EQ(1, report.value_metrics().data_size());
5743 
5744     // {{}, ON}
5745     ValueMetricData data = report.value_metrics().data(0);
5746     EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
5747     EXPECT_EQ(BatterySaverModeStateChanged::ON, data.slice_by_state(0).value());
5748     ASSERT_EQ(1, data.bucket_info_size());
5749     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
5750 }
5751 
5752 /*
5753  * Test slicing condition_true_nanos by state for metric that slices by state with a primary field,
5754  * condition, and has multiple dimensions.
5755  */
TEST(ValueMetricProducerTest,TestSlicedStateWithMultipleDimensions)5756 TEST(ValueMetricProducerTest, TestSlicedStateWithMultipleDimensions) {
5757     // Set up ValueMetricProducer.
5758     ValueMetric metric =
5759             ValueMetricProducerTestHelper::createMetricWithConditionAndState("UID_PROCESS_STATE");
5760     metric.mutable_dimensions_in_what()->set_field(tagId);
5761     metric.mutable_dimensions_in_what()->add_child()->set_field(1);
5762     metric.mutable_dimensions_in_what()->add_child()->set_field(3);
5763 
5764     MetricStateLink* stateLink = metric.add_state_link();
5765     stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
5766     auto fieldsInWhat = stateLink->mutable_fields_in_what();
5767     *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
5768     auto fieldsInState = stateLink->mutable_fields_in_state();
5769     *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
5770 
5771     /*
5772                     bucket # 1                            bucket # 2
5773     10     20     30     40     50     60     70     80     90    100    110    120 (seconds)
5774     |------------------------------------------|---------------------------------|--
5775 
5776     T                           F   T                                               (Condition)
5777                                                                                     (FOREGROUND)
5778            x                                                                        {1, 14}
5779            |------|
5780               10
5781 
5782            x                                                                        {1, 16}
5783            |------|
5784               10
5785                                                                    x                {2, 8}
5786                                                                    |-------------|
5787                                                                          20
5788 
5789                                                                                     (BACKGROUND)
5790                   x                                                                 {1, 14}
5791                   |-------------|   |----------|---------------------------------|
5792                         20              15                     50
5793 
5794                   x                                                                 {1, 16}
5795                   |-------------|   |----------|---------------------------------|
5796                         20              15                     50
5797 
5798                      x                                                              {2, 8}
5799                      |----------|   |----------|-------------------|
5800                          15             15              30
5801     */
5802     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
5803     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
5804             // Uid 1 process state change from kStateUnknown -> Foreground
5805             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5806                                 vector<std::shared_ptr<LogEvent>>* data) {
5807                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10 * NS_PER_SEC);
5808                 data->clear();
5809                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC,
5810                                                          1 /*uid*/, 3, 14 /*tag*/));
5811                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC,
5812                                                          1 /*uid*/, 3, 16 /*tag*/));
5813 
5814                 // This event should be skipped.
5815                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10 * NS_PER_SEC,
5816                                                          2 /*uid*/, 5, 8 /*tag*/));
5817                 return true;
5818             }))
5819             // Uid 1 process state change from Foreground -> Background
5820             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5821                                 vector<std::shared_ptr<LogEvent>>* data) {
5822                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20 * NS_PER_SEC);
5823                 data->clear();
5824                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC,
5825                                                          1 /*uid*/, 5, 14 /*tag*/));
5826                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC,
5827                                                          1 /*uid*/, 5, 16 /*tag*/));
5828 
5829                 // This event should be skipped.
5830                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC,
5831                                                          2 /*uid*/, 7, 8 /*tag*/));
5832 
5833                 return true;
5834             }))
5835             // Uid 2 process state change from kStateUnknown -> Background
5836             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5837                                 vector<std::shared_ptr<LogEvent>>* data) {
5838                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 25 * NS_PER_SEC);
5839                 data->clear();
5840                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 25 * NS_PER_SEC,
5841                                                          2 /*uid*/, 9, 8 /*tag*/));
5842 
5843                 // This event should be skipped.
5844                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 25 * NS_PER_SEC,
5845                                                          1 /*uid*/, 9, 14 /* tag */));
5846 
5847                 // This event should be skipped.
5848                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 25 * NS_PER_SEC,
5849                                                          1 /*uid*/, 9, 16 /* tag */));
5850 
5851                 return true;
5852             }))
5853             // Condition changed to false.
5854             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5855                                 vector<std::shared_ptr<LogEvent>>* data) {
5856                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40 * NS_PER_SEC);
5857                 data->clear();
5858                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC,
5859                                                          1 /*uid*/, 11, 14 /* tag */));
5860                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC,
5861                                                          1 /*uid*/, 11, 16 /* tag */));
5862                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 40 * NS_PER_SEC,
5863                                                          2 /*uid*/, 11, 8 /*tag*/));
5864 
5865                 return true;
5866             }))
5867             // Condition changed to true.
5868             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5869                                 vector<std::shared_ptr<LogEvent>>* data) {
5870                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 45 * NS_PER_SEC);
5871                 data->clear();
5872                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 45 * NS_PER_SEC,
5873                                                          1 /*uid*/, 13, 14 /* tag */));
5874                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 45 * NS_PER_SEC,
5875                                                          1 /*uid*/, 13, 16 /* tag */));
5876                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 45 * NS_PER_SEC,
5877                                                          2 /*uid*/, 13, 8 /*tag*/));
5878                 return true;
5879             }))
5880             // Uid 2 process state change from Background -> Foreground
5881             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5882                                 vector<std::shared_ptr<LogEvent>>* data) {
5883                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 30 * NS_PER_SEC);
5884                 data->clear();
5885                 data->push_back(CreateThreeValueLogEvent(
5886                         tagId, bucket2StartTimeNs + 30 * NS_PER_SEC, 2 /*uid*/, 18, 8 /*tag*/));
5887 
5888                 // This event should be skipped.
5889                 data->push_back(CreateThreeValueLogEvent(
5890                         tagId, bucket2StartTimeNs + 30 * NS_PER_SEC, 1 /*uid*/, 18, 14 /* tag */));
5891                 // This event should be skipped.
5892                 data->push_back(CreateThreeValueLogEvent(
5893                         tagId, bucket2StartTimeNs + 30 * NS_PER_SEC, 1 /*uid*/, 18, 16 /* tag */));
5894 
5895                 return true;
5896             }))
5897             // Dump report pull.
5898             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
5899                                 vector<std::shared_ptr<LogEvent>>* data) {
5900                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 50 * NS_PER_SEC);
5901                 data->clear();
5902                 data->push_back(CreateThreeValueLogEvent(
5903                         tagId, bucket2StartTimeNs + 50 * NS_PER_SEC, 1 /*uid*/, 21, 14 /* tag */));
5904                 data->push_back(CreateThreeValueLogEvent(
5905                         tagId, bucket2StartTimeNs + 50 * NS_PER_SEC, 1 /*uid*/, 21, 16 /* tag */));
5906                 data->push_back(CreateThreeValueLogEvent(
5907                         tagId, bucket2StartTimeNs + 50 * NS_PER_SEC, 2 /*uid*/, 21, 8 /*tag*/));
5908                 return true;
5909             }));
5910 
5911     StateManager::getInstance().clear();
5912     sp<ValueMetricProducer> valueProducer =
5913             ValueMetricProducerTestHelper::createValueProducerWithConditionAndState(
5914                     pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {}, ConditionState::kTrue);
5915     EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
5916 
5917     // Set up StateManager and check that StateTrackers are initialized.
5918     StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
5919     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
5920     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
5921 
5922     // Condition is true.
5923     // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
5924     auto uidProcessEvent =
5925             CreateUidProcessStateChangedEvent(bucketStartTimeNs + 10 * NS_PER_SEC, 1 /* uid */,
5926                                               android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
5927     StateManager::getInstance().onLogEvent(*uidProcessEvent);
5928     ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
5929     ASSERT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
5930     // Base for dimension {uid 1, tag 16}.
5931     auto it = valueProducer->mCurrentSlicedBucket.begin();
5932     auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5933     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5934     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
5935               itBase->second.currentState.getValues()[0].mValue.int_value);
5936     // Value for key {{uid 1, uid 16}, FOREGROUND}.
5937     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
5938     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
5939     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
5940     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5941     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
5942               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5943     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5944     // Value for key {{uid 1, tag 16}, kStateUnknown}.
5945     it++;
5946     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
5947     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
5948     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
5949     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5950     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5951               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5952     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
5953 
5954     // Base for dimension key {uid 1, tag 14}.
5955     it++;
5956     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5957     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5958     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
5959               itBase->second.currentState.getValues()[0].mValue.int_value);
5960     // Value for key {{uid 1, tag 14}, FOREGROUND}.
5961     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
5962     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
5963     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
5964     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5965     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
5966               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5967     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 10 * NS_PER_SEC);
5968     // Value for key {{uid 1, tag 14}, kStateUnknown}.
5969     it++;
5970     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
5971     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
5972     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
5973     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5974     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
5975               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5976     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
5977 
5978     // Bucket status after uid 1 process state change Foreground -> Background.
5979     uidProcessEvent =
5980             CreateUidProcessStateChangedEvent(bucketStartTimeNs + 20 * NS_PER_SEC, 1 /* uid */,
5981                                               android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
5982     StateManager::getInstance().onLogEvent(*uidProcessEvent);
5983     ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
5984     ASSERT_EQ(6UL, valueProducer->mCurrentSlicedBucket.size());
5985     // Base for dimension {uid 1, tag 16}.
5986     it = valueProducer->mCurrentSlicedBucket.begin();
5987     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
5988     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
5989     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
5990               itBase->second.currentState.getValues()[0].mValue.int_value);
5991     // Value for key {{uid 1, uid 16}, BACKGROUND}.
5992     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
5993     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
5994     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
5995     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
5996     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
5997               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
5998     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
5999 
6000     // Base for dimension key {uid 1, tag 14}.
6001     it++;
6002     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6003     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6004     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6005               itBase->second.currentState.getValues()[0].mValue.int_value);
6006     // Value for key {{uid 1, tag 14}, BACKGROUND}.
6007     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6008     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6009     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6010     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6011     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6012               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6013     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6014 
6015     // Value for key {{uid 1, uid 16}, FOREGROUND}.
6016     it++;
6017     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6018     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6019     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6020     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6021     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6022               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6023     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6024                          bucketStartTimeNs + 20 * NS_PER_SEC);
6025 
6026     // Value for key {{uid 1, tag 16}, kStateUnknown}.
6027     it++;
6028     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6029     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6030     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6031     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6032     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6033               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6034     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6035 
6036     // Value for key {{uid 1, tag 14}, FOREGROUND}.
6037     it++;
6038     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6039     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6040     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6041     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6042     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6043               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6044     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6045                          bucketStartTimeNs + 20 * NS_PER_SEC);
6046 
6047     // Value for key {{uid 1, tag 14}, kStateUnknown}.
6048     it++;
6049     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6050     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6051     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6052     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6053     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6054               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6055     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6056 
6057     // Bucket status after uid 2 process state change kStateUnknown -> Background.
6058     uidProcessEvent =
6059             CreateUidProcessStateChangedEvent(bucketStartTimeNs + 25 * NS_PER_SEC, 2 /* uid */,
6060                                               android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
6061     StateManager::getInstance().onLogEvent(*uidProcessEvent);
6062     ASSERT_EQ(3UL, valueProducer->mCurrentBaseInfo.size());
6063     ASSERT_EQ(8UL, valueProducer->mCurrentSlicedBucket.size());
6064     // Base for dimension {uid 2, tag 8}.
6065     it = valueProducer->mCurrentSlicedBucket.begin();
6066     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6067     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6068     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6069               itBase->second.currentState.getValues()[0].mValue.int_value);
6070     // Value for key {{uid 2, uid 8}, BACKGROUND}.
6071     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6072     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6073     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6074     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6075     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6076               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6077     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 25 * NS_PER_SEC);
6078 
6079     // Value for key {{uid 2, uid 8}, kStateUnknown}.
6080     it++;
6081     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6082     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6083     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6084     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6085     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6086               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6087     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6088 
6089     // Base for dimension {uid 1, tag 16}.
6090     it++;
6091     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6092     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6093     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6094               itBase->second.currentState.getValues()[0].mValue.int_value);
6095     // Value for key {{uid 1, uid 16}, BACKGROUND}.
6096     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6097     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6098     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6099     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6100     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6101               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6102     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6103 
6104     // Base for dimension key {uid 1, tag 14}.
6105     it++;
6106     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6107     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6108     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6109               itBase->second.currentState.getValues()[0].mValue.int_value);
6110     // Value for key {{uid 1, tag 14}, BACKGROUND}.
6111     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6112     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6113     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6114     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6115     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6116               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6117     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6118 
6119     // Value for key {{uid 1, uid 16}, FOREGROUND}.
6120     it++;
6121     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6122     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6123     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6124     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6125     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6126               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6127     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6128                          bucketStartTimeNs + 20 * NS_PER_SEC);
6129 
6130     // Value for key {{uid 1, tag 16}, kStateUnknown}.
6131     it++;
6132     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6133     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6134     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6135     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6136     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6137               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6138     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6139 
6140     // Value for key {{uid 1, tag 14}, FOREGROUND}.
6141     it++;
6142     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6143     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6144     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6145     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6146     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6147               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6148     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6149                          bucketStartTimeNs + 20 * NS_PER_SEC);
6150 
6151     // Value for key {{uid 1, tag 14}, kStateUnknown}.
6152     it++;
6153     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6154     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6155     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6156     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6157     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6158               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6159     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6160 
6161     // Bucket 1 status after condition change to false.
6162     // All condition timers should be turned off.
6163     valueProducer->onConditionChanged(false, bucketStartTimeNs + 40 * NS_PER_SEC);
6164     ASSERT_EQ(3UL, valueProducer->mCurrentBaseInfo.size());
6165     ASSERT_EQ(8UL, valueProducer->mCurrentSlicedBucket.size());
6166     // Base for dimension {uid 2, tag 8}.
6167     it = valueProducer->mCurrentSlicedBucket.begin();
6168     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6169     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6170     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6171               itBase->second.currentState.getValues()[0].mValue.int_value);
6172     // Value for key {{uid 2, uid 8}, BACKGROUND}.
6173     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6174     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6175     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6176     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6177     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6178               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6179     assertConditionTimer(it->second.conditionTimer, false, 15 * NS_PER_SEC,
6180                          bucketStartTimeNs + 40 * NS_PER_SEC);
6181 
6182     // Value for key {{uid 2, uid 8}, kStateUnknown}.
6183     it++;
6184     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6185     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6186     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6187     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6188     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6189               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6190     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6191 
6192     // Base for dimension {uid 1, tag 16}.
6193     it++;
6194     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6195     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6196     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6197               itBase->second.currentState.getValues()[0].mValue.int_value);
6198     // Value for key {{uid 1, uid 16}, BACKGROUND}.
6199     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6200     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6201     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6202     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6203     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6204               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6205     assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
6206                          bucketStartTimeNs + 40 * NS_PER_SEC);
6207 
6208     // Base for dimension key {uid 1, tag 14}.
6209     it++;
6210     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6211     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6212     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6213               itBase->second.currentState.getValues()[0].mValue.int_value);
6214     // Value for key {{uid 1, tag 14}, BACKGROUND}.
6215     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6216     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6217     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6218     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6219     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6220               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6221     assertConditionTimer(it->second.conditionTimer, false, 20 * NS_PER_SEC,
6222                          bucketStartTimeNs + 40 * NS_PER_SEC);
6223 
6224     // Value for key {{uid 1, uid 16}, FOREGROUND}.
6225     it++;
6226     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6227     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6228     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6229     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6230     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6231               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6232     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6233                          bucketStartTimeNs + 20 * NS_PER_SEC);
6234 
6235     // Value for key {{uid 1, tag 16}, kStateUnknown}.
6236     it++;
6237     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6238     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6239     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6240     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6241     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6242               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6243     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6244 
6245     // Value for key {{uid 1, tag 14}, FOREGROUND}.
6246     it++;
6247     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6248     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6249     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6250     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6251     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6252               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6253     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6254                          bucketStartTimeNs + 20 * NS_PER_SEC);
6255 
6256     // Value for key {{uid 1, tag 14}, kStateUnknown}.
6257     it++;
6258     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6259     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6260     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6261     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6262     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6263               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6264     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6265 
6266     // Bucket 1 status after condition change to true.
6267     valueProducer->onConditionChanged(true, bucketStartTimeNs + 45 * NS_PER_SEC);
6268     ASSERT_EQ(3UL, valueProducer->mCurrentBaseInfo.size());
6269     ASSERT_EQ(8UL, valueProducer->mCurrentSlicedBucket.size());
6270     // Base for dimension {uid 2, tag 8}.
6271     it = valueProducer->mCurrentSlicedBucket.begin();
6272     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6273     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6274     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6275               itBase->second.currentState.getValues()[0].mValue.int_value);
6276     // Value for key {{uid 2, uid 8}, BACKGROUND}.
6277     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6278     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6279     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6280     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6281     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6282               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6283     assertConditionTimer(it->second.conditionTimer, true, 15 * NS_PER_SEC,
6284                          bucketStartTimeNs + 45 * NS_PER_SEC);
6285 
6286     // Value for key {{uid 2, uid 8}, kStateUnknown}.
6287     it++;
6288     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6289     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6290     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6291     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6292     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6293               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6294     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6295 
6296     // Base for dimension {uid 1, tag 16}.
6297     it++;
6298     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6299     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6300     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6301               itBase->second.currentState.getValues()[0].mValue.int_value);
6302     // Value for key {{uid 1, uid 16}, BACKGROUND}.
6303     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6304     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6305     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6306     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6307     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6308               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6309     assertConditionTimer(it->second.conditionTimer, true, 20 * NS_PER_SEC,
6310                          bucketStartTimeNs + 45 * NS_PER_SEC);
6311 
6312     // Base for dimension key {uid 1, tag 14}.
6313     it++;
6314     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6315     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6316               itBase->second.currentState.getValues()[0].mValue.int_value);
6317     // Value for key {{uid 1, tag 14}, BACKGROUND}.
6318     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6319     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6320     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6321     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6322     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6323               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6324     assertConditionTimer(it->second.conditionTimer, true, 20 * NS_PER_SEC,
6325                          bucketStartTimeNs + 45 * NS_PER_SEC);
6326 
6327     // Value for key {{uid 1, uid 16}, FOREGROUND}.
6328     it++;
6329     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6330     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6331     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6332     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6333     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6334               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6335     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6336                          bucketStartTimeNs + 20 * NS_PER_SEC);
6337 
6338     // Value for key {{uid 1, tag 16}, kStateUnknown}.
6339     it++;
6340     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6341     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6342     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6343     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6344     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6345               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6346     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6347 
6348     // Value for key {{uid 1, tag 14}, FOREGROUND}.
6349     it++;
6350     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6351     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6352     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6353     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6354     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6355               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6356     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6357                          bucketStartTimeNs + 20 * NS_PER_SEC);
6358 
6359     // Value for key {{uid 1, tag 14}, kStateUnknown}.
6360     it++;
6361     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6362     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6363     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6364     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6365     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6366               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6367     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6368 
6369     // Pull at end of first bucket.
6370     vector<shared_ptr<LogEvent>> allData;
6371     allData.push_back(
6372             CreateThreeValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 13, 14 /* tag */));
6373     allData.push_back(
6374             CreateThreeValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 13, 16 /* tag */));
6375     allData.push_back(
6376             CreateThreeValueLogEvent(tagId, bucket2StartTimeNs, 2 /*uid*/, 13, 8 /*tag*/));
6377     valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
6378 
6379     // Buckets flushed after end of first bucket.
6380     // All condition timers' behavior should rollover to bucket 2.
6381     ASSERT_EQ(8UL, valueProducer->mCurrentSlicedBucket.size());
6382     ASSERT_EQ(5UL, valueProducer->mPastBuckets.size());
6383     ASSERT_EQ(3UL, valueProducer->mCurrentBaseInfo.size());
6384     // Base for dimension {uid 2, tag 8}.
6385     it = valueProducer->mCurrentSlicedBucket.begin();
6386     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6387     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6388     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6389               itBase->second.currentState.getValues()[0].mValue.int_value);
6390     // Value for key {{uid 2, uid 8}, BACKGROUND}.
6391     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6392     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6393     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6394     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6395     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6396               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6397     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6398     ASSERT_EQ(1, valueProducer->mPastBuckets[it->first].size());
6399     EXPECT_EQ(30 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
6400 
6401     // Value for key {{uid 2, uid 8}, kStateUnknown}.
6402     it++;
6403     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6404     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6405     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6406     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6407     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6408               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6409     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6410 
6411     // Base for dimension {uid 1, tag 16}.
6412     it++;
6413     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6414     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6415     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6416               itBase->second.currentState.getValues()[0].mValue.int_value);
6417     // Value for key {{uid 1, uid 16}, BACKGROUND}.
6418     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6419     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6420     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6421     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6422     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6423               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6424     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6425     ASSERT_EQ(1, valueProducer->mPastBuckets[it->first].size());
6426     EXPECT_EQ(35 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
6427 
6428     // Base for dimension key {uid 1, tag 14}.
6429     it++;
6430     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6431     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6432               itBase->second.currentState.getValues()[0].mValue.int_value);
6433     // Value for key {{uid 1, tag 14}, BACKGROUND}.
6434     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6435     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6436     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6437     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6438     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6439               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6440     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6441     ASSERT_EQ(1, valueProducer->mPastBuckets[it->first].size());
6442     EXPECT_EQ(35 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
6443 
6444     // Value for key {{uid 1, uid 16}, FOREGROUND}.
6445     it++;
6446     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6447     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6448     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6449     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6450     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6451               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6452     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6453     ASSERT_EQ(1, valueProducer->mPastBuckets[it->first].size());
6454     EXPECT_EQ(10 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
6455 
6456     // Value for key {{uid 1, tag 16}, kStateUnknown}.
6457     it++;
6458     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6459     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6460     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6461     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6462     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6463               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6464     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6465 
6466     // Value for key {{uid 1, tag 14}, FOREGROUND}.
6467     it++;
6468     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6469     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6470     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6471     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6472     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6473               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6474     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6475     ASSERT_EQ(1, valueProducer->mPastBuckets[it->first].size());
6476     EXPECT_EQ(10 * NS_PER_SEC, valueProducer->mPastBuckets[it->first][0].mConditionTrueNs);
6477 
6478     // Value for key {{uid 1, tag 14}, kStateUnknown}.
6479     it++;
6480     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6481     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6482     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6483     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6484     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6485               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6486     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6487 
6488     // Bucket 2 status after uid 2 process state change Background->Foreground.
6489     uidProcessEvent =
6490             CreateUidProcessStateChangedEvent(bucket2StartTimeNs + 30 * NS_PER_SEC, 2 /* uid */,
6491                                               android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
6492     StateManager::getInstance().onLogEvent(*uidProcessEvent);
6493 
6494     ASSERT_EQ(9UL, valueProducer->mCurrentSlicedBucket.size());
6495     ASSERT_EQ(3UL, valueProducer->mCurrentBaseInfo.size());
6496     // Base for dimension {uid 2, tag 8}.
6497     it = valueProducer->mCurrentSlicedBucket.begin();
6498     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6499     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6500     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6501               itBase->second.currentState.getValues()[0].mValue.int_value);
6502     // Value for key {{uid 2, uid 8}, FOREGROUND}.
6503     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6504     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6505     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6506     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6507     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6508               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6509     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs + 30 * NS_PER_SEC);
6510 
6511     // Value for key {{uid 2, uid 8}, BACKGROUND}.
6512     it++;
6513     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6514     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6515     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6516     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6517     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6518               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6519     assertConditionTimer(it->second.conditionTimer, false, 30 * NS_PER_SEC,
6520                          bucket2StartTimeNs + 30 * NS_PER_SEC);
6521 
6522     // Value for key {{uid 2, uid 8}, kStateUnknown}.
6523     it++;
6524     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6525     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6526     EXPECT_EQ(8, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6527     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6528     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6529               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6530     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6531 
6532     // Base for dimension {uid 1, tag 16}.
6533     it++;
6534     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6535     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6536     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6537               itBase->second.currentState.getValues()[0].mValue.int_value);
6538     // Value for key {{uid 1, uid 16}, BACKGROUND}.
6539     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6540     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6541     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6542     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6543     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6544               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6545     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6546 
6547     // Base for dimension key {uid 1, tag 14}.
6548     it++;
6549     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
6550     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6551     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6552               itBase->second.currentState.getValues()[0].mValue.int_value);
6553     // Value for key {{uid 1, tag 14}, BACKGROUND}.
6554     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6555     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6556     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6557     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6558     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND,
6559               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6560     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6561 
6562     // Value for key {{uid 1, uid 16}, FOREGROUND}.
6563     it++;
6564     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6565     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6566     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6567     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6568     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6569               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6570     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6571 
6572     // Value for key {{uid 1, tag 16}, kStateUnknown}.
6573     it++;
6574     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6575     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6576     EXPECT_EQ(16, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6577     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6578     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6579               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6580     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6581 
6582     // Value for key {{uid 1, tag 14}, FOREGROUND}.
6583     it++;
6584     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6585     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6586     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6587     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6588     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND,
6589               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6590     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6591 
6592     // Value for key {{uid 1, tag 14}, kStateUnknown}.
6593     it++;
6594     ASSERT_EQ(2, it->first.getDimensionKeyInWhat().getValues().size());
6595     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
6596     EXPECT_EQ(14, it->first.getDimensionKeyInWhat().getValues()[1].mValue.int_value);
6597     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6598     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */,
6599               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6600     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6601 
6602     // Start dump report and check output.
6603     ProtoOutputStream output;
6604     std::set<string> strSet;
6605     valueProducer->onDumpReport(bucket2StartTimeNs + 50 * NS_PER_SEC,
6606                                 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
6607                                 &strSet, &output);
6608 
6609     StatsLogReport report = outputStreamToProto(&output);
6610     EXPECT_TRUE(report.has_value_metrics());
6611     ASSERT_EQ(6, report.value_metrics().data_size());
6612 
6613     // {{uid 1, tag 14}, FOREGROUND}.
6614     auto data = report.value_metrics().data(0);
6615     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6616     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
6617               data.slice_by_state(0).value());
6618     ASSERT_EQ(1, data.bucket_info_size());
6619     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6620 
6621     // {{uid 1, tag 16}, BACKGROUND}.
6622     data = report.value_metrics().data(1);
6623     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6624     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
6625               data.slice_by_state(0).value());
6626     ASSERT_EQ(2, data.bucket_info_size());
6627     EXPECT_EQ(35 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6628     EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
6629 
6630     // {{uid 1, tag 14}, BACKGROUND}.
6631     data = report.value_metrics().data(2);
6632     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6633     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
6634               data.slice_by_state(0).value());
6635     ASSERT_EQ(2, data.bucket_info_size());
6636     EXPECT_EQ(35 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6637     EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
6638 
6639     // {{uid 1, tag 16}, FOREGROUND}.
6640     data = report.value_metrics().data(3);
6641     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6642     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
6643               data.slice_by_state(0).value());
6644     ASSERT_EQ(1, data.bucket_info_size());
6645     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6646 
6647     // {{uid 2, tag 8}, FOREGROUND}.
6648     data = report.value_metrics().data(4);
6649     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6650     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
6651               data.slice_by_state(0).value());
6652     ASSERT_EQ(1, data.bucket_info_size());
6653     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6654 
6655     // {{uid 2, tag 8}, BACKGROUND}.
6656     data = report.value_metrics().data(5);
6657     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
6658     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
6659               data.slice_by_state(0).value());
6660     ASSERT_EQ(2, data.bucket_info_size());
6661     EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6662     EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
6663 }
6664 
TEST(ValueMetricProducerTest,TestSlicedStateWithCondition)6665 TEST(ValueMetricProducerTest, TestSlicedStateWithCondition) {
6666     // Set up ValueMetricProducer.
6667     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithConditionAndState(
6668             "BATTERY_SAVER_MODE_STATE");
6669     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
6670     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
6671             // Condition changed to true.
6672             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
6673                                 vector<std::shared_ptr<LogEvent>>* data) {
6674                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20 * NS_PER_SEC);
6675                 data->clear();
6676                 data->push_back(
6677                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20 * NS_PER_SEC, 3));
6678                 return true;
6679             }))
6680             // Battery saver mode state changed to OFF.
6681             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
6682                                 vector<std::shared_ptr<LogEvent>>* data) {
6683                 EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 30 * NS_PER_SEC);
6684                 data->clear();
6685                 data->push_back(
6686                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30 * NS_PER_SEC, 5));
6687                 return true;
6688             }))
6689             // Condition changed to false.
6690             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
6691                                 vector<std::shared_ptr<LogEvent>>* data) {
6692                 EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10 * NS_PER_SEC);
6693                 data->clear();
6694                 data->push_back(CreateRepeatedValueLogEvent(
6695                         tagId, bucket2StartTimeNs + 10 * NS_PER_SEC, 15));
6696                 return true;
6697             }));
6698 
6699     StateManager::getInstance().clear();
6700     sp<ValueMetricProducer> valueProducer =
6701             ValueMetricProducerTestHelper::createValueProducerWithConditionAndState(
6702                     pullerManager, metric, {util::BATTERY_SAVER_MODE_STATE_CHANGED}, {},
6703                     ConditionState::kFalse);
6704     EXPECT_EQ(1, valueProducer->mSlicedStateAtoms.size());
6705 
6706     // Set up StateManager and check that StateTrackers are initialized.
6707     StateManager::getInstance().registerListener(util::BATTERY_SAVER_MODE_STATE_CHANGED,
6708                                                  valueProducer);
6709     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
6710     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
6711                          util::BATTERY_SAVER_MODE_STATE_CHANGED));
6712 
6713     // Bucket status after battery saver mode ON event.
6714     // Condition is false so we do nothing.
6715     unique_ptr<LogEvent> batterySaverOnEvent =
6716             CreateBatterySaverOnEvent(/*timestamp=*/bucketStartTimeNs + 10 * NS_PER_SEC);
6717     StateManager::getInstance().onLogEvent(*batterySaverOnEvent);
6718     EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
6719     EXPECT_EQ(0UL, valueProducer->mCurrentBaseInfo.size());
6720 
6721     // Bucket status after condition change to true.
6722     valueProducer->onConditionChanged(true, bucketStartTimeNs + 20 * NS_PER_SEC);
6723     // Base for dimension key {}
6724     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
6725     std::unordered_map<HashableDimensionKey, ValueMetricProducer::DimensionsInWhatInfo>::iterator
6726             itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
6727     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
6728     EXPECT_EQ(3, itBase->second.baseInfos[0].base.long_value);
6729     EXPECT_TRUE(itBase->second.hasCurrentState);
6730     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6731     EXPECT_EQ(BatterySaverModeStateChanged::ON,
6732               itBase->second.currentState.getValues()[0].mValue.int_value);
6733     // Value for key {{}, ON}
6734     ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
6735     std::unordered_map<MetricDimensionKey, ValueMetricProducer::CurrentValueBucket>::iterator it =
6736             valueProducer->mCurrentSlicedBucket.begin();
6737     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6738     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6739     EXPECT_EQ(BatterySaverModeStateChanged::ON,
6740               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6741     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 20 * NS_PER_SEC);
6742     // Value for key {{}, -1}
6743     it++;
6744     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6745     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6746     EXPECT_EQ(-1 /*StateTracker::kUnknown*/,
6747               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6748     EXPECT_FALSE(it->second.intervals[0].hasValue);
6749     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6750 
6751     // Bucket status after battery saver mode OFF event.
6752     unique_ptr<LogEvent> batterySaverOffEvent =
6753             CreateBatterySaverOffEvent(/*timestamp=*/bucketStartTimeNs + 30 * NS_PER_SEC);
6754     StateManager::getInstance().onLogEvent(*batterySaverOffEvent);
6755     // Base for dimension key {}
6756     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
6757     itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
6758     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
6759     EXPECT_EQ(5, itBase->second.baseInfos[0].base.long_value);
6760     EXPECT_TRUE(itBase->second.hasCurrentState);
6761     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6762     EXPECT_EQ(BatterySaverModeStateChanged::OFF,
6763               itBase->second.currentState.getValues()[0].mValue.int_value);
6764     // Value for key {{}, OFF}
6765     ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
6766     it = valueProducer->mCurrentSlicedBucket.begin();
6767     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6768     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6769     EXPECT_EQ(BatterySaverModeStateChanged::OFF,
6770               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6771     assertConditionTimer(it->second.conditionTimer, true, 0, bucketStartTimeNs + 30 * NS_PER_SEC);
6772     // Value for key {{}, ON}
6773     it++;
6774     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6775     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6776     EXPECT_EQ(BatterySaverModeStateChanged::ON,
6777               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6778     EXPECT_TRUE(it->second.intervals[0].hasValue);
6779     EXPECT_EQ(2, it->second.intervals[0].value.long_value);
6780     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6781                          bucketStartTimeNs + 30 * NS_PER_SEC);
6782     // Value for key {{}, -1}
6783     it++;
6784     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6785 
6786     // Pull at end of first bucket.
6787     vector<shared_ptr<LogEvent>> allData;
6788     allData.clear();
6789     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 11));
6790     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
6791 
6792     EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
6793     EXPECT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
6794     // Base for dimension key {}
6795     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
6796     itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
6797     EXPECT_TRUE(itBase->second.baseInfos[0].hasBase);
6798     EXPECT_EQ(11, itBase->second.baseInfos[0].base.long_value);
6799     EXPECT_TRUE(itBase->second.hasCurrentState);
6800     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6801     EXPECT_EQ(BatterySaverModeStateChanged::OFF,
6802               itBase->second.currentState.getValues()[0].mValue.int_value);
6803     // Value for key {{}, OFF}
6804     it = valueProducer->mCurrentSlicedBucket.begin();
6805     assertConditionTimer(it->second.conditionTimer, true, 0, bucket2StartTimeNs);
6806     // Value for key {{}, ON}
6807     it++;
6808     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 30 * NS_PER_SEC);
6809     // Value for key {{}, -1}
6810     it++;
6811     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6812 
6813     // Bucket 2 status after condition change to false.
6814     valueProducer->onConditionChanged(false, bucket2StartTimeNs + 10 * NS_PER_SEC);
6815     // Base for dimension key {}
6816     ASSERT_EQ(1UL, valueProducer->mCurrentBaseInfo.size());
6817     itBase = valueProducer->mCurrentBaseInfo.find(DEFAULT_DIMENSION_KEY);
6818     EXPECT_FALSE(itBase->second.baseInfos[0].hasBase);
6819     EXPECT_TRUE(itBase->second.hasCurrentState);
6820     ASSERT_EQ(1, itBase->second.currentState.getValues().size());
6821     EXPECT_EQ(BatterySaverModeStateChanged::OFF,
6822               itBase->second.currentState.getValues()[0].mValue.int_value);
6823     // Value for key {{}, OFF}
6824     ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
6825     it = valueProducer->mCurrentSlicedBucket.begin();
6826     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6827     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6828     EXPECT_EQ(BatterySaverModeStateChanged::OFF,
6829               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6830     EXPECT_TRUE(it->second.intervals[0].hasValue);
6831     EXPECT_EQ(4, it->second.intervals[0].value.long_value);
6832     assertConditionTimer(it->second.conditionTimer, false, 10 * NS_PER_SEC,
6833                          bucket2StartTimeNs + 10 * NS_PER_SEC);
6834     // Value for key {{}, ON}
6835     it++;
6836     EXPECT_EQ(0, it->first.getDimensionKeyInWhat().getValues().size());
6837     ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
6838     EXPECT_EQ(BatterySaverModeStateChanged::ON,
6839               it->first.getStateValuesKey().getValues()[0].mValue.int_value);
6840     EXPECT_FALSE(it->second.intervals[0].hasValue);
6841     assertConditionTimer(it->second.conditionTimer, false, 0, bucketStartTimeNs + 30 * NS_PER_SEC);
6842     // Value for key {{}, -1}
6843     it++;
6844     assertConditionTimer(it->second.conditionTimer, false, 0, 0);
6845 
6846     // Start dump report and check output.
6847     ProtoOutputStream output;
6848     std::set<string> strSet;
6849     valueProducer->onDumpReport(bucket2StartTimeNs + 50 * NS_PER_SEC,
6850                                 true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
6851                                 &strSet, &output);
6852 
6853     StatsLogReport report = outputStreamToProto(&output);
6854     EXPECT_TRUE(report.has_value_metrics());
6855     ASSERT_EQ(2, report.value_metrics().data_size());
6856 
6857     ValueMetricData data = report.value_metrics().data(0);
6858     EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
6859     EXPECT_TRUE(data.slice_by_state(0).has_value());
6860     EXPECT_EQ(BatterySaverModeStateChanged::ON, data.slice_by_state(0).value());
6861     ASSERT_EQ(1, data.bucket_info_size());
6862     EXPECT_EQ(2, data.bucket_info(0).values(0).value_long());
6863     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6864 
6865     data = report.value_metrics().data(1);
6866     EXPECT_EQ(util::BATTERY_SAVER_MODE_STATE_CHANGED, data.slice_by_state(0).atom_id());
6867     EXPECT_TRUE(data.slice_by_state(0).has_value());
6868     EXPECT_EQ(BatterySaverModeStateChanged::OFF, data.slice_by_state(0).value());
6869     ASSERT_EQ(2, data.bucket_info_size());
6870     EXPECT_EQ(6, data.bucket_info(0).values(0).value_long());
6871     EXPECT_EQ(4, data.bucket_info(1).values(0).value_long());
6872     EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(0).condition_true_nanos());
6873     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(1).condition_true_nanos());
6874 }
6875 
6876 /*
6877  * Test bucket splits when condition is unknown.
6878  */
TEST(ValueMetricProducerTest,TestForcedBucketSplitWhenConditionUnknownSkipsBucket)6879 TEST(ValueMetricProducerTest, TestForcedBucketSplitWhenConditionUnknownSkipsBucket) {
6880     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
6881 
6882     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
6883 
6884     sp<ValueMetricProducer> valueProducer =
6885             ValueMetricProducerTestHelper::createValueProducerWithCondition(
6886                     pullerManager, metric,
6887                     ConditionState::kUnknown);
6888 
6889     // App update event.
6890     int64_t appUpdateTimeNs = bucketStartTimeNs + 1000;
6891     valueProducer->notifyAppUpgrade(appUpdateTimeNs);
6892 
6893     // Check dump report.
6894     ProtoOutputStream output;
6895     std::set<string> strSet;
6896     int64_t dumpReportTimeNs = bucketStartTimeNs + 10000000000; // 10 seconds
6897     valueProducer->onDumpReport(dumpReportTimeNs, false /* include current buckets */, true,
6898                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
6899 
6900     StatsLogReport report = outputStreamToProto(&output);
6901     EXPECT_TRUE(report.has_value_metrics());
6902     ASSERT_EQ(0, report.value_metrics().data_size());
6903     ASSERT_EQ(1, report.value_metrics().skipped_size());
6904 
6905     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
6906               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
6907     EXPECT_EQ(NanoToMillis(appUpdateTimeNs),
6908               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
6909     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
6910 
6911     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
6912     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
6913     EXPECT_EQ(NanoToMillis(appUpdateTimeNs), dropEvent.drop_time_millis());
6914 }
6915 
TEST(ValueMetricProducerTest,TestUploadThreshold)6916 TEST(ValueMetricProducerTest, TestUploadThreshold) {
6917     // Create metric with upload threshold and two value fields.
6918     int64_t thresholdValue = 15;
6919     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
6920     metric.mutable_value_field()->add_child()->set_field(3);
6921     metric.mutable_threshold()->set_gt_int(thresholdValue);
6922     *metric.mutable_dimensions_in_what() = CreateDimensions(tagId, {1 /*uid*/});
6923 
6924     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
6925 
6926     EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
6927             // First bucket pull.
6928             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
6929                                 vector<std::shared_ptr<LogEvent>>* data) {
6930                 data->clear();
6931                 data->push_back(
6932                         CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 1, 1 /*uid*/, 5, 5));
6933                 data->push_back(
6934                         CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 1, 2 /*uid*/, 5, 5));
6935                 return true;
6936             }))
6937             // Dump report.
6938             .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
6939                                 vector<std::shared_ptr<LogEvent>>* data) {
6940                 data->clear();
6941                 data->push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 10000000000,
6942                                                          1 /*uid*/, 22, 21));
6943                 data->push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 10000000000,
6944                                                          2 /*uid*/, 30, 10));
6945                 return true;
6946             }));
6947 
6948     sp<ValueMetricProducer> valueProducer =
6949         ValueMetricProducerTestHelper::createValueProducerNoConditions(
6950                 pullerManager, metric);
6951 
6952     // Bucket 2 start.
6953     vector<shared_ptr<LogEvent>> allData;
6954     allData.clear();
6955     allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, 1 /*uid*/, 21, 21));
6956     allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, 2 /*uid*/, 20, 5));
6957     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
6958 
6959     // Check dump report.
6960     ProtoOutputStream output;
6961     std::set<string> strSet;
6962     int64_t dumpReportTimeNs = bucket2StartTimeNs + 10000000000;
6963     valueProducer->onDumpReport(dumpReportTimeNs, true /* include current buckets */, true,
6964                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
6965 
6966     StatsLogReport report = outputStreamToProto(&output);
6967     backfillDimensionPath(&report);
6968     backfillStartEndTimestamp(&report);
6969     EXPECT_TRUE(report.has_value_metrics());
6970     StatsLogReport::ValueMetricDataWrapper valueMetrics;
6971     sortMetricDataByDimensionsValue(report.value_metrics(), &valueMetrics);
6972     ASSERT_EQ(1, valueMetrics.data_size());
6973     ASSERT_EQ(1, report.value_metrics().skipped_size());
6974 
6975     // Check data keyed to uid 1.
6976     ValueMetricData data = valueMetrics.data(0);
6977     ValidateUidDimension(data.dimensions_in_what(), tagId, 1);
6978     ASSERT_EQ(1, data.bucket_info_size());
6979     // First bucket.
6980     // Values pass threshold.
6981     ValidateValueBucket(data.bucket_info(0), bucketStartTimeNs, bucket2StartTimeNs, {16, 16}, -1);
6982     // Second bucket is dropped because values do not pass threshold.
6983 
6984     // Check data keyed to uid 2.
6985     // First bucket and second bucket are dropped because values do not pass threshold.
6986 
6987     // Check that second bucket has NO_DATA drop reason.
6988     EXPECT_EQ(bucket2StartTimeNs, report.value_metrics().skipped(0).start_bucket_elapsed_nanos());
6989     EXPECT_EQ(dumpReportTimeNs, report.value_metrics().skipped(0).end_bucket_elapsed_nanos());
6990     ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
6991     EXPECT_EQ(BucketDropReason::NO_DATA,
6992               report.value_metrics().skipped(0).drop_event(0).drop_reason());
6993 }
6994 
6995 }  // namespace statsd
6996 }  // namespace os
6997 }  // namespace android
6998 #else
6999 GTEST_LOG_(INFO) << "This test does nothing.\n";
7000 #endif
7001