1 // Copyright (C) 2019 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 <gtest/gtest.h>
16 
17 #include <vector>
18 
19 #include "src/StatsLogProcessor.h"
20 #include "src/state/StateTracker.h"
21 #include "src/stats_log_util.h"
22 #include "tests/statsd_test_util.h"
23 
24 namespace android {
25 namespace os {
26 namespace statsd {
27 
28 #ifdef __ANDROID__
29 
TEST(DurationMetricE2eTest,TestOneBucket)30 TEST(DurationMetricE2eTest, TestOneBucket) {
31     StatsdConfig config;
32 
33     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
34     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
35     *config.add_atom_matcher() = screenOnMatcher;
36     *config.add_atom_matcher() = screenOffMatcher;
37 
38     auto durationPredicate = CreateScreenIsOnPredicate();
39     *config.add_predicate() = durationPredicate;
40 
41     int64_t metricId = 123456;
42     auto durationMetric = config.add_duration_metric();
43     durationMetric->set_id(metricId);
44     durationMetric->set_what(durationPredicate.id());
45     durationMetric->set_bucket(FIVE_MINUTES);
46     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
47 
48     const int64_t baseTimeNs = 0;                                   // 0:00
49     const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
50     const int64_t bucketSizeNs =
51             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
52 
53     int uid = 12345;
54     int64_t cfgId = 98765;
55     ConfigKey cfgKey(uid, cfgId);
56 
57     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
58 
59     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
60     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
61     EXPECT_TRUE(metricsManager->isConfigValid());
62     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
63     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
64     EXPECT_TRUE(metricsManager->isActive());
65     EXPECT_TRUE(metricProducer->mIsActive);
66 
67     std::unique_ptr<LogEvent> event;
68 
69     // Screen is off at start of bucket.
70     event = CreateScreenStateChangedEvent(configAddedTimeNs,
71                                           android::view::DISPLAY_STATE_OFF);  // 0:01
72     processor->OnLogEvent(event.get());
73 
74     // Turn screen on.
75     const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC;  // 0:11
76     event = CreateScreenStateChangedEvent(durationStartNs, android::view::DISPLAY_STATE_ON);
77     processor->OnLogEvent(event.get());
78 
79     // Turn off screen 30 seconds after turning on.
80     const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC;  // 0:41
81     event = CreateScreenStateChangedEvent(durationEndNs, android::view::DISPLAY_STATE_OFF);
82     processor->OnLogEvent(event.get());
83 
84     event = CreateScreenBrightnessChangedEvent(durationEndNs + 1 * NS_PER_SEC, 64);  // 0:42
85     processor->OnLogEvent(event.get());
86 
87     ConfigMetricsReportList reports;
88     vector<uint8_t> buffer;
89     processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
90                             ADB_DUMP, FAST, &buffer);  // 5:01
91     EXPECT_TRUE(buffer.size() > 0);
92     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
93     backfillDimensionPath(&reports);
94     backfillStartEndTimestamp(&reports);
95     ASSERT_EQ(1, reports.reports_size());
96     ASSERT_EQ(1, reports.reports(0).metrics_size());
97     EXPECT_TRUE(reports.reports(0).metrics(0).has_estimated_data_bytes());
98     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
99     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
100 
101     StatsLogReport::DurationMetricDataWrapper durationMetrics;
102     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
103                                     &durationMetrics);
104     ASSERT_EQ(1, durationMetrics.data_size());
105 
106     DurationMetricData data = durationMetrics.data(0);
107     ASSERT_EQ(1, data.bucket_info_size());
108     EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
109     EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
110     EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
111 }
112 
TEST(DurationMetricE2eTest,TestTwoBuckets)113 TEST(DurationMetricE2eTest, TestTwoBuckets) {
114     StatsdConfig config;
115 
116     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
117     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
118     *config.add_atom_matcher() = screenOnMatcher;
119     *config.add_atom_matcher() = screenOffMatcher;
120 
121     auto durationPredicate = CreateScreenIsOnPredicate();
122     *config.add_predicate() = durationPredicate;
123 
124     int64_t metricId = 123456;
125     auto durationMetric = config.add_duration_metric();
126     durationMetric->set_id(metricId);
127     durationMetric->set_what(durationPredicate.id());
128     durationMetric->set_bucket(FIVE_MINUTES);
129     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
130 
131     const int64_t baseTimeNs = 0;                                   // 0:00
132     const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
133     const int64_t bucketSizeNs =
134             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
135 
136     int uid = 12345;
137     int64_t cfgId = 98765;
138     ConfigKey cfgKey(uid, cfgId);
139 
140     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
141 
142     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
143     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
144     EXPECT_TRUE(metricsManager->isConfigValid());
145     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
146     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
147     EXPECT_TRUE(metricsManager->isActive());
148     EXPECT_TRUE(metricProducer->mIsActive);
149 
150     std::unique_ptr<LogEvent> event;
151 
152     // Screen is off at start of bucket.
153     event = CreateScreenStateChangedEvent(configAddedTimeNs,
154                                           android::view::DISPLAY_STATE_OFF);  // 0:01
155     processor->OnLogEvent(event.get());
156 
157     // Turn screen on.
158     const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC;  // 0:11
159     event = CreateScreenStateChangedEvent(durationStartNs, android::view::DISPLAY_STATE_ON);
160     processor->OnLogEvent(event.get());
161 
162     // Turn off screen 30 seconds after turning on.
163     const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC;  // 0:41
164     event = CreateScreenStateChangedEvent(durationEndNs, android::view::DISPLAY_STATE_OFF);
165     processor->OnLogEvent(event.get());
166 
167     event = CreateScreenBrightnessChangedEvent(durationEndNs + 1 * NS_PER_SEC, 64);  // 0:42
168     processor->OnLogEvent(event.get());
169 
170     ConfigMetricsReportList reports;
171     vector<uint8_t> buffer;
172     processor->onDumpReport(cfgKey, configAddedTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, false,
173                             true, ADB_DUMP, FAST, &buffer);  // 10:01
174     EXPECT_TRUE(buffer.size() > 0);
175     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
176     backfillDimensionPath(&reports);
177     backfillStartEndTimestamp(&reports);
178     ASSERT_EQ(1, reports.reports_size());
179     ASSERT_EQ(1, reports.reports(0).metrics_size());
180     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
181     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
182 
183     StatsLogReport::DurationMetricDataWrapper durationMetrics;
184     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
185                                     &durationMetrics);
186     ASSERT_EQ(1, durationMetrics.data_size());
187 
188     DurationMetricData data = durationMetrics.data(0);
189     ASSERT_EQ(1, data.bucket_info_size());
190 
191     auto bucketInfo = data.bucket_info(0);
192     EXPECT_EQ(0, bucketInfo.bucket_num());
193     EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
194     EXPECT_EQ(configAddedTimeNs, bucketInfo.start_bucket_elapsed_nanos());
195     EXPECT_EQ(baseTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
196 }
197 
TEST(DurationMetricE2eTest,TestWithActivation)198 TEST(DurationMetricE2eTest, TestWithActivation) {
199     StatsdConfig config;
200 
201     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
202     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
203     auto crashMatcher = CreateProcessCrashAtomMatcher();
204     *config.add_atom_matcher() = screenOnMatcher;
205     *config.add_atom_matcher() = screenOffMatcher;
206     *config.add_atom_matcher() = crashMatcher;
207 
208     auto durationPredicate = CreateScreenIsOnPredicate();
209     *config.add_predicate() = durationPredicate;
210 
211     int64_t metricId = 123456;
212     auto durationMetric = config.add_duration_metric();
213     durationMetric->set_id(metricId);
214     durationMetric->set_what(durationPredicate.id());
215     durationMetric->set_bucket(FIVE_MINUTES);
216     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
217 
218     auto metric_activation1 = config.add_metric_activation();
219     metric_activation1->set_metric_id(metricId);
220     auto event_activation1 = metric_activation1->add_event_activation();
221     event_activation1->set_atom_matcher_id(crashMatcher.id());
222     event_activation1->set_ttl_seconds(30);  // 30 secs.
223 
224     const int64_t bucketStartTimeNs = 10000000000;
225     const int64_t bucketSizeNs =
226             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
227 
228     int uid = 12345;
229     int64_t cfgId = 98765;
230     ConfigKey cfgKey(uid, cfgId);
231 
232     sp<UidMap> m = new UidMap();
233     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
234     sp<AlarmMonitor> anomalyAlarmMonitor;
235     sp<AlarmMonitor> subscriberAlarmMonitor;
236     vector<int64_t> activeConfigsBroadcast;
237 
238     std::shared_ptr<MockLogEventFilter> mockLogEventFilter = std::make_shared<MockLogEventFilter>();
239     EXPECT_CALL(*mockLogEventFilter, setAtomIds(StatsLogProcessor::getDefaultAtomIdSet(), _))
240             .Times(1);
241 
242     int broadcastCount = 0;
243     StatsLogProcessor processor(
244             m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, bucketStartTimeNs,
245             [](const ConfigKey& key) { return true; },
246             [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
247                                                              const vector<int64_t>& activeConfigs) {
248                 broadcastCount++;
249                 EXPECT_EQ(broadcastUid, uid);
250                 activeConfigsBroadcast.clear();
251                 activeConfigsBroadcast.insert(activeConfigsBroadcast.end(), activeConfigs.begin(),
252                                               activeConfigs.end());
253                 return true;
254             },
255             [](const ConfigKey&, const string&, const vector<int64_t>&) {}, mockLogEventFilter);
256 
257     EXPECT_CALL(*mockLogEventFilter, setAtomIds(CreateAtomIdSetFromConfig(config), &processor))
258             .Times(1);
259 
260     processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);  // 0:00
261 
262     ASSERT_EQ(processor.mMetricsManagers.size(), 1u);
263     sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
264     EXPECT_TRUE(metricsManager->isConfigValid());
265     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
266     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
267     auto& eventActivationMap = metricProducer->mEventActivationMap;
268 
269     EXPECT_FALSE(metricsManager->isActive());
270     EXPECT_FALSE(metricProducer->mIsActive);
271     ASSERT_EQ(eventActivationMap.size(), 1u);
272     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
273     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
274     EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
275     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
276 
277     std::unique_ptr<LogEvent> event;
278 
279     // Turn screen off.
280     event = CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * NS_PER_SEC,
281                                           android::view::DISPLAY_STATE_OFF);  // 0:02
282     processor.OnLogEvent(event.get(), bucketStartTimeNs + 2 * NS_PER_SEC);
283 
284     // Turn screen on.
285     const int64_t durationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC;  // 0:05
286     event = CreateScreenStateChangedEvent(durationStartNs, android::view::DISPLAY_STATE_ON);
287     processor.OnLogEvent(event.get(), durationStartNs);
288 
289     // Activate metric.
290     const int64_t activationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC;  // 0:10
291     const int64_t activationEndNs =
292             activationStartNs + event_activation1->ttl_seconds() * NS_PER_SEC;  // 0:40
293     event = CreateAppCrashEvent(activationStartNs, 111);
294     processor.OnLogEvent(event.get(), activationStartNs);
295     EXPECT_TRUE(metricsManager->isActive());
296     EXPECT_TRUE(metricProducer->mIsActive);
297     EXPECT_EQ(broadcastCount, 1);
298     ASSERT_EQ(activeConfigsBroadcast.size(), 1);
299     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
300     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
301     EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
302     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
303 
304     // Expire activation.
305     const int64_t expirationNs = activationEndNs + 7 * NS_PER_SEC;
306     event = CreateScreenBrightnessChangedEvent(expirationNs, 64);  // 0:47
307     processor.OnLogEvent(event.get(), expirationNs);
308     EXPECT_FALSE(metricsManager->isActive());
309     EXPECT_FALSE(metricProducer->mIsActive);
310     EXPECT_EQ(broadcastCount, 2);
311     ASSERT_EQ(activeConfigsBroadcast.size(), 0);
312     ASSERT_EQ(eventActivationMap.size(), 1u);
313     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
314     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
315     EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
316     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
317 
318     // Turn off screen 10 seconds after activation expiration.
319     const int64_t durationEndNs = activationEndNs + 10 * NS_PER_SEC;  // 0:50
320     event = CreateScreenStateChangedEvent(durationEndNs, android::view::DISPLAY_STATE_OFF);
321     processor.OnLogEvent(event.get(), durationEndNs);
322 
323     // Turn screen on.
324     const int64_t duration2StartNs = durationEndNs + 5 * NS_PER_SEC;  // 0:55
325     event = CreateScreenStateChangedEvent(duration2StartNs, android::view::DISPLAY_STATE_ON);
326     processor.OnLogEvent(event.get(), duration2StartNs);
327 
328     // Turn off screen.
329     const int64_t duration2EndNs = duration2StartNs + 10 * NS_PER_SEC;  // 1:05
330     event = CreateScreenStateChangedEvent(duration2EndNs, android::view::DISPLAY_STATE_OFF);
331     processor.OnLogEvent(event.get(), duration2EndNs);
332 
333     // Activate metric.
334     const int64_t activation2StartNs = duration2EndNs + 5 * NS_PER_SEC;  // 1:10
335     const int64_t activation2EndNs =
336             activation2StartNs + event_activation1->ttl_seconds() * NS_PER_SEC;  // 1:40
337     event = CreateAppCrashEvent(activation2StartNs, 211);
338     processor.OnLogEvent(event.get(), activation2StartNs);
339     EXPECT_TRUE(metricsManager->isActive());
340     EXPECT_TRUE(metricProducer->mIsActive);
341     EXPECT_EQ(broadcastCount, 3);
342     ASSERT_EQ(activeConfigsBroadcast.size(), 1);
343     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
344     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
345     EXPECT_EQ(eventActivationMap[2]->start_ns, activation2StartNs);
346     EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
347 
348     ConfigMetricsReportList reports;
349     vector<uint8_t> buffer;
350     processor.onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
351                            ADB_DUMP, FAST, &buffer);  // 5:01
352     EXPECT_TRUE(buffer.size() > 0);
353     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
354     backfillDimensionPath(&reports);
355     backfillStartEndTimestamp(&reports);
356     ASSERT_EQ(1, reports.reports_size());
357     ASSERT_EQ(1, reports.reports(0).metrics_size());
358     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
359     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
360 
361     StatsLogReport::DurationMetricDataWrapper durationMetrics;
362     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
363                                     &durationMetrics);
364     ASSERT_EQ(1, durationMetrics.data_size());
365 
366     DurationMetricData data = durationMetrics.data(0);
367     ASSERT_EQ(1, data.bucket_info_size());
368 
369     auto bucketInfo = data.bucket_info(0);
370     EXPECT_EQ(0, bucketInfo.bucket_num());
371     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
372     EXPECT_EQ(expirationNs, bucketInfo.end_bucket_elapsed_nanos());
373     EXPECT_EQ(expirationNs - durationStartNs, bucketInfo.duration_nanos());
374 }
375 
TEST(DurationMetricE2eTest,TestWithCondition)376 TEST(DurationMetricE2eTest, TestWithCondition) {
377     StatsdConfig config;
378     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
379     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
380     *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
381     *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
382 
383     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
384     *config.add_predicate() = holdingWakelockPredicate;
385 
386     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
387     *config.add_predicate() = isInBackgroundPredicate;
388 
389     auto durationMetric = config.add_duration_metric();
390     durationMetric->set_id(StringToId("WakelockDuration"));
391     durationMetric->set_what(holdingWakelockPredicate.id());
392     durationMetric->set_condition(isInBackgroundPredicate.id());
393     durationMetric->set_aggregation_type(DurationMetric::SUM);
394     durationMetric->set_bucket(FIVE_MINUTES);
395 
396     ConfigKey cfgKey;
397     uint64_t bucketStartTimeNs = 10000000000;
398     uint64_t bucketSizeNs =
399             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
400     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
401     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
402     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
403     EXPECT_TRUE(metricsManager->isConfigValid());
404     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
405     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
406     auto& eventActivationMap = metricProducer->mEventActivationMap;
407     EXPECT_TRUE(metricsManager->isActive());
408     EXPECT_TRUE(metricProducer->mIsActive);
409     EXPECT_TRUE(eventActivationMap.empty());
410 
411     int appUid = 123;
412     vector<int> attributionUids1 = {appUid};
413     vector<string> attributionTags1 = {"App1"};
414     int64_t conditionStartTime1Ns = bucketStartTimeNs + 22 * NS_PER_SEC;
415     int64_t conditionEndTimeNs = bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC;
416     int64_t conditionStartTime2Ns = bucketStartTimeNs + (4 * 60 + 20) * NS_PER_SEC;
417     int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
418 
419     std::vector<std::unique_ptr<LogEvent>> events;
420     events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC,
421                                                 attributionUids1, attributionTags1,
422                                                 "wl1"));                           // 0:10
423     events.push_back(CreateMoveToBackgroundEvent(conditionStartTime1Ns, appUid));  // 0:22
424     events.push_back(CreateMoveToForegroundEvent(conditionEndTimeNs,
425                                                  appUid));  // 3:15
426     events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 4 * 60 * NS_PER_SEC,
427                                                 attributionUids1, attributionTags1,
428                                                 "wl1"));                           // 4:00
429     events.push_back(CreateMoveToBackgroundEvent(conditionStartTime2Ns, appUid));  // 4:20
430 
431     // Bucket 2.
432     events.push_back(CreateAcquireWakelockEvent(bucket2StartTimeNs + 10 * NS_PER_SEC,
433                                                 attributionUids1, attributionTags1,
434                                                 "wl1"));  // 5:10
435     // Send log events to StatsLogProcessor.
436     for (auto& event : events) {
437         processor->OnLogEvent(event.get());
438     }
439 
440     vector<uint8_t> buffer;
441     ConfigMetricsReportList reports;
442     int64_t dumpReportTimeNs = bucket2StartTimeNs + 40 * NS_PER_SEC;
443     processor->onDumpReport(cfgKey, dumpReportTimeNs, true, true, ADB_DUMP, FAST, &buffer);  // 5:40
444     ASSERT_GT(buffer.size(), 0);
445     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
446     backfillDimensionPath(&reports);
447     backfillStringInReport(&reports);
448     backfillStartEndTimestamp(&reports);
449 
450     ASSERT_EQ(1, reports.reports_size());
451     ASSERT_EQ(1, reports.reports(0).metrics_size());
452     StatsLogReport::DurationMetricDataWrapper durationMetrics;
453     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
454                                     &durationMetrics);
455     ASSERT_EQ(1, durationMetrics.data_size());
456 
457     // Validate bucket info.
458     ASSERT_EQ(2, durationMetrics.data(0).bucket_info_size());
459     ValidateDurationBucket(durationMetrics.data(0).bucket_info(0), bucketStartTimeNs,
460                            bucket2StartTimeNs, conditionEndTimeNs - conditionStartTime1Ns,
461                            (conditionEndTimeNs - conditionStartTime1Ns) +
462                                    (bucket2StartTimeNs - conditionStartTime2Ns));
463     ValidateDurationBucket(durationMetrics.data(0).bucket_info(1), bucket2StartTimeNs,
464                            dumpReportTimeNs, 30 * NS_PER_SEC,
465                            dumpReportTimeNs - bucket2StartTimeNs);
466 }
467 
TEST(DurationMetricE2eTest,TestWithSlicedCondition)468 TEST(DurationMetricE2eTest, TestWithSlicedCondition) {
469     StatsdConfig config;
470     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
471     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
472     *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
473     *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
474 
475     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
476     // The predicate is dimensioning by first attribution node by uid.
477     FieldMatcher dimensions = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED,
478                                                              {Position::FIRST});
479     *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
480     *config.add_predicate() = holdingWakelockPredicate;
481 
482     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
483     *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
484             CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
485     *config.add_predicate() = isInBackgroundPredicate;
486 
487     auto durationMetric = config.add_duration_metric();
488     durationMetric->set_id(StringToId("WakelockDuration"));
489     durationMetric->set_what(holdingWakelockPredicate.id());
490     durationMetric->set_condition(isInBackgroundPredicate.id());
491     durationMetric->set_aggregation_type(DurationMetric::SUM);
492     // The metric is dimensioning by first attribution node and only by uid.
493     *durationMetric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
494             util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
495     durationMetric->set_bucket(FIVE_MINUTES);
496 
497     // Links between wakelock state atom and condition of app is in background.
498     auto links = durationMetric->add_links();
499     links->set_condition(isInBackgroundPredicate.id());
500     *links->mutable_fields_in_what() =
501             CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
502     auto dimensionCondition = links->mutable_fields_in_condition();
503     dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED);
504     dimensionCondition->add_child()->set_field(1);  // uid field.
505 
506     ConfigKey cfgKey;
507     uint64_t bucketStartTimeNs = 10000000000;
508     uint64_t bucketSizeNs =
509             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
510     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
511     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
512     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
513     EXPECT_TRUE(metricsManager->isConfigValid());
514     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
515     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
516     auto& eventActivationMap = metricProducer->mEventActivationMap;
517     EXPECT_TRUE(metricsManager->isActive());
518     EXPECT_TRUE(metricProducer->mIsActive);
519     EXPECT_TRUE(eventActivationMap.empty());
520 
521     int appUid = 123;
522     std::vector<int> attributionUids1 = {appUid};
523     std::vector<string> attributionTags1 = {"App1"};
524 
525     auto event = CreateAcquireWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC, attributionUids1,
526                                             attributionTags1, "wl1");  // 0:10
527     processor->OnLogEvent(event.get());
528 
529     event = CreateMoveToBackgroundEvent(bucketStartTimeNs + 22 * NS_PER_SEC, appUid);  // 0:22
530     processor->OnLogEvent(event.get());
531 
532     event = CreateReleaseWakelockEvent(bucketStartTimeNs + 60 * NS_PER_SEC, attributionUids1,
533                                        attributionTags1, "wl1");  // 1:00
534     processor->OnLogEvent(event.get());
535 
536     event = CreateMoveToForegroundEvent(bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC,
537                                         appUid);  // 3:15
538     processor->OnLogEvent(event.get());
539 
540     vector<uint8_t> buffer;
541     ConfigMetricsReportList reports;
542     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
543                             FAST, &buffer);
544     ASSERT_GT(buffer.size(), 0);
545     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
546     backfillDimensionPath(&reports);
547     backfillStringInReport(&reports);
548     backfillStartEndTimestamp(&reports);
549 
550     ASSERT_EQ(1, reports.reports_size());
551     ASSERT_EQ(1, reports.reports(0).metrics_size());
552     StatsLogReport::DurationMetricDataWrapper durationMetrics;
553     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
554                                     &durationMetrics);
555     ASSERT_EQ(1, durationMetrics.data_size());
556 
557     DurationMetricData data = durationMetrics.data(0);
558     // Validate dimension value.
559     ValidateAttributionUidDimension(data.dimensions_in_what(),
560                                     util::WAKELOCK_STATE_CHANGED, appUid);
561     // Validate bucket info.
562     ASSERT_EQ(1, data.bucket_info_size());
563 
564     auto bucketInfo = data.bucket_info(0);
565     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
566     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
567     EXPECT_EQ(38 * NS_PER_SEC, bucketInfo.duration_nanos());
568 }
569 
TEST(DurationMetricE2eTest,TestWithActivationAndSlicedCondition)570 TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition) {
571     StatsdConfig config;
572     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
573     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
574     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
575     *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
576     *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
577     *config.add_atom_matcher() = screenOnMatcher;
578 
579     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
580     // The predicate is dimensioning by first attribution node by uid.
581     FieldMatcher dimensions = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED,
582                                                              {Position::FIRST});
583     *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
584     *config.add_predicate() = holdingWakelockPredicate;
585 
586     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
587     *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
588             CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
589     *config.add_predicate() = isInBackgroundPredicate;
590 
591     auto durationMetric = config.add_duration_metric();
592     durationMetric->set_id(StringToId("WakelockDuration"));
593     durationMetric->set_what(holdingWakelockPredicate.id());
594     durationMetric->set_condition(isInBackgroundPredicate.id());
595     durationMetric->set_aggregation_type(DurationMetric::SUM);
596     // The metric is dimensioning by first attribution node and only by uid.
597     *durationMetric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
598             util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
599     durationMetric->set_bucket(FIVE_MINUTES);
600 
601     // Links between wakelock state atom and condition of app is in background.
602     auto links = durationMetric->add_links();
603     links->set_condition(isInBackgroundPredicate.id());
604     *links->mutable_fields_in_what() =
605             CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
606     auto dimensionCondition = links->mutable_fields_in_condition();
607     dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED);
608     dimensionCondition->add_child()->set_field(1);  // uid field.
609 
610     auto metric_activation1 = config.add_metric_activation();
611     metric_activation1->set_metric_id(durationMetric->id());
612     auto event_activation1 = metric_activation1->add_event_activation();
613     event_activation1->set_atom_matcher_id(screenOnMatcher.id());
614     event_activation1->set_ttl_seconds(60 * 2);  // 2 minutes.
615 
616     ConfigKey cfgKey;
617     uint64_t bucketStartTimeNs = 10000000000;
618     uint64_t bucketSizeNs =
619             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
620     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
621     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
622     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
623     EXPECT_TRUE(metricsManager->isConfigValid());
624     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
625     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
626     auto& eventActivationMap = metricProducer->mEventActivationMap;
627     EXPECT_FALSE(metricsManager->isActive());
628     EXPECT_FALSE(metricProducer->mIsActive);
629     ASSERT_EQ(eventActivationMap.size(), 1u);
630     EXPECT_TRUE(eventActivationMap.find(4) != eventActivationMap.end());
631     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
632     EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
633     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
634 
635     int appUid = 123;
636     std::vector<int> attributionUids1 = {appUid};
637     std::vector<string> attributionTags1 = {"App1"};
638 
639     auto event = CreateAcquireWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC, attributionUids1,
640                                             attributionTags1, "wl1");  // 0:10
641     processor->OnLogEvent(event.get());
642     EXPECT_FALSE(metricsManager->isActive());
643     EXPECT_FALSE(metricProducer->mIsActive);
644     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
645     EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
646     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
647 
648     event = CreateMoveToBackgroundEvent(bucketStartTimeNs + 22 * NS_PER_SEC, appUid);  // 0:22
649     processor->OnLogEvent(event.get());
650     EXPECT_FALSE(metricsManager->isActive());
651     EXPECT_FALSE(metricProducer->mIsActive);
652     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
653     EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
654     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
655 
656     const int64_t durationStartNs = bucketStartTimeNs + 30 * NS_PER_SEC;  // 0:30
657     event = CreateScreenStateChangedEvent(durationStartNs, android::view::DISPLAY_STATE_ON);
658     processor->OnLogEvent(event.get());
659     EXPECT_TRUE(metricsManager->isActive());
660     EXPECT_TRUE(metricProducer->mIsActive);
661     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
662     EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
663     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
664 
665     const int64_t durationEndNs =
666             durationStartNs + (event_activation1->ttl_seconds() + 30) * NS_PER_SEC;  // 3:00
667     event = CreateAppCrashEvent(durationEndNs, 333);
668     processor->OnLogEvent(event.get());
669     EXPECT_FALSE(metricsManager->isActive());
670     EXPECT_FALSE(metricProducer->mIsActive);
671     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
672     EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
673     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
674 
675     event = CreateMoveToForegroundEvent(bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC,
676                                         appUid);  // 3:15
677     processor->OnLogEvent(event.get());
678 
679     event = CreateReleaseWakelockEvent(bucketStartTimeNs + (4 * 60 + 17) * NS_PER_SEC,
680                                        attributionUids1, attributionTags1, "wl1");  // 4:17
681     processor->OnLogEvent(event.get());
682 
683     event = CreateMoveToBackgroundEvent(bucketStartTimeNs + (4 * 60 + 20) * NS_PER_SEC,
684                                         appUid);  // 4:20
685     processor->OnLogEvent(event.get());
686 
687     event = CreateAcquireWakelockEvent(bucketStartTimeNs + (4 * 60 + 25) * NS_PER_SEC,
688                                        attributionUids1, attributionTags1, "wl1");  // 4:25
689     processor->OnLogEvent(event.get());
690 
691     const int64_t duration2StartNs = bucketStartTimeNs + (4 * 60 + 30) * NS_PER_SEC;  // 4:30
692     event = CreateScreenStateChangedEvent(duration2StartNs, android::view::DISPLAY_STATE_ON);
693     processor->OnLogEvent(event.get());
694     EXPECT_TRUE(metricsManager->isActive());
695     EXPECT_TRUE(metricProducer->mIsActive);
696     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
697     EXPECT_EQ(eventActivationMap[4]->start_ns, duration2StartNs);
698     EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
699 
700     vector<uint8_t> buffer;
701     ConfigMetricsReportList reports;
702     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
703                             FAST, &buffer);
704     ASSERT_GT(buffer.size(), 0);
705     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
706     backfillDimensionPath(&reports);
707     backfillStringInReport(&reports);
708     backfillStartEndTimestamp(&reports);
709 
710     ASSERT_EQ(1, reports.reports_size());
711     ASSERT_EQ(1, reports.reports(0).metrics_size());
712     StatsLogReport::DurationMetricDataWrapper durationMetrics;
713     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
714                                     &durationMetrics);
715     ASSERT_EQ(1, durationMetrics.data_size());
716 
717     DurationMetricData data = durationMetrics.data(0);
718     // Validate dimension value.
719     ValidateAttributionUidDimension(data.dimensions_in_what(),
720                                     util::WAKELOCK_STATE_CHANGED, appUid);
721     // Validate bucket info.
722     ASSERT_EQ(2, data.bucket_info_size());
723 
724     auto bucketInfo = data.bucket_info(0);
725     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
726     EXPECT_EQ(durationEndNs, bucketInfo.end_bucket_elapsed_nanos());
727     EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
728 
729     bucketInfo = data.bucket_info(1);
730     EXPECT_EQ(durationEndNs, bucketInfo.start_bucket_elapsed_nanos());
731     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
732     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - duration2StartNs, bucketInfo.duration_nanos());
733 }
734 
TEST(DurationMetricE2eTest,TestWithSlicedState)735 TEST(DurationMetricE2eTest, TestWithSlicedState) {
736     // Initialize config.
737     StatsdConfig config;
738 
739     *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher();
740     *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher();
741 
742     auto batterySaverModePredicate = CreateBatterySaverModePredicate();
743     *config.add_predicate() = batterySaverModePredicate;
744 
745     auto screenState = CreateScreenState();
746     *config.add_state() = screenState;
747 
748     // Create duration metric that slices by screen state.
749     auto durationMetric = config.add_duration_metric();
750     durationMetric->set_id(StringToId("DurationBatterySaverModeSliceScreen"));
751     durationMetric->set_what(batterySaverModePredicate.id());
752     durationMetric->add_slice_by_state(screenState.id());
753     durationMetric->set_aggregation_type(DurationMetric::SUM);
754     durationMetric->set_bucket(FIVE_MINUTES);
755 
756     // Initialize StatsLogProcessor.
757     int uid = 12345;
758     int64_t cfgId = 98765;
759     ConfigKey cfgKey(uid, cfgId);
760     uint64_t bucketStartTimeNs = 10000000000;  // 0:10
761     uint64_t bucketSizeNs =
762             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
763     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
764 
765     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
766     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
767     EXPECT_TRUE(metricsManager->isConfigValid());
768     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
769     EXPECT_TRUE(metricsManager->isActive());
770     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
771     EXPECT_TRUE(metricProducer->mIsActive);
772     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
773     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
774     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
775 
776     // Check that StateTrackers were initialized correctly.
777     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
778     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
779 
780     /*
781                bucket #1                      bucket #2
782     |     1     2     3     4     5     6     7     8     9     10 (minutes)
783     |-----------------------------|-----------------------------|--
784         ON              OFF     ON                                  (BatterySaverMode)
785       |          |                   |                              (ScreenIsOnEvent)
786            |                  |                                     (ScreenIsOffEvent)
787               |                                                     (ScreenDozeEvent)
788     */
789     // Initialize log events.
790     std::vector<std::unique_ptr<LogEvent>> events;
791     events.push_back(CreateScreenStateChangedEvent(
792             bucketStartTimeNs + 10 * NS_PER_SEC,
793             android::view::DisplayStateEnum::DISPLAY_STATE_ON));                       // 0:20
794     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
795     events.push_back(CreateScreenStateChangedEvent(
796             bucketStartTimeNs + 50 * NS_PER_SEC,
797             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:00
798     events.push_back(CreateScreenStateChangedEvent(
799             bucketStartTimeNs + 80 * NS_PER_SEC,
800             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 1:30
801     events.push_back(CreateScreenStateChangedEvent(
802             bucketStartTimeNs + 120 * NS_PER_SEC,
803             android::view::DisplayStateEnum::DISPLAY_STATE_ON));                         // 2:10
804     events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
805     events.push_back(CreateScreenStateChangedEvent(
806             bucketStartTimeNs + 250 * NS_PER_SEC,
807             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));                       // 4:20
808     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
809 
810     // Bucket boundary.
811     events.push_back(CreateScreenStateChangedEvent(
812             bucketStartTimeNs + 310 * NS_PER_SEC,
813             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 5:20
814 
815     // Send log events to StatsLogProcessor.
816     for (auto& event : events) {
817         processor->OnLogEvent(event.get());
818     }
819 
820     // Check dump report.
821     vector<uint8_t> buffer;
822     ConfigMetricsReportList reports;
823     processor->onDumpReport(cfgKey, bucketStartTimeNs + 360 * NS_PER_SEC,
824                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
825                             &buffer);  // 6:10
826     ASSERT_GT(buffer.size(), 0);
827     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
828     backfillDimensionPath(&reports);
829     backfillStringInReport(&reports);
830     backfillStartEndTimestamp(&reports);
831 
832     ASSERT_EQ(1, reports.reports_size());
833     ASSERT_EQ(1, reports.reports(0).metrics_size());
834     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
835     StatsLogReport::DurationMetricDataWrapper durationMetrics;
836     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
837                                     &durationMetrics);
838     ASSERT_EQ(3, durationMetrics.data_size());
839 
840     DurationMetricData data = durationMetrics.data(0);
841     ASSERT_EQ(1, data.slice_by_state_size());
842     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
843     EXPECT_TRUE(data.slice_by_state(0).has_value());
844     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
845     ASSERT_EQ(2, data.bucket_info_size());
846     EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
847     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
848     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
849     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
850     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
851     EXPECT_EQ(370 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
852 
853     data = durationMetrics.data(1);
854     ASSERT_EQ(1, data.slice_by_state_size());
855     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
856     EXPECT_TRUE(data.slice_by_state(0).has_value());
857     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
858     ASSERT_EQ(2, data.bucket_info_size());
859     EXPECT_EQ(110 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
860     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
861     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
862     EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
863     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
864     EXPECT_EQ(370 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
865 
866     data = durationMetrics.data(2);
867     ASSERT_EQ(1, data.slice_by_state_size());
868     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
869     EXPECT_TRUE(data.slice_by_state(0).has_value());
870     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE, data.slice_by_state(0).value());
871     ASSERT_EQ(1, data.bucket_info_size());
872     EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
873     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
874     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
875 }
876 
TEST(DurationMetricE2eTest,TestWithConditionAndSlicedState)877 TEST(DurationMetricE2eTest, TestWithConditionAndSlicedState) {
878     // Initialize config.
879     StatsdConfig config;
880 
881     *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher();
882     *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher();
883     *config.add_atom_matcher() = CreateBatteryStateNoneMatcher();
884     *config.add_atom_matcher() = CreateBatteryStateUsbMatcher();
885 
886     auto batterySaverModePredicate = CreateBatterySaverModePredicate();
887     *config.add_predicate() = batterySaverModePredicate;
888 
889     auto deviceUnpluggedPredicate = CreateDeviceUnpluggedPredicate();
890     *config.add_predicate() = deviceUnpluggedPredicate;
891 
892     auto screenState = CreateScreenState();
893     *config.add_state() = screenState;
894 
895     // Create duration metric that has a condition and slices by screen state.
896     auto durationMetric = config.add_duration_metric();
897     durationMetric->set_id(StringToId("DurationBatterySaverModeOnBatterySliceScreen"));
898     durationMetric->set_what(batterySaverModePredicate.id());
899     durationMetric->set_condition(deviceUnpluggedPredicate.id());
900     durationMetric->add_slice_by_state(screenState.id());
901     durationMetric->set_aggregation_type(DurationMetric::SUM);
902     durationMetric->set_bucket(FIVE_MINUTES);
903 
904     // Initialize StatsLogProcessor.
905     int uid = 12345;
906     int64_t cfgId = 98765;
907     ConfigKey cfgKey(uid, cfgId);
908     uint64_t bucketStartTimeNs = 10000000000;  // 0:10
909     uint64_t bucketSizeNs =
910             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
911     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
912 
913     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
914     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
915     EXPECT_TRUE(metricsManager->isConfigValid());
916     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
917     EXPECT_TRUE(metricsManager->isActive());
918     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
919     EXPECT_TRUE(metricProducer->mIsActive);
920     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
921     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
922     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
923 
924     // Check that StateTrackers were initialized correctly.
925     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
926     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
927 
928     /*
929                bucket #1                      bucket #2
930     |       1       2       3       4       5     6     7     8  (minutes)
931     |---------------------------------------|------------------
932              ON                          OFF    ON             (BatterySaverMode)
933                   T            F    T                          (DeviceUnpluggedPredicate)
934          |              |              |                       (ScreenIsOnEvent)
935                 |           |                       |          (ScreenIsOffEvent)
936                                 |                              (ScreenDozeEvent)
937     */
938     // Initialize log events.
939     std::vector<std::unique_ptr<LogEvent>> events;
940     events.push_back(CreateScreenStateChangedEvent(
941             bucketStartTimeNs + 20 * NS_PER_SEC,
942             android::view::DisplayStateEnum::DISPLAY_STATE_ON));                       // 0:30
943     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 60 * NS_PER_SEC));  // 1:10
944     events.push_back(CreateScreenStateChangedEvent(
945             bucketStartTimeNs + 80 * NS_PER_SEC,
946             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:30
947     events.push_back(
948             CreateBatteryStateChangedEvent(bucketStartTimeNs + 110 * NS_PER_SEC,
949                                            BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE));  // 2:00
950     events.push_back(CreateScreenStateChangedEvent(
951             bucketStartTimeNs + 145 * NS_PER_SEC,
952             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 2:35
953     events.push_back(CreateScreenStateChangedEvent(
954             bucketStartTimeNs + 170 * NS_PER_SEC,
955             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 3:00
956     events.push_back(
957             CreateBatteryStateChangedEvent(bucketStartTimeNs + 180 * NS_PER_SEC,
958                                            BatteryPluggedStateEnum::BATTERY_PLUGGED_USB));  // 3:10
959     events.push_back(CreateScreenStateChangedEvent(
960             bucketStartTimeNs + 200 * NS_PER_SEC,
961             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 3:30
962     events.push_back(
963             CreateBatteryStateChangedEvent(bucketStartTimeNs + 230 * NS_PER_SEC,
964                                            BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE));  // 4:00
965     events.push_back(CreateScreenStateChangedEvent(
966             bucketStartTimeNs + 260 * NS_PER_SEC,
967             android::view::DisplayStateEnum::DISPLAY_STATE_ON));                         // 4:30
968     events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
969 
970     // Bucket boundary.
971     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 320 * NS_PER_SEC));  // 5:30
972     events.push_back(CreateScreenStateChangedEvent(
973             bucketStartTimeNs + 380 * NS_PER_SEC,
974             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 6:30
975 
976     // Send log events to StatsLogProcessor.
977     for (auto& event : events) {
978         processor->OnLogEvent(event.get());
979     }
980 
981     // Check dump report.
982     vector<uint8_t> buffer;
983     ConfigMetricsReportList reports;
984     processor->onDumpReport(cfgKey, bucketStartTimeNs + 410 * NS_PER_SEC,
985                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
986                             &buffer);
987     ASSERT_GT(buffer.size(), 0);
988     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
989     backfillDimensionPath(&reports);
990     backfillStringInReport(&reports);
991     backfillStartEndTimestamp(&reports);
992 
993     ASSERT_EQ(1, reports.reports_size());
994     ASSERT_EQ(1, reports.reports(0).metrics_size());
995     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
996     StatsLogReport::DurationMetricDataWrapper durationMetrics;
997     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
998                                     &durationMetrics);
999     ASSERT_EQ(3, durationMetrics.data_size());
1000 
1001     DurationMetricData data = durationMetrics.data(0);
1002     ASSERT_EQ(1, data.slice_by_state_size());
1003     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1004     EXPECT_TRUE(data.slice_by_state(0).has_value());
1005     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
1006     ASSERT_EQ(2, data.bucket_info_size());
1007     EXPECT_EQ(45 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1008     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1009     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1010     EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1011     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1012     EXPECT_EQ(420 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1013 
1014     data = durationMetrics.data(1);
1015     ASSERT_EQ(1, data.slice_by_state_size());
1016     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1017     EXPECT_TRUE(data.slice_by_state(0).has_value());
1018     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
1019     ASSERT_EQ(2, data.bucket_info_size());
1020     EXPECT_EQ(45 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1021     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1022     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1023     EXPECT_EQ(60 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1024     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1025     EXPECT_EQ(420 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1026 
1027     data = durationMetrics.data(2);
1028     ASSERT_EQ(1, data.slice_by_state_size());
1029     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1030     EXPECT_TRUE(data.slice_by_state(0).has_value());
1031     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE, data.slice_by_state(0).value());
1032     ASSERT_EQ(1, data.bucket_info_size());
1033     EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1034     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1035     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1036 }
1037 
TEST(DurationMetricE2eTest,TestWithSlicedStateMapped)1038 TEST(DurationMetricE2eTest, TestWithSlicedStateMapped) {
1039     // Initialize config.
1040     StatsdConfig config;
1041 
1042     *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher();
1043     *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher();
1044 
1045     auto batterySaverModePredicate = CreateBatterySaverModePredicate();
1046     *config.add_predicate() = batterySaverModePredicate;
1047 
1048     int64_t screenOnId = 4444;
1049     int64_t screenOffId = 9876;
1050     auto screenStateWithMap = CreateScreenStateWithOnOffMap(screenOnId, screenOffId);
1051     *config.add_state() = screenStateWithMap;
1052 
1053     // Create duration metric that slices by mapped screen state.
1054     auto durationMetric = config.add_duration_metric();
1055     durationMetric->set_id(StringToId("DurationBatterySaverModeSliceScreenMapped"));
1056     durationMetric->set_what(batterySaverModePredicate.id());
1057     durationMetric->add_slice_by_state(screenStateWithMap.id());
1058     durationMetric->set_aggregation_type(DurationMetric::SUM);
1059     durationMetric->set_bucket(FIVE_MINUTES);
1060 
1061     // Initialize StatsLogProcessor.
1062     int uid = 12345;
1063     int64_t cfgId = 98765;
1064     ConfigKey cfgKey(uid, cfgId);
1065     uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1066     uint64_t bucketSizeNs =
1067             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
1068     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1069 
1070     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
1071     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
1072     EXPECT_TRUE(metricsManager->isConfigValid());
1073     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
1074     EXPECT_TRUE(metricsManager->isActive());
1075     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
1076     EXPECT_TRUE(metricProducer->mIsActive);
1077     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
1078     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
1079     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 1);
1080 
1081     // Check that StateTrackers were initialized correctly.
1082     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
1083     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
1084 
1085     /*
1086                bucket #1                      bucket #2
1087     |     1     2     3     4     5     6     7     8     9     10 (minutes)
1088     |-----------------------------|-----------------------------|--
1089         ON              OFF     ON                                  (BatterySaverMode)
1090      ---------------------------------------------------------SCREEN_OFF events
1091            |                  |                                  (ScreenStateOffEvent = 1)
1092               |                                                  (ScreenStateDozeEvent = 3)
1093                                                 |                (ScreenStateDozeSuspendEvent = 4)
1094      ---------------------------------------------------------SCREEN_ON events
1095       |          |                   |                           (ScreenStateOnEvent = 2)
1096                       |                                          (ScreenStateVrEvent = 5)
1097                                             |                    (ScreenStateOnSuspendEvent = 6)
1098     */
1099     // Initialize log events.
1100     std::vector<std::unique_ptr<LogEvent>> events;
1101     events.push_back(CreateScreenStateChangedEvent(
1102             bucketStartTimeNs + 10 * NS_PER_SEC,
1103             android::view::DisplayStateEnum::DISPLAY_STATE_ON));                       // 0:20
1104     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
1105     events.push_back(CreateScreenStateChangedEvent(
1106             bucketStartTimeNs + 70 * NS_PER_SEC,
1107             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:20
1108     events.push_back(CreateScreenStateChangedEvent(
1109             bucketStartTimeNs + 100 * NS_PER_SEC,
1110             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 1:50
1111     events.push_back(CreateScreenStateChangedEvent(
1112             bucketStartTimeNs + 120 * NS_PER_SEC,
1113             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 2:10
1114     events.push_back(CreateScreenStateChangedEvent(
1115             bucketStartTimeNs + 170 * NS_PER_SEC,
1116             android::view::DisplayStateEnum::DISPLAY_STATE_VR));                         // 3:00
1117     events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
1118     events.push_back(CreateScreenStateChangedEvent(
1119             bucketStartTimeNs + 250 * NS_PER_SEC,
1120             android::view::DisplayStateEnum::DISPLAY_STATE_OFF));                       // 4:20
1121     events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
1122 
1123     // Bucket boundary 5:10.
1124     events.push_back(CreateScreenStateChangedEvent(
1125             bucketStartTimeNs + 320 * NS_PER_SEC,
1126             android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 5:30
1127     events.push_back(CreateScreenStateChangedEvent(
1128             bucketStartTimeNs + 390 * NS_PER_SEC,
1129             android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND));  // 6:40
1130     events.push_back(CreateScreenStateChangedEvent(
1131             bucketStartTimeNs + 430 * NS_PER_SEC,
1132             android::view::DisplayStateEnum::DISPLAY_STATE_DOZE_SUSPEND));  // 7:20
1133     // Send log events to StatsLogProcessor.
1134     for (auto& event : events) {
1135         processor->OnLogEvent(event.get());
1136     }
1137 
1138     // Check dump report.
1139     vector<uint8_t> buffer;
1140     ConfigMetricsReportList reports;
1141     processor->onDumpReport(cfgKey, bucketStartTimeNs + 490 * NS_PER_SEC,
1142                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
1143                             &buffer);
1144     ASSERT_GT(buffer.size(), 0);
1145     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1146     backfillDimensionPath(&reports);
1147     backfillStringInReport(&reports);
1148     backfillStartEndTimestamp(&reports);
1149 
1150     ASSERT_EQ(1, reports.reports_size());
1151     ASSERT_EQ(1, reports.reports(0).metrics_size());
1152     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1153     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1154     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1155                                     &durationMetrics);
1156     ASSERT_EQ(2, durationMetrics.data_size());
1157 
1158     DurationMetricData data = durationMetrics.data(0);
1159     ASSERT_EQ(1, data.slice_by_state_size());
1160     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1161     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
1162     EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
1163     ASSERT_EQ(2, data.bucket_info_size());
1164     EXPECT_EQ(130 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1165     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1166     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1167     EXPECT_EQ(110 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1168     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1169     EXPECT_EQ(500 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1170 
1171     data = durationMetrics.data(1);
1172     ASSERT_EQ(1, data.slice_by_state_size());
1173     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1174     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
1175     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
1176     ASSERT_EQ(2, data.bucket_info_size());
1177     EXPECT_EQ(70 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1178     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1179     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1180     EXPECT_EQ(80 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1181     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1182     EXPECT_EQ(500 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1183 }
1184 
TEST(DurationMetricE2eTest,TestSlicedStatePrimaryFieldsNotSubsetDimInWhat)1185 TEST(DurationMetricE2eTest, TestSlicedStatePrimaryFieldsNotSubsetDimInWhat) {
1186     // Initialize config.
1187     StatsdConfig config;
1188 
1189     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
1190     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
1191 
1192     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
1193     *config.add_predicate() = holdingWakelockPredicate;
1194 
1195     auto uidProcessState = CreateUidProcessState();
1196     *config.add_state() = uidProcessState;
1197 
1198     // Create duration metric that slices by uid process state.
1199     auto durationMetric = config.add_duration_metric();
1200     durationMetric->set_id(StringToId("DurationHoldingWakelockSliceUidProcessState"));
1201     durationMetric->set_what(holdingWakelockPredicate.id());
1202     durationMetric->add_slice_by_state(uidProcessState.id());
1203     durationMetric->set_aggregation_type(DurationMetric::SUM);
1204     durationMetric->set_bucket(FIVE_MINUTES);
1205 
1206     // The state has only one primary field (uid).
1207     auto stateLink = durationMetric->add_state_link();
1208     stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
1209     auto fieldsInWhat = stateLink->mutable_fields_in_what();
1210     *fieldsInWhat = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
1211     auto fieldsInState = stateLink->mutable_fields_in_state();
1212     *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
1213 
1214     // Initialize StatsLogProcessor.
1215     int uid = 12345;
1216     int64_t cfgId = 98765;
1217     ConfigKey cfgKey(uid, cfgId);
1218     uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1219     uint64_t bucketSizeNs =
1220             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
1221     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1222 
1223     // This config is rejected because the dimension in what fields are not a superset of the sliced
1224     // state primary fields.
1225     ASSERT_EQ(processor->mMetricsManagers.size(), 0);
1226 }
1227 
TEST(DurationMetricE2eTest,TestWithSlicedStatePrimaryFieldsSubset)1228 TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset) {
1229     // Initialize config.
1230     StatsdConfig config;
1231 
1232     *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
1233     *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
1234 
1235     auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
1236     *(holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions()) =
1237             CreateAttributionUidAndOtherDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST},
1238                                                    {3 /* tag */});
1239     *config.add_predicate() = holdingWakelockPredicate;
1240 
1241     auto uidProcessState = CreateUidProcessState();
1242     *config.add_state() = uidProcessState;
1243 
1244     // Create duration metric that slices by uid process state.
1245     auto durationMetric = config.add_duration_metric();
1246     durationMetric->set_id(StringToId("DurationPartialWakelockPerTagUidSliceProcessState"));
1247     durationMetric->set_what(holdingWakelockPredicate.id());
1248     durationMetric->add_slice_by_state(uidProcessState.id());
1249     durationMetric->set_aggregation_type(DurationMetric::SUM);
1250     durationMetric->set_bucket(FIVE_MINUTES);
1251 
1252     // The metric is dimensioning by first uid of attribution node and tag.
1253     *durationMetric->mutable_dimensions_in_what() = CreateAttributionUidAndOtherDimensions(
1254             util::WAKELOCK_STATE_CHANGED, {Position::FIRST}, {3 /* tag */});
1255     // The state has only one primary field (uid).
1256     auto stateLink = durationMetric->add_state_link();
1257     stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
1258     auto fieldsInWhat = stateLink->mutable_fields_in_what();
1259     *fieldsInWhat = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
1260     auto fieldsInState = stateLink->mutable_fields_in_state();
1261     *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
1262 
1263     // Initialize StatsLogProcessor.
1264     int uid = 12345;
1265     int64_t cfgId = 98765;
1266     ConfigKey cfgKey(uid, cfgId);
1267     uint64_t bucketStartTimeNs = 10000000000;  // 0:10
1268     uint64_t bucketSizeNs =
1269             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
1270     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1271 
1272     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
1273     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
1274     EXPECT_TRUE(metricsManager->isConfigValid());
1275     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
1276     EXPECT_TRUE(metricsManager->isActive());
1277     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
1278     EXPECT_TRUE(metricProducer->mIsActive);
1279     ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
1280     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
1281     ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
1282 
1283     // Check that StateTrackers were initialized correctly.
1284     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
1285     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
1286 
1287     // Initialize log events.
1288     int appUid1 = 1001;
1289     int appUid2 = 1002;
1290     std::vector<int> attributionUids1 = {appUid1};
1291     std::vector<string> attributionTags1 = {"App1"};
1292 
1293     std::vector<int> attributionUids2 = {appUid2};
1294     std::vector<string> attributionTags2 = {"App2"};
1295 
1296     std::vector<std::unique_ptr<LogEvent>> events;
1297     events.push_back(CreateUidProcessStateChangedEvent(
1298             bucketStartTimeNs + 10 * NS_PER_SEC, appUid1,
1299             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));  // 0:20
1300     events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 20 * NS_PER_SEC,
1301                                                 attributionUids1, attributionTags1,
1302                                                 "wakelock1"));  // 0:30
1303     events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 25 * NS_PER_SEC,
1304                                                 attributionUids1, attributionTags1,
1305                                                 "wakelock2"));  // 0:35
1306     events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 30 * NS_PER_SEC,
1307                                                 attributionUids2, attributionTags2,
1308                                                 "wakelock1"));  // 0:40
1309     events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 35 * NS_PER_SEC,
1310                                                 attributionUids2, attributionTags2,
1311                                                 "wakelock2"));  // 0:45
1312     events.push_back(CreateUidProcessStateChangedEvent(
1313             bucketStartTimeNs + 50 * NS_PER_SEC, appUid2,
1314             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));  // 1:00
1315     events.push_back(CreateUidProcessStateChangedEvent(
1316             bucketStartTimeNs + 60 * NS_PER_SEC, appUid1,
1317             android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));  // 1:10
1318     events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 100 * NS_PER_SEC,
1319                                                 attributionUids2, attributionTags2,
1320                                                 "wakelock1"));  // 1:50
1321     events.push_back(CreateUidProcessStateChangedEvent(
1322             bucketStartTimeNs + 120 * NS_PER_SEC, appUid2,
1323             android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE));  // 2:10
1324     events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 200 * NS_PER_SEC,
1325                                                 attributionUids1, attributionTags1,
1326                                                 "wakelock2"));  // 3:30
1327 
1328     // Send log events to StatsLogProcessor.
1329     for (auto& event : events) {
1330         processor->OnLogEvent(event.get());
1331     }
1332 
1333     // Check dump report.
1334     vector<uint8_t> buffer;
1335     ConfigMetricsReportList reports;
1336     processor->onDumpReport(cfgKey, bucketStartTimeNs + 320 * NS_PER_SEC,
1337                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
1338                             &buffer);
1339     ASSERT_GT(buffer.size(), 0);
1340     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1341     backfillDimensionPath(&reports);
1342     backfillStringInReport(&reports);
1343     backfillStartEndTimestamp(&reports);
1344 
1345     ASSERT_EQ(1, reports.reports_size());
1346     ASSERT_EQ(1, reports.reports(0).metrics_size());
1347     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1348     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1349     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1350                                     &durationMetrics);
1351     ASSERT_EQ(9, durationMetrics.data_size());
1352 
1353     DurationMetricData data = durationMetrics.data(0);
1354     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1355                                                   "wakelock1");
1356     ASSERT_EQ(1, data.slice_by_state_size());
1357     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1358     EXPECT_TRUE(data.slice_by_state(0).has_value());
1359     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
1360               data.slice_by_state(0).value());
1361     ASSERT_EQ(1, data.bucket_info_size());
1362     EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1363     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1364     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1365 
1366     data = durationMetrics.data(1);
1367     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1368                                                   "wakelock1");
1369     ASSERT_EQ(1, data.slice_by_state_size());
1370     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1371     EXPECT_TRUE(data.slice_by_state(0).has_value());
1372     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1373               data.slice_by_state(0).value());
1374     ASSERT_EQ(2, data.bucket_info_size());
1375     EXPECT_EQ(240 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1376     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1377     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1378     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1379     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1380     EXPECT_EQ(330 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1381 
1382     data = durationMetrics.data(2);
1383     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1384                                                   "wakelock2");
1385     ASSERT_EQ(1, data.slice_by_state_size());
1386     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1387     EXPECT_TRUE(data.slice_by_state(0).has_value());
1388     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
1389               data.slice_by_state(0).value());
1390     ASSERT_EQ(1, data.bucket_info_size());
1391     EXPECT_EQ(35 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1392     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1393     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1394 
1395     data = durationMetrics.data(3);
1396     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1397                                                   "wakelock2");
1398     ASSERT_EQ(1, data.slice_by_state_size());
1399     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1400     EXPECT_TRUE(data.slice_by_state(0).has_value());
1401     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1402               data.slice_by_state(0).value());
1403     ASSERT_EQ(1, data.bucket_info_size());
1404     EXPECT_EQ(140 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1405     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1406     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1407 
1408     data = durationMetrics.data(4);
1409     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1410                                                   "wakelock1");
1411     ASSERT_EQ(1, data.slice_by_state_size());
1412     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1413     EXPECT_TRUE(data.slice_by_state(0).has_value());
1414     EXPECT_EQ(-1 /* StateTracker:: kStateUnknown */, data.slice_by_state(0).value());
1415     ASSERT_EQ(1, data.bucket_info_size());
1416     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1417     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1418     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1419 
1420     data = durationMetrics.data(5);
1421     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1422                                                   "wakelock1");
1423     ASSERT_EQ(1, data.slice_by_state_size());
1424     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1425     EXPECT_TRUE(data.slice_by_state(0).has_value());
1426     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1427               data.slice_by_state(0).value());
1428     ASSERT_EQ(1, data.bucket_info_size());
1429     EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1430     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1431     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1432 
1433     data = durationMetrics.data(6);
1434     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1435                                                   "wakelock2");
1436     ASSERT_EQ(1, data.slice_by_state_size());
1437     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1438     EXPECT_TRUE(data.slice_by_state(0).has_value());
1439     EXPECT_EQ(-1 /* StateTracker:: kStateUnknown */, data.slice_by_state(0).value());
1440     ASSERT_EQ(1, data.bucket_info_size());
1441     EXPECT_EQ(15 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1442     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1443     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1444 
1445     data = durationMetrics.data(7);
1446     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1447                                                   "wakelock2");
1448     ASSERT_EQ(1, data.slice_by_state_size());
1449     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1450     EXPECT_TRUE(data.slice_by_state(0).has_value());
1451     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
1452               data.slice_by_state(0).value());
1453     ASSERT_EQ(2, data.bucket_info_size());
1454     EXPECT_EQ(180 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1455     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1456     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1457     EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1458     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1459     EXPECT_EQ(330 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1460 
1461     data = durationMetrics.data(8);
1462     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1463                                                   "wakelock2");
1464     ASSERT_EQ(1, data.slice_by_state_size());
1465     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1466     EXPECT_TRUE(data.slice_by_state(0).has_value());
1467     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1468               data.slice_by_state(0).value());
1469     ASSERT_EQ(1, data.bucket_info_size());
1470     EXPECT_EQ(70 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1471     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1472     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1473 }
1474 
TEST(DurationMetricE2eTest,TestUploadThreshold)1475 TEST(DurationMetricE2eTest, TestUploadThreshold) {
1476     StatsdConfig config;
1477 
1478     auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
1479     auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
1480     *config.add_atom_matcher() = screenOnMatcher;
1481     *config.add_atom_matcher() = screenOffMatcher;
1482 
1483     auto durationPredicate = CreateScreenIsOnPredicate();
1484     *config.add_predicate() = durationPredicate;
1485 
1486     int64_t thresholdDurationNs = 30 * 1000 * 1000 * 1000LL;  // 30 seconds
1487     UploadThreshold threshold;
1488     threshold.set_gt_int(thresholdDurationNs);
1489 
1490     int64_t metricId = 123456;
1491     auto durationMetric = config.add_duration_metric();
1492     durationMetric->set_id(metricId);
1493     durationMetric->set_what(durationPredicate.id());
1494     durationMetric->set_bucket(FIVE_MINUTES);
1495     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
1496     *durationMetric->mutable_threshold() = threshold;
1497 
1498     const int64_t baseTimeNs = 0;                                   // 0:00
1499     const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
1500     const int64_t bucketSizeNs =
1501             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
1502 
1503     int uid = 12345;
1504     int64_t cfgId = 98765;
1505     ConfigKey cfgKey(uid, cfgId);
1506 
1507     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
1508 
1509     ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
1510     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
1511     EXPECT_TRUE(metricsManager->isConfigValid());
1512     ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
1513     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
1514     EXPECT_TRUE(metricsManager->isActive());
1515     EXPECT_TRUE(metricProducer->mIsActive);
1516 
1517     std::unique_ptr<LogEvent> event;
1518 
1519     // Screen is off at start of first bucket.
1520     event = CreateScreenStateChangedEvent(configAddedTimeNs,
1521                                           android::view::DISPLAY_STATE_OFF);  // 0:01
1522     processor->OnLogEvent(event.get());
1523 
1524     // Turn screen on.
1525     const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC;  // 0:11
1526     event = CreateScreenStateChangedEvent(durationStartNs, android::view::DISPLAY_STATE_ON);
1527     processor->OnLogEvent(event.get());
1528 
1529     // Turn off screen 30 seconds after turning on.
1530     const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC;  // 0:41
1531     event = CreateScreenStateChangedEvent(durationEndNs, android::view::DISPLAY_STATE_OFF);
1532     processor->OnLogEvent(event.get());
1533 
1534     // Turn screen on in second bucket.
1535     const int64_t duration2StartNs = configAddedTimeNs + bucketSizeNs + 10 * NS_PER_SEC;  // 5:11
1536     event = CreateScreenStateChangedEvent(duration2StartNs, android::view::DISPLAY_STATE_ON);
1537     processor->OnLogEvent(event.get());
1538 
1539     // Turn off screen 31 seconds after turning on.
1540     const int64_t duration2EndNs = duration2StartNs + 31 * NS_PER_SEC;  // 5:42
1541     event = CreateScreenStateChangedEvent(duration2EndNs, android::view::DISPLAY_STATE_OFF);
1542     processor->OnLogEvent(event.get());
1543 
1544     ConfigMetricsReportList reports;
1545     vector<uint8_t> buffer;
1546     processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs * 2 + 1 * NS_PER_SEC, false,
1547                             true, ADB_DUMP, FAST, &buffer);  // 10:01
1548     EXPECT_TRUE(buffer.size() > 0);
1549     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1550     backfillDimensionPath(&reports);
1551     backfillStartEndTimestamp(&reports);
1552     ASSERT_EQ(1, reports.reports_size());
1553     ASSERT_EQ(1, reports.reports(0).metrics_size());
1554     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
1555     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1556 
1557     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1558     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1559                                     &durationMetrics);
1560     ASSERT_EQ(1, durationMetrics.data_size());
1561 
1562     DurationMetricData data = durationMetrics.data(0);
1563     ASSERT_EQ(1, data.bucket_info_size());
1564     EXPECT_EQ(duration2EndNs - duration2StartNs, data.bucket_info(0).duration_nanos());
1565     EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
1566     EXPECT_EQ(baseTimeNs + bucketSizeNs * 2, data.bucket_info(0).end_bucket_elapsed_nanos());
1567 }
1568 
TEST(DurationMetricE2eTest,TestConditionOnRepeatedEnumField)1569 TEST(DurationMetricE2eTest, TestConditionOnRepeatedEnumField) {
1570     StatsdConfig config;
1571 
1572     AtomMatcher repeatedStateFirstOffAtomMatcher = CreateTestAtomRepeatedStateFirstOffAtomMatcher();
1573     AtomMatcher repeatedStateFirstOnAtomMatcher = CreateTestAtomRepeatedStateFirstOnAtomMatcher();
1574     *config.add_atom_matcher() = repeatedStateFirstOffAtomMatcher;
1575     *config.add_atom_matcher() = repeatedStateFirstOnAtomMatcher;
1576 
1577     Predicate durationPredicate = CreateTestAtomRepeatedStateFirstOffPredicate();
1578     *config.add_predicate() = durationPredicate;
1579 
1580     int64_t metricId = 123456;
1581     DurationMetric* durationMetric = config.add_duration_metric();
1582     durationMetric->set_id(metricId);
1583     durationMetric->set_what(durationPredicate.id());
1584     durationMetric->set_bucket(FIVE_MINUTES);
1585     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
1586 
1587     const int64_t baseTimeNs = 0;                                   // 0:00
1588     const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
1589     const int64_t bucketSizeNs =
1590             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
1591 
1592     int uid = 12345;
1593     int64_t cfgId = 98765;
1594     ConfigKey cfgKey(uid, cfgId);
1595 
1596     sp<StatsLogProcessor> processor =
1597             CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
1598 
1599     vector<int> intArray = {3, 6};
1600     vector<int64_t> longArray = {1000L, 10002L};
1601     vector<float> floatArray = {0.3f, 0.09f};
1602     vector<string> stringArray = {"str1", "str2"};
1603     int boolArrayLength = 2;
1604     bool boolArray[boolArrayLength];
1605     boolArray[0] = 1;
1606     boolArray[1] = 0;
1607     vector<int> enumArrayOff = {TestAtomReported::OFF, TestAtomReported::ON};
1608     vector<int> enumArrayOn = {TestAtomReported::ON, TestAtomReported::OFF};
1609 
1610     std::vector<std::unique_ptr<LogEvent>> events;
1611     uint64_t falseDurationStartNs = configAddedTimeNs + 10 * NS_PER_SEC;
1612     uint64_t durationStartNs = configAddedTimeNs + 20 * NS_PER_SEC;
1613     uint64_t durationEndNs = durationStartNs + 50 * NS_PER_SEC;
1614 
1615     // Condition false
1616     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(falseDurationStartNs, {}, {},
1617                                                                        {}, {}, {}, 0, enumArrayOn));
1618     // Condition true - start collecting duration.
1619     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(durationStartNs, {}, {}, {},
1620                                                                        {}, {}, 0, enumArrayOff));
1621     // Condition false - stop collecting duration.
1622     events.push_back(CreateTestAtomReportedEventVariableRepeatedFields(durationEndNs, {}, {}, {},
1623                                                                        {}, {}, 0, enumArrayOn));
1624 
1625     // Send log events to StatsLogProcessor.
1626     for (auto& event : events) {
1627         processor->OnLogEvent(event.get());
1628     }
1629 
1630     ConfigMetricsReportList reports;
1631     vector<uint8_t> buffer;
1632     processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
1633                             ADB_DUMP, FAST, &buffer);  // 10:01
1634     EXPECT_TRUE(buffer.size() > 0);
1635     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1636     backfillDimensionPath(&reports);
1637     backfillStartEndTimestamp(&reports);
1638     ASSERT_EQ(1, reports.reports_size());
1639     ASSERT_EQ(1, reports.reports(0).metrics_size());
1640     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
1641     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1642 
1643     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1644     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1645                                     &durationMetrics);
1646     ASSERT_EQ(1, durationMetrics.data_size());
1647 
1648     DurationMetricData data = durationMetrics.data(0);
1649     ASSERT_EQ(1, data.bucket_info_size());
1650     EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
1651     EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
1652     EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
1653 }
1654 
TEST(DurationMetricE2eTest,TestDimensionalSampling)1655 TEST(DurationMetricE2eTest, TestDimensionalSampling) {
1656     ShardOffsetProvider::getInstance().setShardOffset(5);
1657 
1658     StatsdConfig config;
1659 
1660     *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
1661     *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
1662     AtomMatcher stopAllMatcher = CreateScheduleScheduledJobAtomMatcher();
1663     *config.add_atom_matcher() = stopAllMatcher;
1664 
1665     Predicate scheduledJobPredicate = CreateScheduledJobPredicate();
1666     *scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions() =
1667             CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
1668     SimplePredicate* simplePredicate = scheduledJobPredicate.mutable_simple_predicate();
1669     simplePredicate->set_stop_all(stopAllMatcher.id());
1670     *config.add_predicate() = scheduledJobPredicate;
1671 
1672     DurationMetric sampledDurationMetric = createDurationMetric(
1673             "DurationSampledScheduledJobPerUid", scheduledJobPredicate.id(), nullopt, {});
1674     sampledDurationMetric.set_aggregation_type(DurationMetric::SUM);
1675     *sampledDurationMetric.mutable_dimensions_in_what() =
1676             CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
1677     *sampledDurationMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
1678             CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
1679     sampledDurationMetric.mutable_dimensional_sampling_info()->set_shard_count(2);
1680     *config.add_duration_metric() = sampledDurationMetric;
1681 
1682     const int64_t configAddedTimeNs = 1 * NS_PER_SEC;  // 0:01
1683     const int64_t bucketSizeNs =
1684             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
1685 
1686     int uid = 12345;
1687     int64_t cfgId = 98765;
1688     ConfigKey cfgKey(uid, cfgId);
1689 
1690     sp<StatsLogProcessor> processor = CreateStatsLogProcessor(
1691             configAddedTimeNs, configAddedTimeNs, config, cfgKey, nullptr, 0, new UidMap());
1692 
1693     int uid1 = 1001;  // odd hash value
1694     int uid2 = 1002;  // even hash value
1695     int uid3 = 1003;  // odd hash value
1696 
1697     const int64_t durationStartNs1 = 20 * NS_PER_SEC;
1698     const int64_t durationStartNs2 = 40 * NS_PER_SEC;
1699     const int64_t durationStartNs3 = 60 * NS_PER_SEC;
1700     const int64_t durationStartNs4 = 80 * NS_PER_SEC;
1701     const int64_t durationEndNs1 = 100 * NS_PER_SEC;
1702     const int64_t durationEndNs2 = 110 * NS_PER_SEC;
1703     const int64_t stopAllNs = 130 * NS_PER_SEC;
1704     const int64_t durationEndNs3 = 150 * NS_PER_SEC;
1705     const int64_t durationEndNs4 = 200 * NS_PER_SEC;
1706 
1707     std::vector<std::unique_ptr<LogEvent>> events;
1708     events.push_back(CreateStartScheduledJobEvent(durationStartNs1, {uid1}, {"App1"}, "job1"));
1709     events.push_back(CreateStartScheduledJobEvent(durationStartNs2, {uid2}, {"App2"}, "job2"));
1710     events.push_back(CreateStartScheduledJobEvent(durationStartNs3, {uid3}, {"App3"}, "job3"));
1711     events.push_back(CreateFinishScheduledJobEvent(durationEndNs1, {uid1}, {"App1"}, "job1"));
1712     events.push_back(CreateFinishScheduledJobEvent(durationEndNs2, {uid2}, {"App2"}, "job2"));
1713     // This event should pass the sample check regardless of the uid.
1714     events.push_back(CreateScheduleScheduledJobEvent(stopAllNs, {uid2}, {"App2"}, "job2"));
1715     // These events shouldn't do anything since all jobs were stopped with the cancel event.
1716     events.push_back(CreateFinishScheduledJobEvent(durationEndNs3, {uid3}, {"App3"}, "job3"));
1717 
1718     // Send log events to StatsLogProcessor.
1719     for (auto& event : events) {
1720         processor->OnLogEvent(event.get());
1721     }
1722 
1723     ConfigMetricsReportList reports;
1724     vector<uint8_t> buffer;
1725     processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
1726                             FAST, &buffer);
1727     EXPECT_TRUE(buffer.size() > 0);
1728     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1729     backfillDimensionPath(&reports);
1730     backfillStartEndTimestamp(&reports);
1731 
1732     ASSERT_EQ(1, reports.reports_size());
1733     ASSERT_EQ(1, reports.reports(0).metrics_size());
1734     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
1735     StatsLogReport::DurationMetricDataWrapper durationMetrics;
1736     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1737                                     &durationMetrics);
1738     ASSERT_EQ(2, durationMetrics.data_size());
1739 
1740     // Only Uid 1 and 3 are logged. (odd hash value) + (offset of 5) % (shard count of 2) = 0
1741     DurationMetricData data = durationMetrics.data(0);
1742     ValidateAttributionUidDimension(data.dimensions_in_what(), util::SCHEDULED_JOB_STATE_CHANGED,
1743                                     uid1);
1744     ValidateDurationBucket(data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs,
1745                            durationEndNs1 - durationStartNs1);
1746 
1747     data = durationMetrics.data(1);
1748     ValidateAttributionUidDimension(data.dimensions_in_what(), util::SCHEDULED_JOB_STATE_CHANGED,
1749                                     uid3);
1750     ValidateDurationBucket(data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs,
1751                            stopAllNs - durationStartNs3);
1752 }
1753 
1754 #else
1755 GTEST_LOG_(INFO) << "This test does nothing.\n";
1756 #endif
1757 
1758 }  // namespace statsd
1759 }  // namespace os
1760 }  // namespace android
1761