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