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