1 // Copyright (C) 2017 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <android/binder_ibinder.h>
16 #include <android/binder_interface_utils.h>
17 #include <gtest/gtest.h>
18
19 #include <vector>
20
21 #include "src/StatsLogProcessor.h"
22 #include "src/StatsService.h"
23 #include "src/stats_log_util.h"
24 #include "tests/statsd_test_util.h"
25
26 using::ndk::SharedRefBase;
27 using std::shared_ptr;
28
29 namespace android {
30 namespace os {
31 namespace statsd {
32
33 #ifdef __ANDROID__
34 namespace {
35 const string kApp1 = "app1.sharing.1";
36 const int kConfigKey = 789130123; // Randomly chosen to avoid collisions with existing configs.
37 const int kCallingUid = 0; // Randomly chosen
38
SendConfig(shared_ptr<StatsService> & service,const StatsdConfig & config)39 void SendConfig(shared_ptr<StatsService>& service, const StatsdConfig& config) {
40 string str;
41 config.SerializeToString(&str);
42 std::vector<int8_t> configAsVec(str.begin(), str.end());
43 service->addConfiguration(kConfigKey, configAsVec, kCallingUid);
44 }
45
GetReports(sp<StatsLogProcessor> processor,int64_t timestamp,bool include_current=false)46 ConfigMetricsReport GetReports(sp<StatsLogProcessor> processor, int64_t timestamp,
47 bool include_current = false) {
48 vector<uint8_t> output;
49 ConfigKey configKey(AIBinder_getCallingUid(), kConfigKey);
50 processor->onDumpReport(configKey, timestamp, include_current /* include_current_bucket*/,
51 true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &output);
52 ConfigMetricsReportList reports;
53 reports.ParseFromArray(output.data(), output.size());
54 EXPECT_EQ(1, reports.reports_size());
55 return reports.reports(kCallingUid);
56 }
57
MakeConfig()58 StatsdConfig MakeConfig() {
59 StatsdConfig config;
60 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
61
62 auto appCrashMatcher = CreateProcessCrashAtomMatcher();
63 *config.add_atom_matcher() = appCrashMatcher;
64 auto countMetric = config.add_count_metric();
65 countMetric->set_id(StringToId("AppCrashes"));
66 countMetric->set_what(appCrashMatcher.id());
67 countMetric->set_bucket(FIVE_MINUTES);
68 return config;
69 }
70
MakeValueMetricConfig(int64_t minTime)71 StatsdConfig MakeValueMetricConfig(int64_t minTime) {
72 StatsdConfig config;
73 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
74 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
75
76 auto pulledAtomMatcher =
77 CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
78 *config.add_atom_matcher() = pulledAtomMatcher;
79 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
80 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
81
82 auto valueMetric = config.add_value_metric();
83 valueMetric->set_id(123456);
84 valueMetric->set_what(pulledAtomMatcher.id());
85 *valueMetric->mutable_value_field() =
86 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
87 *valueMetric->mutable_dimensions_in_what() =
88 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
89 valueMetric->set_bucket(FIVE_MINUTES);
90 valueMetric->set_min_bucket_size_nanos(minTime);
91 valueMetric->set_use_absolute_value_on_reset(true);
92 valueMetric->set_skip_zero_diff_output(false);
93 return config;
94 }
95
MakeGaugeMetricConfig(int64_t minTime)96 StatsdConfig MakeGaugeMetricConfig(int64_t minTime) {
97 StatsdConfig config;
98 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
99 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
100
101 auto pulledAtomMatcher =
102 CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
103 *config.add_atom_matcher() = pulledAtomMatcher;
104 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
105 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
106
107 auto gaugeMetric = config.add_gauge_metric();
108 gaugeMetric->set_id(123456);
109 gaugeMetric->set_what(pulledAtomMatcher.id());
110 gaugeMetric->mutable_gauge_fields_filter()->set_include_all(true);
111 *gaugeMetric->mutable_dimensions_in_what() =
112 CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
113 gaugeMetric->set_bucket(FIVE_MINUTES);
114 gaugeMetric->set_min_bucket_size_nanos(minTime);
115 return config;
116 }
117 } // anonymous namespace
118
TEST(PartialBucketE2eTest,TestCountMetricWithoutSplit)119 TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
120 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
121 SendConfig(service, MakeConfig());
122 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
123 // initialized with.
124
125 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
126 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 2, 100).get());
127
128 ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
129 // Expect no metrics since the bucket has not finished yet.
130 ASSERT_EQ(1, report.metrics_size());
131 ASSERT_EQ(0, report.metrics(0).count_metrics().data_size());
132 }
133
TEST(PartialBucketE2eTest,TestCountMetricNoSplitOnNewApp)134 TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
135 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
136 SendConfig(service, MakeConfig());
137 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
138 // initialized with.
139
140 // Force the uidmap to update at timestamp 2.
141 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
142 // This is a new installation, so there shouldn't be a split (should be same as the without
143 // split case).
144 service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
145 String16(""));
146 // Goes into the second bucket.
147 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
148
149 ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
150 ASSERT_EQ(1, report.metrics_size());
151 ASSERT_EQ(0, report.metrics(0).count_metrics().data_size());
152 }
153
TEST(PartialBucketE2eTest,TestCountMetricSplitOnUpgrade)154 TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
155 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
156 SendConfig(service, MakeConfig());
157 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
158 // initialized with.
159 service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
160 {String16("")});
161
162 // Force the uidmap to update at timestamp 2.
163 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
164 service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
165 String16(""));
166 // Goes into the second bucket.
167 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
168
169 ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
170 backfillStartEndTimestamp(&report);
171
172 ASSERT_EQ(1, report.metrics_size());
173 ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
174 ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
175 EXPECT_TRUE(report.metrics(0)
176 .count_metrics()
177 .data(0)
178 .bucket_info(0)
179 .has_start_bucket_elapsed_nanos());
180 EXPECT_TRUE(report.metrics(0)
181 .count_metrics()
182 .data(0)
183 .bucket_info(0)
184 .has_end_bucket_elapsed_nanos());
185 EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
186 }
187
TEST(PartialBucketE2eTest,TestCountMetricSplitOnRemoval)188 TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
189 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
190 SendConfig(service, MakeConfig());
191 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
192 // initialized with.
193 service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
194 {String16("")});
195
196 // Force the uidmap to update at timestamp 2.
197 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
198 service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
199 // Goes into the second bucket.
200 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
201
202 ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
203 backfillStartEndTimestamp(&report);
204
205 ASSERT_EQ(1, report.metrics_size());
206 ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
207 ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
208 EXPECT_TRUE(report.metrics(0)
209 .count_metrics()
210 .data(0)
211 .bucket_info(0)
212 .has_start_bucket_elapsed_nanos());
213 EXPECT_TRUE(report.metrics(0)
214 .count_metrics()
215 .data(0)
216 .bucket_info(0)
217 .has_end_bucket_elapsed_nanos());
218 EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
219 }
220
TEST(PartialBucketE2eTest,TestCountMetricSplitOnBoot)221 TEST(PartialBucketE2eTest, TestCountMetricSplitOnBoot) {
222 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
223 SendConfig(service, MakeConfig());
224 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
225 // initialized with.
226
227 // Goes into the first bucket
228 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + NS_PER_SEC, 100).get());
229 int64_t bootCompleteTimeNs = start + 2 * NS_PER_SEC;
230 service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
231 // Goes into the second bucket.
232 service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3 * NS_PER_SEC, 100).get());
233
234 ConfigMetricsReport report = GetReports(service->mProcessor, start + 4 * NS_PER_SEC);
235 backfillStartEndTimestamp(&report);
236
237 ASSERT_EQ(1, report.metrics_size());
238 ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
239 ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
240 EXPECT_TRUE(report.metrics(0)
241 .count_metrics()
242 .data(0)
243 .bucket_info(0)
244 .has_start_bucket_elapsed_nanos());
245 EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)),
246 report.metrics(0).count_metrics().data(0).bucket_info(0).end_bucket_elapsed_nanos());
247 EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
248 }
249
TEST(PartialBucketE2eTest,TestValueMetricWithoutMinPartialBucket)250 TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
251 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
252 service->mPullerManager->RegisterPullAtomCallback(
253 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
254 SharedRefBase::make<FakeSubsystemSleepCallback>());
255 // Partial buckets don't occur when app is first installed.
256 service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
257 SendConfig(service, MakeValueMetricConfig(0));
258 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
259 // initialized with.
260
261 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
262 int64_t appUpgradeTimeNs = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC;
263 service->mUidMap->updateApp(appUpgradeTimeNs, String16(kApp1.c_str()), 1, 2, String16("v2"),
264 String16(""));
265
266 ConfigMetricsReport report =
267 GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
268 backfillStartEndTimestamp(&report);
269
270 ASSERT_EQ(1, report.metrics_size());
271 ASSERT_EQ(0, report.metrics(0).value_metrics().skipped_size());
272
273 // The fake subsystem state sleep puller returns two atoms.
274 ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
275 ASSERT_EQ(2, report.metrics(0).value_metrics().data(0).bucket_info_size());
276 EXPECT_EQ(MillisToNano(NanoToMillis(appUpgradeTimeNs)),
277 report.metrics(0).value_metrics().data(0).bucket_info(1).end_bucket_elapsed_nanos());
278 }
279
TEST(PartialBucketE2eTest,TestValueMetricWithMinPartialBucket)280 TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
281 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
282 service->mPullerManager->RegisterPullAtomCallback(
283 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
284 SharedRefBase::make<FakeSubsystemSleepCallback>());
285 // Partial buckets don't occur when app is first installed.
286 service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
287 SendConfig(service, MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
288 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
289 // initialized with.
290
291 const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC;
292 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
293 service->mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
294 String16(""));
295
296 ConfigMetricsReport report =
297 GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
298 backfillStartEndTimestamp(&report);
299
300 ASSERT_EQ(1, report.metrics_size());
301 ASSERT_EQ(1, report.metrics(0).value_metrics().skipped_size());
302 EXPECT_TRUE(report.metrics(0).value_metrics().skipped(0).has_start_bucket_elapsed_nanos());
303 // Can't test the start time since it will be based on the actual time when the pulling occurs.
304 EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)),
305 report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos());
306
307 ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
308 ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
309 }
310
TEST(PartialBucketE2eTest,TestValueMetricOnBootWithoutMinPartialBucket)311 TEST(PartialBucketE2eTest, TestValueMetricOnBootWithoutMinPartialBucket) {
312 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
313 // Initial pull will fail since puller is not registered.
314 SendConfig(service, MakeValueMetricConfig(0));
315 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
316 // initialized with.
317
318 service->mPullerManager->RegisterPullAtomCallback(
319 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
320 SharedRefBase::make<FakeSubsystemSleepCallback>());
321
322 int64_t bootCompleteTimeNs = start + NS_PER_SEC;
323 service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
324
325 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
326
327 ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
328 backfillStartEndTimestamp(&report);
329
330 // First bucket is dropped due to the initial pull failing
331 ASSERT_EQ(1, report.metrics_size());
332 ASSERT_EQ(1, report.metrics(0).value_metrics().skipped_size());
333 EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)),
334 report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos());
335
336 // The fake subsystem state sleep puller returns two atoms.
337 ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
338 ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
339 EXPECT_EQ(
340 MillisToNano(NanoToMillis(bootCompleteTimeNs)),
341 report.metrics(0).value_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos());
342 }
343
TEST(PartialBucketE2eTest,TestGaugeMetricWithoutMinPartialBucket)344 TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
345 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
346 service->mPullerManager->RegisterPullAtomCallback(
347 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
348 SharedRefBase::make<FakeSubsystemSleepCallback>());
349 // Partial buckets don't occur when app is first installed.
350 service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
351 SendConfig(service, MakeGaugeMetricConfig(0));
352 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
353 // initialized with.
354
355 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
356 service->mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
357 String16("v2"), String16(""));
358
359 ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
360 backfillStartEndTimestamp(&report);
361 ASSERT_EQ(1, report.metrics_size());
362 ASSERT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
363 // The fake subsystem state sleep puller returns two atoms.
364 ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
365 ASSERT_EQ(2, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
366 }
367
TEST(PartialBucketE2eTest,TestGaugeMetricWithMinPartialBucket)368 TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
369 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
370 // Partial buckets don't occur when app is first installed.
371 service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
372 service->mPullerManager->RegisterPullAtomCallback(
373 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
374 SharedRefBase::make<FakeSubsystemSleepCallback>());
375 SendConfig(service, MakeGaugeMetricConfig(60 * NS_PER_SEC /* One minute */));
376 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
377 // initialized with.
378
379 const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
380 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
381 service->mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
382 String16(""));
383
384 ConfigMetricsReport report =
385 GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
386 backfillStartEndTimestamp(&report);
387 ASSERT_EQ(1, report.metrics_size());
388 ASSERT_EQ(1, report.metrics(0).gauge_metrics().skipped_size());
389 // Can't test the start time since it will be based on the actual time when the pulling occurs.
390 EXPECT_TRUE(report.metrics(0).gauge_metrics().skipped(0).has_start_bucket_elapsed_nanos());
391 EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)),
392 report.metrics(0).gauge_metrics().skipped(0).end_bucket_elapsed_nanos());
393 ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
394 ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
395 }
396
TEST(PartialBucketE2eTest,TestGaugeMetricOnBootWithoutMinPartialBucket)397 TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket) {
398 shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
399 // Initial pull will fail since puller hasn't been registered.
400 SendConfig(service, MakeGaugeMetricConfig(0));
401 int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
402 // initialized with.
403
404 service->mPullerManager->RegisterPullAtomCallback(
405 /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
406 SharedRefBase::make<FakeSubsystemSleepCallback>());
407
408 int64_t bootCompleteTimeNs = start + NS_PER_SEC;
409 service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
410
411 service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
412
413 ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
414 backfillStartEndTimestamp(&report);
415
416 ASSERT_EQ(1, report.metrics_size());
417 ASSERT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
418 // The fake subsystem state sleep puller returns two atoms.
419 ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
420 // No data in the first bucket, so nothing is reported
421 ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
422 EXPECT_EQ(
423 MillisToNano(NanoToMillis(bootCompleteTimeNs)),
424 report.metrics(0).gauge_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos());
425 }
426
427 #else
428 GTEST_LOG_(INFO) << "This test does nothing.\n";
429 #endif
430
431 } // namespace statsd
432 } // namespace os
433 } // namespace android
434