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