blob: d59ec3ef4a29aeb95d877c84c4d5e616f2791646 [file] [log] [blame]
Muhammad Qureshi18e46922019-05-24 16:38:49 -07001// 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
tsaichristine1449fa42020-01-02 12:12:05 -080017#include <vector>
18
Muhammad Qureshi18e46922019-05-24 16:38:49 -070019#include "src/StatsLogProcessor.h"
tsaichristine1449fa42020-01-02 12:12:05 -080020#include "src/state/StateTracker.h"
Muhammad Qureshi18e46922019-05-24 16:38:49 -070021#include "src/stats_log_util.h"
22#include "tests/statsd_test_util.h"
23
Muhammad Qureshi18e46922019-05-24 16:38:49 -070024namespace android {
25namespace os {
26namespace statsd {
27
28#ifdef __ANDROID__
29
tsaichristine7747d372020-02-28 17:36:59 -080030TEST(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 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
61 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
62 EXPECT_TRUE(metricsManager->isConfigValid());
63 EXPECT_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 EXPECT_EQ(1, reports.reports_size());
97 EXPECT_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
Tej Singh5d823b32019-05-21 20:13:21 -0700101 StatsLogReport::DurationMetricDataWrapper durationMetrics;
102 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
103 &durationMetrics);
tsaichristine7747d372020-02-28 17:36:59 -0800104 EXPECT_EQ(1, durationMetrics.data_size());
105
tsaichristine1449fa42020-01-02 12:12:05 -0800106 DurationMetricData data = durationMetrics.data(0);
tsaichristine7747d372020-02-28 17:36:59 -0800107 EXPECT_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
113TEST(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 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
144 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
145 EXPECT_TRUE(metricsManager->isConfigValid());
146 EXPECT_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 EXPECT_EQ(1, reports.reports_size());
180 EXPECT_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
Tej Singh5d823b32019-05-21 20:13:21 -0700184 StatsLogReport::DurationMetricDataWrapper durationMetrics;
185 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
186 &durationMetrics);
tsaichristine7747d372020-02-28 17:36:59 -0800187 EXPECT_EQ(1, durationMetrics.data_size());
188
tsaichristine1449fa42020-01-02 12:12:05 -0800189 DurationMetricData data = durationMetrics.data(0);
tsaichristine7747d372020-02-28 17:36:59 -0800190 EXPECT_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
199TEST(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 EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
257 sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
258 EXPECT_TRUE(metricsManager->isConfigValid());
259 EXPECT_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 EXPECT_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 EXPECT_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 EXPECT_EQ(activeConfigsBroadcast.size(), 0);
306 EXPECT_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 EXPECT_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 EXPECT_EQ(1, reports.reports_size());
351 EXPECT_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
Tej Singh5d823b32019-05-21 20:13:21 -0700355 StatsLogReport::DurationMetricDataWrapper durationMetrics;
356 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
357 &durationMetrics);
tsaichristine7747d372020-02-28 17:36:59 -0800358 EXPECT_EQ(1, durationMetrics.data_size());
359
tsaichristine1449fa42020-01-02 12:12:05 -0800360 DurationMetricData data = durationMetrics.data(0);
tsaichristine7747d372020-02-28 17:36:59 -0800361 EXPECT_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
370TEST(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 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
397 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
398 EXPECT_TRUE(metricsManager->isConfigValid());
399 EXPECT_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 EXPECT_GT(buffer.size(), 0);
432 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
433 backfillDimensionPath(&reports);
434 backfillStringInReport(&reports);
435 backfillStartEndTimestamp(&reports);
436
437 EXPECT_EQ(1, reports.reports_size());
438 EXPECT_EQ(1, reports.reports(0).metrics_size());
Tej Singh5d823b32019-05-21 20:13:21 -0700439 StatsLogReport::DurationMetricDataWrapper durationMetrics;
440 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
441 &durationMetrics);
442 EXPECT_EQ(1, durationMetrics.data_size());
tsaichristine7747d372020-02-28 17:36:59 -0800443
Tej Singh5d823b32019-05-21 20:13:21 -0700444 DurationMetricData data = durationMetrics.data(0);
tsaichristine7747d372020-02-28 17:36:59 -0800445
446 // Validate bucket info.
447 EXPECT_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
455TEST(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.
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700466 FieldMatcher dimensions = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED,
tsaichristine7747d372020-02-28 17:36:59 -0800467 {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() =
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700473 CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
tsaichristine7747d372020-02-28 17:36:59 -0800474 *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(
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700483 util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
tsaichristine7747d372020-02-28 17:36:59 -0800484 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 auto dimensionWhat = links->mutable_fields_in_what();
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700490 dimensionWhat->set_field(util::WAKELOCK_STATE_CHANGED);
tsaichristine7747d372020-02-28 17:36:59 -0800491 dimensionWhat->add_child()->set_field(1); // uid field.
492 *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700493 util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
tsaichristine7747d372020-02-28 17:36:59 -0800494
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 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
501 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
502 EXPECT_TRUE(metricsManager->isConfigValid());
503 EXPECT_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 EXPECT_GT(buffer.size(), 0);
534 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
535 backfillDimensionPath(&reports);
536 backfillStringInReport(&reports);
537 backfillStartEndTimestamp(&reports);
538
539 EXPECT_EQ(1, reports.reports_size());
540 EXPECT_EQ(1, reports.reports(0).metrics_size());
Tej Singh5d823b32019-05-21 20:13:21 -0700541 StatsLogReport::DurationMetricDataWrapper durationMetrics;
542 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
543 &durationMetrics);
544 EXPECT_EQ(1, durationMetrics.data_size());
tsaichristine7747d372020-02-28 17:36:59 -0800545
Tej Singh5d823b32019-05-21 20:13:21 -0700546 DurationMetricData data = durationMetrics.data(0);
tsaichristine7747d372020-02-28 17:36:59 -0800547 // Validate dimension value.
548 ValidateAttributionUidDimension(data.dimensions_in_what(),
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700549 util::WAKELOCK_STATE_CHANGED, appUid);
tsaichristine7747d372020-02-28 17:36:59 -0800550 // Validate bucket info.
551 EXPECT_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
559TEST(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.
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700571 FieldMatcher dimensions = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED,
tsaichristine7747d372020-02-28 17:36:59 -0800572 {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() =
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700578 CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
tsaichristine7747d372020-02-28 17:36:59 -0800579 *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(
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700588 util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
tsaichristine7747d372020-02-28 17:36:59 -0800589 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 auto dimensionWhat = links->mutable_fields_in_what();
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700595 dimensionWhat->set_field(util::WAKELOCK_STATE_CHANGED);
tsaichristine7747d372020-02-28 17:36:59 -0800596 dimensionWhat->add_child()->set_field(1); // uid field.
597 *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700598 util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
tsaichristine7747d372020-02-28 17:36:59 -0800599
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 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
612 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
613 EXPECT_TRUE(metricsManager->isConfigValid());
614 EXPECT_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 EXPECT_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 EXPECT_GT(buffer.size(), 0);
695 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
696 backfillDimensionPath(&reports);
697 backfillStringInReport(&reports);
698 backfillStartEndTimestamp(&reports);
699
700 EXPECT_EQ(1, reports.reports_size());
701 EXPECT_EQ(1, reports.reports(0).metrics_size());
Tej Singh5d823b32019-05-21 20:13:21 -0700702 StatsLogReport::DurationMetricDataWrapper durationMetrics;
703 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
704 &durationMetrics);
705 EXPECT_EQ(1, durationMetrics.data_size());
tsaichristine7747d372020-02-28 17:36:59 -0800706
Tej Singh5d823b32019-05-21 20:13:21 -0700707 DurationMetricData data = durationMetrics.data(0);
tsaichristine7747d372020-02-28 17:36:59 -0800708 // Validate dimension value.
709 ValidateAttributionUidDimension(data.dimensions_in_what(),
Jeffrey Huang3eb84d42020-03-17 10:31:22 -0700710 util::WAKELOCK_STATE_CHANGED, appUid);
tsaichristine7747d372020-02-28 17:36:59 -0800711 // Validate bucket info.
712 EXPECT_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}
Muhammad Qureshi18e46922019-05-24 16:38:49 -0700724
tsaichristine1449fa42020-01-02 12:12:05 -0800725TEST(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 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
757 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
758 EXPECT_TRUE(metricsManager->isConfigValid());
759 EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
760 EXPECT_TRUE(metricsManager->isActive());
761 sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
762 EXPECT_TRUE(metricProducer->mIsActive);
763 EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
764 EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
765 EXPECT_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 EXPECT_GT(buffer.size(), 0);
818 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
819 backfillDimensionPath(&reports);
820 backfillStringInReport(&reports);
821 backfillStartEndTimestamp(&reports);
822
823 EXPECT_EQ(1, reports.reports_size());
824 EXPECT_EQ(1, reports.reports(0).metrics_size());
825 EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
Tej Singh5d823b32019-05-21 20:13:21 -0700826 StatsLogReport::DurationMetricDataWrapper durationMetrics;
827 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
828 &durationMetrics);
829 EXPECT_EQ(3, durationMetrics.data_size());
tsaichristine1449fa42020-01-02 12:12:05 -0800830
Tej Singh5d823b32019-05-21 20:13:21 -0700831 DurationMetricData data = durationMetrics.data(0);
tsaichristine1449fa42020-01-02 12:12:05 -0800832 EXPECT_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 EXPECT_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
Tej Singh5d823b32019-05-21 20:13:21 -0700844 data = durationMetrics.data(1);
tsaichristine1449fa42020-01-02 12:12:05 -0800845 EXPECT_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 EXPECT_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
Tej Singh5d823b32019-05-21 20:13:21 -0700857 data = durationMetrics.data(2);
tsaichristine1449fa42020-01-02 12:12:05 -0800858 EXPECT_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 EXPECT_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
868TEST(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 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
906 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
907 EXPECT_TRUE(metricsManager->isConfigValid());
908 EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
909 EXPECT_TRUE(metricsManager->isActive());
910 sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
911 EXPECT_TRUE(metricProducer->mIsActive);
912 EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
913 EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
914 EXPECT_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 |---------------------------------------|------------------
Muhammad Qureshibfc4bdb2020-04-08 06:26:49 -0700924 ON OFF ON (BatterySaverMode)
tsaichristine1449fa42020-01-02 12:12:05 -0800925 T F T (DeviceUnpluggedPredicate)
Muhammad Qureshibfc4bdb2020-04-08 06:26:49 -0700926 | | | (ScreenIsOnEvent)
tsaichristine1449fa42020-01-02 12:12:05 -0800927 | | | (ScreenIsOffEvent)
928 | (ScreenDozeEvent)
929 */
930 // Initialize log events.
931 std::vector<std::unique_ptr<LogEvent>> events;
tsaichristine1449fa42020-01-02 12:12:05 -0800932 events.push_back(CreateScreenStateChangedEvent(
Muhammad Qureshibfc4bdb2020-04-08 06:26:49 -0700933 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
tsaichristine1449fa42020-01-02 12:12:05 -0800936 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 EXPECT_GT(buffer.size(), 0);
980 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
981 backfillDimensionPath(&reports);
982 backfillStringInReport(&reports);
983 backfillStartEndTimestamp(&reports);
984
985 EXPECT_EQ(1, reports.reports_size());
986 EXPECT_EQ(1, reports.reports(0).metrics_size());
987 EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
Tej Singh5d823b32019-05-21 20:13:21 -0700988 StatsLogReport::DurationMetricDataWrapper durationMetrics;
989 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
990 &durationMetrics);
991 EXPECT_EQ(3, durationMetrics.data_size());
tsaichristine1449fa42020-01-02 12:12:05 -0800992
Tej Singh5d823b32019-05-21 20:13:21 -0700993 DurationMetricData data = durationMetrics.data(0);
tsaichristine1449fa42020-01-02 12:12:05 -0800994 EXPECT_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 EXPECT_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
Tej Singh5d823b32019-05-21 20:13:21 -07001006 data = durationMetrics.data(1);
tsaichristine1449fa42020-01-02 12:12:05 -08001007 EXPECT_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 EXPECT_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
Tej Singh5d823b32019-05-21 20:13:21 -07001019 data = durationMetrics.data(2);
tsaichristine1449fa42020-01-02 12:12:05 -08001020 EXPECT_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 EXPECT_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
1030TEST(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
Tej Singh5d823b32019-05-21 20:13:21 -07001041 int64_t screenOnId = 4444;
1042 int64_t screenOffId = 9876;
1043 auto screenStateWithMap = CreateScreenStateWithOnOffMap(screenOnId, screenOffId);
tsaichristine1449fa42020-01-02 12:12:05 -08001044 *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 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
1064 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
1065 EXPECT_TRUE(metricsManager->isConfigValid());
1066 EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
1067 EXPECT_TRUE(metricsManager->isActive());
1068 sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
1069 EXPECT_TRUE(metricProducer->mIsActive);
1070 EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
1071 EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
1072 EXPECT_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 EXPECT_GT(buffer.size(), 0);
1138 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1139 backfillDimensionPath(&reports);
1140 backfillStringInReport(&reports);
1141 backfillStartEndTimestamp(&reports);
1142
1143 EXPECT_EQ(1, reports.reports_size());
1144 EXPECT_EQ(1, reports.reports(0).metrics_size());
1145 EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
Tej Singh5d823b32019-05-21 20:13:21 -07001146 StatsLogReport::DurationMetricDataWrapper durationMetrics;
1147 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1148 &durationMetrics);
1149 EXPECT_EQ(2, durationMetrics.data_size());
tsaichristine1449fa42020-01-02 12:12:05 -08001150
Tej Singh5d823b32019-05-21 20:13:21 -07001151 DurationMetricData data = durationMetrics.data(0);
tsaichristine1449fa42020-01-02 12:12:05 -08001152 EXPECT_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());
Tej Singh5d823b32019-05-21 20:13:21 -07001155 EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
tsaichristine1449fa42020-01-02 12:12:05 -08001156 EXPECT_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
Tej Singh5d823b32019-05-21 20:13:21 -07001164 data = durationMetrics.data(1);
tsaichristine1449fa42020-01-02 12:12:05 -08001165 EXPECT_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());
Tej Singh5d823b32019-05-21 20:13:21 -07001168 EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
tsaichristine1449fa42020-01-02 12:12:05 -08001169 EXPECT_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
1178TEST(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 EXPECT_EQ(processor->mMetricsManagers.size(), 0);
1220}
1221
1222TEST(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 *config.add_predicate() = holdingWakelockPredicate;
1232
1233 auto uidProcessState = CreateUidProcessState();
1234 *config.add_state() = uidProcessState;
1235
1236 // Create duration metric that slices by uid process state.
1237 auto durationMetric = config.add_duration_metric();
1238 durationMetric->set_id(StringToId("DurationPartialWakelockPerTagUidSliceProcessState"));
1239 durationMetric->set_what(holdingWakelockPredicate.id());
1240 durationMetric->add_slice_by_state(uidProcessState.id());
1241 durationMetric->set_aggregation_type(DurationMetric::SUM);
1242 durationMetric->set_bucket(FIVE_MINUTES);
1243
1244 // The metric is dimensioning by first uid of attribution node and tag.
1245 *durationMetric->mutable_dimensions_in_what() = CreateAttributionUidAndOtherDimensions(
1246 util::WAKELOCK_STATE_CHANGED, {Position::FIRST}, {3 /* tag */});
1247 // The state has only one primary field (uid).
1248 auto stateLink = durationMetric->add_state_link();
1249 stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
1250 auto fieldsInWhat = stateLink->mutable_fields_in_what();
1251 *fieldsInWhat = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
1252 auto fieldsInState = stateLink->mutable_fields_in_state();
1253 *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
1254
1255 // Initialize StatsLogProcessor.
1256 int uid = 12345;
1257 int64_t cfgId = 98765;
1258 ConfigKey cfgKey(uid, cfgId);
1259 uint64_t bucketStartTimeNs = 10000000000; // 0:10
1260 uint64_t bucketSizeNs =
1261 TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
1262 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
1263
1264 EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
1265 sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
1266 EXPECT_TRUE(metricsManager->isConfigValid());
1267 EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
1268 EXPECT_TRUE(metricsManager->isActive());
1269 sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
1270 EXPECT_TRUE(metricProducer->mIsActive);
1271 EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
1272 EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
1273 EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
1274
1275 // Check that StateTrackers were initialized correctly.
1276 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
1277 EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
1278
1279 // Initialize log events.
1280 int appUid1 = 1001;
1281 int appUid2 = 1002;
1282 std::vector<int> attributionUids1 = {appUid1};
1283 std::vector<string> attributionTags1 = {"App1"};
1284
1285 std::vector<int> attributionUids2 = {appUid2};
1286 std::vector<string> attributionTags2 = {"App2"};
1287
1288 std::vector<std::unique_ptr<LogEvent>> events;
1289 events.push_back(CreateUidProcessStateChangedEvent(
1290 bucketStartTimeNs + 10 * NS_PER_SEC, appUid1,
1291 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND)); // 0:20
1292 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 20 * NS_PER_SEC,
1293 attributionUids1, attributionTags1,
1294 "wakelock1")); // 0:30
1295 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 25 * NS_PER_SEC,
1296 attributionUids1, attributionTags1,
1297 "wakelock2")); // 0:35
1298 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 30 * NS_PER_SEC,
1299 attributionUids2, attributionTags2,
1300 "wakelock1")); // 0:40
1301 events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 35 * NS_PER_SEC,
1302 attributionUids2, attributionTags2,
1303 "wakelock2")); // 0:45
1304 events.push_back(CreateUidProcessStateChangedEvent(
1305 bucketStartTimeNs + 50 * NS_PER_SEC, appUid2,
1306 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND)); // 1:00
1307 events.push_back(CreateUidProcessStateChangedEvent(
1308 bucketStartTimeNs + 60 * NS_PER_SEC, appUid1,
1309 android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND)); // 1:10
1310 events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 100 * NS_PER_SEC,
1311 attributionUids2, attributionTags2,
1312 "wakelock1")); // 1:50
1313 events.push_back(CreateUidProcessStateChangedEvent(
1314 bucketStartTimeNs + 120 * NS_PER_SEC, appUid2,
1315 android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE)); // 2:10
1316 events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 200 * NS_PER_SEC,
1317 attributionUids1, attributionTags1,
1318 "wakelock2")); // 3:30
1319
1320 // Send log events to StatsLogProcessor.
1321 for (auto& event : events) {
1322 processor->OnLogEvent(event.get());
1323 }
1324
1325 // Check dump report.
1326 vector<uint8_t> buffer;
1327 ConfigMetricsReportList reports;
1328 processor->onDumpReport(cfgKey, bucketStartTimeNs + 320 * NS_PER_SEC,
1329 true /* include current partial bucket */, true, ADB_DUMP, FAST,
1330 &buffer);
1331 EXPECT_GT(buffer.size(), 0);
1332 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1333 backfillDimensionPath(&reports);
1334 backfillStringInReport(&reports);
1335 backfillStartEndTimestamp(&reports);
1336
1337 EXPECT_EQ(1, reports.reports_size());
1338 EXPECT_EQ(1, reports.reports(0).metrics_size());
1339 EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
Tej Singh5d823b32019-05-21 20:13:21 -07001340 StatsLogReport::DurationMetricDataWrapper durationMetrics;
1341 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
1342 &durationMetrics);
1343 EXPECT_EQ(9, durationMetrics.data_size());
tsaichristine1449fa42020-01-02 12:12:05 -08001344
Tej Singh5d823b32019-05-21 20:13:21 -07001345 DurationMetricData data = durationMetrics.data(0);
tsaichristine1449fa42020-01-02 12:12:05 -08001346 ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
Tej Singh5d823b32019-05-21 20:13:21 -07001347 "wakelock1");
tsaichristine1449fa42020-01-02 12:12:05 -08001348 EXPECT_EQ(1, data.slice_by_state_size());
1349 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1350 EXPECT_TRUE(data.slice_by_state(0).has_value());
1351 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
1352 data.slice_by_state(0).value());
Tej Singh5d823b32019-05-21 20:13:21 -07001353 ASSERT_EQ(1, data.bucket_info_size());
1354 EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
tsaichristine1449fa42020-01-02 12:12:05 -08001355 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1356 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1357
Tej Singh5d823b32019-05-21 20:13:21 -07001358 data = durationMetrics.data(1);
tsaichristine1449fa42020-01-02 12:12:05 -08001359 ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1360 "wakelock1");
1361 EXPECT_EQ(1, data.slice_by_state_size());
1362 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1363 EXPECT_TRUE(data.slice_by_state(0).has_value());
1364 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1365 data.slice_by_state(0).value());
Tej Singh5d823b32019-05-21 20:13:21 -07001366 ASSERT_EQ(2, data.bucket_info_size());
tsaichristine1449fa42020-01-02 12:12:05 -08001367 EXPECT_EQ(240 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1368 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1369 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1370 EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1371 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1372 EXPECT_EQ(330 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1373
Tej Singh5d823b32019-05-21 20:13:21 -07001374 data = durationMetrics.data(2);
1375 ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1376 "wakelock2");
1377 EXPECT_EQ(1, data.slice_by_state_size());
1378 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1379 EXPECT_TRUE(data.slice_by_state(0).has_value());
1380 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
1381 data.slice_by_state(0).value());
1382 ASSERT_EQ(1, data.bucket_info_size());
1383 EXPECT_EQ(35 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1384 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1385 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1386
1387 data = durationMetrics.data(3);
1388 ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
1389 "wakelock2");
1390 EXPECT_EQ(1, data.slice_by_state_size());
1391 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1392 EXPECT_TRUE(data.slice_by_state(0).has_value());
1393 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1394 data.slice_by_state(0).value());
1395 ASSERT_EQ(1, data.bucket_info_size());
1396 EXPECT_EQ(140 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1397 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1398 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1399
1400 data = durationMetrics.data(4);
1401 ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1402 "wakelock1");
1403 EXPECT_EQ(1, data.slice_by_state_size());
1404 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1405 EXPECT_TRUE(data.slice_by_state(0).has_value());
1406 EXPECT_EQ(-1 /* StateTracker:: kStateUnknown */, data.slice_by_state(0).value());
1407 ASSERT_EQ(1, data.bucket_info_size());
1408 EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1409 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1410 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1411
1412 data = durationMetrics.data(5);
tsaichristine1449fa42020-01-02 12:12:05 -08001413 ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1414 "wakelock1");
1415 EXPECT_EQ(1, data.slice_by_state_size());
1416 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1417 EXPECT_TRUE(data.slice_by_state(0).has_value());
1418 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1419 data.slice_by_state(0).value());
Tej Singh5d823b32019-05-21 20:13:21 -07001420 ASSERT_EQ(1, data.bucket_info_size());
tsaichristine1449fa42020-01-02 12:12:05 -08001421 EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1422 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1423 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1424
Tej Singh5d823b32019-05-21 20:13:21 -07001425 data = durationMetrics.data(6);
1426 ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1427 "wakelock2");
1428 EXPECT_EQ(1, data.slice_by_state_size());
1429 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1430 EXPECT_TRUE(data.slice_by_state(0).has_value());
1431 EXPECT_EQ(-1 /* StateTracker:: kStateUnknown */, data.slice_by_state(0).value());
1432 ASSERT_EQ(1, data.bucket_info_size());
1433 EXPECT_EQ(15 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1434 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1435 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1436
1437 data = durationMetrics.data(7);
tsaichristine1449fa42020-01-02 12:12:05 -08001438 ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1439 "wakelock2");
1440 EXPECT_EQ(1, data.slice_by_state_size());
1441 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1442 EXPECT_TRUE(data.slice_by_state(0).has_value());
1443 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
1444 data.slice_by_state(0).value());
Tej Singh5d823b32019-05-21 20:13:21 -07001445 ASSERT_EQ(2, data.bucket_info_size());
tsaichristine1449fa42020-01-02 12:12:05 -08001446 EXPECT_EQ(180 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1447 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1448 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1449 EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
1450 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
1451 EXPECT_EQ(330 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
1452
Tej Singh5d823b32019-05-21 20:13:21 -07001453 data = durationMetrics.data(8);
tsaichristine1449fa42020-01-02 12:12:05 -08001454 ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
1455 "wakelock2");
1456 EXPECT_EQ(1, data.slice_by_state_size());
1457 EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
1458 EXPECT_TRUE(data.slice_by_state(0).has_value());
1459 EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
1460 data.slice_by_state(0).value());
Tej Singh5d823b32019-05-21 20:13:21 -07001461 ASSERT_EQ(1, data.bucket_info_size());
tsaichristine1449fa42020-01-02 12:12:05 -08001462 EXPECT_EQ(70 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
1463 EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
1464 EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
1465}
1466
Muhammad Qureshi18e46922019-05-24 16:38:49 -07001467#else
1468GTEST_LOG_(INFO) << "This test does nothing.\n";
1469#endif
1470
1471} // namespace statsd
1472} // namespace os
1473} // namespace android