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