• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_dimensions_in_what() =
92             CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
93     gaugeMetric->set_bucket(FIVE_MINUTES);
94     gaugeMetric->set_min_bucket_size_nanos(minTime);
95     gaugeMetric->set_split_bucket_for_app_upgrade(true);
96     return config;
97 }
98 }  // anonymous namespace
99 
100 // Setup for test fixture.
101 class PartialBucketE2eTest : public StatsServiceConfigTest {};
102 
TEST_F(PartialBucketE2eTest,TestCountMetricWithoutSplit)103 TEST_F(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
104     sendConfig(MakeCountMetricConfig({true}));
105     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
106                                              // initialized with.
107 
108     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
109     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 2, 100).get());
110 
111     ConfigMetricsReport report = getReports(service->mProcessor, start + 3);
112     // Expect no metrics since the bucket has not finished yet.
113     ASSERT_EQ(1, report.metrics_size());
114     ASSERT_EQ(0, report.metrics(0).count_metrics().data_size());
115 }
116 
TEST_F(PartialBucketE2eTest,TestCountMetricNoSplitOnNewApp)117 TEST_F(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
118     sendConfig(MakeCountMetricConfig({true}));
119     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
120                                              // initialized with.
121 
122     // Force the uidmap to update at timestamp 2.
123     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
124     // This is a new installation, so there shouldn't be a split (should be same as the without
125     // split case).
126     service->mUidMap->updateApp(start + 2, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
127     // Goes into the second bucket.
128     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
129 
130     ConfigMetricsReport report = getReports(service->mProcessor, start + 4);
131     ASSERT_EQ(1, report.metrics_size());
132     ASSERT_EQ(0, report.metrics(0).count_metrics().data_size());
133 }
134 
TEST_F(PartialBucketE2eTest,TestCountMetricSplitOnUpgrade)135 TEST_F(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
136     sendConfig(MakeCountMetricConfig({true}));
137     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
138                                              // initialized with.
139     UidData uidData;
140     *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1, /*version*/ 1, "v1", kApp1);
141     service->mUidMap->updateMap(start, uidData);
142 
143     // Force the uidmap to update at timestamp 2.
144     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
145     service->mUidMap->updateApp(start + 2, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
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     backfillStartEndTimestamp(&report);
151 
152     ASSERT_EQ(1, report.metrics_size());
153     ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
154     ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
155     EXPECT_TRUE(report.metrics(0)
156                         .count_metrics()
157                         .data(0)
158                         .bucket_info(0)
159                         .has_start_bucket_elapsed_nanos());
160     EXPECT_TRUE(report.metrics(0)
161                         .count_metrics()
162                         .data(0)
163                         .bucket_info(0)
164                         .has_end_bucket_elapsed_nanos());
165     EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
166 }
167 
TEST_F(PartialBucketE2eTest,TestCountMetricSplitOnRemoval)168 TEST_F(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
169     sendConfig(MakeCountMetricConfig({true}));
170     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
171                                              // initialized with.
172     UidData uidData;
173     *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1, /*version*/ 1, "v1", kApp1);
174     service->mUidMap->updateMap(start, uidData);
175 
176     // Force the uidmap to update at timestamp 2.
177     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
178     service->mUidMap->removeApp(start + 2, kApp1, 1);
179     // Goes into the second bucket.
180     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
181 
182     ConfigMetricsReport report = getReports(service->mProcessor, start + 4);
183     backfillStartEndTimestamp(&report);
184 
185     ASSERT_EQ(1, report.metrics_size());
186     ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
187     ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
188     EXPECT_TRUE(report.metrics(0)
189                         .count_metrics()
190                         .data(0)
191                         .bucket_info(0)
192                         .has_start_bucket_elapsed_nanos());
193     EXPECT_TRUE(report.metrics(0)
194                         .count_metrics()
195                         .data(0)
196                         .bucket_info(0)
197                         .has_end_bucket_elapsed_nanos());
198     EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
199 }
200 
TEST_F(PartialBucketE2eTest,TestCountMetricSplitOnBoot)201 TEST_F(PartialBucketE2eTest, TestCountMetricSplitOnBoot) {
202     sendConfig(MakeCountMetricConfig(std::nullopt));
203     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
204                                              // initialized with.
205 
206     // Goes into the first bucket
207     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + NS_PER_SEC, 100).get());
208     int64_t bootCompleteTimeNs = start + 2 * NS_PER_SEC;
209     service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
210     // Goes into the second bucket.
211     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3 * NS_PER_SEC, 100).get());
212 
213     ConfigMetricsReport report = getReports(service->mProcessor, start + 4 * NS_PER_SEC);
214     backfillStartEndTimestamp(&report);
215 
216     ASSERT_EQ(1, report.metrics_size());
217     ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
218     ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
219     EXPECT_TRUE(report.metrics(0)
220                         .count_metrics()
221                         .data(0)
222                         .bucket_info(0)
223                         .has_start_bucket_elapsed_nanos());
224     EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)),
225               report.metrics(0).count_metrics().data(0).bucket_info(0).end_bucket_elapsed_nanos());
226     EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
227 }
228 
TEST_F(PartialBucketE2eTest,TestCountMetricNoSplitOnUpgradeWhenDisabled)229 TEST_F(PartialBucketE2eTest, TestCountMetricNoSplitOnUpgradeWhenDisabled) {
230     StatsdConfig config = MakeCountMetricConfig({false});
231     sendConfig(config);
232     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
233                                              // initialized with.
234     UidData uidData;
235     *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1, /*version*/ 1, "v1", kApp1);
236     service->mUidMap->updateMap(start, uidData);
237 
238     // Force the uidmap to update at timestamp 2.
239     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
240     service->mUidMap->updateApp(start + 2, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
241     // Still goes into the first bucket.
242     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
243 
244     ConfigMetricsReport report =
245             getReports(service->mProcessor, start + 4, /*include_current=*/true);
246     backfillStartEndTimestamp(&report);
247 
248     ASSERT_EQ(1, report.metrics_size());
249     ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
250     ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
251     const CountBucketInfo& bucketInfo = report.metrics(0).count_metrics().data(0).bucket_info(0);
252     EXPECT_EQ(bucketInfo.end_bucket_elapsed_nanos(), MillisToNano(NanoToMillis(start + 4)));
253     EXPECT_EQ(bucketInfo.count(), 2);
254 }
255 
TEST_F(PartialBucketE2eTest,TestValueMetricWithoutMinPartialBucket)256 TEST_F(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
257     service->mPullerManager->RegisterPullAtomCallback(
258             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
259             SharedRefBase::make<FakeSubsystemSleepCallback>());
260     // Partial buckets don't occur when app is first installed.
261     service->mUidMap->updateApp(1, kApp1, 1, 1, "v1", "", /* certificateHash */ {});
262     sendConfig(MakeValueMetricConfig(0));
263     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
264                                              // initialized with.
265 
266     service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
267     int64_t appUpgradeTimeNs = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC;
268     service->mUidMap->updateApp(appUpgradeTimeNs, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
269 
270     ConfigMetricsReport report =
271             getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
272     backfillStartEndTimestamp(&report);
273 
274     ASSERT_EQ(1, report.metrics_size());
275     ASSERT_EQ(0, report.metrics(0).value_metrics().skipped_size());
276 
277     // The fake subsystem state sleep puller returns two atoms.
278     ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
279     ASSERT_EQ(2, report.metrics(0).value_metrics().data(0).bucket_info_size());
280     EXPECT_EQ(MillisToNano(NanoToMillis(appUpgradeTimeNs)),
281               report.metrics(0).value_metrics().data(0).bucket_info(1).end_bucket_elapsed_nanos());
282 }
283 
TEST_F(PartialBucketE2eTest,TestValueMetricWithMinPartialBucket)284 TEST_F(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
285     service->mPullerManager->RegisterPullAtomCallback(
286             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
287             SharedRefBase::make<FakeSubsystemSleepCallback>());
288     // Partial buckets don't occur when app is first installed.
289     service->mUidMap->updateApp(1, kApp1, 1, 1, "v1", "", /* certificateHash */ {});
290     sendConfig(MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
291     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
292                                              // initialized with.
293 
294     const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC;
295     service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
296     service->mUidMap->updateApp(endSkipped, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
297 
298     ConfigMetricsReport report =
299             getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
300     backfillStartEndTimestamp(&report);
301 
302     ASSERT_EQ(1, report.metrics_size());
303     ASSERT_EQ(1, report.metrics(0).value_metrics().skipped_size());
304     EXPECT_TRUE(report.metrics(0).value_metrics().skipped(0).has_start_bucket_elapsed_nanos());
305     // Can't test the start time since it will be based on the actual time when the pulling occurs.
306     EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)),
307               report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos());
308 
309     ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
310     ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
311 }
312 
TEST_F(PartialBucketE2eTest,TestValueMetricOnBootWithoutMinPartialBucket)313 TEST_F(PartialBucketE2eTest, TestValueMetricOnBootWithoutMinPartialBucket) {
314     // Initial pull will fail since puller is not registered.
315     sendConfig(MakeValueMetricConfig(0));
316     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
317                                              // initialized with.
318 
319     service->mPullerManager->RegisterPullAtomCallback(
320             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
321             SharedRefBase::make<FakeSubsystemSleepCallback>());
322 
323     int64_t bootCompleteTimeNs = start + NS_PER_SEC;
324     service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
325 
326     service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
327 
328     ConfigMetricsReport report = getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
329     backfillStartEndTimestamp(&report);
330 
331     // First bucket is dropped due to the initial pull failing
332     ASSERT_EQ(1, report.metrics_size());
333     ASSERT_EQ(1, report.metrics(0).value_metrics().skipped_size());
334     EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)),
335               report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos());
336 
337     // The fake subsystem state sleep puller returns two atoms.
338     ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
339     ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
340     EXPECT_EQ(
341             MillisToNano(NanoToMillis(bootCompleteTimeNs)),
342             report.metrics(0).value_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos());
343 }
344 
TEST_F(PartialBucketE2eTest,TestGaugeMetricWithoutMinPartialBucket)345 TEST_F(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
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, kApp1, 1, 1, "v1", "", /* certificateHash */ {});
351     sendConfig(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, kApp1, 1, 2, "v2", "",
357                                 /* certificateHash */ {});
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_F(PartialBucketE2eTest,TestGaugeMetricWithMinPartialBucket)368 TEST_F(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
369     // Partial buckets don't occur when app is first installed.
370     service->mUidMap->updateApp(1, kApp1, 1, 1, "v1", "", /* certificateHash */ {});
371     service->mPullerManager->RegisterPullAtomCallback(
372             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
373             SharedRefBase::make<FakeSubsystemSleepCallback>());
374     sendConfig(MakeGaugeMetricConfig(60 * NS_PER_SEC /* One minute */));
375     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
376                                              // initialized with.
377 
378     const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
379     service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
380     service->mUidMap->updateApp(endSkipped, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
381 
382     ConfigMetricsReport report =
383             getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
384     backfillStartEndTimestamp(&report);
385     ASSERT_EQ(1, report.metrics_size());
386     ASSERT_EQ(1, report.metrics(0).gauge_metrics().skipped_size());
387     // Can't test the start time since it will be based on the actual time when the pulling occurs.
388     EXPECT_TRUE(report.metrics(0).gauge_metrics().skipped(0).has_start_bucket_elapsed_nanos());
389     EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)),
390               report.metrics(0).gauge_metrics().skipped(0).end_bucket_elapsed_nanos());
391     ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
392     ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
393 }
394 
TEST_F(PartialBucketE2eTest,TestGaugeMetricOnBootWithoutMinPartialBucket)395 TEST_F(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket) {
396     // Initial pull will fail since puller hasn't been registered.
397     sendConfig(MakeGaugeMetricConfig(0));
398     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
399                                              // initialized with.
400 
401     service->mPullerManager->RegisterPullAtomCallback(
402             /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
403             SharedRefBase::make<FakeSubsystemSleepCallback>());
404 
405     int64_t bootCompleteTimeNs = start + NS_PER_SEC;
406     service->mProcessor->onStatsdInitCompleted(bootCompleteTimeNs);
407 
408     service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
409 
410     ConfigMetricsReport report = getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
411     backfillStartEndTimestamp(&report);
412 
413     ASSERT_EQ(1, report.metrics_size());
414     ASSERT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
415     // The fake subsystem state sleep puller returns two atoms.
416     ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
417     // No data in the first bucket, so nothing is reported
418     ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
419     EXPECT_EQ(
420             MillisToNano(NanoToMillis(bootCompleteTimeNs)),
421             report.metrics(0).gauge_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos());
422 }
423 
TEST_F(PartialBucketE2eTest,TestCountMetricNoSplitByDefault)424 TEST_F(PartialBucketE2eTest, TestCountMetricNoSplitByDefault) {
425     StatsdConfig config = MakeCountMetricConfig({nullopt});  // Do not set the value in the metric.
426     sendConfig(config);
427     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
428                                              // initialized with.
429     UidData uidData;
430     *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1, /*version*/ 1, "v1", kApp1);
431     service->mUidMap->updateMap(start, uidData);
432 
433     // Force the uidmap to update at timestamp 2.
434     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
435     service->mUidMap->updateApp(start + 2, kApp1, 1, 2, "v2", "", /* certificateHash */ {});
436     // Still goes into the first bucket.
437     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
438 
439     ConfigMetricsReport report =
440             getReports(service->mProcessor, start + 4, /*include_current=*/true);
441     backfillStartEndTimestamp(&report);
442 
443     ASSERT_EQ(1, report.metrics_size());
444     ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
445     ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
446     const CountBucketInfo& bucketInfo = report.metrics(0).count_metrics().data(0).bucket_info(0);
447     EXPECT_EQ(bucketInfo.end_bucket_elapsed_nanos(), MillisToNano(NanoToMillis(start + 4)));
448     EXPECT_EQ(bucketInfo.count(), 2);
449 }
450 
451 #else
452 GTEST_LOG_(INFO) << "This test does nothing.\n";
453 #endif
454 
455 }  // namespace statsd
456 }  // namespace os
457 }  // namespace android
458