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