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