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/packages/UidMap.h"
24 #include "src/stats_log_util.h"
25 #include "tests/statsd_test_util.h"
26 
27 using ::ndk::SharedRefBase;
28 using std::shared_ptr;
29 
30 namespace android {
31 namespace os {
32 namespace statsd {
33 
34 #ifdef __ANDROID__
35 namespace {
36 const string kApp1 = "app1.sharing.1";
37 
MakeCountMetricConfig(const std::optional<bool> splitBucket)38 StatsdConfig MakeCountMetricConfig(const std::optional<bool> splitBucket) {
39     StatsdConfig config;
40 
41     auto appCrashMatcher = CreateProcessCrashAtomMatcher();
42     *config.add_atom_matcher() = appCrashMatcher;
43     auto countMetric = config.add_count_metric();
44     countMetric->set_id(StringToId("AppCrashes"));
45     countMetric->set_what(appCrashMatcher.id());
46     countMetric->set_bucket(FIVE_MINUTES);
47     if (splitBucket.has_value()) {
48         countMetric->set_split_bucket_for_app_upgrade(splitBucket.value());
49     }
50     return config;
51 }
52 
MakeValueMetricConfig(int64_t minTime)53 StatsdConfig MakeValueMetricConfig(int64_t minTime) {
54     StatsdConfig config;
55     config.add_default_pull_packages("AID_ROOT");  // Fake puller is registered with root.
56 
57     auto pulledAtomMatcher =
58             CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
59     *config.add_atom_matcher() = pulledAtomMatcher;
60     *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
61     *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
62 
63     auto valueMetric = config.add_value_metric();
64     valueMetric->set_id(123456);
65     valueMetric->set_what(pulledAtomMatcher.id());
66     *valueMetric->mutable_value_field() =
67             CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
68     *valueMetric->mutable_dimensions_in_what() =
69             CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
70     valueMetric->set_bucket(FIVE_MINUTES);
71     valueMetric->set_min_bucket_size_nanos(minTime);
72     valueMetric->set_use_absolute_value_on_reset(true);
73     valueMetric->set_skip_zero_diff_output(false);
74     valueMetric->set_split_bucket_for_app_upgrade(true);
75     return config;
76 }
77 
MakeGaugeMetricConfig(int64_t minTime)78 StatsdConfig MakeGaugeMetricConfig(int64_t minTime) {
79     StatsdConfig config;
80     config.add_default_pull_packages("AID_ROOT");  // Fake puller is registered with root.
81 
82     auto pulledAtomMatcher =
83                 CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
84     *config.add_atom_matcher() = pulledAtomMatcher;
85     *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
86     *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
87 
88     auto gaugeMetric = config.add_gauge_metric();
89     gaugeMetric->set_id(123456);
90     gaugeMetric->set_what(pulledAtomMatcher.id());
91     gaugeMetric->mutable_gauge_fields_filter()->set_include_all(true);
92     *gaugeMetric->mutable_dimensions_in_what() =
93             CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
94     gaugeMetric->set_bucket(FIVE_MINUTES);
95     gaugeMetric->set_min_bucket_size_nanos(minTime);
96     gaugeMetric->set_split_bucket_for_app_upgrade(true);
97     return config;
98 }
99 }  // anonymous namespace
100 
101 // Setup for test fixture.
102 class PartialBucketE2eTest : public StatsServiceConfigTest {};
103 
TEST_F(PartialBucketE2eTest,TestCountMetricWithoutSplit)104 TEST_F(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
105     sendConfig(MakeCountMetricConfig({true}));
106     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
107                                              // initialized with.
108 
109     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
110     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 2, 100).get());
111 
112     ConfigMetricsReport report = getReports(service->mProcessor, start + 3);
113     // Expect no metrics since the bucket has not finished yet.
114     ASSERT_EQ(1, report.metrics_size());
115     ASSERT_EQ(0, report.metrics(0).count_metrics().data_size());
116 }
117 
TEST_F(PartialBucketE2eTest,TestCountMetricNoSplitOnNewApp)118 TEST_F(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
119     sendConfig(MakeCountMetricConfig({true}));
120     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
121                                              // initialized with.
122 
123     // Force the uidmap to update at timestamp 2.
124     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
125     // This is a new installation, so there shouldn't be a split (should be same as the without
126     // split case).
127     service->mUidMap->updateApp(start + 2, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
128     // Goes into the second bucket.
129     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
130 
131     ConfigMetricsReport report = getReports(service->mProcessor, start + 4);
132     ASSERT_EQ(1, report.metrics_size());
133     ASSERT_EQ(0, report.metrics(0).count_metrics().data_size());
134 }
135 
TEST_F(PartialBucketE2eTest,TestCountMetricSplitOnUpgrade)136 TEST_F(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
137     sendConfig(MakeCountMetricConfig({true}));
138     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
139                                              // initialized with.
140     UidData uidData;
141     *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1, /*version*/ 1, "v1", kApp1);
142     service->mUidMap->updateMap(start, uidData);
143 
144     // Force the uidmap to update at timestamp 2.
145     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
146     service->mUidMap->updateApp(start + 2, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
147     // Goes into the second bucket.
148     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
149 
150     ConfigMetricsReport report = getReports(service->mProcessor, start + 4);
151     backfillStartEndTimestamp(&report);
152 
153     ASSERT_EQ(1, report.metrics_size());
154     ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
155     ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
156     EXPECT_TRUE(report.metrics(0)
157                         .count_metrics()
158                         .data(0)
159                         .bucket_info(0)
160                         .has_start_bucket_elapsed_nanos());
161     EXPECT_TRUE(report.metrics(0)
162                         .count_metrics()
163                         .data(0)
164                         .bucket_info(0)
165                         .has_end_bucket_elapsed_nanos());
166     EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
167 }
168 
TEST_F(PartialBucketE2eTest,TestCountMetricSplitOnRemoval)169 TEST_F(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
170     sendConfig(MakeCountMetricConfig({true}));
171     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
172                                              // initialized with.
173     UidData uidData;
174     *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1, /*version*/ 1, "v1", kApp1);
175     service->mUidMap->updateMap(start, uidData);
176 
177     // Force the uidmap to update at timestamp 2.
178     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
179     service->mUidMap->removeApp(start + 2, kApp1, 1);
180     // Goes into the second bucket.
181     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
182 
183     ConfigMetricsReport report = getReports(service->mProcessor, start + 4);
184     backfillStartEndTimestamp(&report);
185 
186     ASSERT_EQ(1, report.metrics_size());
187     ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
188     ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
189     EXPECT_TRUE(report.metrics(0)
190                         .count_metrics()
191                         .data(0)
192                         .bucket_info(0)
193                         .has_start_bucket_elapsed_nanos());
194     EXPECT_TRUE(report.metrics(0)
195                         .count_metrics()
196                         .data(0)
197                         .bucket_info(0)
198                         .has_end_bucket_elapsed_nanos());
199     EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
200 }
201 
TEST_F(PartialBucketE2eTest,TestCountMetricSplitOnBoot)202 TEST_F(PartialBucketE2eTest, TestCountMetricSplitOnBoot) {
203     sendConfig(MakeCountMetricConfig(std::nullopt));
204     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
205                                              // initialized with.
206 
207     // Goes into the first bucket
208     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + NS_PER_SEC, 100).get());
209     int64_t bootCompleteTimeNs = start + 2 * NS_PER_SEC;
210     service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
211     // Goes into the second bucket.
212     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3 * NS_PER_SEC, 100).get());
213 
214     ConfigMetricsReport report = getReports(service->mProcessor, start + 4 * NS_PER_SEC);
215     backfillStartEndTimestamp(&report);
216 
217     ASSERT_EQ(1, report.metrics_size());
218     ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
219     ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
220     EXPECT_TRUE(report.metrics(0)
221                         .count_metrics()
222                         .data(0)
223                         .bucket_info(0)
224                         .has_start_bucket_elapsed_nanos());
225     EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)),
226               report.metrics(0).count_metrics().data(0).bucket_info(0).end_bucket_elapsed_nanos());
227     EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
228 }
229 
TEST_F(PartialBucketE2eTest,TestCountMetricNoSplitOnUpgradeWhenDisabled)230 TEST_F(PartialBucketE2eTest, TestCountMetricNoSplitOnUpgradeWhenDisabled) {
231     StatsdConfig config = MakeCountMetricConfig({false});
232     sendConfig(config);
233     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
234                                              // initialized with.
235     UidData uidData;
236     *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1, /*version*/ 1, "v1", kApp1);
237     service->mUidMap->updateMap(start, uidData);
238 
239     // Force the uidmap to update at timestamp 2.
240     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
241     service->mUidMap->updateApp(start + 2, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
242     // Still goes into the first bucket.
243     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
244 
245     ConfigMetricsReport report =
246             getReports(service->mProcessor, start + 4, /*include_current=*/true);
247     backfillStartEndTimestamp(&report);
248 
249     ASSERT_EQ(1, report.metrics_size());
250     ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
251     ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
252     const CountBucketInfo& bucketInfo = report.metrics(0).count_metrics().data(0).bucket_info(0);
253     EXPECT_EQ(bucketInfo.end_bucket_elapsed_nanos(), MillisToNano(NanoToMillis(start + 4)));
254     EXPECT_EQ(bucketInfo.count(), 2);
255 }
256 
TEST_F(PartialBucketE2eTest,TestValueMetricWithoutMinPartialBucket)257 TEST_F(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
258     service->mPullerManager->RegisterPullAtomCallback(
259             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
260             SharedRefBase::make<FakeSubsystemSleepCallback>());
261     // Partial buckets don't occur when app is first installed.
262     service->mUidMap->updateApp(1, kApp1, 1, 1, "v1", "", /* certificateHash */ {});
263     sendConfig(MakeValueMetricConfig(0));
264     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
265                                              // initialized with.
266 
267     service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
268     int64_t appUpgradeTimeNs = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC;
269     service->mUidMap->updateApp(appUpgradeTimeNs, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
270 
271     ConfigMetricsReport report =
272             getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
273     backfillStartEndTimestamp(&report);
274 
275     ASSERT_EQ(1, report.metrics_size());
276     ASSERT_EQ(0, report.metrics(0).value_metrics().skipped_size());
277 
278     // The fake subsystem state sleep puller returns two atoms.
279     ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
280     ASSERT_EQ(2, report.metrics(0).value_metrics().data(0).bucket_info_size());
281     EXPECT_EQ(MillisToNano(NanoToMillis(appUpgradeTimeNs)),
282               report.metrics(0).value_metrics().data(0).bucket_info(1).end_bucket_elapsed_nanos());
283 }
284 
TEST_F(PartialBucketE2eTest,TestValueMetricWithMinPartialBucket)285 TEST_F(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
286     service->mPullerManager->RegisterPullAtomCallback(
287             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
288             SharedRefBase::make<FakeSubsystemSleepCallback>());
289     // Partial buckets don't occur when app is first installed.
290     service->mUidMap->updateApp(1, kApp1, 1, 1, "v1", "", /* certificateHash */ {});
291     sendConfig(MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
292     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
293                                              // initialized with.
294 
295     const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC;
296     service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
297     service->mUidMap->updateApp(endSkipped, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
298 
299     ConfigMetricsReport report =
300             getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
301     backfillStartEndTimestamp(&report);
302 
303     ASSERT_EQ(1, report.metrics_size());
304     ASSERT_EQ(1, report.metrics(0).value_metrics().skipped_size());
305     EXPECT_TRUE(report.metrics(0).value_metrics().skipped(0).has_start_bucket_elapsed_nanos());
306     // Can't test the start time since it will be based on the actual time when the pulling occurs.
307     EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)),
308               report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos());
309 
310     ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
311     ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
312 }
313 
TEST_F(PartialBucketE2eTest,TestValueMetricOnBootWithoutMinPartialBucket)314 TEST_F(PartialBucketE2eTest, TestValueMetricOnBootWithoutMinPartialBucket) {
315     // Initial pull will fail since puller is not registered.
316     sendConfig(MakeValueMetricConfig(0));
317     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
318                                              // initialized with.
319 
320     service->mPullerManager->RegisterPullAtomCallback(
321             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
322             SharedRefBase::make<FakeSubsystemSleepCallback>());
323 
324     int64_t bootCompleteTimeNs = start + NS_PER_SEC;
325     service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
326 
327     service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
328 
329     ConfigMetricsReport report = getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
330     backfillStartEndTimestamp(&report);
331 
332     // First bucket is dropped due to the initial pull failing
333     ASSERT_EQ(1, report.metrics_size());
334     ASSERT_EQ(1, report.metrics(0).value_metrics().skipped_size());
335     EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)),
336               report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos());
337 
338     // The fake subsystem state sleep puller returns two atoms.
339     ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
340     ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
341     EXPECT_EQ(
342             MillisToNano(NanoToMillis(bootCompleteTimeNs)),
343             report.metrics(0).value_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos());
344 }
345 
TEST_F(PartialBucketE2eTest,TestGaugeMetricWithoutMinPartialBucket)346 TEST_F(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
347     service->mPullerManager->RegisterPullAtomCallback(
348             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
349             SharedRefBase::make<FakeSubsystemSleepCallback>());
350     // Partial buckets don't occur when app is first installed.
351     service->mUidMap->updateApp(1, kApp1, 1, 1, "v1", "", /* certificateHash */ {});
352     sendConfig(MakeGaugeMetricConfig(0));
353     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
354                                              // initialized with.
355 
356     service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
357     service->mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, kApp1, 1, 2, "v2", "",
358                                 /* certificateHash */ {});
359 
360     ConfigMetricsReport report = getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
361     backfillStartEndTimestamp(&report);
362     ASSERT_EQ(1, report.metrics_size());
363     ASSERT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
364     // The fake subsystem state sleep puller returns two atoms.
365     ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
366     ASSERT_EQ(2, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
367 }
368 
TEST_F(PartialBucketE2eTest,TestGaugeMetricWithMinPartialBucket)369 TEST_F(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
370     // Partial buckets don't occur when app is first installed.
371     service->mUidMap->updateApp(1, kApp1, 1, 1, "v1", "", /* certificateHash */ {});
372     service->mPullerManager->RegisterPullAtomCallback(
373             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
374             SharedRefBase::make<FakeSubsystemSleepCallback>());
375     sendConfig(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, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
382 
383     ConfigMetricsReport report =
384             getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
385     backfillStartEndTimestamp(&report);
386     ASSERT_EQ(1, report.metrics_size());
387     ASSERT_EQ(1, report.metrics(0).gauge_metrics().skipped_size());
388     // Can't test the start time since it will be based on the actual time when the pulling occurs.
389     EXPECT_TRUE(report.metrics(0).gauge_metrics().skipped(0).has_start_bucket_elapsed_nanos());
390     EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)),
391               report.metrics(0).gauge_metrics().skipped(0).end_bucket_elapsed_nanos());
392     ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
393     ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
394 }
395 
TEST_F(PartialBucketE2eTest,TestGaugeMetricOnBootWithoutMinPartialBucket)396 TEST_F(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket) {
397     // Initial pull will fail since puller hasn't been registered.
398     sendConfig(MakeGaugeMetricConfig(0));
399     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
400                                              // initialized with.
401 
402     service->mPullerManager->RegisterPullAtomCallback(
403             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
404             SharedRefBase::make<FakeSubsystemSleepCallback>());
405 
406     int64_t bootCompleteTimeNs = start + NS_PER_SEC;
407     service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
408 
409     service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
410 
411     ConfigMetricsReport report = getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
412     backfillStartEndTimestamp(&report);
413 
414     ASSERT_EQ(1, report.metrics_size());
415     ASSERT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
416     // The fake subsystem state sleep puller returns two atoms.
417     ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
418     // No data in the first bucket, so nothing is reported
419     ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
420     EXPECT_EQ(
421             MillisToNano(NanoToMillis(bootCompleteTimeNs)),
422             report.metrics(0).gauge_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos());
423 }
424 
TEST_F(PartialBucketE2eTest,TestCountMetricNoSplitByDefault)425 TEST_F(PartialBucketE2eTest, TestCountMetricNoSplitByDefault) {
426     StatsdConfig config = MakeCountMetricConfig({nullopt});  // Do not set the value in the metric.
427     sendConfig(config);
428     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
429                                              // initialized with.
430     UidData uidData;
431     *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1, /*version*/ 1, "v1", kApp1);
432     service->mUidMap->updateMap(start, uidData);
433 
434     // Force the uidmap to update at timestamp 2.
435     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
436     service->mUidMap->updateApp(start + 2, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
437     // Still goes into the first bucket.
438     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
439 
440     ConfigMetricsReport report =
441             getReports(service->mProcessor, start + 4, /*include_current=*/true);
442     backfillStartEndTimestamp(&report);
443 
444     ASSERT_EQ(1, report.metrics_size());
445     ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
446     ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
447     const CountBucketInfo& bucketInfo = report.metrics(0).count_metrics().data(0).bucket_info(0);
448     EXPECT_EQ(bucketInfo.end_bucket_elapsed_nanos(), MillisToNano(NanoToMillis(start + 4)));
449     EXPECT_EQ(bucketInfo.count(), 2);
450 }
451 
452 #else
453 GTEST_LOG_(INFO) << "This test does nothing.\n";
454 #endif
455 
456 }  // namespace statsd
457 }  // namespace os
458 }  // namespace android
459