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